From 49cf65a5cb6a46e29a7710794000eb08b3394637 Mon Sep 17 00:00:00 2001 From: admin Date: Sat, 13 Dec 2025 23:35:45 +0900 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E8=A6=8F=E4=BD=9C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env | 5 + .env.example | 5 + .gitignore | 28 + README.md | 0 .../typing_extensions.cpython-312.pyc | Bin 0 -> 163641 bytes .../.venv/Lib/site-packages/_yaml/__init__.py | 33 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 862 bytes .../annotated_types-0.7.0.dist-info/INSTALLER | 1 + .../annotated_types-0.7.0.dist-info/METADATA | 295 + .../annotated_types-0.7.0.dist-info/RECORD | 10 + .../annotated_types-0.7.0.dist-info/WHEEL | 4 + .../licenses/LICENSE | 21 + .../site-packages/annotated_types/__init__.py | 432 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 18621 bytes .../__pycache__/test_cases.cpython-312.pyc | Bin 0 -> 13234 bytes .../site-packages/annotated_types/py.typed | 0 .../annotated_types/test_cases.py | 151 + .../anyio-4.12.0.dist-info/INSTALLER | 1 + .../anyio-4.12.0.dist-info/METADATA | 96 + .../anyio-4.12.0.dist-info/RECORD | 92 + .../anyio-4.12.0.dist-info/WHEEL | 5 + .../anyio-4.12.0.dist-info/entry_points.txt | 2 + .../anyio-4.12.0.dist-info/licenses/LICENSE | 20 + .../anyio-4.12.0.dist-info/top_level.txt | 1 + .../.venv/Lib/site-packages/anyio/__init__.py | 111 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 4624 bytes .../__pycache__/from_thread.cpython-312.pyc | Bin 0 -> 25797 bytes .../__pycache__/functools.cpython-312.pyc | Bin 0 -> 13724 bytes .../__pycache__/lowlevel.cpython-312.pyc | Bin 0 -> 7885 bytes .../__pycache__/pytest_plugin.cpython-312.pyc | Bin 0 -> 14283 bytes .../to_interpreter.cpython-312.pyc | Bin 0 -> 10327 bytes .../__pycache__/to_process.cpython-312.pyc | Bin 0 -> 11830 bytes .../__pycache__/to_thread.cpython-312.pyc | Bin 0 -> 2973 bytes .../site-packages/anyio/_backends/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 190 bytes .../__pycache__/_asyncio.cpython-312.pyc | Bin 0 -> 139824 bytes .../__pycache__/_trio.cpython-312.pyc | Bin 0 -> 73271 bytes .../site-packages/anyio/_backends/_asyncio.py | 3007 ++++++ .../site-packages/anyio/_backends/_trio.py | 1384 +++ .../Lib/site-packages/anyio/_core/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 186 bytes .../_asyncio_selector_thread.cpython-312.pyc | Bin 0 -> 8401 bytes .../_contextmanagers.cpython-312.pyc | Bin 0 -> 8996 bytes .../__pycache__/_eventloop.cpython-312.pyc | Bin 0 -> 8305 bytes .../__pycache__/_exceptions.cpython-312.pyc | Bin 0 -> 7263 bytes .../_core/__pycache__/_fileio.cpython-312.pyc | Bin 0 -> 43368 bytes .../__pycache__/_resources.cpython-312.pyc | Bin 0 -> 928 bytes .../__pycache__/_signals.cpython-312.pyc | Bin 0 -> 1271 bytes .../__pycache__/_sockets.cpython-312.pyc | Bin 0 -> 39926 bytes .../__pycache__/_streams.cpython-312.pyc | Bin 0 -> 2335 bytes .../__pycache__/_subprocesses.cpython-312.pyc | Bin 0 -> 9626 bytes .../_synchronization.cpython-312.pyc | Bin 0 -> 32941 bytes .../_core/__pycache__/_tasks.cpython-312.pyc | Bin 0 -> 7127 bytes .../__pycache__/_tempfile.cpython-312.pyc | Bin 0 -> 28130 bytes .../__pycache__/_testing.cpython-312.pyc | Bin 0 -> 3566 bytes .../__pycache__/_typedattr.cpython-312.pyc | Bin 0 -> 3831 bytes .../anyio/_core/_asyncio_selector_thread.py | 167 + .../anyio/_core/_contextmanagers.py | 200 + .../site-packages/anyio/_core/_eventloop.py | 229 + .../site-packages/anyio/_core/_exceptions.py | 153 + .../Lib/site-packages/anyio/_core/_fileio.py | 797 ++ .../site-packages/anyio/_core/_resources.py | 18 + .../Lib/site-packages/anyio/_core/_signals.py | 27 + .../Lib/site-packages/anyio/_core/_sockets.py | 991 ++ .../Lib/site-packages/anyio/_core/_streams.py | 52 + .../anyio/_core/_subprocesses.py | 202 + .../anyio/_core/_synchronization.py | 753 ++ .../Lib/site-packages/anyio/_core/_tasks.py | 163 + .../site-packages/anyio/_core/_tempfile.py | 616 ++ .../Lib/site-packages/anyio/_core/_testing.py | 78 + .../site-packages/anyio/_core/_typedattr.py | 81 + .../Lib/site-packages/anyio/abc/__init__.py | 58 + .../abc/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 2361 bytes .../__pycache__/_eventloop.cpython-312.pyc | Bin 0 -> 16888 bytes .../__pycache__/_resources.cpython-312.pyc | Bin 0 -> 1633 bytes .../abc/__pycache__/_sockets.cpython-312.pyc | Bin 0 -> 18426 bytes .../abc/__pycache__/_streams.cpython-312.pyc | Bin 0 -> 9887 bytes .../__pycache__/_subprocesses.cpython-312.pyc | Bin 0 -> 3241 bytes .../abc/__pycache__/_tasks.cpython-312.pyc | Bin 0 -> 5140 bytes .../abc/__pycache__/_testing.cpython-312.pyc | Bin 0 -> 2836 bytes .../Lib/site-packages/anyio/abc/_eventloop.py | 420 + .../Lib/site-packages/anyio/abc/_resources.py | 33 + .../Lib/site-packages/anyio/abc/_sockets.py | 405 + .../Lib/site-packages/anyio/abc/_streams.py | 239 + .../site-packages/anyio/abc/_subprocesses.py | 79 + .../Lib/site-packages/anyio/abc/_tasks.py | 117 + .../Lib/site-packages/anyio/abc/_testing.py | 65 + .../Lib/site-packages/anyio/from_thread.py | 570 ++ .../Lib/site-packages/anyio/functools.py | 347 + .../.venv/Lib/site-packages/anyio/lowlevel.py | 195 + .../.venv/Lib/site-packages/anyio/py.typed | 0 .../Lib/site-packages/anyio/pytest_plugin.py | 302 + .../site-packages/anyio/streams/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 188 bytes .../__pycache__/buffered.cpython-312.pyc | Bin 0 -> 9067 bytes .../streams/__pycache__/file.cpython-312.pyc | Bin 0 -> 7562 bytes .../__pycache__/memory.cpython-312.pyc | Bin 0 -> 15009 bytes .../__pycache__/stapled.cpython-312.pyc | Bin 0 -> 7538 bytes .../streams/__pycache__/text.cpython-312.pyc | Bin 0 -> 9334 bytes .../streams/__pycache__/tls.cpython-312.pyc | Bin 0 -> 20219 bytes .../site-packages/anyio/streams/buffered.py | 188 + .../Lib/site-packages/anyio/streams/file.py | 154 + .../Lib/site-packages/anyio/streams/memory.py | 325 + .../site-packages/anyio/streams/stapled.py | 147 + .../Lib/site-packages/anyio/streams/text.py | 176 + .../Lib/site-packages/anyio/streams/tls.py | 424 + .../Lib/site-packages/anyio/to_interpreter.py | 246 + .../Lib/site-packages/anyio/to_process.py | 264 + .../Lib/site-packages/anyio/to_thread.py | 74 + .../click-8.3.1.dist-info/INSTALLER | 1 + .../click-8.3.1.dist-info/METADATA | 84 + .../click-8.3.1.dist-info/RECORD | 40 + .../site-packages/click-8.3.1.dist-info/WHEEL | 4 + .../licenses/LICENSE.txt | 28 + .../.venv/Lib/site-packages/click/__init__.py | 123 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 4066 bytes .../click/__pycache__/_compat.cpython-312.pyc | Bin 0 -> 24185 bytes .../__pycache__/_termui_impl.cpython-312.pyc | Bin 0 -> 31554 bytes .../__pycache__/_textwrap.cpython-312.pyc | Bin 0 -> 2414 bytes .../click/__pycache__/_utils.cpython-312.pyc | Bin 0 -> 1194 bytes .../__pycache__/_winconsole.cpython-312.pyc | Bin 0 -> 11759 bytes .../click/__pycache__/core.cpython-312.pyc | Bin 0 -> 134390 bytes .../__pycache__/decorators.cpython-312.pyc | Bin 0 -> 22131 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 14771 bytes .../__pycache__/formatting.cpython-312.pyc | Bin 0 -> 13592 bytes .../click/__pycache__/globals.cpython-312.pyc | Bin 0 -> 2959 bytes .../click/__pycache__/parser.cpython-312.pyc | Bin 0 -> 20418 bytes .../shell_completion.cpython-312.pyc | Bin 0 -> 23293 bytes .../click/__pycache__/termui.cpython-312.pyc | Bin 0 -> 34646 bytes .../click/__pycache__/testing.cpython-312.pyc | Bin 0 -> 27388 bytes .../click/__pycache__/types.cpython-312.pyc | Bin 0 -> 50058 bytes .../click/__pycache__/utils.cpython-312.pyc | Bin 0 -> 24863 bytes .../.venv/Lib/site-packages/click/_compat.py | 622 ++ .../Lib/site-packages/click/_termui_impl.py | 852 ++ .../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 | 3415 +++++++ .../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 + .../.venv/Lib/site-packages/click/py.typed | 0 .../site-packages/click/shell_completion.py | 667 ++ .../.venv/Lib/site-packages/click/termui.py | 883 ++ .../.venv/Lib/site-packages/click/testing.py | 577 ++ .../.venv/Lib/site-packages/click/types.py | 1209 +++ .../.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 -> 483 bytes .../colorama/__pycache__/ansi.cpython-312.pyc | Bin 0 -> 3936 bytes .../__pycache__/ansitowin32.cpython-312.pyc | Bin 0 -> 16403 bytes .../__pycache__/initialise.cpython-312.pyc | Bin 0 -> 3541 bytes .../__pycache__/win32.cpython-312.pyc | Bin 0 -> 8126 bytes .../__pycache__/winterm.cpython-312.pyc | Bin 0 -> 9079 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 -> 189 bytes .../__pycache__/ansi_test.cpython-312.pyc | Bin 0 -> 5458 bytes .../ansitowin32_test.cpython-312.pyc | Bin 0 -> 17997 bytes .../initialise_test.cpython-312.pyc | Bin 0 -> 11645 bytes .../__pycache__/isatty_test.cpython-312.pyc | Bin 0 -> 4772 bytes .../tests/__pycache__/utils.cpython-312.pyc | Bin 0 -> 2461 bytes .../__pycache__/winterm_test.cpython-312.pyc | Bin 0 -> 6603 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 + .../Lib/site-packages/dotenv/__init__.py | 51 + .../Lib/site-packages/dotenv/__main__.py | 6 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1686 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 354 bytes .../dotenv/__pycache__/cli.cpython-312.pyc | Bin 0 -> 10280 bytes .../__pycache__/ipython.cpython-312.pyc | Bin 0 -> 1970 bytes .../dotenv/__pycache__/main.cpython-312.pyc | Bin 0 -> 18130 bytes .../dotenv/__pycache__/parser.cpython-312.pyc | Bin 0 -> 9980 bytes .../__pycache__/variables.cpython-312.pyc | Bin 0 -> 5022 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 206 bytes backend/.venv/Lib/site-packages/dotenv/cli.py | 218 + .../.venv/Lib/site-packages/dotenv/ipython.py | 50 + .../.venv/Lib/site-packages/dotenv/main.py | 435 + .../.venv/Lib/site-packages/dotenv/parser.py | 182 + .../.venv/Lib/site-packages/dotenv/py.typed | 1 + .../Lib/site-packages/dotenv/variables.py | 86 + .../.venv/Lib/site-packages/dotenv/version.py | 1 + .../fastapi-0.115.6.dist-info/INSTALLER | 1 + .../fastapi-0.115.6.dist-info/METADATA | 562 ++ .../fastapi-0.115.6.dist-info/RECORD | 97 + .../fastapi-0.115.6.dist-info/REQUESTED | 0 .../fastapi-0.115.6.dist-info/WHEEL | 4 + .../entry_points.txt | 5 + .../licenses/LICENSE | 21 + .../Lib/site-packages/fastapi/__init__.py | 25 + .../Lib/site-packages/fastapi/__main__.py | 3 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1097 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 244 bytes .../__pycache__/_compat.cpython-312.pyc | Bin 0 -> 27872 bytes .../__pycache__/applications.cpython-312.pyc | Bin 0 -> 84112 bytes .../__pycache__/background.cpython-312.pyc | Bin 0 -> 2370 bytes .../fastapi/__pycache__/cli.cpython-312.pyc | Bin 0 -> 658 bytes .../__pycache__/concurrency.cpython-312.pyc | Bin 0 -> 1671 bytes .../datastructures.cpython-312.pyc | Bin 0 -> 8143 bytes .../__pycache__/encoders.cpython-312.pyc | Bin 0 -> 10893 bytes .../exception_handlers.cpython-312.pyc | Bin 0 -> 2072 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 7158 bytes .../__pycache__/logger.cpython-312.pyc | Bin 0 -> 284 bytes .../param_functions.cpython-312.pyc | Bin 0 -> 35095 bytes .../__pycache__/params.cpython-312.pyc | Bin 0 -> 25040 bytes .../__pycache__/requests.cpython-312.pyc | Bin 0 -> 273 bytes .../__pycache__/responses.cpython-312.pyc | Bin 0 -> 2401 bytes .../__pycache__/routing.cpython-312.pyc | Bin 0 -> 82043 bytes .../__pycache__/staticfiles.cpython-312.pyc | Bin 0 -> 245 bytes .../__pycache__/templating.cpython-312.pyc | Bin 0 -> 247 bytes .../__pycache__/testclient.cpython-312.pyc | Bin 0 -> 242 bytes .../fastapi/__pycache__/types.cpython-312.pyc | Bin 0 -> 753 bytes .../fastapi/__pycache__/utils.cpython-312.pyc | Bin 0 -> 8371 bytes .../__pycache__/websockets.cpython-312.pyc | Bin 0 -> 322 bytes .../Lib/site-packages/fastapi/_compat.py | 659 ++ .../Lib/site-packages/fastapi/applications.py | 4585 +++++++++ .../Lib/site-packages/fastapi/background.py | 59 + .../.venv/Lib/site-packages/fastapi/cli.py | 13 + .../Lib/site-packages/fastapi/concurrency.py | 39 + .../site-packages/fastapi/datastructures.py | 204 + .../fastapi/dependencies/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 195 bytes .../__pycache__/models.cpython-312.pyc | Bin 0 -> 2738 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 38032 bytes .../fastapi/dependencies/models.py | 37 + .../fastapi/dependencies/utils.py | 972 ++ .../Lib/site-packages/fastapi/encoders.py | 343 + .../fastapi/exception_handlers.py | 34 + .../Lib/site-packages/fastapi/exceptions.py | 176 + .../.venv/Lib/site-packages/fastapi/logger.py | 3 + .../fastapi/middleware/__init__.py | 1 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 251 bytes .../__pycache__/cors.cpython-312.pyc | Bin 0 -> 256 bytes .../__pycache__/gzip.cpython-312.pyc | Bin 0 -> 256 bytes .../__pycache__/httpsredirect.cpython-312.pyc | Bin 0 -> 285 bytes .../__pycache__/trustedhost.cpython-312.pyc | Bin 0 -> 279 bytes .../__pycache__/wsgi.cpython-312.pyc | Bin 0 -> 256 bytes .../site-packages/fastapi/middleware/cors.py | 1 + .../site-packages/fastapi/middleware/gzip.py | 1 + .../fastapi/middleware/httpsredirect.py | 3 + .../fastapi/middleware/trustedhost.py | 3 + .../site-packages/fastapi/middleware/wsgi.py | 1 + .../site-packages/fastapi/openapi/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 190 bytes .../__pycache__/constants.cpython-312.pyc | Bin 0 -> 360 bytes .../openapi/__pycache__/docs.cpython-312.pyc | Bin 0 -> 10810 bytes .../__pycache__/models.cpython-312.pyc | Bin 0 -> 22998 bytes .../openapi/__pycache__/utils.cpython-312.pyc | Bin 0 -> 20317 bytes .../fastapi/openapi/constants.py | 3 + .../Lib/site-packages/fastapi/openapi/docs.py | 344 + .../site-packages/fastapi/openapi/models.py | 445 + .../site-packages/fastapi/openapi/utils.py | 548 + .../site-packages/fastapi/param_functions.py | 2360 +++++ .../.venv/Lib/site-packages/fastapi/params.py | 786 ++ .../.venv/Lib/site-packages/fastapi/py.typed | 0 .../Lib/site-packages/fastapi/requests.py | 2 + .../Lib/site-packages/fastapi/responses.py | 48 + .../Lib/site-packages/fastapi/routing.py | 4439 +++++++++ .../fastapi/security/__init__.py | 15 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 847 bytes .../__pycache__/api_key.cpython-312.pyc | Bin 0 -> 9439 bytes .../security/__pycache__/base.cpython-312.pyc | Bin 0 -> 509 bytes .../security/__pycache__/http.cpython-312.pyc | Bin 0 -> 13745 bytes .../__pycache__/oauth2.cpython-312.pyc | Bin 0 -> 18261 bytes .../open_id_connect_url.cpython-312.pyc | Bin 0 -> 3220 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 602 bytes .../site-packages/fastapi/security/api_key.py | 301 + .../site-packages/fastapi/security/base.py | 6 + .../site-packages/fastapi/security/http.py | 420 + .../site-packages/fastapi/security/oauth2.py | 638 ++ .../fastapi/security/open_id_connect_url.py | 84 + .../site-packages/fastapi/security/utils.py | 10 + .../Lib/site-packages/fastapi/staticfiles.py | 1 + .../Lib/site-packages/fastapi/templating.py | 1 + .../Lib/site-packages/fastapi/testclient.py | 1 + .../.venv/Lib/site-packages/fastapi/types.py | 10 + .../.venv/Lib/site-packages/fastapi/utils.py | 220 + .../Lib/site-packages/fastapi/websockets.py | 3 + .../h11-0.16.0.dist-info/INSTALLER | 1 + .../h11-0.16.0.dist-info/METADATA | 202 + .../site-packages/h11-0.16.0.dist-info/RECORD | 29 + .../site-packages/h11-0.16.0.dist-info/WHEEL | 5 + .../h11-0.16.0.dist-info/licenses/LICENSE.txt | 22 + .../h11-0.16.0.dist-info/top_level.txt | 1 + .../.venv/Lib/site-packages/h11/__init__.py | 62 + .../h11/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1069 bytes .../h11/__pycache__/_abnf.cpython-312.pyc | Bin 0 -> 1775 bytes .../__pycache__/_connection.cpython-312.pyc | Bin 0 -> 23125 bytes .../h11/__pycache__/_events.cpython-312.pyc | Bin 0 -> 13215 bytes .../h11/__pycache__/_headers.cpython-312.pyc | Bin 0 -> 7977 bytes .../h11/__pycache__/_readers.cpython-312.pyc | Bin 0 -> 9642 bytes .../_receivebuffer.cpython-312.pyc | Bin 0 -> 4693 bytes .../h11/__pycache__/_state.cpython-312.pyc | Bin 0 -> 8457 bytes .../h11/__pycache__/_util.cpython-312.pyc | Bin 0 -> 4713 bytes .../h11/__pycache__/_version.cpython-312.pyc | Bin 0 -> 207 bytes .../h11/__pycache__/_writers.cpython-312.pyc | Bin 0 -> 6279 bytes backend/.venv/Lib/site-packages/h11/_abnf.py | 132 + .../Lib/site-packages/h11/_connection.py | 659 ++ .../.venv/Lib/site-packages/h11/_events.py | 369 + .../.venv/Lib/site-packages/h11/_headers.py | 282 + .../.venv/Lib/site-packages/h11/_readers.py | 250 + .../Lib/site-packages/h11/_receivebuffer.py | 153 + backend/.venv/Lib/site-packages/h11/_state.py | 365 + backend/.venv/Lib/site-packages/h11/_util.py | 135 + .../.venv/Lib/site-packages/h11/_version.py | 16 + .../.venv/Lib/site-packages/h11/_writers.py | 145 + backend/.venv/Lib/site-packages/h11/py.typed | 1 + .../httptools-0.7.1.dist-info/INSTALLER | 1 + .../httptools-0.7.1.dist-info/METADATA | 130 + .../httptools-0.7.1.dist-info/RECORD | 25 + .../httptools-0.7.1.dist-info/WHEEL | 5 + .../licenses/LICENSE | 21 + .../httptools-0.7.1.dist-info/top_level.txt | 1 + .../Lib/site-packages/httptools/__init__.py | 6 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 335 bytes .../__pycache__/_version.cpython-312.pyc | Bin 0 -> 212 bytes .../Lib/site-packages/httptools/_version.py | 13 + .../httptools/parser/__init__.py | 6 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 425 bytes .../parser/__pycache__/errors.cpython-312.pyc | Bin 0 -> 1209 bytes .../__pycache__/protocol.cpython-312.pyc | Bin 0 -> 1839 bytes .../httptools/parser/cparser.pxd | 167 + .../site-packages/httptools/parser/errors.py | 30 + .../parser/parser.cp312-win_amd64.pyd | Bin 0 -> 124928 bytes .../site-packages/httptools/parser/parser.pyi | 57 + .../site-packages/httptools/parser/parser.pyx | 436 + .../httptools/parser/protocol.py | 15 + .../site-packages/httptools/parser/python.pxd | 6 + .../httptools/parser/url_cparser.pxd | 31 + .../parser/url_parser.cp312-win_amd64.pyd | Bin 0 -> 53248 bytes .../httptools/parser/url_parser.pyi | 27 + .../httptools/parser/url_parser.pyx | 108 + .../idna-3.11.dist-info/INSTALLER | 1 + .../idna-3.11.dist-info/METADATA | 209 + .../site-packages/idna-3.11.dist-info/RECORD | 22 + .../site-packages/idna-3.11.dist-info/WHEEL | 4 + .../idna-3.11.dist-info/licenses/LICENSE.md | 31 + .../.venv/Lib/site-packages/idna/__init__.py | 45 + .../idna/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 877 bytes .../idna/__pycache__/codec.cpython-312.pyc | Bin 0 -> 4967 bytes .../idna/__pycache__/compat.cpython-312.pyc | Bin 0 -> 881 bytes .../idna/__pycache__/core.cpython-312.pyc | Bin 0 -> 16134 bytes .../idna/__pycache__/idnadata.cpython-312.pyc | Bin 0 -> 100906 bytes .../__pycache__/intranges.cpython-312.pyc | Bin 0 -> 2624 bytes .../__pycache__/package_data.cpython-312.pyc | Bin 0 -> 208 bytes .../__pycache__/uts46data.cpython-312.pyc | Bin 0 -> 161836 bytes backend/.venv/Lib/site-packages/idna/codec.py | 122 + .../.venv/Lib/site-packages/idna/compat.py | 15 + backend/.venv/Lib/site-packages/idna/core.py | 437 + .../.venv/Lib/site-packages/idna/idnadata.py | 4309 ++++++++ .../.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 | 8841 +++++++++++++++++ .../pip-24.3.1.dist-info/AUTHORS.txt | 799 ++ .../pip-24.3.1.dist-info/INSTALLER | 1 + .../pip-24.3.1.dist-info/LICENSE.txt | 20 + .../pip-24.3.1.dist-info/METADATA | 90 + .../site-packages/pip-24.3.1.dist-info/RECORD | 853 ++ .../pip-24.3.1.dist-info/REQUESTED | 0 .../site-packages/pip-24.3.1.dist-info/WHEEL | 5 + .../pip-24.3.1.dist-info/entry_points.txt | 3 + .../pip-24.3.1.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 -> 689 bytes .../pip/__pycache__/__main__.cpython-312.pyc | Bin 0 -> 843 bytes .../__pip-runner__.cpython-312.pyc | Bin 0 -> 2207 bytes .../site-packages/pip/_internal/__init__.py | 18 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 789 bytes .../__pycache__/build_env.cpython-312.pyc | Bin 0 -> 14501 bytes .../__pycache__/cache.cpython-312.pyc | Bin 0 -> 12669 bytes .../__pycache__/configuration.cpython-312.pyc | Bin 0 -> 17634 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 36847 bytes .../__pycache__/main.cpython-312.pyc | Bin 0 -> 672 bytes .../__pycache__/pyproject.cpython-312.pyc | Bin 0 -> 5120 bytes .../self_outdated_check.cpython-312.pyc | Bin 0 -> 10210 bytes .../__pycache__/wheel_builder.cpython-312.pyc | Bin 0 -> 13617 bytes .../site-packages/pip/_internal/build_env.py | 319 + .../Lib/site-packages/pip/_internal/cache.py | 290 + .../pip/_internal/cli/__init__.py | 4 + .../cli/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 280 bytes .../autocompletion.cpython-312.pyc | Bin 0 -> 8608 bytes .../__pycache__/base_command.cpython-312.pyc | Bin 0 -> 10196 bytes .../__pycache__/cmdoptions.cpython-312.pyc | Bin 0 -> 30397 bytes .../command_context.cpython-312.pyc | Bin 0 -> 1776 bytes .../__pycache__/index_command.cpython-312.pyc | Bin 0 -> 7126 bytes .../cli/__pycache__/main.cpython-312.pyc | Bin 0 -> 2302 bytes .../__pycache__/main_parser.cpython-312.pyc | Bin 0 -> 4908 bytes .../cli/__pycache__/parser.cpython-312.pyc | Bin 0 -> 15042 bytes .../__pycache__/progress_bars.cpython-312.pyc | Bin 0 -> 3846 bytes .../__pycache__/req_command.cpython-312.pyc | Bin 0 -> 12243 bytes .../cli/__pycache__/spinners.cpython-312.pyc | Bin 0 -> 7835 bytes .../__pycache__/status_codes.cpython-312.pyc | Bin 0 -> 377 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 -> 4004 bytes .../__pycache__/cache.cpython-312.pyc | Bin 0 -> 9703 bytes .../__pycache__/check.cpython-312.pyc | Bin 0 -> 2594 bytes .../__pycache__/completion.cpython-312.pyc | Bin 0 -> 5195 bytes .../__pycache__/configuration.cpython-312.pyc | Bin 0 -> 13165 bytes .../__pycache__/debug.cpython-312.pyc | Bin 0 -> 10070 bytes .../__pycache__/download.cpython-312.pyc | Bin 0 -> 7505 bytes .../__pycache__/freeze.cpython-312.pyc | Bin 0 -> 4387 bytes .../commands/__pycache__/hash.cpython-312.pyc | Bin 0 -> 2970 bytes .../commands/__pycache__/help.cpython-312.pyc | Bin 0 -> 1675 bytes .../__pycache__/index.cpython-312.pyc | Bin 0 -> 6673 bytes .../__pycache__/inspect.cpython-312.pyc | Bin 0 -> 3982 bytes .../__pycache__/install.cpython-312.pyc | Bin 0 -> 29116 bytes .../commands/__pycache__/list.cpython-312.pyc | Bin 0 -> 15759 bytes .../__pycache__/search.cpython-312.pyc | Bin 0 -> 7520 bytes .../commands/__pycache__/show.cpython-312.pyc | Bin 0 -> 10479 bytes .../__pycache__/uninstall.cpython-312.pyc | Bin 0 -> 4711 bytes .../__pycache__/wheel.cpython-312.pyc | Bin 0 -> 8867 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 -> 943 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 2895 bytes .../__pycache__/installed.cpython-312.pyc | Bin 0 -> 1702 bytes .../__pycache__/sdist.cpython-312.pyc | Bin 0 -> 8429 bytes .../__pycache__/wheel.cpython-312.pyc | Bin 0 -> 2283 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 | 809 ++ .../pip/_internal/index/__init__.py | 2 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 234 bytes .../__pycache__/collector.cpython-312.pyc | Bin 0 -> 21619 bytes .../package_finder.cpython-312.pyc | Bin 0 -> 40650 bytes .../index/__pycache__/sources.cpython-312.pyc | Bin 0 -> 12526 bytes .../pip/_internal/index/collector.py | 494 + .../pip/_internal/index/package_finder.py | 1020 ++ .../pip/_internal/index/sources.py | 284 + .../pip/_internal/locations/__init__.py | 456 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 16442 bytes .../__pycache__/_distutils.cpython-312.pyc | Bin 0 -> 6793 bytes .../__pycache__/_sysconfig.cpython-312.pyc | Bin 0 -> 8030 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 3783 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 -> 5871 bytes .../__pycache__/_json.cpython-312.pyc | Bin 0 -> 2928 bytes .../metadata/__pycache__/base.cpython-312.pyc | Bin 0 -> 35200 bytes .../__pycache__/pkg_resources.cpython-312.pyc | Bin 0 -> 16086 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 -> 360 bytes .../__pycache__/_compat.cpython-312.pyc | Bin 0 -> 4493 bytes .../__pycache__/_dists.cpython-312.pyc | Bin 0 -> 12567 bytes .../__pycache__/_envs.cpython-312.pyc | Bin 0 -> 11081 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 -> 268 bytes .../__pycache__/candidate.cpython-312.pyc | Bin 0 -> 1606 bytes .../__pycache__/direct_url.cpython-312.pyc | Bin 0 -> 10846 bytes .../format_control.cpython-312.pyc | Bin 0 -> 4225 bytes .../models/__pycache__/index.cpython-312.pyc | Bin 0 -> 1696 bytes .../installation_report.cpython-312.pyc | Bin 0 -> 2279 bytes .../models/__pycache__/link.cpython-312.pyc | Bin 0 -> 26619 bytes .../models/__pycache__/scheme.cpython-312.pyc | Bin 0 -> 1025 bytes .../__pycache__/search_scope.cpython-312.pyc | Bin 0 -> 4989 bytes .../selection_prefs.cpython-312.pyc | Bin 0 -> 1853 bytes .../__pycache__/target_python.cpython-312.pyc | Bin 0 -> 4955 bytes .../models/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 6554 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 | 118 + .../pip/_internal/network/__init__.py | 2 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 256 bytes .../network/__pycache__/auth.cpython-312.pyc | Bin 0 -> 22101 bytes .../network/__pycache__/cache.cpython-312.pyc | Bin 0 -> 6453 bytes .../__pycache__/download.cpython-312.pyc | Bin 0 -> 8481 bytes .../__pycache__/lazy_wheel.cpython-312.pyc | Bin 0 -> 11609 bytes .../__pycache__/session.cpython-312.pyc | Bin 0 -> 18876 bytes .../network/__pycache__/utils.cpython-312.pyc | Bin 0 -> 2257 bytes .../__pycache__/xmlrpc.cpython-312.pyc | Bin 0 -> 2951 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 -> 199 bytes .../__pycache__/check.cpython-312.pyc | Bin 0 -> 7106 bytes .../__pycache__/freeze.cpython-312.pyc | Bin 0 -> 10130 bytes .../__pycache__/prepare.cpython-312.pyc | Bin 0 -> 25774 bytes .../_internal/operations/build/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 205 bytes .../__pycache__/build_tracker.cpython-312.pyc | Bin 0 -> 7669 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 0 -> 1859 bytes .../metadata_editable.cpython-312.pyc | Bin 0 -> 1893 bytes .../metadata_legacy.cpython-312.pyc | Bin 0 -> 3013 bytes .../build/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 1679 bytes .../wheel_editable.cpython-312.pyc | Bin 0 -> 2018 bytes .../__pycache__/wheel_legacy.cpython-312.pyc | Bin 0 -> 3848 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 -> 268 bytes .../editable_legacy.cpython-312.pyc | Bin 0 -> 1800 bytes .../install/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 34105 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 -> 3447 bytes .../__pycache__/constructors.cpython-312.pyc | Bin 0 -> 21257 bytes .../req/__pycache__/req_file.cpython-312.pyc | Bin 0 -> 22125 bytes .../__pycache__/req_install.cpython-312.pyc | Bin 0 -> 38477 bytes .../req/__pycache__/req_set.cpython-312.pyc | Bin 0 -> 5485 bytes .../__pycache__/req_uninstall.cpython-312.pyc | Bin 0 -> 32096 bytes .../pip/_internal/req/constructors.py | 560 ++ .../pip/_internal/req/req_file.py | 574 ++ .../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 -> 199 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 1187 bytes .../pip/_internal/resolution/base.py | 20 + .../_internal/resolution/legacy/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 206 bytes .../__pycache__/resolver.cpython-312.pyc | Bin 0 -> 22581 bytes .../_internal/resolution/legacy/resolver.py | 597 ++ .../resolution/resolvelib/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 210 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 8151 bytes .../__pycache__/candidates.cpython-312.pyc | Bin 0 -> 29410 bytes .../__pycache__/factory.cpython-312.pyc | Bin 0 -> 32521 bytes .../found_candidates.cpython-312.pyc | Bin 0 -> 6795 bytes .../__pycache__/provider.cpython-312.pyc | Bin 0 -> 10525 bytes .../__pycache__/reporter.cpython-312.pyc | Bin 0 -> 5042 bytes .../__pycache__/requirements.cpython-312.pyc | Bin 0 -> 15358 bytes .../__pycache__/resolver.cpython-312.pyc | Bin 0 -> 12316 bytes .../_internal/resolution/resolvelib/base.py | 139 + .../resolution/resolvelib/candidates.py | 574 ++ .../resolution/resolvelib/factory.py | 823 ++ .../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 -> 194 bytes .../__pycache__/_jaraco_text.cpython-312.pyc | Bin 0 -> 4529 bytes .../utils/__pycache__/_log.cpython-312.pyc | Bin 0 -> 1865 bytes .../utils/__pycache__/appdirs.cpython-312.pyc | Bin 0 -> 2409 bytes .../utils/__pycache__/compat.cpython-312.pyc | Bin 0 -> 2906 bytes .../compatibility_tags.cpython-312.pyc | Bin 0 -> 6349 bytes .../__pycache__/datetime.cpython-312.pyc | Bin 0 -> 683 bytes .../__pycache__/deprecation.cpython-312.pyc | Bin 0 -> 4190 bytes .../direct_url_helpers.cpython-312.pyc | Bin 0 -> 3535 bytes .../__pycache__/egg_link.cpython-312.pyc | Bin 0 -> 3205 bytes .../__pycache__/encoding.cpython-312.pyc | Bin 0 -> 2147 bytes .../__pycache__/entrypoints.cpython-312.pyc | Bin 0 -> 3992 bytes .../__pycache__/filesystem.cpython-312.pyc | Bin 0 -> 7328 bytes .../__pycache__/filetypes.cpython-312.pyc | Bin 0 -> 1163 bytes .../utils/__pycache__/glibc.cpython-312.pyc | Bin 0 -> 2418 bytes .../utils/__pycache__/hashes.cpython-312.pyc | Bin 0 -> 7602 bytes .../utils/__pycache__/logging.cpython-312.pyc | Bin 0 -> 13557 bytes .../utils/__pycache__/misc.cpython-312.pyc | Bin 0 -> 33450 bytes .../__pycache__/packaging.cpython-312.pyc | Bin 0 -> 2582 bytes .../utils/__pycache__/retry.cpython-312.pyc | Bin 0 -> 2107 bytes .../setuptools_build.cpython-312.pyc | Bin 0 -> 4549 bytes .../__pycache__/subprocess.cpython-312.pyc | Bin 0 -> 8638 bytes .../__pycache__/temp_dir.cpython-312.pyc | Bin 0 -> 12023 bytes .../__pycache__/unpacking.cpython-312.pyc | Bin 0 -> 13497 bytes .../utils/__pycache__/urls.cpython-312.pyc | Bin 0 -> 2076 bytes .../__pycache__/virtualenv.cpython-312.pyc | Bin 0 -> 4465 bytes .../utils/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 5902 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 | 188 + .../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 | 772 ++ .../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 -> 533 bytes .../vcs/__pycache__/bazaar.cpython-312.pyc | Bin 0 -> 5054 bytes .../vcs/__pycache__/git.cpython-312.pyc | Bin 0 -> 19019 bytes .../vcs/__pycache__/mercurial.cpython-312.pyc | Bin 0 -> 7607 bytes .../__pycache__/subversion.cpython-312.pyc | Bin 0 -> 12526 bytes .../versioncontrol.cpython-312.pyc | Bin 0 -> 28999 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 -> 4552 bytes .../typing_extensions.cpython-312.pyc | Bin 0 -> 139454 bytes .../pip/_vendor/cachecontrol/__init__.py | 28 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 905 bytes .../__pycache__/_cmd.cpython-312.pyc | Bin 0 -> 2649 bytes .../__pycache__/adapter.cpython-312.pyc | Bin 0 -> 6467 bytes .../__pycache__/cache.cpython-312.pyc | Bin 0 -> 3790 bytes .../__pycache__/controller.cpython-312.pyc | Bin 0 -> 16227 bytes .../__pycache__/filewrapper.cpython-312.pyc | Bin 0 -> 4350 bytes .../__pycache__/heuristics.cpython-312.pyc | Bin 0 -> 6697 bytes .../__pycache__/serialize.cpython-312.pyc | Bin 0 -> 5264 bytes .../__pycache__/wrapper.cpython-312.pyc | Bin 0 -> 1677 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 -> 438 bytes .../__pycache__/file_cache.cpython-312.pyc | Bin 0 -> 7766 bytes .../__pycache__/redis_cache.cpython-312.pyc | Bin 0 -> 2736 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 -> 321 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 648 bytes .../certifi/__pycache__/core.cpython-312.pyc | Bin 0 -> 3214 bytes .../pip/_vendor/certifi/cacert.pem | 4929 +++++++++ .../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 -> 1272 bytes .../__pycache__/compat.cpython-312.pyc | Bin 0 -> 45529 bytes .../__pycache__/database.cpython-312.pyc | Bin 0 -> 65584 bytes .../distlib/__pycache__/index.cpython-312.pyc | Bin 0 -> 24319 bytes .../__pycache__/locators.cpython-312.pyc | Bin 0 -> 59864 bytes .../__pycache__/manifest.cpython-312.pyc | Bin 0 -> 15079 bytes .../__pycache__/markers.cpython-312.pyc | Bin 0 -> 7657 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 0 -> 41563 bytes .../__pycache__/resources.cpython-312.pyc | Bin 0 -> 17315 bytes .../__pycache__/scripts.cpython-312.pyc | Bin 0 -> 19756 bytes .../distlib/__pycache__/util.cpython-312.pyc | Bin 0 -> 88038 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 30347 bytes .../distlib/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 52548 bytes .../pip/_vendor/distlib/compat.py | 1137 +++ .../pip/_vendor/distlib/database.py | 1329 +++ .../pip/_vendor/distlib/index.py | 508 + .../pip/_vendor/distlib/locators.py | 1295 +++ .../pip/_vendor/distlib/manifest.py | 384 + .../pip/_vendor/distlib/markers.py | 162 + .../pip/_vendor/distlib/metadata.py | 1031 ++ .../pip/_vendor/distlib/resources.py | 358 + .../pip/_vendor/distlib/scripts.py | 447 + .../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 | 1984 ++++ .../pip/_vendor/distlib/version.py | 750 ++ .../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 | 1100 ++ .../pip/_vendor/distro/__init__.py | 54 + .../pip/_vendor/distro/__main__.py | 4 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 963 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 295 bytes .../distro/__pycache__/distro.cpython-312.pyc | Bin 0 -> 53795 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 -> 884 bytes .../idna/__pycache__/codec.cpython-312.pyc | Bin 0 -> 4979 bytes .../idna/__pycache__/compat.cpython-312.pyc | Bin 0 -> 890 bytes .../idna/__pycache__/core.cpython-312.pyc | Bin 0 -> 15794 bytes .../idna/__pycache__/idnadata.cpython-312.pyc | Bin 0 -> 99479 bytes .../__pycache__/intranges.cpython-312.pyc | Bin 0 -> 2636 bytes .../__pycache__/package_data.cpython-312.pyc | Bin 0 -> 219 bytes .../__pycache__/uts46data.cpython-312.pyc | Bin 0 -> 158851 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 -> 1744 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 2028 bytes .../msgpack/__pycache__/ext.cpython-312.pyc | Bin 0 -> 8173 bytes .../__pycache__/fallback.cpython-312.pyc | Bin 0 -> 42046 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 -> 561 bytes .../__pycache__/_elffile.cpython-312.pyc | Bin 0 -> 4970 bytes .../__pycache__/_manylinux.cpython-312.pyc | Bin 0 -> 9688 bytes .../__pycache__/_musllinux.cpython-312.pyc | Bin 0 -> 4557 bytes .../__pycache__/_parser.cpython-312.pyc | Bin 0 -> 13988 bytes .../__pycache__/_structures.cpython-312.pyc | Bin 0 -> 3244 bytes .../__pycache__/_tokenizer.cpython-312.pyc | Bin 0 -> 7918 bytes .../__pycache__/markers.cpython-312.pyc | Bin 0 -> 11014 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 0 -> 24956 bytes .../__pycache__/requirements.cpython-312.pyc | Bin 0 -> 4413 bytes .../__pycache__/specifiers.cpython-312.pyc | Bin 0 -> 38742 bytes .../__pycache__/tags.cpython-312.pyc | Bin 0 -> 23222 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 7344 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 19510 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 | 627 ++ .../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 -> 161264 bytes .../pip/_vendor/platformdirs/__init__.py | 627 ++ .../pip/_vendor/platformdirs/__main__.py | 55 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 19832 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 1951 bytes .../__pycache__/android.cpython-312.pyc | Bin 0 -> 10700 bytes .../__pycache__/api.cpython-312.pyc | Bin 0 -> 12914 bytes .../__pycache__/macos.cpython-312.pyc | Bin 0 -> 8010 bytes .../__pycache__/unix.cpython-312.pyc | Bin 0 -> 15040 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 600 bytes .../__pycache__/windows.cpython-312.pyc | Bin 0 -> 13677 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 -> 3492 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 738 bytes .../__pycache__/cmdline.cpython-312.pyc | Bin 0 -> 26588 bytes .../__pycache__/console.cpython-312.pyc | Bin 0 -> 2632 bytes .../__pycache__/filter.cpython-312.pyc | Bin 0 -> 3225 bytes .../__pycache__/formatter.cpython-312.pyc | Bin 0 -> 4724 bytes .../__pycache__/lexer.cpython-312.pyc | Bin 0 -> 38365 bytes .../__pycache__/modeline.cpython-312.pyc | Bin 0 -> 1563 bytes .../__pycache__/plugin.cpython-312.pyc | Bin 0 -> 2612 bytes .../__pycache__/regexopt.cpython-312.pyc | Bin 0 -> 4081 bytes .../__pycache__/scanner.cpython-312.pyc | Bin 0 -> 4760 bytes .../__pycache__/sphinxext.cpython-312.pyc | Bin 0 -> 12102 bytes .../__pycache__/style.cpython-312.pyc | Bin 0 -> 6697 bytes .../__pycache__/token.cpython-312.pyc | Bin 0 -> 8193 bytes .../__pycache__/unistring.cpython-312.pyc | Bin 0 -> 32976 bytes .../pygments/__pycache__/util.cpython-312.pyc | Bin 0 -> 14073 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 -> 37915 bytes .../pip/_vendor/pygments/formatter.py | 129 + .../_vendor/pygments/formatters/__init__.py | 157 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 6906 bytes .../__pycache__/_mapping.cpython-312.pyc | Bin 0 -> 4219 bytes .../__pycache__/bbcode.cpython-312.pyc | Bin 0 -> 4226 bytes .../__pycache__/groff.cpython-312.pyc | Bin 0 -> 7297 bytes .../__pycache__/html.cpython-312.pyc | Bin 0 -> 41030 bytes .../__pycache__/img.cpython-312.pyc | Bin 0 -> 28552 bytes .../__pycache__/irc.cpython-312.pyc | Bin 0 -> 6059 bytes .../__pycache__/latex.cpython-312.pyc | Bin 0 -> 20129 bytes .../__pycache__/other.cpython-312.pyc | Bin 0 -> 6881 bytes .../__pycache__/pangomarkup.cpython-312.pyc | Bin 0 -> 2962 bytes .../__pycache__/rtf.cpython-312.pyc | Bin 0 -> 13777 bytes .../__pycache__/svg.cpython-312.pyc | Bin 0 -> 9143 bytes .../__pycache__/terminal.cpython-312.pyc | Bin 0 -> 5823 bytes .../__pycache__/terminal256.cpython-312.pyc | Bin 0 -> 15122 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 -> 14625 bytes .../__pycache__/_mapping.cpython-312.pyc | Bin 0 -> 68267 bytes .../lexers/__pycache__/python.cpython-312.pyc | Bin 0 -> 42971 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 -> 2668 bytes .../__pycache__/_mapping.cpython-312.pyc | Bin 0 -> 3652 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 -> 617 bytes .../__pycache__/_compat.cpython-312.pyc | Bin 0 -> 378 bytes .../__pycache__/_impl.cpython-312.pyc | Bin 0 -> 14697 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 -> 1084 bytes .../__pycache__/_in_process.cpython-312.pyc | Bin 0 -> 14357 bytes .../_in_process/_in_process.py | 353 + .../pip/_vendor/requests/__init__.py | 179 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 5257 bytes .../__pycache__/__version__.cpython-312.pyc | Bin 0 -> 588 bytes .../_internal_utils.cpython-312.pyc | Bin 0 -> 2028 bytes .../__pycache__/adapters.cpython-312.pyc | Bin 0 -> 28435 bytes .../requests/__pycache__/api.cpython-312.pyc | Bin 0 -> 7195 bytes .../requests/__pycache__/auth.cpython-312.pyc | Bin 0 -> 13925 bytes .../__pycache__/certs.cpython-312.pyc | Bin 0 -> 926 bytes .../__pycache__/compat.cpython-312.pyc | Bin 0 -> 1681 bytes .../__pycache__/cookies.cpython-312.pyc | Bin 0 -> 25202 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 7602 bytes .../requests/__pycache__/help.cpython-312.pyc | Bin 0 -> 4232 bytes .../__pycache__/hooks.cpython-312.pyc | Bin 0 -> 1055 bytes .../__pycache__/models.cpython-312.pyc | Bin 0 -> 35432 bytes .../__pycache__/packages.cpython-312.pyc | Bin 0 -> 1270 bytes .../__pycache__/sessions.cpython-312.pyc | Bin 0 -> 27850 bytes .../__pycache__/status_codes.cpython-312.pyc | Bin 0 -> 6027 bytes .../__pycache__/structures.cpython-312.pyc | Bin 0 -> 5627 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 36370 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 -> 638 bytes .../__pycache__/providers.cpython-312.pyc | Bin 0 -> 6855 bytes .../__pycache__/reporters.cpython-312.pyc | Bin 0 -> 2658 bytes .../__pycache__/resolvers.cpython-312.pyc | Bin 0 -> 25884 bytes .../__pycache__/structs.cpython-312.pyc | Bin 0 -> 10504 bytes .../pip/_vendor/resolvelib/compat/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 204 bytes .../collections_abc.cpython-312.pyc | Bin 0 -> 424 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 -> 7019 bytes .../rich/__pycache__/__main__.cpython-312.pyc | Bin 0 -> 10296 bytes .../__pycache__/_cell_widths.cpython-312.pyc | Bin 0 -> 7876 bytes .../__pycache__/_emoji_codes.cpython-312.pyc | Bin 0 -> 205980 bytes .../_emoji_replace.cpython-312.pyc | Bin 0 -> 1733 bytes .../_export_format.cpython-312.pyc | Bin 0 -> 2353 bytes .../__pycache__/_extension.cpython-312.pyc | Bin 0 -> 541 bytes .../rich/__pycache__/_fileno.cpython-312.pyc | Bin 0 -> 859 bytes .../rich/__pycache__/_inspect.cpython-312.pyc | Bin 0 -> 12077 bytes .../__pycache__/_log_render.cpython-312.pyc | Bin 0 -> 4151 bytes .../rich/__pycache__/_loop.cpython-312.pyc | Bin 0 -> 1874 bytes .../__pycache__/_null_file.cpython-312.pyc | Bin 0 -> 3624 bytes .../__pycache__/_palettes.cpython-312.pyc | Bin 0 -> 5164 bytes .../rich/__pycache__/_pick.cpython-312.pyc | Bin 0 -> 725 bytes .../rich/__pycache__/_ratio.cpython-312.pyc | Bin 0 -> 6574 bytes .../__pycache__/_spinners.cpython-312.pyc | Bin 0 -> 13183 bytes .../rich/__pycache__/_stack.cpython-312.pyc | Bin 0 -> 969 bytes .../rich/__pycache__/_timer.cpython-312.pyc | Bin 0 -> 869 bytes .../_win32_console.cpython-312.pyc | Bin 0 -> 28980 bytes .../rich/__pycache__/_windows.cpython-312.pyc | Bin 0 -> 2494 bytes .../_windows_renderer.cpython-312.pyc | Bin 0 -> 3567 bytes .../rich/__pycache__/_wrap.cpython-312.pyc | Bin 0 -> 3330 bytes .../rich/__pycache__/abc.cpython-312.pyc | Bin 0 -> 1612 bytes .../rich/__pycache__/align.cpython-312.pyc | Bin 0 -> 12291 bytes .../rich/__pycache__/ansi.cpython-312.pyc | Bin 0 -> 9070 bytes .../rich/__pycache__/bar.cpython-312.pyc | Bin 0 -> 4276 bytes .../rich/__pycache__/box.cpython-312.pyc | Bin 0 -> 11842 bytes .../rich/__pycache__/cells.cpython-312.pyc | Bin 0 -> 5814 bytes .../rich/__pycache__/color.cpython-312.pyc | Bin 0 -> 26573 bytes .../__pycache__/color_triplet.cpython-312.pyc | Bin 0 -> 1705 bytes .../rich/__pycache__/columns.cpython-312.pyc | Bin 0 -> 8588 bytes .../rich/__pycache__/console.cpython-312.pyc | Bin 0 -> 113440 bytes .../__pycache__/constrain.cpython-312.pyc | Bin 0 -> 2262 bytes .../__pycache__/containers.cpython-312.pyc | Bin 0 -> 9214 bytes .../rich/__pycache__/control.cpython-312.pyc | Bin 0 -> 10945 bytes .../default_styles.cpython-312.pyc | Bin 0 -> 10370 bytes .../rich/__pycache__/diagnose.cpython-312.pyc | Bin 0 -> 1492 bytes .../rich/__pycache__/emoji.cpython-312.pyc | Bin 0 -> 4216 bytes .../rich/__pycache__/errors.cpython-312.pyc | Bin 0 -> 1849 bytes .../__pycache__/file_proxy.cpython-312.pyc | Bin 0 -> 3575 bytes .../rich/__pycache__/filesize.cpython-312.pyc | Bin 0 -> 3076 bytes .../__pycache__/highlighter.cpython-312.pyc | Bin 0 -> 9891 bytes .../rich/__pycache__/json.cpython-312.pyc | Bin 0 -> 6039 bytes .../rich/__pycache__/jupyter.cpython-312.pyc | Bin 0 -> 5212 bytes .../rich/__pycache__/layout.cpython-312.pyc | Bin 0 -> 20162 bytes .../rich/__pycache__/live.cpython-312.pyc | Bin 0 -> 19013 bytes .../__pycache__/live_render.cpython-312.pyc | Bin 0 -> 4893 bytes .../rich/__pycache__/logging.cpython-312.pyc | Bin 0 -> 13558 bytes .../rich/__pycache__/markup.cpython-312.pyc | Bin 0 -> 9571 bytes .../rich/__pycache__/measure.cpython-312.pyc | Bin 0 -> 6382 bytes .../rich/__pycache__/padding.cpython-312.pyc | Bin 0 -> 7128 bytes .../rich/__pycache__/pager.cpython-312.pyc | Bin 0 -> 1815 bytes .../rich/__pycache__/palette.cpython-312.pyc | Bin 0 -> 5301 bytes .../rich/__pycache__/panel.cpython-312.pyc | Bin 0 -> 12187 bytes .../rich/__pycache__/pretty.cpython-312.pyc | Bin 0 -> 40151 bytes .../rich/__pycache__/progress.cpython-312.pyc | Bin 0 -> 74939 bytes .../__pycache__/progress_bar.cpython-312.pyc | Bin 0 -> 10381 bytes .../rich/__pycache__/prompt.cpython-312.pyc | Bin 0 -> 14791 bytes .../rich/__pycache__/protocol.cpython-312.pyc | Bin 0 -> 1796 bytes .../rich/__pycache__/region.cpython-312.pyc | Bin 0 -> 571 bytes .../rich/__pycache__/repr.cpython-312.pyc | Bin 0 -> 6617 bytes .../rich/__pycache__/rule.cpython-312.pyc | Bin 0 -> 6572 bytes .../rich/__pycache__/scope.cpython-312.pyc | Bin 0 -> 3829 bytes .../rich/__pycache__/screen.cpython-312.pyc | Bin 0 -> 2483 bytes .../rich/__pycache__/segment.cpython-312.pyc | Bin 0 -> 28119 bytes .../rich/__pycache__/spinner.cpython-312.pyc | Bin 0 -> 6068 bytes .../rich/__pycache__/status.cpython-312.pyc | Bin 0 -> 6065 bytes .../rich/__pycache__/style.cpython-312.pyc | Bin 0 -> 33504 bytes .../rich/__pycache__/styled.cpython-312.pyc | Bin 0 -> 2143 bytes .../rich/__pycache__/syntax.cpython-312.pyc | Bin 0 -> 39952 bytes .../rich/__pycache__/table.cpython-312.pyc | Bin 0 -> 43543 bytes .../terminal_theme.cpython-312.pyc | Bin 0 -> 3352 bytes .../rich/__pycache__/text.cpython-312.pyc | Bin 0 -> 60853 bytes .../rich/__pycache__/theme.cpython-312.pyc | Bin 0 -> 6339 bytes .../rich/__pycache__/themes.cpython-312.pyc | Bin 0 -> 318 bytes .../__pycache__/traceback.cpython-312.pyc | Bin 0 -> 31515 bytes .../rich/__pycache__/tree.cpython-312.pyc | Bin 0 -> 11440 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 -> 388 bytes .../tomli/__pycache__/_parser.cpython-312.pyc | Bin 0 -> 26903 bytes .../tomli/__pycache__/_re.cpython-312.pyc | Bin 0 -> 3912 bytes .../tomli/__pycache__/_types.cpython-312.pyc | Bin 0 -> 370 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 | 36 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1348 bytes .../__pycache__/_api.cpython-312.pyc | Bin 0 -> 16777 bytes .../__pycache__/_macos.cpython-312.pyc | Bin 0 -> 18991 bytes .../__pycache__/_openssl.cpython-312.pyc | Bin 0 -> 2209 bytes .../_ssl_constants.cpython-312.pyc | Bin 0 -> 1103 bytes .../__pycache__/_windows.cpython-312.pyc | Bin 0 -> 15769 bytes .../pip/_vendor/truststore/_api.py | 316 + .../pip/_vendor/truststore/_macos.py | 571 ++ .../pip/_vendor/truststore/_openssl.py | 66 + .../pip/_vendor/truststore/_ssl_constants.py | 31 + .../pip/_vendor/truststore/_windows.py | 567 ++ .../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 -> 3409 bytes .../__pycache__/_collections.cpython-312.pyc | Bin 0 -> 16368 bytes .../__pycache__/_version.cpython-312.pyc | Bin 0 -> 222 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 20407 bytes .../connectionpool.cpython-312.pyc | Bin 0 -> 36542 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 13497 bytes .../__pycache__/fields.cpython-312.pyc | Bin 0 -> 10406 bytes .../__pycache__/filepost.cpython-312.pyc | Bin 0 -> 4016 bytes .../__pycache__/poolmanager.cpython-312.pyc | Bin 0 -> 20433 bytes .../__pycache__/request.cpython-312.pyc | Bin 0 -> 7298 bytes .../__pycache__/response.cpython-312.pyc | Bin 0 -> 33947 bytes .../pip/_vendor/urllib3/_collections.py | 355 + .../pip/_vendor/urllib3/_version.py | 2 + .../pip/_vendor/urllib3/connection.py | 572 ++ .../pip/_vendor/urllib3/connectionpool.py | 1140 +++ .../pip/_vendor/urllib3/contrib/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 202 bytes .../_appengine_environ.cpython-312.pyc | Bin 0 -> 1852 bytes .../__pycache__/appengine.cpython-312.pyc | Bin 0 -> 11568 bytes .../__pycache__/ntlmpool.cpython-312.pyc | Bin 0 -> 5718 bytes .../__pycache__/pyopenssl.cpython-312.pyc | Bin 0 -> 24452 bytes .../securetransport.cpython-312.pyc | Bin 0 -> 35505 bytes .../contrib/__pycache__/socks.cpython-312.pyc | Bin 0 -> 7515 bytes .../urllib3/contrib/_appengine_environ.py | 36 + .../contrib/_securetransport/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 219 bytes .../__pycache__/bindings.cpython-312.pyc | Bin 0 -> 17431 bytes .../__pycache__/low_level.cpython-312.pyc | Bin 0 -> 14767 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 -> 203 bytes .../packages/__pycache__/six.cpython-312.pyc | Bin 0 -> 41259 bytes .../urllib3/packages/backports/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 213 bytes .../__pycache__/makefile.cpython-312.pyc | Bin 0 -> 1829 bytes .../weakref_finalize.cpython-312.pyc | Bin 0 -> 7340 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 -> 1150 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 4751 bytes .../util/__pycache__/proxy.cpython-312.pyc | Bin 0 -> 1556 bytes .../util/__pycache__/queue.cpython-312.pyc | Bin 0 -> 1356 bytes .../util/__pycache__/request.cpython-312.pyc | Bin 0 -> 4187 bytes .../util/__pycache__/response.cpython-312.pyc | Bin 0 -> 2996 bytes .../util/__pycache__/retry.cpython-312.pyc | Bin 0 -> 21726 bytes .../util/__pycache__/ssl_.cpython-312.pyc | Bin 0 -> 15368 bytes .../ssl_match_hostname.cpython-312.pyc | Bin 0 -> 5055 bytes .../__pycache__/ssltransport.cpython-312.pyc | Bin 0 -> 10757 bytes .../util/__pycache__/timeout.cpython-312.pyc | Bin 0 -> 11143 bytes .../util/__pycache__/url.cpython-312.pyc | Bin 0 -> 15789 bytes .../util/__pycache__/wait.cpython-312.pyc | Bin 0 -> 4407 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 | 622 ++ .../pip/_vendor/urllib3/util/ssl_.py | 504 + .../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 + .../psycopg-3.2.3.dist-info/INSTALLER | 1 + .../psycopg-3.2.3.dist-info/LICENSE.txt | 165 + .../psycopg-3.2.3.dist-info/METADATA | 109 + .../psycopg-3.2.3.dist-info/RECORD | 165 + .../psycopg-3.2.3.dist-info/REQUESTED | 0 .../psycopg-3.2.3.dist-info/WHEEL | 5 + .../psycopg-3.2.3.dist-info/top_level.txt | 1 + .../Lib/site-packages/psycopg/__init__.py | 121 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 3121 bytes .../__pycache__/_acompat.cpython-312.pyc | Bin 0 -> 4354 bytes .../__pycache__/_adapters_map.cpython-312.pyc | Bin 0 -> 12424 bytes .../__pycache__/_capabilities.cpython-312.pyc | Bin 0 -> 5942 bytes .../__pycache__/_cmodule.cpython-312.pyc | Bin 0 -> 800 bytes .../__pycache__/_column.cpython-312.pyc | Bin 0 -> 5593 bytes .../__pycache__/_compat.cpython-312.pyc | Bin 0 -> 1794 bytes .../_connection_base.cpython-312.pyc | Bin 0 -> 32595 bytes .../_connection_info.cpython-312.pyc | Bin 0 -> 8975 bytes .../_conninfo_attempts.cpython-312.pyc | Bin 0 -> 3657 bytes .../_conninfo_attempts_async.cpython-312.pyc | Bin 0 -> 3930 bytes .../_conninfo_utils.cpython-312.pyc | Bin 0 -> 4366 bytes .../psycopg/__pycache__/_copy.cpython-312.pyc | Bin 0 -> 12284 bytes .../__pycache__/_copy_async.cpython-312.pyc | Bin 0 -> 13641 bytes .../__pycache__/_copy_base.cpython-312.pyc | Bin 0 -> 17498 bytes .../__pycache__/_cursor_base.cpython-312.pyc | Bin 0 -> 28155 bytes .../psycopg/__pycache__/_dns.cpython-312.pyc | Bin 0 -> 11354 bytes .../__pycache__/_encodings.cpython-312.pyc | Bin 0 -> 6189 bytes .../__pycache__/_enums.cpython-312.pyc | Bin 0 -> 2612 bytes .../psycopg/__pycache__/_oids.cpython-312.pyc | Bin 0 -> 2532 bytes .../__pycache__/_pipeline.cpython-312.pyc | Bin 0 -> 15139 bytes .../__pycache__/_preparing.cpython-312.pyc | Bin 0 -> 8534 bytes .../_py_transformer.cpython-312.pyc | Bin 0 -> 14417 bytes .../__pycache__/_queries.cpython-312.pyc | Bin 0 -> 16051 bytes .../__pycache__/_struct.cpython-312.pyc | Bin 0 -> 3633 bytes .../psycopg/__pycache__/_tpc.cpython-312.pyc | Bin 0 -> 5565 bytes .../__pycache__/_transformer.cpython-312.pyc | Bin 0 -> 670 bytes .../__pycache__/_typeinfo.cpython-312.pyc | Bin 0 -> 16086 bytes .../__pycache__/_typemod.cpython-312.pyc | Bin 0 -> 4223 bytes .../psycopg/__pycache__/_tz.cpython-312.pyc | Bin 0 -> 1871 bytes .../__pycache__/_wrappers.cpython-312.pyc | Bin 0 -> 5919 bytes .../psycopg/__pycache__/abc.cpython-312.pyc | Bin 0 -> 10826 bytes .../psycopg/__pycache__/adapt.cpython-312.pyc | Bin 0 -> 6153 bytes .../__pycache__/client_cursor.cpython-312.pyc | Bin 0 -> 3978 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 22231 bytes .../connection_async.cpython-312.pyc | Bin 0 -> 27272 bytes .../__pycache__/conninfo.cpython-312.pyc | Bin 0 -> 5279 bytes .../psycopg/__pycache__/copy.cpython-312.pyc | Bin 0 -> 1571 bytes .../__pycache__/cursor.cpython-312.pyc | Bin 0 -> 14910 bytes .../__pycache__/cursor_async.cpython-312.pyc | Bin 0 -> 17506 bytes .../__pycache__/dbapi20.cpython-312.pyc | Bin 0 -> 6743 bytes .../__pycache__/errors.cpython-312.pyc | Bin 0 -> 79169 bytes .../__pycache__/generators.cpython-312.pyc | Bin 0 -> 13543 bytes .../__pycache__/postgres.cpython-312.pyc | Bin 0 -> 7825 bytes .../__pycache__/raw_cursor.cpython-312.pyc | Bin 0 -> 3597 bytes .../psycopg/__pycache__/rows.cpython-312.pyc | Bin 0 -> 11421 bytes .../__pycache__/server_cursor.cpython-312.pyc | Bin 0 -> 25081 bytes .../psycopg/__pycache__/sql.cpython-312.pyc | Bin 0 -> 22166 bytes .../__pycache__/transaction.cpython-312.pyc | Bin 0 -> 14101 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 491 bytes .../__pycache__/waiting.cpython-312.pyc | Bin 0 -> 15193 bytes .../Lib/site-packages/psycopg/_acompat.py | 106 + .../site-packages/psycopg/_adapters_map.py | 296 + .../site-packages/psycopg/_capabilities.py | 132 + .../Lib/site-packages/psycopg/_cmodule.py | 24 + .../Lib/site-packages/psycopg/_column.py | 104 + .../Lib/site-packages/psycopg/_compat.py | 59 + .../site-packages/psycopg/_connection_base.py | 691 ++ .../site-packages/psycopg/_connection_info.py | 173 + .../psycopg/_conninfo_attempts.py | 96 + .../psycopg/_conninfo_attempts_async.py | 101 + .../site-packages/psycopg/_conninfo_utils.py | 124 + .../.venv/Lib/site-packages/psycopg/_copy.py | 298 + .../Lib/site-packages/psycopg/_copy_async.py | 299 + .../Lib/site-packages/psycopg/_copy_base.py | 438 + .../Lib/site-packages/psycopg/_cursor_base.py | 627 ++ .../.venv/Lib/site-packages/psycopg/_dns.py | 247 + .../Lib/site-packages/psycopg/_encodings.py | 154 + .../.venv/Lib/site-packages/psycopg/_enums.py | 80 + .../.venv/Lib/site-packages/psycopg/_oids.py | 97 + .../Lib/site-packages/psycopg/_pipeline.py | 268 + .../Lib/site-packages/psycopg/_preparing.py | 201 + .../site-packages/psycopg/_py_transformer.py | 361 + .../Lib/site-packages/psycopg/_queries.py | 425 + .../Lib/site-packages/psycopg/_struct.py | 57 + .../.venv/Lib/site-packages/psycopg/_tpc.py | 115 + .../Lib/site-packages/psycopg/_transformer.py | 21 + .../Lib/site-packages/psycopg/_typeinfo.py | 343 + .../Lib/site-packages/psycopg/_typemod.py | 86 + .../.venv/Lib/site-packages/psycopg/_tz.py | 45 + .../Lib/site-packages/psycopg/_wrappers.py | 137 + .../.venv/Lib/site-packages/psycopg/abc.py | 251 + .../.venv/Lib/site-packages/psycopg/adapt.py | 153 + .../site-packages/psycopg/client_cursor.py | 93 + .../Lib/site-packages/psycopg/connection.py | 479 + .../site-packages/psycopg/connection_async.py | 519 + .../Lib/site-packages/psycopg/conninfo.py | 154 + .../.venv/Lib/site-packages/psycopg/copy.py | 35 + .../site-packages/psycopg/crdb/__init__.py | 20 + .../crdb/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 693 bytes .../crdb/__pycache__/_types.cpython-312.pyc | Bin 0 -> 9477 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 4774 bytes .../Lib/site-packages/psycopg/crdb/_types.py | 201 + .../site-packages/psycopg/crdb/connection.py | 105 + .../.venv/Lib/site-packages/psycopg/cursor.py | 288 + .../Lib/site-packages/psycopg/cursor_async.py | 298 + .../Lib/site-packages/psycopg/dbapi20.py | 134 + .../.venv/Lib/site-packages/psycopg/errors.py | 1759 ++++ .../Lib/site-packages/psycopg/generators.py | 407 + .../Lib/site-packages/psycopg/postgres.py | 158 + .../Lib/site-packages/psycopg/pq/__init__.py | 137 + .../pq/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 4114 bytes .../pq/__pycache__/_debug.cpython-312.pyc | Bin 0 -> 5237 bytes .../pq/__pycache__/_enums.cpython-312.pyc | Bin 0 -> 5178 bytes .../pq/__pycache__/_pq_ctypes.cpython-312.pyc | Bin 0 -> 20981 bytes .../pq/__pycache__/abc.cpython-312.pyc | Bin 0 -> 18861 bytes .../pq/__pycache__/misc.cpython-312.pyc | Bin 0 -> 8434 bytes .../pq/__pycache__/pq_ctypes.cpython-312.pyc | Bin 0 -> 63278 bytes .../Lib/site-packages/psycopg/pq/_debug.py | 104 + .../Lib/site-packages/psycopg/pq/_enums.py | 259 + .../site-packages/psycopg/pq/_pq_ctypes.py | 841 ++ .../site-packages/psycopg/pq/_pq_ctypes.pyi | 227 + .../.venv/Lib/site-packages/psycopg/pq/abc.py | 336 + .../Lib/site-packages/psycopg/pq/misc.py | 187 + .../Lib/site-packages/psycopg/pq/pq_ctypes.py | 1276 +++ .../.venv/Lib/site-packages/psycopg/py.typed | 0 .../Lib/site-packages/psycopg/raw_cursor.py | 73 + .../.venv/Lib/site-packages/psycopg/rows.py | 276 + .../site-packages/psycopg/server_cursor.py | 475 + .../.venv/Lib/site-packages/psycopg/sql.py | 484 + .../Lib/site-packages/psycopg/transaction.py | 286 + .../site-packages/psycopg/types/__init__.py | 11 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 367 bytes .../types/__pycache__/array.cpython-312.pyc | Bin 0 -> 21715 bytes .../types/__pycache__/bool.cpython-312.pyc | Bin 0 -> 2675 bytes .../__pycache__/composite.cpython-312.pyc | Bin 0 -> 17711 bytes .../__pycache__/datetime.cpython-312.pyc | Bin 0 -> 37932 bytes .../types/__pycache__/enum.cpython-312.pyc | Bin 0 -> 11576 bytes .../types/__pycache__/hstore.cpython-312.pyc | Bin 0 -> 6022 bytes .../types/__pycache__/json.cpython-312.pyc | Bin 0 -> 10964 bytes .../__pycache__/multirange.cpython-312.pyc | Bin 0 -> 27181 bytes .../types/__pycache__/net.cpython-312.pyc | Bin 0 -> 10596 bytes .../types/__pycache__/none.cpython-312.pyc | Bin 0 -> 1394 bytes .../types/__pycache__/numeric.cpython-312.pyc | Bin 0 -> 24291 bytes .../types/__pycache__/numpy.cpython-312.pyc | Bin 0 -> 5516 bytes .../types/__pycache__/range.cpython-312.pyc | Bin 0 -> 31821 bytes .../types/__pycache__/shapely.cpython-312.pyc | Bin 0 -> 4404 bytes .../types/__pycache__/string.cpython-312.pyc | Bin 0 -> 11375 bytes .../types/__pycache__/uuid.cpython-312.pyc | Bin 0 -> 3260 bytes .../Lib/site-packages/psycopg/types/array.py | 476 + .../Lib/site-packages/psycopg/types/bool.py | 50 + .../site-packages/psycopg/types/composite.py | 386 + .../site-packages/psycopg/types/datetime.py | 763 ++ .../Lib/site-packages/psycopg/types/enum.py | 254 + .../Lib/site-packages/psycopg/types/hstore.py | 146 + .../Lib/site-packages/psycopg/types/json.py | 253 + .../site-packages/psycopg/types/multirange.py | 561 ++ .../Lib/site-packages/psycopg/types/net.py | 203 + .../Lib/site-packages/psycopg/types/none.py | 27 + .../site-packages/psycopg/types/numeric.py | 551 + .../Lib/site-packages/psycopg/types/numpy.py | 99 + .../Lib/site-packages/psycopg/types/range.py | 753 ++ .../site-packages/psycopg/types/shapely.py | 89 + .../Lib/site-packages/psycopg/types/string.py | 233 + .../Lib/site-packages/psycopg/types/uuid.py | 64 + .../Lib/site-packages/psycopg/version.py | 12 + .../Lib/site-packages/psycopg/waiting.py | 424 + .../psycopg_binary-3.2.3.dist-info/DELVEWHEEL | 2 + .../psycopg_binary-3.2.3.dist-info/INSTALLER | 1 + .../LICENSE.txt | 165 + .../psycopg_binary-3.2.3.dist-info/METADATA | 70 + .../psycopg_binary-3.2.3.dist-info/RECORD | 21 + .../psycopg_binary-3.2.3.dist-info/WHEEL | 5 + .../top_level.txt | 1 + ...1-x64-15ec4b7b2d8017a72acf488cff1a1c38.dll | Bin 0 -> 2878976 bytes .../psycopg_binary.libs/libiconv-2.dll | Bin 0 -> 1851113 bytes ...ntl-9-6b2fa35014185f5e79c4c76df54d19ae.dll | Bin 0 -> 475769 bytes ...libpq-de0d6d7eef3cda3760db155fac0f1d34.dll | Bin 0 -> 308224 bytes ...1-x64-56850767f4919548e5b00c9d311d045e.dll | Bin 0 -> 686592 bytes .../psycopg_binary.libs/libwinpthread-1.dll | Bin 0 -> 52736 bytes .../site-packages/psycopg_binary/__init__.py | 27 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1150 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 502 bytes .../_psycopg.cp312-win_amd64.pyd | Bin 0 -> 669184 bytes .../site-packages/psycopg_binary/_psycopg.pyi | 83 + .../psycopg_binary/pq.cp312-win_amd64.pyd | Bin 0 -> 284672 bytes .../Lib/site-packages/psycopg_binary/py.typed | 0 .../site-packages/psycopg_binary/version.py | 12 + .../pydantic-2.12.5.dist-info/INSTALLER | 1 + .../pydantic-2.12.5.dist-info/METADATA | 1029 ++ .../pydantic-2.12.5.dist-info/RECORD | 217 + .../pydantic-2.12.5.dist-info/WHEEL | 4 + .../licenses/LICENSE | 21 + .../Lib/site-packages/pydantic/__init__.py | 456 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 14423 bytes .../__pycache__/_migration.cpython-312.pyc | Bin 0 -> 11030 bytes .../alias_generators.cpython-312.pyc | Bin 0 -> 3280 bytes .../__pycache__/aliases.cpython-312.pyc | Bin 0 -> 6560 bytes .../annotated_handlers.cpython-312.pyc | Bin 0 -> 5494 bytes .../class_validators.cpython-312.pyc | Bin 0 -> 368 bytes .../__pycache__/color.cpython-312.pyc | Bin 0 -> 30174 bytes .../__pycache__/config.cpython-312.pyc | Bin 0 -> 7500 bytes .../__pycache__/dataclasses.cpython-312.pyc | Bin 0 -> 17327 bytes .../datetime_parse.cpython-312.pyc | Bin 0 -> 368 bytes .../__pycache__/decorator.cpython-312.pyc | Bin 0 -> 358 bytes .../__pycache__/env_settings.cpython-312.pyc | Bin 0 -> 364 bytes .../error_wrappers.cpython-312.pyc | Bin 0 -> 368 bytes .../__pycache__/errors.cpython-312.pyc | Bin 0 -> 7629 bytes .../__pycache__/fields.cpython-312.pyc | Bin 0 -> 72925 bytes .../functional_serializers.cpython-312.pyc | Bin 0 -> 17931 bytes .../functional_validators.cpython-312.pyc | Bin 0 -> 34742 bytes .../__pycache__/generics.cpython-312.pyc | Bin 0 -> 356 bytes .../pydantic/__pycache__/json.cpython-312.pyc | Bin 0 -> 348 bytes .../__pycache__/json_schema.cpython-312.pyc | Bin 0 -> 120011 bytes .../pydantic/__pycache__/main.cpython-312.pyc | Bin 0 -> 77302 bytes .../pydantic/__pycache__/mypy.cpython-312.pyc | Bin 0 -> 61637 bytes .../__pycache__/networks.cpython-312.pyc | Bin 0 -> 50217 bytes .../__pycache__/parse.cpython-312.pyc | Bin 0 -> 350 bytes .../__pycache__/root_model.cpython-312.pyc | Bin 0 -> 7811 bytes .../__pycache__/schema.cpython-312.pyc | Bin 0 -> 352 bytes .../__pycache__/tools.cpython-312.pyc | Bin 0 -> 350 bytes .../__pycache__/type_adapter.cpython-312.pyc | Bin 0 -> 35547 bytes .../__pycache__/types.cpython-312.pyc | Bin 0 -> 96768 bytes .../__pycache__/typing.cpython-312.pyc | Bin 0 -> 348 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 350 bytes .../validate_call_decorator.cpython-312.pyc | Bin 0 -> 5446 bytes .../__pycache__/validators.cpython-312.pyc | Bin 0 -> 360 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 4796 bytes .../__pycache__/warnings.cpython-312.pyc | Bin 0 -> 7212 bytes .../pydantic/_internal/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 193 bytes .../__pycache__/_config.cpython-312.pyc | Bin 0 -> 15672 bytes .../_core_metadata.cpython-312.pyc | Bin 0 -> 4613 bytes .../__pycache__/_core_utils.cpython-312.pyc | Bin 0 -> 7710 bytes .../__pycache__/_dataclasses.cpython-312.pyc | Bin 0 -> 13401 bytes .../__pycache__/_decorators.cpython-312.pyc | Bin 0 -> 36756 bytes .../_decorators_v1.cpython-312.pyc | Bin 0 -> 8613 bytes .../_discriminated_union.cpython-312.pyc | Bin 0 -> 20844 bytes .../_docs_extraction.cpython-312.pyc | Bin 0 -> 5306 bytes .../__pycache__/_fields.cpython-312.pyc | Bin 0 -> 24288 bytes .../__pycache__/_forward_ref.cpython-312.pyc | Bin 0 -> 1302 bytes .../_generate_schema.cpython-312.pyc | Bin 0 -> 130329 bytes .../__pycache__/_generics.cpython-312.pyc | Bin 0 -> 24329 bytes .../__pycache__/_git.cpython-312.pyc | Bin 0 -> 1508 bytes .../__pycache__/_import_utils.cpython-312.pyc | Bin 0 -> 821 bytes .../_internal_dataclass.cpython-312.pyc | Bin 0 -> 342 bytes .../_known_annotated_metadata.cpython-312.pyc | Bin 0 -> 14224 bytes .../__pycache__/_mock_val_ser.cpython-312.pyc | Bin 0 -> 11091 bytes .../_model_construction.cpython-312.pyc | Bin 0 -> 35103 bytes .../_namespace_utils.cpython-312.pyc | Bin 0 -> 12311 bytes .../__pycache__/_repr.cpython-312.pyc | Bin 0 -> 7851 bytes .../_schema_gather.cpython-312.pyc | Bin 0 -> 7638 bytes .../_schema_generation_shared.cpython-312.pyc | Bin 0 -> 6219 bytes .../__pycache__/_serializers.cpython-312.pyc | Bin 0 -> 2109 bytes .../__pycache__/_signature.cpython-312.pyc | Bin 0 -> 6759 bytes .../__pycache__/_typing_extra.cpython-312.pyc | Bin 0 -> 28178 bytes .../__pycache__/_utils.cpython-312.pyc | Bin 0 -> 19766 bytes .../_validate_call.cpython-312.pyc | Bin 0 -> 6980 bytes .../__pycache__/_validators.cpython-312.pyc | Bin 0 -> 22959 bytes .../pydantic/_internal/_config.py | 383 + .../pydantic/_internal/_core_metadata.py | 97 + .../pydantic/_internal/_core_utils.py | 174 + .../pydantic/_internal/_dataclasses.py | 315 + .../pydantic/_internal/_decorators.py | 858 ++ .../pydantic/_internal/_decorators_v1.py | 174 + .../_internal/_discriminated_union.py | 479 + .../pydantic/_internal/_docs_extraction.py | 113 + .../pydantic/_internal/_fields.py | 635 ++ .../pydantic/_internal/_forward_ref.py | 23 + .../pydantic/_internal/_generate_schema.py | 2867 ++++++ .../pydantic/_internal/_generics.py | 543 + .../site-packages/pydantic/_internal/_git.py | 27 + .../pydantic/_internal/_import_utils.py | 20 + .../pydantic/_internal/_internal_dataclass.py | 7 + .../_internal/_known_annotated_metadata.py | 401 + .../pydantic/_internal/_mock_val_ser.py | 228 + .../pydantic/_internal/_model_construction.py | 848 ++ .../pydantic/_internal/_namespace_utils.py | 293 + .../site-packages/pydantic/_internal/_repr.py | 124 + .../pydantic/_internal/_schema_gather.py | 209 + .../_internal/_schema_generation_shared.py | 125 + .../pydantic/_internal/_serializers.py | 53 + .../pydantic/_internal/_signature.py | 188 + .../pydantic/_internal/_typing_extra.py | 760 ++ .../pydantic/_internal/_utils.py | 446 + .../pydantic/_internal/_validate_call.py | 140 + .../pydantic/_internal/_validators.py | 533 + .../Lib/site-packages/pydantic/_migration.py | 316 + .../pydantic/alias_generators.py | 62 + .../Lib/site-packages/pydantic/aliases.py | 135 + .../pydantic/annotated_handlers.py | 122 + .../pydantic/class_validators.py | 5 + .../.venv/Lib/site-packages/pydantic/color.py | 604 ++ .../Lib/site-packages/pydantic/config.py | 1288 +++ .../Lib/site-packages/pydantic/dataclasses.py | 413 + .../site-packages/pydantic/datetime_parse.py | 5 + .../Lib/site-packages/pydantic/decorator.py | 5 + .../pydantic/deprecated/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 194 bytes .../class_validators.cpython-312.pyc | Bin 0 -> 11752 bytes .../__pycache__/config.cpython-312.pyc | Bin 0 -> 4071 bytes .../copy_internals.cpython-312.pyc | Bin 0 -> 8658 bytes .../__pycache__/decorator.cpython-312.pyc | Bin 0 -> 14022 bytes .../__pycache__/json.cpython-312.pyc | Bin 0 -> 6170 bytes .../__pycache__/parse.cpython-312.pyc | Bin 0 -> 3400 bytes .../__pycache__/tools.cpython-312.pyc | Bin 0 -> 3536 bytes .../pydantic/deprecated/class_validators.py | 256 + .../pydantic/deprecated/config.py | 72 + .../pydantic/deprecated/copy_internals.py | 224 + .../pydantic/deprecated/decorator.py | 284 + .../site-packages/pydantic/deprecated/json.py | 141 + .../pydantic/deprecated/parse.py | 80 + .../pydantic/deprecated/tools.py | 103 + .../site-packages/pydantic/env_settings.py | 5 + .../site-packages/pydantic/error_wrappers.py | 5 + .../Lib/site-packages/pydantic/errors.py | 189 + .../pydantic/experimental/__init__.py | 1 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 308 bytes .../arguments_schema.cpython-312.pyc | Bin 0 -> 2400 bytes .../missing_sentinel.cpython-312.pyc | Bin 0 -> 349 bytes .../__pycache__/pipeline.cpython-312.pyc | Bin 0 -> 34457 bytes .../pydantic/experimental/arguments_schema.py | 44 + .../pydantic/experimental/missing_sentinel.py | 5 + .../pydantic/experimental/pipeline.py | 654 ++ .../Lib/site-packages/pydantic/fields.py | 1834 ++++ .../pydantic/functional_serializers.py | 451 + .../pydantic/functional_validators.py | 893 ++ .../Lib/site-packages/pydantic/generics.py | 5 + .../.venv/Lib/site-packages/pydantic/json.py | 5 + .../Lib/site-packages/pydantic/json_schema.py | 2854 ++++++ .../.venv/Lib/site-packages/pydantic/main.py | 1819 ++++ .../.venv/Lib/site-packages/pydantic/mypy.py | 1374 +++ .../Lib/site-packages/pydantic/networks.py | 1331 +++ .../.venv/Lib/site-packages/pydantic/parse.py | 5 + .../site-packages/pydantic/plugin/__init__.py | 193 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 8936 bytes .../__pycache__/_loader.cpython-312.pyc | Bin 0 -> 2426 bytes .../_schema_validator.cpython-312.pyc | Bin 0 -> 6914 bytes .../site-packages/pydantic/plugin/_loader.py | 58 + .../pydantic/plugin/_schema_validator.py | 140 + .../.venv/Lib/site-packages/pydantic/py.typed | 0 .../Lib/site-packages/pydantic/root_model.py | 155 + .../Lib/site-packages/pydantic/schema.py | 5 + .../.venv/Lib/site-packages/pydantic/tools.py | 5 + .../site-packages/pydantic/type_adapter.py | 795 ++ .../.venv/Lib/site-packages/pydantic/types.py | 3295 ++++++ .../Lib/site-packages/pydantic/typing.py | 5 + .../.venv/Lib/site-packages/pydantic/utils.py | 5 + .../Lib/site-packages/pydantic/v1/__init__.py | 142 + .../v1/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 2515 bytes .../_hypothesis_plugin.cpython-312.pyc | Bin 0 -> 20502 bytes .../annotated_types.cpython-312.pyc | Bin 0 -> 3881 bytes .../class_validators.cpython-312.pyc | Bin 0 -> 19641 bytes .../v1/__pycache__/color.cpython-312.pyc | Bin 0 -> 25847 bytes .../v1/__pycache__/config.cpython-312.pyc | Bin 0 -> 8396 bytes .../__pycache__/dataclasses.cpython-312.pyc | Bin 0 -> 22741 bytes .../datetime_parse.cpython-312.pyc | Bin 0 -> 10349 bytes .../v1/__pycache__/decorator.cpython-312.pyc | Bin 0 -> 13914 bytes .../__pycache__/env_settings.cpython-312.pyc | Bin 0 -> 17716 bytes .../error_wrappers.cpython-312.pyc | Bin 0 -> 8924 bytes .../v1/__pycache__/errors.cpython-312.pyc | Bin 0 -> 29599 bytes .../v1/__pycache__/fields.cpython-312.pyc | Bin 0 -> 57439 bytes .../v1/__pycache__/generics.cpython-312.pyc | Bin 0 -> 16989 bytes .../v1/__pycache__/json.cpython-312.pyc | Bin 0 -> 5207 bytes .../v1/__pycache__/main.cpython-312.pyc | Bin 0 -> 48213 bytes .../v1/__pycache__/mypy.cpython-312.pyc | Bin 0 -> 46355 bytes .../v1/__pycache__/networks.cpython-312.pyc | Bin 0 -> 29546 bytes .../v1/__pycache__/parse.cpython-312.pyc | Bin 0 -> 2744 bytes .../v1/__pycache__/schema.cpython-312.pyc | Bin 0 -> 48472 bytes .../v1/__pycache__/tools.cpython-312.pyc | Bin 0 -> 3877 bytes .../v1/__pycache__/types.cpython-312.pyc | Bin 0 -> 48484 bytes .../v1/__pycache__/typing.cpython-312.pyc | Bin 0 -> 22627 bytes .../v1/__pycache__/utils.cpython-312.pyc | Bin 0 -> 35234 bytes .../v1/__pycache__/validators.cpython-312.pyc | Bin 0 -> 30892 bytes .../v1/__pycache__/version.cpython-312.pyc | Bin 0 -> 1955 bytes .../pydantic/v1/_hypothesis_plugin.py | 391 + .../pydantic/v1/annotated_types.py | 72 + .../pydantic/v1/class_validators.py | 361 + .../Lib/site-packages/pydantic/v1/color.py | 494 + .../Lib/site-packages/pydantic/v1/config.py | 191 + .../site-packages/pydantic/v1/dataclasses.py | 500 + .../pydantic/v1/datetime_parse.py | 248 + .../site-packages/pydantic/v1/decorator.py | 264 + .../site-packages/pydantic/v1/env_settings.py | 350 + .../pydantic/v1/error_wrappers.py | 161 + .../Lib/site-packages/pydantic/v1/errors.py | 646 ++ .../Lib/site-packages/pydantic/v1/fields.py | 1253 +++ .../Lib/site-packages/pydantic/v1/generics.py | 400 + .../Lib/site-packages/pydantic/v1/json.py | 112 + .../Lib/site-packages/pydantic/v1/main.py | 1113 +++ .../Lib/site-packages/pydantic/v1/mypy.py | 949 ++ .../Lib/site-packages/pydantic/v1/networks.py | 747 ++ .../Lib/site-packages/pydantic/v1/parse.py | 66 + .../Lib/site-packages/pydantic/v1/py.typed | 0 .../Lib/site-packages/pydantic/v1/schema.py | 1163 +++ .../Lib/site-packages/pydantic/v1/tools.py | 92 + .../Lib/site-packages/pydantic/v1/types.py | 1205 +++ .../Lib/site-packages/pydantic/v1/typing.py | 614 ++ .../Lib/site-packages/pydantic/v1/utils.py | 806 ++ .../site-packages/pydantic/v1/validators.py | 768 ++ .../Lib/site-packages/pydantic/v1/version.py | 38 + .../pydantic/validate_call_decorator.py | 116 + .../Lib/site-packages/pydantic/validators.py | 5 + .../Lib/site-packages/pydantic/version.py | 113 + .../Lib/site-packages/pydantic/warnings.py | 122 + .../pydantic_core-2.41.5.dist-info/INSTALLER | 1 + .../pydantic_core-2.41.5.dist-info/METADATA | 180 + .../pydantic_core-2.41.5.dist-info/RECORD | 12 + .../pydantic_core-2.41.5.dist-info/WHEEL | 4 + .../licenses/LICENSE | 21 + .../site-packages/pydantic_core/__init__.py | 171 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 3149 bytes .../__pycache__/core_schema.cpython-312.pyc | Bin 0 -> 155155 bytes .../_pydantic_core.cp312-win_amd64.pyd | Bin 0 -> 5436928 bytes .../pydantic_core/_pydantic_core.pyi | 1046 ++ .../pydantic_core/core_schema.py | 4435 +++++++++ .../Lib/site-packages/pydantic_core/py.typed | 0 .../python_dotenv-1.2.1.dist-info/INSTALLER | 1 + .../python_dotenv-1.2.1.dist-info/METADATA | 749 ++ .../python_dotenv-1.2.1.dist-info/RECORD | 25 + .../python_dotenv-1.2.1.dist-info/WHEEL | 5 + .../entry_points.txt | 2 + .../licenses/LICENSE | 27 + .../top_level.txt | 1 + .../pyyaml-6.0.3.dist-info/INSTALLER | 1 + .../pyyaml-6.0.3.dist-info/METADATA | 59 + .../pyyaml-6.0.3.dist-info/RECORD | 43 + .../pyyaml-6.0.3.dist-info/WHEEL | 5 + .../pyyaml-6.0.3.dist-info/licenses/LICENSE | 20 + .../pyyaml-6.0.3.dist-info/top_level.txt | 2 + .../starlette-0.41.3.dist-info/INSTALLER | 1 + .../starlette-0.41.3.dist-info/METADATA | 173 + .../starlette-0.41.3.dist-info/RECORD | 76 + .../starlette-0.41.3.dist-info/WHEEL | 4 + .../licenses/LICENSE.md | 27 + .../Lib/site-packages/starlette/__init__.py | 1 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 211 bytes .../__pycache__/_compat.cpython-312.pyc | Bin 0 -> 914 bytes .../_exception_handler.cpython-312.pyc | Bin 0 -> 3131 bytes .../__pycache__/_utils.cpython-312.pyc | Bin 0 -> 5349 bytes .../__pycache__/applications.cpython-312.pyc | Bin 0 -> 12805 bytes .../authentication.cpython-312.pyc | Bin 0 -> 7841 bytes .../__pycache__/background.cpython-312.pyc | Bin 0 -> 2604 bytes .../__pycache__/concurrency.cpython-312.pyc | Bin 0 -> 3241 bytes .../__pycache__/config.cpython-312.pyc | Bin 0 -> 7530 bytes .../__pycache__/convertors.cpython-312.pyc | Bin 0 -> 4762 bytes .../datastructures.cpython-312.pyc | Bin 0 -> 39322 bytes .../__pycache__/endpoints.cpython-312.pyc | Bin 0 -> 7841 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 3407 bytes .../__pycache__/formparsers.cpython-312.pyc | Bin 0 -> 14162 bytes .../__pycache__/requests.cpython-312.pyc | Bin 0 -> 16113 bytes .../__pycache__/responses.cpython-312.pyc | Bin 0 -> 28761 bytes .../__pycache__/routing.cpython-312.pyc | Bin 0 -> 43958 bytes .../__pycache__/schemas.cpython-312.pyc | Bin 0 -> 7040 bytes .../__pycache__/staticfiles.cpython-312.pyc | Bin 0 -> 11494 bytes .../__pycache__/status.cpython-312.pyc | Bin 0 -> 5097 bytes .../__pycache__/templating.cpython-312.pyc | Bin 0 -> 10032 bytes .../__pycache__/testclient.cpython-312.pyc | Bin 0 -> 36657 bytes .../__pycache__/types.cpython-312.pyc | Bin 0 -> 1785 bytes .../__pycache__/websockets.cpython-312.pyc | Bin 0 -> 11817 bytes .../Lib/site-packages/starlette/_compat.py | 26 + .../starlette/_exception_handler.py | 65 + .../Lib/site-packages/starlette/_utils.py | 100 + .../site-packages/starlette/applications.py | 250 + .../site-packages/starlette/authentication.py | 147 + .../Lib/site-packages/starlette/background.py | 41 + .../site-packages/starlette/concurrency.py | 64 + .../Lib/site-packages/starlette/config.py | 138 + .../Lib/site-packages/starlette/convertors.py | 89 + .../site-packages/starlette/datastructures.py | 679 ++ .../Lib/site-packages/starlette/endpoints.py | 122 + .../Lib/site-packages/starlette/exceptions.py | 62 + .../site-packages/starlette/formparsers.py | 271 + .../starlette/middleware/__init__.py | 41 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 2520 bytes .../authentication.cpython-312.pyc | Bin 0 -> 2872 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 11758 bytes .../__pycache__/cors.cpython-312.pyc | Bin 0 -> 7433 bytes .../__pycache__/errors.cpython-312.pyc | Bin 0 -> 9963 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 4085 bytes .../__pycache__/gzip.cpython-312.pyc | Bin 0 -> 6810 bytes .../__pycache__/httpsredirect.cpython-312.pyc | Bin 0 -> 1770 bytes .../__pycache__/sessions.cpython-312.pyc | Bin 0 -> 4650 bytes .../__pycache__/trustedhost.cpython-312.pyc | Bin 0 -> 3113 bytes .../__pycache__/wsgi.cpython-312.pyc | Bin 0 -> 8500 bytes .../starlette/middleware/authentication.py | 52 + .../starlette/middleware/base.py | 228 + .../starlette/middleware/cors.py | 172 + .../starlette/middleware/errors.py | 260 + .../starlette/middleware/exceptions.py | 72 + .../starlette/middleware/gzip.py | 108 + .../starlette/middleware/httpsredirect.py | 19 + .../starlette/middleware/sessions.py | 85 + .../starlette/middleware/trustedhost.py | 60 + .../starlette/middleware/wsgi.py | 152 + .../Lib/site-packages/starlette/py.typed | 0 .../Lib/site-packages/starlette/requests.py | 309 + .../Lib/site-packages/starlette/responses.py | 531 + .../Lib/site-packages/starlette/routing.py | 875 ++ .../Lib/site-packages/starlette/schemas.py | 147 + .../site-packages/starlette/staticfiles.py | 220 + .../Lib/site-packages/starlette/status.py | 201 + .../Lib/site-packages/starlette/templating.py | 216 + .../Lib/site-packages/starlette/testclient.py | 791 ++ .../Lib/site-packages/starlette/types.py | 24 + .../Lib/site-packages/starlette/websockets.py | 195 + .../INSTALLER | 1 + .../METADATA | 72 + .../typing_extensions-4.15.0.dist-info/RECORD | 7 + .../typing_extensions-4.15.0.dist-info/WHEEL | 4 + .../licenses/LICENSE | 279 + .../Lib/site-packages/typing_extensions.py | 4317 ++++++++ .../INSTALLER | 1 + .../METADATA | 49 + .../typing_inspection-0.4.2.dist-info/RECORD | 13 + .../typing_inspection-0.4.2.dist-info/WHEEL | 4 + .../licenses/LICENSE | 21 + .../typing_inspection/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 192 bytes .../__pycache__/introspection.cpython-312.pyc | Bin 0 -> 17789 bytes .../typing_objects.cpython-312.pyc | Bin 0 -> 17368 bytes .../typing_inspection/introspection.py | 587 ++ .../site-packages/typing_inspection/py.typed | 0 .../typing_inspection/typing_objects.py | 607 ++ .../typing_inspection/typing_objects.pyi | 417 + .../tzdata-2025.2.dist-info/INSTALLER | 1 + .../tzdata-2025.2.dist-info/METADATA | 34 + .../tzdata-2025.2.dist-info/RECORD | 656 ++ .../tzdata-2025.2.dist-info/WHEEL | 6 + .../tzdata-2025.2.dist-info/licenses/LICENSE | 15 + .../licenses/licenses/LICENSE_APACHE | 201 + .../tzdata-2025.2.dist-info/top_level.txt | 1 + .../Lib/site-packages/tzdata/__init__.py | 6 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 242 bytes .../tzdata/zoneinfo/Africa/Abidjan | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Africa/Accra | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Africa/Addis_Ababa | Bin 0 -> 191 bytes .../tzdata/zoneinfo/Africa/Algiers | Bin 0 -> 470 bytes .../tzdata/zoneinfo/Africa/Asmara | Bin 0 -> 191 bytes .../tzdata/zoneinfo/Africa/Asmera | Bin 0 -> 191 bytes .../tzdata/zoneinfo/Africa/Bamako | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Africa/Bangui | Bin 0 -> 180 bytes .../tzdata/zoneinfo/Africa/Banjul | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Africa/Bissau | Bin 0 -> 149 bytes .../tzdata/zoneinfo/Africa/Blantyre | Bin 0 -> 131 bytes .../tzdata/zoneinfo/Africa/Brazzaville | Bin 0 -> 180 bytes .../tzdata/zoneinfo/Africa/Bujumbura | Bin 0 -> 131 bytes .../tzdata/zoneinfo/Africa/Cairo | Bin 0 -> 1309 bytes .../tzdata/zoneinfo/Africa/Casablanca | Bin 0 -> 1919 bytes .../tzdata/zoneinfo/Africa/Ceuta | Bin 0 -> 562 bytes .../tzdata/zoneinfo/Africa/Conakry | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Africa/Dakar | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Africa/Dar_es_Salaam | Bin 0 -> 191 bytes .../tzdata/zoneinfo/Africa/Djibouti | Bin 0 -> 191 bytes .../tzdata/zoneinfo/Africa/Douala | Bin 0 -> 180 bytes .../tzdata/zoneinfo/Africa/El_Aaiun | Bin 0 -> 1830 bytes .../tzdata/zoneinfo/Africa/Freetown | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Africa/Gaborone | Bin 0 -> 131 bytes .../tzdata/zoneinfo/Africa/Harare | Bin 0 -> 131 bytes .../tzdata/zoneinfo/Africa/Johannesburg | Bin 0 -> 190 bytes .../site-packages/tzdata/zoneinfo/Africa/Juba | Bin 0 -> 458 bytes .../tzdata/zoneinfo/Africa/Kampala | Bin 0 -> 191 bytes .../tzdata/zoneinfo/Africa/Khartoum | Bin 0 -> 458 bytes .../tzdata/zoneinfo/Africa/Kigali | Bin 0 -> 131 bytes .../tzdata/zoneinfo/Africa/Kinshasa | Bin 0 -> 180 bytes .../tzdata/zoneinfo/Africa/Lagos | Bin 0 -> 180 bytes .../tzdata/zoneinfo/Africa/Libreville | Bin 0 -> 180 bytes .../site-packages/tzdata/zoneinfo/Africa/Lome | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Africa/Luanda | Bin 0 -> 180 bytes .../tzdata/zoneinfo/Africa/Lubumbashi | Bin 0 -> 131 bytes .../tzdata/zoneinfo/Africa/Lusaka | Bin 0 -> 131 bytes .../tzdata/zoneinfo/Africa/Malabo | Bin 0 -> 180 bytes .../tzdata/zoneinfo/Africa/Maputo | Bin 0 -> 131 bytes .../tzdata/zoneinfo/Africa/Maseru | Bin 0 -> 190 bytes .../tzdata/zoneinfo/Africa/Mbabane | Bin 0 -> 190 bytes .../tzdata/zoneinfo/Africa/Mogadishu | Bin 0 -> 191 bytes .../tzdata/zoneinfo/Africa/Monrovia | Bin 0 -> 164 bytes .../tzdata/zoneinfo/Africa/Nairobi | Bin 0 -> 191 bytes .../tzdata/zoneinfo/Africa/Ndjamena | Bin 0 -> 160 bytes .../tzdata/zoneinfo/Africa/Niamey | Bin 0 -> 180 bytes .../tzdata/zoneinfo/Africa/Nouakchott | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Africa/Ouagadougou | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Africa/Porto-Novo | Bin 0 -> 180 bytes .../tzdata/zoneinfo/Africa/Sao_Tome | Bin 0 -> 173 bytes .../tzdata/zoneinfo/Africa/Timbuktu | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Africa/Tripoli | Bin 0 -> 431 bytes .../tzdata/zoneinfo/Africa/Tunis | Bin 0 -> 449 bytes .../tzdata/zoneinfo/Africa/Windhoek | Bin 0 -> 638 bytes .../tzdata/zoneinfo/Africa/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 197 bytes .../tzdata/zoneinfo/America/Adak | Bin 0 -> 969 bytes .../tzdata/zoneinfo/America/Anchorage | Bin 0 -> 977 bytes .../tzdata/zoneinfo/America/Anguilla | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Antigua | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Araguaina | Bin 0 -> 592 bytes .../zoneinfo/America/Argentina/Buenos_Aires | Bin 0 -> 708 bytes .../zoneinfo/America/Argentina/Catamarca | Bin 0 -> 708 bytes .../zoneinfo/America/Argentina/ComodRivadavia | Bin 0 -> 708 bytes .../tzdata/zoneinfo/America/Argentina/Cordoba | Bin 0 -> 708 bytes .../tzdata/zoneinfo/America/Argentina/Jujuy | Bin 0 -> 690 bytes .../zoneinfo/America/Argentina/La_Rioja | Bin 0 -> 717 bytes .../tzdata/zoneinfo/America/Argentina/Mendoza | Bin 0 -> 708 bytes .../zoneinfo/America/Argentina/Rio_Gallegos | Bin 0 -> 708 bytes .../tzdata/zoneinfo/America/Argentina/Salta | Bin 0 -> 690 bytes .../zoneinfo/America/Argentina/San_Juan | Bin 0 -> 717 bytes .../zoneinfo/America/Argentina/San_Luis | Bin 0 -> 717 bytes .../tzdata/zoneinfo/America/Argentina/Tucuman | Bin 0 -> 726 bytes .../tzdata/zoneinfo/America/Argentina/Ushuaia | Bin 0 -> 708 bytes .../zoneinfo/America/Argentina/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 208 bytes .../tzdata/zoneinfo/America/Aruba | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Asuncion | Bin 0 -> 1085 bytes .../tzdata/zoneinfo/America/Atikokan | Bin 0 -> 149 bytes .../tzdata/zoneinfo/America/Atka | Bin 0 -> 969 bytes .../tzdata/zoneinfo/America/Bahia | Bin 0 -> 682 bytes .../tzdata/zoneinfo/America/Bahia_Banderas | Bin 0 -> 700 bytes .../tzdata/zoneinfo/America/Barbados | Bin 0 -> 278 bytes .../tzdata/zoneinfo/America/Belem | Bin 0 -> 394 bytes .../tzdata/zoneinfo/America/Belize | Bin 0 -> 1045 bytes .../tzdata/zoneinfo/America/Blanc-Sablon | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Boa_Vista | Bin 0 -> 430 bytes .../tzdata/zoneinfo/America/Bogota | Bin 0 -> 179 bytes .../tzdata/zoneinfo/America/Boise | Bin 0 -> 999 bytes .../tzdata/zoneinfo/America/Buenos_Aires | Bin 0 -> 708 bytes .../tzdata/zoneinfo/America/Cambridge_Bay | Bin 0 -> 883 bytes .../tzdata/zoneinfo/America/Campo_Grande | Bin 0 -> 952 bytes .../tzdata/zoneinfo/America/Cancun | Bin 0 -> 538 bytes .../tzdata/zoneinfo/America/Caracas | Bin 0 -> 190 bytes .../tzdata/zoneinfo/America/Catamarca | Bin 0 -> 708 bytes .../tzdata/zoneinfo/America/Cayenne | Bin 0 -> 151 bytes .../tzdata/zoneinfo/America/Cayman | Bin 0 -> 149 bytes .../tzdata/zoneinfo/America/Chicago | Bin 0 -> 1754 bytes .../tzdata/zoneinfo/America/Chihuahua | Bin 0 -> 691 bytes .../tzdata/zoneinfo/America/Ciudad_Juarez | Bin 0 -> 718 bytes .../tzdata/zoneinfo/America/Coral_Harbour | Bin 0 -> 149 bytes .../tzdata/zoneinfo/America/Cordoba | Bin 0 -> 708 bytes .../tzdata/zoneinfo/America/Costa_Rica | Bin 0 -> 232 bytes .../tzdata/zoneinfo/America/Coyhaique | Bin 0 -> 1362 bytes .../tzdata/zoneinfo/America/Creston | Bin 0 -> 240 bytes .../tzdata/zoneinfo/America/Cuiaba | Bin 0 -> 934 bytes .../tzdata/zoneinfo/America/Curacao | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Danmarkshavn | Bin 0 -> 447 bytes .../tzdata/zoneinfo/America/Dawson | Bin 0 -> 1029 bytes .../tzdata/zoneinfo/America/Dawson_Creek | Bin 0 -> 683 bytes .../tzdata/zoneinfo/America/Denver | Bin 0 -> 1042 bytes .../tzdata/zoneinfo/America/Detroit | Bin 0 -> 899 bytes .../tzdata/zoneinfo/America/Dominica | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Edmonton | Bin 0 -> 970 bytes .../tzdata/zoneinfo/America/Eirunepe | Bin 0 -> 436 bytes .../tzdata/zoneinfo/America/El_Salvador | Bin 0 -> 176 bytes .../tzdata/zoneinfo/America/Ensenada | Bin 0 -> 1079 bytes .../tzdata/zoneinfo/America/Fort_Nelson | Bin 0 -> 1448 bytes .../tzdata/zoneinfo/America/Fort_Wayne | Bin 0 -> 531 bytes .../tzdata/zoneinfo/America/Fortaleza | Bin 0 -> 484 bytes .../tzdata/zoneinfo/America/Glace_Bay | Bin 0 -> 880 bytes .../tzdata/zoneinfo/America/Godthab | Bin 0 -> 965 bytes .../tzdata/zoneinfo/America/Goose_Bay | Bin 0 -> 1580 bytes .../tzdata/zoneinfo/America/Grand_Turk | Bin 0 -> 853 bytes .../tzdata/zoneinfo/America/Grenada | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Guadeloupe | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Guatemala | Bin 0 -> 212 bytes .../tzdata/zoneinfo/America/Guayaquil | Bin 0 -> 179 bytes .../tzdata/zoneinfo/America/Guyana | Bin 0 -> 181 bytes .../tzdata/zoneinfo/America/Halifax | Bin 0 -> 1672 bytes .../tzdata/zoneinfo/America/Havana | Bin 0 -> 1117 bytes .../tzdata/zoneinfo/America/Hermosillo | Bin 0 -> 258 bytes .../zoneinfo/America/Indiana/Indianapolis | Bin 0 -> 531 bytes .../tzdata/zoneinfo/America/Indiana/Knox | Bin 0 -> 1016 bytes .../tzdata/zoneinfo/America/Indiana/Marengo | Bin 0 -> 567 bytes .../zoneinfo/America/Indiana/Petersburg | Bin 0 -> 683 bytes .../tzdata/zoneinfo/America/Indiana/Tell_City | Bin 0 -> 522 bytes .../tzdata/zoneinfo/America/Indiana/Vevay | Bin 0 -> 369 bytes .../tzdata/zoneinfo/America/Indiana/Vincennes | Bin 0 -> 558 bytes .../tzdata/zoneinfo/America/Indiana/Winamac | Bin 0 -> 603 bytes .../zoneinfo/America/Indiana/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 206 bytes .../tzdata/zoneinfo/America/Indianapolis | Bin 0 -> 531 bytes .../tzdata/zoneinfo/America/Inuvik | Bin 0 -> 817 bytes .../tzdata/zoneinfo/America/Iqaluit | Bin 0 -> 855 bytes .../tzdata/zoneinfo/America/Jamaica | Bin 0 -> 339 bytes .../tzdata/zoneinfo/America/Jujuy | Bin 0 -> 690 bytes .../tzdata/zoneinfo/America/Juneau | Bin 0 -> 966 bytes .../zoneinfo/America/Kentucky/Louisville | Bin 0 -> 1242 bytes .../zoneinfo/America/Kentucky/Monticello | Bin 0 -> 972 bytes .../zoneinfo/America/Kentucky/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 207 bytes .../tzdata/zoneinfo/America/Knox_IN | Bin 0 -> 1016 bytes .../tzdata/zoneinfo/America/Kralendijk | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/La_Paz | Bin 0 -> 170 bytes .../tzdata/zoneinfo/America/Lima | Bin 0 -> 283 bytes .../tzdata/zoneinfo/America/Los_Angeles | Bin 0 -> 1294 bytes .../tzdata/zoneinfo/America/Louisville | Bin 0 -> 1242 bytes .../tzdata/zoneinfo/America/Lower_Princes | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Maceio | Bin 0 -> 502 bytes .../tzdata/zoneinfo/America/Managua | Bin 0 -> 295 bytes .../tzdata/zoneinfo/America/Manaus | Bin 0 -> 412 bytes .../tzdata/zoneinfo/America/Marigot | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Martinique | Bin 0 -> 178 bytes .../tzdata/zoneinfo/America/Matamoros | Bin 0 -> 437 bytes .../tzdata/zoneinfo/America/Mazatlan | Bin 0 -> 690 bytes .../tzdata/zoneinfo/America/Mendoza | Bin 0 -> 708 bytes .../tzdata/zoneinfo/America/Menominee | Bin 0 -> 917 bytes .../tzdata/zoneinfo/America/Merida | Bin 0 -> 654 bytes .../tzdata/zoneinfo/America/Metlakatla | Bin 0 -> 586 bytes .../tzdata/zoneinfo/America/Mexico_City | Bin 0 -> 773 bytes .../tzdata/zoneinfo/America/Miquelon | Bin 0 -> 550 bytes .../tzdata/zoneinfo/America/Moncton | Bin 0 -> 1493 bytes .../tzdata/zoneinfo/America/Monterrey | Bin 0 -> 709 bytes .../tzdata/zoneinfo/America/Montevideo | Bin 0 -> 969 bytes .../tzdata/zoneinfo/America/Montreal | Bin 0 -> 1717 bytes .../tzdata/zoneinfo/America/Montserrat | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Nassau | Bin 0 -> 1717 bytes .../tzdata/zoneinfo/America/New_York | Bin 0 -> 1744 bytes .../tzdata/zoneinfo/America/Nipigon | Bin 0 -> 1717 bytes .../tzdata/zoneinfo/America/Nome | Bin 0 -> 975 bytes .../tzdata/zoneinfo/America/Noronha | Bin 0 -> 484 bytes .../zoneinfo/America/North_Dakota/Beulah | Bin 0 -> 1043 bytes .../zoneinfo/America/North_Dakota/Center | Bin 0 -> 990 bytes .../zoneinfo/America/North_Dakota/New_Salem | Bin 0 -> 990 bytes .../zoneinfo/America/North_Dakota/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 211 bytes .../tzdata/zoneinfo/America/Nuuk | Bin 0 -> 965 bytes .../tzdata/zoneinfo/America/Ojinaga | Bin 0 -> 718 bytes .../tzdata/zoneinfo/America/Panama | Bin 0 -> 149 bytes .../tzdata/zoneinfo/America/Pangnirtung | Bin 0 -> 855 bytes .../tzdata/zoneinfo/America/Paramaribo | Bin 0 -> 187 bytes .../tzdata/zoneinfo/America/Phoenix | Bin 0 -> 240 bytes .../tzdata/zoneinfo/America/Port-au-Prince | Bin 0 -> 565 bytes .../tzdata/zoneinfo/America/Port_of_Spain | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Porto_Acre | Bin 0 -> 418 bytes .../tzdata/zoneinfo/America/Porto_Velho | Bin 0 -> 394 bytes .../tzdata/zoneinfo/America/Puerto_Rico | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Punta_Arenas | Bin 0 -> 1218 bytes .../tzdata/zoneinfo/America/Rainy_River | Bin 0 -> 1294 bytes .../tzdata/zoneinfo/America/Rankin_Inlet | Bin 0 -> 807 bytes .../tzdata/zoneinfo/America/Recife | Bin 0 -> 484 bytes .../tzdata/zoneinfo/America/Regina | Bin 0 -> 638 bytes .../tzdata/zoneinfo/America/Resolute | Bin 0 -> 807 bytes .../tzdata/zoneinfo/America/Rio_Branco | Bin 0 -> 418 bytes .../tzdata/zoneinfo/America/Rosario | Bin 0 -> 708 bytes .../tzdata/zoneinfo/America/Santa_Isabel | Bin 0 -> 1079 bytes .../tzdata/zoneinfo/America/Santarem | Bin 0 -> 409 bytes .../tzdata/zoneinfo/America/Santiago | Bin 0 -> 1354 bytes .../tzdata/zoneinfo/America/Santo_Domingo | Bin 0 -> 317 bytes .../tzdata/zoneinfo/America/Sao_Paulo | Bin 0 -> 952 bytes .../tzdata/zoneinfo/America/Scoresbysund | Bin 0 -> 984 bytes .../tzdata/zoneinfo/America/Shiprock | Bin 0 -> 1042 bytes .../tzdata/zoneinfo/America/Sitka | Bin 0 -> 956 bytes .../tzdata/zoneinfo/America/St_Barthelemy | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/St_Johns | Bin 0 -> 1878 bytes .../tzdata/zoneinfo/America/St_Kitts | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/St_Lucia | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/St_Thomas | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/St_Vincent | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Swift_Current | Bin 0 -> 368 bytes .../tzdata/zoneinfo/America/Tegucigalpa | Bin 0 -> 194 bytes .../tzdata/zoneinfo/America/Thule | Bin 0 -> 455 bytes .../tzdata/zoneinfo/America/Thunder_Bay | Bin 0 -> 1717 bytes .../tzdata/zoneinfo/America/Tijuana | Bin 0 -> 1079 bytes .../tzdata/zoneinfo/America/Toronto | Bin 0 -> 1717 bytes .../tzdata/zoneinfo/America/Tortola | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Vancouver | Bin 0 -> 1330 bytes .../tzdata/zoneinfo/America/Virgin | Bin 0 -> 177 bytes .../tzdata/zoneinfo/America/Whitehorse | Bin 0 -> 1029 bytes .../tzdata/zoneinfo/America/Winnipeg | Bin 0 -> 1294 bytes .../tzdata/zoneinfo/America/Yakutat | Bin 0 -> 946 bytes .../tzdata/zoneinfo/America/Yellowknife | Bin 0 -> 970 bytes .../tzdata/zoneinfo/America/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 198 bytes .../tzdata/zoneinfo/Antarctica/Casey | Bin 0 -> 287 bytes .../tzdata/zoneinfo/Antarctica/Davis | Bin 0 -> 197 bytes .../tzdata/zoneinfo/Antarctica/DumontDUrville | Bin 0 -> 154 bytes .../tzdata/zoneinfo/Antarctica/Macquarie | Bin 0 -> 976 bytes .../tzdata/zoneinfo/Antarctica/Mawson | Bin 0 -> 152 bytes .../tzdata/zoneinfo/Antarctica/McMurdo | Bin 0 -> 1043 bytes .../tzdata/zoneinfo/Antarctica/Palmer | Bin 0 -> 887 bytes .../tzdata/zoneinfo/Antarctica/Rothera | Bin 0 -> 132 bytes .../tzdata/zoneinfo/Antarctica/South_Pole | Bin 0 -> 1043 bytes .../tzdata/zoneinfo/Antarctica/Syowa | Bin 0 -> 133 bytes .../tzdata/zoneinfo/Antarctica/Troll | Bin 0 -> 158 bytes .../tzdata/zoneinfo/Antarctica/Vostok | Bin 0 -> 170 bytes .../tzdata/zoneinfo/Antarctica/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 201 bytes .../tzdata/zoneinfo/Arctic/Longyearbyen | Bin 0 -> 705 bytes .../tzdata/zoneinfo/Arctic/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 197 bytes .../site-packages/tzdata/zoneinfo/Asia/Aden | Bin 0 -> 133 bytes .../site-packages/tzdata/zoneinfo/Asia/Almaty | Bin 0 -> 618 bytes .../site-packages/tzdata/zoneinfo/Asia/Amman | Bin 0 -> 928 bytes .../site-packages/tzdata/zoneinfo/Asia/Anadyr | Bin 0 -> 743 bytes .../site-packages/tzdata/zoneinfo/Asia/Aqtau | Bin 0 -> 606 bytes .../site-packages/tzdata/zoneinfo/Asia/Aqtobe | Bin 0 -> 615 bytes .../tzdata/zoneinfo/Asia/Ashgabat | Bin 0 -> 375 bytes .../tzdata/zoneinfo/Asia/Ashkhabad | Bin 0 -> 375 bytes .../site-packages/tzdata/zoneinfo/Asia/Atyrau | Bin 0 -> 616 bytes .../tzdata/zoneinfo/Asia/Baghdad | Bin 0 -> 630 bytes .../tzdata/zoneinfo/Asia/Bahrain | Bin 0 -> 152 bytes .../site-packages/tzdata/zoneinfo/Asia/Baku | Bin 0 -> 744 bytes .../tzdata/zoneinfo/Asia/Bangkok | Bin 0 -> 152 bytes .../tzdata/zoneinfo/Asia/Barnaul | Bin 0 -> 753 bytes .../site-packages/tzdata/zoneinfo/Asia/Beirut | Bin 0 -> 732 bytes .../tzdata/zoneinfo/Asia/Bishkek | Bin 0 -> 618 bytes .../site-packages/tzdata/zoneinfo/Asia/Brunei | Bin 0 -> 320 bytes .../tzdata/zoneinfo/Asia/Calcutta | Bin 0 -> 220 bytes .../site-packages/tzdata/zoneinfo/Asia/Chita | Bin 0 -> 750 bytes .../tzdata/zoneinfo/Asia/Choibalsan | Bin 0 -> 594 bytes .../tzdata/zoneinfo/Asia/Chongqing | Bin 0 -> 393 bytes .../tzdata/zoneinfo/Asia/Chungking | Bin 0 -> 393 bytes .../tzdata/zoneinfo/Asia/Colombo | Bin 0 -> 247 bytes .../site-packages/tzdata/zoneinfo/Asia/Dacca | Bin 0 -> 231 bytes .../tzdata/zoneinfo/Asia/Damascus | Bin 0 -> 1234 bytes .../site-packages/tzdata/zoneinfo/Asia/Dhaka | Bin 0 -> 231 bytes .../site-packages/tzdata/zoneinfo/Asia/Dili | Bin 0 -> 170 bytes .../site-packages/tzdata/zoneinfo/Asia/Dubai | Bin 0 -> 133 bytes .../tzdata/zoneinfo/Asia/Dushanbe | Bin 0 -> 366 bytes .../tzdata/zoneinfo/Asia/Famagusta | Bin 0 -> 940 bytes .../site-packages/tzdata/zoneinfo/Asia/Gaza | Bin 0 -> 2950 bytes .../site-packages/tzdata/zoneinfo/Asia/Harbin | Bin 0 -> 393 bytes .../site-packages/tzdata/zoneinfo/Asia/Hebron | Bin 0 -> 2968 bytes .../tzdata/zoneinfo/Asia/Ho_Chi_Minh | Bin 0 -> 236 bytes .../tzdata/zoneinfo/Asia/Hong_Kong | Bin 0 -> 775 bytes .../site-packages/tzdata/zoneinfo/Asia/Hovd | Bin 0 -> 594 bytes .../tzdata/zoneinfo/Asia/Irkutsk | Bin 0 -> 760 bytes .../tzdata/zoneinfo/Asia/Istanbul | Bin 0 -> 1200 bytes .../tzdata/zoneinfo/Asia/Jakarta | Bin 0 -> 248 bytes .../tzdata/zoneinfo/Asia/Jayapura | Bin 0 -> 171 bytes .../tzdata/zoneinfo/Asia/Jerusalem | Bin 0 -> 1074 bytes .../site-packages/tzdata/zoneinfo/Asia/Kabul | Bin 0 -> 159 bytes .../tzdata/zoneinfo/Asia/Kamchatka | Bin 0 -> 727 bytes .../tzdata/zoneinfo/Asia/Karachi | Bin 0 -> 266 bytes .../tzdata/zoneinfo/Asia/Kashgar | Bin 0 -> 133 bytes .../tzdata/zoneinfo/Asia/Kathmandu | Bin 0 -> 161 bytes .../tzdata/zoneinfo/Asia/Katmandu | Bin 0 -> 161 bytes .../tzdata/zoneinfo/Asia/Khandyga | Bin 0 -> 775 bytes .../tzdata/zoneinfo/Asia/Kolkata | Bin 0 -> 220 bytes .../tzdata/zoneinfo/Asia/Krasnoyarsk | Bin 0 -> 741 bytes .../tzdata/zoneinfo/Asia/Kuala_Lumpur | Bin 0 -> 256 bytes .../tzdata/zoneinfo/Asia/Kuching | Bin 0 -> 320 bytes .../site-packages/tzdata/zoneinfo/Asia/Kuwait | Bin 0 -> 133 bytes .../site-packages/tzdata/zoneinfo/Asia/Macao | Bin 0 -> 791 bytes .../site-packages/tzdata/zoneinfo/Asia/Macau | Bin 0 -> 791 bytes .../tzdata/zoneinfo/Asia/Magadan | Bin 0 -> 751 bytes .../tzdata/zoneinfo/Asia/Makassar | Bin 0 -> 190 bytes .../site-packages/tzdata/zoneinfo/Asia/Manila | Bin 0 -> 274 bytes .../site-packages/tzdata/zoneinfo/Asia/Muscat | Bin 0 -> 133 bytes .../tzdata/zoneinfo/Asia/Nicosia | Bin 0 -> 597 bytes .../tzdata/zoneinfo/Asia/Novokuznetsk | Bin 0 -> 726 bytes .../tzdata/zoneinfo/Asia/Novosibirsk | Bin 0 -> 753 bytes .../site-packages/tzdata/zoneinfo/Asia/Omsk | Bin 0 -> 741 bytes .../site-packages/tzdata/zoneinfo/Asia/Oral | Bin 0 -> 625 bytes .../tzdata/zoneinfo/Asia/Phnom_Penh | Bin 0 -> 152 bytes .../tzdata/zoneinfo/Asia/Pontianak | Bin 0 -> 247 bytes .../tzdata/zoneinfo/Asia/Pyongyang | Bin 0 -> 183 bytes .../site-packages/tzdata/zoneinfo/Asia/Qatar | Bin 0 -> 152 bytes .../tzdata/zoneinfo/Asia/Qostanay | Bin 0 -> 624 bytes .../tzdata/zoneinfo/Asia/Qyzylorda | Bin 0 -> 624 bytes .../tzdata/zoneinfo/Asia/Rangoon | Bin 0 -> 187 bytes .../site-packages/tzdata/zoneinfo/Asia/Riyadh | Bin 0 -> 133 bytes .../site-packages/tzdata/zoneinfo/Asia/Saigon | Bin 0 -> 236 bytes .../tzdata/zoneinfo/Asia/Sakhalin | Bin 0 -> 755 bytes .../tzdata/zoneinfo/Asia/Samarkand | Bin 0 -> 366 bytes .../site-packages/tzdata/zoneinfo/Asia/Seoul | Bin 0 -> 415 bytes .../tzdata/zoneinfo/Asia/Shanghai | Bin 0 -> 393 bytes .../tzdata/zoneinfo/Asia/Singapore | Bin 0 -> 256 bytes .../tzdata/zoneinfo/Asia/Srednekolymsk | Bin 0 -> 742 bytes .../site-packages/tzdata/zoneinfo/Asia/Taipei | Bin 0 -> 511 bytes .../tzdata/zoneinfo/Asia/Tashkent | Bin 0 -> 366 bytes .../tzdata/zoneinfo/Asia/Tbilisi | Bin 0 -> 629 bytes .../site-packages/tzdata/zoneinfo/Asia/Tehran | Bin 0 -> 812 bytes .../tzdata/zoneinfo/Asia/Tel_Aviv | Bin 0 -> 1074 bytes .../site-packages/tzdata/zoneinfo/Asia/Thimbu | Bin 0 -> 154 bytes .../tzdata/zoneinfo/Asia/Thimphu | Bin 0 -> 154 bytes .../site-packages/tzdata/zoneinfo/Asia/Tokyo | Bin 0 -> 213 bytes .../site-packages/tzdata/zoneinfo/Asia/Tomsk | Bin 0 -> 753 bytes .../tzdata/zoneinfo/Asia/Ujung_Pandang | Bin 0 -> 190 bytes .../tzdata/zoneinfo/Asia/Ulaanbaatar | Bin 0 -> 594 bytes .../tzdata/zoneinfo/Asia/Ulan_Bator | Bin 0 -> 594 bytes .../site-packages/tzdata/zoneinfo/Asia/Urumqi | Bin 0 -> 133 bytes .../tzdata/zoneinfo/Asia/Ust-Nera | Bin 0 -> 771 bytes .../tzdata/zoneinfo/Asia/Vientiane | Bin 0 -> 152 bytes .../tzdata/zoneinfo/Asia/Vladivostok | Bin 0 -> 742 bytes .../tzdata/zoneinfo/Asia/Yakutsk | Bin 0 -> 741 bytes .../site-packages/tzdata/zoneinfo/Asia/Yangon | Bin 0 -> 187 bytes .../tzdata/zoneinfo/Asia/Yekaterinburg | Bin 0 -> 760 bytes .../tzdata/zoneinfo/Asia/Yerevan | Bin 0 -> 708 bytes .../tzdata/zoneinfo/Asia/__init__.py | 0 .../Asia/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 195 bytes .../tzdata/zoneinfo/Atlantic/Azores | Bin 0 -> 1401 bytes .../tzdata/zoneinfo/Atlantic/Bermuda | Bin 0 -> 1024 bytes .../tzdata/zoneinfo/Atlantic/Canary | Bin 0 -> 478 bytes .../tzdata/zoneinfo/Atlantic/Cape_Verde | Bin 0 -> 175 bytes .../tzdata/zoneinfo/Atlantic/Faeroe | Bin 0 -> 441 bytes .../tzdata/zoneinfo/Atlantic/Faroe | Bin 0 -> 441 bytes .../tzdata/zoneinfo/Atlantic/Jan_Mayen | Bin 0 -> 705 bytes .../tzdata/zoneinfo/Atlantic/Madeira | Bin 0 -> 1372 bytes .../tzdata/zoneinfo/Atlantic/Reykjavik | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Atlantic/South_Georgia | Bin 0 -> 132 bytes .../tzdata/zoneinfo/Atlantic/St_Helena | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Atlantic/Stanley | Bin 0 -> 789 bytes .../tzdata/zoneinfo/Atlantic/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 199 bytes .../tzdata/zoneinfo/Australia/ACT | Bin 0 -> 904 bytes .../tzdata/zoneinfo/Australia/Adelaide | Bin 0 -> 921 bytes .../tzdata/zoneinfo/Australia/Brisbane | Bin 0 -> 289 bytes .../tzdata/zoneinfo/Australia/Broken_Hill | Bin 0 -> 941 bytes .../tzdata/zoneinfo/Australia/Canberra | Bin 0 -> 904 bytes .../tzdata/zoneinfo/Australia/Currie | Bin 0 -> 1003 bytes .../tzdata/zoneinfo/Australia/Darwin | Bin 0 -> 234 bytes .../tzdata/zoneinfo/Australia/Eucla | Bin 0 -> 314 bytes .../tzdata/zoneinfo/Australia/Hobart | Bin 0 -> 1003 bytes .../tzdata/zoneinfo/Australia/LHI | Bin 0 -> 692 bytes .../tzdata/zoneinfo/Australia/Lindeman | Bin 0 -> 325 bytes .../tzdata/zoneinfo/Australia/Lord_Howe | Bin 0 -> 692 bytes .../tzdata/zoneinfo/Australia/Melbourne | Bin 0 -> 904 bytes .../tzdata/zoneinfo/Australia/NSW | Bin 0 -> 904 bytes .../tzdata/zoneinfo/Australia/North | Bin 0 -> 234 bytes .../tzdata/zoneinfo/Australia/Perth | Bin 0 -> 306 bytes .../tzdata/zoneinfo/Australia/Queensland | Bin 0 -> 289 bytes .../tzdata/zoneinfo/Australia/South | Bin 0 -> 921 bytes .../tzdata/zoneinfo/Australia/Sydney | Bin 0 -> 904 bytes .../tzdata/zoneinfo/Australia/Tasmania | Bin 0 -> 1003 bytes .../tzdata/zoneinfo/Australia/Victoria | Bin 0 -> 904 bytes .../tzdata/zoneinfo/Australia/West | Bin 0 -> 306 bytes .../tzdata/zoneinfo/Australia/Yancowinna | Bin 0 -> 941 bytes .../tzdata/zoneinfo/Australia/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 200 bytes .../site-packages/tzdata/zoneinfo/Brazil/Acre | Bin 0 -> 418 bytes .../tzdata/zoneinfo/Brazil/DeNoronha | Bin 0 -> 484 bytes .../site-packages/tzdata/zoneinfo/Brazil/East | Bin 0 -> 952 bytes .../site-packages/tzdata/zoneinfo/Brazil/West | Bin 0 -> 412 bytes .../tzdata/zoneinfo/Brazil/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 197 bytes .../Lib/site-packages/tzdata/zoneinfo/CET | Bin 0 -> 1103 bytes .../Lib/site-packages/tzdata/zoneinfo/CST6CDT | Bin 0 -> 1754 bytes .../tzdata/zoneinfo/Canada/Atlantic | Bin 0 -> 1672 bytes .../tzdata/zoneinfo/Canada/Central | Bin 0 -> 1294 bytes .../tzdata/zoneinfo/Canada/Eastern | Bin 0 -> 1717 bytes .../tzdata/zoneinfo/Canada/Mountain | Bin 0 -> 970 bytes .../tzdata/zoneinfo/Canada/Newfoundland | Bin 0 -> 1878 bytes .../tzdata/zoneinfo/Canada/Pacific | Bin 0 -> 1330 bytes .../tzdata/zoneinfo/Canada/Saskatchewan | Bin 0 -> 638 bytes .../tzdata/zoneinfo/Canada/Yukon | Bin 0 -> 1029 bytes .../tzdata/zoneinfo/Canada/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 197 bytes .../tzdata/zoneinfo/Chile/Continental | Bin 0 -> 1354 bytes .../tzdata/zoneinfo/Chile/EasterIsland | Bin 0 -> 1174 bytes .../tzdata/zoneinfo/Chile/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 196 bytes .../Lib/site-packages/tzdata/zoneinfo/Cuba | Bin 0 -> 1117 bytes .../Lib/site-packages/tzdata/zoneinfo/EET | Bin 0 -> 682 bytes .../Lib/site-packages/tzdata/zoneinfo/EST | Bin 0 -> 149 bytes .../Lib/site-packages/tzdata/zoneinfo/EST5EDT | Bin 0 -> 1744 bytes .../Lib/site-packages/tzdata/zoneinfo/Egypt | Bin 0 -> 1309 bytes .../Lib/site-packages/tzdata/zoneinfo/Eire | Bin 0 -> 1496 bytes .../Lib/site-packages/tzdata/zoneinfo/Etc/GMT | Bin 0 -> 111 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+0 | Bin 0 -> 111 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+1 | Bin 0 -> 113 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+10 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+11 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+12 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+2 | Bin 0 -> 113 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+3 | Bin 0 -> 113 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+4 | Bin 0 -> 113 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+5 | Bin 0 -> 113 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+6 | Bin 0 -> 113 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+7 | Bin 0 -> 113 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+8 | Bin 0 -> 113 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+9 | Bin 0 -> 113 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-0 | Bin 0 -> 111 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-1 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-10 | Bin 0 -> 115 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-11 | Bin 0 -> 115 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-12 | Bin 0 -> 115 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-13 | Bin 0 -> 115 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-14 | Bin 0 -> 115 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-2 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-3 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-4 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-5 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-6 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-7 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-8 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-9 | Bin 0 -> 114 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT0 | Bin 0 -> 111 bytes .../tzdata/zoneinfo/Etc/Greenwich | Bin 0 -> 111 bytes .../Lib/site-packages/tzdata/zoneinfo/Etc/UCT | Bin 0 -> 111 bytes .../Lib/site-packages/tzdata/zoneinfo/Etc/UTC | Bin 0 -> 111 bytes .../tzdata/zoneinfo/Etc/Universal | Bin 0 -> 111 bytes .../site-packages/tzdata/zoneinfo/Etc/Zulu | Bin 0 -> 111 bytes .../tzdata/zoneinfo/Etc/__init__.py | 0 .../Etc/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 194 bytes .../tzdata/zoneinfo/Europe/Amsterdam | Bin 0 -> 1103 bytes .../tzdata/zoneinfo/Europe/Andorra | Bin 0 -> 389 bytes .../tzdata/zoneinfo/Europe/Astrakhan | Bin 0 -> 726 bytes .../tzdata/zoneinfo/Europe/Athens | Bin 0 -> 682 bytes .../tzdata/zoneinfo/Europe/Belfast | Bin 0 -> 1599 bytes .../tzdata/zoneinfo/Europe/Belgrade | Bin 0 -> 478 bytes .../tzdata/zoneinfo/Europe/Berlin | Bin 0 -> 705 bytes .../tzdata/zoneinfo/Europe/Bratislava | Bin 0 -> 723 bytes .../tzdata/zoneinfo/Europe/Brussels | Bin 0 -> 1103 bytes .../tzdata/zoneinfo/Europe/Bucharest | Bin 0 -> 661 bytes .../tzdata/zoneinfo/Europe/Budapest | Bin 0 -> 766 bytes .../tzdata/zoneinfo/Europe/Busingen | Bin 0 -> 497 bytes .../tzdata/zoneinfo/Europe/Chisinau | Bin 0 -> 755 bytes .../tzdata/zoneinfo/Europe/Copenhagen | Bin 0 -> 705 bytes .../tzdata/zoneinfo/Europe/Dublin | Bin 0 -> 1496 bytes .../tzdata/zoneinfo/Europe/Gibraltar | Bin 0 -> 1220 bytes .../tzdata/zoneinfo/Europe/Guernsey | Bin 0 -> 1599 bytes .../tzdata/zoneinfo/Europe/Helsinki | Bin 0 -> 481 bytes .../tzdata/zoneinfo/Europe/Isle_of_Man | Bin 0 -> 1599 bytes .../tzdata/zoneinfo/Europe/Istanbul | Bin 0 -> 1200 bytes .../tzdata/zoneinfo/Europe/Jersey | Bin 0 -> 1599 bytes .../tzdata/zoneinfo/Europe/Kaliningrad | Bin 0 -> 904 bytes .../site-packages/tzdata/zoneinfo/Europe/Kiev | Bin 0 -> 558 bytes .../tzdata/zoneinfo/Europe/Kirov | Bin 0 -> 735 bytes .../site-packages/tzdata/zoneinfo/Europe/Kyiv | Bin 0 -> 558 bytes .../tzdata/zoneinfo/Europe/Lisbon | Bin 0 -> 1463 bytes .../tzdata/zoneinfo/Europe/Ljubljana | Bin 0 -> 478 bytes .../tzdata/zoneinfo/Europe/London | Bin 0 -> 1599 bytes .../tzdata/zoneinfo/Europe/Luxembourg | Bin 0 -> 1103 bytes .../tzdata/zoneinfo/Europe/Madrid | Bin 0 -> 897 bytes .../tzdata/zoneinfo/Europe/Malta | Bin 0 -> 928 bytes .../tzdata/zoneinfo/Europe/Mariehamn | Bin 0 -> 481 bytes .../tzdata/zoneinfo/Europe/Minsk | Bin 0 -> 808 bytes .../tzdata/zoneinfo/Europe/Monaco | Bin 0 -> 1105 bytes .../tzdata/zoneinfo/Europe/Moscow | Bin 0 -> 908 bytes .../tzdata/zoneinfo/Europe/Nicosia | Bin 0 -> 597 bytes .../site-packages/tzdata/zoneinfo/Europe/Oslo | Bin 0 -> 705 bytes .../tzdata/zoneinfo/Europe/Paris | Bin 0 -> 1105 bytes .../tzdata/zoneinfo/Europe/Podgorica | Bin 0 -> 478 bytes .../tzdata/zoneinfo/Europe/Prague | Bin 0 -> 723 bytes .../site-packages/tzdata/zoneinfo/Europe/Riga | Bin 0 -> 694 bytes .../site-packages/tzdata/zoneinfo/Europe/Rome | Bin 0 -> 947 bytes .../tzdata/zoneinfo/Europe/Samara | Bin 0 -> 732 bytes .../tzdata/zoneinfo/Europe/San_Marino | Bin 0 -> 947 bytes .../tzdata/zoneinfo/Europe/Sarajevo | Bin 0 -> 478 bytes .../tzdata/zoneinfo/Europe/Saratov | Bin 0 -> 726 bytes .../tzdata/zoneinfo/Europe/Simferopol | Bin 0 -> 865 bytes .../tzdata/zoneinfo/Europe/Skopje | Bin 0 -> 478 bytes .../tzdata/zoneinfo/Europe/Sofia | Bin 0 -> 592 bytes .../tzdata/zoneinfo/Europe/Stockholm | Bin 0 -> 705 bytes .../tzdata/zoneinfo/Europe/Tallinn | Bin 0 -> 675 bytes .../tzdata/zoneinfo/Europe/Tirane | Bin 0 -> 604 bytes .../tzdata/zoneinfo/Europe/Tiraspol | Bin 0 -> 755 bytes .../tzdata/zoneinfo/Europe/Ulyanovsk | Bin 0 -> 760 bytes .../tzdata/zoneinfo/Europe/Uzhgorod | Bin 0 -> 558 bytes .../tzdata/zoneinfo/Europe/Vaduz | Bin 0 -> 497 bytes .../tzdata/zoneinfo/Europe/Vatican | Bin 0 -> 947 bytes .../tzdata/zoneinfo/Europe/Vienna | Bin 0 -> 658 bytes .../tzdata/zoneinfo/Europe/Vilnius | Bin 0 -> 676 bytes .../tzdata/zoneinfo/Europe/Volgograd | Bin 0 -> 753 bytes .../tzdata/zoneinfo/Europe/Warsaw | Bin 0 -> 923 bytes .../tzdata/zoneinfo/Europe/Zagreb | Bin 0 -> 478 bytes .../tzdata/zoneinfo/Europe/Zaporozhye | Bin 0 -> 558 bytes .../tzdata/zoneinfo/Europe/Zurich | Bin 0 -> 497 bytes .../tzdata/zoneinfo/Europe/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 197 bytes .../Lib/site-packages/tzdata/zoneinfo/Factory | Bin 0 -> 113 bytes .../Lib/site-packages/tzdata/zoneinfo/GB | Bin 0 -> 1599 bytes .../Lib/site-packages/tzdata/zoneinfo/GB-Eire | Bin 0 -> 1599 bytes .../Lib/site-packages/tzdata/zoneinfo/GMT | Bin 0 -> 111 bytes .../Lib/site-packages/tzdata/zoneinfo/GMT+0 | Bin 0 -> 111 bytes .../Lib/site-packages/tzdata/zoneinfo/GMT-0 | Bin 0 -> 111 bytes .../Lib/site-packages/tzdata/zoneinfo/GMT0 | Bin 0 -> 111 bytes .../site-packages/tzdata/zoneinfo/Greenwich | Bin 0 -> 111 bytes .../Lib/site-packages/tzdata/zoneinfo/HST | Bin 0 -> 221 bytes .../site-packages/tzdata/zoneinfo/Hongkong | Bin 0 -> 775 bytes .../Lib/site-packages/tzdata/zoneinfo/Iceland | Bin 0 -> 130 bytes .../tzdata/zoneinfo/Indian/Antananarivo | Bin 0 -> 191 bytes .../tzdata/zoneinfo/Indian/Chagos | Bin 0 -> 152 bytes .../tzdata/zoneinfo/Indian/Christmas | Bin 0 -> 152 bytes .../tzdata/zoneinfo/Indian/Cocos | Bin 0 -> 187 bytes .../tzdata/zoneinfo/Indian/Comoro | Bin 0 -> 191 bytes .../tzdata/zoneinfo/Indian/Kerguelen | Bin 0 -> 152 bytes .../site-packages/tzdata/zoneinfo/Indian/Mahe | Bin 0 -> 133 bytes .../tzdata/zoneinfo/Indian/Maldives | Bin 0 -> 152 bytes .../tzdata/zoneinfo/Indian/Mauritius | Bin 0 -> 179 bytes .../tzdata/zoneinfo/Indian/Mayotte | Bin 0 -> 191 bytes .../tzdata/zoneinfo/Indian/Reunion | Bin 0 -> 133 bytes .../tzdata/zoneinfo/Indian/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 197 bytes .../Lib/site-packages/tzdata/zoneinfo/Iran | Bin 0 -> 812 bytes .../Lib/site-packages/tzdata/zoneinfo/Israel | Bin 0 -> 1074 bytes .../Lib/site-packages/tzdata/zoneinfo/Jamaica | Bin 0 -> 339 bytes .../Lib/site-packages/tzdata/zoneinfo/Japan | Bin 0 -> 213 bytes .../site-packages/tzdata/zoneinfo/Kwajalein | Bin 0 -> 219 bytes .../Lib/site-packages/tzdata/zoneinfo/Libya | Bin 0 -> 431 bytes .../Lib/site-packages/tzdata/zoneinfo/MET | Bin 0 -> 1103 bytes .../Lib/site-packages/tzdata/zoneinfo/MST | Bin 0 -> 240 bytes .../Lib/site-packages/tzdata/zoneinfo/MST7MDT | Bin 0 -> 1042 bytes .../tzdata/zoneinfo/Mexico/BajaNorte | Bin 0 -> 1079 bytes .../tzdata/zoneinfo/Mexico/BajaSur | Bin 0 -> 690 bytes .../tzdata/zoneinfo/Mexico/General | Bin 0 -> 773 bytes .../tzdata/zoneinfo/Mexico/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 197 bytes .../Lib/site-packages/tzdata/zoneinfo/NZ | Bin 0 -> 1043 bytes .../Lib/site-packages/tzdata/zoneinfo/NZ-CHAT | Bin 0 -> 808 bytes .../Lib/site-packages/tzdata/zoneinfo/Navajo | Bin 0 -> 1042 bytes .../Lib/site-packages/tzdata/zoneinfo/PRC | Bin 0 -> 393 bytes .../Lib/site-packages/tzdata/zoneinfo/PST8PDT | Bin 0 -> 1294 bytes .../tzdata/zoneinfo/Pacific/Apia | Bin 0 -> 407 bytes .../tzdata/zoneinfo/Pacific/Auckland | Bin 0 -> 1043 bytes .../tzdata/zoneinfo/Pacific/Bougainville | Bin 0 -> 201 bytes .../tzdata/zoneinfo/Pacific/Chatham | Bin 0 -> 808 bytes .../tzdata/zoneinfo/Pacific/Chuuk | Bin 0 -> 154 bytes .../tzdata/zoneinfo/Pacific/Easter | Bin 0 -> 1174 bytes .../tzdata/zoneinfo/Pacific/Efate | Bin 0 -> 342 bytes .../tzdata/zoneinfo/Pacific/Enderbury | Bin 0 -> 172 bytes .../tzdata/zoneinfo/Pacific/Fakaofo | Bin 0 -> 153 bytes .../tzdata/zoneinfo/Pacific/Fiji | Bin 0 -> 396 bytes .../tzdata/zoneinfo/Pacific/Funafuti | Bin 0 -> 134 bytes .../tzdata/zoneinfo/Pacific/Galapagos | Bin 0 -> 175 bytes .../tzdata/zoneinfo/Pacific/Gambier | Bin 0 -> 132 bytes .../tzdata/zoneinfo/Pacific/Guadalcanal | Bin 0 -> 134 bytes .../tzdata/zoneinfo/Pacific/Guam | Bin 0 -> 350 bytes .../tzdata/zoneinfo/Pacific/Honolulu | Bin 0 -> 221 bytes .../tzdata/zoneinfo/Pacific/Johnston | Bin 0 -> 221 bytes .../tzdata/zoneinfo/Pacific/Kanton | Bin 0 -> 172 bytes .../tzdata/zoneinfo/Pacific/Kiritimati | Bin 0 -> 174 bytes .../tzdata/zoneinfo/Pacific/Kosrae | Bin 0 -> 242 bytes .../tzdata/zoneinfo/Pacific/Kwajalein | Bin 0 -> 219 bytes .../tzdata/zoneinfo/Pacific/Majuro | Bin 0 -> 134 bytes .../tzdata/zoneinfo/Pacific/Marquesas | Bin 0 -> 139 bytes .../tzdata/zoneinfo/Pacific/Midway | Bin 0 -> 146 bytes .../tzdata/zoneinfo/Pacific/Nauru | Bin 0 -> 183 bytes .../tzdata/zoneinfo/Pacific/Niue | Bin 0 -> 154 bytes .../tzdata/zoneinfo/Pacific/Norfolk | Bin 0 -> 237 bytes .../tzdata/zoneinfo/Pacific/Noumea | Bin 0 -> 198 bytes .../tzdata/zoneinfo/Pacific/Pago_Pago | Bin 0 -> 146 bytes .../tzdata/zoneinfo/Pacific/Palau | Bin 0 -> 148 bytes .../tzdata/zoneinfo/Pacific/Pitcairn | Bin 0 -> 153 bytes .../tzdata/zoneinfo/Pacific/Pohnpei | Bin 0 -> 134 bytes .../tzdata/zoneinfo/Pacific/Ponape | Bin 0 -> 134 bytes .../tzdata/zoneinfo/Pacific/Port_Moresby | Bin 0 -> 154 bytes .../tzdata/zoneinfo/Pacific/Rarotonga | Bin 0 -> 406 bytes .../tzdata/zoneinfo/Pacific/Saipan | Bin 0 -> 350 bytes .../tzdata/zoneinfo/Pacific/Samoa | Bin 0 -> 146 bytes .../tzdata/zoneinfo/Pacific/Tahiti | Bin 0 -> 133 bytes .../tzdata/zoneinfo/Pacific/Tarawa | Bin 0 -> 134 bytes .../tzdata/zoneinfo/Pacific/Tongatapu | Bin 0 -> 237 bytes .../tzdata/zoneinfo/Pacific/Truk | Bin 0 -> 154 bytes .../tzdata/zoneinfo/Pacific/Wake | Bin 0 -> 134 bytes .../tzdata/zoneinfo/Pacific/Wallis | Bin 0 -> 134 bytes .../site-packages/tzdata/zoneinfo/Pacific/Yap | Bin 0 -> 154 bytes .../tzdata/zoneinfo/Pacific/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 198 bytes .../Lib/site-packages/tzdata/zoneinfo/Poland | Bin 0 -> 923 bytes .../site-packages/tzdata/zoneinfo/Portugal | Bin 0 -> 1463 bytes .../Lib/site-packages/tzdata/zoneinfo/ROC | Bin 0 -> 511 bytes .../Lib/site-packages/tzdata/zoneinfo/ROK | Bin 0 -> 415 bytes .../site-packages/tzdata/zoneinfo/Singapore | Bin 0 -> 256 bytes .../Lib/site-packages/tzdata/zoneinfo/Turkey | Bin 0 -> 1200 bytes .../Lib/site-packages/tzdata/zoneinfo/UCT | Bin 0 -> 111 bytes .../site-packages/tzdata/zoneinfo/US/Alaska | Bin 0 -> 977 bytes .../site-packages/tzdata/zoneinfo/US/Aleutian | Bin 0 -> 969 bytes .../site-packages/tzdata/zoneinfo/US/Arizona | Bin 0 -> 240 bytes .../site-packages/tzdata/zoneinfo/US/Central | Bin 0 -> 1754 bytes .../tzdata/zoneinfo/US/East-Indiana | Bin 0 -> 531 bytes .../site-packages/tzdata/zoneinfo/US/Eastern | Bin 0 -> 1744 bytes .../site-packages/tzdata/zoneinfo/US/Hawaii | Bin 0 -> 221 bytes .../tzdata/zoneinfo/US/Indiana-Starke | Bin 0 -> 1016 bytes .../site-packages/tzdata/zoneinfo/US/Michigan | Bin 0 -> 899 bytes .../site-packages/tzdata/zoneinfo/US/Mountain | Bin 0 -> 1042 bytes .../site-packages/tzdata/zoneinfo/US/Pacific | Bin 0 -> 1294 bytes .../site-packages/tzdata/zoneinfo/US/Samoa | Bin 0 -> 146 bytes .../tzdata/zoneinfo/US/__init__.py | 0 .../US/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 193 bytes .../Lib/site-packages/tzdata/zoneinfo/UTC | Bin 0 -> 111 bytes .../site-packages/tzdata/zoneinfo/Universal | Bin 0 -> 111 bytes .../Lib/site-packages/tzdata/zoneinfo/W-SU | Bin 0 -> 908 bytes .../Lib/site-packages/tzdata/zoneinfo/WET | Bin 0 -> 1463 bytes .../Lib/site-packages/tzdata/zoneinfo/Zulu | Bin 0 -> 111 bytes .../site-packages/tzdata/zoneinfo/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 190 bytes .../site-packages/tzdata/zoneinfo/iso3166.tab | 279 + .../site-packages/tzdata/zoneinfo/leapseconds | 79 + .../site-packages/tzdata/zoneinfo/tzdata.zi | 4300 ++++++++ .../site-packages/tzdata/zoneinfo/zone.tab | 448 + .../tzdata/zoneinfo/zone1970.tab | 375 + .../site-packages/tzdata/zoneinfo/zonenow.tab | 296 + backend/.venv/Lib/site-packages/tzdata/zones | 598 ++ .../uvicorn-0.32.1.dist-info/INSTALLER | 1 + .../uvicorn-0.32.1.dist-info/METADATA | 186 + .../uvicorn-0.32.1.dist-info/RECORD | 87 + .../uvicorn-0.32.1.dist-info/REQUESTED | 0 .../uvicorn-0.32.1.dist-info/WHEEL | 4 + .../uvicorn-0.32.1.dist-info/entry_points.txt | 2 + .../licenses/LICENSE.md | 27 + .../Lib/site-packages/uvicorn/__init__.py | 5 + .../Lib/site-packages/uvicorn/__main__.py | 4 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 380 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 300 bytes .../__pycache__/_subprocess.cpython-312.pyc | Bin 0 -> 2934 bytes .../__pycache__/_types.cpython-312.pyc | Bin 0 -> 11349 bytes .../__pycache__/config.cpython-312.pyc | Bin 0 -> 24695 bytes .../__pycache__/importer.cpython-312.pyc | Bin 0 -> 1773 bytes .../__pycache__/logging.cpython-312.pyc | Bin 0 -> 7783 bytes .../uvicorn/__pycache__/main.cpython-312.pyc | Bin 0 -> 19971 bytes .../__pycache__/server.cpython-312.pyc | Bin 0 -> 16598 bytes .../__pycache__/workers.cpython-312.pyc | Bin 0 -> 6715 bytes .../Lib/site-packages/uvicorn/_subprocess.py | 84 + .../.venv/Lib/site-packages/uvicorn/_types.py | 293 + .../.venv/Lib/site-packages/uvicorn/config.py | 529 + .../Lib/site-packages/uvicorn/importer.py | 34 + .../uvicorn/lifespan/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 191 bytes .../lifespan/__pycache__/off.cpython-312.pyc | Bin 0 -> 980 bytes .../lifespan/__pycache__/on.cpython-312.pyc | Bin 0 -> 7955 bytes .../Lib/site-packages/uvicorn/lifespan/off.py | 17 + .../Lib/site-packages/uvicorn/lifespan/on.py | 137 + .../Lib/site-packages/uvicorn/logging.py | 117 + .../site-packages/uvicorn/loops/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 188 bytes .../loops/__pycache__/asyncio.cpython-312.pyc | Bin 0 -> 751 bytes .../loops/__pycache__/auto.cpython-312.pyc | Bin 0 -> 655 bytes .../loops/__pycache__/uvloop.cpython-312.pyc | Bin 0 -> 541 bytes .../site-packages/uvicorn/loops/asyncio.py | 10 + .../Lib/site-packages/uvicorn/loops/auto.py | 11 + .../Lib/site-packages/uvicorn/loops/uvloop.py | 7 + .../.venv/Lib/site-packages/uvicorn/main.py | 591 ++ .../uvicorn/middleware/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 193 bytes .../__pycache__/asgi2.cpython-312.pyc | Bin 0 -> 1003 bytes .../message_logger.cpython-312.pyc | Bin 0 -> 4394 bytes .../__pycache__/proxy_headers.cpython-312.pyc | Bin 0 -> 5813 bytes .../__pycache__/wsgi.cpython-312.pyc | Bin 0 -> 9927 bytes .../site-packages/uvicorn/middleware/asgi2.py | 15 + .../uvicorn/middleware/message_logger.py | 87 + .../uvicorn/middleware/proxy_headers.py | 142 + .../site-packages/uvicorn/middleware/wsgi.py | 200 + .../uvicorn/protocols/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 192 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 2959 bytes .../uvicorn/protocols/http/__init__.py | 0 .../http/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 197 bytes .../http/__pycache__/auto.cpython-312.pyc | Bin 0 -> 608 bytes .../__pycache__/flow_control.cpython-312.pyc | Bin 0 -> 3038 bytes .../http/__pycache__/h11_impl.cpython-312.pyc | Bin 0 -> 27028 bytes .../httptools_impl.cpython-312.pyc | Bin 0 -> 29029 bytes .../uvicorn/protocols/http/auto.py | 15 + .../uvicorn/protocols/http/flow_control.py | 54 + .../uvicorn/protocols/http/h11_impl.py | 543 + .../uvicorn/protocols/http/httptools_impl.py | 570 ++ .../site-packages/uvicorn/protocols/utils.py | 56 + .../uvicorn/protocols/websockets/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 203 bytes .../__pycache__/auto.cpython-312.pyc | Bin 0 -> 788 bytes .../websockets_impl.cpython-312.pyc | Bin 0 -> 20452 bytes .../__pycache__/wsproto_impl.cpython-312.pyc | Bin 0 -> 21122 bytes .../uvicorn/protocols/websockets/auto.py | 21 + .../protocols/websockets/websockets_impl.py | 385 + .../protocols/websockets/wsproto_impl.py | 376 + .../.venv/Lib/site-packages/uvicorn/py.typed | 1 + .../.venv/Lib/site-packages/uvicorn/server.py | 339 + .../uvicorn/supervisors/__init__.py | 23 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 921 bytes .../__pycache__/basereload.cpython-312.pyc | Bin 0 -> 6837 bytes .../__pycache__/multiprocess.cpython-312.pyc | Bin 0 -> 13324 bytes .../__pycache__/statreload.cpython-312.pyc | Bin 0 -> 2814 bytes .../watchfilesreload.cpython-312.pyc | Bin 0 -> 4535 bytes .../watchgodreload.cpython-312.pyc | Bin 0 -> 7719 bytes .../uvicorn/supervisors/basereload.py | 121 + .../uvicorn/supervisors/multiprocess.py | 222 + .../uvicorn/supervisors/statreload.py | 52 + .../uvicorn/supervisors/watchfilesreload.py | 88 + .../uvicorn/supervisors/watchgodreload.py | 152 + .../Lib/site-packages/uvicorn/workers.py | 114 + .../watchfiles-1.1.1.dist-info/INSTALLER | 1 + .../watchfiles-1.1.1.dist-info/METADATA | 148 + .../watchfiles-1.1.1.dist-info/RECORD | 24 + .../watchfiles-1.1.1.dist-info/WHEEL | 4 + .../entry_points.txt | 2 + .../licenses/LICENSE | 21 + .../Lib/site-packages/watchfiles/__init__.py | 17 + .../Lib/site-packages/watchfiles/__main__.py | 4 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 544 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 278 bytes .../__pycache__/cli.cpython-312.pyc | Bin 0 -> 10196 bytes .../__pycache__/filters.cpython-312.pyc | Bin 0 -> 7219 bytes .../__pycache__/main.cpython-312.pyc | Bin 0 -> 17116 bytes .../__pycache__/run.cpython-312.pyc | Bin 0 -> 19474 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 278 bytes .../_rust_notify.cp312-win_amd64.pyd | Bin 0 -> 685568 bytes .../site-packages/watchfiles/_rust_notify.pyi | 111 + .../.venv/Lib/site-packages/watchfiles/cli.py | 224 + .../Lib/site-packages/watchfiles/filters.py | 149 + .../Lib/site-packages/watchfiles/main.py | 373 + .../Lib/site-packages/watchfiles/py.typed | 1 + .../.venv/Lib/site-packages/watchfiles/run.py | 438 + .../Lib/site-packages/watchfiles/version.py | 5 + .../websockets-15.0.1.dist-info/INSTALLER | 1 + .../websockets-15.0.1.dist-info/LICENSE | 24 + .../websockets-15.0.1.dist-info/METADATA | 179 + .../websockets-15.0.1.dist-info/RECORD | 106 + .../websockets-15.0.1.dist-info/WHEEL | 5 + .../entry_points.txt | 2 + .../websockets-15.0.1.dist-info/top_level.txt | 1 + .../Lib/site-packages/websockets/__init__.py | 236 + .../Lib/site-packages/websockets/__main__.py | 5 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 4486 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 286 bytes .../__pycache__/auth.cpython-312.pyc | Bin 0 -> 798 bytes .../__pycache__/cli.cpython-312.pyc | Bin 0 -> 8314 bytes .../__pycache__/client.cpython-312.pyc | Bin 0 -> 16161 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 554 bytes .../datastructures.cpython-312.pyc | Bin 0 -> 8908 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 17931 bytes .../__pycache__/frames.cpython-312.pyc | Bin 0 -> 16009 bytes .../__pycache__/headers.cpython-312.pyc | Bin 0 -> 18141 bytes .../__pycache__/http.cpython-312.pyc | Bin 0 -> 910 bytes .../__pycache__/http11.cpython-312.pyc | Bin 0 -> 15480 bytes .../__pycache__/imports.cpython-312.pyc | Bin 0 -> 3409 bytes .../__pycache__/protocol.cpython-312.pyc | Bin 0 -> 25396 bytes .../__pycache__/server.cpython-312.pyc | Bin 0 -> 23051 bytes .../__pycache__/streams.cpython-312.pyc | Bin 0 -> 5448 bytes .../__pycache__/typing.cpython-312.pyc | Bin 0 -> 1255 bytes .../__pycache__/uri.cpython-312.pyc | Bin 0 -> 8121 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 2231 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 2979 bytes .../websockets/asyncio/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 193 bytes .../__pycache__/async_timeout.cpython-312.pyc | Bin 0 -> 10634 bytes .../__pycache__/client.cpython-312.pyc | Bin 0 -> 33669 bytes .../__pycache__/compatibility.cpython-312.pyc | Bin 0 -> 1069 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 51681 bytes .../__pycache__/messages.cpython-312.pyc | Bin 0 -> 13591 bytes .../__pycache__/router.cpython-312.pyc | Bin 0 -> 8184 bytes .../__pycache__/server.cpython-312.pyc | Bin 0 -> 39238 bytes .../websockets/asyncio/async_timeout.py | 282 + .../websockets/asyncio/client.py | 820 ++ .../websockets/asyncio/compatibility.py | 30 + .../websockets/asyncio/connection.py | 1237 +++ .../websockets/asyncio/messages.py | 314 + .../websockets/asyncio/router.py | 198 + .../websockets/asyncio/server.py | 981 ++ .../Lib/site-packages/websockets/auth.py | 18 + .../.venv/Lib/site-packages/websockets/cli.py | 178 + .../Lib/site-packages/websockets/client.py | 389 + .../site-packages/websockets/connection.py | 12 + .../websockets/datastructures.py | 187 + .../site-packages/websockets/exceptions.py | 473 + .../websockets/extensions/__init__.py | 4 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 308 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 3922 bytes .../permessage_deflate.cpython-312.pyc | Bin 0 -> 19439 bytes .../websockets/extensions/base.py | 123 + .../extensions/permessage_deflate.py | 697 ++ .../Lib/site-packages/websockets/frames.py | 430 + .../Lib/site-packages/websockets/headers.py | 586 ++ .../Lib/site-packages/websockets/http.py | 20 + .../Lib/site-packages/websockets/http11.py | 427 + .../Lib/site-packages/websockets/imports.py | 100 + .../websockets/legacy/__init__.py | 11 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 478 bytes .../legacy/__pycache__/auth.cpython-312.pyc | Bin 0 -> 7693 bytes .../legacy/__pycache__/client.cpython-312.pyc | Bin 0 -> 27844 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 3326 bytes .../__pycache__/framing.cpython-312.pyc | Bin 0 -> 8188 bytes .../__pycache__/handshake.cpython-312.pyc | Bin 0 -> 6337 bytes .../legacy/__pycache__/http.cpython-312.pyc | Bin 0 -> 7695 bytes .../__pycache__/protocol.cpython-312.pyc | Bin 0 -> 63999 bytes .../legacy/__pycache__/server.cpython-312.pyc | Bin 0 -> 46690 bytes .../site-packages/websockets/legacy/auth.py | 190 + .../site-packages/websockets/legacy/client.py | 705 ++ .../websockets/legacy/exceptions.py | 71 + .../websockets/legacy/framing.py | 225 + .../websockets/legacy/handshake.py | 158 + .../site-packages/websockets/legacy/http.py | 201 + .../websockets/legacy/protocol.py | 1641 +++ .../site-packages/websockets/legacy/server.py | 1191 +++ .../Lib/site-packages/websockets/protocol.py | 758 ++ .../Lib/site-packages/websockets/py.typed | 0 .../Lib/site-packages/websockets/server.py | 587 ++ .../Lib/site-packages/websockets/speedups.c | 222 + .../websockets/speedups.cp312-win_amd64.pyd | Bin 0 -> 11776 bytes .../Lib/site-packages/websockets/speedups.pyi | 1 + .../Lib/site-packages/websockets/streams.py | 151 + .../site-packages/websockets/sync/__init__.py | 0 .../sync/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 190 bytes .../sync/__pycache__/client.cpython-312.pyc | Bin 0 -> 24597 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 39780 bytes .../sync/__pycache__/messages.cpython-312.pyc | Bin 0 -> 13466 bytes .../sync/__pycache__/router.cpython-312.pyc | Bin 0 -> 7866 bytes .../sync/__pycache__/server.cpython-312.pyc | Bin 0 -> 28354 bytes .../sync/__pycache__/utils.cpython-312.pyc | Bin 0 -> 1659 bytes .../site-packages/websockets/sync/client.py | 648 ++ .../websockets/sync/connection.py | 1072 ++ .../site-packages/websockets/sync/messages.py | 345 + .../site-packages/websockets/sync/router.py | 192 + .../site-packages/websockets/sync/server.py | 763 ++ .../site-packages/websockets/sync/utils.py | 45 + .../Lib/site-packages/websockets/typing.py | 74 + .../.venv/Lib/site-packages/websockets/uri.py | 225 + .../Lib/site-packages/websockets/utils.py | 51 + .../Lib/site-packages/websockets/version.py | 92 + .../.venv/Lib/site-packages/yaml/__init__.py | 390 + .../yaml/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 15594 bytes .../yaml/__pycache__/composer.cpython-312.pyc | Bin 0 -> 6525 bytes .../__pycache__/constructor.cpython-312.pyc | Bin 0 -> 34847 bytes .../yaml/__pycache__/cyaml.cpython-312.pyc | Bin 0 -> 4626 bytes .../yaml/__pycache__/dumper.cpython-312.pyc | Bin 0 -> 2462 bytes .../yaml/__pycache__/emitter.cpython-312.pyc | Bin 0 -> 50109 bytes .../yaml/__pycache__/error.cpython-312.pyc | Bin 0 -> 4268 bytes .../yaml/__pycache__/events.cpython-312.pyc | Bin 0 -> 4716 bytes .../yaml/__pycache__/loader.cpython-312.pyc | Bin 0 -> 3524 bytes .../yaml/__pycache__/nodes.cpython-312.pyc | Bin 0 -> 2209 bytes .../yaml/__pycache__/parser.cpython-312.pyc | Bin 0 -> 24704 bytes .../yaml/__pycache__/reader.cpython-312.pyc | Bin 0 -> 8844 bytes .../__pycache__/representer.cpython-312.pyc | Bin 0 -> 16898 bytes .../yaml/__pycache__/resolver.cpython-312.pyc | Bin 0 -> 9025 bytes .../yaml/__pycache__/scanner.cpython-312.pyc | Bin 0 -> 49825 bytes .../__pycache__/serializer.cpython-312.pyc | Bin 0 -> 6179 bytes .../yaml/__pycache__/tokens.cpython-312.pyc | Bin 0 -> 5783 bytes .../yaml/_yaml.cp312-win_amd64.pyd | Bin 0 -> 253952 bytes .../.venv/Lib/site-packages/yaml/composer.py | 139 + .../Lib/site-packages/yaml/constructor.py | 748 ++ backend/.venv/Lib/site-packages/yaml/cyaml.py | 101 + .../.venv/Lib/site-packages/yaml/dumper.py | 62 + .../.venv/Lib/site-packages/yaml/emitter.py | 1137 +++ backend/.venv/Lib/site-packages/yaml/error.py | 75 + .../.venv/Lib/site-packages/yaml/events.py | 86 + .../.venv/Lib/site-packages/yaml/loader.py | 63 + backend/.venv/Lib/site-packages/yaml/nodes.py | 49 + .../.venv/Lib/site-packages/yaml/parser.py | 589 ++ .../.venv/Lib/site-packages/yaml/reader.py | 185 + .../Lib/site-packages/yaml/representer.py | 389 + .../.venv/Lib/site-packages/yaml/resolver.py | 227 + .../.venv/Lib/site-packages/yaml/scanner.py | 1435 +++ .../Lib/site-packages/yaml/serializer.py | 111 + .../.venv/Lib/site-packages/yaml/tokens.py | 104 + backend/.venv/Scripts/Activate.ps1 | 528 + backend/.venv/Scripts/activate | 71 + backend/.venv/Scripts/activate.bat | 34 + backend/.venv/Scripts/deactivate.bat | 22 + backend/.venv/Scripts/dotenv.exe | Bin 0 -> 108414 bytes backend/.venv/Scripts/fastapi.exe | Bin 0 -> 108412 bytes backend/.venv/Scripts/pip.exe | Bin 0 -> 108423 bytes backend/.venv/Scripts/pip3.12.exe | Bin 0 -> 108423 bytes backend/.venv/Scripts/pip3.exe | Bin 0 -> 108423 bytes backend/.venv/Scripts/python.exe | Bin 0 -> 275176 bytes backend/.venv/Scripts/pythonw.exe | Bin 0 -> 263528 bytes backend/.venv/Scripts/uvicorn.exe | Bin 0 -> 108413 bytes backend/.venv/Scripts/watchfiles.exe | Bin 0 -> 108413 bytes backend/.venv/Scripts/websockets.exe | Bin 0 -> 108415 bytes backend/.venv/pyvenv.cfg | 5 + backend/app/__init__.py | 0 .../app/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 154 bytes backend/app/__pycache__/main.cpython-312.pyc | Bin 0 -> 1724 bytes backend/app/common/auth.py | 0 backend/app/common/utils.py | 0 backend/app/core/__init__.py | 0 .../core/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 159 bytes .../core/__pycache__/database.cpython-312.pyc | Bin 0 -> 794 bytes backend/app/core/config.py | 0 backend/app/core/database.py | 14 + backend/app/main.py | 44 + backend/app/modules/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 162 bytes backend/app/modules/accounts/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 171 bytes .../__pycache__/router.cpython-312.pyc | Bin 0 -> 4388 bytes backend/app/modules/accounts/router.py | 66 + backend/app/modules/journals/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 171 bytes .../__pycache__/router.cpython-312.pyc | Bin 0 -> 6548 bytes backend/app/modules/journals/router.py | 111 + backend/app/modules/ledger/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 169 bytes .../ledger/__pycache__/router.cpython-312.pyc | Bin 0 -> 4813 bytes backend/app/modules/ledger/router.py | 109 + backend/app/modules/trial_balance/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 176 bytes .../__pycache__/router.cpython-312.pyc | Bin 0 -> 3791 bytes backend/app/modules/trial_balance/router.py | 94 + backend/requirements.txt | 2 + docs/api_design.md | 0 docs/db_design.md | 0 scripts/fix_data.py | 0 scripts/import_csv.py | 0 2696 files changed, 332525 insertions(+) create mode 100644 .env create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 README.md create mode 100644 backend/.venv/Lib/site-packages/__pycache__/typing_extensions.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/_yaml/__init__.py create mode 100644 backend/.venv/Lib/site-packages/_yaml/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/annotated_types-0.7.0.dist-info/INSTALLER create mode 100644 backend/.venv/Lib/site-packages/annotated_types-0.7.0.dist-info/METADATA create mode 100644 backend/.venv/Lib/site-packages/annotated_types-0.7.0.dist-info/RECORD create mode 100644 backend/.venv/Lib/site-packages/annotated_types-0.7.0.dist-info/WHEEL create mode 100644 backend/.venv/Lib/site-packages/annotated_types-0.7.0.dist-info/licenses/LICENSE create mode 100644 backend/.venv/Lib/site-packages/annotated_types/__init__.py create mode 100644 backend/.venv/Lib/site-packages/annotated_types/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/annotated_types/__pycache__/test_cases.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/annotated_types/py.typed create mode 100644 backend/.venv/Lib/site-packages/annotated_types/test_cases.py create mode 100644 backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/INSTALLER create mode 100644 backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/METADATA create mode 100644 backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/RECORD create mode 100644 backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/WHEEL create mode 100644 backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/entry_points.txt create mode 100644 backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/licenses/LICENSE create mode 100644 backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/top_level.txt create mode 100644 backend/.venv/Lib/site-packages/anyio/__init__.py create mode 100644 backend/.venv/Lib/site-packages/anyio/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/__pycache__/from_thread.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/__pycache__/functools.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/__pycache__/lowlevel.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/__pycache__/pytest_plugin.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/__pycache__/to_interpreter.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/__pycache__/to_process.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/__pycache__/to_thread.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/_backends/__init__.py create mode 100644 backend/.venv/Lib/site-packages/anyio/_backends/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/_backends/__pycache__/_asyncio.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/_backends/__pycache__/_trio.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/_backends/_asyncio.py create mode 100644 backend/.venv/Lib/site-packages/anyio/_backends/_trio.py create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/__init__.py create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_asyncio_selector_thread.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_contextmanagers.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_eventloop.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_exceptions.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_fileio.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_resources.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_signals.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_sockets.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_streams.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_subprocesses.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_synchronization.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_tasks.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_tempfile.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_testing.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_typedattr.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/_asyncio_selector_thread.py create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/_contextmanagers.py create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/_eventloop.py create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/_exceptions.py create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/_fileio.py create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/_resources.py create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/_signals.py create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/_sockets.py create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/_streams.py create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/_subprocesses.py create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/_synchronization.py create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/_tasks.py create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/_tempfile.py create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/_testing.py create mode 100644 backend/.venv/Lib/site-packages/anyio/_core/_typedattr.py create mode 100644 backend/.venv/Lib/site-packages/anyio/abc/__init__.py create mode 100644 backend/.venv/Lib/site-packages/anyio/abc/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/abc/__pycache__/_eventloop.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/abc/__pycache__/_resources.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/abc/__pycache__/_sockets.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/abc/__pycache__/_streams.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/abc/__pycache__/_subprocesses.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/abc/__pycache__/_tasks.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/abc/__pycache__/_testing.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/abc/_eventloop.py create mode 100644 backend/.venv/Lib/site-packages/anyio/abc/_resources.py create mode 100644 backend/.venv/Lib/site-packages/anyio/abc/_sockets.py create mode 100644 backend/.venv/Lib/site-packages/anyio/abc/_streams.py create mode 100644 backend/.venv/Lib/site-packages/anyio/abc/_subprocesses.py create mode 100644 backend/.venv/Lib/site-packages/anyio/abc/_tasks.py create mode 100644 backend/.venv/Lib/site-packages/anyio/abc/_testing.py create mode 100644 backend/.venv/Lib/site-packages/anyio/from_thread.py create mode 100644 backend/.venv/Lib/site-packages/anyio/functools.py create mode 100644 backend/.venv/Lib/site-packages/anyio/lowlevel.py create mode 100644 backend/.venv/Lib/site-packages/anyio/py.typed create mode 100644 backend/.venv/Lib/site-packages/anyio/pytest_plugin.py create mode 100644 backend/.venv/Lib/site-packages/anyio/streams/__init__.py create mode 100644 backend/.venv/Lib/site-packages/anyio/streams/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/streams/__pycache__/buffered.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/streams/__pycache__/file.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/streams/__pycache__/memory.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/streams/__pycache__/stapled.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/streams/__pycache__/text.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/streams/__pycache__/tls.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/anyio/streams/buffered.py create mode 100644 backend/.venv/Lib/site-packages/anyio/streams/file.py create mode 100644 backend/.venv/Lib/site-packages/anyio/streams/memory.py create mode 100644 backend/.venv/Lib/site-packages/anyio/streams/stapled.py create mode 100644 backend/.venv/Lib/site-packages/anyio/streams/text.py create mode 100644 backend/.venv/Lib/site-packages/anyio/streams/tls.py create mode 100644 backend/.venv/Lib/site-packages/anyio/to_interpreter.py create mode 100644 backend/.venv/Lib/site-packages/anyio/to_process.py create mode 100644 backend/.venv/Lib/site-packages/anyio/to_thread.py create mode 100644 backend/.venv/Lib/site-packages/click-8.3.1.dist-info/INSTALLER create mode 100644 backend/.venv/Lib/site-packages/click-8.3.1.dist-info/METADATA create mode 100644 backend/.venv/Lib/site-packages/click-8.3.1.dist-info/RECORD create mode 100644 backend/.venv/Lib/site-packages/click-8.3.1.dist-info/WHEEL create mode 100644 backend/.venv/Lib/site-packages/click-8.3.1.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/fastapi-0.115.6.dist-info/INSTALLER create mode 100644 backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/METADATA create mode 100644 backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/RECORD create mode 100644 backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/REQUESTED create mode 100644 backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/WHEEL create mode 100644 backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/entry_points.txt create mode 100644 backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/licenses/LICENSE create mode 100644 backend/.venv/Lib/site-packages/fastapi/__init__.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/__main__.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/__main__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/_compat.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/applications.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/background.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/cli.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/concurrency.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/datastructures.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/encoders.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/exception_handlers.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/exceptions.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/logger.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/param_functions.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/params.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/requests.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/responses.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/routing.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/staticfiles.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/templating.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/testclient.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/types.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/utils.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/__pycache__/websockets.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/_compat.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/applications.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/background.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/cli.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/concurrency.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/datastructures.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/dependencies/__init__.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/dependencies/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/dependencies/__pycache__/models.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/dependencies/__pycache__/utils.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/dependencies/models.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/dependencies/utils.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/encoders.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/exception_handlers.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/exceptions.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/logger.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/middleware/__init__.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/middleware/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/middleware/__pycache__/cors.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/middleware/__pycache__/gzip.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/middleware/__pycache__/httpsredirect.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/middleware/__pycache__/trustedhost.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/middleware/__pycache__/wsgi.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/middleware/cors.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/middleware/gzip.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/middleware/httpsredirect.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/middleware/trustedhost.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/middleware/wsgi.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/openapi/__init__.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/openapi/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/openapi/__pycache__/constants.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/openapi/__pycache__/docs.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/openapi/__pycache__/models.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/openapi/__pycache__/utils.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/openapi/constants.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/openapi/docs.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/openapi/models.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/openapi/utils.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/param_functions.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/params.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/py.typed create mode 100644 backend/.venv/Lib/site-packages/fastapi/requests.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/responses.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/routing.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/security/__init__.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/security/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/security/__pycache__/api_key.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/security/__pycache__/base.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/security/__pycache__/http.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/security/__pycache__/oauth2.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/security/__pycache__/open_id_connect_url.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/security/__pycache__/utils.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/fastapi/security/api_key.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/security/base.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/security/http.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/security/oauth2.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/security/open_id_connect_url.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/security/utils.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/staticfiles.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/templating.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/testclient.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/types.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/utils.py create mode 100644 backend/.venv/Lib/site-packages/fastapi/websockets.py create mode 100644 backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/INSTALLER create mode 100644 backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/METADATA create mode 100644 backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/RECORD create mode 100644 backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/WHEEL create mode 100644 backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/licenses/LICENSE.txt create mode 100644 backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/top_level.txt create mode 100644 backend/.venv/Lib/site-packages/h11/__init__.py create mode 100644 backend/.venv/Lib/site-packages/h11/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/h11/__pycache__/_abnf.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/h11/__pycache__/_connection.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/h11/__pycache__/_events.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/h11/__pycache__/_headers.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/h11/__pycache__/_readers.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/h11/__pycache__/_receivebuffer.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/h11/__pycache__/_state.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/h11/__pycache__/_util.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/h11/__pycache__/_version.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/h11/__pycache__/_writers.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/h11/_abnf.py create mode 100644 backend/.venv/Lib/site-packages/h11/_connection.py create mode 100644 backend/.venv/Lib/site-packages/h11/_events.py create mode 100644 backend/.venv/Lib/site-packages/h11/_headers.py create mode 100644 backend/.venv/Lib/site-packages/h11/_readers.py create mode 100644 backend/.venv/Lib/site-packages/h11/_receivebuffer.py create mode 100644 backend/.venv/Lib/site-packages/h11/_state.py create mode 100644 backend/.venv/Lib/site-packages/h11/_util.py create mode 100644 backend/.venv/Lib/site-packages/h11/_version.py create mode 100644 backend/.venv/Lib/site-packages/h11/_writers.py create mode 100644 backend/.venv/Lib/site-packages/h11/py.typed create mode 100644 backend/.venv/Lib/site-packages/httptools-0.7.1.dist-info/INSTALLER create mode 100644 backend/.venv/Lib/site-packages/httptools-0.7.1.dist-info/METADATA create mode 100644 backend/.venv/Lib/site-packages/httptools-0.7.1.dist-info/RECORD create mode 100644 backend/.venv/Lib/site-packages/httptools-0.7.1.dist-info/WHEEL create mode 100644 backend/.venv/Lib/site-packages/httptools-0.7.1.dist-info/licenses/LICENSE create mode 100644 backend/.venv/Lib/site-packages/httptools-0.7.1.dist-info/top_level.txt create mode 100644 backend/.venv/Lib/site-packages/httptools/__init__.py create mode 100644 backend/.venv/Lib/site-packages/httptools/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/httptools/__pycache__/_version.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/httptools/_version.py create mode 100644 backend/.venv/Lib/site-packages/httptools/parser/__init__.py create mode 100644 backend/.venv/Lib/site-packages/httptools/parser/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/httptools/parser/__pycache__/errors.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/httptools/parser/__pycache__/protocol.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/httptools/parser/cparser.pxd create mode 100644 backend/.venv/Lib/site-packages/httptools/parser/errors.py create mode 100644 backend/.venv/Lib/site-packages/httptools/parser/parser.cp312-win_amd64.pyd create mode 100644 backend/.venv/Lib/site-packages/httptools/parser/parser.pyi create mode 100644 backend/.venv/Lib/site-packages/httptools/parser/parser.pyx create mode 100644 backend/.venv/Lib/site-packages/httptools/parser/protocol.py create mode 100644 backend/.venv/Lib/site-packages/httptools/parser/python.pxd create mode 100644 backend/.venv/Lib/site-packages/httptools/parser/url_cparser.pxd create mode 100644 backend/.venv/Lib/site-packages/httptools/parser/url_parser.cp312-win_amd64.pyd create mode 100644 backend/.venv/Lib/site-packages/httptools/parser/url_parser.pyi create mode 100644 backend/.venv/Lib/site-packages/httptools/parser/url_parser.pyx create mode 100644 backend/.venv/Lib/site-packages/idna-3.11.dist-info/INSTALLER create mode 100644 backend/.venv/Lib/site-packages/idna-3.11.dist-info/METADATA create mode 100644 backend/.venv/Lib/site-packages/idna-3.11.dist-info/RECORD create mode 100644 backend/.venv/Lib/site-packages/idna-3.11.dist-info/WHEEL create mode 100644 backend/.venv/Lib/site-packages/idna-3.11.dist-info/licenses/LICENSE.md 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/pip-24.3.1.dist-info/AUTHORS.txt create mode 100644 backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/INSTALLER create mode 100644 backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/LICENSE.txt create mode 100644 backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/METADATA create mode 100644 backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/RECORD create mode 100644 backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/REQUESTED create mode 100644 backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/WHEEL create mode 100644 backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/entry_points.txt create mode 100644 backend/.venv/Lib/site-packages/pip-24.3.1.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/psycopg-3.2.3.dist-info/INSTALLER create mode 100644 backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/LICENSE.txt create mode 100644 backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/METADATA create mode 100644 backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/RECORD create mode 100644 backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/REQUESTED create mode 100644 backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/WHEEL create mode 100644 backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/top_level.txt create mode 100644 backend/.venv/Lib/site-packages/psycopg/__init__.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_acompat.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_adapters_map.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_capabilities.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_cmodule.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_column.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_compat.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_connection_base.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_connection_info.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_conninfo_attempts.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_conninfo_attempts_async.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_conninfo_utils.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_copy.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_copy_async.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_copy_base.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_cursor_base.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_dns.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_encodings.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_enums.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_oids.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_pipeline.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_preparing.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_py_transformer.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_queries.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_struct.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_tpc.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_transformer.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_typeinfo.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_typemod.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_tz.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/_wrappers.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/abc.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/adapt.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/client_cursor.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/connection.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/connection_async.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/conninfo.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/copy.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/cursor.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/cursor_async.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/dbapi20.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/errors.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/generators.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/postgres.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/raw_cursor.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/rows.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/server_cursor.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/sql.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/transaction.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/version.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/__pycache__/waiting.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/_acompat.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_adapters_map.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_capabilities.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_cmodule.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_column.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_compat.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_connection_base.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_connection_info.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_conninfo_attempts.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_conninfo_attempts_async.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_conninfo_utils.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_copy.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_copy_async.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_copy_base.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_cursor_base.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_dns.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_encodings.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_enums.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_oids.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_pipeline.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_preparing.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_py_transformer.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_queries.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_struct.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_tpc.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_transformer.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_typeinfo.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_typemod.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_tz.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/_wrappers.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/abc.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/adapt.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/client_cursor.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/connection.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/connection_async.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/conninfo.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/copy.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/crdb/__init__.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/crdb/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/crdb/__pycache__/_types.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/crdb/__pycache__/connection.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/crdb/_types.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/crdb/connection.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/cursor.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/cursor_async.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/dbapi20.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/errors.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/generators.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/postgres.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/pq/__init__.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/pq/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/pq/__pycache__/_debug.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/pq/__pycache__/_enums.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/pq/__pycache__/_pq_ctypes.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/pq/__pycache__/abc.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/pq/__pycache__/misc.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/pq/__pycache__/pq_ctypes.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/pq/_debug.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/pq/_enums.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/pq/_pq_ctypes.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/pq/_pq_ctypes.pyi create mode 100644 backend/.venv/Lib/site-packages/psycopg/pq/abc.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/pq/misc.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/pq/pq_ctypes.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/py.typed create mode 100644 backend/.venv/Lib/site-packages/psycopg/raw_cursor.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/rows.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/server_cursor.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/sql.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/transaction.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/__init__.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/__pycache__/array.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/__pycache__/bool.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/__pycache__/composite.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/__pycache__/datetime.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/__pycache__/enum.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/__pycache__/hstore.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/__pycache__/json.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/__pycache__/multirange.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/__pycache__/net.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/__pycache__/none.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/__pycache__/numeric.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/__pycache__/numpy.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/__pycache__/range.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/__pycache__/shapely.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/__pycache__/string.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/__pycache__/uuid.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/array.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/bool.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/composite.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/datetime.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/enum.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/hstore.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/json.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/multirange.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/net.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/none.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/numeric.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/numpy.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/range.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/shapely.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/string.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/types/uuid.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/version.py create mode 100644 backend/.venv/Lib/site-packages/psycopg/waiting.py create mode 100644 backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/DELVEWHEEL create mode 100644 backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/INSTALLER create mode 100644 backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/LICENSE.txt create mode 100644 backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/METADATA create mode 100644 backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/RECORD create mode 100644 backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/WHEEL create mode 100644 backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/top_level.txt create mode 100644 backend/.venv/Lib/site-packages/psycopg_binary.libs/libcrypto-1_1-x64-15ec4b7b2d8017a72acf488cff1a1c38.dll create mode 100644 backend/.venv/Lib/site-packages/psycopg_binary.libs/libiconv-2.dll create mode 100644 backend/.venv/Lib/site-packages/psycopg_binary.libs/libintl-9-6b2fa35014185f5e79c4c76df54d19ae.dll create mode 100644 backend/.venv/Lib/site-packages/psycopg_binary.libs/libpq-de0d6d7eef3cda3760db155fac0f1d34.dll create mode 100644 backend/.venv/Lib/site-packages/psycopg_binary.libs/libssl-1_1-x64-56850767f4919548e5b00c9d311d045e.dll create mode 100644 backend/.venv/Lib/site-packages/psycopg_binary.libs/libwinpthread-1.dll create mode 100644 backend/.venv/Lib/site-packages/psycopg_binary/__init__.py create mode 100644 backend/.venv/Lib/site-packages/psycopg_binary/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg_binary/__pycache__/version.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/psycopg_binary/_psycopg.cp312-win_amd64.pyd create mode 100644 backend/.venv/Lib/site-packages/psycopg_binary/_psycopg.pyi create mode 100644 backend/.venv/Lib/site-packages/psycopg_binary/pq.cp312-win_amd64.pyd create mode 100644 backend/.venv/Lib/site-packages/psycopg_binary/py.typed create mode 100644 backend/.venv/Lib/site-packages/psycopg_binary/version.py create mode 100644 backend/.venv/Lib/site-packages/pydantic-2.12.5.dist-info/INSTALLER create mode 100644 backend/.venv/Lib/site-packages/pydantic-2.12.5.dist-info/METADATA create mode 100644 backend/.venv/Lib/site-packages/pydantic-2.12.5.dist-info/RECORD create mode 100644 backend/.venv/Lib/site-packages/pydantic-2.12.5.dist-info/WHEEL create mode 100644 backend/.venv/Lib/site-packages/pydantic-2.12.5.dist-info/licenses/LICENSE create mode 100644 backend/.venv/Lib/site-packages/pydantic/__init__.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/_migration.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/alias_generators.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/aliases.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/annotated_handlers.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/class_validators.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/color.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/config.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/dataclasses.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/datetime_parse.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/decorator.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/env_settings.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/error_wrappers.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/errors.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/fields.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/functional_serializers.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/functional_validators.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/generics.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/json.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/json_schema.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/main.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/mypy.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/networks.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/parse.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/root_model.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/schema.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/tools.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/type_adapter.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/types.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/typing.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/utils.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/validate_call_decorator.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/validators.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/version.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/__pycache__/warnings.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__init__.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_config.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_core_metadata.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_core_utils.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_dataclasses.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_decorators.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_decorators_v1.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_discriminated_union.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_docs_extraction.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_fields.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_forward_ref.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_generate_schema.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_generics.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_git.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_import_utils.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_internal_dataclass.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_known_annotated_metadata.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_mock_val_ser.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_model_construction.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_namespace_utils.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_repr.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_schema_gather.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_schema_generation_shared.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_serializers.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_signature.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_typing_extra.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_utils.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_validate_call.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_validators.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_config.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_core_metadata.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_core_utils.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_dataclasses.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_decorators.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_decorators_v1.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_discriminated_union.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_docs_extraction.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_fields.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_forward_ref.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_generate_schema.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_generics.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_git.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_import_utils.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_internal_dataclass.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_known_annotated_metadata.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_mock_val_ser.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_model_construction.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_namespace_utils.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_repr.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_schema_gather.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_schema_generation_shared.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_serializers.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_signature.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_typing_extra.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_utils.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_validate_call.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_internal/_validators.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/_migration.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/alias_generators.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/aliases.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/annotated_handlers.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/class_validators.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/color.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/config.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/dataclasses.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/datetime_parse.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/decorator.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/deprecated/__init__.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/deprecated/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/deprecated/__pycache__/class_validators.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/deprecated/__pycache__/config.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/deprecated/__pycache__/copy_internals.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/deprecated/__pycache__/decorator.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/deprecated/__pycache__/json.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/deprecated/__pycache__/parse.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/deprecated/__pycache__/tools.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/deprecated/class_validators.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/deprecated/config.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/deprecated/copy_internals.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/deprecated/decorator.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/deprecated/json.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/deprecated/parse.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/deprecated/tools.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/env_settings.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/error_wrappers.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/errors.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/experimental/__init__.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/experimental/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/experimental/__pycache__/arguments_schema.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/experimental/__pycache__/missing_sentinel.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/experimental/__pycache__/pipeline.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/experimental/arguments_schema.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/experimental/missing_sentinel.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/experimental/pipeline.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/fields.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/functional_serializers.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/functional_validators.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/generics.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/json.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/json_schema.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/main.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/mypy.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/networks.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/parse.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/plugin/__init__.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/plugin/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/plugin/__pycache__/_loader.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/plugin/__pycache__/_schema_validator.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/plugin/_loader.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/plugin/_schema_validator.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/py.typed create mode 100644 backend/.venv/Lib/site-packages/pydantic/root_model.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/schema.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/tools.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/type_adapter.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/types.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/typing.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/utils.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__init__.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/_hypothesis_plugin.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/annotated_types.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/class_validators.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/color.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/config.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/dataclasses.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/datetime_parse.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/decorator.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/env_settings.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/error_wrappers.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/errors.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/fields.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/generics.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/json.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/main.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/mypy.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/networks.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/parse.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/schema.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/tools.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/types.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/typing.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/utils.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/validators.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/version.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/_hypothesis_plugin.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/annotated_types.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/class_validators.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/color.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/config.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/dataclasses.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/datetime_parse.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/decorator.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/env_settings.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/error_wrappers.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/errors.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/fields.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/generics.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/json.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/main.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/mypy.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/networks.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/parse.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/py.typed create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/schema.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/tools.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/types.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/typing.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/utils.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/validators.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/v1/version.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/validate_call_decorator.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/validators.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/version.py create mode 100644 backend/.venv/Lib/site-packages/pydantic/warnings.py create mode 100644 backend/.venv/Lib/site-packages/pydantic_core-2.41.5.dist-info/INSTALLER create mode 100644 backend/.venv/Lib/site-packages/pydantic_core-2.41.5.dist-info/METADATA create mode 100644 backend/.venv/Lib/site-packages/pydantic_core-2.41.5.dist-info/RECORD create mode 100644 backend/.venv/Lib/site-packages/pydantic_core-2.41.5.dist-info/WHEEL create mode 100644 backend/.venv/Lib/site-packages/pydantic_core-2.41.5.dist-info/licenses/LICENSE create mode 100644 backend/.venv/Lib/site-packages/pydantic_core/__init__.py create mode 100644 backend/.venv/Lib/site-packages/pydantic_core/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic_core/__pycache__/core_schema.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/pydantic_core/_pydantic_core.cp312-win_amd64.pyd create mode 100644 backend/.venv/Lib/site-packages/pydantic_core/_pydantic_core.pyi create mode 100644 backend/.venv/Lib/site-packages/pydantic_core/core_schema.py create mode 100644 backend/.venv/Lib/site-packages/pydantic_core/py.typed create mode 100644 backend/.venv/Lib/site-packages/python_dotenv-1.2.1.dist-info/INSTALLER create mode 100644 backend/.venv/Lib/site-packages/python_dotenv-1.2.1.dist-info/METADATA create mode 100644 backend/.venv/Lib/site-packages/python_dotenv-1.2.1.dist-info/RECORD create mode 100644 backend/.venv/Lib/site-packages/python_dotenv-1.2.1.dist-info/WHEEL create mode 100644 backend/.venv/Lib/site-packages/python_dotenv-1.2.1.dist-info/entry_points.txt create mode 100644 backend/.venv/Lib/site-packages/python_dotenv-1.2.1.dist-info/licenses/LICENSE create mode 100644 backend/.venv/Lib/site-packages/python_dotenv-1.2.1.dist-info/top_level.txt create mode 100644 backend/.venv/Lib/site-packages/pyyaml-6.0.3.dist-info/INSTALLER create mode 100644 backend/.venv/Lib/site-packages/pyyaml-6.0.3.dist-info/METADATA create mode 100644 backend/.venv/Lib/site-packages/pyyaml-6.0.3.dist-info/RECORD create mode 100644 backend/.venv/Lib/site-packages/pyyaml-6.0.3.dist-info/WHEEL create mode 100644 backend/.venv/Lib/site-packages/pyyaml-6.0.3.dist-info/licenses/LICENSE create mode 100644 backend/.venv/Lib/site-packages/pyyaml-6.0.3.dist-info/top_level.txt create mode 100644 backend/.venv/Lib/site-packages/starlette-0.41.3.dist-info/INSTALLER create mode 100644 backend/.venv/Lib/site-packages/starlette-0.41.3.dist-info/METADATA create mode 100644 backend/.venv/Lib/site-packages/starlette-0.41.3.dist-info/RECORD create mode 100644 backend/.venv/Lib/site-packages/starlette-0.41.3.dist-info/WHEEL create mode 100644 backend/.venv/Lib/site-packages/starlette-0.41.3.dist-info/licenses/LICENSE.md create mode 100644 backend/.venv/Lib/site-packages/starlette/__init__.py create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/_compat.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/_exception_handler.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/_utils.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/applications.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/authentication.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/background.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/concurrency.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/config.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/convertors.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/datastructures.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/endpoints.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/exceptions.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/formparsers.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/requests.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/responses.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/routing.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/schemas.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/staticfiles.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/status.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/templating.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/testclient.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/types.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/__pycache__/websockets.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/_compat.py create mode 100644 backend/.venv/Lib/site-packages/starlette/_exception_handler.py create mode 100644 backend/.venv/Lib/site-packages/starlette/_utils.py create mode 100644 backend/.venv/Lib/site-packages/starlette/applications.py create mode 100644 backend/.venv/Lib/site-packages/starlette/authentication.py create mode 100644 backend/.venv/Lib/site-packages/starlette/background.py create mode 100644 backend/.venv/Lib/site-packages/starlette/concurrency.py create mode 100644 backend/.venv/Lib/site-packages/starlette/config.py create mode 100644 backend/.venv/Lib/site-packages/starlette/convertors.py create mode 100644 backend/.venv/Lib/site-packages/starlette/datastructures.py create mode 100644 backend/.venv/Lib/site-packages/starlette/endpoints.py create mode 100644 backend/.venv/Lib/site-packages/starlette/exceptions.py create mode 100644 backend/.venv/Lib/site-packages/starlette/formparsers.py create mode 100644 backend/.venv/Lib/site-packages/starlette/middleware/__init__.py create mode 100644 backend/.venv/Lib/site-packages/starlette/middleware/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/middleware/__pycache__/authentication.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/middleware/__pycache__/base.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/middleware/__pycache__/cors.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/middleware/__pycache__/errors.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/middleware/__pycache__/exceptions.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/middleware/__pycache__/gzip.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/middleware/__pycache__/httpsredirect.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/middleware/__pycache__/sessions.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/middleware/__pycache__/trustedhost.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/middleware/__pycache__/wsgi.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/starlette/middleware/authentication.py create mode 100644 backend/.venv/Lib/site-packages/starlette/middleware/base.py create mode 100644 backend/.venv/Lib/site-packages/starlette/middleware/cors.py create mode 100644 backend/.venv/Lib/site-packages/starlette/middleware/errors.py create mode 100644 backend/.venv/Lib/site-packages/starlette/middleware/exceptions.py create mode 100644 backend/.venv/Lib/site-packages/starlette/middleware/gzip.py create mode 100644 backend/.venv/Lib/site-packages/starlette/middleware/httpsredirect.py create mode 100644 backend/.venv/Lib/site-packages/starlette/middleware/sessions.py create mode 100644 backend/.venv/Lib/site-packages/starlette/middleware/trustedhost.py create mode 100644 backend/.venv/Lib/site-packages/starlette/middleware/wsgi.py create mode 100644 backend/.venv/Lib/site-packages/starlette/py.typed create mode 100644 backend/.venv/Lib/site-packages/starlette/requests.py create mode 100644 backend/.venv/Lib/site-packages/starlette/responses.py create mode 100644 backend/.venv/Lib/site-packages/starlette/routing.py create mode 100644 backend/.venv/Lib/site-packages/starlette/schemas.py create mode 100644 backend/.venv/Lib/site-packages/starlette/staticfiles.py create mode 100644 backend/.venv/Lib/site-packages/starlette/status.py create mode 100644 backend/.venv/Lib/site-packages/starlette/templating.py create mode 100644 backend/.venv/Lib/site-packages/starlette/testclient.py create mode 100644 backend/.venv/Lib/site-packages/starlette/types.py create mode 100644 backend/.venv/Lib/site-packages/starlette/websockets.py create mode 100644 backend/.venv/Lib/site-packages/typing_extensions-4.15.0.dist-info/INSTALLER create mode 100644 backend/.venv/Lib/site-packages/typing_extensions-4.15.0.dist-info/METADATA create mode 100644 backend/.venv/Lib/site-packages/typing_extensions-4.15.0.dist-info/RECORD create mode 100644 backend/.venv/Lib/site-packages/typing_extensions-4.15.0.dist-info/WHEEL create mode 100644 backend/.venv/Lib/site-packages/typing_extensions-4.15.0.dist-info/licenses/LICENSE create mode 100644 backend/.venv/Lib/site-packages/typing_extensions.py create mode 100644 backend/.venv/Lib/site-packages/typing_inspection-0.4.2.dist-info/INSTALLER create mode 100644 backend/.venv/Lib/site-packages/typing_inspection-0.4.2.dist-info/METADATA create mode 100644 backend/.venv/Lib/site-packages/typing_inspection-0.4.2.dist-info/RECORD create mode 100644 backend/.venv/Lib/site-packages/typing_inspection-0.4.2.dist-info/WHEEL create mode 100644 backend/.venv/Lib/site-packages/typing_inspection-0.4.2.dist-info/licenses/LICENSE create mode 100644 backend/.venv/Lib/site-packages/typing_inspection/__init__.py create mode 100644 backend/.venv/Lib/site-packages/typing_inspection/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/typing_inspection/__pycache__/introspection.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/typing_inspection/__pycache__/typing_objects.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/typing_inspection/introspection.py create mode 100644 backend/.venv/Lib/site-packages/typing_inspection/py.typed create mode 100644 backend/.venv/Lib/site-packages/typing_inspection/typing_objects.py create mode 100644 backend/.venv/Lib/site-packages/typing_inspection/typing_objects.pyi create mode 100644 backend/.venv/Lib/site-packages/tzdata-2025.2.dist-info/INSTALLER create mode 100644 backend/.venv/Lib/site-packages/tzdata-2025.2.dist-info/METADATA create mode 100644 backend/.venv/Lib/site-packages/tzdata-2025.2.dist-info/RECORD create mode 100644 backend/.venv/Lib/site-packages/tzdata-2025.2.dist-info/WHEEL create mode 100644 backend/.venv/Lib/site-packages/tzdata-2025.2.dist-info/licenses/LICENSE create mode 100644 backend/.venv/Lib/site-packages/tzdata-2025.2.dist-info/licenses/licenses/LICENSE_APACHE create mode 100644 backend/.venv/Lib/site-packages/tzdata-2025.2.dist-info/top_level.txt create mode 100644 backend/.venv/Lib/site-packages/tzdata/__init__.py create mode 100644 backend/.venv/Lib/site-packages/tzdata/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Abidjan create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Accra create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Addis_Ababa create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Algiers create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Asmara create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Asmera create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Bamako create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Bangui create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Banjul create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Bissau create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Blantyre create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Brazzaville create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Bujumbura create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Cairo create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Casablanca create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Ceuta create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Conakry create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Dakar create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Dar_es_Salaam create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Djibouti create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Douala create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/El_Aaiun create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Freetown create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Gaborone create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Harare create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Johannesburg create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Juba create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Kampala create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Khartoum create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Kigali create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Kinshasa create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Lagos create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Libreville create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Lome create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Luanda create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Lubumbashi create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Lusaka create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Malabo create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Maputo create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Maseru create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Mbabane create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Mogadishu create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Monrovia create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Nairobi create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Ndjamena create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Niamey create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Nouakchott create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Ouagadougou create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Porto-Novo create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Sao_Tome create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Timbuktu create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Tripoli create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Tunis create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/Windhoek create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/__init__.py create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Africa/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Adak create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Anchorage create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Anguilla create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Antigua create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Araguaina create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Buenos_Aires create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Catamarca create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/ComodRivadavia create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Cordoba create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Jujuy create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/La_Rioja create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Mendoza create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Rio_Gallegos create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Salta create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/San_Juan create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/San_Luis create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Tucuman create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Ushuaia create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/__init__.py create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Aruba create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Asuncion create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Atikokan create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Atka create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Bahia create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Bahia_Banderas create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Barbados create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Belem create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Belize create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Blanc-Sablon create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Boa_Vista create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Bogota create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Boise create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Buenos_Aires create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Cambridge_Bay create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Campo_Grande create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Cancun create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Caracas create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Catamarca create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Cayenne create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Cayman create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Chicago create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Chihuahua create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Ciudad_Juarez create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Coral_Harbour create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Cordoba create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Costa_Rica create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Coyhaique create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Creston create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Cuiaba create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Curacao create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Danmarkshavn create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Dawson create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Dawson_Creek create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Denver create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Detroit create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Dominica create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Edmonton create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Eirunepe create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/El_Salvador create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Ensenada create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Fort_Nelson create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Fort_Wayne create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Fortaleza create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Glace_Bay create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Godthab create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Goose_Bay create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Grand_Turk create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Grenada create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Guadeloupe create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Guatemala create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Guayaquil create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Guyana create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Halifax create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Havana create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Hermosillo create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Indianapolis create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Knox create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Marengo create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Petersburg create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Tell_City create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Vevay create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Vincennes create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Winamac create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/__init__.py create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Indianapolis create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Inuvik create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Iqaluit create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Jamaica create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Jujuy create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Juneau create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Kentucky/Louisville create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Kentucky/Monticello create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Kentucky/__init__.py create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Kentucky/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Knox_IN create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Kralendijk create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/La_Paz create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Lima create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Los_Angeles create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Louisville create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Lower_Princes create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Maceio create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Managua create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Manaus create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Marigot create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Martinique create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Matamoros create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Mazatlan create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Mendoza create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Menominee create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Merida create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Metlakatla create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Mexico_City create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Miquelon create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Moncton create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Monterrey create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Montevideo create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Montreal create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Montserrat create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Nassau create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/New_York create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Nipigon create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Nome create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Noronha create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/North_Dakota/Beulah create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/North_Dakota/Center create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/North_Dakota/New_Salem create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/North_Dakota/__init__.py create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/North_Dakota/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Nuuk create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Ojinaga create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Panama create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Pangnirtung create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Paramaribo create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Phoenix create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Port-au-Prince create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Port_of_Spain create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Porto_Acre create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Porto_Velho create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Puerto_Rico create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Punta_Arenas create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Rainy_River create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Rankin_Inlet create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Recife create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Regina create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Resolute create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Rio_Branco create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Rosario create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Santa_Isabel create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Santarem create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Santiago create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Santo_Domingo create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Sao_Paulo create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Scoresbysund create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Shiprock create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Sitka create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/St_Barthelemy create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/St_Johns create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/St_Kitts create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/St_Lucia create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/St_Thomas create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/St_Vincent create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Swift_Current create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Tegucigalpa create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Thule create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Thunder_Bay create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Tijuana create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Toronto create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Tortola create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Vancouver create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Virgin create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Whitehorse create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Winnipeg create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Yakutat create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/Yellowknife create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/__init__.py create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/America/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Casey create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Davis create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/DumontDUrville create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Macquarie create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Mawson create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/McMurdo create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Palmer create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Rothera create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/South_Pole create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Syowa create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Troll create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Vostok create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/__init__.py create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Arctic/Longyearbyen create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Arctic/__init__.py create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Arctic/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Aden create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Almaty create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Amman create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Anadyr create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Aqtau create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Aqtobe create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Ashgabat create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Ashkhabad create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Atyrau create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Baghdad create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Bahrain create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Baku create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Bangkok create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Barnaul create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Beirut create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Bishkek create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Brunei create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Calcutta create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Chita create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Choibalsan create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Chongqing create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Chungking create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Colombo create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Dacca create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Damascus create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Dhaka create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Dili create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Dubai create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Dushanbe create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Famagusta create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Gaza create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Harbin create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Hebron create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Ho_Chi_Minh create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Hong_Kong create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Hovd create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Irkutsk create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Istanbul create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Jakarta create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Jayapura create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Jerusalem create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kabul create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kamchatka create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Karachi create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kashgar create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kathmandu create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Katmandu create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Khandyga create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kolkata create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Krasnoyarsk create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kuala_Lumpur create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kuching create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kuwait create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Macao create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Macau create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Magadan create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Makassar create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Manila create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Muscat create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Nicosia create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Novokuznetsk create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Novosibirsk create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Omsk create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Oral create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Phnom_Penh create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Pontianak create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Pyongyang create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Qatar create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Qostanay create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Qyzylorda create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Rangoon create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Riyadh create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Saigon create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Sakhalin create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Samarkand create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Seoul create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Shanghai create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Singapore create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Srednekolymsk create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Taipei create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Tashkent create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Tbilisi create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Tehran create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Tel_Aviv create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Thimbu create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Thimphu create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Tokyo create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Tomsk create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Ujung_Pandang create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Ulaanbaatar create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Ulan_Bator create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Urumqi create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Ust-Nera create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Vientiane create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Vladivostok create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Yakutsk create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Yangon create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Yekaterinburg create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/Yerevan create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/__init__.py create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Asia/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Azores create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Bermuda create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Canary create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Cape_Verde create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Faeroe create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Faroe create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Jan_Mayen create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Madeira create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Reykjavik create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/South_Georgia create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/St_Helena create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Stanley create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/__init__.py create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/ACT create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/Adelaide create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/Brisbane create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/Broken_Hill create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/Canberra create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/Currie create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/Darwin create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/Eucla create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/Hobart create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/LHI create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/Lindeman create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/Lord_Howe create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/Melbourne create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/NSW create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/North create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/Perth create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/Queensland create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/South create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/Sydney create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/Tasmania create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/Victoria create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/West create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/Yancowinna create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/__init__.py create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Australia/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Brazil/Acre create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Brazil/DeNoronha create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Brazil/East create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Brazil/West create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Brazil/__init__.py create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Brazil/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/CET create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/CST6CDT create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Canada/Atlantic create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Canada/Central create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Canada/Eastern create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Canada/Mountain create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Canada/Newfoundland create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Canada/Pacific create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Canada/Saskatchewan create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Canada/Yukon create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Canada/__init__.py create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Canada/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Chile/Continental create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Chile/EasterIsland create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Chile/__init__.py create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Chile/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Cuba create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/EET create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/EST create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/EST5EDT create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Egypt create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Eire create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+0 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+1 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+10 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+11 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+12 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+2 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+3 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+4 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+5 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+6 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+7 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+8 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+9 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-0 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-1 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-10 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-11 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-12 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-13 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-14 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-2 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-3 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-4 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-5 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-6 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-7 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-8 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-9 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT0 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/Greenwich create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/UCT create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/UTC create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/Universal create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/Zulu create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/__init__.py create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Etc/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Amsterdam create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Andorra create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Astrakhan create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Athens create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Belfast create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Belgrade create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Berlin create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Bratislava create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Brussels create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Bucharest create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Budapest create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Busingen create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Chisinau create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Copenhagen create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Dublin create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Gibraltar create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Guernsey create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Helsinki create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Isle_of_Man create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Istanbul create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Jersey create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Kaliningrad create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Kiev create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Kirov create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Kyiv create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Lisbon create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Ljubljana create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/London create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Luxembourg create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Madrid create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Malta create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Mariehamn create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Minsk create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Monaco create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Moscow create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Nicosia create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Oslo create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Paris create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Podgorica create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Prague create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Riga create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Rome create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Samara create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/San_Marino create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Sarajevo create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Saratov create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Simferopol create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Skopje create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Sofia create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Stockholm create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Tallinn create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Tirane create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Tiraspol create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Ulyanovsk create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Uzhgorod create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Vaduz create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Vatican create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Vienna create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Vilnius create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Volgograd create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Warsaw create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Zagreb create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Zaporozhye create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/Zurich create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/__init__.py create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Europe/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Factory create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/GB create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/GB-Eire create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/GMT create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/GMT+0 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/GMT-0 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/GMT0 create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Greenwich create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/HST create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Hongkong create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Iceland create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Indian/Antananarivo create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Indian/Chagos create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Indian/Christmas create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Indian/Cocos create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Indian/Comoro create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Indian/Kerguelen create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Indian/Mahe create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Indian/Maldives create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Indian/Mauritius create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Indian/Mayotte create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Indian/Reunion create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Indian/__init__.py create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Indian/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Iran create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Israel create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Jamaica create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Japan create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Kwajalein create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Libya create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/MET create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/MST create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/MST7MDT create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Mexico/BajaNorte create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Mexico/BajaSur create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Mexico/General create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Mexico/__init__.py create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Mexico/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/NZ create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/NZ-CHAT create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Navajo create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/PRC create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/PST8PDT create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Apia create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Auckland create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Bougainville create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Chatham create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Chuuk create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Easter create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Efate create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Enderbury create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Fakaofo create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Fiji create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Funafuti create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Galapagos create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Gambier create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Guadalcanal create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Guam create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Honolulu create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Johnston create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Kanton create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Kiritimati create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Kosrae create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Kwajalein create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Majuro create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Marquesas create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Midway create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Nauru create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Niue create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Norfolk create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Noumea create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Pago_Pago create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Palau create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Pitcairn create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Pohnpei create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Ponape create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Port_Moresby create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Rarotonga create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Saipan create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Samoa create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Tahiti create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Tarawa create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Tongatapu create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Truk create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Wake create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Wallis create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Yap create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/__init__.py create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Pacific/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Poland create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Portugal create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/ROC create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/ROK create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Singapore create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Turkey create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/UCT create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/US/Alaska create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/US/Aleutian create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/US/Arizona create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/US/Central create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/US/East-Indiana create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/US/Eastern create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/US/Hawaii create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/US/Indiana-Starke create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/US/Michigan create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/US/Mountain create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/US/Pacific create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/US/Samoa create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/US/__init__.py create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/US/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/UTC create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Universal create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/W-SU create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/WET create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/Zulu create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/__init__.py create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/iso3166.tab create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/leapseconds create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/tzdata.zi create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/zone.tab create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/zone1970.tab create mode 100644 backend/.venv/Lib/site-packages/tzdata/zoneinfo/zonenow.tab create mode 100644 backend/.venv/Lib/site-packages/tzdata/zones create mode 100644 backend/.venv/Lib/site-packages/uvicorn-0.32.1.dist-info/INSTALLER create mode 100644 backend/.venv/Lib/site-packages/uvicorn-0.32.1.dist-info/METADATA create mode 100644 backend/.venv/Lib/site-packages/uvicorn-0.32.1.dist-info/RECORD create mode 100644 backend/.venv/Lib/site-packages/uvicorn-0.32.1.dist-info/REQUESTED create mode 100644 backend/.venv/Lib/site-packages/uvicorn-0.32.1.dist-info/WHEEL create mode 100644 backend/.venv/Lib/site-packages/uvicorn-0.32.1.dist-info/entry_points.txt create mode 100644 backend/.venv/Lib/site-packages/uvicorn-0.32.1.dist-info/licenses/LICENSE.md create mode 100644 backend/.venv/Lib/site-packages/uvicorn/__init__.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/__main__.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/__pycache__/__main__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/__pycache__/_subprocess.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/__pycache__/_types.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/__pycache__/config.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/__pycache__/importer.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/__pycache__/logging.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/__pycache__/main.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/__pycache__/server.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/__pycache__/workers.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/_subprocess.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/_types.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/config.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/importer.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/lifespan/__init__.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/lifespan/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/lifespan/__pycache__/off.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/lifespan/__pycache__/on.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/lifespan/off.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/lifespan/on.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/logging.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/loops/__init__.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/loops/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/loops/__pycache__/asyncio.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/loops/__pycache__/auto.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/loops/__pycache__/uvloop.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/loops/asyncio.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/loops/auto.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/loops/uvloop.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/main.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/middleware/__init__.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/middleware/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/middleware/__pycache__/asgi2.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/middleware/__pycache__/message_logger.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/middleware/__pycache__/proxy_headers.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/middleware/__pycache__/wsgi.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/middleware/asgi2.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/middleware/message_logger.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/middleware/proxy_headers.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/middleware/wsgi.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/protocols/__init__.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/protocols/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/protocols/__pycache__/utils.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/protocols/http/__init__.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/protocols/http/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/protocols/http/__pycache__/auto.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/protocols/http/__pycache__/flow_control.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/protocols/http/__pycache__/h11_impl.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/protocols/http/__pycache__/httptools_impl.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/protocols/http/auto.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/protocols/http/flow_control.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/protocols/http/h11_impl.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/protocols/http/httptools_impl.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/protocols/utils.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/protocols/websockets/__init__.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/protocols/websockets/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/protocols/websockets/__pycache__/auto.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/protocols/websockets/__pycache__/websockets_impl.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/protocols/websockets/__pycache__/wsproto_impl.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/protocols/websockets/auto.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/protocols/websockets/websockets_impl.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/protocols/websockets/wsproto_impl.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/py.typed create mode 100644 backend/.venv/Lib/site-packages/uvicorn/server.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/supervisors/__init__.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/supervisors/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/supervisors/__pycache__/basereload.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/supervisors/__pycache__/multiprocess.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/supervisors/__pycache__/statreload.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/supervisors/__pycache__/watchfilesreload.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/supervisors/__pycache__/watchgodreload.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/uvicorn/supervisors/basereload.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/supervisors/multiprocess.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/supervisors/statreload.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/supervisors/watchfilesreload.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/supervisors/watchgodreload.py create mode 100644 backend/.venv/Lib/site-packages/uvicorn/workers.py create mode 100644 backend/.venv/Lib/site-packages/watchfiles-1.1.1.dist-info/INSTALLER create mode 100644 backend/.venv/Lib/site-packages/watchfiles-1.1.1.dist-info/METADATA create mode 100644 backend/.venv/Lib/site-packages/watchfiles-1.1.1.dist-info/RECORD create mode 100644 backend/.venv/Lib/site-packages/watchfiles-1.1.1.dist-info/WHEEL create mode 100644 backend/.venv/Lib/site-packages/watchfiles-1.1.1.dist-info/entry_points.txt create mode 100644 backend/.venv/Lib/site-packages/watchfiles-1.1.1.dist-info/licenses/LICENSE create mode 100644 backend/.venv/Lib/site-packages/watchfiles/__init__.py create mode 100644 backend/.venv/Lib/site-packages/watchfiles/__main__.py create mode 100644 backend/.venv/Lib/site-packages/watchfiles/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/watchfiles/__pycache__/__main__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/watchfiles/__pycache__/cli.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/watchfiles/__pycache__/filters.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/watchfiles/__pycache__/main.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/watchfiles/__pycache__/run.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/watchfiles/__pycache__/version.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/watchfiles/_rust_notify.cp312-win_amd64.pyd create mode 100644 backend/.venv/Lib/site-packages/watchfiles/_rust_notify.pyi create mode 100644 backend/.venv/Lib/site-packages/watchfiles/cli.py create mode 100644 backend/.venv/Lib/site-packages/watchfiles/filters.py create mode 100644 backend/.venv/Lib/site-packages/watchfiles/main.py create mode 100644 backend/.venv/Lib/site-packages/watchfiles/py.typed create mode 100644 backend/.venv/Lib/site-packages/watchfiles/run.py create mode 100644 backend/.venv/Lib/site-packages/watchfiles/version.py create mode 100644 backend/.venv/Lib/site-packages/websockets-15.0.1.dist-info/INSTALLER create mode 100644 backend/.venv/Lib/site-packages/websockets-15.0.1.dist-info/LICENSE create mode 100644 backend/.venv/Lib/site-packages/websockets-15.0.1.dist-info/METADATA create mode 100644 backend/.venv/Lib/site-packages/websockets-15.0.1.dist-info/RECORD create mode 100644 backend/.venv/Lib/site-packages/websockets-15.0.1.dist-info/WHEEL create mode 100644 backend/.venv/Lib/site-packages/websockets-15.0.1.dist-info/entry_points.txt create mode 100644 backend/.venv/Lib/site-packages/websockets-15.0.1.dist-info/top_level.txt create mode 100644 backend/.venv/Lib/site-packages/websockets/__init__.py create mode 100644 backend/.venv/Lib/site-packages/websockets/__main__.py create mode 100644 backend/.venv/Lib/site-packages/websockets/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/__pycache__/__main__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/__pycache__/auth.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/__pycache__/cli.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/__pycache__/client.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/__pycache__/connection.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/__pycache__/datastructures.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/__pycache__/exceptions.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/__pycache__/frames.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/__pycache__/headers.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/__pycache__/http.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/__pycache__/http11.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/__pycache__/imports.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/__pycache__/protocol.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/__pycache__/server.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/__pycache__/streams.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/__pycache__/typing.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/__pycache__/uri.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/__pycache__/utils.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/__pycache__/version.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/asyncio/__init__.py create mode 100644 backend/.venv/Lib/site-packages/websockets/asyncio/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/asyncio/__pycache__/async_timeout.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/asyncio/__pycache__/client.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/asyncio/__pycache__/compatibility.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/asyncio/__pycache__/connection.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/asyncio/__pycache__/messages.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/asyncio/__pycache__/router.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/asyncio/__pycache__/server.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/asyncio/async_timeout.py create mode 100644 backend/.venv/Lib/site-packages/websockets/asyncio/client.py create mode 100644 backend/.venv/Lib/site-packages/websockets/asyncio/compatibility.py create mode 100644 backend/.venv/Lib/site-packages/websockets/asyncio/connection.py create mode 100644 backend/.venv/Lib/site-packages/websockets/asyncio/messages.py create mode 100644 backend/.venv/Lib/site-packages/websockets/asyncio/router.py create mode 100644 backend/.venv/Lib/site-packages/websockets/asyncio/server.py create mode 100644 backend/.venv/Lib/site-packages/websockets/auth.py create mode 100644 backend/.venv/Lib/site-packages/websockets/cli.py create mode 100644 backend/.venv/Lib/site-packages/websockets/client.py create mode 100644 backend/.venv/Lib/site-packages/websockets/connection.py create mode 100644 backend/.venv/Lib/site-packages/websockets/datastructures.py create mode 100644 backend/.venv/Lib/site-packages/websockets/exceptions.py create mode 100644 backend/.venv/Lib/site-packages/websockets/extensions/__init__.py create mode 100644 backend/.venv/Lib/site-packages/websockets/extensions/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/extensions/__pycache__/base.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/extensions/__pycache__/permessage_deflate.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/extensions/base.py create mode 100644 backend/.venv/Lib/site-packages/websockets/extensions/permessage_deflate.py create mode 100644 backend/.venv/Lib/site-packages/websockets/frames.py create mode 100644 backend/.venv/Lib/site-packages/websockets/headers.py create mode 100644 backend/.venv/Lib/site-packages/websockets/http.py create mode 100644 backend/.venv/Lib/site-packages/websockets/http11.py create mode 100644 backend/.venv/Lib/site-packages/websockets/imports.py create mode 100644 backend/.venv/Lib/site-packages/websockets/legacy/__init__.py create mode 100644 backend/.venv/Lib/site-packages/websockets/legacy/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/legacy/__pycache__/auth.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/legacy/__pycache__/client.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/legacy/__pycache__/exceptions.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/legacy/__pycache__/framing.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/legacy/__pycache__/handshake.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/legacy/__pycache__/http.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/legacy/__pycache__/protocol.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/legacy/__pycache__/server.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/legacy/auth.py create mode 100644 backend/.venv/Lib/site-packages/websockets/legacy/client.py create mode 100644 backend/.venv/Lib/site-packages/websockets/legacy/exceptions.py create mode 100644 backend/.venv/Lib/site-packages/websockets/legacy/framing.py create mode 100644 backend/.venv/Lib/site-packages/websockets/legacy/handshake.py create mode 100644 backend/.venv/Lib/site-packages/websockets/legacy/http.py create mode 100644 backend/.venv/Lib/site-packages/websockets/legacy/protocol.py create mode 100644 backend/.venv/Lib/site-packages/websockets/legacy/server.py create mode 100644 backend/.venv/Lib/site-packages/websockets/protocol.py create mode 100644 backend/.venv/Lib/site-packages/websockets/py.typed create mode 100644 backend/.venv/Lib/site-packages/websockets/server.py create mode 100644 backend/.venv/Lib/site-packages/websockets/speedups.c create mode 100644 backend/.venv/Lib/site-packages/websockets/speedups.cp312-win_amd64.pyd create mode 100644 backend/.venv/Lib/site-packages/websockets/speedups.pyi create mode 100644 backend/.venv/Lib/site-packages/websockets/streams.py create mode 100644 backend/.venv/Lib/site-packages/websockets/sync/__init__.py create mode 100644 backend/.venv/Lib/site-packages/websockets/sync/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/sync/__pycache__/client.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/sync/__pycache__/connection.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/sync/__pycache__/messages.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/sync/__pycache__/router.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/sync/__pycache__/server.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/sync/__pycache__/utils.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/websockets/sync/client.py create mode 100644 backend/.venv/Lib/site-packages/websockets/sync/connection.py create mode 100644 backend/.venv/Lib/site-packages/websockets/sync/messages.py create mode 100644 backend/.venv/Lib/site-packages/websockets/sync/router.py create mode 100644 backend/.venv/Lib/site-packages/websockets/sync/server.py create mode 100644 backend/.venv/Lib/site-packages/websockets/sync/utils.py create mode 100644 backend/.venv/Lib/site-packages/websockets/typing.py create mode 100644 backend/.venv/Lib/site-packages/websockets/uri.py create mode 100644 backend/.venv/Lib/site-packages/websockets/utils.py create mode 100644 backend/.venv/Lib/site-packages/websockets/version.py create mode 100644 backend/.venv/Lib/site-packages/yaml/__init__.py create mode 100644 backend/.venv/Lib/site-packages/yaml/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/yaml/__pycache__/composer.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/yaml/__pycache__/constructor.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/yaml/__pycache__/cyaml.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/yaml/__pycache__/dumper.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/yaml/__pycache__/emitter.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/yaml/__pycache__/error.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/yaml/__pycache__/events.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/yaml/__pycache__/loader.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/yaml/__pycache__/nodes.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/yaml/__pycache__/parser.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/yaml/__pycache__/reader.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/yaml/__pycache__/representer.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/yaml/__pycache__/resolver.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/yaml/__pycache__/scanner.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/yaml/__pycache__/serializer.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/yaml/__pycache__/tokens.cpython-312.pyc create mode 100644 backend/.venv/Lib/site-packages/yaml/_yaml.cp312-win_amd64.pyd create mode 100644 backend/.venv/Lib/site-packages/yaml/composer.py create mode 100644 backend/.venv/Lib/site-packages/yaml/constructor.py create mode 100644 backend/.venv/Lib/site-packages/yaml/cyaml.py create mode 100644 backend/.venv/Lib/site-packages/yaml/dumper.py create mode 100644 backend/.venv/Lib/site-packages/yaml/emitter.py create mode 100644 backend/.venv/Lib/site-packages/yaml/error.py create mode 100644 backend/.venv/Lib/site-packages/yaml/events.py create mode 100644 backend/.venv/Lib/site-packages/yaml/loader.py create mode 100644 backend/.venv/Lib/site-packages/yaml/nodes.py create mode 100644 backend/.venv/Lib/site-packages/yaml/parser.py create mode 100644 backend/.venv/Lib/site-packages/yaml/reader.py create mode 100644 backend/.venv/Lib/site-packages/yaml/representer.py create mode 100644 backend/.venv/Lib/site-packages/yaml/resolver.py create mode 100644 backend/.venv/Lib/site-packages/yaml/scanner.py create mode 100644 backend/.venv/Lib/site-packages/yaml/serializer.py create mode 100644 backend/.venv/Lib/site-packages/yaml/tokens.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/fastapi.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/Scripts/uvicorn.exe create mode 100644 backend/.venv/Scripts/watchfiles.exe create mode 100644 backend/.venv/Scripts/websockets.exe create mode 100644 backend/.venv/pyvenv.cfg create mode 100644 backend/app/__init__.py create mode 100644 backend/app/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/app/__pycache__/main.cpython-312.pyc create mode 100644 backend/app/common/auth.py create mode 100644 backend/app/common/utils.py create mode 100644 backend/app/core/__init__.py create mode 100644 backend/app/core/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/app/core/__pycache__/database.cpython-312.pyc create mode 100644 backend/app/core/config.py create mode 100644 backend/app/core/database.py create mode 100644 backend/app/main.py create mode 100644 backend/app/modules/__init__.py create mode 100644 backend/app/modules/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/app/modules/accounts/__init__.py create mode 100644 backend/app/modules/accounts/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/app/modules/accounts/__pycache__/router.cpython-312.pyc create mode 100644 backend/app/modules/accounts/router.py create mode 100644 backend/app/modules/journals/__init__.py create mode 100644 backend/app/modules/journals/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/app/modules/journals/__pycache__/router.cpython-312.pyc create mode 100644 backend/app/modules/journals/router.py create mode 100644 backend/app/modules/ledger/__init__.py create mode 100644 backend/app/modules/ledger/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/app/modules/ledger/__pycache__/router.cpython-312.pyc create mode 100644 backend/app/modules/ledger/router.py create mode 100644 backend/app/modules/trial_balance/__init__.py create mode 100644 backend/app/modules/trial_balance/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/app/modules/trial_balance/__pycache__/router.cpython-312.pyc create mode 100644 backend/app/modules/trial_balance/router.py create mode 100644 backend/requirements.txt create mode 100644 docs/api_design.md create mode 100644 docs/db_design.md create mode 100644 scripts/fix_data.py create mode 100644 scripts/import_csv.py diff --git a/.env b/.env new file mode 100644 index 0000000..3b03878 --- /dev/null +++ b/.env @@ -0,0 +1,5 @@ +DB_HOST=192.168.0.61 +DB_PORT=55432 +DB_NAME=njts_acct +DB_USER=njts_app +DB_PASSWORD=njts_app2025 diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..cdefd67 --- /dev/null +++ b/.env.example @@ -0,0 +1,5 @@ +DB_HOST=192.168.0.61 +DB_PORT=55432 +DB_NAME=accounting +DB_USER=accounting123 +DB_PASSWORD=accounting diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..21664bc --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +# ===== Visual Studio ===== +.vs/ +*.user +*.suo +*.userosscache +*.sln.docstates + +# ===== Build output ===== +bin/ +obj/ + +# ===== .NET Core ===== +appsettings.Development.json +appsettings.*.json +secrets.json + +# ===== Logs ===== +*.log +logs/ + +# ===== OS ===== +.DS_Store +Thumbs.db + +# ===== Docker / NAS ===== +docker-data/ +*.bak +*.tmp \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/__pycache__/typing_extensions.cpython-312.pyc b/backend/.venv/Lib/site-packages/__pycache__/typing_extensions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..874be8b1849e63e3a5bdbf464207e0fcb54c485a GIT binary patch literal 163641 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ž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 Bz_tJY literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/_yaml/__init__.py b/backend/.venv/Lib/site-packages/_yaml/__init__.py new file mode 100644 index 0000000..7baa8c4 --- /dev/null +++ b/backend/.venv/Lib/site-packages/_yaml/__init__.py @@ -0,0 +1,33 @@ +# This is a stub package designed to roughly emulate the _yaml +# extension module, which previously existed as a standalone module +# and has been moved into the `yaml` package namespace. +# It does not perfectly mimic its old counterpart, but should get +# close enough for anyone who's relying on it even when they shouldn't. +import yaml + +# in some circumstances, the yaml module we imoprted may be from a different version, so we need +# to tread carefully when poking at it here (it may not have the attributes we expect) +if not getattr(yaml, '__with_libyaml__', False): + from sys import version_info + + exc = ModuleNotFoundError if version_info >= (3, 6) else ImportError + raise exc("No module named '_yaml'") +else: + from yaml._yaml import * + import warnings + warnings.warn( + 'The _yaml extension module is now located at yaml._yaml' + ' and its location is subject to change. To use the' + ' LibYAML-based parser and emitter, import from `yaml`:' + ' `from yaml import CLoader as Loader, CDumper as Dumper`.', + DeprecationWarning + ) + del warnings + # Don't `del yaml` here because yaml is actually an existing + # namespace member of _yaml. + +__name__ = '_yaml' +# If the module is top-level (i.e. not a part of any specific package) +# then the attribute should be set to ''. +# https://docs.python.org/3.8/library/types.html +__package__ = '' diff --git a/backend/.venv/Lib/site-packages/_yaml/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/_yaml/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..696f314f09d38811b1ca4bb0a86569b776781078 GIT binary patch literal 862 zcmYjPzi$&U6t?d!$>mo|Ta^j{k~^hAO*$e~fP_*ikeV)3LZl}-m$RE*dv}g(r)fI1 zEHJY1FMui}M*atu@?)SzNJy}B3n~*6c8&_(VEcRT``&wg_PcVq0JPP-+u=b5fbRxe zn8sr}f3CL|fB*s`&;k~qkOE>6``AtiVot}L$cpWj4FR=DX4eCNThvJ)&9t&wktNw< zn6jTh&CW%+*A`53x-C~T+@0w({{Ko`S~#{+4+NVo$+wE6&?*gKwRmRS>*^B5gHUec zDC`XVIKp_f3RP*3auKowhshSJT4$!wv#eeY=GGaC8RxI<8i!I+zKFuO$GAjWoW-bZinW(fdyEXY2shT4 zPmENc^t6Z?EB&~ay3$j-t}^3B6{wb#W8^B=rP7y@D_aZ&cl2=7OmjS$btYF?KOy%x zXIvE@jN3?oP4@#;_;+#T4t$=3NmnSxoYeFR?QyC{q=)b*4Jj96Gi!`h5#yd8?D|~| zUV(F66a0SISoQ{t?+P8EUa})a%?|=yU+T2AfN|<|w1y_ctMAcd&(nkRL?~(PZz|!9 zueOBsYljl!dT*%QTj?X;;a7AG^YcWgmyr!2JTC!Q`so69@|irDt-PH5lw11hpl|cF zHhS*4=23HG+4&VXazXy;uVOZn X9Zi7zl!m35LsxH;Q%6NUr>p$|)lvo| literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/annotated_types-0.7.0.dist-info/INSTALLER b/backend/.venv/Lib/site-packages/annotated_types-0.7.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/backend/.venv/Lib/site-packages/annotated_types-0.7.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/backend/.venv/Lib/site-packages/annotated_types-0.7.0.dist-info/METADATA b/backend/.venv/Lib/site-packages/annotated_types-0.7.0.dist-info/METADATA new file mode 100644 index 0000000..3ac05cf --- /dev/null +++ b/backend/.venv/Lib/site-packages/annotated_types-0.7.0.dist-info/METADATA @@ -0,0 +1,295 @@ +Metadata-Version: 2.3 +Name: annotated-types +Version: 0.7.0 +Summary: Reusable constraint types to use with typing.Annotated +Project-URL: Homepage, https://github.com/annotated-types/annotated-types +Project-URL: Source, https://github.com/annotated-types/annotated-types +Project-URL: Changelog, https://github.com/annotated-types/annotated-types/releases +Author-email: Adrian Garcia Badaracco <1755071+adriangb@users.noreply.github.com>, Samuel Colvin , Zac Hatfield-Dodds +License-File: LICENSE +Classifier: Development Status :: 4 - Beta +Classifier: Environment :: Console +Classifier: Environment :: MacOS X +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: Information Technology +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: POSIX :: Linux +Classifier: Operating System :: Unix +Classifier: Programming Language :: Python :: 3 :: Only +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: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Typing :: Typed +Requires-Python: >=3.8 +Requires-Dist: typing-extensions>=4.0.0; python_version < '3.9' +Description-Content-Type: text/markdown + +# annotated-types + +[![CI](https://github.com/annotated-types/annotated-types/workflows/CI/badge.svg?event=push)](https://github.com/annotated-types/annotated-types/actions?query=event%3Apush+branch%3Amain+workflow%3ACI) +[![pypi](https://img.shields.io/pypi/v/annotated-types.svg)](https://pypi.python.org/pypi/annotated-types) +[![versions](https://img.shields.io/pypi/pyversions/annotated-types.svg)](https://github.com/annotated-types/annotated-types) +[![license](https://img.shields.io/github/license/annotated-types/annotated-types.svg)](https://github.com/annotated-types/annotated-types/blob/main/LICENSE) + +[PEP-593](https://peps.python.org/pep-0593/) added `typing.Annotated` as a way of +adding context-specific metadata to existing types, and specifies that +`Annotated[T, x]` _should_ be treated as `T` by any tool or library without special +logic for `x`. + +This package provides metadata objects which can be used to represent common +constraints such as upper and lower bounds on scalar values and collection sizes, +a `Predicate` marker for runtime checks, and +descriptions of how we intend these metadata to be interpreted. In some cases, +we also note alternative representations which do not require this package. + +## Install + +```bash +pip install annotated-types +``` + +## Examples + +```python +from typing import Annotated +from annotated_types import Gt, Len, Predicate + +class MyClass: + age: Annotated[int, Gt(18)] # Valid: 19, 20, ... + # Invalid: 17, 18, "19", 19.0, ... + factors: list[Annotated[int, Predicate(is_prime)]] # Valid: 2, 3, 5, 7, 11, ... + # Invalid: 4, 8, -2, 5.0, "prime", ... + + my_list: Annotated[list[int], Len(0, 10)] # Valid: [], [10, 20, 30, 40, 50] + # Invalid: (1, 2), ["abc"], [0] * 20 +``` + +## Documentation + +_While `annotated-types` avoids runtime checks for performance, users should not +construct invalid combinations such as `MultipleOf("non-numeric")` or `Annotated[int, Len(3)]`. +Downstream implementors may choose to raise an error, emit a warning, silently ignore +a metadata item, etc., if the metadata objects described below are used with an +incompatible type - or for any other reason!_ + +### Gt, Ge, Lt, Le + +Express inclusive and/or exclusive bounds on orderable values - which may be numbers, +dates, times, strings, sets, etc. Note that the boundary value need not be of the +same type that was annotated, so long as they can be compared: `Annotated[int, Gt(1.5)]` +is fine, for example, and implies that the value is an integer x such that `x > 1.5`. + +We suggest that implementors may also interpret `functools.partial(operator.le, 1.5)` +as being equivalent to `Gt(1.5)`, for users who wish to avoid a runtime dependency on +the `annotated-types` package. + +To be explicit, these types have the following meanings: + +* `Gt(x)` - value must be "Greater Than" `x` - equivalent to exclusive minimum +* `Ge(x)` - value must be "Greater than or Equal" to `x` - equivalent to inclusive minimum +* `Lt(x)` - value must be "Less Than" `x` - equivalent to exclusive maximum +* `Le(x)` - value must be "Less than or Equal" to `x` - equivalent to inclusive maximum + +### Interval + +`Interval(gt, ge, lt, le)` allows you to specify an upper and lower bound with a single +metadata object. `None` attributes should be ignored, and non-`None` attributes +treated as per the single bounds above. + +### MultipleOf + +`MultipleOf(multiple_of=x)` might be interpreted in two ways: + +1. Python semantics, implying `value % multiple_of == 0`, or +2. [JSONschema semantics](https://json-schema.org/draft/2020-12/json-schema-validation.html#rfc.section.6.2.1), + where `int(value / multiple_of) == value / multiple_of`. + +We encourage users to be aware of these two common interpretations and their +distinct behaviours, especially since very large or non-integer numbers make +it easy to cause silent data corruption due to floating-point imprecision. + +We encourage libraries to carefully document which interpretation they implement. + +### MinLen, MaxLen, Len + +`Len()` implies that `min_length <= len(value) <= max_length` - lower and upper bounds are inclusive. + +As well as `Len()` which can optionally include upper and lower bounds, we also +provide `MinLen(x)` and `MaxLen(y)` which are equivalent to `Len(min_length=x)` +and `Len(max_length=y)` respectively. + +`Len`, `MinLen`, and `MaxLen` may be used with any type which supports `len(value)`. + +Examples of usage: + +* `Annotated[list, MaxLen(10)]` (or `Annotated[list, Len(max_length=10))`) - list must have a length of 10 or less +* `Annotated[str, MaxLen(10)]` - string must have a length of 10 or less +* `Annotated[list, MinLen(3))` (or `Annotated[list, Len(min_length=3))`) - list must have a length of 3 or more +* `Annotated[list, Len(4, 6)]` - list must have a length of 4, 5, or 6 +* `Annotated[list, Len(8, 8)]` - list must have a length of exactly 8 + +#### Changed in v0.4.0 + +* `min_inclusive` has been renamed to `min_length`, no change in meaning +* `max_exclusive` has been renamed to `max_length`, upper bound is now **inclusive** instead of **exclusive** +* The recommendation that slices are interpreted as `Len` has been removed due to ambiguity and different semantic + meaning of the upper bound in slices vs. `Len` + +See [issue #23](https://github.com/annotated-types/annotated-types/issues/23) for discussion. + +### Timezone + +`Timezone` can be used with a `datetime` or a `time` to express which timezones +are allowed. `Annotated[datetime, Timezone(None)]` must be a naive datetime. +`Timezone[...]` ([literal ellipsis](https://docs.python.org/3/library/constants.html#Ellipsis)) +expresses that any timezone-aware datetime is allowed. You may also pass a specific +timezone string or [`tzinfo`](https://docs.python.org/3/library/datetime.html#tzinfo-objects) +object such as `Timezone(timezone.utc)` or `Timezone("Africa/Abidjan")` to express that you only +allow a specific timezone, though we note that this is often a symptom of fragile design. + +#### Changed in v0.x.x + +* `Timezone` accepts [`tzinfo`](https://docs.python.org/3/library/datetime.html#tzinfo-objects) objects instead of + `timezone`, extending compatibility to [`zoneinfo`](https://docs.python.org/3/library/zoneinfo.html) and third party libraries. + +### Unit + +`Unit(unit: str)` expresses that the annotated numeric value is the magnitude of +a quantity with the specified unit. For example, `Annotated[float, Unit("m/s")]` +would be a float representing a velocity in meters per second. + +Please note that `annotated_types` itself makes no attempt to parse or validate +the unit string in any way. That is left entirely to downstream libraries, +such as [`pint`](https://pint.readthedocs.io) or +[`astropy.units`](https://docs.astropy.org/en/stable/units/). + +An example of how a library might use this metadata: + +```python +from annotated_types import Unit +from typing import Annotated, TypeVar, Callable, Any, get_origin, get_args + +# given a type annotated with a unit: +Meters = Annotated[float, Unit("m")] + + +# you can cast the annotation to a specific unit type with any +# callable that accepts a string and returns the desired type +T = TypeVar("T") +def cast_unit(tp: Any, unit_cls: Callable[[str], T]) -> T | None: + if get_origin(tp) is Annotated: + for arg in get_args(tp): + if isinstance(arg, Unit): + return unit_cls(arg.unit) + return None + + +# using `pint` +import pint +pint_unit = cast_unit(Meters, pint.Unit) + + +# using `astropy.units` +import astropy.units as u +astropy_unit = cast_unit(Meters, u.Unit) +``` + +### Predicate + +`Predicate(func: Callable)` expresses that `func(value)` is truthy for valid values. +Users should prefer the statically inspectable metadata above, but if you need +the full power and flexibility of arbitrary runtime predicates... here it is. + +For some common constraints, we provide generic types: + +* `IsLower = Annotated[T, Predicate(str.islower)]` +* `IsUpper = Annotated[T, Predicate(str.isupper)]` +* `IsDigit = Annotated[T, Predicate(str.isdigit)]` +* `IsFinite = Annotated[T, Predicate(math.isfinite)]` +* `IsNotFinite = Annotated[T, Predicate(Not(math.isfinite))]` +* `IsNan = Annotated[T, Predicate(math.isnan)]` +* `IsNotNan = Annotated[T, Predicate(Not(math.isnan))]` +* `IsInfinite = Annotated[T, Predicate(math.isinf)]` +* `IsNotInfinite = Annotated[T, Predicate(Not(math.isinf))]` + +so that you can write e.g. `x: IsFinite[float] = 2.0` instead of the longer +(but exactly equivalent) `x: Annotated[float, Predicate(math.isfinite)] = 2.0`. + +Some libraries might have special logic to handle known or understandable predicates, +for example by checking for `str.isdigit` and using its presence to both call custom +logic to enforce digit-only strings, and customise some generated external schema. +Users are therefore encouraged to avoid indirection like `lambda s: s.lower()`, in +favor of introspectable methods such as `str.lower` or `re.compile("pattern").search`. + +To enable basic negation of commonly used predicates like `math.isnan` without introducing introspection that makes it impossible for implementers to introspect the predicate we provide a `Not` wrapper that simply negates the predicate in an introspectable manner. Several of the predicates listed above are created in this manner. + +We do not specify what behaviour should be expected for predicates that raise +an exception. For example `Annotated[int, Predicate(str.isdigit)]` might silently +skip invalid constraints, or statically raise an error; or it might try calling it +and then propagate or discard the resulting +`TypeError: descriptor 'isdigit' for 'str' objects doesn't apply to a 'int' object` +exception. We encourage libraries to document the behaviour they choose. + +### Doc + +`doc()` can be used to add documentation information in `Annotated`, for function and method parameters, variables, class attributes, return types, and any place where `Annotated` can be used. + +It expects a value that can be statically analyzed, as the main use case is for static analysis, editors, documentation generators, and similar tools. + +It returns a `DocInfo` class with a single attribute `documentation` containing the value passed to `doc()`. + +This is the early adopter's alternative form of the [`typing-doc` proposal](https://github.com/tiangolo/fastapi/blob/typing-doc/typing_doc.md). + +### Integrating downstream types with `GroupedMetadata` + +Implementers may choose to provide a convenience wrapper that groups multiple pieces of metadata. +This can help reduce verbosity and cognitive overhead for users. +For example, an implementer like Pydantic might provide a `Field` or `Meta` type that accepts keyword arguments and transforms these into low-level metadata: + +```python +from dataclasses import dataclass +from typing import Iterator +from annotated_types import GroupedMetadata, Ge + +@dataclass +class Field(GroupedMetadata): + ge: int | None = None + description: str | None = None + + def __iter__(self) -> Iterator[object]: + # Iterating over a GroupedMetadata object should yield annotated-types + # constraint metadata objects which describe it as fully as possible, + # and may include other unknown objects too. + if self.ge is not None: + yield Ge(self.ge) + if self.description is not None: + yield Description(self.description) +``` + +Libraries consuming annotated-types constraints should check for `GroupedMetadata` and unpack it by iterating over the object and treating the results as if they had been "unpacked" in the `Annotated` type. The same logic should be applied to the [PEP 646 `Unpack` type](https://peps.python.org/pep-0646/), so that `Annotated[T, Field(...)]`, `Annotated[T, Unpack[Field(...)]]` and `Annotated[T, *Field(...)]` are all treated consistently. + +Libraries consuming annotated-types should also ignore any metadata they do not recongize that came from unpacking a `GroupedMetadata`, just like they ignore unrecognized metadata in `Annotated` itself. + +Our own `annotated_types.Interval` class is a `GroupedMetadata` which unpacks itself into `Gt`, `Lt`, etc., so this is not an abstract concern. Similarly, `annotated_types.Len` is a `GroupedMetadata` which unpacks itself into `MinLen` (optionally) and `MaxLen`. + +### Consuming metadata + +We intend to not be prescriptive as to _how_ the metadata and constraints are used, but as an example of how one might parse constraints from types annotations see our [implementation in `test_main.py`](https://github.com/annotated-types/annotated-types/blob/f59cf6d1b5255a0fe359b93896759a180bec30ae/tests/test_main.py#L94-L103). + +It is up to the implementer to determine how this metadata is used. +You could use the metadata for runtime type checking, for generating schemas or to generate example data, amongst other use cases. + +## Design & History + +This package was designed at the PyCon 2022 sprints by the maintainers of Pydantic +and Hypothesis, with the goal of making it as easy as possible for end-users to +provide more informative annotations for use by runtime libraries. + +It is deliberately minimal, and following PEP-593 allows considerable downstream +discretion in what (if anything!) they choose to support. Nonetheless, we expect +that staying simple and covering _only_ the most common use-cases will give users +and maintainers the best experience we can. If you'd like more constraints for your +types - follow our lead, by defining them and documenting them downstream! diff --git a/backend/.venv/Lib/site-packages/annotated_types-0.7.0.dist-info/RECORD b/backend/.venv/Lib/site-packages/annotated_types-0.7.0.dist-info/RECORD new file mode 100644 index 0000000..7045729 --- /dev/null +++ b/backend/.venv/Lib/site-packages/annotated_types-0.7.0.dist-info/RECORD @@ -0,0 +1,10 @@ +annotated_types-0.7.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +annotated_types-0.7.0.dist-info/METADATA,sha256=7ltqxksJJ0wCYFGBNIQCWTlWQGeAH0hRFdnK3CB895E,15046 +annotated_types-0.7.0.dist-info/RECORD,, +annotated_types-0.7.0.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87 +annotated_types-0.7.0.dist-info/licenses/LICENSE,sha256=_hBJiEsaDZNCkB6I4H8ykl0ksxIdmXK2poBfuYJLCV0,1083 +annotated_types/__init__.py,sha256=RynLsRKUEGI0KimXydlD1fZEfEzWwDo0Uon3zOKhG1Q,13819 +annotated_types/__pycache__/__init__.cpython-312.pyc,, +annotated_types/__pycache__/test_cases.cpython-312.pyc,, +annotated_types/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +annotated_types/test_cases.py,sha256=zHFX6EpcMbGJ8FzBYDbO56bPwx_DYIVSKbZM-4B3_lg,6421 diff --git a/backend/.venv/Lib/site-packages/annotated_types-0.7.0.dist-info/WHEEL b/backend/.venv/Lib/site-packages/annotated_types-0.7.0.dist-info/WHEEL new file mode 100644 index 0000000..516596c --- /dev/null +++ b/backend/.venv/Lib/site-packages/annotated_types-0.7.0.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: hatchling 1.24.2 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/backend/.venv/Lib/site-packages/annotated_types-0.7.0.dist-info/licenses/LICENSE b/backend/.venv/Lib/site-packages/annotated_types-0.7.0.dist-info/licenses/LICENSE new file mode 100644 index 0000000..d99323a --- /dev/null +++ b/backend/.venv/Lib/site-packages/annotated_types-0.7.0.dist-info/licenses/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2022 the contributors + +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/annotated_types/__init__.py b/backend/.venv/Lib/site-packages/annotated_types/__init__.py new file mode 100644 index 0000000..74e0dee --- /dev/null +++ b/backend/.venv/Lib/site-packages/annotated_types/__init__.py @@ -0,0 +1,432 @@ +import math +import sys +import types +from dataclasses import dataclass +from datetime import tzinfo +from typing import TYPE_CHECKING, Any, Callable, Iterator, Optional, SupportsFloat, SupportsIndex, TypeVar, Union + +if sys.version_info < (3, 8): + from typing_extensions import Protocol, runtime_checkable +else: + from typing import Protocol, runtime_checkable + +if sys.version_info < (3, 9): + from typing_extensions import Annotated, Literal +else: + from typing import Annotated, Literal + +if sys.version_info < (3, 10): + EllipsisType = type(Ellipsis) + KW_ONLY = {} + SLOTS = {} +else: + from types import EllipsisType + + KW_ONLY = {"kw_only": True} + SLOTS = {"slots": True} + + +__all__ = ( + 'BaseMetadata', + 'GroupedMetadata', + 'Gt', + 'Ge', + 'Lt', + 'Le', + 'Interval', + 'MultipleOf', + 'MinLen', + 'MaxLen', + 'Len', + 'Timezone', + 'Predicate', + 'LowerCase', + 'UpperCase', + 'IsDigits', + 'IsFinite', + 'IsNotFinite', + 'IsNan', + 'IsNotNan', + 'IsInfinite', + 'IsNotInfinite', + 'doc', + 'DocInfo', + '__version__', +) + +__version__ = '0.7.0' + + +T = TypeVar('T') + + +# arguments that start with __ are considered +# positional only +# see https://peps.python.org/pep-0484/#positional-only-arguments + + +class SupportsGt(Protocol): + def __gt__(self: T, __other: T) -> bool: + ... + + +class SupportsGe(Protocol): + def __ge__(self: T, __other: T) -> bool: + ... + + +class SupportsLt(Protocol): + def __lt__(self: T, __other: T) -> bool: + ... + + +class SupportsLe(Protocol): + def __le__(self: T, __other: T) -> bool: + ... + + +class SupportsMod(Protocol): + def __mod__(self: T, __other: T) -> T: + ... + + +class SupportsDiv(Protocol): + def __div__(self: T, __other: T) -> T: + ... + + +class BaseMetadata: + """Base class for all metadata. + + This exists mainly so that implementers + can do `isinstance(..., BaseMetadata)` while traversing field annotations. + """ + + __slots__ = () + + +@dataclass(frozen=True, **SLOTS) +class Gt(BaseMetadata): + """Gt(gt=x) implies that the value must be greater than x. + + It can be used with any type that supports the ``>`` operator, + including numbers, dates and times, strings, sets, and so on. + """ + + gt: SupportsGt + + +@dataclass(frozen=True, **SLOTS) +class Ge(BaseMetadata): + """Ge(ge=x) implies that the value must be greater than or equal to x. + + It can be used with any type that supports the ``>=`` operator, + including numbers, dates and times, strings, sets, and so on. + """ + + ge: SupportsGe + + +@dataclass(frozen=True, **SLOTS) +class Lt(BaseMetadata): + """Lt(lt=x) implies that the value must be less than x. + + It can be used with any type that supports the ``<`` operator, + including numbers, dates and times, strings, sets, and so on. + """ + + lt: SupportsLt + + +@dataclass(frozen=True, **SLOTS) +class Le(BaseMetadata): + """Le(le=x) implies that the value must be less than or equal to x. + + It can be used with any type that supports the ``<=`` operator, + including numbers, dates and times, strings, sets, and so on. + """ + + le: SupportsLe + + +@runtime_checkable +class GroupedMetadata(Protocol): + """A grouping of multiple objects, like typing.Unpack. + + `GroupedMetadata` on its own is not metadata and has no meaning. + All of the constraints and metadata should be fully expressable + in terms of the `BaseMetadata`'s returned by `GroupedMetadata.__iter__()`. + + Concrete implementations should override `GroupedMetadata.__iter__()` + to add their own metadata. + For example: + + >>> @dataclass + >>> class Field(GroupedMetadata): + >>> gt: float | None = None + >>> description: str | None = None + ... + >>> def __iter__(self) -> Iterable[object]: + >>> if self.gt is not None: + >>> yield Gt(self.gt) + >>> if self.description is not None: + >>> yield Description(self.gt) + + Also see the implementation of `Interval` below for an example. + + Parsers should recognize this and unpack it so that it can be used + both with and without unpacking: + + - `Annotated[int, Field(...)]` (parser must unpack Field) + - `Annotated[int, *Field(...)]` (PEP-646) + """ # noqa: trailing-whitespace + + @property + def __is_annotated_types_grouped_metadata__(self) -> Literal[True]: + return True + + def __iter__(self) -> Iterator[object]: + ... + + if not TYPE_CHECKING: + __slots__ = () # allow subclasses to use slots + + def __init_subclass__(cls, *args: Any, **kwargs: Any) -> None: + # Basic ABC like functionality without the complexity of an ABC + super().__init_subclass__(*args, **kwargs) + if cls.__iter__ is GroupedMetadata.__iter__: + raise TypeError("Can't subclass GroupedMetadata without implementing __iter__") + + def __iter__(self) -> Iterator[object]: # noqa: F811 + raise NotImplementedError # more helpful than "None has no attribute..." type errors + + +@dataclass(frozen=True, **KW_ONLY, **SLOTS) +class Interval(GroupedMetadata): + """Interval can express inclusive or exclusive bounds with a single object. + + It accepts keyword arguments ``gt``, ``ge``, ``lt``, and/or ``le``, which + are interpreted the same way as the single-bound constraints. + """ + + gt: Union[SupportsGt, None] = None + ge: Union[SupportsGe, None] = None + lt: Union[SupportsLt, None] = None + le: Union[SupportsLe, None] = None + + def __iter__(self) -> Iterator[BaseMetadata]: + """Unpack an Interval into zero or more single-bounds.""" + if self.gt is not None: + yield Gt(self.gt) + if self.ge is not None: + yield Ge(self.ge) + if self.lt is not None: + yield Lt(self.lt) + if self.le is not None: + yield Le(self.le) + + +@dataclass(frozen=True, **SLOTS) +class MultipleOf(BaseMetadata): + """MultipleOf(multiple_of=x) might be interpreted in two ways: + + 1. Python semantics, implying ``value % multiple_of == 0``, or + 2. JSONschema semantics, where ``int(value / multiple_of) == value / multiple_of`` + + We encourage users to be aware of these two common interpretations, + and libraries to carefully document which they implement. + """ + + multiple_of: Union[SupportsDiv, SupportsMod] + + +@dataclass(frozen=True, **SLOTS) +class MinLen(BaseMetadata): + """ + MinLen() implies minimum inclusive length, + e.g. ``len(value) >= min_length``. + """ + + min_length: Annotated[int, Ge(0)] + + +@dataclass(frozen=True, **SLOTS) +class MaxLen(BaseMetadata): + """ + MaxLen() implies maximum inclusive length, + e.g. ``len(value) <= max_length``. + """ + + max_length: Annotated[int, Ge(0)] + + +@dataclass(frozen=True, **SLOTS) +class Len(GroupedMetadata): + """ + Len() implies that ``min_length <= len(value) <= max_length``. + + Upper bound may be omitted or ``None`` to indicate no upper length bound. + """ + + min_length: Annotated[int, Ge(0)] = 0 + max_length: Optional[Annotated[int, Ge(0)]] = None + + def __iter__(self) -> Iterator[BaseMetadata]: + """Unpack a Len into zone or more single-bounds.""" + if self.min_length > 0: + yield MinLen(self.min_length) + if self.max_length is not None: + yield MaxLen(self.max_length) + + +@dataclass(frozen=True, **SLOTS) +class Timezone(BaseMetadata): + """Timezone(tz=...) requires a datetime to be aware (or ``tz=None``, naive). + + ``Annotated[datetime, Timezone(None)]`` must be a naive datetime. + ``Timezone[...]`` (the ellipsis literal) expresses that the datetime must be + tz-aware but any timezone is allowed. + + You may also pass a specific timezone string or tzinfo object such as + ``Timezone(timezone.utc)`` or ``Timezone("Africa/Abidjan")`` to express that + you only allow a specific timezone, though we note that this is often + a symptom of poor design. + """ + + tz: Union[str, tzinfo, EllipsisType, None] + + +@dataclass(frozen=True, **SLOTS) +class Unit(BaseMetadata): + """Indicates that the value is a physical quantity with the specified unit. + + It is intended for usage with numeric types, where the value represents the + magnitude of the quantity. For example, ``distance: Annotated[float, Unit('m')]`` + or ``speed: Annotated[float, Unit('m/s')]``. + + Interpretation of the unit string is left to the discretion of the consumer. + It is suggested to follow conventions established by python libraries that work + with physical quantities, such as + + - ``pint`` : + - ``astropy.units``: + + For indicating a quantity with a certain dimensionality but without a specific unit + it is recommended to use square brackets, e.g. `Annotated[float, Unit('[time]')]`. + Note, however, ``annotated_types`` itself makes no use of the unit string. + """ + + unit: str + + +@dataclass(frozen=True, **SLOTS) +class Predicate(BaseMetadata): + """``Predicate(func: Callable)`` implies `func(value)` is truthy for valid values. + + Users should prefer statically inspectable metadata, but if you need the full + power and flexibility of arbitrary runtime predicates... here it is. + + We provide a few predefined predicates for common string constraints: + ``IsLower = Predicate(str.islower)``, ``IsUpper = Predicate(str.isupper)``, and + ``IsDigits = Predicate(str.isdigit)``. Users are encouraged to use methods which + can be given special handling, and avoid indirection like ``lambda s: s.lower()``. + + Some libraries might have special logic to handle certain predicates, e.g. by + checking for `str.isdigit` and using its presence to both call custom logic to + enforce digit-only strings, and customise some generated external schema. + + We do not specify what behaviour should be expected for predicates that raise + an exception. For example `Annotated[int, Predicate(str.isdigit)]` might silently + skip invalid constraints, or statically raise an error; or it might try calling it + and then propagate or discard the resulting exception. + """ + + func: Callable[[Any], bool] + + def __repr__(self) -> str: + if getattr(self.func, "__name__", "") == "": + return f"{self.__class__.__name__}({self.func!r})" + if isinstance(self.func, (types.MethodType, types.BuiltinMethodType)) and ( + namespace := getattr(self.func.__self__, "__name__", None) + ): + return f"{self.__class__.__name__}({namespace}.{self.func.__name__})" + if isinstance(self.func, type(str.isascii)): # method descriptor + return f"{self.__class__.__name__}({self.func.__qualname__})" + return f"{self.__class__.__name__}({self.func.__name__})" + + +@dataclass +class Not: + func: Callable[[Any], bool] + + def __call__(self, __v: Any) -> bool: + return not self.func(__v) + + +_StrType = TypeVar("_StrType", bound=str) + +LowerCase = Annotated[_StrType, Predicate(str.islower)] +""" +Return True if the string is a lowercase string, False otherwise. + +A string is lowercase if all cased characters in the string are lowercase and there is at least one cased character in the string. +""" # noqa: E501 +UpperCase = Annotated[_StrType, Predicate(str.isupper)] +""" +Return True if the string is an uppercase string, False otherwise. + +A string is uppercase if all cased characters in the string are uppercase and there is at least one cased character in the string. +""" # noqa: E501 +IsDigit = Annotated[_StrType, Predicate(str.isdigit)] +IsDigits = IsDigit # type: ignore # plural for backwards compatibility, see #63 +""" +Return True if the string is a digit string, False otherwise. + +A string is a digit string if all characters in the string are digits and there is at least one character in the string. +""" # noqa: E501 +IsAscii = Annotated[_StrType, Predicate(str.isascii)] +""" +Return True if all characters in the string are ASCII, False otherwise. + +ASCII characters have code points in the range U+0000-U+007F. Empty string is ASCII too. +""" + +_NumericType = TypeVar('_NumericType', bound=Union[SupportsFloat, SupportsIndex]) +IsFinite = Annotated[_NumericType, Predicate(math.isfinite)] +"""Return True if x is neither an infinity nor a NaN, and False otherwise.""" +IsNotFinite = Annotated[_NumericType, Predicate(Not(math.isfinite))] +"""Return True if x is one of infinity or NaN, and False otherwise""" +IsNan = Annotated[_NumericType, Predicate(math.isnan)] +"""Return True if x is a NaN (not a number), and False otherwise.""" +IsNotNan = Annotated[_NumericType, Predicate(Not(math.isnan))] +"""Return True if x is anything but NaN (not a number), and False otherwise.""" +IsInfinite = Annotated[_NumericType, Predicate(math.isinf)] +"""Return True if x is a positive or negative infinity, and False otherwise.""" +IsNotInfinite = Annotated[_NumericType, Predicate(Not(math.isinf))] +"""Return True if x is neither a positive or negative infinity, and False otherwise.""" + +try: + from typing_extensions import DocInfo, doc # type: ignore [attr-defined] +except ImportError: + + @dataclass(frozen=True, **SLOTS) + class DocInfo: # type: ignore [no-redef] + """ " + The return value of doc(), mainly to be used by tools that want to extract the + Annotated documentation at runtime. + """ + + documentation: str + """The documentation string passed to doc().""" + + def doc( + documentation: str, + ) -> DocInfo: + """ + Add documentation to a type annotation inside of Annotated. + + For example: + + >>> def hi(name: Annotated[int, doc("The name of the user")]) -> None: ... + """ + return DocInfo(documentation) diff --git a/backend/.venv/Lib/site-packages/annotated_types/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/annotated_types/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9149c8263dcddfdd78f1ef85ce05cf0832248a60 GIT binary patch literal 18621 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 ZKbb!8gOcg+s6d&4~~mS{|8oO^GyH% literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/annotated_types/__pycache__/test_cases.cpython-312.pyc b/backend/.venv/Lib/site-packages/annotated_types/__pycache__/test_cases.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..944fabb10f2126b25677845408506456dae9a053 GIT binary patch literal 13234 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/annotated_types/py.typed b/backend/.venv/Lib/site-packages/annotated_types/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/annotated_types/test_cases.py b/backend/.venv/Lib/site-packages/annotated_types/test_cases.py new file mode 100644 index 0000000..d9164d6 --- /dev/null +++ b/backend/.venv/Lib/site-packages/annotated_types/test_cases.py @@ -0,0 +1,151 @@ +import math +import sys +from datetime import date, datetime, timedelta, timezone +from decimal import Decimal +from typing import Any, Dict, Iterable, Iterator, List, NamedTuple, Set, Tuple + +if sys.version_info < (3, 9): + from typing_extensions import Annotated +else: + from typing import Annotated + +import annotated_types as at + + +class Case(NamedTuple): + """ + A test case for `annotated_types`. + """ + + annotation: Any + valid_cases: Iterable[Any] + invalid_cases: Iterable[Any] + + +def cases() -> Iterable[Case]: + # Gt, Ge, Lt, Le + yield Case(Annotated[int, at.Gt(4)], (5, 6, 1000), (4, 0, -1)) + yield Case(Annotated[float, at.Gt(0.5)], (0.6, 0.7, 0.8, 0.9), (0.5, 0.0, -0.1)) + yield Case( + Annotated[datetime, at.Gt(datetime(2000, 1, 1))], + [datetime(2000, 1, 2), datetime(2000, 1, 3)], + [datetime(2000, 1, 1), datetime(1999, 12, 31)], + ) + yield Case( + Annotated[datetime, at.Gt(date(2000, 1, 1))], + [date(2000, 1, 2), date(2000, 1, 3)], + [date(2000, 1, 1), date(1999, 12, 31)], + ) + yield Case( + Annotated[datetime, at.Gt(Decimal('1.123'))], + [Decimal('1.1231'), Decimal('123')], + [Decimal('1.123'), Decimal('0')], + ) + + yield Case(Annotated[int, at.Ge(4)], (4, 5, 6, 1000, 4), (0, -1)) + yield Case(Annotated[float, at.Ge(0.5)], (0.5, 0.6, 0.7, 0.8, 0.9), (0.4, 0.0, -0.1)) + yield Case( + Annotated[datetime, at.Ge(datetime(2000, 1, 1))], + [datetime(2000, 1, 2), datetime(2000, 1, 3)], + [datetime(1998, 1, 1), datetime(1999, 12, 31)], + ) + + yield Case(Annotated[int, at.Lt(4)], (0, -1), (4, 5, 6, 1000, 4)) + yield Case(Annotated[float, at.Lt(0.5)], (0.4, 0.0, -0.1), (0.5, 0.6, 0.7, 0.8, 0.9)) + yield Case( + Annotated[datetime, at.Lt(datetime(2000, 1, 1))], + [datetime(1999, 12, 31), datetime(1999, 12, 31)], + [datetime(2000, 1, 2), datetime(2000, 1, 3)], + ) + + yield Case(Annotated[int, at.Le(4)], (4, 0, -1), (5, 6, 1000)) + yield Case(Annotated[float, at.Le(0.5)], (0.5, 0.0, -0.1), (0.6, 0.7, 0.8, 0.9)) + yield Case( + Annotated[datetime, at.Le(datetime(2000, 1, 1))], + [datetime(2000, 1, 1), datetime(1999, 12, 31)], + [datetime(2000, 1, 2), datetime(2000, 1, 3)], + ) + + # Interval + yield Case(Annotated[int, at.Interval(gt=4)], (5, 6, 1000), (4, 0, -1)) + yield Case(Annotated[int, at.Interval(gt=4, lt=10)], (5, 6), (4, 10, 1000, 0, -1)) + yield Case(Annotated[float, at.Interval(ge=0.5, le=1)], (0.5, 0.9, 1), (0.49, 1.1)) + yield Case( + Annotated[datetime, at.Interval(gt=datetime(2000, 1, 1), le=datetime(2000, 1, 3))], + [datetime(2000, 1, 2), datetime(2000, 1, 3)], + [datetime(2000, 1, 1), datetime(2000, 1, 4)], + ) + + yield Case(Annotated[int, at.MultipleOf(multiple_of=3)], (0, 3, 9), (1, 2, 4)) + yield Case(Annotated[float, at.MultipleOf(multiple_of=0.5)], (0, 0.5, 1, 1.5), (0.4, 1.1)) + + # lengths + + yield Case(Annotated[str, at.MinLen(3)], ('123', '1234', 'x' * 10), ('', '1', '12')) + yield Case(Annotated[str, at.Len(3)], ('123', '1234', 'x' * 10), ('', '1', '12')) + yield Case(Annotated[List[int], at.MinLen(3)], ([1, 2, 3], [1, 2, 3, 4], [1] * 10), ([], [1], [1, 2])) + yield Case(Annotated[List[int], at.Len(3)], ([1, 2, 3], [1, 2, 3, 4], [1] * 10), ([], [1], [1, 2])) + + yield Case(Annotated[str, at.MaxLen(4)], ('', '1234'), ('12345', 'x' * 10)) + yield Case(Annotated[str, at.Len(0, 4)], ('', '1234'), ('12345', 'x' * 10)) + yield Case(Annotated[List[str], at.MaxLen(4)], ([], ['a', 'bcdef'], ['a', 'b', 'c']), (['a'] * 5, ['b'] * 10)) + yield Case(Annotated[List[str], at.Len(0, 4)], ([], ['a', 'bcdef'], ['a', 'b', 'c']), (['a'] * 5, ['b'] * 10)) + + yield Case(Annotated[str, at.Len(3, 5)], ('123', '12345'), ('', '1', '12', '123456', 'x' * 10)) + yield Case(Annotated[str, at.Len(3, 3)], ('123',), ('12', '1234')) + + yield Case(Annotated[Dict[int, int], at.Len(2, 3)], [{1: 1, 2: 2}], [{}, {1: 1}, {1: 1, 2: 2, 3: 3, 4: 4}]) + yield Case(Annotated[Set[int], at.Len(2, 3)], ({1, 2}, {1, 2, 3}), (set(), {1}, {1, 2, 3, 4})) + yield Case(Annotated[Tuple[int, ...], at.Len(2, 3)], ((1, 2), (1, 2, 3)), ((), (1,), (1, 2, 3, 4))) + + # Timezone + + yield Case( + Annotated[datetime, at.Timezone(None)], [datetime(2000, 1, 1)], [datetime(2000, 1, 1, tzinfo=timezone.utc)] + ) + yield Case( + Annotated[datetime, at.Timezone(...)], [datetime(2000, 1, 1, tzinfo=timezone.utc)], [datetime(2000, 1, 1)] + ) + yield Case( + Annotated[datetime, at.Timezone(timezone.utc)], + [datetime(2000, 1, 1, tzinfo=timezone.utc)], + [datetime(2000, 1, 1), datetime(2000, 1, 1, tzinfo=timezone(timedelta(hours=6)))], + ) + yield Case( + Annotated[datetime, at.Timezone('Europe/London')], + [datetime(2000, 1, 1, tzinfo=timezone(timedelta(0), name='Europe/London'))], + [datetime(2000, 1, 1), datetime(2000, 1, 1, tzinfo=timezone(timedelta(hours=6)))], + ) + + # Quantity + + yield Case(Annotated[float, at.Unit(unit='m')], (5, 4.2), ('5m', '4.2m')) + + # predicate types + + yield Case(at.LowerCase[str], ['abc', 'foobar'], ['', 'A', 'Boom']) + yield Case(at.UpperCase[str], ['ABC', 'DEFO'], ['', 'a', 'abc', 'AbC']) + yield Case(at.IsDigit[str], ['123'], ['', 'ab', 'a1b2']) + yield Case(at.IsAscii[str], ['123', 'foo bar'], ['£100', '😊', 'whatever 👀']) + + yield Case(Annotated[int, at.Predicate(lambda x: x % 2 == 0)], [0, 2, 4], [1, 3, 5]) + + yield Case(at.IsFinite[float], [1.23], [math.nan, math.inf, -math.inf]) + yield Case(at.IsNotFinite[float], [math.nan, math.inf], [1.23]) + yield Case(at.IsNan[float], [math.nan], [1.23, math.inf]) + yield Case(at.IsNotNan[float], [1.23, math.inf], [math.nan]) + yield Case(at.IsInfinite[float], [math.inf], [math.nan, 1.23]) + yield Case(at.IsNotInfinite[float], [math.nan, 1.23], [math.inf]) + + # check stacked predicates + yield Case(at.IsInfinite[Annotated[float, at.Predicate(lambda x: x > 0)]], [math.inf], [-math.inf, 1.23, math.nan]) + + # doc + yield Case(Annotated[int, at.doc("A number")], [1, 2], []) + + # custom GroupedMetadata + class MyCustomGroupedMetadata(at.GroupedMetadata): + def __iter__(self) -> Iterator[at.Predicate]: + yield at.Predicate(lambda x: float(x).is_integer()) + + yield Case(Annotated[float, MyCustomGroupedMetadata()], [0, 2.0], [0.01, 1.5]) diff --git a/backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/INSTALLER b/backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/METADATA b/backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/METADATA new file mode 100644 index 0000000..0552dea --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/METADATA @@ -0,0 +1,96 @@ +Metadata-Version: 2.4 +Name: anyio +Version: 4.12.0 +Summary: High-level concurrency and networking framework on top of asyncio or Trio +Author-email: Alex Grönholm +License-Expression: MIT +Project-URL: Documentation, https://anyio.readthedocs.io/en/latest/ +Project-URL: Changelog, https://anyio.readthedocs.io/en/stable/versionhistory.html +Project-URL: Source code, https://github.com/agronholm/anyio +Project-URL: Issue tracker, https://github.com/agronholm/anyio/issues +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Framework :: AnyIO +Classifier: Typing :: Typed +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: Programming Language :: Python :: 3.14 +Requires-Python: >=3.9 +Description-Content-Type: text/x-rst +License-File: LICENSE +Requires-Dist: exceptiongroup>=1.0.2; python_version < "3.11" +Requires-Dist: idna>=2.8 +Requires-Dist: typing_extensions>=4.5; python_version < "3.13" +Provides-Extra: trio +Requires-Dist: trio>=0.32.0; python_version >= "3.10" and extra == "trio" +Requires-Dist: trio>=0.31.0; python_version < "3.10" and extra == "trio" +Dynamic: license-file + +.. image:: https://github.com/agronholm/anyio/actions/workflows/test.yml/badge.svg + :target: https://github.com/agronholm/anyio/actions/workflows/test.yml + :alt: Build Status +.. image:: https://coveralls.io/repos/github/agronholm/anyio/badge.svg?branch=master + :target: https://coveralls.io/github/agronholm/anyio?branch=master + :alt: Code Coverage +.. image:: https://readthedocs.org/projects/anyio/badge/?version=latest + :target: https://anyio.readthedocs.io/en/latest/?badge=latest + :alt: Documentation +.. image:: https://badges.gitter.im/gitterHQ/gitter.svg + :target: https://gitter.im/python-trio/AnyIO + :alt: Gitter chat + +AnyIO is an asynchronous networking and concurrency library that works on top of either asyncio_ or +Trio_. It implements Trio-like `structured concurrency`_ (SC) on top of asyncio and works in harmony +with the native SC of Trio itself. + +Applications and libraries written against AnyIO's API will run unmodified on either asyncio_ or +Trio_. AnyIO can also be adopted into a library or application incrementally – bit by bit, no full +refactoring necessary. It will blend in with the native libraries of your chosen backend. + +To find out why you might want to use AnyIO's APIs instead of asyncio's, you can read about it +`here `_. + +Documentation +------------- + +View full documentation at: https://anyio.readthedocs.io/ + +Features +-------- + +AnyIO offers the following functionality: + +* Task groups (nurseries_ in trio terminology) +* High-level networking (TCP, UDP and UNIX sockets) + + * `Happy eyeballs`_ algorithm for TCP connections (more robust than that of asyncio on Python + 3.8) + * async/await style UDP sockets (unlike asyncio where you still have to use Transports and + Protocols) + +* A versatile API for byte streams and object streams +* Inter-task synchronization and communication (locks, conditions, events, semaphores, object + streams) +* Worker threads +* Subprocesses +* Subinterpreter support for code parallelization (on Python 3.13 and later) +* Asynchronous file I/O (using worker threads) +* Signal handling +* Asynchronous version of the functools_ module + +AnyIO also comes with its own pytest_ plugin which also supports asynchronous fixtures. +It even works with the popular Hypothesis_ library. + +.. _asyncio: https://docs.python.org/3/library/asyncio.html +.. _Trio: https://github.com/python-trio/trio +.. _structured concurrency: https://en.wikipedia.org/wiki/Structured_concurrency +.. _nurseries: https://trio.readthedocs.io/en/stable/reference-core.html#nurseries-and-spawning +.. _Happy eyeballs: https://en.wikipedia.org/wiki/Happy_Eyeballs +.. _pytest: https://docs.pytest.org/en/latest/ +.. _functools: https://docs.python.org/3/library/functools.html +.. _Hypothesis: https://hypothesis.works/ diff --git a/backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/RECORD b/backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/RECORD new file mode 100644 index 0000000..c203c32 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/RECORD @@ -0,0 +1,92 @@ +anyio-4.12.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +anyio-4.12.0.dist-info/METADATA,sha256=rte2_C2hYKP9_iVMFYogSzBxdHBzwY45S1TrLiBsxdk,4277 +anyio-4.12.0.dist-info/RECORD,, +anyio-4.12.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91 +anyio-4.12.0.dist-info/entry_points.txt,sha256=_d6Yu6uiaZmNe0CydowirE9Cmg7zUL2g08tQpoS3Qvc,39 +anyio-4.12.0.dist-info/licenses/LICENSE,sha256=U2GsncWPLvX9LpsJxoKXwX8ElQkJu8gCO9uC6s8iwrA,1081 +anyio-4.12.0.dist-info/top_level.txt,sha256=QglSMiWX8_5dpoVAEIHdEYzvqFMdSYWmCj6tYw2ITkQ,6 +anyio/__init__.py,sha256=7iDVqMUprUuKNY91FuoKqayAhR-OY136YDPI6P78HHk,6170 +anyio/__pycache__/__init__.cpython-312.pyc,, +anyio/__pycache__/from_thread.cpython-312.pyc,, +anyio/__pycache__/functools.cpython-312.pyc,, +anyio/__pycache__/lowlevel.cpython-312.pyc,, +anyio/__pycache__/pytest_plugin.cpython-312.pyc,, +anyio/__pycache__/to_interpreter.cpython-312.pyc,, +anyio/__pycache__/to_process.cpython-312.pyc,, +anyio/__pycache__/to_thread.cpython-312.pyc,, +anyio/_backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +anyio/_backends/__pycache__/__init__.cpython-312.pyc,, +anyio/_backends/__pycache__/_asyncio.cpython-312.pyc,, +anyio/_backends/__pycache__/_trio.cpython-312.pyc,, +anyio/_backends/_asyncio.py,sha256=w6gCSMs_2D1doKVtzi32bOloBl1df-IHubl8-Vks908,99656 +anyio/_backends/_trio.py,sha256=ScNVMQB0iiuJMAon1epQCVOVbIbf-Lxnfb5OxujzMok,42398 +anyio/_core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +anyio/_core/__pycache__/__init__.cpython-312.pyc,, +anyio/_core/__pycache__/_asyncio_selector_thread.cpython-312.pyc,, +anyio/_core/__pycache__/_contextmanagers.cpython-312.pyc,, +anyio/_core/__pycache__/_eventloop.cpython-312.pyc,, +anyio/_core/__pycache__/_exceptions.cpython-312.pyc,, +anyio/_core/__pycache__/_fileio.cpython-312.pyc,, +anyio/_core/__pycache__/_resources.cpython-312.pyc,, +anyio/_core/__pycache__/_signals.cpython-312.pyc,, +anyio/_core/__pycache__/_sockets.cpython-312.pyc,, +anyio/_core/__pycache__/_streams.cpython-312.pyc,, +anyio/_core/__pycache__/_subprocesses.cpython-312.pyc,, +anyio/_core/__pycache__/_synchronization.cpython-312.pyc,, +anyio/_core/__pycache__/_tasks.cpython-312.pyc,, +anyio/_core/__pycache__/_tempfile.cpython-312.pyc,, +anyio/_core/__pycache__/_testing.cpython-312.pyc,, +anyio/_core/__pycache__/_typedattr.cpython-312.pyc,, +anyio/_core/_asyncio_selector_thread.py,sha256=2PdxFM3cs02Kp6BSppbvmRT7q7asreTW5FgBxEsflBo,5626 +anyio/_core/_contextmanagers.py,sha256=YInBCabiEeS-UaP_Jdxa1CaFC71ETPW8HZTHIM8Rsc8,7215 +anyio/_core/_eventloop.py,sha256=xsoYgHIddNYusTqAFDVmcvpjHKJFmdgtDcAjpN3JEWQ,6261 +anyio/_core/_exceptions.py,sha256=fR2SvRUBYVHvolNKbzWSLt8FC_5NFB2OAzGD738fD8Q,4257 +anyio/_core/_fileio.py,sha256=uc7t10Vb-If7GbdWM_zFf-ajUe6uek63fSt7IBLlZW0,25731 +anyio/_core/_resources.py,sha256=NbmU5O5UX3xEyACnkmYX28Fmwdl-f-ny0tHym26e0w0,435 +anyio/_core/_signals.py,sha256=vulT1M1xdLYtAR-eY5TamIgaf1WTlOwOrMGwswlTTr8,905 +anyio/_core/_sockets.py,sha256=aTbgMr0qPmBPfrapxLykyajsmS7IAerhW9_Qk5r5E18,34311 +anyio/_core/_streams.py,sha256=FczFwIgDpnkK0bODWJXMpsUJYdvAD04kaUaGzJU8DK0,1806 +anyio/_core/_subprocesses.py,sha256=EXm5igL7dj55iYkPlbYVAqtbqxJxjU-6OndSTIx9SRg,8047 +anyio/_core/_synchronization.py,sha256=SY3nsr1ZZyDrjamsOVoYcvj-x6d_AR13Cu5lZecG0gY,20894 +anyio/_core/_tasks.py,sha256=km6hVE1fsuIenya3MDud8KP6-J_bNzlgYC10wUxI7iA,4880 +anyio/_core/_tempfile.py,sha256=lHb7CW4FyIlpkf5ADAf4VmLHCKwEHF9nxqNyBCFFUiA,19697 +anyio/_core/_testing.py,sha256=YUGwA5cgFFbUTv4WFd7cv_BSVr4ryTtPp8owQA3JdWE,2118 +anyio/_core/_typedattr.py,sha256=P4ozZikn3-DbpoYcvyghS_FOYAgbmUxeoU8-L_07pZM,2508 +anyio/abc/__init__.py,sha256=6mWhcl_pGXhrgZVHP_TCfMvIXIOp9mroEFM90fYCU_U,2869 +anyio/abc/__pycache__/__init__.cpython-312.pyc,, +anyio/abc/__pycache__/_eventloop.cpython-312.pyc,, +anyio/abc/__pycache__/_resources.cpython-312.pyc,, +anyio/abc/__pycache__/_sockets.cpython-312.pyc,, +anyio/abc/__pycache__/_streams.cpython-312.pyc,, +anyio/abc/__pycache__/_subprocesses.cpython-312.pyc,, +anyio/abc/__pycache__/_tasks.cpython-312.pyc,, +anyio/abc/__pycache__/_testing.cpython-312.pyc,, +anyio/abc/_eventloop.py,sha256=GTZbdItBHcj_b-8K2XylET2-bBYLZ3XjW4snY7vK7LE,10900 +anyio/abc/_resources.py,sha256=DrYvkNN1hH6Uvv5_5uKySvDsnknGVDe8FCKfko0VtN8,783 +anyio/abc/_sockets.py,sha256=ECTY0jLEF18gryANHR3vFzXzGdZ-xPwELq1QdgOb0Jo,13258 +anyio/abc/_streams.py,sha256=005GKSCXGprxnhucILboSqc2JFovECZk9m3p-qqxXVc,7640 +anyio/abc/_subprocesses.py,sha256=cumAPJTktOQtw63IqG0lDpyZqu_l1EElvQHMiwJgL08,2067 +anyio/abc/_tasks.py,sha256=KC7wrciE48AINOI-AhPutnFhe1ewfP7QnamFlDzqesQ,3721 +anyio/abc/_testing.py,sha256=tBJUzkSfOXJw23fe8qSJ03kJlShOYjjaEyFB6k6MYT8,1821 +anyio/from_thread.py,sha256=-YZOTpu9WVHtAsMxQGIOaHMjaDRNeKQilx6Nn2qDU-o,19017 +anyio/functools.py,sha256=tIWQ90cuLMxfJIpdBfFY3W3CC1zqFCRAyR3DxKc0Xlo,10061 +anyio/lowlevel.py,sha256=NnPYQ6tWDzLRwpalX2CvsbkXkTeasbJcL52gPopWdYg,5048 +anyio/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +anyio/pytest_plugin.py,sha256=3jAFQn0jv_pyoWE2GBBlHaj9sqXj4e8vob0_hgrsXE8,10244 +anyio/streams/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +anyio/streams/__pycache__/__init__.cpython-312.pyc,, +anyio/streams/__pycache__/buffered.cpython-312.pyc,, +anyio/streams/__pycache__/file.cpython-312.pyc,, +anyio/streams/__pycache__/memory.cpython-312.pyc,, +anyio/streams/__pycache__/stapled.cpython-312.pyc,, +anyio/streams/__pycache__/text.cpython-312.pyc,, +anyio/streams/__pycache__/tls.cpython-312.pyc,, +anyio/streams/buffered.py,sha256=2R3PeJhe4EXrdYqz44Y6-Eg9R6DrmlsYrP36Ir43-po,6263 +anyio/streams/file.py,sha256=4WZ7XGz5WNu39FQHvqbe__TQ0HDP9OOhgO1mk9iVpVU,4470 +anyio/streams/memory.py,sha256=F0zwzvFJKAhX_LRZGoKzzqDC2oMM-f-yyTBrEYEGOaU,10740 +anyio/streams/stapled.py,sha256=T8Xqwf8K6EgURPxbt1N4i7A8BAk-gScv-GRhjLXIf_o,4390 +anyio/streams/text.py,sha256=BcVAGJw1VRvtIqnv-o0Rb0pwH7p8vwlvl21xHq522ag,5765 +anyio/streams/tls.py,sha256=Jpxy0Mfbcp1BxHCwE-YjSSFaLnIBbnnwur-excYThs4,15368 +anyio/to_interpreter.py,sha256=_mLngrMy97TMR6VbW4Y6YzDUk9ZuPcQMPlkuyRh3C9k,7100 +anyio/to_process.py,sha256=cEyYUgb8LJVRJCfs6rK3aEM_T3k2gEmhl0nBjEvflOk,9687 +anyio/to_thread.py,sha256=tXQPvHohvQ2Vrw2pBtdzkRPNV7u3H2_UDbvwL2u_R7k,2465 diff --git a/backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/WHEEL b/backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/WHEEL new file mode 100644 index 0000000..e7fa31b --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio-4.12.0.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/anyio-4.12.0.dist-info/entry_points.txt b/backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/entry_points.txt new file mode 100644 index 0000000..44dd9bd --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[pytest11] +anyio = anyio.pytest_plugin diff --git a/backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/licenses/LICENSE b/backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/licenses/LICENSE new file mode 100644 index 0000000..104eebf --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/licenses/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2018 Alex Grönholm + +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/anyio-4.12.0.dist-info/top_level.txt b/backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/top_level.txt new file mode 100644 index 0000000..c77c069 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio-4.12.0.dist-info/top_level.txt @@ -0,0 +1 @@ +anyio diff --git a/backend/.venv/Lib/site-packages/anyio/__init__.py b/backend/.venv/Lib/site-packages/anyio/__init__.py new file mode 100644 index 0000000..d23c5a5 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/__init__.py @@ -0,0 +1,111 @@ +from __future__ import annotations + +from ._core._contextmanagers import AsyncContextManagerMixin as AsyncContextManagerMixin +from ._core._contextmanagers import ContextManagerMixin as ContextManagerMixin +from ._core._eventloop import current_time as current_time +from ._core._eventloop import get_all_backends as get_all_backends +from ._core._eventloop import get_available_backends as get_available_backends +from ._core._eventloop import get_cancelled_exc_class as get_cancelled_exc_class +from ._core._eventloop import run as run +from ._core._eventloop import sleep as sleep +from ._core._eventloop import sleep_forever as sleep_forever +from ._core._eventloop import sleep_until as sleep_until +from ._core._exceptions import BrokenResourceError as BrokenResourceError +from ._core._exceptions import BrokenWorkerInterpreter as BrokenWorkerInterpreter +from ._core._exceptions import BrokenWorkerProcess as BrokenWorkerProcess +from ._core._exceptions import BusyResourceError as BusyResourceError +from ._core._exceptions import ClosedResourceError as ClosedResourceError +from ._core._exceptions import ConnectionFailed as ConnectionFailed +from ._core._exceptions import DelimiterNotFound as DelimiterNotFound +from ._core._exceptions import EndOfStream as EndOfStream +from ._core._exceptions import IncompleteRead as IncompleteRead +from ._core._exceptions import NoEventLoopError as NoEventLoopError +from ._core._exceptions import RunFinishedError as RunFinishedError +from ._core._exceptions import TypedAttributeLookupError as TypedAttributeLookupError +from ._core._exceptions import WouldBlock as WouldBlock +from ._core._fileio import AsyncFile as AsyncFile +from ._core._fileio import Path as Path +from ._core._fileio import open_file as open_file +from ._core._fileio import wrap_file as wrap_file +from ._core._resources import aclose_forcefully as aclose_forcefully +from ._core._signals import open_signal_receiver as open_signal_receiver +from ._core._sockets import TCPConnectable as TCPConnectable +from ._core._sockets import UNIXConnectable as UNIXConnectable +from ._core._sockets import as_connectable as as_connectable +from ._core._sockets import connect_tcp as connect_tcp +from ._core._sockets import connect_unix as connect_unix +from ._core._sockets import create_connected_udp_socket as create_connected_udp_socket +from ._core._sockets import ( + create_connected_unix_datagram_socket as create_connected_unix_datagram_socket, +) +from ._core._sockets import create_tcp_listener as create_tcp_listener +from ._core._sockets import create_udp_socket as create_udp_socket +from ._core._sockets import create_unix_datagram_socket as create_unix_datagram_socket +from ._core._sockets import create_unix_listener as create_unix_listener +from ._core._sockets import getaddrinfo as getaddrinfo +from ._core._sockets import getnameinfo as getnameinfo +from ._core._sockets import notify_closing as notify_closing +from ._core._sockets import wait_readable as wait_readable +from ._core._sockets import wait_socket_readable as wait_socket_readable +from ._core._sockets import wait_socket_writable as wait_socket_writable +from ._core._sockets import wait_writable as wait_writable +from ._core._streams import create_memory_object_stream as create_memory_object_stream +from ._core._subprocesses import open_process as open_process +from ._core._subprocesses import run_process as run_process +from ._core._synchronization import CapacityLimiter as CapacityLimiter +from ._core._synchronization import ( + CapacityLimiterStatistics as CapacityLimiterStatistics, +) +from ._core._synchronization import Condition as Condition +from ._core._synchronization import ConditionStatistics as ConditionStatistics +from ._core._synchronization import Event as Event +from ._core._synchronization import EventStatistics as EventStatistics +from ._core._synchronization import Lock as Lock +from ._core._synchronization import LockStatistics as LockStatistics +from ._core._synchronization import ResourceGuard as ResourceGuard +from ._core._synchronization import Semaphore as Semaphore +from ._core._synchronization import SemaphoreStatistics as SemaphoreStatistics +from ._core._tasks import TASK_STATUS_IGNORED as TASK_STATUS_IGNORED +from ._core._tasks import CancelScope as CancelScope +from ._core._tasks import create_task_group as create_task_group +from ._core._tasks import current_effective_deadline as current_effective_deadline +from ._core._tasks import fail_after as fail_after +from ._core._tasks import move_on_after as move_on_after +from ._core._tempfile import NamedTemporaryFile as NamedTemporaryFile +from ._core._tempfile import SpooledTemporaryFile as SpooledTemporaryFile +from ._core._tempfile import TemporaryDirectory as TemporaryDirectory +from ._core._tempfile import TemporaryFile as TemporaryFile +from ._core._tempfile import gettempdir as gettempdir +from ._core._tempfile import gettempdirb as gettempdirb +from ._core._tempfile import mkdtemp as mkdtemp +from ._core._tempfile import mkstemp as mkstemp +from ._core._testing import TaskInfo as TaskInfo +from ._core._testing import get_current_task as get_current_task +from ._core._testing import get_running_tasks as get_running_tasks +from ._core._testing import wait_all_tasks_blocked as wait_all_tasks_blocked +from ._core._typedattr import TypedAttributeProvider as TypedAttributeProvider +from ._core._typedattr import TypedAttributeSet as TypedAttributeSet +from ._core._typedattr import typed_attribute as typed_attribute + +# Re-export imports so they look like they live directly in this package +for __value in list(locals().values()): + if getattr(__value, "__module__", "").startswith("anyio."): + __value.__module__ = __name__ + + +del __value + + +def __getattr__(attr: str) -> type[BrokenWorkerInterpreter]: + """Support deprecated aliases.""" + if attr == "BrokenWorkerIntepreter": + import warnings + + warnings.warn( + "The 'BrokenWorkerIntepreter' alias is deprecated, use 'BrokenWorkerInterpreter' instead.", + DeprecationWarning, + stacklevel=2, + ) + return BrokenWorkerInterpreter + + raise AttributeError(f"module {__name__!r} has no attribute {attr!r}") diff --git a/backend/.venv/Lib/site-packages/anyio/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5022fbced0677040fe007dd0e4f0b719b2fea012 GIT binary patch literal 4624 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

q1^ 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 D-e!l< literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/__pycache__/functools.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/__pycache__/functools.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..90460ff1d61204b4aa24727a1b1ae19338c49764 GIT binary patch literal 13724 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/__pycache__/lowlevel.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/__pycache__/lowlevel.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..246752564580cbe48bc5b9e6837cd8c967fcf218 GIT binary patch literal 7885 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 WbLb^OIK2Gk-Pi9#{)-^aIs3nuUi*;% literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/__pycache__/pytest_plugin.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/__pycache__/pytest_plugin.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f8b72be01b549bd90669858e253382ed86cdb0a4 GIT binary patch literal 14283 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 WUnMK9QP$s4fZ`*nl79uJ>3;y=;JqgR literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/__pycache__/to_thread.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/__pycache__/to_thread.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d341d34dc1403acf7d307af5e1b65dbb76ad9de6 GIT binary patch literal 2973 zcmZuz&5s;M6|er7nV#v{kC`=goH*+OTgF4|NkAx;CfLRpMT!UpB@2l0SUok}wY%-@ zsUB7J>}HllT8IT4IOGE600)l9;SV6E+_|jr!Apx3L4e5K2CWe&C*G^>ncb{ivs?A* z>(#6G`@L8F$C;T5fzs?;4S!oExE3VJuX`OdUBCo*D^1UG#@ia*=oeUuMH7@sd@^ zS>Q!sKTNp11$&*FEQ(k!;vkonMg#s`CPB0}m=ybHEp%!tJnJFu+kdq zF%iVVgFl}MpGT>iwc50_lpE~l?jv|o5&nNlh;eWagl`Z7fZsBIbYjc=p^;410sM&x z)4BxK`}PCe3B@2uA(IGskPCN9laa%Ai)`6j#+LPd;XzKacY$0#04={X?^{196v*4; z3i-MHduzjJ6xm~#s8A^ARhq1Fx)QE)L6?WZM|kK)n5-TdXL4oO2Y?g}1!Z(2mTO$X zJfhUBXiaY{>-F945r=fUG#+Sup`u(Md;tXy>XivoYjlH!Nhnt6ax7^G>ixJ6IOJQj z-dr6IE@iv)nP4B-trDz(MfujDRGjvPiSA0C45gre;gHjdpq_~ll`K>|(0chhKG(K2 zGG#qZ!xa%rKDkh9z$EKym$cx{e$GF=IiCZ!s1_Z>3N8@~7STgL;f2tz&)jyLMJ?Lx zF3BMWeLaL)T#ORH0(Jwc@*nH(R?Uknyf`dY# z5=aXBn9U&jR#XD{G~(+#YM8PPgYpE<*wTR}t$#g-9{Bb>$mHNZiO*+xdSZ(g3NK?* zZe^p8+L)#?WeXFHsg1#?Fj-<$&`*|bwmP^`0i?Vm?k4Io^L+#j4!P_@pm*{|qSJ)b zx88X(>~$cJ`DJ_o*a}x2?Vpzq{WBOzOs={*4TAbUR3DT7ZIkh<#97!WE$*KA{El<_ zFHUuA8Z+NC{!v}rJ@wpw%7t>}$tj(*Yrd{T{pq@v>Iu$0C2tCy|j8vo&S- z({UE}?s7lL9unXQQa~b-iGDAktzo8en+fPc$kn_at_C9nNp9xlW>6xl(tvaaE0bNq97NsLa%BdQs*oEI2cC!n!E&K_zk0e z1J&3v3}cUcZfskwxm`M_5X0Rg=l96-d*t*#$;*3$eq0kD%e{<{awE)F!=g;n`UsWEt=eC`3m7G1ld-mM!g)jWuy@Ln8%z*UdEyFRsYH0KS507wJ9RL6T literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/_backends/__init__.py b/backend/.venv/Lib/site-packages/anyio/_backends/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/anyio/_backends/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/_backends/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b46cca29363201ae8736e15506e74c2f0c4ff6d4 GIT binary patch literal 190 zcmX@j%ge<81bQ*HnIQTxh(HIQS%4zb87dhx8U0o=6fpsLpFwJV#X4KXl;;;^7Z)TZ zr^e)El@#kHCMV~Y=9OgTrRyf=7p2A|B_?O5=B32wm8IsD#rR|<#S~|jr0N1SWGAMl z7RMy!Rc7Yv$3vAB>&M4u=4F<|$LkeT-r}&y%}*)KNwq6t1=_|4#Kj=SM`lJw#v*1Q F3jkXnGcW)E literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/_backends/__pycache__/_asyncio.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/_backends/__pycache__/_asyncio.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..623ecda3a07c7e3f69436dc81816ccfe2ced7c4d GIT binary patch literal 139824 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ȥAAYAVnYmY=tpx5O|DcK@%;6L3OfFG)Eg9 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/_backends/_asyncio.py b/backend/.venv/Lib/site-packages/anyio/_backends/_asyncio.py new file mode 100644 index 0000000..2a4dacc --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/_backends/_asyncio.py @@ -0,0 +1,3007 @@ +from __future__ import annotations + +import array +import asyncio +import concurrent.futures +import contextvars +import math +import os +import socket +import sys +import threading +import weakref +from asyncio import ( + AbstractEventLoop, + CancelledError, + all_tasks, + create_task, + current_task, + get_running_loop, + sleep, +) +from asyncio.base_events import _run_until_complete_cb # type: ignore[attr-defined] +from collections import OrderedDict, deque +from collections.abc import ( + AsyncGenerator, + AsyncIterator, + Awaitable, + Callable, + Collection, + Coroutine, + Iterable, + Sequence, +) +from concurrent.futures import Future +from contextlib import AbstractContextManager, suppress +from contextvars import Context, copy_context +from dataclasses import dataclass, field +from functools import partial, wraps +from inspect import ( + CORO_RUNNING, + CORO_SUSPENDED, + getcoroutinestate, + iscoroutine, +) +from io import IOBase +from os import PathLike +from queue import Queue +from signal import Signals +from socket import AddressFamily, SocketKind +from threading import Thread +from types import CodeType, TracebackType +from typing import ( + IO, + TYPE_CHECKING, + Any, + Optional, + TypeVar, + cast, +) +from weakref import WeakKeyDictionary + +from .. import ( + CapacityLimiterStatistics, + EventStatistics, + LockStatistics, + TaskInfo, + abc, +) +from .._core._eventloop import ( + claim_worker_thread, + set_current_async_library, + threadlocals, +) +from .._core._exceptions import ( + BrokenResourceError, + BusyResourceError, + ClosedResourceError, + EndOfStream, + RunFinishedError, + WouldBlock, + iterate_exceptions, +) +from .._core._sockets import convert_ipv6_sockaddr +from .._core._streams import create_memory_object_stream +from .._core._synchronization import ( + CapacityLimiter as BaseCapacityLimiter, +) +from .._core._synchronization import Event as BaseEvent +from .._core._synchronization import Lock as BaseLock +from .._core._synchronization import ( + ResourceGuard, + SemaphoreStatistics, +) +from .._core._synchronization import Semaphore as BaseSemaphore +from .._core._tasks import CancelScope as BaseCancelScope +from ..abc import ( + AsyncBackend, + IPSockAddrType, + SocketListener, + UDPPacketType, + UNIXDatagramPacketType, +) +from ..abc._eventloop import StrOrBytesPath +from ..lowlevel import RunVar +from ..streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream + +if TYPE_CHECKING: + from _typeshed import FileDescriptorLike +else: + FileDescriptorLike = object + +if sys.version_info >= (3, 10): + from typing import ParamSpec +else: + from typing_extensions import ParamSpec + +if sys.version_info >= (3, 11): + from asyncio import Runner + from typing import TypeVarTuple, Unpack +else: + import contextvars + import enum + import signal + from asyncio import coroutines, events, exceptions, tasks + + from exceptiongroup import BaseExceptionGroup + from typing_extensions import TypeVarTuple, Unpack + + class _State(enum.Enum): + CREATED = "created" + INITIALIZED = "initialized" + CLOSED = "closed" + + class Runner: + # Copied from CPython 3.11 + def __init__( + self, + *, + debug: bool | None = None, + loop_factory: Callable[[], AbstractEventLoop] | None = None, + ): + self._state = _State.CREATED + self._debug = debug + self._loop_factory = loop_factory + self._loop: AbstractEventLoop | None = None + self._context = None + self._interrupt_count = 0 + self._set_event_loop = False + + def __enter__(self) -> Runner: + self._lazy_init() + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self.close() + + def close(self) -> None: + """Shutdown and close event loop.""" + loop = self._loop + if self._state is not _State.INITIALIZED or loop is None: + return + try: + _cancel_all_tasks(loop) + loop.run_until_complete(loop.shutdown_asyncgens()) + if hasattr(loop, "shutdown_default_executor"): + loop.run_until_complete(loop.shutdown_default_executor()) + else: + loop.run_until_complete(_shutdown_default_executor(loop)) + finally: + if self._set_event_loop: + events.set_event_loop(None) + loop.close() + self._loop = None + self._state = _State.CLOSED + + def get_loop(self) -> AbstractEventLoop: + """Return embedded event loop.""" + self._lazy_init() + return self._loop + + def run(self, coro: Coroutine[T_Retval], *, context=None) -> T_Retval: + """Run a coroutine inside the embedded event loop.""" + if not coroutines.iscoroutine(coro): + raise ValueError(f"a coroutine was expected, got {coro!r}") + + if events._get_running_loop() is not None: + # fail fast with short traceback + raise RuntimeError( + "Runner.run() cannot be called from a running event loop" + ) + + self._lazy_init() + + if context is None: + context = self._context + task = context.run(self._loop.create_task, coro) + + if ( + threading.current_thread() is threading.main_thread() + and signal.getsignal(signal.SIGINT) is signal.default_int_handler + ): + sigint_handler = partial(self._on_sigint, main_task=task) + try: + signal.signal(signal.SIGINT, sigint_handler) + except ValueError: + # `signal.signal` may throw if `threading.main_thread` does + # not support signals (e.g. embedded interpreter with signals + # not registered - see gh-91880) + sigint_handler = None + else: + sigint_handler = None + + self._interrupt_count = 0 + try: + return self._loop.run_until_complete(task) + except exceptions.CancelledError: + if self._interrupt_count > 0: + uncancel = getattr(task, "uncancel", None) + if uncancel is not None and uncancel() == 0: + raise KeyboardInterrupt # noqa: B904 + raise # CancelledError + finally: + if ( + sigint_handler is not None + and signal.getsignal(signal.SIGINT) is sigint_handler + ): + signal.signal(signal.SIGINT, signal.default_int_handler) + + def _lazy_init(self) -> None: + if self._state is _State.CLOSED: + raise RuntimeError("Runner is closed") + if self._state is _State.INITIALIZED: + return + if self._loop_factory is None: + self._loop = events.new_event_loop() + if not self._set_event_loop: + # Call set_event_loop only once to avoid calling + # attach_loop multiple times on child watchers + events.set_event_loop(self._loop) + self._set_event_loop = True + else: + self._loop = self._loop_factory() + if self._debug is not None: + self._loop.set_debug(self._debug) + self._context = contextvars.copy_context() + self._state = _State.INITIALIZED + + def _on_sigint(self, signum, frame, main_task: asyncio.Task) -> None: + self._interrupt_count += 1 + if self._interrupt_count == 1 and not main_task.done(): + main_task.cancel() + # wakeup loop if it is blocked by select() with long timeout + self._loop.call_soon_threadsafe(lambda: None) + return + raise KeyboardInterrupt() + + def _cancel_all_tasks(loop: AbstractEventLoop) -> None: + to_cancel = tasks.all_tasks(loop) + if not to_cancel: + return + + for task in to_cancel: + task.cancel() + + loop.run_until_complete(tasks.gather(*to_cancel, return_exceptions=True)) + + for task in to_cancel: + if task.cancelled(): + continue + if task.exception() is not None: + loop.call_exception_handler( + { + "message": "unhandled exception during asyncio.run() shutdown", + "exception": task.exception(), + "task": task, + } + ) + + async def _shutdown_default_executor(loop: AbstractEventLoop) -> None: + """Schedule the shutdown of the default executor.""" + + def _do_shutdown(future: asyncio.futures.Future) -> None: + try: + loop._default_executor.shutdown(wait=True) # type: ignore[attr-defined] + loop.call_soon_threadsafe(future.set_result, None) + except Exception as ex: + loop.call_soon_threadsafe(future.set_exception, ex) + + loop._executor_shutdown_called = True + if loop._default_executor is None: + return + future = loop.create_future() + thread = threading.Thread(target=_do_shutdown, args=(future,)) + thread.start() + try: + await future + finally: + thread.join() + + +T_Retval = TypeVar("T_Retval") +T_contra = TypeVar("T_contra", contravariant=True) +PosArgsT = TypeVarTuple("PosArgsT") +P = ParamSpec("P") + +_root_task: RunVar[asyncio.Task | None] = RunVar("_root_task") + + +def find_root_task() -> asyncio.Task: + root_task = _root_task.get(None) + if root_task is not None and not root_task.done(): + return root_task + + # Look for a task that has been started via run_until_complete() + for task in all_tasks(): + if task._callbacks and not task.done(): + callbacks = [cb for cb, context in task._callbacks] + for cb in callbacks: + if ( + cb is _run_until_complete_cb + or getattr(cb, "__module__", None) == "uvloop.loop" + ): + _root_task.set(task) + return task + + # Look up the topmost task in the AnyIO task tree, if possible + task = cast(asyncio.Task, current_task()) + state = _task_states.get(task) + if state: + cancel_scope = state.cancel_scope + while cancel_scope and cancel_scope._parent_scope is not None: + cancel_scope = cancel_scope._parent_scope + + if cancel_scope is not None: + return cast(asyncio.Task, cancel_scope._host_task) + + return task + + +def get_callable_name(func: Callable) -> str: + module = getattr(func, "__module__", None) + qualname = getattr(func, "__qualname__", None) + return ".".join([x for x in (module, qualname) if x]) + + +# +# Event loop +# + +_run_vars: WeakKeyDictionary[asyncio.AbstractEventLoop, Any] = WeakKeyDictionary() + + +def _task_started(task: asyncio.Task) -> bool: + """Return ``True`` if the task has been started and has not finished.""" + # The task coro should never be None here, as we never add finished tasks to the + # task list + coro = task.get_coro() + assert coro is not None + try: + return getcoroutinestate(coro) in (CORO_RUNNING, CORO_SUSPENDED) + except AttributeError: + # task coro is async_genenerator_asend https://bugs.python.org/issue37771 + raise Exception(f"Cannot determine if task {task} has started or not") from None + + +# +# Timeouts and cancellation +# + + +def is_anyio_cancellation(exc: CancelledError) -> bool: + # Sometimes third party frameworks catch a CancelledError and raise a new one, so as + # a workaround we have to look at the previous ones in __context__ too for a + # matching cancel message + while True: + if ( + exc.args + and isinstance(exc.args[0], str) + and exc.args[0].startswith("Cancelled via cancel scope ") + ): + return True + + if isinstance(exc.__context__, CancelledError): + exc = exc.__context__ + continue + + return False + + +class CancelScope(BaseCancelScope): + def __new__( + cls, *, deadline: float = math.inf, shield: bool = False + ) -> CancelScope: + return object.__new__(cls) + + def __init__(self, deadline: float = math.inf, shield: bool = False): + self._deadline = deadline + self._shield = shield + self._parent_scope: CancelScope | None = None + self._child_scopes: set[CancelScope] = set() + self._cancel_called = False + self._cancel_reason: str | None = None + self._cancelled_caught = False + self._active = False + self._timeout_handle: asyncio.TimerHandle | None = None + self._cancel_handle: asyncio.Handle | None = None + self._tasks: set[asyncio.Task] = set() + self._host_task: asyncio.Task | None = None + if sys.version_info >= (3, 11): + self._pending_uncancellations: int | None = 0 + else: + self._pending_uncancellations = None + + def __enter__(self) -> CancelScope: + if self._active: + raise RuntimeError( + "Each CancelScope may only be used for a single 'with' block" + ) + + self._host_task = host_task = cast(asyncio.Task, current_task()) + self._tasks.add(host_task) + try: + task_state = _task_states[host_task] + except KeyError: + task_state = TaskState(None, self) + _task_states[host_task] = task_state + else: + self._parent_scope = task_state.cancel_scope + task_state.cancel_scope = self + if self._parent_scope is not None: + # If using an eager task factory, the parent scope may not even contain + # the host task + self._parent_scope._child_scopes.add(self) + self._parent_scope._tasks.discard(host_task) + + self._timeout() + self._active = True + + # Start cancelling the host task if the scope was cancelled before entering + if self._cancel_called: + self._deliver_cancellation(self) + + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> bool: + del exc_tb + + if not self._active: + raise RuntimeError("This cancel scope is not active") + if current_task() is not self._host_task: + raise RuntimeError( + "Attempted to exit cancel scope in a different task than it was " + "entered in" + ) + + assert self._host_task is not None + host_task_state = _task_states.get(self._host_task) + if host_task_state is None or host_task_state.cancel_scope is not self: + raise RuntimeError( + "Attempted to exit a cancel scope that isn't the current tasks's " + "current cancel scope" + ) + + try: + self._active = False + if self._timeout_handle: + self._timeout_handle.cancel() + self._timeout_handle = None + + self._tasks.remove(self._host_task) + if self._parent_scope is not None: + self._parent_scope._child_scopes.remove(self) + self._parent_scope._tasks.add(self._host_task) + + host_task_state.cancel_scope = self._parent_scope + + # Restart the cancellation effort in the closest visible, cancelled parent + # scope if necessary + self._restart_cancellation_in_parent() + + # We only swallow the exception iff it was an AnyIO CancelledError, either + # directly as exc_val or inside an exception group and there are no cancelled + # parent cancel scopes visible to us here + if self._cancel_called and not self._parent_cancellation_is_visible_to_us: + # For each level-cancel() call made on the host task, call uncancel() + while self._pending_uncancellations: + self._host_task.uncancel() + self._pending_uncancellations -= 1 + + # Update cancelled_caught and check for exceptions we must not swallow + cannot_swallow_exc_val = False + if exc_val is not None: + for exc in iterate_exceptions(exc_val): + if isinstance(exc, CancelledError) and is_anyio_cancellation( + exc + ): + self._cancelled_caught = True + else: + cannot_swallow_exc_val = True + + return self._cancelled_caught and not cannot_swallow_exc_val + else: + if self._pending_uncancellations: + assert self._parent_scope is not None + assert self._parent_scope._pending_uncancellations is not None + self._parent_scope._pending_uncancellations += ( + self._pending_uncancellations + ) + self._pending_uncancellations = 0 + + return False + finally: + self._host_task = None + del exc_val + + @property + def _effectively_cancelled(self) -> bool: + cancel_scope: CancelScope | None = self + while cancel_scope is not None: + if cancel_scope._cancel_called: + return True + + if cancel_scope.shield: + return False + + cancel_scope = cancel_scope._parent_scope + + return False + + @property + def _parent_cancellation_is_visible_to_us(self) -> bool: + return ( + self._parent_scope is not None + and not self.shield + and self._parent_scope._effectively_cancelled + ) + + def _timeout(self) -> None: + if self._deadline != math.inf: + loop = get_running_loop() + if loop.time() >= self._deadline: + self.cancel("deadline exceeded") + else: + self._timeout_handle = loop.call_at(self._deadline, self._timeout) + + def _deliver_cancellation(self, origin: CancelScope) -> bool: + """ + Deliver cancellation to directly contained tasks and nested cancel scopes. + + Schedule another run at the end if we still have tasks eligible for + cancellation. + + :param origin: the cancel scope that originated the cancellation + :return: ``True`` if the delivery needs to be retried on the next cycle + + """ + should_retry = False + current = current_task() + for task in self._tasks: + should_retry = True + if task._must_cancel: # type: ignore[attr-defined] + continue + + # The task is eligible for cancellation if it has started + if task is not current and (task is self._host_task or _task_started(task)): + waiter = task._fut_waiter # type: ignore[attr-defined] + if not isinstance(waiter, asyncio.Future) or not waiter.done(): + task.cancel(origin._cancel_reason) + if ( + task is origin._host_task + and origin._pending_uncancellations is not None + ): + origin._pending_uncancellations += 1 + + # Deliver cancellation to child scopes that aren't shielded or running their own + # cancellation callbacks + for scope in self._child_scopes: + if not scope._shield and not scope.cancel_called: + should_retry = scope._deliver_cancellation(origin) or should_retry + + # Schedule another callback if there are still tasks left + if origin is self: + if should_retry: + self._cancel_handle = get_running_loop().call_soon( + self._deliver_cancellation, origin + ) + else: + self._cancel_handle = None + + return should_retry + + def _restart_cancellation_in_parent(self) -> None: + """ + Restart the cancellation effort in the closest directly cancelled parent scope. + + """ + scope = self._parent_scope + while scope is not None: + if scope._cancel_called: + if scope._cancel_handle is None: + scope._deliver_cancellation(scope) + + break + + # No point in looking beyond any shielded scope + if scope._shield: + break + + scope = scope._parent_scope + + def cancel(self, reason: str | None = None) -> None: + if not self._cancel_called: + if self._timeout_handle: + self._timeout_handle.cancel() + self._timeout_handle = None + + self._cancel_called = True + self._cancel_reason = f"Cancelled via cancel scope {id(self):x}" + if task := current_task(): + self._cancel_reason += f" by {task}" + + if reason: + self._cancel_reason += f"; reason: {reason}" + + if self._host_task is not None: + self._deliver_cancellation(self) + + @property + def deadline(self) -> float: + return self._deadline + + @deadline.setter + def deadline(self, value: float) -> None: + self._deadline = float(value) + if self._timeout_handle is not None: + self._timeout_handle.cancel() + self._timeout_handle = None + + if self._active and not self._cancel_called: + self._timeout() + + @property + def cancel_called(self) -> bool: + return self._cancel_called + + @property + def cancelled_caught(self) -> bool: + return self._cancelled_caught + + @property + def shield(self) -> bool: + return self._shield + + @shield.setter + def shield(self, value: bool) -> None: + if self._shield != value: + self._shield = value + if not value: + self._restart_cancellation_in_parent() + + +# +# Task states +# + + +class TaskState: + """ + Encapsulates auxiliary task information that cannot be added to the Task instance + itself because there are no guarantees about its implementation. + """ + + __slots__ = "parent_id", "cancel_scope", "__weakref__" + + def __init__(self, parent_id: int | None, cancel_scope: CancelScope | None): + self.parent_id = parent_id + self.cancel_scope = cancel_scope + + +_task_states: WeakKeyDictionary[asyncio.Task, TaskState] = WeakKeyDictionary() + + +# +# Task groups +# + + +class _AsyncioTaskStatus(abc.TaskStatus): + def __init__(self, future: asyncio.Future, parent_id: int): + self._future = future + self._parent_id = parent_id + + def started(self, value: T_contra | None = None) -> None: + try: + self._future.set_result(value) + except asyncio.InvalidStateError: + if not self._future.cancelled(): + raise RuntimeError( + "called 'started' twice on the same task status" + ) from None + + task = cast(asyncio.Task, current_task()) + _task_states[task].parent_id = self._parent_id + + +if sys.version_info >= (3, 12): + _eager_task_factory_code: CodeType | None = asyncio.eager_task_factory.__code__ +else: + _eager_task_factory_code = None + + +class TaskGroup(abc.TaskGroup): + def __init__(self) -> None: + self.cancel_scope: CancelScope = CancelScope() + self._active = False + self._exceptions: list[BaseException] = [] + self._tasks: set[asyncio.Task] = set() + self._on_completed_fut: asyncio.Future[None] | None = None + + async def __aenter__(self) -> TaskGroup: + self.cancel_scope.__enter__() + self._active = True + return self + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> bool: + try: + if exc_val is not None: + self.cancel_scope.cancel() + if not isinstance(exc_val, CancelledError): + self._exceptions.append(exc_val) + + loop = get_running_loop() + try: + if self._tasks: + with CancelScope() as wait_scope: + while self._tasks: + self._on_completed_fut = loop.create_future() + + try: + await self._on_completed_fut + except CancelledError as exc: + # Shield the scope against further cancellation attempts, + # as they're not productive (#695) + wait_scope.shield = True + self.cancel_scope.cancel() + + # Set exc_val from the cancellation exception if it was + # previously unset. However, we should not replace a native + # cancellation exception with one raise by a cancel scope. + if exc_val is None or ( + isinstance(exc_val, CancelledError) + and not is_anyio_cancellation(exc) + ): + exc_val = exc + + self._on_completed_fut = None + else: + # If there are no child tasks to wait on, run at least one checkpoint + # anyway + await AsyncIOBackend.cancel_shielded_checkpoint() + + self._active = False + if self._exceptions: + # The exception that got us here should already have been + # added to self._exceptions so it's ok to break exception + # chaining and avoid adding a "During handling of above..." + # for each nesting level. + raise BaseExceptionGroup( + "unhandled errors in a TaskGroup", self._exceptions + ) from None + elif exc_val: + raise exc_val + except BaseException as exc: + if self.cancel_scope.__exit__(type(exc), exc, exc.__traceback__): + return True + + raise + + return self.cancel_scope.__exit__(exc_type, exc_val, exc_tb) + finally: + del exc_val, exc_tb, self._exceptions + + def _spawn( + self, + func: Callable[[Unpack[PosArgsT]], Awaitable[Any]], + args: tuple[Unpack[PosArgsT]], + name: object, + task_status_future: asyncio.Future | None = None, + ) -> asyncio.Task: + def task_done(_task: asyncio.Task) -> None: + if sys.version_info >= (3, 14) and self.cancel_scope._host_task is not None: + asyncio.future_discard_from_awaited_by( + _task, self.cancel_scope._host_task + ) + + task_state = _task_states[_task] + assert task_state.cancel_scope is not None + assert _task in task_state.cancel_scope._tasks + task_state.cancel_scope._tasks.remove(_task) + self._tasks.remove(task) + del _task_states[_task] + + if self._on_completed_fut is not None and not self._tasks: + try: + self._on_completed_fut.set_result(None) + except asyncio.InvalidStateError: + pass + + try: + exc = _task.exception() + except CancelledError as e: + while isinstance(e.__context__, CancelledError): + e = e.__context__ + + exc = e + + if exc is not None: + # The future can only be in the cancelled state if the host task was + # cancelled, so return immediately instead of adding one more + # CancelledError to the exceptions list + if task_status_future is not None and task_status_future.cancelled(): + return + + if task_status_future is None or task_status_future.done(): + if not isinstance(exc, CancelledError): + self._exceptions.append(exc) + + if not self.cancel_scope._effectively_cancelled: + self.cancel_scope.cancel() + else: + task_status_future.set_exception(exc) + elif task_status_future is not None and not task_status_future.done(): + task_status_future.set_exception( + RuntimeError("Child exited without calling task_status.started()") + ) + + if not self._active: + raise RuntimeError( + "This task group is not active; no new tasks can be started." + ) + + kwargs = {} + if task_status_future: + parent_id = id(current_task()) + kwargs["task_status"] = _AsyncioTaskStatus( + task_status_future, id(self.cancel_scope._host_task) + ) + else: + parent_id = id(self.cancel_scope._host_task) + + coro = func(*args, **kwargs) + if not iscoroutine(coro): + prefix = f"{func.__module__}." if hasattr(func, "__module__") else "" + raise TypeError( + f"Expected {prefix}{func.__qualname__}() to return a coroutine, but " + f"the return value ({coro!r}) is not a coroutine object" + ) + + name = get_callable_name(func) if name is None else str(name) + loop = asyncio.get_running_loop() + if ( + (factory := loop.get_task_factory()) + and getattr(factory, "__code__", None) is _eager_task_factory_code + and (closure := getattr(factory, "__closure__", None)) + ): + custom_task_constructor = closure[0].cell_contents + task = custom_task_constructor(coro, loop=loop, name=name) + else: + task = create_task(coro, name=name) + + # Make the spawned task inherit the task group's cancel scope + _task_states[task] = TaskState( + parent_id=parent_id, cancel_scope=self.cancel_scope + ) + self.cancel_scope._tasks.add(task) + self._tasks.add(task) + if sys.version_info >= (3, 14) and self.cancel_scope._host_task is not None: + asyncio.future_add_to_awaited_by(task, self.cancel_scope._host_task) + + task.add_done_callback(task_done) + return task + + def start_soon( + self, + func: Callable[[Unpack[PosArgsT]], Awaitable[Any]], + *args: Unpack[PosArgsT], + name: object = None, + ) -> None: + self._spawn(func, args, name) + + async def start( + self, func: Callable[..., Awaitable[Any]], *args: object, name: object = None + ) -> Any: + future: asyncio.Future = asyncio.Future() + task = self._spawn(func, args, name, future) + + # If the task raises an exception after sending a start value without a switch + # point between, the task group is cancelled and this method never proceeds to + # process the completed future. That's why we have to have a shielded cancel + # scope here. + try: + return await future + except CancelledError: + # Cancel the task and wait for it to exit before returning + task.cancel() + with CancelScope(shield=True), suppress(CancelledError): + await task + + raise + + +# +# Threads +# + +_Retval_Queue_Type = tuple[Optional[T_Retval], Optional[BaseException]] + + +class WorkerThread(Thread): + MAX_IDLE_TIME = 10 # seconds + + def __init__( + self, + root_task: asyncio.Task, + workers: set[WorkerThread], + idle_workers: deque[WorkerThread], + ): + super().__init__(name="AnyIO worker thread") + self.root_task = root_task + self.workers = workers + self.idle_workers = idle_workers + self.loop = root_task._loop + self.queue: Queue[ + tuple[Context, Callable, tuple, asyncio.Future, CancelScope] | None + ] = Queue(2) + self.idle_since = AsyncIOBackend.current_time() + self.stopping = False + + def _report_result( + self, future: asyncio.Future, result: Any, exc: BaseException | None + ) -> None: + self.idle_since = AsyncIOBackend.current_time() + if not self.stopping: + self.idle_workers.append(self) + + if not future.cancelled(): + if exc is not None: + if isinstance(exc, StopIteration): + new_exc = RuntimeError("coroutine raised StopIteration") + new_exc.__cause__ = exc + exc = new_exc + + future.set_exception(exc) + else: + future.set_result(result) + + def run(self) -> None: + with claim_worker_thread(AsyncIOBackend, self.loop): + while True: + item = self.queue.get() + if item is None: + # Shutdown command received + return + + context, func, args, future, cancel_scope = item + if not future.cancelled(): + result = None + exception: BaseException | None = None + threadlocals.current_cancel_scope = cancel_scope + try: + result = context.run(func, *args) + except BaseException as exc: + exception = exc + finally: + del threadlocals.current_cancel_scope + + if not self.loop.is_closed(): + self.loop.call_soon_threadsafe( + self._report_result, future, result, exception + ) + + del result, exception + + self.queue.task_done() + del item, context, func, args, future, cancel_scope + + def stop(self, f: asyncio.Task | None = None) -> None: + self.stopping = True + self.queue.put_nowait(None) + self.workers.discard(self) + try: + self.idle_workers.remove(self) + except ValueError: + pass + + +_threadpool_idle_workers: RunVar[deque[WorkerThread]] = RunVar( + "_threadpool_idle_workers" +) +_threadpool_workers: RunVar[set[WorkerThread]] = RunVar("_threadpool_workers") + + +class BlockingPortal(abc.BlockingPortal): + def __new__(cls) -> BlockingPortal: + return object.__new__(cls) + + def __init__(self) -> None: + super().__init__() + self._loop = get_running_loop() + + def _spawn_task_from_thread( + self, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval], + args: tuple[Unpack[PosArgsT]], + kwargs: dict[str, Any], + name: object, + future: Future[T_Retval], + ) -> None: + AsyncIOBackend.run_sync_from_thread( + partial(self._task_group.start_soon, name=name), + (self._call_func, func, args, kwargs, future), + self._loop, + ) + + +# +# Subprocesses +# + + +@dataclass(eq=False) +class StreamReaderWrapper(abc.ByteReceiveStream): + _stream: asyncio.StreamReader + + async def receive(self, max_bytes: int = 65536) -> bytes: + data = await self._stream.read(max_bytes) + if data: + return data + else: + raise EndOfStream + + async def aclose(self) -> None: + self._stream.set_exception(ClosedResourceError()) + await AsyncIOBackend.checkpoint() + + +@dataclass(eq=False) +class StreamWriterWrapper(abc.ByteSendStream): + _stream: asyncio.StreamWriter + _closed: bool = field(init=False, default=False) + + async def send(self, item: bytes) -> None: + await AsyncIOBackend.checkpoint_if_cancelled() + stream_paused = self._stream._protocol._paused # type: ignore[attr-defined] + try: + self._stream.write(item) + await self._stream.drain() + except (ConnectionResetError, BrokenPipeError, RuntimeError) as exc: + # If closed by us and/or the peer: + # * on stdlib, drain() raises ConnectionResetError or BrokenPipeError + # * on uvloop and Winloop, write() eventually starts raising RuntimeError + if self._closed: + raise ClosedResourceError from exc + elif self._stream.is_closing(): + raise BrokenResourceError from exc + + raise + + if not stream_paused: + await AsyncIOBackend.cancel_shielded_checkpoint() + + async def aclose(self) -> None: + self._closed = True + self._stream.close() + await AsyncIOBackend.checkpoint() + + +@dataclass(eq=False) +class Process(abc.Process): + _process: asyncio.subprocess.Process + _stdin: StreamWriterWrapper | None + _stdout: StreamReaderWrapper | None + _stderr: StreamReaderWrapper | None + + async def aclose(self) -> None: + with CancelScope(shield=True) as scope: + if self._stdin: + await self._stdin.aclose() + if self._stdout: + await self._stdout.aclose() + if self._stderr: + await self._stderr.aclose() + + scope.shield = False + try: + await self.wait() + except BaseException: + scope.shield = True + self.kill() + await self.wait() + raise + + async def wait(self) -> int: + return await self._process.wait() + + def terminate(self) -> None: + self._process.terminate() + + def kill(self) -> None: + self._process.kill() + + def send_signal(self, signal: int) -> None: + self._process.send_signal(signal) + + @property + def pid(self) -> int: + return self._process.pid + + @property + def returncode(self) -> int | None: + return self._process.returncode + + @property + def stdin(self) -> abc.ByteSendStream | None: + return self._stdin + + @property + def stdout(self) -> abc.ByteReceiveStream | None: + return self._stdout + + @property + def stderr(self) -> abc.ByteReceiveStream | None: + return self._stderr + + +def _forcibly_shutdown_process_pool_on_exit( + workers: set[Process], _task: object +) -> None: + """ + Forcibly shuts down worker processes belonging to this event loop.""" + child_watcher: asyncio.AbstractChildWatcher | None = None # type: ignore[name-defined] + if sys.version_info < (3, 12): + try: + child_watcher = asyncio.get_event_loop_policy().get_child_watcher() + except NotImplementedError: + pass + + # Close as much as possible (w/o async/await) to avoid warnings + for process in workers.copy(): + if process.returncode is None: + continue + + process._stdin._stream._transport.close() # type: ignore[union-attr] + process._stdout._stream._transport.close() # type: ignore[union-attr] + process._stderr._stream._transport.close() # type: ignore[union-attr] + process.kill() + if child_watcher: + child_watcher.remove_child_handler(process.pid) + + +async def _shutdown_process_pool_on_exit(workers: set[abc.Process]) -> None: + """ + Shuts down worker processes belonging to this event loop. + + NOTE: this only works when the event loop was started using asyncio.run() or + anyio.run(). + + """ + process: abc.Process + try: + await sleep(math.inf) + except asyncio.CancelledError: + workers = workers.copy() + for process in workers: + if process.returncode is None: + process.kill() + + for process in workers: + await process.aclose() + + +# +# Sockets and networking +# + + +class StreamProtocol(asyncio.Protocol): + read_queue: deque[bytes] + read_event: asyncio.Event + write_event: asyncio.Event + exception: Exception | None = None + is_at_eof: bool = False + + def connection_made(self, transport: asyncio.BaseTransport) -> None: + self.read_queue = deque() + self.read_event = asyncio.Event() + self.write_event = asyncio.Event() + self.write_event.set() + cast(asyncio.Transport, transport).set_write_buffer_limits(0) + + def connection_lost(self, exc: Exception | None) -> None: + if exc: + self.exception = BrokenResourceError() + self.exception.__cause__ = exc + + self.read_event.set() + self.write_event.set() + + def data_received(self, data: bytes) -> None: + # ProactorEventloop sometimes sends bytearray instead of bytes + self.read_queue.append(bytes(data)) + self.read_event.set() + + def eof_received(self) -> bool | None: + self.is_at_eof = True + self.read_event.set() + return True + + def pause_writing(self) -> None: + self.write_event = asyncio.Event() + + def resume_writing(self) -> None: + self.write_event.set() + + +class DatagramProtocol(asyncio.DatagramProtocol): + read_queue: deque[tuple[bytes, IPSockAddrType]] + read_event: asyncio.Event + write_event: asyncio.Event + exception: Exception | None = None + + def connection_made(self, transport: asyncio.BaseTransport) -> None: + self.read_queue = deque(maxlen=100) # arbitrary value + self.read_event = asyncio.Event() + self.write_event = asyncio.Event() + self.write_event.set() + + def connection_lost(self, exc: Exception | None) -> None: + self.read_event.set() + self.write_event.set() + + def datagram_received(self, data: bytes, addr: IPSockAddrType) -> None: + addr = convert_ipv6_sockaddr(addr) + self.read_queue.append((data, addr)) + self.read_event.set() + + def error_received(self, exc: Exception) -> None: + self.exception = exc + + def pause_writing(self) -> None: + self.write_event.clear() + + def resume_writing(self) -> None: + self.write_event.set() + + +class SocketStream(abc.SocketStream): + def __init__(self, transport: asyncio.Transport, protocol: StreamProtocol): + self._transport = transport + self._protocol = protocol + self._receive_guard = ResourceGuard("reading from") + self._send_guard = ResourceGuard("writing to") + self._closed = False + + @property + def _raw_socket(self) -> socket.socket: + return self._transport.get_extra_info("socket") + + async def receive(self, max_bytes: int = 65536) -> bytes: + with self._receive_guard: + if ( + not self._protocol.read_event.is_set() + and not self._transport.is_closing() + and not self._protocol.is_at_eof + ): + self._transport.resume_reading() + await self._protocol.read_event.wait() + self._transport.pause_reading() + else: + await AsyncIOBackend.checkpoint() + + try: + chunk = self._protocol.read_queue.popleft() + except IndexError: + if self._closed: + raise ClosedResourceError from None + elif self._protocol.exception: + raise self._protocol.exception from None + else: + raise EndOfStream from None + + if len(chunk) > max_bytes: + # Split the oversized chunk + chunk, leftover = chunk[:max_bytes], chunk[max_bytes:] + self._protocol.read_queue.appendleft(leftover) + + # If the read queue is empty, clear the flag so that the next call will + # block until data is available + if not self._protocol.read_queue: + self._protocol.read_event.clear() + + return chunk + + async def send(self, item: bytes) -> None: + with self._send_guard: + await AsyncIOBackend.checkpoint() + + if self._closed: + raise ClosedResourceError + elif self._protocol.exception is not None: + raise self._protocol.exception + + try: + self._transport.write(item) + except RuntimeError as exc: + if self._transport.is_closing(): + raise BrokenResourceError from exc + else: + raise + + await self._protocol.write_event.wait() + + async def send_eof(self) -> None: + try: + self._transport.write_eof() + except OSError: + pass + + async def aclose(self) -> None: + self._closed = True + if not self._transport.is_closing(): + try: + self._transport.write_eof() + except OSError: + pass + + self._transport.close() + await sleep(0) + self._transport.abort() + + +class _RawSocketMixin: + _receive_future: asyncio.Future | None = None + _send_future: asyncio.Future | None = None + _closing = False + + def __init__(self, raw_socket: socket.socket): + self.__raw_socket = raw_socket + self._receive_guard = ResourceGuard("reading from") + self._send_guard = ResourceGuard("writing to") + + @property + def _raw_socket(self) -> socket.socket: + return self.__raw_socket + + def _wait_until_readable(self, loop: asyncio.AbstractEventLoop) -> asyncio.Future: + def callback(f: object) -> None: + del self._receive_future + loop.remove_reader(self.__raw_socket) + + f = self._receive_future = asyncio.Future() + loop.add_reader(self.__raw_socket, f.set_result, None) + f.add_done_callback(callback) + return f + + def _wait_until_writable(self, loop: asyncio.AbstractEventLoop) -> asyncio.Future: + def callback(f: object) -> None: + del self._send_future + loop.remove_writer(self.__raw_socket) + + f = self._send_future = asyncio.Future() + loop.add_writer(self.__raw_socket, f.set_result, None) + f.add_done_callback(callback) + return f + + async def aclose(self) -> None: + if not self._closing: + self._closing = True + if self.__raw_socket.fileno() != -1: + self.__raw_socket.close() + + if self._receive_future: + self._receive_future.set_result(None) + if self._send_future: + self._send_future.set_result(None) + + +class UNIXSocketStream(_RawSocketMixin, abc.UNIXSocketStream): + async def send_eof(self) -> None: + with self._send_guard: + self._raw_socket.shutdown(socket.SHUT_WR) + + async def receive(self, max_bytes: int = 65536) -> bytes: + loop = get_running_loop() + await AsyncIOBackend.checkpoint() + with self._receive_guard: + while True: + try: + data = self._raw_socket.recv(max_bytes) + except BlockingIOError: + await self._wait_until_readable(loop) + except OSError as exc: + if self._closing: + raise ClosedResourceError from None + else: + raise BrokenResourceError from exc + else: + if not data: + raise EndOfStream + + return data + + async def send(self, item: bytes) -> None: + loop = get_running_loop() + await AsyncIOBackend.checkpoint() + with self._send_guard: + view = memoryview(item) + while view: + try: + bytes_sent = self._raw_socket.send(view) + except BlockingIOError: + await self._wait_until_writable(loop) + except OSError as exc: + if self._closing: + raise ClosedResourceError from None + else: + raise BrokenResourceError from exc + else: + view = view[bytes_sent:] + + async def receive_fds(self, msglen: int, maxfds: int) -> tuple[bytes, list[int]]: + if not isinstance(msglen, int) or msglen < 0: + raise ValueError("msglen must be a non-negative integer") + if not isinstance(maxfds, int) or maxfds < 1: + raise ValueError("maxfds must be a positive integer") + + loop = get_running_loop() + fds = array.array("i") + await AsyncIOBackend.checkpoint() + with self._receive_guard: + while True: + try: + message, ancdata, flags, addr = self._raw_socket.recvmsg( + msglen, socket.CMSG_LEN(maxfds * fds.itemsize) + ) + except BlockingIOError: + await self._wait_until_readable(loop) + except OSError as exc: + if self._closing: + raise ClosedResourceError from None + else: + raise BrokenResourceError from exc + else: + if not message and not ancdata: + raise EndOfStream + + break + + for cmsg_level, cmsg_type, cmsg_data in ancdata: + if cmsg_level != socket.SOL_SOCKET or cmsg_type != socket.SCM_RIGHTS: + raise RuntimeError( + f"Received unexpected ancillary data; message = {message!r}, " + f"cmsg_level = {cmsg_level}, cmsg_type = {cmsg_type}" + ) + + fds.frombytes(cmsg_data[: len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) + + return message, list(fds) + + async def send_fds(self, message: bytes, fds: Collection[int | IOBase]) -> None: + if not message: + raise ValueError("message must not be empty") + if not fds: + raise ValueError("fds must not be empty") + + loop = get_running_loop() + filenos: list[int] = [] + for fd in fds: + if isinstance(fd, int): + filenos.append(fd) + elif isinstance(fd, IOBase): + filenos.append(fd.fileno()) + + fdarray = array.array("i", filenos) + await AsyncIOBackend.checkpoint() + with self._send_guard: + while True: + try: + # The ignore can be removed after mypy picks up + # https://github.com/python/typeshed/pull/5545 + self._raw_socket.sendmsg( + [message], [(socket.SOL_SOCKET, socket.SCM_RIGHTS, fdarray)] + ) + break + except BlockingIOError: + await self._wait_until_writable(loop) + except OSError as exc: + if self._closing: + raise ClosedResourceError from None + else: + raise BrokenResourceError from exc + + +class TCPSocketListener(abc.SocketListener): + _accept_scope: CancelScope | None = None + _closed = False + + def __init__(self, raw_socket: socket.socket): + self.__raw_socket = raw_socket + self._loop = cast(asyncio.BaseEventLoop, get_running_loop()) + self._accept_guard = ResourceGuard("accepting connections from") + + @property + def _raw_socket(self) -> socket.socket: + return self.__raw_socket + + async def accept(self) -> abc.SocketStream: + if self._closed: + raise ClosedResourceError + + with self._accept_guard: + await AsyncIOBackend.checkpoint() + with CancelScope() as self._accept_scope: + try: + client_sock, _addr = await self._loop.sock_accept(self._raw_socket) + except asyncio.CancelledError: + # Workaround for https://bugs.python.org/issue41317 + try: + self._loop.remove_reader(self._raw_socket) + except (ValueError, NotImplementedError): + pass + + if self._closed: + raise ClosedResourceError from None + + raise + finally: + self._accept_scope = None + + client_sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + transport, protocol = await self._loop.connect_accepted_socket( + StreamProtocol, client_sock + ) + return SocketStream(transport, protocol) + + async def aclose(self) -> None: + if self._closed: + return + + self._closed = True + if self._accept_scope: + # Workaround for https://bugs.python.org/issue41317 + try: + self._loop.remove_reader(self._raw_socket) + except (ValueError, NotImplementedError): + pass + + self._accept_scope.cancel() + await sleep(0) + + self._raw_socket.close() + + +class UNIXSocketListener(abc.SocketListener): + def __init__(self, raw_socket: socket.socket): + self.__raw_socket = raw_socket + self._loop = get_running_loop() + self._accept_guard = ResourceGuard("accepting connections from") + self._closed = False + + async def accept(self) -> abc.SocketStream: + await AsyncIOBackend.checkpoint() + with self._accept_guard: + while True: + try: + client_sock, _ = self.__raw_socket.accept() + client_sock.setblocking(False) + return UNIXSocketStream(client_sock) + except BlockingIOError: + f: asyncio.Future = asyncio.Future() + self._loop.add_reader(self.__raw_socket, f.set_result, None) + f.add_done_callback( + lambda _: self._loop.remove_reader(self.__raw_socket) + ) + await f + except OSError as exc: + if self._closed: + raise ClosedResourceError from None + else: + raise BrokenResourceError from exc + + async def aclose(self) -> None: + self._closed = True + self.__raw_socket.close() + + @property + def _raw_socket(self) -> socket.socket: + return self.__raw_socket + + +class UDPSocket(abc.UDPSocket): + def __init__( + self, transport: asyncio.DatagramTransport, protocol: DatagramProtocol + ): + self._transport = transport + self._protocol = protocol + self._receive_guard = ResourceGuard("reading from") + self._send_guard = ResourceGuard("writing to") + self._closed = False + + @property + def _raw_socket(self) -> socket.socket: + return self._transport.get_extra_info("socket") + + async def aclose(self) -> None: + self._closed = True + if not self._transport.is_closing(): + self._transport.close() + + async def receive(self) -> tuple[bytes, IPSockAddrType]: + with self._receive_guard: + await AsyncIOBackend.checkpoint() + + # If the buffer is empty, ask for more data + if not self._protocol.read_queue and not self._transport.is_closing(): + self._protocol.read_event.clear() + await self._protocol.read_event.wait() + + try: + return self._protocol.read_queue.popleft() + except IndexError: + if self._closed: + raise ClosedResourceError from None + else: + raise BrokenResourceError from None + + async def send(self, item: UDPPacketType) -> None: + with self._send_guard: + await AsyncIOBackend.checkpoint() + await self._protocol.write_event.wait() + if self._closed: + raise ClosedResourceError + elif self._transport.is_closing(): + raise BrokenResourceError + else: + self._transport.sendto(*item) + + +class ConnectedUDPSocket(abc.ConnectedUDPSocket): + def __init__( + self, transport: asyncio.DatagramTransport, protocol: DatagramProtocol + ): + self._transport = transport + self._protocol = protocol + self._receive_guard = ResourceGuard("reading from") + self._send_guard = ResourceGuard("writing to") + self._closed = False + + @property + def _raw_socket(self) -> socket.socket: + return self._transport.get_extra_info("socket") + + async def aclose(self) -> None: + self._closed = True + if not self._transport.is_closing(): + self._transport.close() + + async def receive(self) -> bytes: + with self._receive_guard: + await AsyncIOBackend.checkpoint() + + # If the buffer is empty, ask for more data + if not self._protocol.read_queue and not self._transport.is_closing(): + self._protocol.read_event.clear() + await self._protocol.read_event.wait() + + try: + packet = self._protocol.read_queue.popleft() + except IndexError: + if self._closed: + raise ClosedResourceError from None + else: + raise BrokenResourceError from None + + return packet[0] + + async def send(self, item: bytes) -> None: + with self._send_guard: + await AsyncIOBackend.checkpoint() + await self._protocol.write_event.wait() + if self._closed: + raise ClosedResourceError + elif self._transport.is_closing(): + raise BrokenResourceError + else: + self._transport.sendto(item) + + +class UNIXDatagramSocket(_RawSocketMixin, abc.UNIXDatagramSocket): + async def receive(self) -> UNIXDatagramPacketType: + loop = get_running_loop() + await AsyncIOBackend.checkpoint() + with self._receive_guard: + while True: + try: + data = self._raw_socket.recvfrom(65536) + except BlockingIOError: + await self._wait_until_readable(loop) + except OSError as exc: + if self._closing: + raise ClosedResourceError from None + else: + raise BrokenResourceError from exc + else: + return data + + async def send(self, item: UNIXDatagramPacketType) -> None: + loop = get_running_loop() + await AsyncIOBackend.checkpoint() + with self._send_guard: + while True: + try: + self._raw_socket.sendto(*item) + except BlockingIOError: + await self._wait_until_writable(loop) + except OSError as exc: + if self._closing: + raise ClosedResourceError from None + else: + raise BrokenResourceError from exc + else: + return + + +class ConnectedUNIXDatagramSocket(_RawSocketMixin, abc.ConnectedUNIXDatagramSocket): + async def receive(self) -> bytes: + loop = get_running_loop() + await AsyncIOBackend.checkpoint() + with self._receive_guard: + while True: + try: + data = self._raw_socket.recv(65536) + except BlockingIOError: + await self._wait_until_readable(loop) + except OSError as exc: + if self._closing: + raise ClosedResourceError from None + else: + raise BrokenResourceError from exc + else: + return data + + async def send(self, item: bytes) -> None: + loop = get_running_loop() + await AsyncIOBackend.checkpoint() + with self._send_guard: + while True: + try: + self._raw_socket.send(item) + except BlockingIOError: + await self._wait_until_writable(loop) + except OSError as exc: + if self._closing: + raise ClosedResourceError from None + else: + raise BrokenResourceError from exc + else: + return + + +_read_events: RunVar[dict[int, asyncio.Future[bool]]] = RunVar("read_events") +_write_events: RunVar[dict[int, asyncio.Future[bool]]] = RunVar("write_events") + + +# +# Synchronization +# + + +class Event(BaseEvent): + def __new__(cls) -> Event: + return object.__new__(cls) + + def __init__(self) -> None: + self._event = asyncio.Event() + + def set(self) -> None: + self._event.set() + + def is_set(self) -> bool: + return self._event.is_set() + + async def wait(self) -> None: + if self.is_set(): + await AsyncIOBackend.checkpoint() + else: + await self._event.wait() + + def statistics(self) -> EventStatistics: + return EventStatistics(len(self._event._waiters)) + + +class Lock(BaseLock): + def __new__(cls, *, fast_acquire: bool = False) -> Lock: + return object.__new__(cls) + + def __init__(self, *, fast_acquire: bool = False) -> None: + self._fast_acquire = fast_acquire + self._owner_task: asyncio.Task | None = None + self._waiters: deque[tuple[asyncio.Task, asyncio.Future]] = deque() + + async def acquire(self) -> None: + task = cast(asyncio.Task, current_task()) + if self._owner_task is None and not self._waiters: + await AsyncIOBackend.checkpoint_if_cancelled() + self._owner_task = task + + # Unless on the "fast path", yield control of the event loop so that other + # tasks can run too + if not self._fast_acquire: + try: + await AsyncIOBackend.cancel_shielded_checkpoint() + except CancelledError: + self.release() + raise + + return + + if self._owner_task == task: + raise RuntimeError("Attempted to acquire an already held Lock") + + fut: asyncio.Future[None] = asyncio.Future() + item = task, fut + self._waiters.append(item) + try: + await fut + except CancelledError: + self._waiters.remove(item) + if self._owner_task is task: + self.release() + + raise + + self._waiters.remove(item) + + def acquire_nowait(self) -> None: + task = cast(asyncio.Task, current_task()) + if self._owner_task is None and not self._waiters: + self._owner_task = task + return + + if self._owner_task is task: + raise RuntimeError("Attempted to acquire an already held Lock") + + raise WouldBlock + + def locked(self) -> bool: + return self._owner_task is not None + + def release(self) -> None: + if self._owner_task != current_task(): + raise RuntimeError("The current task is not holding this lock") + + for task, fut in self._waiters: + if not fut.cancelled(): + self._owner_task = task + fut.set_result(None) + return + + self._owner_task = None + + def statistics(self) -> LockStatistics: + task_info = AsyncIOTaskInfo(self._owner_task) if self._owner_task else None + return LockStatistics(self.locked(), task_info, len(self._waiters)) + + +class Semaphore(BaseSemaphore): + def __new__( + cls, + initial_value: int, + *, + max_value: int | None = None, + fast_acquire: bool = False, + ) -> Semaphore: + return object.__new__(cls) + + def __init__( + self, + initial_value: int, + *, + max_value: int | None = None, + fast_acquire: bool = False, + ): + super().__init__(initial_value, max_value=max_value) + self._value = initial_value + self._max_value = max_value + self._fast_acquire = fast_acquire + self._waiters: deque[asyncio.Future[None]] = deque() + + async def acquire(self) -> None: + if self._value > 0 and not self._waiters: + await AsyncIOBackend.checkpoint_if_cancelled() + self._value -= 1 + + # Unless on the "fast path", yield control of the event loop so that other + # tasks can run too + if not self._fast_acquire: + try: + await AsyncIOBackend.cancel_shielded_checkpoint() + except CancelledError: + self.release() + raise + + return + + fut: asyncio.Future[None] = asyncio.Future() + self._waiters.append(fut) + try: + await fut + except CancelledError: + try: + self._waiters.remove(fut) + except ValueError: + self.release() + + raise + + def acquire_nowait(self) -> None: + if self._value == 0: + raise WouldBlock + + self._value -= 1 + + def release(self) -> None: + if self._max_value is not None and self._value == self._max_value: + raise ValueError("semaphore released too many times") + + for fut in self._waiters: + if not fut.cancelled(): + fut.set_result(None) + self._waiters.remove(fut) + return + + self._value += 1 + + @property + def value(self) -> int: + return self._value + + @property + def max_value(self) -> int | None: + return self._max_value + + def statistics(self) -> SemaphoreStatistics: + return SemaphoreStatistics(len(self._waiters)) + + +class CapacityLimiter(BaseCapacityLimiter): + _total_tokens: float = 0 + + def __new__(cls, total_tokens: float) -> CapacityLimiter: + return object.__new__(cls) + + def __init__(self, total_tokens: float): + self._borrowers: set[Any] = set() + self._wait_queue: OrderedDict[Any, asyncio.Event] = OrderedDict() + self.total_tokens = total_tokens + + async def __aenter__(self) -> None: + await self.acquire() + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self.release() + + @property + def total_tokens(self) -> float: + return self._total_tokens + + @total_tokens.setter + def total_tokens(self, value: float) -> None: + if not isinstance(value, int) and not math.isinf(value): + raise TypeError("total_tokens must be an int or math.inf") + + if value < 0: + raise ValueError("total_tokens must be >= 0") + + waiters_to_notify = max(value - self._total_tokens, 0) + self._total_tokens = value + + # Notify waiting tasks that they have acquired the limiter + while self._wait_queue and waiters_to_notify: + event = self._wait_queue.popitem(last=False)[1] + event.set() + waiters_to_notify -= 1 + + @property + def borrowed_tokens(self) -> int: + return len(self._borrowers) + + @property + def available_tokens(self) -> float: + return self._total_tokens - len(self._borrowers) + + def _notify_next_waiter(self) -> None: + """Notify the next task in line if this limiter has free capacity now.""" + if self._wait_queue and len(self._borrowers) < self._total_tokens: + event = self._wait_queue.popitem(last=False)[1] + event.set() + + def acquire_nowait(self) -> None: + self.acquire_on_behalf_of_nowait(current_task()) + + def acquire_on_behalf_of_nowait(self, borrower: object) -> None: + if borrower in self._borrowers: + raise RuntimeError( + "this borrower is already holding one of this CapacityLimiter's tokens" + ) + + if self._wait_queue or len(self._borrowers) >= self._total_tokens: + raise WouldBlock + + self._borrowers.add(borrower) + + async def acquire(self) -> None: + return await self.acquire_on_behalf_of(current_task()) + + async def acquire_on_behalf_of(self, borrower: object) -> None: + await AsyncIOBackend.checkpoint_if_cancelled() + try: + self.acquire_on_behalf_of_nowait(borrower) + except WouldBlock: + event = asyncio.Event() + self._wait_queue[borrower] = event + try: + await event.wait() + except BaseException: + self._wait_queue.pop(borrower, None) + if event.is_set(): + self._notify_next_waiter() + + raise + + self._borrowers.add(borrower) + else: + try: + await AsyncIOBackend.cancel_shielded_checkpoint() + except BaseException: + self.release() + raise + + def release(self) -> None: + self.release_on_behalf_of(current_task()) + + def release_on_behalf_of(self, borrower: object) -> None: + try: + self._borrowers.remove(borrower) + except KeyError: + raise RuntimeError( + "this borrower isn't holding any of this CapacityLimiter's tokens" + ) from None + + self._notify_next_waiter() + + def statistics(self) -> CapacityLimiterStatistics: + return CapacityLimiterStatistics( + self.borrowed_tokens, + self.total_tokens, + tuple(self._borrowers), + len(self._wait_queue), + ) + + +_default_thread_limiter: RunVar[CapacityLimiter] = RunVar("_default_thread_limiter") + + +# +# Operating system signals +# + + +class _SignalReceiver: + def __init__(self, signals: tuple[Signals, ...]): + self._signals = signals + self._loop = get_running_loop() + self._signal_queue: deque[Signals] = deque() + self._future: asyncio.Future = asyncio.Future() + self._handled_signals: set[Signals] = set() + + def _deliver(self, signum: Signals) -> None: + self._signal_queue.append(signum) + if not self._future.done(): + self._future.set_result(None) + + def __enter__(self) -> _SignalReceiver: + for sig in set(self._signals): + self._loop.add_signal_handler(sig, self._deliver, sig) + self._handled_signals.add(sig) + + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + for sig in self._handled_signals: + self._loop.remove_signal_handler(sig) + + def __aiter__(self) -> _SignalReceiver: + return self + + async def __anext__(self) -> Signals: + await AsyncIOBackend.checkpoint() + if not self._signal_queue: + self._future = asyncio.Future() + await self._future + + return self._signal_queue.popleft() + + +# +# Testing and debugging +# + + +class AsyncIOTaskInfo(TaskInfo): + def __init__(self, task: asyncio.Task): + task_state = _task_states.get(task) + if task_state is None: + parent_id = None + else: + parent_id = task_state.parent_id + + coro = task.get_coro() + assert coro is not None, "created TaskInfo from a completed Task" + super().__init__(id(task), parent_id, task.get_name(), coro) + self._task = weakref.ref(task) + + def has_pending_cancellation(self) -> bool: + if not (task := self._task()): + # If the task isn't around anymore, it won't have a pending cancellation + return False + + if task._must_cancel: # type: ignore[attr-defined] + return True + elif ( + isinstance(task._fut_waiter, asyncio.Future) # type: ignore[attr-defined] + and task._fut_waiter.cancelled() # type: ignore[attr-defined] + ): + return True + + if task_state := _task_states.get(task): + if cancel_scope := task_state.cancel_scope: + return cancel_scope._effectively_cancelled + + return False + + +class TestRunner(abc.TestRunner): + _send_stream: MemoryObjectSendStream[tuple[Awaitable[Any], asyncio.Future[Any]]] + + def __init__( + self, + *, + debug: bool | None = None, + use_uvloop: bool = False, + loop_factory: Callable[[], AbstractEventLoop] | None = None, + ) -> None: + if use_uvloop and loop_factory is None: + if sys.platform != "win32": + import uvloop + + loop_factory = uvloop.new_event_loop + else: + import winloop + + loop_factory = winloop.new_event_loop + + self._runner = Runner(debug=debug, loop_factory=loop_factory) + self._exceptions: list[BaseException] = [] + self._runner_task: asyncio.Task | None = None + + def __enter__(self) -> TestRunner: + self._runner.__enter__() + self.get_loop().set_exception_handler(self._exception_handler) + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self._runner.__exit__(exc_type, exc_val, exc_tb) + + def get_loop(self) -> AbstractEventLoop: + return self._runner.get_loop() + + def _exception_handler( + self, loop: asyncio.AbstractEventLoop, context: dict[str, Any] + ) -> None: + if isinstance(context.get("exception"), Exception): + self._exceptions.append(context["exception"]) + else: + loop.default_exception_handler(context) + + def _raise_async_exceptions(self) -> None: + # Re-raise any exceptions raised in asynchronous callbacks + if self._exceptions: + exceptions, self._exceptions = self._exceptions, [] + if len(exceptions) == 1: + raise exceptions[0] + elif exceptions: + raise BaseExceptionGroup( + "Multiple exceptions occurred in asynchronous callbacks", exceptions + ) + + async def _run_tests_and_fixtures( + self, + receive_stream: MemoryObjectReceiveStream[ + tuple[Awaitable[T_Retval], asyncio.Future[T_Retval]] + ], + ) -> None: + from _pytest.outcomes import OutcomeException + + with receive_stream, self._send_stream: + async for coro, future in receive_stream: + try: + retval = await coro + except CancelledError as exc: + if not future.cancelled(): + future.cancel(*exc.args) + + raise + except BaseException as exc: + if not future.cancelled(): + future.set_exception(exc) + + if not isinstance(exc, (Exception, OutcomeException)): + raise + else: + if not future.cancelled(): + future.set_result(retval) + + async def _call_in_runner_task( + self, + func: Callable[P, Awaitable[T_Retval]], + *args: P.args, + **kwargs: P.kwargs, + ) -> T_Retval: + if not self._runner_task: + self._send_stream, receive_stream = create_memory_object_stream[ + tuple[Awaitable[Any], asyncio.Future] + ](1) + self._runner_task = self.get_loop().create_task( + self._run_tests_and_fixtures(receive_stream) + ) + + coro = func(*args, **kwargs) + future: asyncio.Future[T_Retval] = self.get_loop().create_future() + self._send_stream.send_nowait((coro, future)) + return await future + + def run_asyncgen_fixture( + self, + fixture_func: Callable[..., AsyncGenerator[T_Retval, Any]], + kwargs: dict[str, Any], + ) -> Iterable[T_Retval]: + asyncgen = fixture_func(**kwargs) + fixturevalue: T_Retval = self.get_loop().run_until_complete( + self._call_in_runner_task(asyncgen.asend, None) + ) + self._raise_async_exceptions() + + yield fixturevalue + + try: + self.get_loop().run_until_complete( + self._call_in_runner_task(asyncgen.asend, None) + ) + except StopAsyncIteration: + self._raise_async_exceptions() + else: + self.get_loop().run_until_complete(asyncgen.aclose()) + raise RuntimeError("Async generator fixture did not stop") + + def run_fixture( + self, + fixture_func: Callable[..., Coroutine[Any, Any, T_Retval]], + kwargs: dict[str, Any], + ) -> T_Retval: + retval = self.get_loop().run_until_complete( + self._call_in_runner_task(fixture_func, **kwargs) + ) + self._raise_async_exceptions() + return retval + + def run_test( + self, test_func: Callable[..., Coroutine[Any, Any, Any]], kwargs: dict[str, Any] + ) -> None: + try: + self.get_loop().run_until_complete( + self._call_in_runner_task(test_func, **kwargs) + ) + except Exception as exc: + self._exceptions.append(exc) + + self._raise_async_exceptions() + + +class AsyncIOBackend(AsyncBackend): + @classmethod + def run( + cls, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], + args: tuple[Unpack[PosArgsT]], + kwargs: dict[str, Any], + options: dict[str, Any], + ) -> T_Retval: + @wraps(func) + async def wrapper() -> T_Retval: + task = cast(asyncio.Task, current_task()) + task.set_name(get_callable_name(func)) + _task_states[task] = TaskState(None, None) + + try: + return await func(*args) + finally: + del _task_states[task] + + debug = options.get("debug", None) + loop_factory = options.get("loop_factory", None) + if loop_factory is None and options.get("use_uvloop", False): + if sys.platform != "win32": + import uvloop + + loop_factory = uvloop.new_event_loop + else: + import winloop + + loop_factory = winloop.new_event_loop + + with Runner(debug=debug, loop_factory=loop_factory) as runner: + return runner.run(wrapper()) + + @classmethod + def current_token(cls) -> object: + return get_running_loop() + + @classmethod + def current_time(cls) -> float: + return get_running_loop().time() + + @classmethod + def cancelled_exception_class(cls) -> type[BaseException]: + return CancelledError + + @classmethod + async def checkpoint(cls) -> None: + await sleep(0) + + @classmethod + async def checkpoint_if_cancelled(cls) -> None: + task = current_task() + if task is None: + return + + try: + cancel_scope = _task_states[task].cancel_scope + except KeyError: + return + + while cancel_scope: + if cancel_scope.cancel_called: + await sleep(0) + elif cancel_scope.shield: + break + else: + cancel_scope = cancel_scope._parent_scope + + @classmethod + async def cancel_shielded_checkpoint(cls) -> None: + with CancelScope(shield=True): + await sleep(0) + + @classmethod + async def sleep(cls, delay: float) -> None: + await sleep(delay) + + @classmethod + def create_cancel_scope( + cls, *, deadline: float = math.inf, shield: bool = False + ) -> CancelScope: + return CancelScope(deadline=deadline, shield=shield) + + @classmethod + def current_effective_deadline(cls) -> float: + if (task := current_task()) is None: + return math.inf + + try: + cancel_scope = _task_states[task].cancel_scope + except KeyError: + return math.inf + + deadline = math.inf + while cancel_scope: + deadline = min(deadline, cancel_scope.deadline) + if cancel_scope._cancel_called: + deadline = -math.inf + break + elif cancel_scope.shield: + break + else: + cancel_scope = cancel_scope._parent_scope + + return deadline + + @classmethod + def create_task_group(cls) -> abc.TaskGroup: + return TaskGroup() + + @classmethod + def create_event(cls) -> abc.Event: + return Event() + + @classmethod + def create_lock(cls, *, fast_acquire: bool) -> abc.Lock: + return Lock(fast_acquire=fast_acquire) + + @classmethod + def create_semaphore( + cls, + initial_value: int, + *, + max_value: int | None = None, + fast_acquire: bool = False, + ) -> abc.Semaphore: + return Semaphore(initial_value, max_value=max_value, fast_acquire=fast_acquire) + + @classmethod + def create_capacity_limiter(cls, total_tokens: float) -> abc.CapacityLimiter: + return CapacityLimiter(total_tokens) + + @classmethod + async def run_sync_in_worker_thread( # type: ignore[return] + cls, + func: Callable[[Unpack[PosArgsT]], T_Retval], + args: tuple[Unpack[PosArgsT]], + abandon_on_cancel: bool = False, + limiter: abc.CapacityLimiter | None = None, + ) -> T_Retval: + await cls.checkpoint() + + # If this is the first run in this event loop thread, set up the necessary + # variables + try: + idle_workers = _threadpool_idle_workers.get() + workers = _threadpool_workers.get() + except LookupError: + idle_workers = deque() + workers = set() + _threadpool_idle_workers.set(idle_workers) + _threadpool_workers.set(workers) + + async with limiter or cls.current_default_thread_limiter(): + with CancelScope(shield=not abandon_on_cancel) as scope: + future = asyncio.Future[T_Retval]() + root_task = find_root_task() + if not idle_workers: + worker = WorkerThread(root_task, workers, idle_workers) + worker.start() + workers.add(worker) + root_task.add_done_callback( + worker.stop, context=contextvars.Context() + ) + else: + worker = idle_workers.pop() + + # Prune any other workers that have been idle for MAX_IDLE_TIME + # seconds or longer + now = cls.current_time() + while idle_workers: + if ( + now - idle_workers[0].idle_since + < WorkerThread.MAX_IDLE_TIME + ): + break + + expired_worker = idle_workers.popleft() + expired_worker.root_task.remove_done_callback( + expired_worker.stop + ) + expired_worker.stop() + + context = copy_context() + context.run(set_current_async_library, None) + if abandon_on_cancel or scope._parent_scope is None: + worker_scope = scope + else: + worker_scope = scope._parent_scope + + worker.queue.put_nowait((context, func, args, future, worker_scope)) + return await future + + @classmethod + def check_cancelled(cls) -> None: + scope: CancelScope | None = threadlocals.current_cancel_scope + while scope is not None: + if scope.cancel_called: + raise CancelledError(f"Cancelled by cancel scope {id(scope):x}") + + if scope.shield: + return + + scope = scope._parent_scope + + @classmethod + def run_async_from_thread( + cls, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], + args: tuple[Unpack[PosArgsT]], + token: object, + ) -> T_Retval: + async def task_wrapper() -> T_Retval: + __tracebackhide__ = True + if scope is not None: + task = cast(asyncio.Task, current_task()) + _task_states[task] = TaskState(None, scope) + scope._tasks.add(task) + try: + return await func(*args) + except CancelledError as exc: + raise concurrent.futures.CancelledError(str(exc)) from None + finally: + if scope is not None: + scope._tasks.discard(task) + + loop = cast( + "AbstractEventLoop", token or threadlocals.current_token.native_token + ) + if loop.is_closed(): + raise RunFinishedError + + context = copy_context() + context.run(set_current_async_library, "asyncio") + scope = getattr(threadlocals, "current_cancel_scope", None) + f: concurrent.futures.Future[T_Retval] = context.run( + asyncio.run_coroutine_threadsafe, task_wrapper(), loop=loop + ) + return f.result() + + @classmethod + def run_sync_from_thread( + cls, + func: Callable[[Unpack[PosArgsT]], T_Retval], + args: tuple[Unpack[PosArgsT]], + token: object, + ) -> T_Retval: + @wraps(func) + def wrapper() -> None: + try: + set_current_async_library("asyncio") + f.set_result(func(*args)) + except BaseException as exc: + f.set_exception(exc) + if not isinstance(exc, Exception): + raise + + loop = cast( + "AbstractEventLoop", token or threadlocals.current_token.native_token + ) + if loop.is_closed(): + raise RunFinishedError + + f: concurrent.futures.Future[T_Retval] = Future() + loop.call_soon_threadsafe(wrapper) + return f.result() + + @classmethod + def create_blocking_portal(cls) -> abc.BlockingPortal: + return BlockingPortal() + + @classmethod + async def open_process( + cls, + command: StrOrBytesPath | Sequence[StrOrBytesPath], + *, + stdin: int | IO[Any] | None, + stdout: int | IO[Any] | None, + stderr: int | IO[Any] | None, + **kwargs: Any, + ) -> Process: + await cls.checkpoint() + if isinstance(command, PathLike): + command = os.fspath(command) + + if isinstance(command, (str, bytes)): + process = await asyncio.create_subprocess_shell( + command, + stdin=stdin, + stdout=stdout, + stderr=stderr, + **kwargs, + ) + else: + process = await asyncio.create_subprocess_exec( + *command, + stdin=stdin, + stdout=stdout, + stderr=stderr, + **kwargs, + ) + + stdin_stream = StreamWriterWrapper(process.stdin) if process.stdin else None + stdout_stream = StreamReaderWrapper(process.stdout) if process.stdout else None + stderr_stream = StreamReaderWrapper(process.stderr) if process.stderr else None + return Process(process, stdin_stream, stdout_stream, stderr_stream) + + @classmethod + def setup_process_pool_exit_at_shutdown(cls, workers: set[abc.Process]) -> None: + create_task( + _shutdown_process_pool_on_exit(workers), + name="AnyIO process pool shutdown task", + ) + find_root_task().add_done_callback( + partial(_forcibly_shutdown_process_pool_on_exit, workers) # type:ignore[arg-type] + ) + + @classmethod + async def connect_tcp( + cls, host: str, port: int, local_address: IPSockAddrType | None = None + ) -> abc.SocketStream: + transport, protocol = cast( + tuple[asyncio.Transport, StreamProtocol], + await get_running_loop().create_connection( + StreamProtocol, host, port, local_addr=local_address + ), + ) + transport.pause_reading() + return SocketStream(transport, protocol) + + @classmethod + async def connect_unix(cls, path: str | bytes) -> abc.UNIXSocketStream: + await cls.checkpoint() + loop = get_running_loop() + raw_socket = socket.socket(socket.AF_UNIX) + raw_socket.setblocking(False) + while True: + try: + raw_socket.connect(path) + except BlockingIOError: + f: asyncio.Future = asyncio.Future() + loop.add_writer(raw_socket, f.set_result, None) + f.add_done_callback(lambda _: loop.remove_writer(raw_socket)) + await f + except BaseException: + raw_socket.close() + raise + else: + return UNIXSocketStream(raw_socket) + + @classmethod + def create_tcp_listener(cls, sock: socket.socket) -> SocketListener: + return TCPSocketListener(sock) + + @classmethod + def create_unix_listener(cls, sock: socket.socket) -> SocketListener: + return UNIXSocketListener(sock) + + @classmethod + async def create_udp_socket( + cls, + family: AddressFamily, + local_address: IPSockAddrType | None, + remote_address: IPSockAddrType | None, + reuse_port: bool, + ) -> UDPSocket | ConnectedUDPSocket: + transport, protocol = await get_running_loop().create_datagram_endpoint( + DatagramProtocol, + local_addr=local_address, + remote_addr=remote_address, + family=family, + reuse_port=reuse_port, + ) + if protocol.exception: + transport.close() + raise protocol.exception + + if not remote_address: + return UDPSocket(transport, protocol) + else: + return ConnectedUDPSocket(transport, protocol) + + @classmethod + async def create_unix_datagram_socket( # type: ignore[override] + cls, raw_socket: socket.socket, remote_path: str | bytes | None + ) -> abc.UNIXDatagramSocket | abc.ConnectedUNIXDatagramSocket: + await cls.checkpoint() + loop = get_running_loop() + + if remote_path: + while True: + try: + raw_socket.connect(remote_path) + except BlockingIOError: + f: asyncio.Future = asyncio.Future() + loop.add_writer(raw_socket, f.set_result, None) + f.add_done_callback(lambda _: loop.remove_writer(raw_socket)) + await f + except BaseException: + raw_socket.close() + raise + else: + return ConnectedUNIXDatagramSocket(raw_socket) + else: + return UNIXDatagramSocket(raw_socket) + + @classmethod + async def getaddrinfo( + cls, + host: bytes | str | None, + port: str | int | None, + *, + family: int | AddressFamily = 0, + type: int | SocketKind = 0, + proto: int = 0, + flags: int = 0, + ) -> Sequence[ + tuple[ + AddressFamily, + SocketKind, + int, + str, + tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes], + ] + ]: + return await get_running_loop().getaddrinfo( + host, port, family=family, type=type, proto=proto, flags=flags + ) + + @classmethod + async def getnameinfo( + cls, sockaddr: IPSockAddrType, flags: int = 0 + ) -> tuple[str, str]: + return await get_running_loop().getnameinfo(sockaddr, flags) + + @classmethod + async def wait_readable(cls, obj: FileDescriptorLike) -> None: + try: + read_events = _read_events.get() + except LookupError: + read_events = {} + _read_events.set(read_events) + + fd = obj if isinstance(obj, int) else obj.fileno() + if read_events.get(fd): + raise BusyResourceError("reading from") + + loop = get_running_loop() + fut: asyncio.Future[bool] = loop.create_future() + + def cb() -> None: + try: + del read_events[fd] + except KeyError: + pass + else: + remove_reader(fd) + + try: + fut.set_result(True) + except asyncio.InvalidStateError: + pass + + try: + loop.add_reader(fd, cb) + except NotImplementedError: + from anyio._core._asyncio_selector_thread import get_selector + + selector = get_selector() + selector.add_reader(fd, cb) + remove_reader = selector.remove_reader + else: + remove_reader = loop.remove_reader + + read_events[fd] = fut + try: + success = await fut + finally: + try: + del read_events[fd] + except KeyError: + pass + else: + remove_reader(fd) + + if not success: + raise ClosedResourceError + + @classmethod + async def wait_writable(cls, obj: FileDescriptorLike) -> None: + try: + write_events = _write_events.get() + except LookupError: + write_events = {} + _write_events.set(write_events) + + fd = obj if isinstance(obj, int) else obj.fileno() + if write_events.get(fd): + raise BusyResourceError("writing to") + + loop = get_running_loop() + fut: asyncio.Future[bool] = loop.create_future() + + def cb() -> None: + try: + del write_events[fd] + except KeyError: + pass + else: + remove_writer(fd) + + try: + fut.set_result(True) + except asyncio.InvalidStateError: + pass + + try: + loop.add_writer(fd, cb) + except NotImplementedError: + from anyio._core._asyncio_selector_thread import get_selector + + selector = get_selector() + selector.add_writer(fd, cb) + remove_writer = selector.remove_writer + else: + remove_writer = loop.remove_writer + + write_events[fd] = fut + try: + success = await fut + finally: + try: + del write_events[fd] + except KeyError: + pass + else: + remove_writer(fd) + + if not success: + raise ClosedResourceError + + @classmethod + def notify_closing(cls, obj: FileDescriptorLike) -> None: + fd = obj if isinstance(obj, int) else obj.fileno() + loop = get_running_loop() + + try: + write_events = _write_events.get() + except LookupError: + pass + else: + try: + fut = write_events.pop(fd) + except KeyError: + pass + else: + try: + fut.set_result(False) + except asyncio.InvalidStateError: + pass + + try: + loop.remove_writer(fd) + except NotImplementedError: + from anyio._core._asyncio_selector_thread import get_selector + + get_selector().remove_writer(fd) + + try: + read_events = _read_events.get() + except LookupError: + pass + else: + try: + fut = read_events.pop(fd) + except KeyError: + pass + else: + try: + fut.set_result(False) + except asyncio.InvalidStateError: + pass + + try: + loop.remove_reader(fd) + except NotImplementedError: + from anyio._core._asyncio_selector_thread import get_selector + + get_selector().remove_reader(fd) + + @classmethod + async def wrap_listener_socket(cls, sock: socket.socket) -> SocketListener: + return TCPSocketListener(sock) + + @classmethod + async def wrap_stream_socket(cls, sock: socket.socket) -> SocketStream: + transport, protocol = await get_running_loop().create_connection( + StreamProtocol, sock=sock + ) + return SocketStream(transport, protocol) + + @classmethod + async def wrap_unix_stream_socket(cls, sock: socket.socket) -> UNIXSocketStream: + return UNIXSocketStream(sock) + + @classmethod + async def wrap_udp_socket(cls, sock: socket.socket) -> UDPSocket: + transport, protocol = await get_running_loop().create_datagram_endpoint( + DatagramProtocol, sock=sock + ) + return UDPSocket(transport, protocol) + + @classmethod + async def wrap_connected_udp_socket(cls, sock: socket.socket) -> ConnectedUDPSocket: + transport, protocol = await get_running_loop().create_datagram_endpoint( + DatagramProtocol, sock=sock + ) + return ConnectedUDPSocket(transport, protocol) + + @classmethod + async def wrap_unix_datagram_socket(cls, sock: socket.socket) -> UNIXDatagramSocket: + return UNIXDatagramSocket(sock) + + @classmethod + async def wrap_connected_unix_datagram_socket( + cls, sock: socket.socket + ) -> ConnectedUNIXDatagramSocket: + return ConnectedUNIXDatagramSocket(sock) + + @classmethod + def current_default_thread_limiter(cls) -> CapacityLimiter: + try: + return _default_thread_limiter.get() + except LookupError: + limiter = CapacityLimiter(40) + _default_thread_limiter.set(limiter) + return limiter + + @classmethod + def open_signal_receiver( + cls, *signals: Signals + ) -> AbstractContextManager[AsyncIterator[Signals]]: + return _SignalReceiver(signals) + + @classmethod + def get_current_task(cls) -> TaskInfo: + return AsyncIOTaskInfo(current_task()) # type: ignore[arg-type] + + @classmethod + def get_running_tasks(cls) -> Sequence[TaskInfo]: + return [AsyncIOTaskInfo(task) for task in all_tasks() if not task.done()] + + @classmethod + async def wait_all_tasks_blocked(cls) -> None: + await cls.checkpoint() + this_task = current_task() + while True: + for task in all_tasks(): + if task is this_task: + continue + + waiter = task._fut_waiter # type: ignore[attr-defined] + if waiter is None or waiter.done(): + await sleep(0.1) + break + else: + return + + @classmethod + def create_test_runner(cls, options: dict[str, Any]) -> TestRunner: + return TestRunner(**options) + + +backend_class = AsyncIOBackend diff --git a/backend/.venv/Lib/site-packages/anyio/_backends/_trio.py b/backend/.venv/Lib/site-packages/anyio/_backends/_trio.py new file mode 100644 index 0000000..36941f0 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/_backends/_trio.py @@ -0,0 +1,1384 @@ +from __future__ import annotations + +import array +import math +import os +import socket +import sys +import types +import weakref +from collections.abc import ( + AsyncGenerator, + AsyncIterator, + Awaitable, + Callable, + Collection, + Coroutine, + Iterable, + Sequence, +) +from concurrent.futures import Future +from contextlib import AbstractContextManager +from dataclasses import dataclass +from functools import partial +from io import IOBase +from os import PathLike +from signal import Signals +from socket import AddressFamily, SocketKind +from types import TracebackType +from typing import ( + IO, + TYPE_CHECKING, + Any, + Generic, + NoReturn, + TypeVar, + cast, + overload, +) + +import trio.from_thread +import trio.lowlevel +from outcome import Error, Outcome, Value +from trio.lowlevel import ( + current_root_task, + current_task, + notify_closing, + wait_readable, + wait_writable, +) +from trio.socket import SocketType as TrioSocketType +from trio.to_thread import run_sync + +from .. import ( + CapacityLimiterStatistics, + EventStatistics, + LockStatistics, + RunFinishedError, + TaskInfo, + WouldBlock, + abc, +) +from .._core._eventloop import claim_worker_thread +from .._core._exceptions import ( + BrokenResourceError, + BusyResourceError, + ClosedResourceError, + EndOfStream, +) +from .._core._sockets import convert_ipv6_sockaddr +from .._core._streams import create_memory_object_stream +from .._core._synchronization import ( + CapacityLimiter as BaseCapacityLimiter, +) +from .._core._synchronization import Event as BaseEvent +from .._core._synchronization import Lock as BaseLock +from .._core._synchronization import ( + ResourceGuard, + SemaphoreStatistics, +) +from .._core._synchronization import Semaphore as BaseSemaphore +from .._core._tasks import CancelScope as BaseCancelScope +from ..abc import IPSockAddrType, UDPPacketType, UNIXDatagramPacketType +from ..abc._eventloop import AsyncBackend, StrOrBytesPath +from ..streams.memory import MemoryObjectSendStream + +if TYPE_CHECKING: + from _typeshed import FileDescriptorLike + +if sys.version_info >= (3, 10): + from typing import ParamSpec +else: + from typing_extensions import ParamSpec + +if sys.version_info >= (3, 11): + from typing import TypeVarTuple, Unpack +else: + from exceptiongroup import BaseExceptionGroup + from typing_extensions import TypeVarTuple, Unpack + +T = TypeVar("T") +T_Retval = TypeVar("T_Retval") +T_SockAddr = TypeVar("T_SockAddr", str, IPSockAddrType) +PosArgsT = TypeVarTuple("PosArgsT") +P = ParamSpec("P") + + +# +# Event loop +# + +RunVar = trio.lowlevel.RunVar + + +# +# Timeouts and cancellation +# + + +class CancelScope(BaseCancelScope): + def __new__( + cls, original: trio.CancelScope | None = None, **kwargs: object + ) -> CancelScope: + return object.__new__(cls) + + def __init__(self, original: trio.CancelScope | None = None, **kwargs: Any) -> None: + self.__original = original or trio.CancelScope(**kwargs) + + def __enter__(self) -> CancelScope: + self.__original.__enter__() + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> bool: + return self.__original.__exit__(exc_type, exc_val, exc_tb) + + def cancel(self, reason: str | None = None) -> None: + self.__original.cancel(reason) + + @property + def deadline(self) -> float: + return self.__original.deadline + + @deadline.setter + def deadline(self, value: float) -> None: + self.__original.deadline = value + + @property + def cancel_called(self) -> bool: + return self.__original.cancel_called + + @property + def cancelled_caught(self) -> bool: + return self.__original.cancelled_caught + + @property + def shield(self) -> bool: + return self.__original.shield + + @shield.setter + def shield(self, value: bool) -> None: + self.__original.shield = value + + +# +# Task groups +# + + +class TaskGroup(abc.TaskGroup): + def __init__(self) -> None: + self._active = False + self._nursery_manager = trio.open_nursery(strict_exception_groups=True) + self.cancel_scope = None # type: ignore[assignment] + + async def __aenter__(self) -> TaskGroup: + self._active = True + self._nursery = await self._nursery_manager.__aenter__() + self.cancel_scope = CancelScope(self._nursery.cancel_scope) + return self + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> bool: + try: + # trio.Nursery.__exit__ returns bool; .open_nursery has wrong type + return await self._nursery_manager.__aexit__(exc_type, exc_val, exc_tb) # type: ignore[return-value] + except BaseExceptionGroup as exc: + if not exc.split(trio.Cancelled)[1]: + raise trio.Cancelled._create() from exc + + raise + finally: + del exc_val, exc_tb + self._active = False + + def start_soon( + self, + func: Callable[[Unpack[PosArgsT]], Awaitable[Any]], + *args: Unpack[PosArgsT], + name: object = None, + ) -> None: + if not self._active: + raise RuntimeError( + "This task group is not active; no new tasks can be started." + ) + + self._nursery.start_soon(func, *args, name=name) + + async def start( + self, func: Callable[..., Awaitable[Any]], *args: object, name: object = None + ) -> Any: + if not self._active: + raise RuntimeError( + "This task group is not active; no new tasks can be started." + ) + + return await self._nursery.start(func, *args, name=name) + + +# +# Threads +# + + +class BlockingPortal(abc.BlockingPortal): + def __new__(cls) -> BlockingPortal: + return object.__new__(cls) + + def __init__(self) -> None: + super().__init__() + self._token = trio.lowlevel.current_trio_token() + + def _spawn_task_from_thread( + self, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval], + args: tuple[Unpack[PosArgsT]], + kwargs: dict[str, Any], + name: object, + future: Future[T_Retval], + ) -> None: + trio.from_thread.run_sync( + partial(self._task_group.start_soon, name=name), + self._call_func, + func, + args, + kwargs, + future, + trio_token=self._token, + ) + + +# +# Subprocesses +# + + +@dataclass(eq=False) +class ReceiveStreamWrapper(abc.ByteReceiveStream): + _stream: trio.abc.ReceiveStream + + async def receive(self, max_bytes: int | None = None) -> bytes: + try: + data = await self._stream.receive_some(max_bytes) + except trio.ClosedResourceError as exc: + raise ClosedResourceError from exc.__cause__ + except trio.BrokenResourceError as exc: + raise BrokenResourceError from exc.__cause__ + + if data: + return bytes(data) + else: + raise EndOfStream + + async def aclose(self) -> None: + await self._stream.aclose() + + +@dataclass(eq=False) +class SendStreamWrapper(abc.ByteSendStream): + _stream: trio.abc.SendStream + + async def send(self, item: bytes) -> None: + try: + await self._stream.send_all(item) + except trio.ClosedResourceError as exc: + raise ClosedResourceError from exc.__cause__ + except trio.BrokenResourceError as exc: + raise BrokenResourceError from exc.__cause__ + + async def aclose(self) -> None: + await self._stream.aclose() + + +@dataclass(eq=False) +class Process(abc.Process): + _process: trio.Process + _stdin: abc.ByteSendStream | None + _stdout: abc.ByteReceiveStream | None + _stderr: abc.ByteReceiveStream | None + + async def aclose(self) -> None: + with CancelScope(shield=True): + if self._stdin: + await self._stdin.aclose() + if self._stdout: + await self._stdout.aclose() + if self._stderr: + await self._stderr.aclose() + + try: + await self.wait() + except BaseException: + self.kill() + with CancelScope(shield=True): + await self.wait() + raise + + async def wait(self) -> int: + return await self._process.wait() + + def terminate(self) -> None: + self._process.terminate() + + def kill(self) -> None: + self._process.kill() + + def send_signal(self, signal: Signals) -> None: + self._process.send_signal(signal) + + @property + def pid(self) -> int: + return self._process.pid + + @property + def returncode(self) -> int | None: + return self._process.returncode + + @property + def stdin(self) -> abc.ByteSendStream | None: + return self._stdin + + @property + def stdout(self) -> abc.ByteReceiveStream | None: + return self._stdout + + @property + def stderr(self) -> abc.ByteReceiveStream | None: + return self._stderr + + +class _ProcessPoolShutdownInstrument(trio.abc.Instrument): + def after_run(self) -> None: + super().after_run() + + +current_default_worker_process_limiter: trio.lowlevel.RunVar = RunVar( + "current_default_worker_process_limiter" +) + + +async def _shutdown_process_pool(workers: set[abc.Process]) -> None: + try: + await trio.sleep(math.inf) + except trio.Cancelled: + for process in workers: + if process.returncode is None: + process.kill() + + with CancelScope(shield=True): + for process in workers: + await process.aclose() + + +# +# Sockets and networking +# + + +class _TrioSocketMixin(Generic[T_SockAddr]): + def __init__(self, trio_socket: TrioSocketType) -> None: + self._trio_socket = trio_socket + self._closed = False + + def _check_closed(self) -> None: + if self._closed: + raise ClosedResourceError + if self._trio_socket.fileno() < 0: + raise BrokenResourceError + + @property + def _raw_socket(self) -> socket.socket: + return self._trio_socket._sock # type: ignore[attr-defined] + + async def aclose(self) -> None: + if self._trio_socket.fileno() >= 0: + self._closed = True + self._trio_socket.close() + + def _convert_socket_error(self, exc: BaseException) -> NoReturn: + if isinstance(exc, trio.ClosedResourceError): + raise ClosedResourceError from exc + elif self._trio_socket.fileno() < 0 and self._closed: + raise ClosedResourceError from None + elif isinstance(exc, OSError): + raise BrokenResourceError from exc + else: + raise exc + + +class SocketStream(_TrioSocketMixin, abc.SocketStream): + def __init__(self, trio_socket: TrioSocketType) -> None: + super().__init__(trio_socket) + self._receive_guard = ResourceGuard("reading from") + self._send_guard = ResourceGuard("writing to") + + async def receive(self, max_bytes: int = 65536) -> bytes: + with self._receive_guard: + try: + data = await self._trio_socket.recv(max_bytes) + except BaseException as exc: + self._convert_socket_error(exc) + + if data: + return data + else: + raise EndOfStream + + async def send(self, item: bytes) -> None: + with self._send_guard: + view = memoryview(item) + while view: + try: + bytes_sent = await self._trio_socket.send(view) + except BaseException as exc: + self._convert_socket_error(exc) + + view = view[bytes_sent:] + + async def send_eof(self) -> None: + self._trio_socket.shutdown(socket.SHUT_WR) + + +class UNIXSocketStream(SocketStream, abc.UNIXSocketStream): + async def receive_fds(self, msglen: int, maxfds: int) -> tuple[bytes, list[int]]: + if not isinstance(msglen, int) or msglen < 0: + raise ValueError("msglen must be a non-negative integer") + if not isinstance(maxfds, int) or maxfds < 1: + raise ValueError("maxfds must be a positive integer") + + fds = array.array("i") + await trio.lowlevel.checkpoint() + with self._receive_guard: + while True: + try: + message, ancdata, flags, addr = await self._trio_socket.recvmsg( + msglen, socket.CMSG_LEN(maxfds * fds.itemsize) + ) + except BaseException as exc: + self._convert_socket_error(exc) + else: + if not message and not ancdata: + raise EndOfStream + + break + + for cmsg_level, cmsg_type, cmsg_data in ancdata: + if cmsg_level != socket.SOL_SOCKET or cmsg_type != socket.SCM_RIGHTS: + raise RuntimeError( + f"Received unexpected ancillary data; message = {message!r}, " + f"cmsg_level = {cmsg_level}, cmsg_type = {cmsg_type}" + ) + + fds.frombytes(cmsg_data[: len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) + + return message, list(fds) + + async def send_fds(self, message: bytes, fds: Collection[int | IOBase]) -> None: + if not message: + raise ValueError("message must not be empty") + if not fds: + raise ValueError("fds must not be empty") + + filenos: list[int] = [] + for fd in fds: + if isinstance(fd, int): + filenos.append(fd) + elif isinstance(fd, IOBase): + filenos.append(fd.fileno()) + + fdarray = array.array("i", filenos) + await trio.lowlevel.checkpoint() + with self._send_guard: + while True: + try: + await self._trio_socket.sendmsg( + [message], + [ + ( + socket.SOL_SOCKET, + socket.SCM_RIGHTS, + fdarray, + ) + ], + ) + break + except BaseException as exc: + self._convert_socket_error(exc) + + +class TCPSocketListener(_TrioSocketMixin, abc.SocketListener): + def __init__(self, raw_socket: socket.socket): + super().__init__(trio.socket.from_stdlib_socket(raw_socket)) + self._accept_guard = ResourceGuard("accepting connections from") + + async def accept(self) -> SocketStream: + with self._accept_guard: + try: + trio_socket, _addr = await self._trio_socket.accept() + except BaseException as exc: + self._convert_socket_error(exc) + + trio_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + return SocketStream(trio_socket) + + +class UNIXSocketListener(_TrioSocketMixin, abc.SocketListener): + def __init__(self, raw_socket: socket.socket): + super().__init__(trio.socket.from_stdlib_socket(raw_socket)) + self._accept_guard = ResourceGuard("accepting connections from") + + async def accept(self) -> UNIXSocketStream: + with self._accept_guard: + try: + trio_socket, _addr = await self._trio_socket.accept() + except BaseException as exc: + self._convert_socket_error(exc) + + return UNIXSocketStream(trio_socket) + + +class UDPSocket(_TrioSocketMixin[IPSockAddrType], abc.UDPSocket): + def __init__(self, trio_socket: TrioSocketType) -> None: + super().__init__(trio_socket) + self._receive_guard = ResourceGuard("reading from") + self._send_guard = ResourceGuard("writing to") + + async def receive(self) -> tuple[bytes, IPSockAddrType]: + with self._receive_guard: + try: + data, addr = await self._trio_socket.recvfrom(65536) + return data, convert_ipv6_sockaddr(addr) + except BaseException as exc: + self._convert_socket_error(exc) + + async def send(self, item: UDPPacketType) -> None: + with self._send_guard: + try: + await self._trio_socket.sendto(*item) + except BaseException as exc: + self._convert_socket_error(exc) + + +class ConnectedUDPSocket(_TrioSocketMixin[IPSockAddrType], abc.ConnectedUDPSocket): + def __init__(self, trio_socket: TrioSocketType) -> None: + super().__init__(trio_socket) + self._receive_guard = ResourceGuard("reading from") + self._send_guard = ResourceGuard("writing to") + + async def receive(self) -> bytes: + with self._receive_guard: + try: + return await self._trio_socket.recv(65536) + except BaseException as exc: + self._convert_socket_error(exc) + + async def send(self, item: bytes) -> None: + with self._send_guard: + try: + await self._trio_socket.send(item) + except BaseException as exc: + self._convert_socket_error(exc) + + +class UNIXDatagramSocket(_TrioSocketMixin[str], abc.UNIXDatagramSocket): + def __init__(self, trio_socket: TrioSocketType) -> None: + super().__init__(trio_socket) + self._receive_guard = ResourceGuard("reading from") + self._send_guard = ResourceGuard("writing to") + + async def receive(self) -> UNIXDatagramPacketType: + with self._receive_guard: + try: + data, addr = await self._trio_socket.recvfrom(65536) + return data, addr + except BaseException as exc: + self._convert_socket_error(exc) + + async def send(self, item: UNIXDatagramPacketType) -> None: + with self._send_guard: + try: + await self._trio_socket.sendto(*item) + except BaseException as exc: + self._convert_socket_error(exc) + + +class ConnectedUNIXDatagramSocket( + _TrioSocketMixin[str], abc.ConnectedUNIXDatagramSocket +): + def __init__(self, trio_socket: TrioSocketType) -> None: + super().__init__(trio_socket) + self._receive_guard = ResourceGuard("reading from") + self._send_guard = ResourceGuard("writing to") + + async def receive(self) -> bytes: + with self._receive_guard: + try: + return await self._trio_socket.recv(65536) + except BaseException as exc: + self._convert_socket_error(exc) + + async def send(self, item: bytes) -> None: + with self._send_guard: + try: + await self._trio_socket.send(item) + except BaseException as exc: + self._convert_socket_error(exc) + + +# +# Synchronization +# + + +class Event(BaseEvent): + def __new__(cls) -> Event: + return object.__new__(cls) + + def __init__(self) -> None: + self.__original = trio.Event() + + def is_set(self) -> bool: + return self.__original.is_set() + + async def wait(self) -> None: + return await self.__original.wait() + + def statistics(self) -> EventStatistics: + orig_statistics = self.__original.statistics() + return EventStatistics(tasks_waiting=orig_statistics.tasks_waiting) + + def set(self) -> None: + self.__original.set() + + +class Lock(BaseLock): + def __new__(cls, *, fast_acquire: bool = False) -> Lock: + return object.__new__(cls) + + def __init__(self, *, fast_acquire: bool = False) -> None: + self._fast_acquire = fast_acquire + self.__original = trio.Lock() + + @staticmethod + def _convert_runtime_error_msg(exc: RuntimeError) -> None: + if exc.args == ("attempt to re-acquire an already held Lock",): + exc.args = ("Attempted to acquire an already held Lock",) + + async def acquire(self) -> None: + if not self._fast_acquire: + try: + await self.__original.acquire() + except RuntimeError as exc: + self._convert_runtime_error_msg(exc) + raise + + return + + # This is the "fast path" where we don't let other tasks run + await trio.lowlevel.checkpoint_if_cancelled() + try: + self.__original.acquire_nowait() + except trio.WouldBlock: + await self.__original._lot.park() + except RuntimeError as exc: + self._convert_runtime_error_msg(exc) + raise + + def acquire_nowait(self) -> None: + try: + self.__original.acquire_nowait() + except trio.WouldBlock: + raise WouldBlock from None + except RuntimeError as exc: + self._convert_runtime_error_msg(exc) + raise + + def locked(self) -> bool: + return self.__original.locked() + + def release(self) -> None: + self.__original.release() + + def statistics(self) -> LockStatistics: + orig_statistics = self.__original.statistics() + owner = TrioTaskInfo(orig_statistics.owner) if orig_statistics.owner else None + return LockStatistics( + orig_statistics.locked, owner, orig_statistics.tasks_waiting + ) + + +class Semaphore(BaseSemaphore): + def __new__( + cls, + initial_value: int, + *, + max_value: int | None = None, + fast_acquire: bool = False, + ) -> Semaphore: + return object.__new__(cls) + + def __init__( + self, + initial_value: int, + *, + max_value: int | None = None, + fast_acquire: bool = False, + ) -> None: + super().__init__(initial_value, max_value=max_value, fast_acquire=fast_acquire) + self.__original = trio.Semaphore(initial_value, max_value=max_value) + + async def acquire(self) -> None: + if not self._fast_acquire: + await self.__original.acquire() + return + + # This is the "fast path" where we don't let other tasks run + await trio.lowlevel.checkpoint_if_cancelled() + try: + self.__original.acquire_nowait() + except trio.WouldBlock: + await self.__original._lot.park() + + def acquire_nowait(self) -> None: + try: + self.__original.acquire_nowait() + except trio.WouldBlock: + raise WouldBlock from None + + @property + def max_value(self) -> int | None: + return self.__original.max_value + + @property + def value(self) -> int: + return self.__original.value + + def release(self) -> None: + self.__original.release() + + def statistics(self) -> SemaphoreStatistics: + orig_statistics = self.__original.statistics() + return SemaphoreStatistics(orig_statistics.tasks_waiting) + + +class CapacityLimiter(BaseCapacityLimiter): + def __new__( + cls, + total_tokens: float | None = None, + *, + original: trio.CapacityLimiter | None = None, + ) -> CapacityLimiter: + return object.__new__(cls) + + def __init__( + self, + total_tokens: float | None = None, + *, + original: trio.CapacityLimiter | None = None, + ) -> None: + if original is not None: + self.__original = original + else: + assert total_tokens is not None + self.__original = trio.CapacityLimiter(total_tokens) + + async def __aenter__(self) -> None: + return await self.__original.__aenter__() + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + await self.__original.__aexit__(exc_type, exc_val, exc_tb) + + @property + def total_tokens(self) -> float: + return self.__original.total_tokens + + @total_tokens.setter + def total_tokens(self, value: float) -> None: + self.__original.total_tokens = value + + @property + def borrowed_tokens(self) -> int: + return self.__original.borrowed_tokens + + @property + def available_tokens(self) -> float: + return self.__original.available_tokens + + def acquire_nowait(self) -> None: + self.__original.acquire_nowait() + + def acquire_on_behalf_of_nowait(self, borrower: object) -> None: + self.__original.acquire_on_behalf_of_nowait(borrower) + + async def acquire(self) -> None: + await self.__original.acquire() + + async def acquire_on_behalf_of(self, borrower: object) -> None: + await self.__original.acquire_on_behalf_of(borrower) + + def release(self) -> None: + return self.__original.release() + + def release_on_behalf_of(self, borrower: object) -> None: + return self.__original.release_on_behalf_of(borrower) + + def statistics(self) -> CapacityLimiterStatistics: + orig = self.__original.statistics() + return CapacityLimiterStatistics( + borrowed_tokens=orig.borrowed_tokens, + total_tokens=orig.total_tokens, + borrowers=tuple(orig.borrowers), + tasks_waiting=orig.tasks_waiting, + ) + + +_capacity_limiter_wrapper: trio.lowlevel.RunVar = RunVar("_capacity_limiter_wrapper") + + +# +# Signal handling +# + + +class _SignalReceiver: + _iterator: AsyncIterator[int] + + def __init__(self, signals: tuple[Signals, ...]): + self._signals = signals + + def __enter__(self) -> _SignalReceiver: + self._cm = trio.open_signal_receiver(*self._signals) + self._iterator = self._cm.__enter__() + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> bool | None: + return self._cm.__exit__(exc_type, exc_val, exc_tb) + + def __aiter__(self) -> _SignalReceiver: + return self + + async def __anext__(self) -> Signals: + signum = await self._iterator.__anext__() + return Signals(signum) + + +# +# Testing and debugging +# + + +class TestRunner(abc.TestRunner): + def __init__(self, **options: Any) -> None: + from queue import Queue + + self._call_queue: Queue[Callable[[], object]] = Queue() + self._send_stream: MemoryObjectSendStream | None = None + self._options = options + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: types.TracebackType | None, + ) -> None: + if self._send_stream: + self._send_stream.close() + while self._send_stream is not None: + self._call_queue.get()() + + async def _run_tests_and_fixtures(self) -> None: + self._send_stream, receive_stream = create_memory_object_stream(1) + with receive_stream: + async for coro, outcome_holder in receive_stream: + try: + retval = await coro + except BaseException as exc: + outcome_holder.append(Error(exc)) + else: + outcome_holder.append(Value(retval)) + + def _main_task_finished(self, outcome: object) -> None: + self._send_stream = None + + def _call_in_runner_task( + self, + func: Callable[P, Awaitable[T_Retval]], + *args: P.args, + **kwargs: P.kwargs, + ) -> T_Retval: + if self._send_stream is None: + trio.lowlevel.start_guest_run( + self._run_tests_and_fixtures, + run_sync_soon_threadsafe=self._call_queue.put, + done_callback=self._main_task_finished, + **self._options, + ) + while self._send_stream is None: + self._call_queue.get()() + + outcome_holder: list[Outcome] = [] + self._send_stream.send_nowait((func(*args, **kwargs), outcome_holder)) + while not outcome_holder: + self._call_queue.get()() + + return outcome_holder[0].unwrap() + + def run_asyncgen_fixture( + self, + fixture_func: Callable[..., AsyncGenerator[T_Retval, Any]], + kwargs: dict[str, Any], + ) -> Iterable[T_Retval]: + asyncgen = fixture_func(**kwargs) + fixturevalue: T_Retval = self._call_in_runner_task(asyncgen.asend, None) + + yield fixturevalue + + try: + self._call_in_runner_task(asyncgen.asend, None) + except StopAsyncIteration: + pass + else: + self._call_in_runner_task(asyncgen.aclose) + raise RuntimeError("Async generator fixture did not stop") + + def run_fixture( + self, + fixture_func: Callable[..., Coroutine[Any, Any, T_Retval]], + kwargs: dict[str, Any], + ) -> T_Retval: + return self._call_in_runner_task(fixture_func, **kwargs) + + def run_test( + self, test_func: Callable[..., Coroutine[Any, Any, Any]], kwargs: dict[str, Any] + ) -> None: + self._call_in_runner_task(test_func, **kwargs) + + +class TrioTaskInfo(TaskInfo): + def __init__(self, task: trio.lowlevel.Task): + parent_id = None + if task.parent_nursery and task.parent_nursery.parent_task: + parent_id = id(task.parent_nursery.parent_task) + + super().__init__(id(task), parent_id, task.name, task.coro) + self._task = weakref.proxy(task) + + def has_pending_cancellation(self) -> bool: + try: + return self._task._cancel_status.effectively_cancelled + except ReferenceError: + # If the task is no longer around, it surely doesn't have a cancellation + # pending + return False + + +class TrioBackend(AsyncBackend): + @classmethod + def run( + cls, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], + args: tuple[Unpack[PosArgsT]], + kwargs: dict[str, Any], + options: dict[str, Any], + ) -> T_Retval: + return trio.run(func, *args) + + @classmethod + def current_token(cls) -> object: + return trio.lowlevel.current_trio_token() + + @classmethod + def current_time(cls) -> float: + return trio.current_time() + + @classmethod + def cancelled_exception_class(cls) -> type[BaseException]: + return trio.Cancelled + + @classmethod + async def checkpoint(cls) -> None: + await trio.lowlevel.checkpoint() + + @classmethod + async def checkpoint_if_cancelled(cls) -> None: + await trio.lowlevel.checkpoint_if_cancelled() + + @classmethod + async def cancel_shielded_checkpoint(cls) -> None: + await trio.lowlevel.cancel_shielded_checkpoint() + + @classmethod + async def sleep(cls, delay: float) -> None: + await trio.sleep(delay) + + @classmethod + def create_cancel_scope( + cls, *, deadline: float = math.inf, shield: bool = False + ) -> abc.CancelScope: + return CancelScope(deadline=deadline, shield=shield) + + @classmethod + def current_effective_deadline(cls) -> float: + return trio.current_effective_deadline() + + @classmethod + def create_task_group(cls) -> abc.TaskGroup: + return TaskGroup() + + @classmethod + def create_event(cls) -> abc.Event: + return Event() + + @classmethod + def create_lock(cls, *, fast_acquire: bool) -> Lock: + return Lock(fast_acquire=fast_acquire) + + @classmethod + def create_semaphore( + cls, + initial_value: int, + *, + max_value: int | None = None, + fast_acquire: bool = False, + ) -> abc.Semaphore: + return Semaphore(initial_value, max_value=max_value, fast_acquire=fast_acquire) + + @classmethod + def create_capacity_limiter(cls, total_tokens: float) -> CapacityLimiter: + return CapacityLimiter(total_tokens) + + @classmethod + async def run_sync_in_worker_thread( + cls, + func: Callable[[Unpack[PosArgsT]], T_Retval], + args: tuple[Unpack[PosArgsT]], + abandon_on_cancel: bool = False, + limiter: abc.CapacityLimiter | None = None, + ) -> T_Retval: + def wrapper() -> T_Retval: + with claim_worker_thread(TrioBackend, token): + return func(*args) + + token = TrioBackend.current_token() + return await run_sync( + wrapper, + abandon_on_cancel=abandon_on_cancel, + limiter=cast(trio.CapacityLimiter, limiter), + ) + + @classmethod + def check_cancelled(cls) -> None: + trio.from_thread.check_cancelled() + + @classmethod + def run_async_from_thread( + cls, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], + args: tuple[Unpack[PosArgsT]], + token: object, + ) -> T_Retval: + trio_token = cast("trio.lowlevel.TrioToken | None", token) + try: + return trio.from_thread.run(func, *args, trio_token=trio_token) + except trio.RunFinishedError: + raise RunFinishedError from None + + @classmethod + def run_sync_from_thread( + cls, + func: Callable[[Unpack[PosArgsT]], T_Retval], + args: tuple[Unpack[PosArgsT]], + token: object, + ) -> T_Retval: + trio_token = cast("trio.lowlevel.TrioToken | None", token) + try: + return trio.from_thread.run_sync(func, *args, trio_token=trio_token) + except trio.RunFinishedError: + raise RunFinishedError from None + + @classmethod + def create_blocking_portal(cls) -> abc.BlockingPortal: + return BlockingPortal() + + @classmethod + async def open_process( + cls, + command: StrOrBytesPath | Sequence[StrOrBytesPath], + *, + stdin: int | IO[Any] | None, + stdout: int | IO[Any] | None, + stderr: int | IO[Any] | None, + **kwargs: Any, + ) -> Process: + def convert_item(item: StrOrBytesPath) -> str: + str_or_bytes = os.fspath(item) + if isinstance(str_or_bytes, str): + return str_or_bytes + else: + return os.fsdecode(str_or_bytes) + + if isinstance(command, (str, bytes, PathLike)): + process = await trio.lowlevel.open_process( + convert_item(command), + stdin=stdin, + stdout=stdout, + stderr=stderr, + shell=True, + **kwargs, + ) + else: + process = await trio.lowlevel.open_process( + [convert_item(item) for item in command], + stdin=stdin, + stdout=stdout, + stderr=stderr, + shell=False, + **kwargs, + ) + + stdin_stream = SendStreamWrapper(process.stdin) if process.stdin else None + stdout_stream = ReceiveStreamWrapper(process.stdout) if process.stdout else None + stderr_stream = ReceiveStreamWrapper(process.stderr) if process.stderr else None + return Process(process, stdin_stream, stdout_stream, stderr_stream) + + @classmethod + def setup_process_pool_exit_at_shutdown(cls, workers: set[abc.Process]) -> None: + trio.lowlevel.spawn_system_task(_shutdown_process_pool, workers) + + @classmethod + async def connect_tcp( + cls, host: str, port: int, local_address: IPSockAddrType | None = None + ) -> SocketStream: + family = socket.AF_INET6 if ":" in host else socket.AF_INET + trio_socket = trio.socket.socket(family) + trio_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + if local_address: + await trio_socket.bind(local_address) + + try: + await trio_socket.connect((host, port)) + except BaseException: + trio_socket.close() + raise + + return SocketStream(trio_socket) + + @classmethod + async def connect_unix(cls, path: str | bytes) -> abc.UNIXSocketStream: + trio_socket = trio.socket.socket(socket.AF_UNIX) + try: + await trio_socket.connect(path) + except BaseException: + trio_socket.close() + raise + + return UNIXSocketStream(trio_socket) + + @classmethod + def create_tcp_listener(cls, sock: socket.socket) -> abc.SocketListener: + return TCPSocketListener(sock) + + @classmethod + def create_unix_listener(cls, sock: socket.socket) -> abc.SocketListener: + return UNIXSocketListener(sock) + + @classmethod + async def create_udp_socket( + cls, + family: socket.AddressFamily, + local_address: IPSockAddrType | None, + remote_address: IPSockAddrType | None, + reuse_port: bool, + ) -> UDPSocket | ConnectedUDPSocket: + trio_socket = trio.socket.socket(family=family, type=socket.SOCK_DGRAM) + + if reuse_port: + trio_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) + + if local_address: + await trio_socket.bind(local_address) + + if remote_address: + await trio_socket.connect(remote_address) + return ConnectedUDPSocket(trio_socket) + else: + return UDPSocket(trio_socket) + + @classmethod + @overload + async def create_unix_datagram_socket( + cls, raw_socket: socket.socket, remote_path: None + ) -> abc.UNIXDatagramSocket: ... + + @classmethod + @overload + async def create_unix_datagram_socket( + cls, raw_socket: socket.socket, remote_path: str | bytes + ) -> abc.ConnectedUNIXDatagramSocket: ... + + @classmethod + async def create_unix_datagram_socket( + cls, raw_socket: socket.socket, remote_path: str | bytes | None + ) -> abc.UNIXDatagramSocket | abc.ConnectedUNIXDatagramSocket: + trio_socket = trio.socket.from_stdlib_socket(raw_socket) + + if remote_path: + await trio_socket.connect(remote_path) + return ConnectedUNIXDatagramSocket(trio_socket) + else: + return UNIXDatagramSocket(trio_socket) + + @classmethod + async def getaddrinfo( + cls, + host: bytes | str | None, + port: str | int | None, + *, + family: int | AddressFamily = 0, + type: int | SocketKind = 0, + proto: int = 0, + flags: int = 0, + ) -> Sequence[ + tuple[ + AddressFamily, + SocketKind, + int, + str, + tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes], + ] + ]: + return await trio.socket.getaddrinfo(host, port, family, type, proto, flags) + + @classmethod + async def getnameinfo( + cls, sockaddr: IPSockAddrType, flags: int = 0 + ) -> tuple[str, str]: + return await trio.socket.getnameinfo(sockaddr, flags) + + @classmethod + async def wait_readable(cls, obj: FileDescriptorLike) -> None: + try: + await wait_readable(obj) + except trio.ClosedResourceError as exc: + raise ClosedResourceError().with_traceback(exc.__traceback__) from None + except trio.BusyResourceError: + raise BusyResourceError("reading from") from None + + @classmethod + async def wait_writable(cls, obj: FileDescriptorLike) -> None: + try: + await wait_writable(obj) + except trio.ClosedResourceError as exc: + raise ClosedResourceError().with_traceback(exc.__traceback__) from None + except trio.BusyResourceError: + raise BusyResourceError("writing to") from None + + @classmethod + def notify_closing(cls, obj: FileDescriptorLike) -> None: + notify_closing(obj) + + @classmethod + async def wrap_listener_socket(cls, sock: socket.socket) -> abc.SocketListener: + return TCPSocketListener(sock) + + @classmethod + async def wrap_stream_socket(cls, sock: socket.socket) -> SocketStream: + trio_sock = trio.socket.from_stdlib_socket(sock) + return SocketStream(trio_sock) + + @classmethod + async def wrap_unix_stream_socket(cls, sock: socket.socket) -> UNIXSocketStream: + trio_sock = trio.socket.from_stdlib_socket(sock) + return UNIXSocketStream(trio_sock) + + @classmethod + async def wrap_udp_socket(cls, sock: socket.socket) -> UDPSocket: + trio_sock = trio.socket.from_stdlib_socket(sock) + return UDPSocket(trio_sock) + + @classmethod + async def wrap_connected_udp_socket(cls, sock: socket.socket) -> ConnectedUDPSocket: + trio_sock = trio.socket.from_stdlib_socket(sock) + return ConnectedUDPSocket(trio_sock) + + @classmethod + async def wrap_unix_datagram_socket(cls, sock: socket.socket) -> UNIXDatagramSocket: + trio_sock = trio.socket.from_stdlib_socket(sock) + return UNIXDatagramSocket(trio_sock) + + @classmethod + async def wrap_connected_unix_datagram_socket( + cls, sock: socket.socket + ) -> ConnectedUNIXDatagramSocket: + trio_sock = trio.socket.from_stdlib_socket(sock) + return ConnectedUNIXDatagramSocket(trio_sock) + + @classmethod + def current_default_thread_limiter(cls) -> CapacityLimiter: + try: + return _capacity_limiter_wrapper.get() + except LookupError: + limiter = CapacityLimiter( + original=trio.to_thread.current_default_thread_limiter() + ) + _capacity_limiter_wrapper.set(limiter) + return limiter + + @classmethod + def open_signal_receiver( + cls, *signals: Signals + ) -> AbstractContextManager[AsyncIterator[Signals]]: + return _SignalReceiver(signals) + + @classmethod + def get_current_task(cls) -> TaskInfo: + task = current_task() + return TrioTaskInfo(task) + + @classmethod + def get_running_tasks(cls) -> Sequence[TaskInfo]: + root_task = current_root_task() + assert root_task + task_infos = [TrioTaskInfo(root_task)] + nurseries = root_task.child_nurseries + while nurseries: + new_nurseries: list[trio.Nursery] = [] + for nursery in nurseries: + for task in nursery.child_tasks: + task_infos.append(TrioTaskInfo(task)) + new_nurseries.extend(task.child_nurseries) + + nurseries = new_nurseries + + return task_infos + + @classmethod + async def wait_all_tasks_blocked(cls) -> None: + from trio.testing import wait_all_tasks_blocked + + await wait_all_tasks_blocked() + + @classmethod + def create_test_runner(cls, options: dict[str, Any]) -> TestRunner: + return TestRunner(**options) + + +backend_class = TrioBackend diff --git a/backend/.venv/Lib/site-packages/anyio/_core/__init__.py b/backend/.venv/Lib/site-packages/anyio/_core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/anyio/_core/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/_core/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0da312bfbb56af30c3225d038b128580f60c18e0 GIT binary patch literal 186 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_contextmanagers.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_contextmanagers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fd573696416eb1bbd0061ff61f056c183686aa0c GIT binary patch literal 8996 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_exceptions.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_exceptions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2e18338818844d67b3ca24311328e9d682c24f1a GIT binary patch literal 7263 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 Y()1&k9&Z-r%WoPnV*Yc6hs4$Y07d%dFaQ7m literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_fileio.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_fileio.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ea4d55853f17a932ba20480223f724a5bb587b82 GIT binary patch literal 43368 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 Som)OG;`+V3`n!y4R_ZUo+jpJ- literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_sockets.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_sockets.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cb425026098023f21b8d955519265977a6a75d5a GIT binary patch literal 39926 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_streams.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_streams.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..94157c49d060023d0be2ba0315ed2cb96ba4f9e5 GIT binary patch literal 2335 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_synchronization.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_synchronization.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6575cc3cf45c8a54dd8357e68a60fabd89966d46 GIT binary patch literal 32941 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_testing.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/_core/__pycache__/_testing.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..74f73498ce9c0a42e2aed4bc31917f7fb1f18f52 GIT binary patch literal 3566 zcmaJDOKjZ6b!L~`4_DI4wq#q4yTQV=kX_xvhX z10XIbg6h0;(_pIO1*&76SA%6+t$NOlstr?Mb(S2Pss57KK&}p+HG=_#-e!B8J|Ym8 zO{mTiNKuQ};l`l0W~&`1Tvgniot%LFB zrtiA8DU4V$7R}NnpZV3m@od!uEIJRdXw6?-0piX>#aWsh$~xX3rW`BGCjy6(Sd{Pp zQ|>Tw8gTg2)@@e{*<_UQVJs^Q|xbe;78KkG%% zhoFd{AApt#C2qS*hwX*ZQq?m#3W6S}stHPe<&sO=GVcPTFO2E$=rs-F~wY=+R zL4Edo94hmro3?jz{&i<@o;!hk78q8I>o%VUw{iSQ9cd@^z~;zVTC0UQU3WYu(DnL} zw)2F=j4~oqbr?=?V*zTDN+h;B`wHKR%7jH}NDtjk} zV94%0S%RT&PaT6HzxUFm+tPda792y&PSc?ggpn5j*(3pmzxWz7Na)%*hYdBzVdibn z!&X;M6Ea7F#FTU79-Y;sP;t29@xbs*n-$VXYpz{^NVF|2#qi;w>_Z$g zj-se4JBdpfUAJ$5s)`+|!i6!|X z#+yCkUlvE2xe@japfr=`!UVljsA2+;1F9g0dHemCcaE@OV1O(tEgO7UyyhMi(sLw< zr3Mq@c9)5xr87Xr(IG+d;<5K%*_^&J{j0Z|x#7o!L~RNoqk01NfQ9bwFmXk29%{W0 zQx*i^N@Ax+r@>D8qs$!9q}jT3+OaOyvlAkPT@0xPmdxwA=^C6vz`^t4U=wjBLhRdc zQkM!CB=Rm5L`!Fpwgg~<>>WM6S-Ml&J*sUV)tX1nY>jONe^|e_zP0+t6CV$JGW4gR zk9$A;L9=+JnY;41f>3&)APJC7Qlna`u8RbSLHwp2RGFtPEWE|4_QC?Da;y`WKUA=V zYN#gqrR$24sjflYgAknnhRcS_kwf_7y2I_b=-{cB?-ADh*pqOa9`oy+ht|K9`0f89 zc^X9LnDjQtzC!v3#VcpETofs3s4F6o)fKFD4RzLsN{$+@D_CRV1@x!7mQ?wxP~s=l zHn;{$+^*o3up$HDWnh3x4 zOKm8df$IAHTDzlrq@(r$B2*pd4%Ns}d8C?$eMoS%9a`74G{XQA`U*ue8{e$s0lZs# zQ%H;8`|#%&2$A;soBiq+qu<#XeSUXzdV6$wXLM$#@M=?f^>H<#s@}nN=?y?$BlLhO z+ba5hp7Rd0Pd|fGex2G(|5BFWgc_Y9@5;YVuVWH>{zuTdLq{7pu4=e$l!#(ILi?&> zXOEg)@|nv0iXALtb1@tHOn4mkbzqDXpf9>UwDnfEBEAd4GX&V!^CtlOi~MJUe5pLK zqm1k-&uuHu?I`DVrE{N4=N@uwtbQ>(PJc(oq`R4MDDQEiD8NP=Klca^CCpXO<3q2u zRE1QG-5Dw_EOzy{OoCO0&K72%!G@q@ek)NU*4wyvGjt{pYRb|Gt-$?VLPHP-CR z=H6LJyR3sSqE&DLp->cPQcNF8f?oRCmy*Xq`yf?>$b(B=+EVf+M**8W^_)9DE6E}B z!d~vZbME=O=R4=@U%I;T1jhLEDf_QELjHxDc&On*+W8$UR*6L{$sskVB1yQG9l54d zl$u&m#a?kzwR9z2%TzM8Y$aRERdR5yS}7-AD^v;+kqOOM=`|_jS}BTsCfRqvzI!c_ zT`5`JR(4sf^vL8V#L6ubE59a3H+#id0nUoaSzoiOT>1KD$atU`#iGYE@S;zwo^5}SAl__t2J zO8o|NHA8E-_8SeVdDR=#^hdP@rTFqc{nvY6oMyv%N2hGwUVa`$4njW90?)>ycyE@HnpN_$WIpaFz(}vr$ zz2iF49@m9PlsH~*1|_l669rg5i0pzNhmavl@z{Q+ zXr|{l;5vNs@w~WjW|o?BT=QoQU!(A_O|9OjI=0#Iq~^^;UwES$vYs_KyapPqb)slo z@H3M)1Z&dp1M{Sv-^1e9((V^-15j+T78!q2@}m_YZ4!t3S#s?;LT<`!`9=yD>>HLG z(=qAofwtV1<|Qt@{gj`H2`!~9|3b&hEVo_mS)!Gaxtsdf0V zm>7SI@h}kbX_y`@k$WR!ADZhgoc*}EIdXobaBt}8_s;w_yK-);|LITrM>hIL?(k3g zzxjvk$A!O5T(~!QaBEPzGjyl8K6+vOiHkdm{AAxYk$d~LQ)Kwi7e$imek-$)J@iTT zun2KTDQPBf8>myBOTi~uT}Ly(pLt!cc~-;0by3&fXc$iPC8O(>XX?5zDd>s}HmT!) zS0r`_^~VVNQD`_k9$`448#qpnmdOKIO=TYzv#BEw2uwm9L1e=BWF(0j-LV&RRJAey zIW^8gl@v`|Sxeb5$~$<0hNT`mNJd!ObN=FQs{Wvw$mHaOKf za1|>Wp>e_HvzXoLA$5dhy67{b15Q4^2XN>b2pVYzk+({0f(g_(561$Wm?2I>x)k{x zaqZ7iZ9hkpX-35$QYCyyK@FLYQC|043xYpkI&U})8mAPLaz5l8>CUtTX4D~PK*gD* zEH;Ua3YJOAgq+2^T9}LQ0)Ru~vtGlo5fe*vG~lg;FHG z#Efc2Q^U%|!1MSaVcD@Yl1_!TSWRpffa{vH93@M%jP-zPp|+@;Ix`{`H4%$Jk8otC z0PxmxU;XUk`w1b*#Z_W^ko5GeI05Z3y}*QxStAmo@~m&n%hCqmhndUlUJve|L?6iQcwbT$D8LBet;7JlL=F=_@#7J~h9%OL z{RsSoGzcs1Dj3olA_#^h--5DZ%C7-}7RaLV8d;Fait(r2ND`hsnz(&bi_AaOaA9S; z)GCKH7F?l4Jq!X)fF(xXbsIX3ug3PSpqs24%&2u>KPf^x5v?7q(OMPI0+2SeNs&e- zUw?D&n?sZEdKti-1U{qq$yW6x78T=%=i( z`PcMQ)QKn!K(+^3$z*5=3MfKtN>qt08u95oV|dgX{hi%WpO3` zzk_`eF7t~pEs^a5>De?Gh3^UD1v5B#coI|tvtj&S2Q5v6DDq$_>l7$SB8f zixaZrKZR+T+*Mz`pX&Nt&Zqiz6q4@V#?|%^tOE6fIN4H907al)iFQ}+r}A4Tf4D;i zQ$u)Ecp$?n6obrT7c#V`+>cGmOauOiK+_U7W~JTTv{5w~W)+5cG)VhR{0k+nGVDh~ zW6-vspwmT@)GyT$%@FKiaIrQF?O-|cftxt+8uJ@GJKlAuw7 P>EV$v3E~YV;e`JI0QTqq literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/_core/_asyncio_selector_thread.py b/backend/.venv/Lib/site-packages/anyio/_core/_asyncio_selector_thread.py new file mode 100644 index 0000000..9f35bae --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/_core/_asyncio_selector_thread.py @@ -0,0 +1,167 @@ +from __future__ import annotations + +import asyncio +import socket +import threading +from collections.abc import Callable +from selectors import EVENT_READ, EVENT_WRITE, DefaultSelector +from typing import TYPE_CHECKING, Any + +if TYPE_CHECKING: + from _typeshed import FileDescriptorLike + +_selector_lock = threading.Lock() +_selector: Selector | None = None + + +class Selector: + def __init__(self) -> None: + self._thread = threading.Thread(target=self.run, name="AnyIO socket selector") + self._selector = DefaultSelector() + self._send, self._receive = socket.socketpair() + self._send.setblocking(False) + self._receive.setblocking(False) + # This somewhat reduces the amount of memory wasted queueing up data + # for wakeups. With these settings, maximum number of 1-byte sends + # before getting BlockingIOError: + # Linux 4.8: 6 + # macOS (darwin 15.5): 1 + # Windows 10: 525347 + # Windows you're weird. (And on Windows setting SNDBUF to 0 makes send + # blocking, even on non-blocking sockets, so don't do that.) + self._receive.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1) + self._send.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1) + # On Windows this is a TCP socket so this might matter. On other + # platforms this fails b/c AF_UNIX sockets aren't actually TCP. + try: + self._send.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + except OSError: + pass + + self._selector.register(self._receive, EVENT_READ) + self._closed = False + + def start(self) -> None: + self._thread.start() + threading._register_atexit(self._stop) # type: ignore[attr-defined] + + def _stop(self) -> None: + global _selector + self._closed = True + self._notify_self() + self._send.close() + self._thread.join() + self._selector.unregister(self._receive) + self._receive.close() + self._selector.close() + _selector = None + assert not self._selector.get_map(), ( + "selector still has registered file descriptors after shutdown" + ) + + def _notify_self(self) -> None: + try: + self._send.send(b"\x00") + except BlockingIOError: + pass + + def add_reader(self, fd: FileDescriptorLike, callback: Callable[[], Any]) -> None: + loop = asyncio.get_running_loop() + try: + key = self._selector.get_key(fd) + except KeyError: + self._selector.register(fd, EVENT_READ, {EVENT_READ: (loop, callback)}) + else: + if EVENT_READ in key.data: + raise ValueError( + "this file descriptor is already registered for reading" + ) + + key.data[EVENT_READ] = loop, callback + self._selector.modify(fd, key.events | EVENT_READ, key.data) + + self._notify_self() + + def add_writer(self, fd: FileDescriptorLike, callback: Callable[[], Any]) -> None: + loop = asyncio.get_running_loop() + try: + key = self._selector.get_key(fd) + except KeyError: + self._selector.register(fd, EVENT_WRITE, {EVENT_WRITE: (loop, callback)}) + else: + if EVENT_WRITE in key.data: + raise ValueError( + "this file descriptor is already registered for writing" + ) + + key.data[EVENT_WRITE] = loop, callback + self._selector.modify(fd, key.events | EVENT_WRITE, key.data) + + self._notify_self() + + def remove_reader(self, fd: FileDescriptorLike) -> bool: + try: + key = self._selector.get_key(fd) + except KeyError: + return False + + if new_events := key.events ^ EVENT_READ: + del key.data[EVENT_READ] + self._selector.modify(fd, new_events, key.data) + else: + self._selector.unregister(fd) + + return True + + def remove_writer(self, fd: FileDescriptorLike) -> bool: + try: + key = self._selector.get_key(fd) + except KeyError: + return False + + if new_events := key.events ^ EVENT_WRITE: + del key.data[EVENT_WRITE] + self._selector.modify(fd, new_events, key.data) + else: + self._selector.unregister(fd) + + return True + + def run(self) -> None: + while not self._closed: + for key, events in self._selector.select(): + if key.fileobj is self._receive: + try: + while self._receive.recv(4096): + pass + except BlockingIOError: + pass + + continue + + if events & EVENT_READ: + loop, callback = key.data[EVENT_READ] + self.remove_reader(key.fd) + try: + loop.call_soon_threadsafe(callback) + except RuntimeError: + pass # the loop was already closed + + if events & EVENT_WRITE: + loop, callback = key.data[EVENT_WRITE] + self.remove_writer(key.fd) + try: + loop.call_soon_threadsafe(callback) + except RuntimeError: + pass # the loop was already closed + + +def get_selector() -> Selector: + global _selector + + with _selector_lock: + if _selector is None: + _selector = Selector() + _selector.start() + + return _selector diff --git a/backend/.venv/Lib/site-packages/anyio/_core/_contextmanagers.py b/backend/.venv/Lib/site-packages/anyio/_core/_contextmanagers.py new file mode 100644 index 0000000..302f32b --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/_core/_contextmanagers.py @@ -0,0 +1,200 @@ +from __future__ import annotations + +from abc import abstractmethod +from contextlib import AbstractAsyncContextManager, AbstractContextManager +from inspect import isasyncgen, iscoroutine, isgenerator +from types import TracebackType +from typing import Protocol, TypeVar, cast, final + +_T_co = TypeVar("_T_co", covariant=True) +_ExitT_co = TypeVar("_ExitT_co", covariant=True, bound="bool | None") + + +class _SupportsCtxMgr(Protocol[_T_co, _ExitT_co]): + def __contextmanager__(self) -> AbstractContextManager[_T_co, _ExitT_co]: ... + + +class _SupportsAsyncCtxMgr(Protocol[_T_co, _ExitT_co]): + def __asynccontextmanager__( + self, + ) -> AbstractAsyncContextManager[_T_co, _ExitT_co]: ... + + +class ContextManagerMixin: + """ + Mixin class providing context manager functionality via a generator-based + implementation. + + This class allows you to implement a context manager via :meth:`__contextmanager__` + which should return a generator. The mechanics are meant to mirror those of + :func:`@contextmanager `. + + .. note:: Classes using this mix-in are not reentrant as context managers, meaning + that once you enter it, you can't re-enter before first exiting it. + + .. seealso:: :doc:`contextmanagers` + """ + + __cm: AbstractContextManager[object, bool | None] | None = None + + @final + def __enter__(self: _SupportsCtxMgr[_T_co, bool | None]) -> _T_co: + # Needed for mypy to assume self still has the __cm member + assert isinstance(self, ContextManagerMixin) + if self.__cm is not None: + raise RuntimeError( + f"this {self.__class__.__qualname__} has already been entered" + ) + + cm = self.__contextmanager__() + if not isinstance(cm, AbstractContextManager): + if isgenerator(cm): + raise TypeError( + "__contextmanager__() returned a generator object instead of " + "a context manager. Did you forget to add the @contextmanager " + "decorator?" + ) + + raise TypeError( + f"__contextmanager__() did not return a context manager object, " + f"but {cm.__class__!r}" + ) + + if cm is self: + raise TypeError( + f"{self.__class__.__qualname__}.__contextmanager__() returned " + f"self. Did you forget to add the @contextmanager decorator and a " + f"'yield' statement?" + ) + + value = cm.__enter__() + self.__cm = cm + return value + + @final + def __exit__( + self: _SupportsCtxMgr[object, _ExitT_co], + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> _ExitT_co: + # Needed for mypy to assume self still has the __cm member + assert isinstance(self, ContextManagerMixin) + if self.__cm is None: + raise RuntimeError( + f"this {self.__class__.__qualname__} has not been entered yet" + ) + + # Prevent circular references + cm = self.__cm + del self.__cm + + return cast(_ExitT_co, cm.__exit__(exc_type, exc_val, exc_tb)) + + @abstractmethod + def __contextmanager__(self) -> AbstractContextManager[object, bool | None]: + """ + Implement your context manager logic here. + + This method **must** be decorated with + :func:`@contextmanager `. + + .. note:: Remember that the ``yield`` will raise any exception raised in the + enclosed context block, so use a ``finally:`` block to clean up resources! + + :return: a context manager object + """ + + +class AsyncContextManagerMixin: + """ + Mixin class providing async context manager functionality via a generator-based + implementation. + + This class allows you to implement a context manager via + :meth:`__asynccontextmanager__`. The mechanics are meant to mirror those of + :func:`@asynccontextmanager `. + + .. note:: Classes using this mix-in are not reentrant as context managers, meaning + that once you enter it, you can't re-enter before first exiting it. + + .. seealso:: :doc:`contextmanagers` + """ + + __cm: AbstractAsyncContextManager[object, bool | None] | None = None + + @final + async def __aenter__(self: _SupportsAsyncCtxMgr[_T_co, bool | None]) -> _T_co: + # Needed for mypy to assume self still has the __cm member + assert isinstance(self, AsyncContextManagerMixin) + if self.__cm is not None: + raise RuntimeError( + f"this {self.__class__.__qualname__} has already been entered" + ) + + cm = self.__asynccontextmanager__() + if not isinstance(cm, AbstractAsyncContextManager): + if isasyncgen(cm): + raise TypeError( + "__asynccontextmanager__() returned an async generator instead of " + "an async context manager. Did you forget to add the " + "@asynccontextmanager decorator?" + ) + elif iscoroutine(cm): + cm.close() + raise TypeError( + "__asynccontextmanager__() returned a coroutine object instead of " + "an async context manager. Did you forget to add the " + "@asynccontextmanager decorator and a 'yield' statement?" + ) + + raise TypeError( + f"__asynccontextmanager__() did not return an async context manager, " + f"but {cm.__class__!r}" + ) + + if cm is self: + raise TypeError( + f"{self.__class__.__qualname__}.__asynccontextmanager__() returned " + f"self. Did you forget to add the @asynccontextmanager decorator and a " + f"'yield' statement?" + ) + + value = await cm.__aenter__() + self.__cm = cm + return value + + @final + async def __aexit__( + self: _SupportsAsyncCtxMgr[object, _ExitT_co], + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> _ExitT_co: + assert isinstance(self, AsyncContextManagerMixin) + if self.__cm is None: + raise RuntimeError( + f"this {self.__class__.__qualname__} has not been entered yet" + ) + + # Prevent circular references + cm = self.__cm + del self.__cm + + return cast(_ExitT_co, await cm.__aexit__(exc_type, exc_val, exc_tb)) + + @abstractmethod + def __asynccontextmanager__( + self, + ) -> AbstractAsyncContextManager[object, bool | None]: + """ + Implement your async context manager logic here. + + This method **must** be decorated with + :func:`@asynccontextmanager `. + + .. note:: Remember that the ``yield`` will raise any exception raised in the + enclosed context block, so use a ``finally:`` block to clean up resources! + + :return: an async context manager object + """ diff --git a/backend/.venv/Lib/site-packages/anyio/_core/_eventloop.py b/backend/.venv/Lib/site-packages/anyio/_core/_eventloop.py new file mode 100644 index 0000000..46d9f46 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/_core/_eventloop.py @@ -0,0 +1,229 @@ +from __future__ import annotations + +import math +import sys +import threading +from collections.abc import Awaitable, Callable, Generator +from contextlib import contextmanager +from contextvars import Token +from importlib import import_module +from typing import TYPE_CHECKING, Any, TypeVar + +if sys.version_info >= (3, 11): + from typing import TypeVarTuple, Unpack +else: + from typing_extensions import TypeVarTuple, Unpack + +sniffio: Any +try: + import sniffio +except ModuleNotFoundError: + sniffio = None + +if TYPE_CHECKING: + from ..abc import AsyncBackend + +# This must be updated when new backends are introduced +BACKENDS = "asyncio", "trio" + +T_Retval = TypeVar("T_Retval") +PosArgsT = TypeVarTuple("PosArgsT") + +threadlocals = threading.local() +loaded_backends: dict[str, type[AsyncBackend]] = {} + + +def run( + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], + *args: Unpack[PosArgsT], + backend: str = "asyncio", + backend_options: dict[str, Any] | None = None, +) -> T_Retval: + """ + Run the given coroutine function in an asynchronous event loop. + + The current thread must not be already running an event loop. + + :param func: a coroutine function + :param args: positional arguments to ``func`` + :param backend: name of the asynchronous event loop implementation – currently + either ``asyncio`` or ``trio`` + :param backend_options: keyword arguments to call the backend ``run()`` + implementation with (documented :ref:`here `) + :return: the return value of the coroutine function + :raises RuntimeError: if an asynchronous event loop is already running in this + thread + :raises LookupError: if the named backend is not found + + """ + if asynclib_name := current_async_library(): + raise RuntimeError(f"Already running {asynclib_name} in this thread") + + try: + async_backend = get_async_backend(backend) + except ImportError as exc: + raise LookupError(f"No such backend: {backend}") from exc + + token = None + if asynclib_name is None: + # Since we're in control of the event loop, we can cache the name of the async + # library + token = set_current_async_library(backend) + + try: + backend_options = backend_options or {} + return async_backend.run(func, args, {}, backend_options) + finally: + reset_current_async_library(token) + + +async def sleep(delay: float) -> None: + """ + Pause the current task for the specified duration. + + :param delay: the duration, in seconds + + """ + return await get_async_backend().sleep(delay) + + +async def sleep_forever() -> None: + """ + Pause the current task until it's cancelled. + + This is a shortcut for ``sleep(math.inf)``. + + .. versionadded:: 3.1 + + """ + await sleep(math.inf) + + +async def sleep_until(deadline: float) -> None: + """ + Pause the current task until the given time. + + :param deadline: the absolute time to wake up at (according to the internal + monotonic clock of the event loop) + + .. versionadded:: 3.1 + + """ + now = current_time() + await sleep(max(deadline - now, 0)) + + +def current_time() -> float: + """ + Return the current value of the event loop's internal clock. + + :return: the clock value (seconds) + + """ + return get_async_backend().current_time() + + +def get_all_backends() -> tuple[str, ...]: + """Return a tuple of the names of all built-in backends.""" + return BACKENDS + + +def get_available_backends() -> tuple[str, ...]: + """ + Test for the availability of built-in backends. + + :return a tuple of the built-in backend names that were successfully imported + + .. versionadded:: 4.12 + + """ + available_backends: list[str] = [] + for backend_name in get_all_backends(): + try: + get_async_backend(backend_name) + except ImportError: + continue + + available_backends.append(backend_name) + + return tuple(available_backends) + + +def get_cancelled_exc_class() -> type[BaseException]: + """Return the current async library's cancellation exception class.""" + return get_async_backend().cancelled_exception_class() + + +# +# Private API +# + + +@contextmanager +def claim_worker_thread( + backend_class: type[AsyncBackend], token: object +) -> Generator[Any, None, None]: + from ..lowlevel import EventLoopToken + + threadlocals.current_token = EventLoopToken(backend_class, token) + try: + yield + finally: + del threadlocals.current_token + + +class NoCurrentAsyncBackend(Exception): + def __init__(self) -> None: + super().__init__( + f"Not currently running on any asynchronous event loop" + f"Available async backends: {', '.join(get_all_backends())}" + ) + + +def get_async_backend(asynclib_name: str | None = None) -> type[AsyncBackend]: + if asynclib_name is None: + asynclib_name = current_async_library() + if not asynclib_name: + raise NoCurrentAsyncBackend + + # We use our own dict instead of sys.modules to get the already imported back-end + # class because the appropriate modules in sys.modules could potentially be only + # partially initialized + try: + return loaded_backends[asynclib_name] + except KeyError: + module = import_module(f"anyio._backends._{asynclib_name}") + loaded_backends[asynclib_name] = module.backend_class + return module.backend_class + + +def current_async_library() -> str | None: + if sniffio is None: + # If sniffio is not installed, we assume we're either running asyncio or nothing + import asyncio + + try: + asyncio.get_running_loop() + return "asyncio" + except RuntimeError: + pass + else: + try: + return sniffio.current_async_library() + except sniffio.AsyncLibraryNotFoundError: + pass + + return None + + +def set_current_async_library(asynclib_name: str | None) -> Token | None: + # no-op if sniffio is not installed + if sniffio is None: + return None + + return sniffio.current_async_library_cvar.set(asynclib_name) + + +def reset_current_async_library(token: Token | None) -> None: + if token is not None: + sniffio.current_async_library_cvar.reset(token) diff --git a/backend/.venv/Lib/site-packages/anyio/_core/_exceptions.py b/backend/.venv/Lib/site-packages/anyio/_core/_exceptions.py new file mode 100644 index 0000000..5f123d7 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/_core/_exceptions.py @@ -0,0 +1,153 @@ +from __future__ import annotations + +import sys +from collections.abc import Generator +from textwrap import dedent +from typing import Any + +if sys.version_info < (3, 11): + from exceptiongroup import BaseExceptionGroup + + +class BrokenResourceError(Exception): + """ + Raised when trying to use a resource that has been rendered unusable due to external + causes (e.g. a send stream whose peer has disconnected). + """ + + +class BrokenWorkerProcess(Exception): + """ + Raised by :meth:`~anyio.to_process.run_sync` if the worker process terminates abruptly or + otherwise misbehaves. + """ + + +class BrokenWorkerInterpreter(Exception): + """ + Raised by :meth:`~anyio.to_interpreter.run_sync` if an unexpected exception is + raised in the subinterpreter. + """ + + def __init__(self, excinfo: Any): + # This was adapted from concurrent.futures.interpreter.ExecutionFailed + msg = excinfo.formatted + if not msg: + if excinfo.type and excinfo.msg: + msg = f"{excinfo.type.__name__}: {excinfo.msg}" + else: + msg = excinfo.type.__name__ or excinfo.msg + + super().__init__(msg) + self.excinfo = excinfo + + def __str__(self) -> str: + try: + formatted = self.excinfo.errdisplay + except Exception: + return super().__str__() + else: + return dedent( + f""" + {super().__str__()} + + Uncaught in the interpreter: + + {formatted} + """.strip() + ) + + +class BusyResourceError(Exception): + """ + Raised when two tasks are trying to read from or write to the same resource + concurrently. + """ + + def __init__(self, action: str): + super().__init__(f"Another task is already {action} this resource") + + +class ClosedResourceError(Exception): + """Raised when trying to use a resource that has been closed.""" + + +class ConnectionFailed(OSError): + """ + Raised when a connection attempt fails. + + .. note:: This class inherits from :exc:`OSError` for backwards compatibility. + """ + + +def iterate_exceptions( + exception: BaseException, +) -> Generator[BaseException, None, None]: + if isinstance(exception, BaseExceptionGroup): + for exc in exception.exceptions: + yield from iterate_exceptions(exc) + else: + yield exception + + +class DelimiterNotFound(Exception): + """ + Raised during + :meth:`~anyio.streams.buffered.BufferedByteReceiveStream.receive_until` if the + maximum number of bytes has been read without the delimiter being found. + """ + + def __init__(self, max_bytes: int) -> None: + super().__init__( + f"The delimiter was not found among the first {max_bytes} bytes" + ) + + +class EndOfStream(Exception): + """ + Raised when trying to read from a stream that has been closed from the other end. + """ + + +class IncompleteRead(Exception): + """ + Raised during + :meth:`~anyio.streams.buffered.BufferedByteReceiveStream.receive_exactly` or + :meth:`~anyio.streams.buffered.BufferedByteReceiveStream.receive_until` if the + connection is closed before the requested amount of bytes has been read. + """ + + def __init__(self) -> None: + super().__init__( + "The stream was closed before the read operation could be completed" + ) + + +class TypedAttributeLookupError(LookupError): + """ + Raised by :meth:`~anyio.TypedAttributeProvider.extra` when the given typed attribute + is not found and no default value has been given. + """ + + +class WouldBlock(Exception): + """Raised by ``X_nowait`` functions if ``X()`` would block.""" + + +class NoEventLoopError(RuntimeError): + """ + Raised by :func:`.from_thread.run` and :func:`.from_thread.run_sync` if + not calling from an AnyIO worker thread, and no ``token`` was passed. + """ + + +class RunFinishedError(RuntimeError): + """ + Raised by :func:`.from_thread.run` and :func:`.from_thread.run_sync` if the event + loop associated with the explicitly passed token has already finished. + """ + + def __init__(self) -> None: + super().__init__( + "The event loop associated with the given token has already finished" + ) diff --git a/backend/.venv/Lib/site-packages/anyio/_core/_fileio.py b/backend/.venv/Lib/site-packages/anyio/_core/_fileio.py new file mode 100644 index 0000000..061f0d7 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/_core/_fileio.py @@ -0,0 +1,797 @@ +from __future__ import annotations + +import os +import pathlib +import sys +from collections.abc import ( + AsyncIterator, + Callable, + Iterable, + Iterator, + Sequence, +) +from dataclasses import dataclass +from functools import partial +from os import PathLike +from typing import ( + IO, + TYPE_CHECKING, + Any, + AnyStr, + ClassVar, + Final, + Generic, + overload, +) + +from .. import to_thread +from ..abc import AsyncResource + +if TYPE_CHECKING: + from types import ModuleType + + from _typeshed import OpenBinaryMode, OpenTextMode, ReadableBuffer, WriteableBuffer +else: + ReadableBuffer = OpenBinaryMode = OpenTextMode = WriteableBuffer = object + + +class AsyncFile(AsyncResource, Generic[AnyStr]): + """ + An asynchronous file object. + + This class wraps a standard file object and provides async friendly versions of the + following blocking methods (where available on the original file object): + + * read + * read1 + * readline + * readlines + * readinto + * readinto1 + * write + * writelines + * truncate + * seek + * tell + * flush + + All other methods are directly passed through. + + This class supports the asynchronous context manager protocol which closes the + underlying file at the end of the context block. + + This class also supports asynchronous iteration:: + + async with await open_file(...) as f: + async for line in f: + print(line) + """ + + def __init__(self, fp: IO[AnyStr]) -> None: + self._fp: Any = fp + + def __getattr__(self, name: str) -> object: + return getattr(self._fp, name) + + @property + def wrapped(self) -> IO[AnyStr]: + """The wrapped file object.""" + return self._fp + + async def __aiter__(self) -> AsyncIterator[AnyStr]: + while True: + line = await self.readline() + if line: + yield line + else: + break + + async def aclose(self) -> None: + return await to_thread.run_sync(self._fp.close) + + async def read(self, size: int = -1) -> AnyStr: + return await to_thread.run_sync(self._fp.read, size) + + async def read1(self: AsyncFile[bytes], size: int = -1) -> bytes: + return await to_thread.run_sync(self._fp.read1, size) + + async def readline(self) -> AnyStr: + return await to_thread.run_sync(self._fp.readline) + + async def readlines(self) -> list[AnyStr]: + return await to_thread.run_sync(self._fp.readlines) + + async def readinto(self: AsyncFile[bytes], b: WriteableBuffer) -> int: + return await to_thread.run_sync(self._fp.readinto, b) + + async def readinto1(self: AsyncFile[bytes], b: WriteableBuffer) -> int: + return await to_thread.run_sync(self._fp.readinto1, b) + + @overload + async def write(self: AsyncFile[bytes], b: ReadableBuffer) -> int: ... + + @overload + async def write(self: AsyncFile[str], b: str) -> int: ... + + async def write(self, b: ReadableBuffer | str) -> int: + return await to_thread.run_sync(self._fp.write, b) + + @overload + async def writelines( + self: AsyncFile[bytes], lines: Iterable[ReadableBuffer] + ) -> None: ... + + @overload + async def writelines(self: AsyncFile[str], lines: Iterable[str]) -> None: ... + + async def writelines(self, lines: Iterable[ReadableBuffer] | Iterable[str]) -> None: + return await to_thread.run_sync(self._fp.writelines, lines) + + async def truncate(self, size: int | None = None) -> int: + return await to_thread.run_sync(self._fp.truncate, size) + + async def seek(self, offset: int, whence: int | None = os.SEEK_SET) -> int: + return await to_thread.run_sync(self._fp.seek, offset, whence) + + async def tell(self) -> int: + return await to_thread.run_sync(self._fp.tell) + + async def flush(self) -> None: + return await to_thread.run_sync(self._fp.flush) + + +@overload +async def open_file( + file: str | PathLike[str] | int, + mode: OpenBinaryMode, + buffering: int = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., + closefd: bool = ..., + opener: Callable[[str, int], int] | None = ..., +) -> AsyncFile[bytes]: ... + + +@overload +async def open_file( + file: str | PathLike[str] | int, + mode: OpenTextMode = ..., + buffering: int = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., + closefd: bool = ..., + opener: Callable[[str, int], int] | None = ..., +) -> AsyncFile[str]: ... + + +async def open_file( + file: str | PathLike[str] | int, + mode: str = "r", + buffering: int = -1, + encoding: str | None = None, + errors: str | None = None, + newline: str | None = None, + closefd: bool = True, + opener: Callable[[str, int], int] | None = None, +) -> AsyncFile[Any]: + """ + Open a file asynchronously. + + The arguments are exactly the same as for the builtin :func:`open`. + + :return: an asynchronous file object + + """ + fp = await to_thread.run_sync( + open, file, mode, buffering, encoding, errors, newline, closefd, opener + ) + return AsyncFile(fp) + + +def wrap_file(file: IO[AnyStr]) -> AsyncFile[AnyStr]: + """ + Wrap an existing file as an asynchronous file. + + :param file: an existing file-like object + :return: an asynchronous file object + + """ + return AsyncFile(file) + + +@dataclass(eq=False) +class _PathIterator(AsyncIterator["Path"]): + iterator: Iterator[PathLike[str]] + + async def __anext__(self) -> Path: + nextval = await to_thread.run_sync( + next, self.iterator, None, abandon_on_cancel=True + ) + if nextval is None: + raise StopAsyncIteration from None + + return Path(nextval) + + +class Path: + """ + An asynchronous version of :class:`pathlib.Path`. + + This class cannot be substituted for :class:`pathlib.Path` or + :class:`pathlib.PurePath`, but it is compatible with the :class:`os.PathLike` + interface. + + It implements the Python 3.10 version of :class:`pathlib.Path` interface, except for + the deprecated :meth:`~pathlib.Path.link_to` method. + + Some methods may be unavailable or have limited functionality, based on the Python + version: + + * :meth:`~pathlib.Path.copy` (available on Python 3.14 or later) + * :meth:`~pathlib.Path.copy_into` (available on Python 3.14 or later) + * :meth:`~pathlib.Path.from_uri` (available on Python 3.13 or later) + * :meth:`~pathlib.PurePath.full_match` (available on Python 3.13 or later) + * :attr:`~pathlib.Path.info` (available on Python 3.14 or later) + * :meth:`~pathlib.Path.is_junction` (available on Python 3.12 or later) + * :meth:`~pathlib.PurePath.match` (the ``case_sensitive`` parameter is only + available on Python 3.13 or later) + * :meth:`~pathlib.Path.move` (available on Python 3.14 or later) + * :meth:`~pathlib.Path.move_into` (available on Python 3.14 or later) + * :meth:`~pathlib.PurePath.relative_to` (the ``walk_up`` parameter is only available + on Python 3.12 or later) + * :meth:`~pathlib.Path.walk` (available on Python 3.12 or later) + + Any methods that do disk I/O need to be awaited on. These methods are: + + * :meth:`~pathlib.Path.absolute` + * :meth:`~pathlib.Path.chmod` + * :meth:`~pathlib.Path.cwd` + * :meth:`~pathlib.Path.exists` + * :meth:`~pathlib.Path.expanduser` + * :meth:`~pathlib.Path.group` + * :meth:`~pathlib.Path.hardlink_to` + * :meth:`~pathlib.Path.home` + * :meth:`~pathlib.Path.is_block_device` + * :meth:`~pathlib.Path.is_char_device` + * :meth:`~pathlib.Path.is_dir` + * :meth:`~pathlib.Path.is_fifo` + * :meth:`~pathlib.Path.is_file` + * :meth:`~pathlib.Path.is_junction` + * :meth:`~pathlib.Path.is_mount` + * :meth:`~pathlib.Path.is_socket` + * :meth:`~pathlib.Path.is_symlink` + * :meth:`~pathlib.Path.lchmod` + * :meth:`~pathlib.Path.lstat` + * :meth:`~pathlib.Path.mkdir` + * :meth:`~pathlib.Path.open` + * :meth:`~pathlib.Path.owner` + * :meth:`~pathlib.Path.read_bytes` + * :meth:`~pathlib.Path.read_text` + * :meth:`~pathlib.Path.readlink` + * :meth:`~pathlib.Path.rename` + * :meth:`~pathlib.Path.replace` + * :meth:`~pathlib.Path.resolve` + * :meth:`~pathlib.Path.rmdir` + * :meth:`~pathlib.Path.samefile` + * :meth:`~pathlib.Path.stat` + * :meth:`~pathlib.Path.symlink_to` + * :meth:`~pathlib.Path.touch` + * :meth:`~pathlib.Path.unlink` + * :meth:`~pathlib.Path.walk` + * :meth:`~pathlib.Path.write_bytes` + * :meth:`~pathlib.Path.write_text` + + Additionally, the following methods return an async iterator yielding + :class:`~.Path` objects: + + * :meth:`~pathlib.Path.glob` + * :meth:`~pathlib.Path.iterdir` + * :meth:`~pathlib.Path.rglob` + """ + + __slots__ = "_path", "__weakref__" + + __weakref__: Any + + def __init__(self, *args: str | PathLike[str]) -> None: + self._path: Final[pathlib.Path] = pathlib.Path(*args) + + def __fspath__(self) -> str: + return self._path.__fspath__() + + def __str__(self) -> str: + return self._path.__str__() + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self.as_posix()!r})" + + def __bytes__(self) -> bytes: + return self._path.__bytes__() + + def __hash__(self) -> int: + return self._path.__hash__() + + def __eq__(self, other: object) -> bool: + target = other._path if isinstance(other, Path) else other + return self._path.__eq__(target) + + def __lt__(self, other: pathlib.PurePath | Path) -> bool: + target = other._path if isinstance(other, Path) else other + return self._path.__lt__(target) + + def __le__(self, other: pathlib.PurePath | Path) -> bool: + target = other._path if isinstance(other, Path) else other + return self._path.__le__(target) + + def __gt__(self, other: pathlib.PurePath | Path) -> bool: + target = other._path if isinstance(other, Path) else other + return self._path.__gt__(target) + + def __ge__(self, other: pathlib.PurePath | Path) -> bool: + target = other._path if isinstance(other, Path) else other + return self._path.__ge__(target) + + def __truediv__(self, other: str | PathLike[str]) -> Path: + return Path(self._path / other) + + def __rtruediv__(self, other: str | PathLike[str]) -> Path: + return Path(other) / self + + @property + def parts(self) -> tuple[str, ...]: + return self._path.parts + + @property + def drive(self) -> str: + return self._path.drive + + @property + def root(self) -> str: + return self._path.root + + @property + def anchor(self) -> str: + return self._path.anchor + + @property + def parents(self) -> Sequence[Path]: + return tuple(Path(p) for p in self._path.parents) + + @property + def parent(self) -> Path: + return Path(self._path.parent) + + @property + def name(self) -> str: + return self._path.name + + @property + def suffix(self) -> str: + return self._path.suffix + + @property + def suffixes(self) -> list[str]: + return self._path.suffixes + + @property + def stem(self) -> str: + return self._path.stem + + async def absolute(self) -> Path: + path = await to_thread.run_sync(self._path.absolute) + return Path(path) + + def as_posix(self) -> str: + return self._path.as_posix() + + def as_uri(self) -> str: + return self._path.as_uri() + + if sys.version_info >= (3, 13): + parser: ClassVar[ModuleType] = pathlib.Path.parser + + @classmethod + def from_uri(cls, uri: str) -> Path: + return Path(pathlib.Path.from_uri(uri)) + + def full_match( + self, path_pattern: str, *, case_sensitive: bool | None = None + ) -> bool: + return self._path.full_match(path_pattern, case_sensitive=case_sensitive) + + def match( + self, path_pattern: str, *, case_sensitive: bool | None = None + ) -> bool: + return self._path.match(path_pattern, case_sensitive=case_sensitive) + else: + + def match(self, path_pattern: str) -> bool: + return self._path.match(path_pattern) + + if sys.version_info >= (3, 14): + + @property + def info(self) -> Any: # TODO: add return type annotation when Typeshed gets it + return self._path.info + + async def copy( + self, + target: str | os.PathLike[str], + *, + follow_symlinks: bool = True, + preserve_metadata: bool = False, + ) -> Path: + func = partial( + self._path.copy, + follow_symlinks=follow_symlinks, + preserve_metadata=preserve_metadata, + ) + return Path(await to_thread.run_sync(func, pathlib.Path(target))) + + async def copy_into( + self, + target_dir: str | os.PathLike[str], + *, + follow_symlinks: bool = True, + preserve_metadata: bool = False, + ) -> Path: + func = partial( + self._path.copy_into, + follow_symlinks=follow_symlinks, + preserve_metadata=preserve_metadata, + ) + return Path(await to_thread.run_sync(func, pathlib.Path(target_dir))) + + async def move(self, target: str | os.PathLike[str]) -> Path: + # Upstream does not handle anyio.Path properly as a PathLike + target = pathlib.Path(target) + return Path(await to_thread.run_sync(self._path.move, target)) + + async def move_into( + self, + target_dir: str | os.PathLike[str], + ) -> Path: + return Path(await to_thread.run_sync(self._path.move_into, target_dir)) + + def is_relative_to(self, other: str | PathLike[str]) -> bool: + try: + self.relative_to(other) + return True + except ValueError: + return False + + async def chmod(self, mode: int, *, follow_symlinks: bool = True) -> None: + func = partial(os.chmod, follow_symlinks=follow_symlinks) + return await to_thread.run_sync(func, self._path, mode) + + @classmethod + async def cwd(cls) -> Path: + path = await to_thread.run_sync(pathlib.Path.cwd) + return cls(path) + + async def exists(self) -> bool: + return await to_thread.run_sync(self._path.exists, abandon_on_cancel=True) + + async def expanduser(self) -> Path: + return Path( + await to_thread.run_sync(self._path.expanduser, abandon_on_cancel=True) + ) + + if sys.version_info < (3, 12): + # Python 3.11 and earlier + def glob(self, pattern: str) -> AsyncIterator[Path]: + gen = self._path.glob(pattern) + return _PathIterator(gen) + elif (3, 12) <= sys.version_info < (3, 13): + # changed in Python 3.12: + # - The case_sensitive parameter was added. + def glob( + self, + pattern: str, + *, + case_sensitive: bool | None = None, + ) -> AsyncIterator[Path]: + gen = self._path.glob(pattern, case_sensitive=case_sensitive) + return _PathIterator(gen) + elif sys.version_info >= (3, 13): + # Changed in Python 3.13: + # - The recurse_symlinks parameter was added. + # - The pattern parameter accepts a path-like object. + def glob( # type: ignore[misc] # mypy doesn't allow for differing signatures in a conditional block + self, + pattern: str | PathLike[str], + *, + case_sensitive: bool | None = None, + recurse_symlinks: bool = False, + ) -> AsyncIterator[Path]: + gen = self._path.glob( + pattern, # type: ignore[arg-type] + case_sensitive=case_sensitive, + recurse_symlinks=recurse_symlinks, + ) + return _PathIterator(gen) + + async def group(self) -> str: + return await to_thread.run_sync(self._path.group, abandon_on_cancel=True) + + async def hardlink_to( + self, target: str | bytes | PathLike[str] | PathLike[bytes] + ) -> None: + if isinstance(target, Path): + target = target._path + + await to_thread.run_sync(os.link, target, self) + + @classmethod + async def home(cls) -> Path: + home_path = await to_thread.run_sync(pathlib.Path.home) + return cls(home_path) + + def is_absolute(self) -> bool: + return self._path.is_absolute() + + async def is_block_device(self) -> bool: + return await to_thread.run_sync( + self._path.is_block_device, abandon_on_cancel=True + ) + + async def is_char_device(self) -> bool: + return await to_thread.run_sync( + self._path.is_char_device, abandon_on_cancel=True + ) + + async def is_dir(self) -> bool: + return await to_thread.run_sync(self._path.is_dir, abandon_on_cancel=True) + + async def is_fifo(self) -> bool: + return await to_thread.run_sync(self._path.is_fifo, abandon_on_cancel=True) + + async def is_file(self) -> bool: + return await to_thread.run_sync(self._path.is_file, abandon_on_cancel=True) + + if sys.version_info >= (3, 12): + + async def is_junction(self) -> bool: + return await to_thread.run_sync(self._path.is_junction) + + async def is_mount(self) -> bool: + return await to_thread.run_sync( + os.path.ismount, self._path, abandon_on_cancel=True + ) + + def is_reserved(self) -> bool: + return self._path.is_reserved() + + async def is_socket(self) -> bool: + return await to_thread.run_sync(self._path.is_socket, abandon_on_cancel=True) + + async def is_symlink(self) -> bool: + return await to_thread.run_sync(self._path.is_symlink, abandon_on_cancel=True) + + async def iterdir(self) -> AsyncIterator[Path]: + gen = ( + self._path.iterdir() + if sys.version_info < (3, 13) + else await to_thread.run_sync(self._path.iterdir, abandon_on_cancel=True) + ) + async for path in _PathIterator(gen): + yield path + + def joinpath(self, *args: str | PathLike[str]) -> Path: + return Path(self._path.joinpath(*args)) + + async def lchmod(self, mode: int) -> None: + await to_thread.run_sync(self._path.lchmod, mode) + + async def lstat(self) -> os.stat_result: + return await to_thread.run_sync(self._path.lstat, abandon_on_cancel=True) + + async def mkdir( + self, mode: int = 0o777, parents: bool = False, exist_ok: bool = False + ) -> None: + await to_thread.run_sync(self._path.mkdir, mode, parents, exist_ok) + + @overload + async def open( + self, + mode: OpenBinaryMode, + buffering: int = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., + ) -> AsyncFile[bytes]: ... + + @overload + async def open( + self, + mode: OpenTextMode = ..., + buffering: int = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., + ) -> AsyncFile[str]: ... + + async def open( + self, + mode: str = "r", + buffering: int = -1, + encoding: str | None = None, + errors: str | None = None, + newline: str | None = None, + ) -> AsyncFile[Any]: + fp = await to_thread.run_sync( + self._path.open, mode, buffering, encoding, errors, newline + ) + return AsyncFile(fp) + + async def owner(self) -> str: + return await to_thread.run_sync(self._path.owner, abandon_on_cancel=True) + + async def read_bytes(self) -> bytes: + return await to_thread.run_sync(self._path.read_bytes) + + async def read_text( + self, encoding: str | None = None, errors: str | None = None + ) -> str: + return await to_thread.run_sync(self._path.read_text, encoding, errors) + + if sys.version_info >= (3, 12): + + def relative_to( + self, *other: str | PathLike[str], walk_up: bool = False + ) -> Path: + # relative_to() should work with any PathLike but it doesn't + others = [pathlib.Path(other) for other in other] + return Path(self._path.relative_to(*others, walk_up=walk_up)) + + else: + + def relative_to(self, *other: str | PathLike[str]) -> Path: + return Path(self._path.relative_to(*other)) + + async def readlink(self) -> Path: + target = await to_thread.run_sync(os.readlink, self._path) + return Path(target) + + async def rename(self, target: str | pathlib.PurePath | Path) -> Path: + if isinstance(target, Path): + target = target._path + + await to_thread.run_sync(self._path.rename, target) + return Path(target) + + async def replace(self, target: str | pathlib.PurePath | Path) -> Path: + if isinstance(target, Path): + target = target._path + + await to_thread.run_sync(self._path.replace, target) + return Path(target) + + async def resolve(self, strict: bool = False) -> Path: + func = partial(self._path.resolve, strict=strict) + return Path(await to_thread.run_sync(func, abandon_on_cancel=True)) + + if sys.version_info < (3, 12): + # Pre Python 3.12 + def rglob(self, pattern: str) -> AsyncIterator[Path]: + gen = self._path.rglob(pattern) + return _PathIterator(gen) + elif (3, 12) <= sys.version_info < (3, 13): + # Changed in Python 3.12: + # - The case_sensitive parameter was added. + def rglob( + self, pattern: str, *, case_sensitive: bool | None = None + ) -> AsyncIterator[Path]: + gen = self._path.rglob(pattern, case_sensitive=case_sensitive) + return _PathIterator(gen) + elif sys.version_info >= (3, 13): + # Changed in Python 3.13: + # - The recurse_symlinks parameter was added. + # - The pattern parameter accepts a path-like object. + def rglob( # type: ignore[misc] # mypy doesn't allow for differing signatures in a conditional block + self, + pattern: str | PathLike[str], + *, + case_sensitive: bool | None = None, + recurse_symlinks: bool = False, + ) -> AsyncIterator[Path]: + gen = self._path.rglob( + pattern, # type: ignore[arg-type] + case_sensitive=case_sensitive, + recurse_symlinks=recurse_symlinks, + ) + return _PathIterator(gen) + + async def rmdir(self) -> None: + await to_thread.run_sync(self._path.rmdir) + + async def samefile(self, other_path: str | PathLike[str]) -> bool: + if isinstance(other_path, Path): + other_path = other_path._path + + return await to_thread.run_sync( + self._path.samefile, other_path, abandon_on_cancel=True + ) + + async def stat(self, *, follow_symlinks: bool = True) -> os.stat_result: + func = partial(os.stat, follow_symlinks=follow_symlinks) + return await to_thread.run_sync(func, self._path, abandon_on_cancel=True) + + async def symlink_to( + self, + target: str | bytes | PathLike[str] | PathLike[bytes], + target_is_directory: bool = False, + ) -> None: + if isinstance(target, Path): + target = target._path + + await to_thread.run_sync(self._path.symlink_to, target, target_is_directory) + + async def touch(self, mode: int = 0o666, exist_ok: bool = True) -> None: + await to_thread.run_sync(self._path.touch, mode, exist_ok) + + async def unlink(self, missing_ok: bool = False) -> None: + try: + await to_thread.run_sync(self._path.unlink) + except FileNotFoundError: + if not missing_ok: + raise + + if sys.version_info >= (3, 12): + + async def walk( + self, + top_down: bool = True, + on_error: Callable[[OSError], object] | None = None, + follow_symlinks: bool = False, + ) -> AsyncIterator[tuple[Path, list[str], list[str]]]: + def get_next_value() -> tuple[pathlib.Path, list[str], list[str]] | None: + try: + return next(gen) + except StopIteration: + return None + + gen = self._path.walk(top_down, on_error, follow_symlinks) + while True: + value = await to_thread.run_sync(get_next_value) + if value is None: + return + + root, dirs, paths = value + yield Path(root), dirs, paths + + def with_name(self, name: str) -> Path: + return Path(self._path.with_name(name)) + + def with_stem(self, stem: str) -> Path: + return Path(self._path.with_name(stem + self._path.suffix)) + + def with_suffix(self, suffix: str) -> Path: + return Path(self._path.with_suffix(suffix)) + + def with_segments(self, *pathsegments: str | PathLike[str]) -> Path: + return Path(*pathsegments) + + async def write_bytes(self, data: bytes) -> int: + return await to_thread.run_sync(self._path.write_bytes, data) + + async def write_text( + self, + data: str, + encoding: str | None = None, + errors: str | None = None, + newline: str | None = None, + ) -> int: + # Path.write_text() does not support the "newline" parameter before Python 3.10 + def sync_write_text() -> int: + with self._path.open( + "w", encoding=encoding, errors=errors, newline=newline + ) as fp: + return fp.write(data) + + return await to_thread.run_sync(sync_write_text) + + +PathLike.register(Path) diff --git a/backend/.venv/Lib/site-packages/anyio/_core/_resources.py b/backend/.venv/Lib/site-packages/anyio/_core/_resources.py new file mode 100644 index 0000000..b9a5344 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/_core/_resources.py @@ -0,0 +1,18 @@ +from __future__ import annotations + +from ..abc import AsyncResource +from ._tasks import CancelScope + + +async def aclose_forcefully(resource: AsyncResource) -> None: + """ + Close an asynchronous resource in a cancelled scope. + + Doing this closes the resource without waiting on anything. + + :param resource: the resource to close + + """ + with CancelScope() as scope: + scope.cancel() + await resource.aclose() diff --git a/backend/.venv/Lib/site-packages/anyio/_core/_signals.py b/backend/.venv/Lib/site-packages/anyio/_core/_signals.py new file mode 100644 index 0000000..f3451d3 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/_core/_signals.py @@ -0,0 +1,27 @@ +from __future__ import annotations + +from collections.abc import AsyncIterator +from contextlib import AbstractContextManager +from signal import Signals + +from ._eventloop import get_async_backend + + +def open_signal_receiver( + *signals: Signals, +) -> AbstractContextManager[AsyncIterator[Signals]]: + """ + Start receiving operating system signals. + + :param signals: signals to receive (e.g. ``signal.SIGINT``) + :return: an asynchronous context manager for an asynchronous iterator which yields + signal numbers + + .. warning:: Windows does not support signals natively so it is best to avoid + relying on this in cross-platform applications. + + .. warning:: On asyncio, this permanently replaces any previous signal handler for + the given signals, as set via :meth:`~asyncio.loop.add_signal_handler`. + + """ + return get_async_backend().open_signal_receiver(*signals) diff --git a/backend/.venv/Lib/site-packages/anyio/_core/_sockets.py b/backend/.venv/Lib/site-packages/anyio/_core/_sockets.py new file mode 100644 index 0000000..c65508f --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/_core/_sockets.py @@ -0,0 +1,991 @@ +from __future__ import annotations + +import errno +import os +import socket +import ssl +import stat +import sys +from collections.abc import Awaitable +from dataclasses import dataclass +from ipaddress import IPv4Address, IPv6Address, ip_address +from os import PathLike, chmod +from socket import AddressFamily, SocketKind +from typing import TYPE_CHECKING, Any, Literal, cast, overload + +from .. import ConnectionFailed, to_thread +from ..abc import ( + ByteStreamConnectable, + ConnectedUDPSocket, + ConnectedUNIXDatagramSocket, + IPAddressType, + IPSockAddrType, + SocketListener, + SocketStream, + UDPSocket, + UNIXDatagramSocket, + UNIXSocketStream, +) +from ..streams.stapled import MultiListener +from ..streams.tls import TLSConnectable, TLSStream +from ._eventloop import get_async_backend +from ._resources import aclose_forcefully +from ._synchronization import Event +from ._tasks import create_task_group, move_on_after + +if TYPE_CHECKING: + from _typeshed import FileDescriptorLike +else: + FileDescriptorLike = object + +if sys.version_info < (3, 11): + from exceptiongroup import ExceptionGroup + +if sys.version_info >= (3, 12): + from typing import override +else: + from typing_extensions import override + +if sys.version_info < (3, 13): + from typing_extensions import deprecated +else: + from warnings import deprecated + +IPPROTO_IPV6 = getattr(socket, "IPPROTO_IPV6", 41) # https://bugs.python.org/issue29515 + +AnyIPAddressFamily = Literal[ + AddressFamily.AF_UNSPEC, AddressFamily.AF_INET, AddressFamily.AF_INET6 +] +IPAddressFamily = Literal[AddressFamily.AF_INET, AddressFamily.AF_INET6] + + +# tls_hostname given +@overload +async def connect_tcp( + remote_host: IPAddressType, + remote_port: int, + *, + local_host: IPAddressType | None = ..., + ssl_context: ssl.SSLContext | None = ..., + tls_standard_compatible: bool = ..., + tls_hostname: str, + happy_eyeballs_delay: float = ..., +) -> TLSStream: ... + + +# ssl_context given +@overload +async def connect_tcp( + remote_host: IPAddressType, + remote_port: int, + *, + local_host: IPAddressType | None = ..., + ssl_context: ssl.SSLContext, + tls_standard_compatible: bool = ..., + tls_hostname: str | None = ..., + happy_eyeballs_delay: float = ..., +) -> TLSStream: ... + + +# tls=True +@overload +async def connect_tcp( + remote_host: IPAddressType, + remote_port: int, + *, + local_host: IPAddressType | None = ..., + tls: Literal[True], + ssl_context: ssl.SSLContext | None = ..., + tls_standard_compatible: bool = ..., + tls_hostname: str | None = ..., + happy_eyeballs_delay: float = ..., +) -> TLSStream: ... + + +# tls=False +@overload +async def connect_tcp( + remote_host: IPAddressType, + remote_port: int, + *, + local_host: IPAddressType | None = ..., + tls: Literal[False], + ssl_context: ssl.SSLContext | None = ..., + tls_standard_compatible: bool = ..., + tls_hostname: str | None = ..., + happy_eyeballs_delay: float = ..., +) -> SocketStream: ... + + +# No TLS arguments +@overload +async def connect_tcp( + remote_host: IPAddressType, + remote_port: int, + *, + local_host: IPAddressType | None = ..., + happy_eyeballs_delay: float = ..., +) -> SocketStream: ... + + +async def connect_tcp( + remote_host: IPAddressType, + remote_port: int, + *, + local_host: IPAddressType | None = None, + tls: bool = False, + ssl_context: ssl.SSLContext | None = None, + tls_standard_compatible: bool = True, + tls_hostname: str | None = None, + happy_eyeballs_delay: float = 0.25, +) -> SocketStream | TLSStream: + """ + Connect to a host using the TCP protocol. + + This function implements the stateless version of the Happy Eyeballs algorithm (RFC + 6555). If ``remote_host`` is a host name that resolves to multiple IP addresses, + each one is tried until one connection attempt succeeds. If the first attempt does + not connected within 250 milliseconds, a second attempt is started using the next + address in the list, and so on. On IPv6 enabled systems, an IPv6 address (if + available) is tried first. + + When the connection has been established, a TLS handshake will be done if either + ``ssl_context`` or ``tls_hostname`` is not ``None``, or if ``tls`` is ``True``. + + :param remote_host: the IP address or host name to connect to + :param remote_port: port on the target host to connect to + :param local_host: the interface address or name to bind the socket to before + connecting + :param tls: ``True`` to do a TLS handshake with the connected stream and return a + :class:`~anyio.streams.tls.TLSStream` instead + :param ssl_context: the SSL context object to use (if omitted, a default context is + created) + :param tls_standard_compatible: If ``True``, performs the TLS shutdown handshake + before closing the stream and requires that the server does this as well. + Otherwise, :exc:`~ssl.SSLEOFError` may be raised during reads from the stream. + Some protocols, such as HTTP, require this option to be ``False``. + See :meth:`~ssl.SSLContext.wrap_socket` for details. + :param tls_hostname: host name to check the server certificate against (defaults to + the value of ``remote_host``) + :param happy_eyeballs_delay: delay (in seconds) before starting the next connection + attempt + :return: a socket stream object if no TLS handshake was done, otherwise a TLS stream + :raises ConnectionFailed: if the connection fails + + """ + # Placed here due to https://github.com/python/mypy/issues/7057 + connected_stream: SocketStream | None = None + + async def try_connect(remote_host: str, event: Event) -> None: + nonlocal connected_stream + try: + stream = await asynclib.connect_tcp(remote_host, remote_port, local_address) + except OSError as exc: + oserrors.append(exc) + return + else: + if connected_stream is None: + connected_stream = stream + tg.cancel_scope.cancel() + else: + await stream.aclose() + finally: + event.set() + + asynclib = get_async_backend() + local_address: IPSockAddrType | None = None + family = socket.AF_UNSPEC + if local_host: + gai_res = await getaddrinfo(str(local_host), None) + family, *_, local_address = gai_res[0] + + target_host = str(remote_host) + try: + addr_obj = ip_address(remote_host) + except ValueError: + addr_obj = None + + if addr_obj is not None: + if isinstance(addr_obj, IPv6Address): + target_addrs = [(socket.AF_INET6, addr_obj.compressed)] + else: + target_addrs = [(socket.AF_INET, addr_obj.compressed)] + else: + # getaddrinfo() will raise an exception if name resolution fails + gai_res = await getaddrinfo( + target_host, remote_port, family=family, type=socket.SOCK_STREAM + ) + + # Organize the list so that the first address is an IPv6 address (if available) + # and the second one is an IPv4 addresses. The rest can be in whatever order. + v6_found = v4_found = False + target_addrs = [] + for af, *_, sa in gai_res: + if af == socket.AF_INET6 and not v6_found: + v6_found = True + target_addrs.insert(0, (af, sa[0])) + elif af == socket.AF_INET and not v4_found and v6_found: + v4_found = True + target_addrs.insert(1, (af, sa[0])) + else: + target_addrs.append((af, sa[0])) + + oserrors: list[OSError] = [] + try: + async with create_task_group() as tg: + for _af, addr in target_addrs: + event = Event() + tg.start_soon(try_connect, addr, event) + with move_on_after(happy_eyeballs_delay): + await event.wait() + + if connected_stream is None: + cause = ( + oserrors[0] + if len(oserrors) == 1 + else ExceptionGroup("multiple connection attempts failed", oserrors) + ) + raise OSError("All connection attempts failed") from cause + finally: + oserrors.clear() + + if tls or tls_hostname or ssl_context: + try: + return await TLSStream.wrap( + connected_stream, + server_side=False, + hostname=tls_hostname or str(remote_host), + ssl_context=ssl_context, + standard_compatible=tls_standard_compatible, + ) + except BaseException: + await aclose_forcefully(connected_stream) + raise + + return connected_stream + + +async def connect_unix(path: str | bytes | PathLike[Any]) -> UNIXSocketStream: + """ + Connect to the given UNIX socket. + + Not available on Windows. + + :param path: path to the socket + :return: a socket stream object + :raises ConnectionFailed: if the connection fails + + """ + path = os.fspath(path) + return await get_async_backend().connect_unix(path) + + +async def create_tcp_listener( + *, + local_host: IPAddressType | None = None, + local_port: int = 0, + family: AnyIPAddressFamily = socket.AddressFamily.AF_UNSPEC, + backlog: int = 65536, + reuse_port: bool = False, +) -> MultiListener[SocketStream]: + """ + Create a TCP socket listener. + + :param local_port: port number to listen on + :param local_host: IP address of the interface to listen on. If omitted, listen on + all IPv4 and IPv6 interfaces. To listen on all interfaces on a specific address + family, use ``0.0.0.0`` for IPv4 or ``::`` for IPv6. + :param family: address family (used if ``local_host`` was omitted) + :param backlog: maximum number of queued incoming connections (up to a maximum of + 2**16, or 65536) + :param reuse_port: ``True`` to allow multiple sockets to bind to the same + address/port (not supported on Windows) + :return: a multi-listener object containing one or more socket listeners + :raises OSError: if there's an error creating a socket, or binding to one or more + interfaces failed + + """ + asynclib = get_async_backend() + backlog = min(backlog, 65536) + local_host = str(local_host) if local_host is not None else None + + def setup_raw_socket( + fam: AddressFamily, + bind_addr: tuple[str, int] | tuple[str, int, int, int], + *, + v6only: bool = True, + ) -> socket.socket: + sock = socket.socket(fam) + try: + sock.setblocking(False) + + if fam == AddressFamily.AF_INET6: + sock.setsockopt(IPPROTO_IPV6, socket.IPV6_V6ONLY, v6only) + + # For Windows, enable exclusive address use. For others, enable address + # reuse. + if sys.platform == "win32": + sock.setsockopt(socket.SOL_SOCKET, socket.SO_EXCLUSIVEADDRUSE, 1) + else: + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + + if reuse_port: + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) + + # Workaround for #554 + if fam == socket.AF_INET6 and "%" in bind_addr[0]: + addr, scope_id = bind_addr[0].split("%", 1) + bind_addr = (addr, bind_addr[1], 0, int(scope_id)) + + sock.bind(bind_addr) + sock.listen(backlog) + except BaseException: + sock.close() + raise + + return sock + + # We passing type=0 on non-Windows platforms as a workaround for a uvloop bug + # where we don't get the correct scope ID for IPv6 link-local addresses when passing + # type=socket.SOCK_STREAM to getaddrinfo(): + # https://github.com/MagicStack/uvloop/issues/539 + gai_res = await getaddrinfo( + local_host, + local_port, + family=family, + type=socket.SOCK_STREAM if sys.platform == "win32" else 0, + flags=socket.AI_PASSIVE | socket.AI_ADDRCONFIG, + ) + + # The set comprehension is here to work around a glibc bug: + # https://sourceware.org/bugzilla/show_bug.cgi?id=14969 + sockaddrs = sorted({res for res in gai_res if res[1] == SocketKind.SOCK_STREAM}) + + # Special case for dual-stack binding on the "any" interface + if ( + local_host is None + and family == AddressFamily.AF_UNSPEC + and socket.has_dualstack_ipv6() + and any(fam == AddressFamily.AF_INET6 for fam, *_ in gai_res) + ): + raw_socket = setup_raw_socket( + AddressFamily.AF_INET6, ("::", local_port), v6only=False + ) + listener = asynclib.create_tcp_listener(raw_socket) + return MultiListener([listener]) + + errors: list[OSError] = [] + try: + for _ in range(len(sockaddrs)): + listeners: list[SocketListener] = [] + bound_ephemeral_port = local_port + try: + for fam, *_, sockaddr in sockaddrs: + sockaddr = sockaddr[0], bound_ephemeral_port, *sockaddr[2:] + raw_socket = setup_raw_socket(fam, sockaddr) + + # Store the assigned port if an ephemeral port was requested, so + # we'll bind to the same port on all interfaces + if local_port == 0 and len(gai_res) > 1: + bound_ephemeral_port = raw_socket.getsockname()[1] + + listeners.append(asynclib.create_tcp_listener(raw_socket)) + except BaseException as exc: + for listener in listeners: + await listener.aclose() + + # If an ephemeral port was requested but binding the assigned port + # failed for another interface, rotate the address list and try again + if ( + isinstance(exc, OSError) + and exc.errno == errno.EADDRINUSE + and local_port == 0 + and bound_ephemeral_port + ): + errors.append(exc) + sockaddrs.append(sockaddrs.pop(0)) + continue + + raise + + return MultiListener(listeners) + + raise OSError( + f"Could not create {len(sockaddrs)} listeners with a consistent port" + ) from ExceptionGroup("Several bind attempts failed", errors) + finally: + del errors # Prevent reference cycles + + +async def create_unix_listener( + path: str | bytes | PathLike[Any], + *, + mode: int | None = None, + backlog: int = 65536, +) -> SocketListener: + """ + Create a UNIX socket listener. + + Not available on Windows. + + :param path: path of the socket + :param mode: permissions to set on the socket + :param backlog: maximum number of queued incoming connections (up to a maximum of + 2**16, or 65536) + :return: a listener object + + .. versionchanged:: 3.0 + If a socket already exists on the file system in the given path, it will be + removed first. + + """ + backlog = min(backlog, 65536) + raw_socket = await setup_unix_local_socket(path, mode, socket.SOCK_STREAM) + try: + raw_socket.listen(backlog) + return get_async_backend().create_unix_listener(raw_socket) + except BaseException: + raw_socket.close() + raise + + +async def create_udp_socket( + family: AnyIPAddressFamily = AddressFamily.AF_UNSPEC, + *, + local_host: IPAddressType | None = None, + local_port: int = 0, + reuse_port: bool = False, +) -> UDPSocket: + """ + Create a UDP socket. + + If ``port`` has been given, the socket will be bound to this port on the local + machine, making this socket suitable for providing UDP based services. + + :param family: address family (``AF_INET`` or ``AF_INET6``) – automatically + determined from ``local_host`` if omitted + :param local_host: IP address or host name of the local interface to bind to + :param local_port: local port to bind to + :param reuse_port: ``True`` to allow multiple sockets to bind to the same + address/port (not supported on Windows) + :return: a UDP socket + + """ + if family is AddressFamily.AF_UNSPEC and not local_host: + raise ValueError('Either "family" or "local_host" must be given') + + if local_host: + gai_res = await getaddrinfo( + str(local_host), + local_port, + family=family, + type=socket.SOCK_DGRAM, + flags=socket.AI_PASSIVE | socket.AI_ADDRCONFIG, + ) + family = cast(AnyIPAddressFamily, gai_res[0][0]) + local_address = gai_res[0][-1] + elif family is AddressFamily.AF_INET6: + local_address = ("::", 0) + else: + local_address = ("0.0.0.0", 0) + + sock = await get_async_backend().create_udp_socket( + family, local_address, None, reuse_port + ) + return cast(UDPSocket, sock) + + +async def create_connected_udp_socket( + remote_host: IPAddressType, + remote_port: int, + *, + family: AnyIPAddressFamily = AddressFamily.AF_UNSPEC, + local_host: IPAddressType | None = None, + local_port: int = 0, + reuse_port: bool = False, +) -> ConnectedUDPSocket: + """ + Create a connected UDP socket. + + Connected UDP sockets can only communicate with the specified remote host/port, an + any packets sent from other sources are dropped. + + :param remote_host: remote host to set as the default target + :param remote_port: port on the remote host to set as the default target + :param family: address family (``AF_INET`` or ``AF_INET6``) – automatically + determined from ``local_host`` or ``remote_host`` if omitted + :param local_host: IP address or host name of the local interface to bind to + :param local_port: local port to bind to + :param reuse_port: ``True`` to allow multiple sockets to bind to the same + address/port (not supported on Windows) + :return: a connected UDP socket + + """ + local_address = None + if local_host: + gai_res = await getaddrinfo( + str(local_host), + local_port, + family=family, + type=socket.SOCK_DGRAM, + flags=socket.AI_PASSIVE | socket.AI_ADDRCONFIG, + ) + family = cast(AnyIPAddressFamily, gai_res[0][0]) + local_address = gai_res[0][-1] + + gai_res = await getaddrinfo( + str(remote_host), remote_port, family=family, type=socket.SOCK_DGRAM + ) + family = cast(AnyIPAddressFamily, gai_res[0][0]) + remote_address = gai_res[0][-1] + + sock = await get_async_backend().create_udp_socket( + family, local_address, remote_address, reuse_port + ) + return cast(ConnectedUDPSocket, sock) + + +async def create_unix_datagram_socket( + *, + local_path: None | str | bytes | PathLike[Any] = None, + local_mode: int | None = None, +) -> UNIXDatagramSocket: + """ + Create a UNIX datagram socket. + + Not available on Windows. + + If ``local_path`` has been given, the socket will be bound to this path, making this + socket suitable for receiving datagrams from other processes. Other processes can + send datagrams to this socket only if ``local_path`` is set. + + If a socket already exists on the file system in the ``local_path``, it will be + removed first. + + :param local_path: the path on which to bind to + :param local_mode: permissions to set on the local socket + :return: a UNIX datagram socket + + """ + raw_socket = await setup_unix_local_socket( + local_path, local_mode, socket.SOCK_DGRAM + ) + return await get_async_backend().create_unix_datagram_socket(raw_socket, None) + + +async def create_connected_unix_datagram_socket( + remote_path: str | bytes | PathLike[Any], + *, + local_path: None | str | bytes | PathLike[Any] = None, + local_mode: int | None = None, +) -> ConnectedUNIXDatagramSocket: + """ + Create a connected UNIX datagram socket. + + Connected datagram sockets can only communicate with the specified remote path. + + If ``local_path`` has been given, the socket will be bound to this path, making + this socket suitable for receiving datagrams from other processes. Other processes + can send datagrams to this socket only if ``local_path`` is set. + + If a socket already exists on the file system in the ``local_path``, it will be + removed first. + + :param remote_path: the path to set as the default target + :param local_path: the path on which to bind to + :param local_mode: permissions to set on the local socket + :return: a connected UNIX datagram socket + + """ + remote_path = os.fspath(remote_path) + raw_socket = await setup_unix_local_socket( + local_path, local_mode, socket.SOCK_DGRAM + ) + return await get_async_backend().create_unix_datagram_socket( + raw_socket, remote_path + ) + + +async def getaddrinfo( + host: bytes | str | None, + port: str | int | None, + *, + family: int | AddressFamily = 0, + type: int | SocketKind = 0, + proto: int = 0, + flags: int = 0, +) -> list[tuple[AddressFamily, SocketKind, int, str, tuple[str, int]]]: + """ + Look up a numeric IP address given a host name. + + Internationalized domain names are translated according to the (non-transitional) + IDNA 2008 standard. + + .. note:: 4-tuple IPv6 socket addresses are automatically converted to 2-tuples of + (host, port), unlike what :func:`socket.getaddrinfo` does. + + :param host: host name + :param port: port number + :param family: socket family (`'AF_INET``, ...) + :param type: socket type (``SOCK_STREAM``, ...) + :param proto: protocol number + :param flags: flags to pass to upstream ``getaddrinfo()`` + :return: list of tuples containing (family, type, proto, canonname, sockaddr) + + .. seealso:: :func:`socket.getaddrinfo` + + """ + # Handle unicode hostnames + if isinstance(host, str): + try: + encoded_host: bytes | None = host.encode("ascii") + except UnicodeEncodeError: + import idna + + encoded_host = idna.encode(host, uts46=True) + else: + encoded_host = host + + gai_res = await get_async_backend().getaddrinfo( + encoded_host, port, family=family, type=type, proto=proto, flags=flags + ) + return [ + (family, type, proto, canonname, convert_ipv6_sockaddr(sockaddr)) + for family, type, proto, canonname, sockaddr in gai_res + # filter out IPv6 results when IPv6 is disabled + if not isinstance(sockaddr[0], int) + ] + + +def getnameinfo(sockaddr: IPSockAddrType, flags: int = 0) -> Awaitable[tuple[str, str]]: + """ + Look up the host name of an IP address. + + :param sockaddr: socket address (e.g. (ipaddress, port) for IPv4) + :param flags: flags to pass to upstream ``getnameinfo()`` + :return: a tuple of (host name, service name) + + .. seealso:: :func:`socket.getnameinfo` + + """ + return get_async_backend().getnameinfo(sockaddr, flags) + + +@deprecated("This function is deprecated; use `wait_readable` instead") +def wait_socket_readable(sock: socket.socket) -> Awaitable[None]: + """ + .. deprecated:: 4.7.0 + Use :func:`wait_readable` instead. + + Wait until the given socket has data to be read. + + .. warning:: Only use this on raw sockets that have not been wrapped by any higher + level constructs like socket streams! + + :param sock: a socket object + :raises ~anyio.ClosedResourceError: if the socket was closed while waiting for the + socket to become readable + :raises ~anyio.BusyResourceError: if another task is already waiting for the socket + to become readable + + """ + return get_async_backend().wait_readable(sock.fileno()) + + +@deprecated("This function is deprecated; use `wait_writable` instead") +def wait_socket_writable(sock: socket.socket) -> Awaitable[None]: + """ + .. deprecated:: 4.7.0 + Use :func:`wait_writable` instead. + + Wait until the given socket can be written to. + + This does **NOT** work on Windows when using the asyncio backend with a proactor + event loop (default on py3.8+). + + .. warning:: Only use this on raw sockets that have not been wrapped by any higher + level constructs like socket streams! + + :param sock: a socket object + :raises ~anyio.ClosedResourceError: if the socket was closed while waiting for the + socket to become writable + :raises ~anyio.BusyResourceError: if another task is already waiting for the socket + to become writable + + """ + return get_async_backend().wait_writable(sock.fileno()) + + +def wait_readable(obj: FileDescriptorLike) -> Awaitable[None]: + """ + Wait until the given object has data to be read. + + On Unix systems, ``obj`` must either be an integer file descriptor, or else an + object with a ``.fileno()`` method which returns an integer file descriptor. Any + kind of file descriptor can be passed, though the exact semantics will depend on + your kernel. For example, this probably won't do anything useful for on-disk files. + + On Windows systems, ``obj`` must either be an integer ``SOCKET`` handle, or else an + object with a ``.fileno()`` method which returns an integer ``SOCKET`` handle. File + descriptors aren't supported, and neither are handles that refer to anything besides + a ``SOCKET``. + + On backends where this functionality is not natively provided (asyncio + ``ProactorEventLoop`` on Windows), it is provided using a separate selector thread + which is set to shut down when the interpreter shuts down. + + .. warning:: Don't use this on raw sockets that have been wrapped by any higher + level constructs like socket streams! + + :param obj: an object with a ``.fileno()`` method or an integer handle + :raises ~anyio.ClosedResourceError: if the object was closed while waiting for the + object to become readable + :raises ~anyio.BusyResourceError: if another task is already waiting for the object + to become readable + + """ + return get_async_backend().wait_readable(obj) + + +def wait_writable(obj: FileDescriptorLike) -> Awaitable[None]: + """ + Wait until the given object can be written to. + + :param obj: an object with a ``.fileno()`` method or an integer handle + :raises ~anyio.ClosedResourceError: if the object was closed while waiting for the + object to become writable + :raises ~anyio.BusyResourceError: if another task is already waiting for the object + to become writable + + .. seealso:: See the documentation of :func:`wait_readable` for the definition of + ``obj`` and notes on backend compatibility. + + .. warning:: Don't use this on raw sockets that have been wrapped by any higher + level constructs like socket streams! + + """ + return get_async_backend().wait_writable(obj) + + +def notify_closing(obj: FileDescriptorLike) -> None: + """ + Call this before closing a file descriptor (on Unix) or socket (on + Windows). This will cause any `wait_readable` or `wait_writable` + calls on the given object to immediately wake up and raise + `~anyio.ClosedResourceError`. + + This doesn't actually close the object – you still have to do that + yourself afterwards. Also, you want to be careful to make sure no + new tasks start waiting on the object in between when you call this + and when it's actually closed. So to close something properly, you + usually want to do these steps in order: + + 1. Explicitly mark the object as closed, so that any new attempts + to use it will abort before they start. + 2. Call `notify_closing` to wake up any already-existing users. + 3. Actually close the object. + + It's also possible to do them in a different order if that's more + convenient, *but only if* you make sure not to have any checkpoints in + between the steps. This way they all happen in a single atomic + step, so other tasks won't be able to tell what order they happened + in anyway. + + :param obj: an object with a ``.fileno()`` method or an integer handle + + """ + get_async_backend().notify_closing(obj) + + +# +# Private API +# + + +def convert_ipv6_sockaddr( + sockaddr: tuple[str, int, int, int] | tuple[str, int], +) -> tuple[str, int]: + """ + Convert a 4-tuple IPv6 socket address to a 2-tuple (address, port) format. + + If the scope ID is nonzero, it is added to the address, separated with ``%``. + Otherwise the flow id and scope id are simply cut off from the tuple. + Any other kinds of socket addresses are returned as-is. + + :param sockaddr: the result of :meth:`~socket.socket.getsockname` + :return: the converted socket address + + """ + # This is more complicated than it should be because of MyPy + if isinstance(sockaddr, tuple) and len(sockaddr) == 4: + host, port, flowinfo, scope_id = sockaddr + if scope_id: + # PyPy (as of v7.3.11) leaves the interface name in the result, so + # we discard it and only get the scope ID from the end + # (https://foss.heptapod.net/pypy/pypy/-/issues/3938) + host = host.split("%")[0] + + # Add scope_id to the address + return f"{host}%{scope_id}", port + else: + return host, port + else: + return sockaddr + + +async def setup_unix_local_socket( + path: None | str | bytes | PathLike[Any], + mode: int | None, + socktype: int, +) -> socket.socket: + """ + Create a UNIX local socket object, deleting the socket at the given path if it + exists. + + Not available on Windows. + + :param path: path of the socket + :param mode: permissions to set on the socket + :param socktype: socket.SOCK_STREAM or socket.SOCK_DGRAM + + """ + path_str: str | None + if path is not None: + path_str = os.fsdecode(path) + + # Linux abstract namespace sockets aren't backed by a concrete file so skip stat call + if not path_str.startswith("\0"): + # Copied from pathlib... + try: + stat_result = os.stat(path) + except OSError as e: + if e.errno not in ( + errno.ENOENT, + errno.ENOTDIR, + errno.EBADF, + errno.ELOOP, + ): + raise + else: + if stat.S_ISSOCK(stat_result.st_mode): + os.unlink(path) + else: + path_str = None + + raw_socket = socket.socket(socket.AF_UNIX, socktype) + raw_socket.setblocking(False) + + if path_str is not None: + try: + await to_thread.run_sync(raw_socket.bind, path_str, abandon_on_cancel=True) + if mode is not None: + await to_thread.run_sync(chmod, path_str, mode, abandon_on_cancel=True) + except BaseException: + raw_socket.close() + raise + + return raw_socket + + +@dataclass +class TCPConnectable(ByteStreamConnectable): + """ + Connects to a TCP server at the given host and port. + + :param host: host name or IP address of the server + :param port: TCP port number of the server + """ + + host: str | IPv4Address | IPv6Address + port: int + + def __post_init__(self) -> None: + if self.port < 1 or self.port > 65535: + raise ValueError("TCP port number out of range") + + @override + async def connect(self) -> SocketStream: + try: + return await connect_tcp(self.host, self.port) + except OSError as exc: + raise ConnectionFailed( + f"error connecting to {self.host}:{self.port}: {exc}" + ) from exc + + +@dataclass +class UNIXConnectable(ByteStreamConnectable): + """ + Connects to a UNIX domain socket at the given path. + + :param path: the file system path of the socket + """ + + path: str | bytes | PathLike[str] | PathLike[bytes] + + @override + async def connect(self) -> UNIXSocketStream: + try: + return await connect_unix(self.path) + except OSError as exc: + raise ConnectionFailed(f"error connecting to {self.path!r}: {exc}") from exc + + +def as_connectable( + remote: ByteStreamConnectable + | tuple[str | IPv4Address | IPv6Address, int] + | str + | bytes + | PathLike[str], + /, + *, + tls: bool = False, + ssl_context: ssl.SSLContext | None = None, + tls_hostname: str | None = None, + tls_standard_compatible: bool = True, +) -> ByteStreamConnectable: + """ + Return a byte stream connectable from the given object. + + If a bytestream connectable is given, it is returned unchanged. + If a tuple of (host, port) is given, a TCP connectable is returned. + If a string or bytes path is given, a UNIX connectable is returned. + + If ``tls=True``, the connectable will be wrapped in a + :class:`~.streams.tls.TLSConnectable`. + + :param remote: a connectable, a tuple of (host, port) or a path to a UNIX socket + :param tls: if ``True``, wrap the plaintext connectable in a + :class:`~.streams.tls.TLSConnectable`, using the provided TLS settings) + :param ssl_context: if ``tls=True``, the SSLContext object to use (if not provided, + a secure default will be created) + :param tls_hostname: if ``tls=True``, host name of the server to use for checking + the server certificate (defaults to the host portion of the address for TCP + connectables) + :param tls_standard_compatible: if ``False`` and ``tls=True``, makes the TLS stream + skip the closing handshake when closing the connection, so it won't raise an + exception if the server does the same + + """ + connectable: TCPConnectable | UNIXConnectable | TLSConnectable + if isinstance(remote, ByteStreamConnectable): + return remote + elif isinstance(remote, tuple) and len(remote) == 2: + connectable = TCPConnectable(*remote) + elif isinstance(remote, (str, bytes, PathLike)): + connectable = UNIXConnectable(remote) + else: + raise TypeError(f"cannot convert {remote!r} to a connectable") + + if tls: + if not tls_hostname and isinstance(connectable, TCPConnectable): + tls_hostname = str(connectable.host) + + connectable = TLSConnectable( + connectable, + ssl_context=ssl_context, + hostname=tls_hostname, + standard_compatible=tls_standard_compatible, + ) + + return connectable diff --git a/backend/.venv/Lib/site-packages/anyio/_core/_streams.py b/backend/.venv/Lib/site-packages/anyio/_core/_streams.py new file mode 100644 index 0000000..2b9c7df --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/_core/_streams.py @@ -0,0 +1,52 @@ +from __future__ import annotations + +import math +from typing import TypeVar +from warnings import warn + +from ..streams.memory import ( + MemoryObjectReceiveStream, + MemoryObjectSendStream, + _MemoryObjectStreamState, +) + +T_Item = TypeVar("T_Item") + + +class create_memory_object_stream( + tuple[MemoryObjectSendStream[T_Item], MemoryObjectReceiveStream[T_Item]], +): + """ + Create a memory object stream. + + The stream's item type can be annotated like + :func:`create_memory_object_stream[T_Item]`. + + :param max_buffer_size: number of items held in the buffer until ``send()`` starts + blocking + :param item_type: old way of marking the streams with the right generic type for + static typing (does nothing on AnyIO 4) + + .. deprecated:: 4.0 + Use ``create_memory_object_stream[YourItemType](...)`` instead. + :return: a tuple of (send stream, receive stream) + + """ + + def __new__( # type: ignore[misc] + cls, max_buffer_size: float = 0, item_type: object = None + ) -> tuple[MemoryObjectSendStream[T_Item], MemoryObjectReceiveStream[T_Item]]: + if max_buffer_size != math.inf and not isinstance(max_buffer_size, int): + raise ValueError("max_buffer_size must be either an integer or math.inf") + if max_buffer_size < 0: + raise ValueError("max_buffer_size cannot be negative") + if item_type is not None: + warn( + "The item_type argument has been deprecated in AnyIO 4.0. " + "Use create_memory_object_stream[YourItemType](...) instead.", + DeprecationWarning, + stacklevel=2, + ) + + state = _MemoryObjectStreamState[T_Item](max_buffer_size) + return (MemoryObjectSendStream(state), MemoryObjectReceiveStream(state)) diff --git a/backend/.venv/Lib/site-packages/anyio/_core/_subprocesses.py b/backend/.venv/Lib/site-packages/anyio/_core/_subprocesses.py new file mode 100644 index 0000000..36d9b30 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/_core/_subprocesses.py @@ -0,0 +1,202 @@ +from __future__ import annotations + +import sys +from collections.abc import AsyncIterable, Iterable, Mapping, Sequence +from io import BytesIO +from os import PathLike +from subprocess import PIPE, CalledProcessError, CompletedProcess +from typing import IO, Any, Union, cast + +from ..abc import Process +from ._eventloop import get_async_backend +from ._tasks import create_task_group + +if sys.version_info >= (3, 10): + from typing import TypeAlias +else: + from typing_extensions import TypeAlias + +StrOrBytesPath: TypeAlias = Union[str, bytes, "PathLike[str]", "PathLike[bytes]"] + + +async def run_process( + command: StrOrBytesPath | Sequence[StrOrBytesPath], + *, + input: bytes | None = None, + stdin: int | IO[Any] | None = None, + stdout: int | IO[Any] | None = PIPE, + stderr: int | IO[Any] | None = PIPE, + check: bool = True, + cwd: StrOrBytesPath | None = None, + env: Mapping[str, str] | None = None, + startupinfo: Any = None, + creationflags: int = 0, + start_new_session: bool = False, + pass_fds: Sequence[int] = (), + user: str | int | None = None, + group: str | int | None = None, + extra_groups: Iterable[str | int] | None = None, + umask: int = -1, +) -> CompletedProcess[bytes]: + """ + Run an external command in a subprocess and wait until it completes. + + .. seealso:: :func:`subprocess.run` + + :param command: either a string to pass to the shell, or an iterable of strings + containing the executable name or path and its arguments + :param input: bytes passed to the standard input of the subprocess + :param stdin: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, + a file-like object, or `None`; ``input`` overrides this + :param stdout: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, + a file-like object, or `None` + :param stderr: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, + :data:`subprocess.STDOUT`, a file-like object, or `None` + :param check: if ``True``, raise :exc:`~subprocess.CalledProcessError` if the + process terminates with a return code other than 0 + :param cwd: If not ``None``, change the working directory to this before running the + command + :param env: if not ``None``, this mapping replaces the inherited environment + variables from the parent process + :param startupinfo: an instance of :class:`subprocess.STARTUPINFO` that can be used + to specify process startup parameters (Windows only) + :param creationflags: flags that can be used to control the creation of the + subprocess (see :class:`subprocess.Popen` for the specifics) + :param start_new_session: if ``true`` the setsid() system call will be made in the + child process prior to the execution of the subprocess. (POSIX only) + :param pass_fds: sequence of file descriptors to keep open between the parent and + child processes. (POSIX only) + :param user: effective user to run the process as (Python >= 3.9, POSIX only) + :param group: effective group to run the process as (Python >= 3.9, POSIX only) + :param extra_groups: supplementary groups to set in the subprocess (Python >= 3.9, + POSIX only) + :param umask: if not negative, this umask is applied in the child process before + running the given command (Python >= 3.9, POSIX only) + :return: an object representing the completed process + :raises ~subprocess.CalledProcessError: if ``check`` is ``True`` and the process + exits with a nonzero return code + + """ + + async def drain_stream(stream: AsyncIterable[bytes], index: int) -> None: + buffer = BytesIO() + async for chunk in stream: + buffer.write(chunk) + + stream_contents[index] = buffer.getvalue() + + if stdin is not None and input is not None: + raise ValueError("only one of stdin and input is allowed") + + async with await open_process( + command, + stdin=PIPE if input else stdin, + stdout=stdout, + stderr=stderr, + cwd=cwd, + env=env, + startupinfo=startupinfo, + creationflags=creationflags, + start_new_session=start_new_session, + pass_fds=pass_fds, + user=user, + group=group, + extra_groups=extra_groups, + umask=umask, + ) as process: + stream_contents: list[bytes | None] = [None, None] + async with create_task_group() as tg: + if process.stdout: + tg.start_soon(drain_stream, process.stdout, 0) + + if process.stderr: + tg.start_soon(drain_stream, process.stderr, 1) + + if process.stdin and input: + await process.stdin.send(input) + await process.stdin.aclose() + + await process.wait() + + output, errors = stream_contents + if check and process.returncode != 0: + raise CalledProcessError(cast(int, process.returncode), command, output, errors) + + return CompletedProcess(command, cast(int, process.returncode), output, errors) + + +async def open_process( + command: StrOrBytesPath | Sequence[StrOrBytesPath], + *, + stdin: int | IO[Any] | None = PIPE, + stdout: int | IO[Any] | None = PIPE, + stderr: int | IO[Any] | None = PIPE, + cwd: StrOrBytesPath | None = None, + env: Mapping[str, str] | None = None, + startupinfo: Any = None, + creationflags: int = 0, + start_new_session: bool = False, + pass_fds: Sequence[int] = (), + user: str | int | None = None, + group: str | int | None = None, + extra_groups: Iterable[str | int] | None = None, + umask: int = -1, +) -> Process: + """ + Start an external command in a subprocess. + + .. seealso:: :class:`subprocess.Popen` + + :param command: either a string to pass to the shell, or an iterable of strings + containing the executable name or path and its arguments + :param stdin: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, a + file-like object, or ``None`` + :param stdout: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, + a file-like object, or ``None`` + :param stderr: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, + :data:`subprocess.STDOUT`, a file-like object, or ``None`` + :param cwd: If not ``None``, the working directory is changed before executing + :param env: If env is not ``None``, it must be a mapping that defines the + environment variables for the new process + :param creationflags: flags that can be used to control the creation of the + subprocess (see :class:`subprocess.Popen` for the specifics) + :param startupinfo: an instance of :class:`subprocess.STARTUPINFO` that can be used + to specify process startup parameters (Windows only) + :param start_new_session: if ``true`` the setsid() system call will be made in the + child process prior to the execution of the subprocess. (POSIX only) + :param pass_fds: sequence of file descriptors to keep open between the parent and + child processes. (POSIX only) + :param user: effective user to run the process as (POSIX only) + :param group: effective group to run the process as (POSIX only) + :param extra_groups: supplementary groups to set in the subprocess (POSIX only) + :param umask: if not negative, this umask is applied in the child process before + running the given command (POSIX only) + :return: an asynchronous process object + + """ + kwargs: dict[str, Any] = {} + if user is not None: + kwargs["user"] = user + + if group is not None: + kwargs["group"] = group + + if extra_groups is not None: + kwargs["extra_groups"] = group + + if umask >= 0: + kwargs["umask"] = umask + + return await get_async_backend().open_process( + command, + stdin=stdin, + stdout=stdout, + stderr=stderr, + cwd=cwd, + env=env, + startupinfo=startupinfo, + creationflags=creationflags, + start_new_session=start_new_session, + pass_fds=pass_fds, + **kwargs, + ) diff --git a/backend/.venv/Lib/site-packages/anyio/_core/_synchronization.py b/backend/.venv/Lib/site-packages/anyio/_core/_synchronization.py new file mode 100644 index 0000000..eab87d4 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/_core/_synchronization.py @@ -0,0 +1,753 @@ +from __future__ import annotations + +import math +from collections import deque +from collections.abc import Callable +from dataclasses import dataclass +from types import TracebackType +from typing import TypeVar + +from ..lowlevel import checkpoint_if_cancelled +from ._eventloop import NoCurrentAsyncBackend, get_async_backend +from ._exceptions import BusyResourceError +from ._tasks import CancelScope +from ._testing import TaskInfo, get_current_task + +T = TypeVar("T") + + +@dataclass(frozen=True) +class EventStatistics: + """ + :ivar int tasks_waiting: number of tasks waiting on :meth:`~.Event.wait` + """ + + tasks_waiting: int + + +@dataclass(frozen=True) +class CapacityLimiterStatistics: + """ + :ivar int borrowed_tokens: number of tokens currently borrowed by tasks + :ivar float total_tokens: total number of available tokens + :ivar tuple borrowers: tasks or other objects currently holding tokens borrowed from + this limiter + :ivar int tasks_waiting: number of tasks waiting on + :meth:`~.CapacityLimiter.acquire` or + :meth:`~.CapacityLimiter.acquire_on_behalf_of` + """ + + borrowed_tokens: int + total_tokens: float + borrowers: tuple[object, ...] + tasks_waiting: int + + +@dataclass(frozen=True) +class LockStatistics: + """ + :ivar bool locked: flag indicating if this lock is locked or not + :ivar ~anyio.TaskInfo owner: task currently holding the lock (or ``None`` if the + lock is not held by any task) + :ivar int tasks_waiting: number of tasks waiting on :meth:`~.Lock.acquire` + """ + + locked: bool + owner: TaskInfo | None + tasks_waiting: int + + +@dataclass(frozen=True) +class ConditionStatistics: + """ + :ivar int tasks_waiting: number of tasks blocked on :meth:`~.Condition.wait` + :ivar ~anyio.LockStatistics lock_statistics: statistics of the underlying + :class:`~.Lock` + """ + + tasks_waiting: int + lock_statistics: LockStatistics + + +@dataclass(frozen=True) +class SemaphoreStatistics: + """ + :ivar int tasks_waiting: number of tasks waiting on :meth:`~.Semaphore.acquire` + + """ + + tasks_waiting: int + + +class Event: + def __new__(cls) -> Event: + try: + return get_async_backend().create_event() + except NoCurrentAsyncBackend: + return EventAdapter() + + def set(self) -> None: + """Set the flag, notifying all listeners.""" + raise NotImplementedError + + def is_set(self) -> bool: + """Return ``True`` if the flag is set, ``False`` if not.""" + raise NotImplementedError + + async def wait(self) -> None: + """ + Wait until the flag has been set. + + If the flag has already been set when this method is called, it returns + immediately. + + """ + raise NotImplementedError + + def statistics(self) -> EventStatistics: + """Return statistics about the current state of this event.""" + raise NotImplementedError + + +class EventAdapter(Event): + _internal_event: Event | None = None + _is_set: bool = False + + def __new__(cls) -> EventAdapter: + return object.__new__(cls) + + @property + def _event(self) -> Event: + if self._internal_event is None: + self._internal_event = get_async_backend().create_event() + if self._is_set: + self._internal_event.set() + + return self._internal_event + + def set(self) -> None: + if self._internal_event is None: + self._is_set = True + else: + self._event.set() + + def is_set(self) -> bool: + if self._internal_event is None: + return self._is_set + + return self._internal_event.is_set() + + async def wait(self) -> None: + await self._event.wait() + + def statistics(self) -> EventStatistics: + if self._internal_event is None: + return EventStatistics(tasks_waiting=0) + + return self._internal_event.statistics() + + +class Lock: + def __new__(cls, *, fast_acquire: bool = False) -> Lock: + try: + return get_async_backend().create_lock(fast_acquire=fast_acquire) + except NoCurrentAsyncBackend: + return LockAdapter(fast_acquire=fast_acquire) + + async def __aenter__(self) -> None: + await self.acquire() + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self.release() + + async def acquire(self) -> None: + """Acquire the lock.""" + raise NotImplementedError + + def acquire_nowait(self) -> None: + """ + Acquire the lock, without blocking. + + :raises ~anyio.WouldBlock: if the operation would block + + """ + raise NotImplementedError + + def release(self) -> None: + """Release the lock.""" + raise NotImplementedError + + def locked(self) -> bool: + """Return True if the lock is currently held.""" + raise NotImplementedError + + def statistics(self) -> LockStatistics: + """ + Return statistics about the current state of this lock. + + .. versionadded:: 3.0 + """ + raise NotImplementedError + + +class LockAdapter(Lock): + _internal_lock: Lock | None = None + + def __new__(cls, *, fast_acquire: bool = False) -> LockAdapter: + return object.__new__(cls) + + def __init__(self, *, fast_acquire: bool = False): + self._fast_acquire = fast_acquire + + @property + def _lock(self) -> Lock: + if self._internal_lock is None: + self._internal_lock = get_async_backend().create_lock( + fast_acquire=self._fast_acquire + ) + + return self._internal_lock + + async def __aenter__(self) -> None: + await self._lock.acquire() + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + if self._internal_lock is not None: + self._internal_lock.release() + + async def acquire(self) -> None: + """Acquire the lock.""" + await self._lock.acquire() + + def acquire_nowait(self) -> None: + """ + Acquire the lock, without blocking. + + :raises ~anyio.WouldBlock: if the operation would block + + """ + self._lock.acquire_nowait() + + def release(self) -> None: + """Release the lock.""" + self._lock.release() + + def locked(self) -> bool: + """Return True if the lock is currently held.""" + return self._lock.locked() + + def statistics(self) -> LockStatistics: + """ + Return statistics about the current state of this lock. + + .. versionadded:: 3.0 + + """ + if self._internal_lock is None: + return LockStatistics(False, None, 0) + + return self._internal_lock.statistics() + + +class Condition: + _owner_task: TaskInfo | None = None + + def __init__(self, lock: Lock | None = None): + self._lock = lock or Lock() + self._waiters: deque[Event] = deque() + + async def __aenter__(self) -> None: + await self.acquire() + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self.release() + + def _check_acquired(self) -> None: + if self._owner_task != get_current_task(): + raise RuntimeError("The current task is not holding the underlying lock") + + async def acquire(self) -> None: + """Acquire the underlying lock.""" + await self._lock.acquire() + self._owner_task = get_current_task() + + def acquire_nowait(self) -> None: + """ + Acquire the underlying lock, without blocking. + + :raises ~anyio.WouldBlock: if the operation would block + + """ + self._lock.acquire_nowait() + self._owner_task = get_current_task() + + def release(self) -> None: + """Release the underlying lock.""" + self._lock.release() + + def locked(self) -> bool: + """Return True if the lock is set.""" + return self._lock.locked() + + def notify(self, n: int = 1) -> None: + """Notify exactly n listeners.""" + self._check_acquired() + for _ in range(n): + try: + event = self._waiters.popleft() + except IndexError: + break + + event.set() + + def notify_all(self) -> None: + """Notify all the listeners.""" + self._check_acquired() + for event in self._waiters: + event.set() + + self._waiters.clear() + + async def wait(self) -> None: + """Wait for a notification.""" + await checkpoint_if_cancelled() + self._check_acquired() + event = Event() + self._waiters.append(event) + self.release() + try: + await event.wait() + except BaseException: + if not event.is_set(): + self._waiters.remove(event) + + raise + finally: + with CancelScope(shield=True): + await self.acquire() + + async def wait_for(self, predicate: Callable[[], T]) -> T: + """ + Wait until a predicate becomes true. + + :param predicate: a callable that returns a truthy value when the condition is + met + :return: the result of the predicate + + .. versionadded:: 4.11.0 + + """ + while not (result := predicate()): + await self.wait() + + return result + + def statistics(self) -> ConditionStatistics: + """ + Return statistics about the current state of this condition. + + .. versionadded:: 3.0 + """ + return ConditionStatistics(len(self._waiters), self._lock.statistics()) + + +class Semaphore: + def __new__( + cls, + initial_value: int, + *, + max_value: int | None = None, + fast_acquire: bool = False, + ) -> Semaphore: + try: + return get_async_backend().create_semaphore( + initial_value, max_value=max_value, fast_acquire=fast_acquire + ) + except NoCurrentAsyncBackend: + return SemaphoreAdapter(initial_value, max_value=max_value) + + def __init__( + self, + initial_value: int, + *, + max_value: int | None = None, + fast_acquire: bool = False, + ): + if not isinstance(initial_value, int): + raise TypeError("initial_value must be an integer") + if initial_value < 0: + raise ValueError("initial_value must be >= 0") + if max_value is not None: + if not isinstance(max_value, int): + raise TypeError("max_value must be an integer or None") + if max_value < initial_value: + raise ValueError( + "max_value must be equal to or higher than initial_value" + ) + + self._fast_acquire = fast_acquire + + async def __aenter__(self) -> Semaphore: + await self.acquire() + return self + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self.release() + + async def acquire(self) -> None: + """Decrement the semaphore value, blocking if necessary.""" + raise NotImplementedError + + def acquire_nowait(self) -> None: + """ + Acquire the underlying lock, without blocking. + + :raises ~anyio.WouldBlock: if the operation would block + + """ + raise NotImplementedError + + def release(self) -> None: + """Increment the semaphore value.""" + raise NotImplementedError + + @property + def value(self) -> int: + """The current value of the semaphore.""" + raise NotImplementedError + + @property + def max_value(self) -> int | None: + """The maximum value of the semaphore.""" + raise NotImplementedError + + def statistics(self) -> SemaphoreStatistics: + """ + Return statistics about the current state of this semaphore. + + .. versionadded:: 3.0 + """ + raise NotImplementedError + + +class SemaphoreAdapter(Semaphore): + _internal_semaphore: Semaphore | None = None + + def __new__( + cls, + initial_value: int, + *, + max_value: int | None = None, + fast_acquire: bool = False, + ) -> SemaphoreAdapter: + return object.__new__(cls) + + def __init__( + self, + initial_value: int, + *, + max_value: int | None = None, + fast_acquire: bool = False, + ) -> None: + super().__init__(initial_value, max_value=max_value, fast_acquire=fast_acquire) + self._initial_value = initial_value + self._max_value = max_value + + @property + def _semaphore(self) -> Semaphore: + if self._internal_semaphore is None: + self._internal_semaphore = get_async_backend().create_semaphore( + self._initial_value, max_value=self._max_value + ) + + return self._internal_semaphore + + async def acquire(self) -> None: + await self._semaphore.acquire() + + def acquire_nowait(self) -> None: + self._semaphore.acquire_nowait() + + def release(self) -> None: + self._semaphore.release() + + @property + def value(self) -> int: + if self._internal_semaphore is None: + return self._initial_value + + return self._semaphore.value + + @property + def max_value(self) -> int | None: + return self._max_value + + def statistics(self) -> SemaphoreStatistics: + if self._internal_semaphore is None: + return SemaphoreStatistics(tasks_waiting=0) + + return self._semaphore.statistics() + + +class CapacityLimiter: + def __new__(cls, total_tokens: float) -> CapacityLimiter: + try: + return get_async_backend().create_capacity_limiter(total_tokens) + except NoCurrentAsyncBackend: + return CapacityLimiterAdapter(total_tokens) + + async def __aenter__(self) -> None: + raise NotImplementedError + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + raise NotImplementedError + + @property + def total_tokens(self) -> float: + """ + The total number of tokens available for borrowing. + + This is a read-write property. If the total number of tokens is increased, the + proportionate number of tasks waiting on this limiter will be granted their + tokens. + + .. versionchanged:: 3.0 + The property is now writable. + .. versionchanged:: 4.12 + The value can now be set to 0. + + """ + raise NotImplementedError + + @total_tokens.setter + def total_tokens(self, value: float) -> None: + raise NotImplementedError + + @property + def borrowed_tokens(self) -> int: + """The number of tokens that have currently been borrowed.""" + raise NotImplementedError + + @property + def available_tokens(self) -> float: + """The number of tokens currently available to be borrowed""" + raise NotImplementedError + + def acquire_nowait(self) -> None: + """ + Acquire a token for the current task without waiting for one to become + available. + + :raises ~anyio.WouldBlock: if there are no tokens available for borrowing + + """ + raise NotImplementedError + + def acquire_on_behalf_of_nowait(self, borrower: object) -> None: + """ + Acquire a token without waiting for one to become available. + + :param borrower: the entity borrowing a token + :raises ~anyio.WouldBlock: if there are no tokens available for borrowing + + """ + raise NotImplementedError + + async def acquire(self) -> None: + """ + Acquire a token for the current task, waiting if necessary for one to become + available. + + """ + raise NotImplementedError + + async def acquire_on_behalf_of(self, borrower: object) -> None: + """ + Acquire a token, waiting if necessary for one to become available. + + :param borrower: the entity borrowing a token + + """ + raise NotImplementedError + + def release(self) -> None: + """ + Release the token held by the current task. + + :raises RuntimeError: if the current task has not borrowed a token from this + limiter. + + """ + raise NotImplementedError + + def release_on_behalf_of(self, borrower: object) -> None: + """ + Release the token held by the given borrower. + + :raises RuntimeError: if the borrower has not borrowed a token from this + limiter. + + """ + raise NotImplementedError + + def statistics(self) -> CapacityLimiterStatistics: + """ + Return statistics about the current state of this limiter. + + .. versionadded:: 3.0 + + """ + raise NotImplementedError + + +class CapacityLimiterAdapter(CapacityLimiter): + _internal_limiter: CapacityLimiter | None = None + + def __new__(cls, total_tokens: float) -> CapacityLimiterAdapter: + return object.__new__(cls) + + def __init__(self, total_tokens: float) -> None: + self.total_tokens = total_tokens + + @property + def _limiter(self) -> CapacityLimiter: + if self._internal_limiter is None: + self._internal_limiter = get_async_backend().create_capacity_limiter( + self._total_tokens + ) + + return self._internal_limiter + + async def __aenter__(self) -> None: + await self._limiter.__aenter__() + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + return await self._limiter.__aexit__(exc_type, exc_val, exc_tb) + + @property + def total_tokens(self) -> float: + if self._internal_limiter is None: + return self._total_tokens + + return self._internal_limiter.total_tokens + + @total_tokens.setter + def total_tokens(self, value: float) -> None: + if not isinstance(value, int) and value is not math.inf: + raise TypeError("total_tokens must be an int or math.inf") + elif value < 1: + raise ValueError("total_tokens must be >= 1") + + if self._internal_limiter is None: + self._total_tokens = value + return + + self._limiter.total_tokens = value + + @property + def borrowed_tokens(self) -> int: + if self._internal_limiter is None: + return 0 + + return self._internal_limiter.borrowed_tokens + + @property + def available_tokens(self) -> float: + if self._internal_limiter is None: + return self._total_tokens + + return self._internal_limiter.available_tokens + + def acquire_nowait(self) -> None: + self._limiter.acquire_nowait() + + def acquire_on_behalf_of_nowait(self, borrower: object) -> None: + self._limiter.acquire_on_behalf_of_nowait(borrower) + + async def acquire(self) -> None: + await self._limiter.acquire() + + async def acquire_on_behalf_of(self, borrower: object) -> None: + await self._limiter.acquire_on_behalf_of(borrower) + + def release(self) -> None: + self._limiter.release() + + def release_on_behalf_of(self, borrower: object) -> None: + self._limiter.release_on_behalf_of(borrower) + + def statistics(self) -> CapacityLimiterStatistics: + if self._internal_limiter is None: + return CapacityLimiterStatistics( + borrowed_tokens=0, + total_tokens=self.total_tokens, + borrowers=(), + tasks_waiting=0, + ) + + return self._internal_limiter.statistics() + + +class ResourceGuard: + """ + A context manager for ensuring that a resource is only used by a single task at a + time. + + Entering this context manager while the previous has not exited it yet will trigger + :exc:`BusyResourceError`. + + :param action: the action to guard against (visible in the :exc:`BusyResourceError` + when triggered, e.g. "Another task is already {action} this resource") + + .. versionadded:: 4.1 + """ + + __slots__ = "action", "_guarded" + + def __init__(self, action: str = "using"): + self.action: str = action + self._guarded = False + + def __enter__(self) -> None: + if self._guarded: + raise BusyResourceError(self.action) + + self._guarded = True + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self._guarded = False diff --git a/backend/.venv/Lib/site-packages/anyio/_core/_tasks.py b/backend/.venv/Lib/site-packages/anyio/_core/_tasks.py new file mode 100644 index 0000000..d37efe3 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/_core/_tasks.py @@ -0,0 +1,163 @@ +from __future__ import annotations + +import math +from collections.abc import Generator +from contextlib import contextmanager +from types import TracebackType + +from ..abc._tasks import TaskGroup, TaskStatus +from ._eventloop import get_async_backend + + +class _IgnoredTaskStatus(TaskStatus[object]): + def started(self, value: object = None) -> None: + pass + + +TASK_STATUS_IGNORED = _IgnoredTaskStatus() + + +class CancelScope: + """ + Wraps a unit of work that can be made separately cancellable. + + :param deadline: The time (clock value) when this scope is cancelled automatically + :param shield: ``True`` to shield the cancel scope from external cancellation + """ + + def __new__( + cls, *, deadline: float = math.inf, shield: bool = False + ) -> CancelScope: + return get_async_backend().create_cancel_scope(shield=shield, deadline=deadline) + + def cancel(self, reason: str | None = None) -> None: + """ + Cancel this scope immediately. + + :param reason: a message describing the reason for the cancellation + + """ + raise NotImplementedError + + @property + def deadline(self) -> float: + """ + The time (clock value) when this scope is cancelled automatically. + + Will be ``float('inf')`` if no timeout has been set. + + """ + raise NotImplementedError + + @deadline.setter + def deadline(self, value: float) -> None: + raise NotImplementedError + + @property + def cancel_called(self) -> bool: + """``True`` if :meth:`cancel` has been called.""" + raise NotImplementedError + + @property + def cancelled_caught(self) -> bool: + """ + ``True`` if this scope suppressed a cancellation exception it itself raised. + + This is typically used to check if any work was interrupted, or to see if the + scope was cancelled due to its deadline being reached. The value will, however, + only be ``True`` if the cancellation was triggered by the scope itself (and not + an outer scope). + + """ + raise NotImplementedError + + @property + def shield(self) -> bool: + """ + ``True`` if this scope is shielded from external cancellation. + + While a scope is shielded, it will not receive cancellations from outside. + + """ + raise NotImplementedError + + @shield.setter + def shield(self, value: bool) -> None: + raise NotImplementedError + + def __enter__(self) -> CancelScope: + raise NotImplementedError + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> bool: + raise NotImplementedError + + +@contextmanager +def fail_after( + delay: float | None, shield: bool = False +) -> Generator[CancelScope, None, None]: + """ + Create a context manager which raises a :class:`TimeoutError` if does not finish in + time. + + :param delay: maximum allowed time (in seconds) before raising the exception, or + ``None`` to disable the timeout + :param shield: ``True`` to shield the cancel scope from external cancellation + :return: a context manager that yields a cancel scope + :rtype: :class:`~typing.ContextManager`\\[:class:`~anyio.CancelScope`\\] + + """ + current_time = get_async_backend().current_time + deadline = (current_time() + delay) if delay is not None else math.inf + with get_async_backend().create_cancel_scope( + deadline=deadline, shield=shield + ) as cancel_scope: + yield cancel_scope + + if cancel_scope.cancelled_caught and current_time() >= cancel_scope.deadline: + raise TimeoutError + + +def move_on_after(delay: float | None, shield: bool = False) -> CancelScope: + """ + Create a cancel scope with a deadline that expires after the given delay. + + :param delay: maximum allowed time (in seconds) before exiting the context block, or + ``None`` to disable the timeout + :param shield: ``True`` to shield the cancel scope from external cancellation + :return: a cancel scope + + """ + deadline = ( + (get_async_backend().current_time() + delay) if delay is not None else math.inf + ) + return get_async_backend().create_cancel_scope(deadline=deadline, shield=shield) + + +def current_effective_deadline() -> float: + """ + Return the nearest deadline among all the cancel scopes effective for the current + task. + + :return: a clock value from the event loop's internal clock (or ``float('inf')`` if + there is no deadline in effect, or ``float('-inf')`` if the current scope has + been cancelled) + :rtype: float + + """ + return get_async_backend().current_effective_deadline() + + +def create_task_group() -> TaskGroup: + """ + Create a task group. + + :return: a task group + + """ + return get_async_backend().create_task_group() diff --git a/backend/.venv/Lib/site-packages/anyio/_core/_tempfile.py b/backend/.venv/Lib/site-packages/anyio/_core/_tempfile.py new file mode 100644 index 0000000..fbb6b14 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/_core/_tempfile.py @@ -0,0 +1,616 @@ +from __future__ import annotations + +import os +import sys +import tempfile +from collections.abc import Iterable +from io import BytesIO, TextIOWrapper +from types import TracebackType +from typing import ( + TYPE_CHECKING, + Any, + AnyStr, + Generic, + overload, +) + +from .. import to_thread +from .._core._fileio import AsyncFile +from ..lowlevel import checkpoint_if_cancelled + +if TYPE_CHECKING: + from _typeshed import OpenBinaryMode, OpenTextMode, ReadableBuffer, WriteableBuffer + + +class TemporaryFile(Generic[AnyStr]): + """ + An asynchronous temporary file that is automatically created and cleaned up. + + This class provides an asynchronous context manager interface to a temporary file. + The file is created using Python's standard `tempfile.TemporaryFile` function in a + background thread, and is wrapped as an asynchronous file using `AsyncFile`. + + :param mode: The mode in which the file is opened. Defaults to "w+b". + :param buffering: The buffering policy (-1 means the default buffering). + :param encoding: The encoding used to decode or encode the file. Only applicable in + text mode. + :param newline: Controls how universal newlines mode works (only applicable in text + mode). + :param suffix: The suffix for the temporary file name. + :param prefix: The prefix for the temporary file name. + :param dir: The directory in which the temporary file is created. + :param errors: The error handling scheme used for encoding/decoding errors. + """ + + _async_file: AsyncFile[AnyStr] + + @overload + def __init__( + self: TemporaryFile[bytes], + mode: OpenBinaryMode = ..., + buffering: int = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: str | None = ..., + prefix: str | None = ..., + dir: str | None = ..., + *, + errors: str | None = ..., + ): ... + @overload + def __init__( + self: TemporaryFile[str], + mode: OpenTextMode, + buffering: int = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: str | None = ..., + prefix: str | None = ..., + dir: str | None = ..., + *, + errors: str | None = ..., + ): ... + + def __init__( + self, + mode: OpenTextMode | OpenBinaryMode = "w+b", + buffering: int = -1, + encoding: str | None = None, + newline: str | None = None, + suffix: str | None = None, + prefix: str | None = None, + dir: str | None = None, + *, + errors: str | None = None, + ) -> None: + self.mode = mode + self.buffering = buffering + self.encoding = encoding + self.newline = newline + self.suffix: str | None = suffix + self.prefix: str | None = prefix + self.dir: str | None = dir + self.errors = errors + + async def __aenter__(self) -> AsyncFile[AnyStr]: + fp = await to_thread.run_sync( + lambda: tempfile.TemporaryFile( + self.mode, + self.buffering, + self.encoding, + self.newline, + self.suffix, + self.prefix, + self.dir, + errors=self.errors, + ) + ) + self._async_file = AsyncFile(fp) + return self._async_file + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + traceback: TracebackType | None, + ) -> None: + await self._async_file.aclose() + + +class NamedTemporaryFile(Generic[AnyStr]): + """ + An asynchronous named temporary file that is automatically created and cleaned up. + + This class provides an asynchronous context manager for a temporary file with a + visible name in the file system. It uses Python's standard + :func:`~tempfile.NamedTemporaryFile` function and wraps the file object with + :class:`AsyncFile` for asynchronous operations. + + :param mode: The mode in which the file is opened. Defaults to "w+b". + :param buffering: The buffering policy (-1 means the default buffering). + :param encoding: The encoding used to decode or encode the file. Only applicable in + text mode. + :param newline: Controls how universal newlines mode works (only applicable in text + mode). + :param suffix: The suffix for the temporary file name. + :param prefix: The prefix for the temporary file name. + :param dir: The directory in which the temporary file is created. + :param delete: Whether to delete the file when it is closed. + :param errors: The error handling scheme used for encoding/decoding errors. + :param delete_on_close: (Python 3.12+) Whether to delete the file on close. + """ + + _async_file: AsyncFile[AnyStr] + + @overload + def __init__( + self: NamedTemporaryFile[bytes], + mode: OpenBinaryMode = ..., + buffering: int = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: str | None = ..., + prefix: str | None = ..., + dir: str | None = ..., + delete: bool = ..., + *, + errors: str | None = ..., + delete_on_close: bool = ..., + ): ... + @overload + def __init__( + self: NamedTemporaryFile[str], + mode: OpenTextMode, + buffering: int = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: str | None = ..., + prefix: str | None = ..., + dir: str | None = ..., + delete: bool = ..., + *, + errors: str | None = ..., + delete_on_close: bool = ..., + ): ... + + def __init__( + self, + mode: OpenBinaryMode | OpenTextMode = "w+b", + buffering: int = -1, + encoding: str | None = None, + newline: str | None = None, + suffix: str | None = None, + prefix: str | None = None, + dir: str | None = None, + delete: bool = True, + *, + errors: str | None = None, + delete_on_close: bool = True, + ) -> None: + self._params: dict[str, Any] = { + "mode": mode, + "buffering": buffering, + "encoding": encoding, + "newline": newline, + "suffix": suffix, + "prefix": prefix, + "dir": dir, + "delete": delete, + "errors": errors, + } + if sys.version_info >= (3, 12): + self._params["delete_on_close"] = delete_on_close + + async def __aenter__(self) -> AsyncFile[AnyStr]: + fp = await to_thread.run_sync( + lambda: tempfile.NamedTemporaryFile(**self._params) + ) + self._async_file = AsyncFile(fp) + return self._async_file + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + traceback: TracebackType | None, + ) -> None: + await self._async_file.aclose() + + +class SpooledTemporaryFile(AsyncFile[AnyStr]): + """ + An asynchronous spooled temporary file that starts in memory and is spooled to disk. + + This class provides an asynchronous interface to a spooled temporary file, much like + Python's standard :class:`~tempfile.SpooledTemporaryFile`. It supports asynchronous + write operations and provides a method to force a rollover to disk. + + :param max_size: Maximum size in bytes before the file is rolled over to disk. + :param mode: The mode in which the file is opened. Defaults to "w+b". + :param buffering: The buffering policy (-1 means the default buffering). + :param encoding: The encoding used to decode or encode the file (text mode only). + :param newline: Controls how universal newlines mode works (text mode only). + :param suffix: The suffix for the temporary file name. + :param prefix: The prefix for the temporary file name. + :param dir: The directory in which the temporary file is created. + :param errors: The error handling scheme used for encoding/decoding errors. + """ + + _rolled: bool = False + + @overload + def __init__( + self: SpooledTemporaryFile[bytes], + max_size: int = ..., + mode: OpenBinaryMode = ..., + buffering: int = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: str | None = ..., + prefix: str | None = ..., + dir: str | None = ..., + *, + errors: str | None = ..., + ): ... + @overload + def __init__( + self: SpooledTemporaryFile[str], + max_size: int = ..., + mode: OpenTextMode = ..., + buffering: int = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: str | None = ..., + prefix: str | None = ..., + dir: str | None = ..., + *, + errors: str | None = ..., + ): ... + + def __init__( + self, + max_size: int = 0, + mode: OpenBinaryMode | OpenTextMode = "w+b", + buffering: int = -1, + encoding: str | None = None, + newline: str | None = None, + suffix: str | None = None, + prefix: str | None = None, + dir: str | None = None, + *, + errors: str | None = None, + ) -> None: + self._tempfile_params: dict[str, Any] = { + "mode": mode, + "buffering": buffering, + "encoding": encoding, + "newline": newline, + "suffix": suffix, + "prefix": prefix, + "dir": dir, + "errors": errors, + } + self._max_size = max_size + if "b" in mode: + super().__init__(BytesIO()) # type: ignore[arg-type] + else: + super().__init__( + TextIOWrapper( # type: ignore[arg-type] + BytesIO(), + encoding=encoding, + errors=errors, + newline=newline, + write_through=True, + ) + ) + + async def aclose(self) -> None: + if not self._rolled: + self._fp.close() + return + + await super().aclose() + + async def _check(self) -> None: + if self._rolled or self._fp.tell() <= self._max_size: + return + + await self.rollover() + + async def rollover(self) -> None: + if self._rolled: + return + + self._rolled = True + buffer = self._fp + buffer.seek(0) + self._fp = await to_thread.run_sync( + lambda: tempfile.TemporaryFile(**self._tempfile_params) + ) + await self.write(buffer.read()) + buffer.close() + + @property + def closed(self) -> bool: + return self._fp.closed + + async def read(self, size: int = -1) -> AnyStr: + if not self._rolled: + await checkpoint_if_cancelled() + return self._fp.read(size) + + return await super().read(size) # type: ignore[return-value] + + async def read1(self: SpooledTemporaryFile[bytes], size: int = -1) -> bytes: + if not self._rolled: + await checkpoint_if_cancelled() + return self._fp.read1(size) + + return await super().read1(size) + + async def readline(self) -> AnyStr: + if not self._rolled: + await checkpoint_if_cancelled() + return self._fp.readline() + + return await super().readline() # type: ignore[return-value] + + async def readlines(self) -> list[AnyStr]: + if not self._rolled: + await checkpoint_if_cancelled() + return self._fp.readlines() + + return await super().readlines() # type: ignore[return-value] + + async def readinto(self: SpooledTemporaryFile[bytes], b: WriteableBuffer) -> int: + if not self._rolled: + await checkpoint_if_cancelled() + self._fp.readinto(b) + + return await super().readinto(b) + + async def readinto1(self: SpooledTemporaryFile[bytes], b: WriteableBuffer) -> int: + if not self._rolled: + await checkpoint_if_cancelled() + self._fp.readinto(b) + + return await super().readinto1(b) + + async def seek(self, offset: int, whence: int | None = os.SEEK_SET) -> int: + if not self._rolled: + await checkpoint_if_cancelled() + return self._fp.seek(offset, whence) + + return await super().seek(offset, whence) + + async def tell(self) -> int: + if not self._rolled: + await checkpoint_if_cancelled() + return self._fp.tell() + + return await super().tell() + + async def truncate(self, size: int | None = None) -> int: + if not self._rolled: + await checkpoint_if_cancelled() + return self._fp.truncate(size) + + return await super().truncate(size) + + @overload + async def write(self: SpooledTemporaryFile[bytes], b: ReadableBuffer) -> int: ... + @overload + async def write(self: SpooledTemporaryFile[str], b: str) -> int: ... + + async def write(self, b: ReadableBuffer | str) -> int: + """ + Asynchronously write data to the spooled temporary file. + + If the file has not yet been rolled over, the data is written synchronously, + and a rollover is triggered if the size exceeds the maximum size. + + :param s: The data to write. + :return: The number of bytes written. + :raises RuntimeError: If the underlying file is not initialized. + + """ + if not self._rolled: + await checkpoint_if_cancelled() + result = self._fp.write(b) + await self._check() + return result + + return await super().write(b) # type: ignore[misc] + + @overload + async def writelines( + self: SpooledTemporaryFile[bytes], lines: Iterable[ReadableBuffer] + ) -> None: ... + @overload + async def writelines( + self: SpooledTemporaryFile[str], lines: Iterable[str] + ) -> None: ... + + async def writelines(self, lines: Iterable[str] | Iterable[ReadableBuffer]) -> None: + """ + Asynchronously write a list of lines to the spooled temporary file. + + If the file has not yet been rolled over, the lines are written synchronously, + and a rollover is triggered if the size exceeds the maximum size. + + :param lines: An iterable of lines to write. + :raises RuntimeError: If the underlying file is not initialized. + + """ + if not self._rolled: + await checkpoint_if_cancelled() + result = self._fp.writelines(lines) + await self._check() + return result + + return await super().writelines(lines) # type: ignore[misc] + + +class TemporaryDirectory(Generic[AnyStr]): + """ + An asynchronous temporary directory that is created and cleaned up automatically. + + This class provides an asynchronous context manager for creating a temporary + directory. It wraps Python's standard :class:`~tempfile.TemporaryDirectory` to + perform directory creation and cleanup operations in a background thread. + + :param suffix: Suffix to be added to the temporary directory name. + :param prefix: Prefix to be added to the temporary directory name. + :param dir: The parent directory where the temporary directory is created. + :param ignore_cleanup_errors: Whether to ignore errors during cleanup + (Python 3.10+). + :param delete: Whether to delete the directory upon closing (Python 3.12+). + """ + + def __init__( + self, + suffix: AnyStr | None = None, + prefix: AnyStr | None = None, + dir: AnyStr | None = None, + *, + ignore_cleanup_errors: bool = False, + delete: bool = True, + ) -> None: + self.suffix: AnyStr | None = suffix + self.prefix: AnyStr | None = prefix + self.dir: AnyStr | None = dir + self.ignore_cleanup_errors = ignore_cleanup_errors + self.delete = delete + + self._tempdir: tempfile.TemporaryDirectory | None = None + + async def __aenter__(self) -> str: + params: dict[str, Any] = { + "suffix": self.suffix, + "prefix": self.prefix, + "dir": self.dir, + } + if sys.version_info >= (3, 10): + params["ignore_cleanup_errors"] = self.ignore_cleanup_errors + + if sys.version_info >= (3, 12): + params["delete"] = self.delete + + self._tempdir = await to_thread.run_sync( + lambda: tempfile.TemporaryDirectory(**params) + ) + return await to_thread.run_sync(self._tempdir.__enter__) + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + traceback: TracebackType | None, + ) -> None: + if self._tempdir is not None: + await to_thread.run_sync( + self._tempdir.__exit__, exc_type, exc_value, traceback + ) + + async def cleanup(self) -> None: + if self._tempdir is not None: + await to_thread.run_sync(self._tempdir.cleanup) + + +@overload +async def mkstemp( + suffix: str | None = None, + prefix: str | None = None, + dir: str | None = None, + text: bool = False, +) -> tuple[int, str]: ... + + +@overload +async def mkstemp( + suffix: bytes | None = None, + prefix: bytes | None = None, + dir: bytes | None = None, + text: bool = False, +) -> tuple[int, bytes]: ... + + +async def mkstemp( + suffix: AnyStr | None = None, + prefix: AnyStr | None = None, + dir: AnyStr | None = None, + text: bool = False, +) -> tuple[int, str | bytes]: + """ + Asynchronously create a temporary file and return an OS-level handle and the file + name. + + This function wraps `tempfile.mkstemp` and executes it in a background thread. + + :param suffix: Suffix to be added to the file name. + :param prefix: Prefix to be added to the file name. + :param dir: Directory in which the temporary file is created. + :param text: Whether the file is opened in text mode. + :return: A tuple containing the file descriptor and the file name. + + """ + return await to_thread.run_sync(tempfile.mkstemp, suffix, prefix, dir, text) + + +@overload +async def mkdtemp( + suffix: str | None = None, + prefix: str | None = None, + dir: str | None = None, +) -> str: ... + + +@overload +async def mkdtemp( + suffix: bytes | None = None, + prefix: bytes | None = None, + dir: bytes | None = None, +) -> bytes: ... + + +async def mkdtemp( + suffix: AnyStr | None = None, + prefix: AnyStr | None = None, + dir: AnyStr | None = None, +) -> str | bytes: + """ + Asynchronously create a temporary directory and return its path. + + This function wraps `tempfile.mkdtemp` and executes it in a background thread. + + :param suffix: Suffix to be added to the directory name. + :param prefix: Prefix to be added to the directory name. + :param dir: Parent directory where the temporary directory is created. + :return: The path of the created temporary directory. + + """ + return await to_thread.run_sync(tempfile.mkdtemp, suffix, prefix, dir) + + +async def gettempdir() -> str: + """ + Asynchronously return the name of the directory used for temporary files. + + This function wraps `tempfile.gettempdir` and executes it in a background thread. + + :return: The path of the temporary directory as a string. + + """ + return await to_thread.run_sync(tempfile.gettempdir) + + +async def gettempdirb() -> bytes: + """ + Asynchronously return the name of the directory used for temporary files in bytes. + + This function wraps `tempfile.gettempdirb` and executes it in a background thread. + + :return: The path of the temporary directory as bytes. + + """ + return await to_thread.run_sync(tempfile.gettempdirb) diff --git a/backend/.venv/Lib/site-packages/anyio/_core/_testing.py b/backend/.venv/Lib/site-packages/anyio/_core/_testing.py new file mode 100644 index 0000000..9e28b22 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/_core/_testing.py @@ -0,0 +1,78 @@ +from __future__ import annotations + +from collections.abc import Awaitable, Generator +from typing import Any, cast + +from ._eventloop import get_async_backend + + +class TaskInfo: + """ + Represents an asynchronous task. + + :ivar int id: the unique identifier of the task + :ivar parent_id: the identifier of the parent task, if any + :vartype parent_id: Optional[int] + :ivar str name: the description of the task (if any) + :ivar ~collections.abc.Coroutine coro: the coroutine object of the task + """ + + __slots__ = "_name", "id", "parent_id", "name", "coro" + + def __init__( + self, + id: int, + parent_id: int | None, + name: str | None, + coro: Generator[Any, Any, Any] | Awaitable[Any], + ): + func = get_current_task + self._name = f"{func.__module__}.{func.__qualname__}" + self.id: int = id + self.parent_id: int | None = parent_id + self.name: str | None = name + self.coro: Generator[Any, Any, Any] | Awaitable[Any] = coro + + def __eq__(self, other: object) -> bool: + if isinstance(other, TaskInfo): + return self.id == other.id + + return NotImplemented + + def __hash__(self) -> int: + return hash(self.id) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}(id={self.id!r}, name={self.name!r})" + + def has_pending_cancellation(self) -> bool: + """ + Return ``True`` if the task has a cancellation pending, ``False`` otherwise. + + """ + return False + + +def get_current_task() -> TaskInfo: + """ + Return the current task. + + :return: a representation of the current task + + """ + return get_async_backend().get_current_task() + + +def get_running_tasks() -> list[TaskInfo]: + """ + Return a list of running tasks in the current event loop. + + :return: a list of task info objects + + """ + return cast("list[TaskInfo]", get_async_backend().get_running_tasks()) + + +async def wait_all_tasks_blocked() -> None: + """Wait until all other tasks are waiting for something.""" + await get_async_backend().wait_all_tasks_blocked() diff --git a/backend/.venv/Lib/site-packages/anyio/_core/_typedattr.py b/backend/.venv/Lib/site-packages/anyio/_core/_typedattr.py new file mode 100644 index 0000000..f358a44 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/_core/_typedattr.py @@ -0,0 +1,81 @@ +from __future__ import annotations + +from collections.abc import Callable, Mapping +from typing import Any, TypeVar, final, overload + +from ._exceptions import TypedAttributeLookupError + +T_Attr = TypeVar("T_Attr") +T_Default = TypeVar("T_Default") +undefined = object() + + +def typed_attribute() -> Any: + """Return a unique object, used to mark typed attributes.""" + return object() + + +class TypedAttributeSet: + """ + Superclass for typed attribute collections. + + Checks that every public attribute of every subclass has a type annotation. + """ + + def __init_subclass__(cls) -> None: + annotations: dict[str, Any] = getattr(cls, "__annotations__", {}) + for attrname in dir(cls): + if not attrname.startswith("_") and attrname not in annotations: + raise TypeError( + f"Attribute {attrname!r} is missing its type annotation" + ) + + super().__init_subclass__() + + +class TypedAttributeProvider: + """Base class for classes that wish to provide typed extra attributes.""" + + @property + def extra_attributes(self) -> Mapping[T_Attr, Callable[[], T_Attr]]: + """ + A mapping of the extra attributes to callables that return the corresponding + values. + + If the provider wraps another provider, the attributes from that wrapper should + also be included in the returned mapping (but the wrapper may override the + callables from the wrapped instance). + + """ + return {} + + @overload + def extra(self, attribute: T_Attr) -> T_Attr: ... + + @overload + def extra(self, attribute: T_Attr, default: T_Default) -> T_Attr | T_Default: ... + + @final + def extra(self, attribute: Any, default: object = undefined) -> object: + """ + extra(attribute, default=undefined) + + Return the value of the given typed extra attribute. + + :param attribute: the attribute (member of a :class:`~TypedAttributeSet`) to + look for + :param default: the value that should be returned if no value is found for the + attribute + :raises ~anyio.TypedAttributeLookupError: if the search failed and no default + value was given + + """ + try: + getter = self.extra_attributes[attribute] + except KeyError: + if default is undefined: + raise TypedAttributeLookupError("Attribute not found") from None + else: + return default + + return getter() diff --git a/backend/.venv/Lib/site-packages/anyio/abc/__init__.py b/backend/.venv/Lib/site-packages/anyio/abc/__init__.py new file mode 100644 index 0000000..d560ce3 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/abc/__init__.py @@ -0,0 +1,58 @@ +from __future__ import annotations + +from ._eventloop import AsyncBackend as AsyncBackend +from ._resources import AsyncResource as AsyncResource +from ._sockets import ConnectedUDPSocket as ConnectedUDPSocket +from ._sockets import ConnectedUNIXDatagramSocket as ConnectedUNIXDatagramSocket +from ._sockets import IPAddressType as IPAddressType +from ._sockets import IPSockAddrType as IPSockAddrType +from ._sockets import SocketAttribute as SocketAttribute +from ._sockets import SocketListener as SocketListener +from ._sockets import SocketStream as SocketStream +from ._sockets import UDPPacketType as UDPPacketType +from ._sockets import UDPSocket as UDPSocket +from ._sockets import UNIXDatagramPacketType as UNIXDatagramPacketType +from ._sockets import UNIXDatagramSocket as UNIXDatagramSocket +from ._sockets import UNIXSocketStream as UNIXSocketStream +from ._streams import AnyByteReceiveStream as AnyByteReceiveStream +from ._streams import AnyByteSendStream as AnyByteSendStream +from ._streams import AnyByteStream as AnyByteStream +from ._streams import AnyByteStreamConnectable as AnyByteStreamConnectable +from ._streams import AnyUnreliableByteReceiveStream as AnyUnreliableByteReceiveStream +from ._streams import AnyUnreliableByteSendStream as AnyUnreliableByteSendStream +from ._streams import AnyUnreliableByteStream as AnyUnreliableByteStream +from ._streams import ByteReceiveStream as ByteReceiveStream +from ._streams import ByteSendStream as ByteSendStream +from ._streams import ByteStream as ByteStream +from ._streams import ByteStreamConnectable as ByteStreamConnectable +from ._streams import Listener as Listener +from ._streams import ObjectReceiveStream as ObjectReceiveStream +from ._streams import ObjectSendStream as ObjectSendStream +from ._streams import ObjectStream as ObjectStream +from ._streams import ObjectStreamConnectable as ObjectStreamConnectable +from ._streams import UnreliableObjectReceiveStream as UnreliableObjectReceiveStream +from ._streams import UnreliableObjectSendStream as UnreliableObjectSendStream +from ._streams import UnreliableObjectStream as UnreliableObjectStream +from ._subprocesses import Process as Process +from ._tasks import TaskGroup as TaskGroup +from ._tasks import TaskStatus as TaskStatus +from ._testing import TestRunner as TestRunner + +# Re-exported here, for backwards compatibility +# isort: off +from .._core._synchronization import ( + CapacityLimiter as CapacityLimiter, + Condition as Condition, + Event as Event, + Lock as Lock, + Semaphore as Semaphore, +) +from .._core._tasks import CancelScope as CancelScope +from ..from_thread import BlockingPortal as BlockingPortal + +# Re-export imports so they look like they live directly in this package +for __value in list(locals().values()): + if getattr(__value, "__module__", "").startswith("anyio.abc."): + __value.__module__ = __name__ + +del __value diff --git a/backend/.venv/Lib/site-packages/anyio/abc/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/abc/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2086e71163f6c012deb62b36d8368d2d4e3afb92 GIT binary patch literal 2361 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/abc/__pycache__/_sockets.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/abc/__pycache__/_sockets.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..413e5e2da949bbe8bc2774b8cd9a4504219fc7e2 GIT binary patch literal 18426 zcmeG@dvFu?nZMQQE!mPEvW;!b+6H5R5CIGh4j6=alNgFk9tx=QZ^6I)_WQjb-}|S3uc)vRc)W)ijzTX8kOE>-~Covr$9L=r__b`lu;p_M2lCza?h%TPe;EwZ-gyJB5wW ziddz;lES8_Bj)rwV^#ht`fZM~v1)%cg)PyVSgpS{=JLB@b^bcQS;MwyeXPOXKw*1y zQLNG57;Ex3#hU%ifU5{sMi<9g{4KF1{v|Qa&rzHs+8S%~w=sm*kL*+@T6l+@#|{%B zm|zxF(Bo47QijBh^lO>?#n~+ zujD%vyocglO8Hg%N(Jww__{n^Ex(%L>k+Rbyer)B8Y7R^{{YX949T!I9cIFd;9uhf zorRS97xspm&Y1jbbz~O_H=iNl#eCCitkUK>ifsYx6238y?V?x?u&sOx-}RbaDZQTJ z+W_Crug{m>K(R{!yNqALugBHU)aj^mlSdO_H!GR@ zg3)MjD9TILzC<+2hp?<fd$e>5mahC^}a=sln}9B0)LJ{bsN zM}Z;egpcFU>ac9smrM$gp|K=?Ku8>qgn2=#D#j1+Ny(AKqJf}V_B}j1(1dl{c#

I4pxf@z^dQF*fSfy@zMzJ!Bd*13K_Q z9Z_foj8w7bfHFTEj8wVjz(68&3{mvkUi4LQX#0T!IISejtUJ`d=ke{qWblX(jA`)Z z!N5U2c{~{12}@fg@Xw4z1U?W-#N#kTJ}gzJsG-DIJRDMvGEfU4$iU#6nHz>9d!8f} z(jjD$Br%^puPKnwU?E9^iXBl7x%!RoN%A_QlHZgezNM(WeED)U^L?qyiPMaQOtL~1q=pe!p_B@}rT`3?)C(V{rRvnY!aG?Q zbwdHGLYmx06<2r<>y8tl7J6S?z^Rbhd)S0TI%SGG?_F-nG-(oT$qKc8SYMduq)s!A z7PUm-eXJW8b}zJFW`2`8n!8%lvUyTB!WC+(5Uj4Hd>iFUe?>b&!-!LDr|_O+7W8eM zWXiWj`!3T)`O@0H>CP@M^r}K(o4SH<0t^GBog@`;PRLRs?3*%98b{1(>B2ji$Bj_M zppb*mu})ZPyJj_YYA=(<(>geh+PwT(rFr_Iy!`56-f2)Kri{-TPcSFQN%jeHf+-no z)s#`wXHmN!Qj;nnQ>G`#4D-@jP3vvyykIRr87QLUg`5FT?=rPU;r*HdGUPN-+jiSg zpcscEQ9hoS@FtJ)9Ku|f7ehj1G?@^%aDo>(kUyNj5Ay<-OmIO?1UAVhCz`Rm40EwD zG06?_T%OZStSpmDnV#H6G!Y6$xu7g}CYJCgM=68kf^jYqPjb+++_Hx|0-aBo0SlZz z7#5IyOtdK#xnU}qxL8Dt1(TtpJzTz_38PYVi84eKFXamEbk|DOh=}b6;~`#Rp?}FJ zSCUNo2X+WT0%RR82=Rnu-qF8*aA1GmKFRuMFgnJ|nHH1@GN{LHBzqw6%vdlQ561XF zK(c{k9OZcdKVh}$kR_9EXJAkNjzP(+02^pI?3b3a0Qyk>z=0iolAafd+LSZ@}8!lKt?pkPvB@~uIBI&V&#PTOY zl9g^w0LzI;R-E$Od91JJ@QH+QOdJh{_`~s$q_`>=3W4}aLXWFL34uSX$os?I<9z)1 z;fEtbhs8*eUj-G81&{FJ;b43`l2{!a3at)chkR1>j*d&t0LaNmIGE%WtgsFG#c_#k zaIB}vypx!#XI5MYT{pGmbaqSKJ2i{WZ~n~YOV;Z(>&|VTZy?s%nZ2(Xzg6+Iit85d ztYgtR{Vyx)XDe5|9=_6(@%CoD`_kThsZ|eO+nur>nqzeiYmVqF)||P`PYOM_2(b@%tNnk_*U=NdjDa=_qKdzORB9eUDG$) zx-8qeCf&Lw)4J}8FWtJ~Gkb4pP&0d>joOxX>bO*Ef2MAK%DMlht?oicwsA$eamCxV z6_=9VK6Uxj8^_*Wz2}|k=Gp45D^F(E??|uTk?Pv{=CIOjwx&H@)1Incnq!%&jyaaC zsmu|!qB3VCcIT%zp4<4cb5_K*eK60#Hryr#L**}Ru9=Zn+ppU? zW?|y{&h2~Yk(=gh;cY8pRL=mg&Oos+nOQg zM_VkrYS@1@`;5CP*|#bU@bOliW!D4jTTAS_R`{1$ZlM$GQM-qwUxbKW=wdNR9zYetCU7_*)<}D^j}G%jGri zo*sp-(j3g~K_=3puw<`K=GwAVV9ggohF`*$6T=*0LDl7j=s55Tr3txGNuN|CPzD61 zNWN92>*UyIlz$Qo9}mihr?^QD;NrfEL`wO7xrkU0Q6Px!F^(L=kH2Z9aUeH5xFEIR@rctT-`r6Z8pr&oRz#!|Y-$#66>qzsBnQ2VHS zM|>;+>{r>f(#}4@nhUgn{I-{lgPyjJwCHj}fj?l?m7&~w+4K4dZa$uD!49+`ti@yr zBvM7uDHK43B$8FeVasxYZeM z4SZB&^lNUkug$b~P4~|{oY8mPsPD+scTVq{skyH26b`6e74bwpVBulrdLS+EM4k=n z!_1ii=hO2nZwLclEa39o(m2k#jj#YRvr>Hqp}av1Et}vE*e^5pK44!UFX&!iU(lZi z#tVKv@cF%{12tJ03LztTV*+X^&shS#C-#h4Qwp`7lIN@r%IU)TqH<+S4ceOFj5)$i zfvKw_=XB@D2%fBxXC!Y*7c$gozoyLZMfM!~T-{j~#%DZZo@6v5EMsURYrjihWoDhk z^F^O>2B;>tjDbx}=yi0arjl`$F}Uft*yozgv0*cs)i3JL>S0EflA6uRa5OKhImu8X zFmGgn;bQ=gD0vYKu9s%==8Lsoz#?G7xPY*a^FlHZ89ly%@=m0}qLYcsTZ2aiDeeo* zd0aMtN}mysh^5Z}xy5Pg4?<%$uUY*ibmwJF&Lp1bg|D z;J7PzxJ2(J%2~u-0OUF^Lpvh+Sl*u|m$qj;o6??5Sx?{Fo<2%%MH9mFO(%pz{{`K7 zJa^wDqfq9uPIwGn!g@$x$|hxDg(u)!#I>20=PCFB{(YwS3O0oM z4paP2cV79c4V~$R&TKKd=4!*M&LN^t24yjQhmg+W{uBtuz~prV>eX-Z0KFk=NK zRA^I;V;z2WVM0avUVz*NN@S8XuZWAnQ&{3@Ot1tU$kW``ty^VQ<1A$;6WoWfoX=r1 zzl7w2Y4R)cj(H=gXwKT(()PB@(!O`>Oqy%>GM!sxg=sTK8Db4?ol+t)%( zXG6--KHJi9@tIeS&Deh0^T>?#!j^2)hBW+lcHeX?N|_hEKi^7iSjN&kTi^8JZZIP) z&38l;m{-kQ-%9esmA1Z(><=GgAT81)poFYRAUi!z#$_%@>9ugqIa#~H-JEDDU1E(; z_%0L>Q8$?;FmOu+JufIZi~^q=6XFv~l%UL$5J>TGYTV|@C!g|gfO+aEw@x?$)rDP< zxJ|-7gdfHPg%)rRAu$S4Zd~9Iha;BR9C8<#RD1{>RFlsFAY#=sWY$n|Ti0x8oMVZx zGKWxZ6F{?un%g?YP=V-Lns-YNpK@c^P7&QHoPwEagPekPhxRV72Mtf7&G`+W#Tg_T zMd6j`%)}Vgxd(+{TtsbJ`4a29}lgn?;j9I8wq)KV@q5@uf4 zsj-T?MmQG3C%ZTI#0_iunaZ%NT-X-hz2J2sU_}KM@`0LXZP-DAhDP z0sX*%;*!B*xD6*DvL+sljB<+IF55cb*To@>!V*KxNL*f29459~Iz;LT4o0D$@OY6& zSTmlU(IAA)=pbZQWlv%7vb9=fiuuLqk!eX&N1m`|zLy#5FJcQLyZi=vB1m-GpTpOM@rRYS1eB1`)<<{i< z0P8`dhx{i>Ht`OU(cjnMcIK9!QWB!@(5&icK0QI}|bWnF{J26(>*4Yi)7-SDswId%wspGP!RQ#7i?+a(GA$lPS+tKef z7D!%*0ft6eu%b-!^_1qv;*pcZgfAqZY!R_jI+4p`r@BDWE<^F47uxOmtvwF~{>XuWI-+L?9iOqqA496RsKRYNPMeP&-3 zbJfcD9Qvy^1Hkzk0+35@3DDDy8l-&M#~CUghMm|Jp4o?d6Wxs zF>tU#U7(E z61h$ux&-Z5~T(gmcOwvhfbx&HOJ^BPdz!9e4B^l`96`lonqM>k6>Pe8FAVuX1QBToolDm(-#Bg2!$m<$!)8E#HE>+h*fuEnmq(o=OkqVgn1pY+SJWywM-qu01 zN|wAi3g$Ra)Nkud20M!5+8jc;>LT1N#K{sG8w|l;{$XW^nM2*aAfaUqUcG`>BAX2u ziz=4Q77{kAr2)2t4QC8~Ge~T!R4Geq^`_Ru6g`acCp}(~cqkFmD7A`D9`Cm)T<9-N z_jhQy#~-Hq<59#5avFXG#Sat<>uv8R5DG)S7UW%tA)PZDcJA zEK(TIKBZ%UtIUeRphifhScs6IEleL(sqG@qLkL@IqfY53b<-`A`jNb?tJXn%WRg{D zz6L$u12(Q)pOtOgDY)4?Ny^#9YRv^T3~=eqCby^;&wyV?zN|&nB{m;7sFDrhKoahZ29D56qeh7c zGtjYszD22qk0*ISxz`GNl|&E3Ut^9H?h8S{K};m#ASuv2E}4!7wi1i`mo=?$LF9T(`^7Q1 z^pbM4&bD`E+c%}*|K|S8<^!4bk7XBsY{q)Cx^8w!`&UoBa_Y-d*+rfis*$0 zF1vW-((&ug4LJj;sn1zR?b7#eF8c@GW0J`Ckz|o2OmdSmr$A>omU1 z0`%o(pO^g}<6B{TqXD3+PR8dkUahJ}xRZebS646yduZx4ZX>3vU5u~Wes#SG;Y}te zqgb;VQGE`2Qr%zF8pUV?tnBCEHLIz-BC^ zVi~Psp+q+0wh9=5DV5DQGy#+UhClHbBwFJbrPM3RAK18S>??c;0<+M%P1yiCf3S%3*clyj=h%`*M=y87hZ#Td?!ZEg@}im+1);Tyyg+$kQ`4Qt)Kj8>Ft+`YPq zkLOR74}X!s;ccQG^v{78+q>Ym4Pe2_49|-e>(g9kCtRBhdbrM`2{Gy6&{6JoyEXgR zFGr@~HyCamc zJaJKfF?nh5Vl=g6UB=awb#$f7T`5P`9TC-@(~H`eFEgC}f}t(%x72X@FF_G7l)eTp z;ZvA=9TJHJ*(m%Ces*GlW|n}w`*LX*gnBeJy!%xwSz=9L7Xl`5Uz&&<09uZX?#wL; za|UR>*W%%s>bJ=|C<5Ae8JU#rLT=pKz ziKqNe&Ts!zA&_$O*0NmLDXNKs2p8Za%SO~9%4_p21U{VWw)8DH+*XpHFBJHQ>RaDG{)1=#>Di2}#n@+c@={lZsaKyEn*K@}QMt{_Wf0j=s*0xBqS@S&JDP-QNeIF4($1j^7g zyy;q`=vU#FCo?Wj*5OH+Jt>DrQLXAZ<`t$z|0M%gPPKX+hhx;JR#yNad;^obLM40? zKT8xQtSDgeB#s6(Xi%7pYWz2+a{%9@CN2VK;x^wlA*g6k2+p_Z469_`iVcvuM zJZ~+hPBj%I&O+vTdI59QT^e219#0U5!|1N&!Uot z5AyFn>z$Olti%FFJy<4QUBa&0OZ791T7N{wz5E_@qvhbIk=}i9TxAZ<$toL$u-)kf z_v;(J-FvzB+Tel^_QPq{!`B8gu7g>}!Ib%6%5m_Ha0*%}qqcn)&}G#&nt{nF9K#v_ zv_@J^S8W)Oc@6@|bC%sUAxL@7Et)N}8*IaEm+$P**xx2VOjIedT~@^QMdD!rRnv)D z1@F`Tj7eyREJ;6~7X`ePE7{>*o(OTdKqLRvX@cB6AiL!J-rCaF75(XL?m5ulo z#G+`E?R*ZQR!q>E7EsE_mo-qV%eNM(=aB<>PhOC@zTynAU3Y+5Ar5n4Z?Pnty(lrZpU6(3T zt#Em@TdvtXyVQMY*_E10E7D8Xr%2t)PELp3MGNxb_n95}q7BVC8^zj5Z9|S$$yE|#&71?V^Luq2 zj5}4ge4fC2{vgxNRHW)W^90`W4>PsQHfE;h5HnwO97fv+zB?m1$%Km{i+?Z@AKJTi#sqYl7dD!v7DRM8@<0 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/abc/__pycache__/_streams.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/abc/__pycache__/_streams.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..208e3793dc73aec3acd15a8cfc0361685cbc91af GIT binary patch literal 9887 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 WGe40x{wQ9dbcufL{7FJ44D(;fCMZAv literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/abc/__pycache__/_tasks.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/abc/__pycache__/_tasks.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..07a52c60e8ca9535014133b574d9d706ed3ace93 GIT binary patch literal 5140 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/abc/__pycache__/_testing.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/abc/__pycache__/_testing.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4cf1e263ab5e7d9df194d426582b7a6d02ea0962 GIT binary patch literal 2836 zcmd5;&2QX96d!xnySCSxex)sqD6uMNwUBNPNPwb(Xrrnsf*c?M1N`$s@cpnF^IjJEM}ah3D5K; z8iuqRvdmaYc+yXUm}UB{6x1LDUzKa|AgiwodhBb;Gu2)3@(6NTgrkgpg!c!85l8U} zEM9RczV54guzaQ&r2O*@zp__-RQPdfWeeZ*t5e$gA#KCgrnLGYt>xFIw8o&`YG&pN z6X}=z7?!-tO&gvYu}6ENAJUWwo7x<7LA+tJZ5F3?m?XWnePf&Pf$ae}c0_$=B4(X0JMF9N+$gZ8nJ0FQs@<_l*>gPFjGb~iPv576?v#EKg1+f1q;^& z8rUzsSz7GeN%)rNQIB=v+o`xrJum6Uke-dpUcyVox0x`0ZY6p z(y2$T0EG|8fbiqMaGcnx@{=%RI@|Hw6e=dGBezY%tR_WWfs-%;{FF3=@9qRC1aqn! zj14EAYh@7Rf+Qf!amDI%(vHh5=rr)bxj;D%XB=fB4%L=xY8Sd0Ep_Fa29frI}IG?*>v#;S9ZxuU%Sy^`U{iv4bEa1jj}-6RPMNvp=sqwM0icdoYE z?FGBsSy$Z^5XFPFHM!guGk)NutI&;eDVJWYaiaz6wf}HCY0InNO-^30!8&)#FF_#E z7q@@|7jI)^m&%bH<>DZ;10Pux!D^YA?z%DbGS|&a*NqatA0ltL?st6}7Mi;2`ibYd z9M5TvHzGcVWFE-{B<~=>#vm(No-{IHk~Baregm>co~ad0ADN0aJFJn~>`>LTxhE$V zh8m0@IeBqdM@}av-WwXonZ!K(yaC*(GPWPiNUot-PtIH&YB0jg6Z6A5ayl{3JU4(V z>`^xNYJ2NwdtI|0pZj!J!SSeW;CM^rh^DN7 z9N;qOnSM3T;V1lku)`~cSO7AtD2nn2x$u-&`{dF-x%E4_wNK{%)U5j}KdjwT|E_(Y NSU-LE4}n3h>0fX#?!f>6 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/abc/_eventloop.py b/backend/.venv/Lib/site-packages/anyio/abc/_eventloop.py new file mode 100644 index 0000000..a99a7ee --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/abc/_eventloop.py @@ -0,0 +1,420 @@ +from __future__ import annotations + +import math +import sys +from abc import ABCMeta, abstractmethod +from collections.abc import AsyncIterator, Awaitable, Callable, Sequence +from contextlib import AbstractContextManager +from os import PathLike +from signal import Signals +from socket import AddressFamily, SocketKind, socket +from typing import ( + IO, + TYPE_CHECKING, + Any, + TypeVar, + Union, + overload, +) + +if sys.version_info >= (3, 11): + from typing import TypeVarTuple, Unpack +else: + from typing_extensions import TypeVarTuple, Unpack + +if sys.version_info >= (3, 10): + from typing import TypeAlias +else: + from typing_extensions import TypeAlias + +if TYPE_CHECKING: + from _typeshed import FileDescriptorLike + + from .._core._synchronization import CapacityLimiter, Event, Lock, Semaphore + from .._core._tasks import CancelScope + from .._core._testing import TaskInfo + from ..from_thread import BlockingPortal + from ._sockets import ( + ConnectedUDPSocket, + ConnectedUNIXDatagramSocket, + IPSockAddrType, + SocketListener, + SocketStream, + UDPSocket, + UNIXDatagramSocket, + UNIXSocketStream, + ) + from ._subprocesses import Process + from ._tasks import TaskGroup + from ._testing import TestRunner + +T_Retval = TypeVar("T_Retval") +PosArgsT = TypeVarTuple("PosArgsT") +StrOrBytesPath: TypeAlias = Union[str, bytes, "PathLike[str]", "PathLike[bytes]"] + + +class AsyncBackend(metaclass=ABCMeta): + @classmethod + @abstractmethod + def run( + cls, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], + args: tuple[Unpack[PosArgsT]], + kwargs: dict[str, Any], + options: dict[str, Any], + ) -> T_Retval: + """ + Run the given coroutine function in an asynchronous event loop. + + The current thread must not be already running an event loop. + + :param func: a coroutine function + :param args: positional arguments to ``func`` + :param kwargs: positional arguments to ``func`` + :param options: keyword arguments to call the backend ``run()`` implementation + with + :return: the return value of the coroutine function + """ + + @classmethod + @abstractmethod + def current_token(cls) -> object: + """ + Return an object that allows other threads to run code inside the event loop. + + :return: a token object, specific to the event loop running in the current + thread + """ + + @classmethod + @abstractmethod + def current_time(cls) -> float: + """ + Return the current value of the event loop's internal clock. + + :return: the clock value (seconds) + """ + + @classmethod + @abstractmethod + def cancelled_exception_class(cls) -> type[BaseException]: + """Return the exception class that is raised in a task if it's cancelled.""" + + @classmethod + @abstractmethod + async def checkpoint(cls) -> None: + """ + Check if the task has been cancelled, and allow rescheduling of other tasks. + + This is effectively the same as running :meth:`checkpoint_if_cancelled` and then + :meth:`cancel_shielded_checkpoint`. + """ + + @classmethod + async def checkpoint_if_cancelled(cls) -> None: + """ + Check if the current task group has been cancelled. + + This will check if the task has been cancelled, but will not allow other tasks + to be scheduled if not. + + """ + if cls.current_effective_deadline() == -math.inf: + await cls.checkpoint() + + @classmethod + async def cancel_shielded_checkpoint(cls) -> None: + """ + Allow the rescheduling of other tasks. + + This will give other tasks the opportunity to run, but without checking if the + current task group has been cancelled, unlike with :meth:`checkpoint`. + + """ + with cls.create_cancel_scope(shield=True): + await cls.sleep(0) + + @classmethod + @abstractmethod + async def sleep(cls, delay: float) -> None: + """ + Pause the current task for the specified duration. + + :param delay: the duration, in seconds + """ + + @classmethod + @abstractmethod + def create_cancel_scope( + cls, *, deadline: float = math.inf, shield: bool = False + ) -> CancelScope: + pass + + @classmethod + @abstractmethod + def current_effective_deadline(cls) -> float: + """ + Return the nearest deadline among all the cancel scopes effective for the + current task. + + :return: + - a clock value from the event loop's internal clock + - ``inf`` if there is no deadline in effect + - ``-inf`` if the current scope has been cancelled + :rtype: float + """ + + @classmethod + @abstractmethod + def create_task_group(cls) -> TaskGroup: + pass + + @classmethod + @abstractmethod + def create_event(cls) -> Event: + pass + + @classmethod + @abstractmethod + def create_lock(cls, *, fast_acquire: bool) -> Lock: + pass + + @classmethod + @abstractmethod + def create_semaphore( + cls, + initial_value: int, + *, + max_value: int | None = None, + fast_acquire: bool = False, + ) -> Semaphore: + pass + + @classmethod + @abstractmethod + def create_capacity_limiter(cls, total_tokens: float) -> CapacityLimiter: + pass + + @classmethod + @abstractmethod + async def run_sync_in_worker_thread( + cls, + func: Callable[[Unpack[PosArgsT]], T_Retval], + args: tuple[Unpack[PosArgsT]], + abandon_on_cancel: bool = False, + limiter: CapacityLimiter | None = None, + ) -> T_Retval: + pass + + @classmethod + @abstractmethod + def check_cancelled(cls) -> None: + pass + + @classmethod + @abstractmethod + def run_async_from_thread( + cls, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], + args: tuple[Unpack[PosArgsT]], + token: object, + ) -> T_Retval: + pass + + @classmethod + @abstractmethod + def run_sync_from_thread( + cls, + func: Callable[[Unpack[PosArgsT]], T_Retval], + args: tuple[Unpack[PosArgsT]], + token: object, + ) -> T_Retval: + pass + + @classmethod + @abstractmethod + def create_blocking_portal(cls) -> BlockingPortal: + pass + + @classmethod + @abstractmethod + async def open_process( + cls, + command: StrOrBytesPath | Sequence[StrOrBytesPath], + *, + stdin: int | IO[Any] | None, + stdout: int | IO[Any] | None, + stderr: int | IO[Any] | None, + **kwargs: Any, + ) -> Process: + pass + + @classmethod + @abstractmethod + def setup_process_pool_exit_at_shutdown(cls, workers: set[Process]) -> None: + pass + + @classmethod + @abstractmethod + async def connect_tcp( + cls, host: str, port: int, local_address: IPSockAddrType | None = None + ) -> SocketStream: + pass + + @classmethod + @abstractmethod + async def connect_unix(cls, path: str | bytes) -> UNIXSocketStream: + pass + + @classmethod + @abstractmethod + def create_tcp_listener(cls, sock: socket) -> SocketListener: + pass + + @classmethod + @abstractmethod + def create_unix_listener(cls, sock: socket) -> SocketListener: + pass + + @classmethod + @abstractmethod + async def create_udp_socket( + cls, + family: AddressFamily, + local_address: IPSockAddrType | None, + remote_address: IPSockAddrType | None, + reuse_port: bool, + ) -> UDPSocket | ConnectedUDPSocket: + pass + + @classmethod + @overload + async def create_unix_datagram_socket( + cls, raw_socket: socket, remote_path: None + ) -> UNIXDatagramSocket: ... + + @classmethod + @overload + async def create_unix_datagram_socket( + cls, raw_socket: socket, remote_path: str | bytes + ) -> ConnectedUNIXDatagramSocket: ... + + @classmethod + @abstractmethod + async def create_unix_datagram_socket( + cls, raw_socket: socket, remote_path: str | bytes | None + ) -> UNIXDatagramSocket | ConnectedUNIXDatagramSocket: + pass + + @classmethod + @abstractmethod + async def getaddrinfo( + cls, + host: bytes | str | None, + port: str | int | None, + *, + family: int | AddressFamily = 0, + type: int | SocketKind = 0, + proto: int = 0, + flags: int = 0, + ) -> Sequence[ + tuple[ + AddressFamily, + SocketKind, + int, + str, + tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes], + ] + ]: + pass + + @classmethod + @abstractmethod + async def getnameinfo( + cls, sockaddr: IPSockAddrType, flags: int = 0 + ) -> tuple[str, str]: + pass + + @classmethod + @abstractmethod + async def wait_readable(cls, obj: FileDescriptorLike) -> None: + pass + + @classmethod + @abstractmethod + async def wait_writable(cls, obj: FileDescriptorLike) -> None: + pass + + @classmethod + @abstractmethod + def notify_closing(cls, obj: FileDescriptorLike) -> None: + pass + + @classmethod + @abstractmethod + async def wrap_listener_socket(cls, sock: socket) -> SocketListener: + pass + + @classmethod + @abstractmethod + async def wrap_stream_socket(cls, sock: socket) -> SocketStream: + pass + + @classmethod + @abstractmethod + async def wrap_unix_stream_socket(cls, sock: socket) -> UNIXSocketStream: + pass + + @classmethod + @abstractmethod + async def wrap_udp_socket(cls, sock: socket) -> UDPSocket: + pass + + @classmethod + @abstractmethod + async def wrap_connected_udp_socket(cls, sock: socket) -> ConnectedUDPSocket: + pass + + @classmethod + @abstractmethod + async def wrap_unix_datagram_socket(cls, sock: socket) -> UNIXDatagramSocket: + pass + + @classmethod + @abstractmethod + async def wrap_connected_unix_datagram_socket( + cls, sock: socket + ) -> ConnectedUNIXDatagramSocket: + pass + + @classmethod + @abstractmethod + def current_default_thread_limiter(cls) -> CapacityLimiter: + pass + + @classmethod + @abstractmethod + def open_signal_receiver( + cls, *signals: Signals + ) -> AbstractContextManager[AsyncIterator[Signals]]: + pass + + @classmethod + @abstractmethod + def get_current_task(cls) -> TaskInfo: + pass + + @classmethod + @abstractmethod + def get_running_tasks(cls) -> Sequence[TaskInfo]: + pass + + @classmethod + @abstractmethod + async def wait_all_tasks_blocked(cls) -> None: + pass + + @classmethod + @abstractmethod + def create_test_runner(cls, options: dict[str, Any]) -> TestRunner: + pass diff --git a/backend/.venv/Lib/site-packages/anyio/abc/_resources.py b/backend/.venv/Lib/site-packages/anyio/abc/_resources.py new file mode 100644 index 0000000..10df115 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/abc/_resources.py @@ -0,0 +1,33 @@ +from __future__ import annotations + +from abc import ABCMeta, abstractmethod +from types import TracebackType +from typing import TypeVar + +T = TypeVar("T") + + +class AsyncResource(metaclass=ABCMeta): + """ + Abstract base class for all closeable asynchronous resources. + + Works as an asynchronous context manager which returns the instance itself on enter, + and calls :meth:`aclose` on exit. + """ + + __slots__ = () + + async def __aenter__(self: T) -> T: + return self + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + await self.aclose() + + @abstractmethod + async def aclose(self) -> None: + """Close the resource.""" diff --git a/backend/.venv/Lib/site-packages/anyio/abc/_sockets.py b/backend/.venv/Lib/site-packages/anyio/abc/_sockets.py new file mode 100644 index 0000000..3ff60d4 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/abc/_sockets.py @@ -0,0 +1,405 @@ +from __future__ import annotations + +import errno +import socket +import sys +from abc import abstractmethod +from collections.abc import Callable, Collection, Mapping +from contextlib import AsyncExitStack +from io import IOBase +from ipaddress import IPv4Address, IPv6Address +from socket import AddressFamily +from typing import Any, TypeVar, Union + +from .._core._eventloop import get_async_backend +from .._core._typedattr import ( + TypedAttributeProvider, + TypedAttributeSet, + typed_attribute, +) +from ._streams import ByteStream, Listener, UnreliableObjectStream +from ._tasks import TaskGroup + +if sys.version_info >= (3, 10): + from typing import TypeAlias +else: + from typing_extensions import TypeAlias + +IPAddressType: TypeAlias = Union[str, IPv4Address, IPv6Address] +IPSockAddrType: TypeAlias = tuple[str, int] +SockAddrType: TypeAlias = Union[IPSockAddrType, str] +UDPPacketType: TypeAlias = tuple[bytes, IPSockAddrType] +UNIXDatagramPacketType: TypeAlias = tuple[bytes, str] +T_Retval = TypeVar("T_Retval") + + +def _validate_socket( + sock_or_fd: socket.socket | int, + sock_type: socket.SocketKind, + addr_family: socket.AddressFamily = socket.AF_UNSPEC, + *, + require_connected: bool = False, + require_bound: bool = False, +) -> socket.socket: + if isinstance(sock_or_fd, int): + try: + sock = socket.socket(fileno=sock_or_fd) + except OSError as exc: + if exc.errno == errno.ENOTSOCK: + raise ValueError( + "the file descriptor does not refer to a socket" + ) from exc + elif require_connected: + raise ValueError("the socket must be connected") from exc + elif require_bound: + raise ValueError("the socket must be bound to a local address") from exc + else: + raise + elif isinstance(sock_or_fd, socket.socket): + sock = sock_or_fd + else: + raise TypeError( + f"expected an int or socket, got {type(sock_or_fd).__qualname__} instead" + ) + + try: + if require_connected: + try: + sock.getpeername() + except OSError as exc: + raise ValueError("the socket must be connected") from exc + + if require_bound: + try: + if sock.family in (socket.AF_INET, socket.AF_INET6): + bound_addr = sock.getsockname()[1] + else: + bound_addr = sock.getsockname() + except OSError: + bound_addr = None + + if not bound_addr: + raise ValueError("the socket must be bound to a local address") + + if addr_family != socket.AF_UNSPEC and sock.family != addr_family: + raise ValueError( + f"address family mismatch: expected {addr_family.name}, got " + f"{sock.family.name}" + ) + + if sock.type != sock_type: + raise ValueError( + f"socket type mismatch: expected {sock_type.name}, got {sock.type.name}" + ) + except BaseException: + # Avoid ResourceWarning from the locally constructed socket object + if isinstance(sock_or_fd, int): + sock.detach() + + raise + + sock.setblocking(False) + return sock + + +class SocketAttribute(TypedAttributeSet): + """ + .. attribute:: family + :type: socket.AddressFamily + + the address family of the underlying socket + + .. attribute:: local_address + :type: tuple[str, int] | str + + the local address the underlying socket is connected to + + .. attribute:: local_port + :type: int + + for IP based sockets, the local port the underlying socket is bound to + + .. attribute:: raw_socket + :type: socket.socket + + the underlying stdlib socket object + + .. attribute:: remote_address + :type: tuple[str, int] | str + + the remote address the underlying socket is connected to + + .. attribute:: remote_port + :type: int + + for IP based sockets, the remote port the underlying socket is connected to + """ + + family: AddressFamily = typed_attribute() + local_address: SockAddrType = typed_attribute() + local_port: int = typed_attribute() + raw_socket: socket.socket = typed_attribute() + remote_address: SockAddrType = typed_attribute() + remote_port: int = typed_attribute() + + +class _SocketProvider(TypedAttributeProvider): + @property + def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: + from .._core._sockets import convert_ipv6_sockaddr as convert + + attributes: dict[Any, Callable[[], Any]] = { + SocketAttribute.family: lambda: self._raw_socket.family, + SocketAttribute.local_address: lambda: convert( + self._raw_socket.getsockname() + ), + SocketAttribute.raw_socket: lambda: self._raw_socket, + } + try: + peername: tuple[str, int] | None = convert(self._raw_socket.getpeername()) + except OSError: + peername = None + + # Provide the remote address for connected sockets + if peername is not None: + attributes[SocketAttribute.remote_address] = lambda: peername + + # Provide local and remote ports for IP based sockets + if self._raw_socket.family in (AddressFamily.AF_INET, AddressFamily.AF_INET6): + attributes[SocketAttribute.local_port] = ( + lambda: self._raw_socket.getsockname()[1] + ) + if peername is not None: + remote_port = peername[1] + attributes[SocketAttribute.remote_port] = lambda: remote_port + + return attributes + + @property + @abstractmethod + def _raw_socket(self) -> socket.socket: + pass + + +class SocketStream(ByteStream, _SocketProvider): + """ + Transports bytes over a socket. + + Supports all relevant extra attributes from :class:`~SocketAttribute`. + """ + + @classmethod + async def from_socket(cls, sock_or_fd: socket.socket | int) -> SocketStream: + """ + Wrap an existing socket object or file descriptor as a socket stream. + + The newly created socket wrapper takes ownership of the socket being passed in. + The existing socket must already be connected. + + :param sock_or_fd: a socket object or file descriptor + :return: a socket stream + + """ + sock = _validate_socket(sock_or_fd, socket.SOCK_STREAM, require_connected=True) + return await get_async_backend().wrap_stream_socket(sock) + + +class UNIXSocketStream(SocketStream): + @classmethod + async def from_socket(cls, sock_or_fd: socket.socket | int) -> UNIXSocketStream: + """ + Wrap an existing socket object or file descriptor as a UNIX socket stream. + + The newly created socket wrapper takes ownership of the socket being passed in. + The existing socket must already be connected. + + :param sock_or_fd: a socket object or file descriptor + :return: a UNIX socket stream + + """ + sock = _validate_socket( + sock_or_fd, socket.SOCK_STREAM, socket.AF_UNIX, require_connected=True + ) + return await get_async_backend().wrap_unix_stream_socket(sock) + + @abstractmethod + async def send_fds(self, message: bytes, fds: Collection[int | IOBase]) -> None: + """ + Send file descriptors along with a message to the peer. + + :param message: a non-empty bytestring + :param fds: a collection of files (either numeric file descriptors or open file + or socket objects) + """ + + @abstractmethod + async def receive_fds(self, msglen: int, maxfds: int) -> tuple[bytes, list[int]]: + """ + Receive file descriptors along with a message from the peer. + + :param msglen: length of the message to expect from the peer + :param maxfds: maximum number of file descriptors to expect from the peer + :return: a tuple of (message, file descriptors) + """ + + +class SocketListener(Listener[SocketStream], _SocketProvider): + """ + Listens to incoming socket connections. + + Supports all relevant extra attributes from :class:`~SocketAttribute`. + """ + + @classmethod + async def from_socket( + cls, + sock_or_fd: socket.socket | int, + ) -> SocketListener: + """ + Wrap an existing socket object or file descriptor as a socket listener. + + The newly created listener takes ownership of the socket being passed in. + + :param sock_or_fd: a socket object or file descriptor + :return: a socket listener + + """ + sock = _validate_socket(sock_or_fd, socket.SOCK_STREAM, require_bound=True) + return await get_async_backend().wrap_listener_socket(sock) + + @abstractmethod + async def accept(self) -> SocketStream: + """Accept an incoming connection.""" + + async def serve( + self, + handler: Callable[[SocketStream], Any], + task_group: TaskGroup | None = None, + ) -> None: + from .. import create_task_group + + async with AsyncExitStack() as stack: + if task_group is None: + task_group = await stack.enter_async_context(create_task_group()) + + while True: + stream = await self.accept() + task_group.start_soon(handler, stream) + + +class UDPSocket(UnreliableObjectStream[UDPPacketType], _SocketProvider): + """ + Represents an unconnected UDP socket. + + Supports all relevant extra attributes from :class:`~SocketAttribute`. + """ + + @classmethod + async def from_socket(cls, sock_or_fd: socket.socket | int) -> UDPSocket: + """ + Wrap an existing socket object or file descriptor as a UDP socket. + + The newly created socket wrapper takes ownership of the socket being passed in. + The existing socket must be bound to a local address. + + :param sock_or_fd: a socket object or file descriptor + :return: a UDP socket + + """ + sock = _validate_socket(sock_or_fd, socket.SOCK_DGRAM, require_bound=True) + return await get_async_backend().wrap_udp_socket(sock) + + async def sendto(self, data: bytes, host: str, port: int) -> None: + """ + Alias for :meth:`~.UnreliableObjectSendStream.send` ((data, (host, port))). + + """ + return await self.send((data, (host, port))) + + +class ConnectedUDPSocket(UnreliableObjectStream[bytes], _SocketProvider): + """ + Represents an connected UDP socket. + + Supports all relevant extra attributes from :class:`~SocketAttribute`. + """ + + @classmethod + async def from_socket(cls, sock_or_fd: socket.socket | int) -> ConnectedUDPSocket: + """ + Wrap an existing socket object or file descriptor as a connected UDP socket. + + The newly created socket wrapper takes ownership of the socket being passed in. + The existing socket must already be connected. + + :param sock_or_fd: a socket object or file descriptor + :return: a connected UDP socket + + """ + sock = _validate_socket( + sock_or_fd, + socket.SOCK_DGRAM, + require_connected=True, + ) + return await get_async_backend().wrap_connected_udp_socket(sock) + + +class UNIXDatagramSocket( + UnreliableObjectStream[UNIXDatagramPacketType], _SocketProvider +): + """ + Represents an unconnected Unix datagram socket. + + Supports all relevant extra attributes from :class:`~SocketAttribute`. + """ + + @classmethod + async def from_socket( + cls, + sock_or_fd: socket.socket | int, + ) -> UNIXDatagramSocket: + """ + Wrap an existing socket object or file descriptor as a UNIX datagram + socket. + + The newly created socket wrapper takes ownership of the socket being passed in. + + :param sock_or_fd: a socket object or file descriptor + :return: a UNIX datagram socket + + """ + sock = _validate_socket(sock_or_fd, socket.SOCK_DGRAM, socket.AF_UNIX) + return await get_async_backend().wrap_unix_datagram_socket(sock) + + async def sendto(self, data: bytes, path: str) -> None: + """Alias for :meth:`~.UnreliableObjectSendStream.send` ((data, path)).""" + return await self.send((data, path)) + + +class ConnectedUNIXDatagramSocket(UnreliableObjectStream[bytes], _SocketProvider): + """ + Represents a connected Unix datagram socket. + + Supports all relevant extra attributes from :class:`~SocketAttribute`. + """ + + @classmethod + async def from_socket( + cls, + sock_or_fd: socket.socket | int, + ) -> ConnectedUNIXDatagramSocket: + """ + Wrap an existing socket object or file descriptor as a connected UNIX datagram + socket. + + The newly created socket wrapper takes ownership of the socket being passed in. + The existing socket must already be connected. + + :param sock_or_fd: a socket object or file descriptor + :return: a connected UNIX datagram socket + + """ + sock = _validate_socket( + sock_or_fd, socket.SOCK_DGRAM, socket.AF_UNIX, require_connected=True + ) + return await get_async_backend().wrap_connected_unix_datagram_socket(sock) diff --git a/backend/.venv/Lib/site-packages/anyio/abc/_streams.py b/backend/.venv/Lib/site-packages/anyio/abc/_streams.py new file mode 100644 index 0000000..369df3f --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/abc/_streams.py @@ -0,0 +1,239 @@ +from __future__ import annotations + +import sys +from abc import ABCMeta, abstractmethod +from collections.abc import Callable +from typing import Any, Generic, TypeVar, Union + +from .._core._exceptions import EndOfStream +from .._core._typedattr import TypedAttributeProvider +from ._resources import AsyncResource +from ._tasks import TaskGroup + +if sys.version_info >= (3, 10): + from typing import TypeAlias +else: + from typing_extensions import TypeAlias + +T_Item = TypeVar("T_Item") +T_co = TypeVar("T_co", covariant=True) +T_contra = TypeVar("T_contra", contravariant=True) + + +class UnreliableObjectReceiveStream( + Generic[T_co], AsyncResource, TypedAttributeProvider +): + """ + An interface for receiving objects. + + This interface makes no guarantees that the received messages arrive in the order in + which they were sent, or that no messages are missed. + + Asynchronously iterating over objects of this type will yield objects matching the + given type parameter. + """ + + def __aiter__(self) -> UnreliableObjectReceiveStream[T_co]: + return self + + async def __anext__(self) -> T_co: + try: + return await self.receive() + except EndOfStream: + raise StopAsyncIteration from None + + @abstractmethod + async def receive(self) -> T_co: + """ + Receive the next item. + + :raises ~anyio.ClosedResourceError: if the receive stream has been explicitly + closed + :raises ~anyio.EndOfStream: if this stream has been closed from the other end + :raises ~anyio.BrokenResourceError: if this stream has been rendered unusable + due to external causes + """ + + +class UnreliableObjectSendStream( + Generic[T_contra], AsyncResource, TypedAttributeProvider +): + """ + An interface for sending objects. + + This interface makes no guarantees that the messages sent will reach the + recipient(s) in the same order in which they were sent, or at all. + """ + + @abstractmethod + async def send(self, item: T_contra) -> None: + """ + Send an item to the peer(s). + + :param item: the item to send + :raises ~anyio.ClosedResourceError: if the send stream has been explicitly + closed + :raises ~anyio.BrokenResourceError: if this stream has been rendered unusable + due to external causes + """ + + +class UnreliableObjectStream( + UnreliableObjectReceiveStream[T_Item], UnreliableObjectSendStream[T_Item] +): + """ + A bidirectional message stream which does not guarantee the order or reliability of + message delivery. + """ + + +class ObjectReceiveStream(UnreliableObjectReceiveStream[T_co]): + """ + A receive message stream which guarantees that messages are received in the same + order in which they were sent, and that no messages are missed. + """ + + +class ObjectSendStream(UnreliableObjectSendStream[T_contra]): + """ + A send message stream which guarantees that messages are delivered in the same order + in which they were sent, without missing any messages in the middle. + """ + + +class ObjectStream( + ObjectReceiveStream[T_Item], + ObjectSendStream[T_Item], + UnreliableObjectStream[T_Item], +): + """ + A bidirectional message stream which guarantees the order and reliability of message + delivery. + """ + + @abstractmethod + async def send_eof(self) -> None: + """ + Send an end-of-file indication to the peer. + + You should not try to send any further data to this stream after calling this + method. This method is idempotent (does nothing on successive calls). + """ + + +class ByteReceiveStream(AsyncResource, TypedAttributeProvider): + """ + An interface for receiving bytes from a single peer. + + Iterating this byte stream will yield a byte string of arbitrary length, but no more + than 65536 bytes. + """ + + def __aiter__(self) -> ByteReceiveStream: + return self + + async def __anext__(self) -> bytes: + try: + return await self.receive() + except EndOfStream: + raise StopAsyncIteration from None + + @abstractmethod + async def receive(self, max_bytes: int = 65536) -> bytes: + """ + Receive at most ``max_bytes`` bytes from the peer. + + .. note:: Implementers of this interface should not return an empty + :class:`bytes` object, and users should ignore them. + + :param max_bytes: maximum number of bytes to receive + :return: the received bytes + :raises ~anyio.EndOfStream: if this stream has been closed from the other end + """ + + +class ByteSendStream(AsyncResource, TypedAttributeProvider): + """An interface for sending bytes to a single peer.""" + + @abstractmethod + async def send(self, item: bytes) -> None: + """ + Send the given bytes to the peer. + + :param item: the bytes to send + """ + + +class ByteStream(ByteReceiveStream, ByteSendStream): + """A bidirectional byte stream.""" + + @abstractmethod + async def send_eof(self) -> None: + """ + Send an end-of-file indication to the peer. + + You should not try to send any further data to this stream after calling this + method. This method is idempotent (does nothing on successive calls). + """ + + +#: Type alias for all unreliable bytes-oriented receive streams. +AnyUnreliableByteReceiveStream: TypeAlias = Union[ + UnreliableObjectReceiveStream[bytes], ByteReceiveStream +] +#: Type alias for all unreliable bytes-oriented send streams. +AnyUnreliableByteSendStream: TypeAlias = Union[ + UnreliableObjectSendStream[bytes], ByteSendStream +] +#: Type alias for all unreliable bytes-oriented streams. +AnyUnreliableByteStream: TypeAlias = Union[UnreliableObjectStream[bytes], ByteStream] +#: Type alias for all bytes-oriented receive streams. +AnyByteReceiveStream: TypeAlias = Union[ObjectReceiveStream[bytes], ByteReceiveStream] +#: Type alias for all bytes-oriented send streams. +AnyByteSendStream: TypeAlias = Union[ObjectSendStream[bytes], ByteSendStream] +#: Type alias for all bytes-oriented streams. +AnyByteStream: TypeAlias = Union[ObjectStream[bytes], ByteStream] + + +class Listener(Generic[T_co], AsyncResource, TypedAttributeProvider): + """An interface for objects that let you accept incoming connections.""" + + @abstractmethod + async def serve( + self, handler: Callable[[T_co], Any], task_group: TaskGroup | None = None + ) -> None: + """ + Accept incoming connections as they come in and start tasks to handle them. + + :param handler: a callable that will be used to handle each accepted connection + :param task_group: the task group that will be used to start tasks for handling + each accepted connection (if omitted, an ad-hoc task group will be created) + """ + + +class ObjectStreamConnectable(Generic[T_co], metaclass=ABCMeta): + @abstractmethod + async def connect(self) -> ObjectStream[T_co]: + """ + Connect to the remote endpoint. + + :return: an object stream connected to the remote end + :raises ConnectionFailed: if the connection fails + """ + + +class ByteStreamConnectable(metaclass=ABCMeta): + @abstractmethod + async def connect(self) -> ByteStream: + """ + Connect to the remote endpoint. + + :return: a bytestream connected to the remote end + :raises ConnectionFailed: if the connection fails + """ + + +#: Type alias for all connectables returning bytestreams or bytes-oriented object streams +AnyByteStreamConnectable: TypeAlias = Union[ + ObjectStreamConnectable[bytes], ByteStreamConnectable +] diff --git a/backend/.venv/Lib/site-packages/anyio/abc/_subprocesses.py b/backend/.venv/Lib/site-packages/anyio/abc/_subprocesses.py new file mode 100644 index 0000000..ce0564c --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/abc/_subprocesses.py @@ -0,0 +1,79 @@ +from __future__ import annotations + +from abc import abstractmethod +from signal import Signals + +from ._resources import AsyncResource +from ._streams import ByteReceiveStream, ByteSendStream + + +class Process(AsyncResource): + """An asynchronous version of :class:`subprocess.Popen`.""" + + @abstractmethod + async def wait(self) -> int: + """ + Wait until the process exits. + + :return: the exit code of the process + """ + + @abstractmethod + def terminate(self) -> None: + """ + Terminates the process, gracefully if possible. + + On Windows, this calls ``TerminateProcess()``. + On POSIX systems, this sends ``SIGTERM`` to the process. + + .. seealso:: :meth:`subprocess.Popen.terminate` + """ + + @abstractmethod + def kill(self) -> None: + """ + Kills the process. + + On Windows, this calls ``TerminateProcess()``. + On POSIX systems, this sends ``SIGKILL`` to the process. + + .. seealso:: :meth:`subprocess.Popen.kill` + """ + + @abstractmethod + def send_signal(self, signal: Signals) -> None: + """ + Send a signal to the subprocess. + + .. seealso:: :meth:`subprocess.Popen.send_signal` + + :param signal: the signal number (e.g. :data:`signal.SIGHUP`) + """ + + @property + @abstractmethod + def pid(self) -> int: + """The process ID of the process.""" + + @property + @abstractmethod + def returncode(self) -> int | None: + """ + The return code of the process. If the process has not yet terminated, this will + be ``None``. + """ + + @property + @abstractmethod + def stdin(self) -> ByteSendStream | None: + """The stream for the standard input of the process.""" + + @property + @abstractmethod + def stdout(self) -> ByteReceiveStream | None: + """The stream for the standard output of the process.""" + + @property + @abstractmethod + def stderr(self) -> ByteReceiveStream | None: + """The stream for the standard error output of the process.""" diff --git a/backend/.venv/Lib/site-packages/anyio/abc/_tasks.py b/backend/.venv/Lib/site-packages/anyio/abc/_tasks.py new file mode 100644 index 0000000..516b3ec --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/abc/_tasks.py @@ -0,0 +1,117 @@ +from __future__ import annotations + +import sys +from abc import ABCMeta, abstractmethod +from collections.abc import Awaitable, Callable +from types import TracebackType +from typing import TYPE_CHECKING, Any, Protocol, overload + +if sys.version_info >= (3, 13): + from typing import TypeVar +else: + from typing_extensions import TypeVar + +if sys.version_info >= (3, 11): + from typing import TypeVarTuple, Unpack +else: + from typing_extensions import TypeVarTuple, Unpack + +if TYPE_CHECKING: + from .._core._tasks import CancelScope + +T_Retval = TypeVar("T_Retval") +T_contra = TypeVar("T_contra", contravariant=True, default=None) +PosArgsT = TypeVarTuple("PosArgsT") + + +class TaskStatus(Protocol[T_contra]): + @overload + def started(self: TaskStatus[None]) -> None: ... + + @overload + def started(self, value: T_contra) -> None: ... + + def started(self, value: T_contra | None = None) -> None: + """ + Signal that the task has started. + + :param value: object passed back to the starter of the task + """ + + +class TaskGroup(metaclass=ABCMeta): + """ + Groups several asynchronous tasks together. + + :ivar cancel_scope: the cancel scope inherited by all child tasks + :vartype cancel_scope: CancelScope + + .. note:: On asyncio, support for eager task factories is considered to be + **experimental**. In particular, they don't follow the usual semantics of new + tasks being scheduled on the next iteration of the event loop, and may thus + cause unexpected behavior in code that wasn't written with such semantics in + mind. + """ + + cancel_scope: CancelScope + + @abstractmethod + def start_soon( + self, + func: Callable[[Unpack[PosArgsT]], Awaitable[Any]], + *args: Unpack[PosArgsT], + name: object = None, + ) -> None: + """ + Start a new task in this task group. + + :param func: a coroutine function + :param args: positional arguments to call the function with + :param name: name of the task, for the purposes of introspection and debugging + + .. versionadded:: 3.0 + """ + + @abstractmethod + async def start( + self, + func: Callable[..., Awaitable[Any]], + *args: object, + name: object = None, + ) -> Any: + """ + Start a new task and wait until it signals for readiness. + + The target callable must accept a keyword argument ``task_status`` (of type + :class:`TaskStatus`). Awaiting on this method will return whatever was passed to + ``task_status.started()`` (``None`` by default). + + .. note:: The :class:`TaskStatus` class is generic, and the type argument should + indicate the type of the value that will be passed to + ``task_status.started()``. + + :param func: a coroutine function that accepts the ``task_status`` keyword + argument + :param args: positional arguments to call the function with + :param name: an optional name for the task, for introspection and debugging + :return: the value passed to ``task_status.started()`` + :raises RuntimeError: if the task finishes without calling + ``task_status.started()`` + + .. seealso:: :ref:`start_initialize` + + .. versionadded:: 3.0 + """ + + @abstractmethod + async def __aenter__(self) -> TaskGroup: + """Enter the task group context and allow starting new tasks.""" + + @abstractmethod + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> bool: + """Exit the task group context waiting for all tasks to finish.""" diff --git a/backend/.venv/Lib/site-packages/anyio/abc/_testing.py b/backend/.venv/Lib/site-packages/anyio/abc/_testing.py new file mode 100644 index 0000000..7c50ed7 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/abc/_testing.py @@ -0,0 +1,65 @@ +from __future__ import annotations + +import types +from abc import ABCMeta, abstractmethod +from collections.abc import AsyncGenerator, Callable, Coroutine, Iterable +from typing import Any, TypeVar + +_T = TypeVar("_T") + + +class TestRunner(metaclass=ABCMeta): + """ + Encapsulates a running event loop. Every call made through this object will use the + same event loop. + """ + + def __enter__(self) -> TestRunner: + return self + + @abstractmethod + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: types.TracebackType | None, + ) -> bool | None: ... + + @abstractmethod + def run_asyncgen_fixture( + self, + fixture_func: Callable[..., AsyncGenerator[_T, Any]], + kwargs: dict[str, Any], + ) -> Iterable[_T]: + """ + Run an async generator fixture. + + :param fixture_func: the fixture function + :param kwargs: keyword arguments to call the fixture function with + :return: an iterator yielding the value yielded from the async generator + """ + + @abstractmethod + def run_fixture( + self, + fixture_func: Callable[..., Coroutine[Any, Any, _T]], + kwargs: dict[str, Any], + ) -> _T: + """ + Run an async fixture. + + :param fixture_func: the fixture function + :param kwargs: keyword arguments to call the fixture function with + :return: the return value of the fixture function + """ + + @abstractmethod + def run_test( + self, test_func: Callable[..., Coroutine[Any, Any, Any]], kwargs: dict[str, Any] + ) -> None: + """ + Run an async test function. + + :param test_func: the test function + :param kwargs: keyword arguments to call the test function with + """ diff --git a/backend/.venv/Lib/site-packages/anyio/from_thread.py b/backend/.venv/Lib/site-packages/anyio/from_thread.py new file mode 100644 index 0000000..f8fb99e --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/from_thread.py @@ -0,0 +1,570 @@ +from __future__ import annotations + +__all__ = ( + "BlockingPortal", + "BlockingPortalProvider", + "check_cancelled", + "run", + "run_sync", + "start_blocking_portal", +) + +import sys +from collections.abc import Awaitable, Callable, Generator +from concurrent.futures import Future +from contextlib import ( + AbstractAsyncContextManager, + AbstractContextManager, + contextmanager, +) +from dataclasses import dataclass, field +from inspect import isawaitable +from threading import Lock, Thread, current_thread, get_ident +from types import TracebackType +from typing import ( + Any, + Generic, + TypeVar, + cast, + overload, +) + +from ._core._eventloop import ( + get_async_backend, + get_cancelled_exc_class, + threadlocals, +) +from ._core._eventloop import run as run_eventloop +from ._core._exceptions import NoEventLoopError +from ._core._synchronization import Event +from ._core._tasks import CancelScope, create_task_group +from .abc._tasks import TaskStatus +from .lowlevel import EventLoopToken + +if sys.version_info >= (3, 11): + from typing import TypeVarTuple, Unpack +else: + from typing_extensions import TypeVarTuple, Unpack + +T_Retval = TypeVar("T_Retval") +T_co = TypeVar("T_co", covariant=True) +PosArgsT = TypeVarTuple("PosArgsT") + + +def _token_or_error(token: EventLoopToken | None) -> EventLoopToken: + if token is not None: + return token + + try: + return threadlocals.current_token + except AttributeError: + raise NoEventLoopError( + "Not running inside an AnyIO worker thread, and no event loop token was " + "provided" + ) from None + + +def run( + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], + *args: Unpack[PosArgsT], + token: EventLoopToken | None = None, +) -> T_Retval: + """ + Call a coroutine function from a worker thread. + + :param func: a coroutine function + :param args: positional arguments for the callable + :param token: an event loop token to use to get back to the event loop thread + (required if calling this function from outside an AnyIO worker thread) + :return: the return value of the coroutine function + :raises MissingTokenError: if no token was provided and called from outside an + AnyIO worker thread + :raises RunFinishedError: if the event loop tied to ``token`` is no longer running + + .. versionchanged:: 4.11.0 + Added the ``token`` parameter. + + """ + explicit_token = token is not None + token = _token_or_error(token) + return token.backend_class.run_async_from_thread( + func, args, token=token.native_token if explicit_token else None + ) + + +def run_sync( + func: Callable[[Unpack[PosArgsT]], T_Retval], + *args: Unpack[PosArgsT], + token: EventLoopToken | None = None, +) -> T_Retval: + """ + Call a function in the event loop thread from a worker thread. + + :param func: a callable + :param args: positional arguments for the callable + :param token: an event loop token to use to get back to the event loop thread + (required if calling this function from outside an AnyIO worker thread) + :return: the return value of the callable + :raises MissingTokenError: if no token was provided and called from outside an + AnyIO worker thread + :raises RunFinishedError: if the event loop tied to ``token`` is no longer running + + .. versionchanged:: 4.11.0 + Added the ``token`` parameter. + + """ + explicit_token = token is not None + token = _token_or_error(token) + return token.backend_class.run_sync_from_thread( + func, args, token=token.native_token if explicit_token else None + ) + + +class _BlockingAsyncContextManager(Generic[T_co], AbstractContextManager): + _enter_future: Future[T_co] + _exit_future: Future[bool | None] + _exit_event: Event + _exit_exc_info: tuple[ + type[BaseException] | None, BaseException | None, TracebackType | None + ] = (None, None, None) + + def __init__( + self, async_cm: AbstractAsyncContextManager[T_co], portal: BlockingPortal + ): + self._async_cm = async_cm + self._portal = portal + + async def run_async_cm(self) -> bool | None: + try: + self._exit_event = Event() + value = await self._async_cm.__aenter__() + except BaseException as exc: + self._enter_future.set_exception(exc) + raise + else: + self._enter_future.set_result(value) + + try: + # Wait for the sync context manager to exit. + # This next statement can raise `get_cancelled_exc_class()` if + # something went wrong in a task group in this async context + # manager. + await self._exit_event.wait() + finally: + # In case of cancellation, it could be that we end up here before + # `_BlockingAsyncContextManager.__exit__` is called, and an + # `_exit_exc_info` has been set. + result = await self._async_cm.__aexit__(*self._exit_exc_info) + + return result + + def __enter__(self) -> T_co: + self._enter_future = Future() + self._exit_future = self._portal.start_task_soon(self.run_async_cm) + return self._enter_future.result() + + def __exit__( + self, + __exc_type: type[BaseException] | None, + __exc_value: BaseException | None, + __traceback: TracebackType | None, + ) -> bool | None: + self._exit_exc_info = __exc_type, __exc_value, __traceback + self._portal.call(self._exit_event.set) + return self._exit_future.result() + + +class _BlockingPortalTaskStatus(TaskStatus): + def __init__(self, future: Future): + self._future = future + + def started(self, value: object = None) -> None: + self._future.set_result(value) + + +class BlockingPortal: + """An object that lets external threads run code in an asynchronous event loop.""" + + def __new__(cls) -> BlockingPortal: + return get_async_backend().create_blocking_portal() + + def __init__(self) -> None: + self._event_loop_thread_id: int | None = get_ident() + self._stop_event = Event() + self._task_group = create_task_group() + self._cancelled_exc_class = get_cancelled_exc_class() + + async def __aenter__(self) -> BlockingPortal: + await self._task_group.__aenter__() + return self + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> bool: + await self.stop() + return await self._task_group.__aexit__(exc_type, exc_val, exc_tb) + + def _check_running(self) -> None: + if self._event_loop_thread_id is None: + raise RuntimeError("This portal is not running") + if self._event_loop_thread_id == get_ident(): + raise RuntimeError( + "This method cannot be called from the event loop thread" + ) + + async def sleep_until_stopped(self) -> None: + """Sleep until :meth:`stop` is called.""" + await self._stop_event.wait() + + async def stop(self, cancel_remaining: bool = False) -> None: + """ + Signal the portal to shut down. + + This marks the portal as no longer accepting new calls and exits from + :meth:`sleep_until_stopped`. + + :param cancel_remaining: ``True`` to cancel all the remaining tasks, ``False`` + to let them finish before returning + + """ + self._event_loop_thread_id = None + self._stop_event.set() + if cancel_remaining: + self._task_group.cancel_scope.cancel("the blocking portal is shutting down") + + async def _call_func( + self, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval], + args: tuple[Unpack[PosArgsT]], + kwargs: dict[str, Any], + future: Future[T_Retval], + ) -> None: + def callback(f: Future[T_Retval]) -> None: + if f.cancelled(): + if self._event_loop_thread_id == get_ident(): + scope.cancel("the future was cancelled") + elif self._event_loop_thread_id is not None: + self.call(scope.cancel, "the future was cancelled") + + try: + retval_or_awaitable = func(*args, **kwargs) + if isawaitable(retval_or_awaitable): + with CancelScope() as scope: + future.add_done_callback(callback) + retval = await retval_or_awaitable + else: + retval = retval_or_awaitable + except self._cancelled_exc_class: + future.cancel() + future.set_running_or_notify_cancel() + except BaseException as exc: + if not future.cancelled(): + future.set_exception(exc) + + # Let base exceptions fall through + if not isinstance(exc, Exception): + raise + else: + if not future.cancelled(): + future.set_result(retval) + finally: + scope = None # type: ignore[assignment] + + def _spawn_task_from_thread( + self, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval], + args: tuple[Unpack[PosArgsT]], + kwargs: dict[str, Any], + name: object, + future: Future[T_Retval], + ) -> None: + """ + Spawn a new task using the given callable. + + Implementers must ensure that the future is resolved when the task finishes. + + :param func: a callable + :param args: positional arguments to be passed to the callable + :param kwargs: keyword arguments to be passed to the callable + :param name: name of the task (will be coerced to a string if not ``None``) + :param future: a future that will resolve to the return value of the callable, + or the exception raised during its execution + + """ + raise NotImplementedError + + @overload + def call( + self, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], + *args: Unpack[PosArgsT], + ) -> T_Retval: ... + + @overload + def call( + self, func: Callable[[Unpack[PosArgsT]], T_Retval], *args: Unpack[PosArgsT] + ) -> T_Retval: ... + + def call( + self, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval], + *args: Unpack[PosArgsT], + ) -> T_Retval: + """ + Call the given function in the event loop thread. + + If the callable returns a coroutine object, it is awaited on. + + :param func: any callable + :raises RuntimeError: if the portal is not running or if this method is called + from within the event loop thread + + """ + return cast(T_Retval, self.start_task_soon(func, *args).result()) + + @overload + def start_task_soon( + self, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], + *args: Unpack[PosArgsT], + name: object = None, + ) -> Future[T_Retval]: ... + + @overload + def start_task_soon( + self, + func: Callable[[Unpack[PosArgsT]], T_Retval], + *args: Unpack[PosArgsT], + name: object = None, + ) -> Future[T_Retval]: ... + + def start_task_soon( + self, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval], + *args: Unpack[PosArgsT], + name: object = None, + ) -> Future[T_Retval]: + """ + Start a task in the portal's task group. + + The task will be run inside a cancel scope which can be cancelled by cancelling + the returned future. + + :param func: the target function + :param args: positional arguments passed to ``func`` + :param name: name of the task (will be coerced to a string if not ``None``) + :return: a future that resolves with the return value of the callable if the + task completes successfully, or with the exception raised in the task + :raises RuntimeError: if the portal is not running or if this method is called + from within the event loop thread + :rtype: concurrent.futures.Future[T_Retval] + + .. versionadded:: 3.0 + + """ + self._check_running() + f: Future[T_Retval] = Future() + self._spawn_task_from_thread(func, args, {}, name, f) + return f + + def start_task( + self, + func: Callable[..., Awaitable[T_Retval]], + *args: object, + name: object = None, + ) -> tuple[Future[T_Retval], Any]: + """ + Start a task in the portal's task group and wait until it signals for readiness. + + This method works the same way as :meth:`.abc.TaskGroup.start`. + + :param func: the target function + :param args: positional arguments passed to ``func`` + :param name: name of the task (will be coerced to a string if not ``None``) + :return: a tuple of (future, task_status_value) where the ``task_status_value`` + is the value passed to ``task_status.started()`` from within the target + function + :rtype: tuple[concurrent.futures.Future[T_Retval], Any] + + .. versionadded:: 3.0 + + """ + + def task_done(future: Future[T_Retval]) -> None: + if not task_status_future.done(): + if future.cancelled(): + task_status_future.cancel() + elif future.exception(): + task_status_future.set_exception(future.exception()) + else: + exc = RuntimeError( + "Task exited without calling task_status.started()" + ) + task_status_future.set_exception(exc) + + self._check_running() + task_status_future: Future = Future() + task_status = _BlockingPortalTaskStatus(task_status_future) + f: Future = Future() + f.add_done_callback(task_done) + self._spawn_task_from_thread(func, args, {"task_status": task_status}, name, f) + return f, task_status_future.result() + + def wrap_async_context_manager( + self, cm: AbstractAsyncContextManager[T_co] + ) -> AbstractContextManager[T_co]: + """ + Wrap an async context manager as a synchronous context manager via this portal. + + Spawns a task that will call both ``__aenter__()`` and ``__aexit__()``, stopping + in the middle until the synchronous context manager exits. + + :param cm: an asynchronous context manager + :return: a synchronous context manager + + .. versionadded:: 2.1 + + """ + return _BlockingAsyncContextManager(cm, self) + + +@dataclass +class BlockingPortalProvider: + """ + A manager for a blocking portal. Used as a context manager. The first thread to + enter this context manager causes a blocking portal to be started with the specific + parameters, and the last thread to exit causes the portal to be shut down. Thus, + there will be exactly one blocking portal running in this context as long as at + least one thread has entered this context manager. + + The parameters are the same as for :func:`~anyio.run`. + + :param backend: name of the backend + :param backend_options: backend options + + .. versionadded:: 4.4 + """ + + backend: str = "asyncio" + backend_options: dict[str, Any] | None = None + _lock: Lock = field(init=False, default_factory=Lock) + _leases: int = field(init=False, default=0) + _portal: BlockingPortal = field(init=False) + _portal_cm: AbstractContextManager[BlockingPortal] | None = field( + init=False, default=None + ) + + def __enter__(self) -> BlockingPortal: + with self._lock: + if self._portal_cm is None: + self._portal_cm = start_blocking_portal( + self.backend, self.backend_options + ) + self._portal = self._portal_cm.__enter__() + + self._leases += 1 + return self._portal + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + portal_cm: AbstractContextManager[BlockingPortal] | None = None + with self._lock: + assert self._portal_cm + assert self._leases > 0 + self._leases -= 1 + if not self._leases: + portal_cm = self._portal_cm + self._portal_cm = None + del self._portal + + if portal_cm: + portal_cm.__exit__(None, None, None) + + +@contextmanager +def start_blocking_portal( + backend: str = "asyncio", + backend_options: dict[str, Any] | None = None, + *, + name: str | None = None, +) -> Generator[BlockingPortal, Any, None]: + """ + Start a new event loop in a new thread and run a blocking portal in its main task. + + The parameters are the same as for :func:`~anyio.run`. + + :param backend: name of the backend + :param backend_options: backend options + :param name: name of the thread + :return: a context manager that yields a blocking portal + + .. versionchanged:: 3.0 + Usage as a context manager is now required. + + """ + + async def run_portal() -> None: + async with BlockingPortal() as portal_: + if name is None: + current_thread().name = f"{backend}-portal-{id(portal_):x}" + + future.set_result(portal_) + await portal_.sleep_until_stopped() + + def run_blocking_portal() -> None: + if future.set_running_or_notify_cancel(): + try: + run_eventloop( + run_portal, backend=backend, backend_options=backend_options + ) + except BaseException as exc: + if not future.done(): + future.set_exception(exc) + + future: Future[BlockingPortal] = Future() + thread = Thread(target=run_blocking_portal, daemon=True, name=name) + thread.start() + try: + cancel_remaining_tasks = False + portal = future.result() + try: + yield portal + except BaseException: + cancel_remaining_tasks = True + raise + finally: + try: + portal.call(portal.stop, cancel_remaining_tasks) + except RuntimeError: + pass + finally: + thread.join() + + +def check_cancelled() -> None: + """ + Check if the cancel scope of the host task's running the current worker thread has + been cancelled. + + If the host task's current cancel scope has indeed been cancelled, the + backend-specific cancellation exception will be raised. + + :raises RuntimeError: if the current thread was not spawned by + :func:`.to_thread.run_sync` + + """ + try: + token: EventLoopToken = threadlocals.current_token + except AttributeError: + raise NoEventLoopError( + "This function can only be called inside an AnyIO worker thread" + ) from None + + token.backend_class.check_cancelled() diff --git a/backend/.venv/Lib/site-packages/anyio/functools.py b/backend/.venv/Lib/site-packages/anyio/functools.py new file mode 100644 index 0000000..41cc723 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/functools.py @@ -0,0 +1,347 @@ +from __future__ import annotations + +__all__ = ( + "AsyncCacheInfo", + "AsyncCacheParameters", + "AsyncLRUCacheWrapper", + "cache", + "lru_cache", + "reduce", +) + +import functools +import sys +from collections import OrderedDict +from collections.abc import ( + AsyncIterable, + Awaitable, + Callable, + Coroutine, + Hashable, + Iterable, +) +from functools import update_wrapper +from inspect import iscoroutinefunction +from typing import ( + Any, + Generic, + NamedTuple, + TypedDict, + TypeVar, + cast, + final, + overload, +) +from weakref import WeakKeyDictionary + +from ._core._synchronization import Lock +from .lowlevel import RunVar, checkpoint + +if sys.version_info >= (3, 11): + from typing import ParamSpec +else: + from typing_extensions import ParamSpec + +T = TypeVar("T") +S = TypeVar("S") +P = ParamSpec("P") +lru_cache_items: RunVar[ + WeakKeyDictionary[ + AsyncLRUCacheWrapper[Any, Any], + OrderedDict[Hashable, tuple[_InitialMissingType, Lock] | tuple[Any, None]], + ] +] = RunVar("lru_cache_items") + + +class _InitialMissingType: + pass + + +initial_missing: _InitialMissingType = _InitialMissingType() + + +class AsyncCacheInfo(NamedTuple): + hits: int + misses: int + maxsize: int | None + currsize: int + + +class AsyncCacheParameters(TypedDict): + maxsize: int | None + typed: bool + always_checkpoint: bool + + +@final +class AsyncLRUCacheWrapper(Generic[P, T]): + def __init__( + self, + func: Callable[..., Awaitable[T]], + maxsize: int | None, + typed: bool, + always_checkpoint: bool, + ): + self.__wrapped__ = func + self._hits: int = 0 + self._misses: int = 0 + self._maxsize = max(maxsize, 0) if maxsize is not None else None + self._currsize: int = 0 + self._typed = typed + self._always_checkpoint = always_checkpoint + update_wrapper(self, func) + + def cache_info(self) -> AsyncCacheInfo: + return AsyncCacheInfo(self._hits, self._misses, self._maxsize, self._currsize) + + def cache_parameters(self) -> AsyncCacheParameters: + return { + "maxsize": self._maxsize, + "typed": self._typed, + "always_checkpoint": self._always_checkpoint, + } + + def cache_clear(self) -> None: + if cache := lru_cache_items.get(None): + cache.pop(self, None) + self._hits = self._misses = self._currsize = 0 + + async def __call__(self, *args: P.args, **kwargs: P.kwargs) -> T: + # Easy case first: if maxsize == 0, no caching is done + if self._maxsize == 0: + value = await self.__wrapped__(*args, **kwargs) + self._misses += 1 + return value + + # The key is constructed as a flat tuple to avoid memory overhead + key: tuple[Any, ...] = args + if kwargs: + # initial_missing is used as a separator + key += (initial_missing,) + sum(kwargs.items(), ()) + + if self._typed: + key += tuple(type(arg) for arg in args) + if kwargs: + key += (initial_missing,) + tuple(type(val) for val in kwargs.values()) + + try: + cache = lru_cache_items.get() + except LookupError: + cache = WeakKeyDictionary() + lru_cache_items.set(cache) + + try: + cache_entry = cache[self] + except KeyError: + cache_entry = cache[self] = OrderedDict() + + cached_value: T | _InitialMissingType + try: + cached_value, lock = cache_entry[key] + except KeyError: + # We're the first task to call this function + cached_value, lock = ( + initial_missing, + Lock(fast_acquire=not self._always_checkpoint), + ) + cache_entry[key] = cached_value, lock + + if lock is None: + # The value was already cached + self._hits += 1 + cache_entry.move_to_end(key) + if self._always_checkpoint: + await checkpoint() + + return cast(T, cached_value) + + async with lock: + # Check if another task filled the cache while we acquired the lock + if (cached_value := cache_entry[key][0]) is initial_missing: + self._misses += 1 + if self._maxsize is not None and self._currsize >= self._maxsize: + cache_entry.popitem(last=False) + else: + self._currsize += 1 + + value = await self.__wrapped__(*args, **kwargs) + cache_entry[key] = value, None + else: + # Another task filled the cache while we were waiting for the lock + self._hits += 1 + cache_entry.move_to_end(key) + value = cast(T, cached_value) + + return value + + +class _LRUCacheWrapper(Generic[T]): + def __init__(self, maxsize: int | None, typed: bool, always_checkpoint: bool): + self._maxsize = maxsize + self._typed = typed + self._always_checkpoint = always_checkpoint + + @overload + def __call__( # type: ignore[overload-overlap] + self, func: Callable[P, Coroutine[Any, Any, T]], / + ) -> AsyncLRUCacheWrapper[P, T]: ... + + @overload + def __call__( + self, func: Callable[..., T], / + ) -> functools._lru_cache_wrapper[T]: ... + + def __call__( + self, f: Callable[P, Coroutine[Any, Any, T]] | Callable[..., T], / + ) -> AsyncLRUCacheWrapper[P, T] | functools._lru_cache_wrapper[T]: + if iscoroutinefunction(f): + return AsyncLRUCacheWrapper( + f, self._maxsize, self._typed, self._always_checkpoint + ) + + return functools.lru_cache(maxsize=self._maxsize, typed=self._typed)(f) # type: ignore[arg-type] + + +@overload +def cache( # type: ignore[overload-overlap] + func: Callable[P, Coroutine[Any, Any, T]], / +) -> AsyncLRUCacheWrapper[P, T]: ... + + +@overload +def cache(func: Callable[..., T], /) -> functools._lru_cache_wrapper[T]: ... + + +def cache( + func: Callable[..., T] | Callable[P, Coroutine[Any, Any, T]], / +) -> AsyncLRUCacheWrapper[P, T] | functools._lru_cache_wrapper[T]: + """ + A convenient shortcut for :func:`lru_cache` with ``maxsize=None``. + + This is the asynchronous equivalent to :func:`functools.cache`. + + """ + return lru_cache(maxsize=None)(func) + + +@overload +def lru_cache( + *, maxsize: int | None = ..., typed: bool = ..., always_checkpoint: bool = ... +) -> _LRUCacheWrapper[Any]: ... + + +@overload +def lru_cache( # type: ignore[overload-overlap] + func: Callable[P, Coroutine[Any, Any, T]], / +) -> AsyncLRUCacheWrapper[P, T]: ... + + +@overload +def lru_cache(func: Callable[..., T], /) -> functools._lru_cache_wrapper[T]: ... + + +def lru_cache( + func: Callable[P, Coroutine[Any, Any, T]] | Callable[..., T] | None = None, + /, + *, + maxsize: int | None = 128, + typed: bool = False, + always_checkpoint: bool = False, +) -> ( + AsyncLRUCacheWrapper[P, T] | functools._lru_cache_wrapper[T] | _LRUCacheWrapper[Any] +): + """ + An asynchronous version of :func:`functools.lru_cache`. + + If a synchronous function is passed, the standard library + :func:`functools.lru_cache` is applied instead. + + :param always_checkpoint: if ``True``, every call to the cached function will be + guaranteed to yield control to the event loop at least once + + .. note:: Caches and locks are managed on a per-event loop basis. + + """ + if func is None: + return _LRUCacheWrapper[Any](maxsize, typed, always_checkpoint) + + if not callable(func): + raise TypeError("the first argument must be callable") + + return _LRUCacheWrapper[T](maxsize, typed, always_checkpoint)(func) + + +@overload +async def reduce( + function: Callable[[T, S], Awaitable[T]], + iterable: Iterable[S] | AsyncIterable[S], + /, + initial: T, +) -> T: ... + + +@overload +async def reduce( + function: Callable[[T, T], Awaitable[T]], + iterable: Iterable[T] | AsyncIterable[T], + /, +) -> T: ... + + +async def reduce( # type: ignore[misc] + function: Callable[[T, T], Awaitable[T]] | Callable[[T, S], Awaitable[T]], + iterable: Iterable[T] | Iterable[S] | AsyncIterable[T] | AsyncIterable[S], + /, + initial: T | _InitialMissingType = initial_missing, +) -> T: + """ + Asynchronous version of :func:`functools.reduce`. + + :param function: a coroutine function that takes two arguments: the accumulated + value and the next element from the iterable + :param iterable: an iterable or async iterable + :param initial: the initial value (if missing, the first element of the iterable is + used as the initial value) + + """ + element: Any + function_called = False + if isinstance(iterable, AsyncIterable): + async_it = iterable.__aiter__() + if initial is initial_missing: + try: + value = cast(T, await async_it.__anext__()) + except StopAsyncIteration: + raise TypeError( + "reduce() of empty sequence with no initial value" + ) from None + else: + value = cast(T, initial) + + async for element in async_it: + value = await function(value, element) + function_called = True + elif isinstance(iterable, Iterable): + it = iter(iterable) + if initial is initial_missing: + try: + value = cast(T, next(it)) + except StopIteration: + raise TypeError( + "reduce() of empty sequence with no initial value" + ) from None + else: + value = cast(T, initial) + + for element in it: + value = await function(value, element) + function_called = True + else: + raise TypeError("reduce() argument 2 must be an iterable or async iterable") + + # Make sure there is at least one checkpoint, even if an empty iterable and an + # initial value were given + if not function_called: + await checkpoint() + + return value diff --git a/backend/.venv/Lib/site-packages/anyio/lowlevel.py b/backend/.venv/Lib/site-packages/anyio/lowlevel.py new file mode 100644 index 0000000..06d23c9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/lowlevel.py @@ -0,0 +1,195 @@ +from __future__ import annotations + +__all__ = ( + "EventLoopToken", + "RunvarToken", + "RunVar", + "checkpoint", + "checkpoint_if_cancelled", + "cancel_shielded_checkpoint", + "current_token", +) + +import enum +from dataclasses import dataclass +from types import TracebackType +from typing import Any, Generic, Literal, TypeVar, final, overload +from weakref import WeakKeyDictionary + +from ._core._eventloop import get_async_backend +from .abc import AsyncBackend + +T = TypeVar("T") +D = TypeVar("D") + + +async def checkpoint() -> None: + """ + Check for cancellation and allow the scheduler to switch to another task. + + Equivalent to (but more efficient than):: + + await checkpoint_if_cancelled() + await cancel_shielded_checkpoint() + + + .. versionadded:: 3.0 + + """ + await get_async_backend().checkpoint() + + +async def checkpoint_if_cancelled() -> None: + """ + Enter a checkpoint if the enclosing cancel scope has been cancelled. + + This does not allow the scheduler to switch to a different task. + + .. versionadded:: 3.0 + + """ + await get_async_backend().checkpoint_if_cancelled() + + +async def cancel_shielded_checkpoint() -> None: + """ + Allow the scheduler to switch to another task but without checking for cancellation. + + Equivalent to (but potentially more efficient than):: + + with CancelScope(shield=True): + await checkpoint() + + + .. versionadded:: 3.0 + + """ + await get_async_backend().cancel_shielded_checkpoint() + + +@final +@dataclass(frozen=True, repr=False) +class EventLoopToken: + """ + An opaque object that holds a reference to an event loop. + + .. versionadded:: 4.11.0 + """ + + backend_class: type[AsyncBackend] + native_token: object + + +def current_token() -> EventLoopToken: + """ + Return a token object that can be used to call code in the current event loop from + another thread. + + .. versionadded:: 4.11.0 + + """ + backend_class = get_async_backend() + raw_token = backend_class.current_token() + return EventLoopToken(backend_class, raw_token) + + +_run_vars: WeakKeyDictionary[object, dict[RunVar[Any], Any]] = WeakKeyDictionary() + + +class _NoValueSet(enum.Enum): + NO_VALUE_SET = enum.auto() + + +class RunvarToken(Generic[T]): + __slots__ = "_var", "_value", "_redeemed" + + def __init__(self, var: RunVar[T], value: T | Literal[_NoValueSet.NO_VALUE_SET]): + self._var = var + self._value: T | Literal[_NoValueSet.NO_VALUE_SET] = value + self._redeemed = False + + def __enter__(self) -> RunvarToken[T]: + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self._var.reset(self) + + +class RunVar(Generic[T]): + """ + Like a :class:`~contextvars.ContextVar`, except scoped to the running event loop. + + Can be used as a context manager, Just like :class:`~contextvars.ContextVar`, that + will reset the variable to its previous value when the context block is exited. + """ + + __slots__ = "_name", "_default" + + NO_VALUE_SET: Literal[_NoValueSet.NO_VALUE_SET] = _NoValueSet.NO_VALUE_SET + + def __init__( + self, name: str, default: T | Literal[_NoValueSet.NO_VALUE_SET] = NO_VALUE_SET + ): + self._name = name + self._default = default + + @property + def _current_vars(self) -> dict[RunVar[T], T]: + native_token = current_token().native_token + try: + return _run_vars[native_token] + except KeyError: + run_vars = _run_vars[native_token] = {} + return run_vars + + @overload + def get(self, default: D) -> T | D: ... + + @overload + def get(self) -> T: ... + + def get( + self, default: D | Literal[_NoValueSet.NO_VALUE_SET] = NO_VALUE_SET + ) -> T | D: + try: + return self._current_vars[self] + except KeyError: + if default is not RunVar.NO_VALUE_SET: + return default + elif self._default is not RunVar.NO_VALUE_SET: + return self._default + + raise LookupError( + f'Run variable "{self._name}" has no value and no default set' + ) + + def set(self, value: T) -> RunvarToken[T]: + current_vars = self._current_vars + token = RunvarToken(self, current_vars.get(self, RunVar.NO_VALUE_SET)) + current_vars[self] = value + return token + + def reset(self, token: RunvarToken[T]) -> None: + if token._var is not self: + raise ValueError("This token does not belong to this RunVar") + + if token._redeemed: + raise ValueError("This token has already been used") + + if token._value is _NoValueSet.NO_VALUE_SET: + try: + del self._current_vars[self] + except KeyError: + pass + else: + self._current_vars[self] = token._value + + token._redeemed = True + + def __repr__(self) -> str: + return f"" diff --git a/backend/.venv/Lib/site-packages/anyio/py.typed b/backend/.venv/Lib/site-packages/anyio/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/anyio/pytest_plugin.py b/backend/.venv/Lib/site-packages/anyio/pytest_plugin.py new file mode 100644 index 0000000..4222816 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/pytest_plugin.py @@ -0,0 +1,302 @@ +from __future__ import annotations + +import socket +import sys +from collections.abc import Callable, Generator, Iterator +from contextlib import ExitStack, contextmanager +from inspect import isasyncgenfunction, iscoroutinefunction, ismethod +from typing import Any, cast + +import pytest +from _pytest.fixtures import SubRequest +from _pytest.outcomes import Exit + +from . import get_available_backends +from ._core._eventloop import ( + current_async_library, + get_async_backend, + reset_current_async_library, + set_current_async_library, +) +from ._core._exceptions import iterate_exceptions +from .abc import TestRunner + +if sys.version_info < (3, 11): + from exceptiongroup import ExceptionGroup + +_current_runner: TestRunner | None = None +_runner_stack: ExitStack | None = None +_runner_leases = 0 + + +def extract_backend_and_options(backend: object) -> tuple[str, dict[str, Any]]: + if isinstance(backend, str): + return backend, {} + elif isinstance(backend, tuple) and len(backend) == 2: + if isinstance(backend[0], str) and isinstance(backend[1], dict): + return cast(tuple[str, dict[str, Any]], backend) + + raise TypeError("anyio_backend must be either a string or tuple of (string, dict)") + + +@contextmanager +def get_runner( + backend_name: str, backend_options: dict[str, Any] +) -> Iterator[TestRunner]: + global _current_runner, _runner_leases, _runner_stack + if _current_runner is None: + asynclib = get_async_backend(backend_name) + _runner_stack = ExitStack() + if current_async_library() is None: + # Since we're in control of the event loop, we can cache the name of the + # async library + token = set_current_async_library(backend_name) + _runner_stack.callback(reset_current_async_library, token) + + backend_options = backend_options or {} + _current_runner = _runner_stack.enter_context( + asynclib.create_test_runner(backend_options) + ) + + _runner_leases += 1 + try: + yield _current_runner + finally: + _runner_leases -= 1 + if not _runner_leases: + assert _runner_stack is not None + _runner_stack.close() + _runner_stack = _current_runner = None + + +def pytest_addoption(parser: pytest.Parser) -> None: + parser.addini( + "anyio_mode", + default="strict", + help='AnyIO plugin mode (either "strict" or "auto")', + ) + + +def pytest_configure(config: pytest.Config) -> None: + config.addinivalue_line( + "markers", + "anyio: mark the (coroutine function) test to be run asynchronously via anyio.", + ) + if ( + config.getini("anyio_mode") == "auto" + and config.pluginmanager.has_plugin("asyncio") + and config.getini("asyncio_mode") == "auto" + ): + config.issue_config_time_warning( + pytest.PytestConfigWarning( + "AnyIO auto mode has been enabled together with pytest-asyncio auto " + "mode. This may cause unexpected behavior." + ), + 1, + ) + + +@pytest.hookimpl(hookwrapper=True) +def pytest_fixture_setup(fixturedef: Any, request: Any) -> Generator[Any]: + def wrapper(anyio_backend: Any, request: SubRequest, **kwargs: Any) -> Any: + # Rebind any fixture methods to the request instance + if ( + request.instance + and ismethod(func) + and type(func.__self__) is type(request.instance) + ): + local_func = func.__func__.__get__(request.instance) + else: + local_func = func + + backend_name, backend_options = extract_backend_and_options(anyio_backend) + if has_backend_arg: + kwargs["anyio_backend"] = anyio_backend + + if has_request_arg: + kwargs["request"] = request + + with get_runner(backend_name, backend_options) as runner: + if isasyncgenfunction(local_func): + yield from runner.run_asyncgen_fixture(local_func, kwargs) + else: + yield runner.run_fixture(local_func, kwargs) + + # Only apply this to coroutine functions and async generator functions in requests + # that involve the anyio_backend fixture + func = fixturedef.func + if isasyncgenfunction(func) or iscoroutinefunction(func): + if "anyio_backend" in request.fixturenames: + fixturedef.func = wrapper + original_argname = fixturedef.argnames + + if not (has_backend_arg := "anyio_backend" in fixturedef.argnames): + fixturedef.argnames += ("anyio_backend",) + + if not (has_request_arg := "request" in fixturedef.argnames): + fixturedef.argnames += ("request",) + + try: + return (yield) + finally: + fixturedef.func = func + fixturedef.argnames = original_argname + + return (yield) + + +@pytest.hookimpl(tryfirst=True) +def pytest_pycollect_makeitem( + collector: pytest.Module | pytest.Class, name: str, obj: object +) -> None: + if collector.istestfunction(obj, name): + inner_func = obj.hypothesis.inner_test if hasattr(obj, "hypothesis") else obj + if iscoroutinefunction(inner_func): + anyio_auto_mode = collector.config.getini("anyio_mode") == "auto" + marker = collector.get_closest_marker("anyio") + own_markers = getattr(obj, "pytestmark", ()) + if ( + anyio_auto_mode + or marker + or any(marker.name == "anyio" for marker in own_markers) + ): + pytest.mark.usefixtures("anyio_backend")(obj) + + +@pytest.hookimpl(tryfirst=True) +def pytest_pyfunc_call(pyfuncitem: Any) -> bool | None: + def run_with_hypothesis(**kwargs: Any) -> None: + with get_runner(backend_name, backend_options) as runner: + runner.run_test(original_func, kwargs) + + backend = pyfuncitem.funcargs.get("anyio_backend") + if backend: + backend_name, backend_options = extract_backend_and_options(backend) + + if hasattr(pyfuncitem.obj, "hypothesis"): + # Wrap the inner test function unless it's already wrapped + original_func = pyfuncitem.obj.hypothesis.inner_test + if original_func.__qualname__ != run_with_hypothesis.__qualname__: + if iscoroutinefunction(original_func): + pyfuncitem.obj.hypothesis.inner_test = run_with_hypothesis + + return None + + if iscoroutinefunction(pyfuncitem.obj): + funcargs = pyfuncitem.funcargs + testargs = {arg: funcargs[arg] for arg in pyfuncitem._fixtureinfo.argnames} + with get_runner(backend_name, backend_options) as runner: + try: + runner.run_test(pyfuncitem.obj, testargs) + except ExceptionGroup as excgrp: + for exc in iterate_exceptions(excgrp): + if isinstance(exc, (Exit, KeyboardInterrupt, SystemExit)): + raise exc from excgrp + + raise + + return True + + return None + + +@pytest.fixture(scope="module", params=get_available_backends()) +def anyio_backend(request: Any) -> Any: + return request.param + + +@pytest.fixture +def anyio_backend_name(anyio_backend: Any) -> str: + if isinstance(anyio_backend, str): + return anyio_backend + else: + return anyio_backend[0] + + +@pytest.fixture +def anyio_backend_options(anyio_backend: Any) -> dict[str, Any]: + if isinstance(anyio_backend, str): + return {} + else: + return anyio_backend[1] + + +class FreePortFactory: + """ + Manages port generation based on specified socket kind, ensuring no duplicate + ports are generated. + + This class provides functionality for generating available free ports on the + system. It is initialized with a specific socket kind and can generate ports + for given address families while avoiding reuse of previously generated ports. + + Users should not instantiate this class directly, but use the + ``free_tcp_port_factory`` and ``free_udp_port_factory`` fixtures instead. For simple + uses cases, ``free_tcp_port`` and ``free_udp_port`` can be used instead. + """ + + def __init__(self, kind: socket.SocketKind) -> None: + self._kind = kind + self._generated = set[int]() + + @property + def kind(self) -> socket.SocketKind: + """ + The type of socket connection (e.g., :data:`~socket.SOCK_STREAM` or + :data:`~socket.SOCK_DGRAM`) used to bind for checking port availability + + """ + return self._kind + + def __call__(self, family: socket.AddressFamily | None = None) -> int: + """ + Return an unbound port for the given address family. + + :param family: if omitted, both IPv4 and IPv6 addresses will be tried + :return: a port number + + """ + if family is not None: + families = [family] + else: + families = [socket.AF_INET] + if socket.has_ipv6: + families.append(socket.AF_INET6) + + while True: + port = 0 + with ExitStack() as stack: + for family in families: + sock = stack.enter_context(socket.socket(family, self._kind)) + addr = "::1" if family == socket.AF_INET6 else "127.0.0.1" + try: + sock.bind((addr, port)) + except OSError: + break + + if not port: + port = sock.getsockname()[1] + else: + if port not in self._generated: + self._generated.add(port) + return port + + +@pytest.fixture(scope="session") +def free_tcp_port_factory() -> FreePortFactory: + return FreePortFactory(socket.SOCK_STREAM) + + +@pytest.fixture(scope="session") +def free_udp_port_factory() -> FreePortFactory: + return FreePortFactory(socket.SOCK_DGRAM) + + +@pytest.fixture +def free_tcp_port(free_tcp_port_factory: Callable[[], int]) -> int: + return free_tcp_port_factory() + + +@pytest.fixture +def free_udp_port(free_udp_port_factory: Callable[[], int]) -> int: + return free_udp_port_factory() diff --git a/backend/.venv/Lib/site-packages/anyio/streams/__init__.py b/backend/.venv/Lib/site-packages/anyio/streams/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/anyio/streams/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/streams/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4531852aafc2b927fa793ef1fa84f1ce58d4e0c6 GIT binary patch literal 188 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 QwcKE#ZO^X>{Ic`-KObU8`Tzg` literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/streams/__pycache__/file.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/streams/__pycache__/file.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..67a2832b95f21b0687e555544969f0171293363d GIT binary patch literal 7562 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/streams/__pycache__/memory.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/streams/__pycache__/memory.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d8f0cff5d434499cbb13487fbd759a042c570235 GIT binary patch literal 15009 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

uI-;Rn?L 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%0DC-77b#J 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/anyio/streams/__pycache__/tls.cpython-312.pyc b/backend/.venv/Lib/site-packages/anyio/streams/__pycache__/tls.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3ac58c82a33d678d97789938fd586b364571ceb1 GIT binary patch literal 20219 zcmd6PdvF`andb~Jc!L1=0w3aIC{iRLl8`7$v_!p3Nz~hvN}}zAmIFbYp+p)4m>JMA z8OqVgN<#1EF487hDH~@a*Jd|z$+;+Zxl3|&TZx>clG^)+BPaolRT8-_sXPC31)ECw zk!;odzMjDVgdjV)WVdc8_4IUq{q_6n@74GpWo2#-Px!?43FkJB`=9iYdmMU%U;dbd zZ<<<#|rBj9Tz*jaf&n>@AE6>}?yhvA2EHj<*nVOgTrLQ?5}L%5ah` z=AQD5dRW{Z^G=nGma(`aW}EVj`dHi<^G^jv15@Rr<@k0wKuWb+nb|;?#CutWE!VNI5?%=K^E^<<^X@nQ9+xM_DIJY0IZP zq9w^hxFtz|@wcMP`9o;Z%4Yj^Wctd=~6OG3c$!KyS5m!S(#yfKO z_+T=rOq`lY${8QNb|>O-c`O+{6_Ya_d>@`rlX6^EGA?`^PbzYBYB*%cICn>5F$Uy# zEIK_s5kC#&E-9Lfj>V#?iVxdaB|1$J_wnP0fi)>VmqbD9V0<>?7@3`xpNJ}NV&!uo zTc&cCl6XdrACuL@j4~z!9K>qklEH;~|IV~q6W6}7S z9E-_PM1F28!s^brl8H$23|cCozH+KcGW&R3PGy8Y#m=85YckJ}@IQ z(-?pIVOO*?f#8$uC>5_^)s>H_A)gs0Ad5AGKoP3Fb1iNfy~IS@lI-knWHKq}v`y zcS?4oJ03`PNlv7@9!PgfZlrr2NcTuyq?bLA?v;E<_dk$cCIygQ{y@5q;i-5a-7i%F zzKYUkt3yFWKxA$cEz{^kTop%@Xk496C`s{fbXHcxF zTTLqByf~bQ%bBuhY&ss9Ruaj?SR$6Oox-A0GxcLbc-yQh$o-U*vBTO&&bN$TEYtC(!^NOgu!=iTJzDTGl6MYRw84vlAIWy z7(+AXysY|M+iHsQsX0+)HY1!$psgNNRF_1}h9r_lYo@Hx`1p}x>{Styt zajy$I-?DQp>r-Oy`Nu8|q=eo#Iv+`OZdnwXuGvz;mN!~Aq*^zg-@E7)Q^H1o?&Tln zQ$tTI3RR22T`A#-H@df`y0g1YOVsh_l=tNR81#}R^Aahm7QoEYwKQ+DU1B^6=cJXOg#MZ zPZ1WA4G;=JClnwJf=(Jh36ufpi7{~^K9QV=#wO-uWve)&%HqJ3oIEpd zl4?DPTpYVmDXg~$RpRtiP+jiKQpIs4F(nQ#%mXK%FFeOjirAN;Ix|fKOa=~yWZ>DT zBCa^sL}1jZTtx5j0JN+`3t z4jjq2B6K2y^@xlk*m(K1tB*naq{VCEz_tc#58Q-G`Jh7Jp%}bM~ac zJOU@RtLT}x-!Sse2}wHP*^{qFvfMCQr?kxr&+(IV!WTVx=t*Bu7C!yl98$+D5wmp# zEebpcpW8_19Dg93Gg+C#GB4zMQ_!ZWTyFk7!zsaeVUku%(KGLucg|bpt*=^d7&CCr z74J?GFUy|E`dlpk1|}l&MNbZs#NRM_{sMTHPk^uaYs(eur)@UwoXf(^bMySXZQe!D zuL?J8I+AnldG{nST}98lYqF^*37@$>7vtx-dG~Sd5$?17`0xCN^(-HiY_ky^ zc@i5L^Z`2;M=4GaldMc6&pedDFg7cdXOsi<2Q2Rt$c~6D4iXZVaO^&VT}oJJyV9Xv zP-|nN!fDWPxNP5H@Zvf+#A((Fy#Csfi>gS2ubI(szm~Ns4Hs ziC_g<6gYV@M?KI$qO+%DIWB??dltG>szl zJ)bjnMjm^HW(gxL$?61{t&rKi+!Wc6#I(L1Ai7aM3RW-1(d-Hh5J`6gQnY;Z^EDCgNQz1n zlctaTm^@93OJ9ll4iKe;%+})ytSScBOc-DoRPlL(Pi0ajYco~4a(9hKCt|98^ik`E zGqp#KMh@&7K5}d*^7!!3M~)8d9vRvb89K5T!Wr?E8Nabva#I|#DZ7!bAC7w{HblW* z1YmQmXhX(vbViwmP@D1WK73$kcqB6T_{jc@=lIaECx(vcA3=TiBgU-cPQ{D^>y3DU zj3dE@LRAg|amJNDZUqu@6*^EdPGTwOuvLg!XPnARJfhCV$1*{P&#@St+4@q65C@Ww zGF~YWG3P4e$ymo?s@@yMLhl0>Wj_VPLT4P)MmOxJA~F%rIOv_2NisG&<1pALl@34} zOyf}=rNRQ`&XMBbIAglP^nC_7>N*^q|C@XFJeM8dyfurSrlqF#tKAES-tgDI(bfM2 z>lM#sPdd%s{3|sRa3ftqgKE1=98)V?F)yH5~%rt zy4cWv$N$JuU{yNMdOOhisx{rYN9)|P*s(_o?D<)s_1EQ9R~j!je!h9Zez&6fO3&q< z&#zl>+;?)`z$H)0)9^Lx*L^ShG*5V`t}R{Hqt*2+1%g){*Pr@nCn~NFFLRc9--`!P zKn$gud$s0XR#%%AXanFU|3b->Tp$gG-G)OJd(r?dqjq z!%|JteUH7;z2M0DIDath>(+eT*GJPmd$gWCDc?}qIke~;TJi@MeA!l@csDC@uD$&G zY8wXb!XC$v!2ig_4{^ee-0LX5g&(pAKN_I)A6s~YCPM{yj*i985JQzjOlPQw%f|7^ z&s+Wjcg{M`O%hzuQ;M-twgR>Ub2Vw`Itx)e1gonMMvv#1mKz2$g`=1&JnC^2TiH=; zZ{?Cq-%905F;i{aC0?=f=-oqVFTpG-+y2e^gpvDef!LQvFe&I&>9O=be1zD@tiWH5uwYfTg=h1VvhqUMe z@t{l&Nx{1mlbNqOX|j{^whPdvpR+x0JIkNtp0j?GJIj9*Yaza)V7)XHAU2|C@6LzL z!=Ham)67}(^N+FnKLzb8!JPj8FrEc16ibfa!oT5+x8_{k(0m zJ)fS7DV-8Thf+Dua!Nf`V`mOB|5h9;S6qJoNZbX>1yHS(EAW!#v)^WdgJn3=u#&5Y zJh}hC;i1T}p}{=|hWCZ48Q*}D7P=>JN$f1n2+%@E8G)o~234r%|G8#`FLyE3K zcNiK8#(R)P9#XebPOvUr0+$ox8OM?13|gVhohdhvJV~%R7C(}X&#J^L=m}0F=rQ*M zxHeMmje(1y)FXQh5Yi}+8lUk9(6FPmvGI&BJ_Ei(h(cAJu`99)-Z~?Ywj^VP{$3?n zPG=7occ46p?>S=44CbITzw%8$scw*Non5eV{>rSSv#ja$y2h)?tE(>Av-^3js`kpx z%RAGRYj0PsU8)CnuuiLAXYdFk--&!HlHPPc+jJnc=}@ZvaJuU7V%6b$HI0|bvNo>z zG5)>#2Y{j`UD=^kb}VzgvUOQYS^2tqHLI?C^71FsHR0Pe;iab4>83udsW08MS!>$- z-Ky_5f3G>c8c*Bs^?DCy1Vr~H~SW=`hS;o0Qz6u*+lr}E0o&cPQ1nFBROM4(v|__TQ}xrYqaE%63#*)&~~mitn;79q7~o zop%Cj>DzzVpALkyKuxY~U0n=p_#KK}*>-u`+nlEi4A6%Zs%*SE_O-sR?|gaZ zoyxwYs+uc@|LXAKn%zH8e=>h-UR!e<SFD{ubV>GlZ&-|_X5?w z%hsTZ_uuNp^uMRlnz&#&xS9WyZLpd9i$O1VVOk^bXN zRv`WH=0PVue!}tltoEPqHj3M+5kGNOP`rNY{%Y$_tAmLDv}>33VA%RkVFLQ6J{y3> zOkEP%ZpHr>h$(A8s-flLCJP||Ko3Y!38tkK6IQ@Jtowt z@})ksObHDadQhtN4`6e~EsWj!m`*(BE}A0V9zzIZ(p*lYG$olrEr}v0XOuW;MVO6) zr0`B%P?4CP#8B3B>q-+bCXXkflV##55nS=q%=oyhgbGB&kdu)sWe-LpW1oo=HeKdB zjTA<}bs1_5pRe#r0xy*&RMctRvxv?G^0ZFJ@C$;9A<$_X#DU7RFQoZG*W1!-2eh>V z>9vE}+QF1>SK7I2(Yb5M>HVDVMPJ$}YEJQvb2WYYU-YM)Et<3Cj!N?_qH}B3!MS!rj-Zp^LTHzlzrpWv3$G3~Bf4UFf>Y6#=lh75 z%Mx5?b|q>l*d*L1P_~dCyTIjmN8s+G#rFz79J1>oK22YyY*$p3hn_R^6G{cr^t0No zo3E9#NGY83PvE<7(seL0)~izp*rYFc{Ao|?ZBJ{~B7lYl>#sa>`I*m8L4;ilv}WCG zMYL+Z*0gV}=3ATcb*G)(nzK9W;mX_IyIU!~%~{HVcY__*g>>h3t#f-SxFa3dp#^p< z1*)?)tpn<=u+LMQ`Ihf8~NF z>*4~(vEhg;URb-Gf0f@Ve8a!}A!A5%;9q+TjjdzLkC?S!#KzGAXuODaWdtyYQz{)k zxe+>rc%d$b7*rw}9a@p*z!iX1=)FjpI_OBUs^yd7uWGFgV!6g{x%7^^$?{?HQE z9OQGn3Wp5Iw6mNOpnS2;3*#2a_6+)?_>$(SDB0)vFLPfpYrDV~ zvoH$XHKFSb_iYuSK~|XZURKG7Pr7DRoO`68a85Tq3nf0&%TG+f<6#PgpnivSgPqp8 z1yT(;Gd5=G)UD=Zp3hhmIb)lOCdbZXtZDdwXM6hJ!|EwH!NGNH5FNK z_Z9a+;8!nshnB4tzdOrWT<-Unm~>%RU{}S;y-|&}f@1N@+c1}(fn9Whd$F|I#M~Pw zVLX4&=a0%#{1`BmI4&nk@PGw)N^pA*!BfJvS%8Q5k)r1zcuGJP;GqM#=vm;#d5OR1 zEPyiAUU^UkWmy4L!Yaw2tSg{Q)mITNVFi?_s49Z8t$-?_pkg)JS3s3e6Fp?C#C&bJ z*o6D<`Qu#3F-%9J`Oq;4eIdU*fXEm5D-T;%1XuLHKx>dgptTI|eZ`_P$R0TFk;#j^ zmGWHCd3MrfoZDj2sZ&yP$6R-QTQaJUciL0K+hPf*B-9;<=+M=uNhK{Jj0QJ1ru%kl zeY?|rN3^~pi$@>7)As~(ZuwX0*ogA)QE_okl+PjYkLyH`Izbk3bmF^h>4AgVz`^vu z6WYKNke=^bEn9sLc7sNk&Chy7K45-IZ2RM!&KBv@qPs|$OsYN|{|}uYUmBJ4Oz6aQ zDIMOSg?FUG2XBWDKG=9_6l?sMKf3WsJyteK6+e?i=8K-3sBj!=xLl{LIvdE0T77{3 zGfW@cq&byvq32B2YS#SCX@A#ke-|u78~Srh;Zd#kXsY)Z2>OQLy>jBiHv}IX8*^eC zfbroIYxD;~B^l)Y484G|pIat*3%$50rTd3(_YeQ6tqbw`X#eS}tBJQkTaFWq9q-Aw!Z=2?AOSKzka;NPA2g9OkUTQ_1z z{Ujw&Tu=R5#EkND&4&B@Q>dj|%y$3{M#|Gqhy2PGDo97KLSm+}je_k6G9KprryK2+ zk5TfI6p$)HAdz5;ihE0N z+ML-cuBI&|v@X>(ri8|&@}`u~wB&C{2@OjDO1WnXKn>B>xzyac)YH4v*7=ry4{xiv zSKpDfQ3UFRU`y7;qHeCTG3#MbFBj~}ma(XhYg(OUg`fj>SH4|NsmoT*UY@lufWww< zThmh2K-Nm{-7xdxea}_CY{Pr`1n;(OTdsB5dhS=*Y*ouX-nO4#wwKx5*(T2Jd)rcJ za}ze-TNKl~Ouc=87eE@nOk%?y=G=;_I1aeA(#;-Rq``$8H@=uJyX=t4C2xVFsnf+t z6?x}XsS<9jHn^%*F&9=hE{0T-6Kn328uiYW!7H7l-RR%ogmjb4GDvPna6E>u)R-)i zgEn2vfKC!Z8EG3Kox#Be?oIhTa!-xUBojSx`E&yArf^0Vbx$%#X(X;O#E{x#(5+b! z?#^(nfmD|F;4+k^2XxOa(60h7p5(+7@WInVgb-(V*D&WOLjk6He;IzQq=tnvx2cVd zF!K=H$>1If%MvPuqml$iG<1hrBf>Q%*#qxUXc@?9X^a}ooS|5oB^eT=B*M=O>2P8< z+Id{}dPS?4TNfOA2FOpQ$U`<Eg{X*3b{M}XxwePNF)9)rhZ*st?u#~8mKzzOU{7b9xe=N3tt8=$ zu8-tBhTkMXC1V?pC8Ehp`2&qzp+zKq?giSLzehyZfaU#Hp`jr@2@mvvMV5`ERnH+i z3AwlEPi~jx^oZ)(57q+ZP06{MN^5@RIe4}bKZ^&d=EAy7`8JoYRISK=XxkM20yoP; z;e3W^a)jtVqO;~a?Pr^6rB@u=i10zjg%!i0ZpE%Gu!1lTQ~mhR{pb3y!ca&Z$lEnq z!{T1^&J}ah!*(4M=oH(t+z@}@s>UGYlYF`B+5?t-5%NU=G3p^@D8Qo{xLB?e^DdQS42h*Y?sg&IqHd>iE%~y~% z+=JwJZZ%qy+tA_CFk6XJRe+1>#qNuoU%X~d`8v|hjzwn&dD_)qZN1anpK9KG$G-*o ztFo%Jw^8#pzH}z#?MQojH80%ax^Jowh{`tHhjqdSAS(3I>>YpT)zR--?`$7QZGYlU z&y!2uazKSY!e>`;u1>=+^U+-Dnf$1BjXN*Lx$iU`Bp8VtK_ zk`x9-4~E#Rm(_#mEp(ClC^^+wpSR8$@4S1LPA!L-ZksNl<_|7#_atKIjw!ATr+kaP z{(%C<0y9S1giz)v<3A#Rl<^IU6L`jF7>kXYGx|nz=oY-0j-<%^k1o zSgLIT51ww@sI_fe>RzAj-lKKzfn~RQV3`xTgYR%cd+^fmJ60~Z8J?##O;_WoU{5;G zqXl}h<;Z)NWi3`e@_x30D-XYS-@#S2kgLc}<|)#v1$%F{-h5U!BmO+F<9E z81|k{{oI_}zi{?1n|^C4bA=&exNG4Ucy$FuSN5`aA8l2 zl}GtanNu`Bhl-Ui5;l^aK~HGu6zSdy)jka$gnovGbQKW1d!AdVW64@Aq(FhmN3X}u zsEkgKN-TI?k!x3IbDWT<_t^93EqpgCZ`id;YvU_;0vpegkw(Y!E-j%iCowak- zYgh_25N_YH3u((?-nIrAq!qB5S^>m#tpGJ@4FAoCW)=^>ycc0!D?s<;B@6znlJJr> zFW2W{l0&jxw2un7;))yb1#-Q8))I0l#O+7#qu-1vd~${CZiwFW+X~?8!N-$N6Xp=2 zt}eopk(EhcVicD=A+f6}eh}e7k=@`)3-IZTX+Z)Bl5`reW*G3f3oIq>DCt*R{?J=W zIiC2>a6>6~56k4COWsb(Rai=n{-bUt`Pn3G`%MzWw5I?;-r9J{D?B~8Xo;tQ^ma;2ElTstPKiqPS6rMm+zl5!C` z;n_1U;LBudXX&Vb4?=$FiBmIhTEI<0=%;cX%jER8Qb*CvZpekopjplT3<`6uR*s?? zO1mGQIj@B8Qx;1#XZ`_?ga|~xiDV=)SA#vj zJKu_ME@Oen<)?uOH=_bvL&t(}$6347u>o#go$hasrTdR+{YUS5{hvGZ;-R#cRP=Bi zc*M=Xbm6QmUB6bVU;FCrZw|jQe8<1_ZUrtS9k^Rrb5%&!c51bqsmf5ga)Va6VX>kQ z%w72=xFb~h;Eqt{10}6%Sr9&3w$$3cApFcJGP=2feW4Zi0+CFzh5fnMmvg+Uz?ZM& zeIo3WQY#y&CDtxd&DDbT8qcfz4TIpD?33Y@$lS>GKy;xyM&@dV=mL9fetoY{MSXz( zAQMh3!^%IRUK|IsE;0^d$rT78E0>CX@RLRW90%iLi3wQYfb~Np%ms@Uj)C_jS~s5p z0At;lCv}Hb(*b{Kt!7=SrZ-*QyI{{+T&{|{b*sPH^ra@cu~ygk)y6M1E;WehhHkB) zo5>a1w6<;VTdVI}=4|!2!)B|((y(D^*tm)f?`8#jzXvDtKqFQpkX5u^+ncKBN_)FB zZx_k)Hl+Su-Gi1~XxilglQ_6Wcv(Q~9|i_P+%1tG>=16XSSj9SLGrB*p5mdJT~6z3 z9KXwIe~oug+-XH_$jydNAxDcMBa-rEN}~;^YaLAn2jj=$B<_VAC0U$XRH}^v8q;Fl zg-9ej#OG;HpTgHg?k$T8yh{@&wi!l{vI^TH_o{ocHoUQIVE1rQ%uQww55>G>^&lwR z@&kL~r&uTBOguVg1A7HxI%h&vhWhANQO0Lr_`Q)7yg^2x6|<1v4$NmdowAQ=}adXq58sk-3A2%8<(NTG02 z=qONV-7Eizf&c|X)^!aPDW~+yr2$+~RpfAlZl9utq@q+)UJyaXN-bbQ8k;O~a!~3i zAnsRbAP}!%K4tnZ{ilq|^%mgwonY=DlZC3Z5d3Ni*bJ?qSUVNBF@v4*2qkn-KxQ(f zlLFe;`qm=)#3rw3R^fJ{|KQ9HWf35lSx)Um2nxvazvNb9WqT~=9m_tB_y05J`e)9K zf4|~-e!;c;f?M?quKrhC^E-l_xBQkv@D9Ls@$Xn1h;j%ZOAC&)wNkTIUOIc*+Vo37 z{Eg6c&uTA7`<2kOD0KZVp?_uaFNNmc2y5T)RN!}FJWc1FuX}2)x>KIk^UkH}`m39+ zRbCsrR{N!$*LN?jS_jY5^NxkO6t{jUxa#V@Ysar1)`Fq)&V^8l3*EQZ@u9`aw)-63 zZ*Ar*o(1_1Uv=Mdz{= (3, 12): + from typing import override +else: + from typing_extensions import override + + +@dataclass(eq=False) +class BufferedByteReceiveStream(ByteReceiveStream): + """ + Wraps any bytes-based receive stream and uses a buffer to provide sophisticated + receiving capabilities in the form of a byte stream. + """ + + receive_stream: AnyByteReceiveStream + _buffer: bytearray = field(init=False, default_factory=bytearray) + _closed: bool = field(init=False, default=False) + + async def aclose(self) -> None: + await self.receive_stream.aclose() + self._closed = True + + @property + def buffer(self) -> bytes: + """The bytes currently in the buffer.""" + return bytes(self._buffer) + + @property + def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: + return self.receive_stream.extra_attributes + + def feed_data(self, data: Iterable[SupportsIndex], /) -> None: + """ + Append data directly into the buffer. + + Any data in the buffer will be consumed by receive operations before receiving + anything from the wrapped stream. + + :param data: the data to append to the buffer (can be bytes or anything else + that supports ``__index__()``) + + """ + self._buffer.extend(data) + + async def receive(self, max_bytes: int = 65536) -> bytes: + if self._closed: + raise ClosedResourceError + + if self._buffer: + chunk = bytes(self._buffer[:max_bytes]) + del self._buffer[:max_bytes] + return chunk + elif isinstance(self.receive_stream, ByteReceiveStream): + return await self.receive_stream.receive(max_bytes) + else: + # With a bytes-oriented object stream, we need to handle any surplus bytes + # we get from the receive() call + chunk = await self.receive_stream.receive() + if len(chunk) > max_bytes: + # Save the surplus bytes in the buffer + self._buffer.extend(chunk[max_bytes:]) + return chunk[:max_bytes] + else: + return chunk + + async def receive_exactly(self, nbytes: int) -> bytes: + """ + Read exactly the given amount of bytes from the stream. + + :param nbytes: the number of bytes to read + :return: the bytes read + :raises ~anyio.IncompleteRead: if the stream was closed before the requested + amount of bytes could be read from the stream + + """ + while True: + remaining = nbytes - len(self._buffer) + if remaining <= 0: + retval = self._buffer[:nbytes] + del self._buffer[:nbytes] + return bytes(retval) + + try: + if isinstance(self.receive_stream, ByteReceiveStream): + chunk = await self.receive_stream.receive(remaining) + else: + chunk = await self.receive_stream.receive() + except EndOfStream as exc: + raise IncompleteRead from exc + + self._buffer.extend(chunk) + + async def receive_until(self, delimiter: bytes, max_bytes: int) -> bytes: + """ + Read from the stream until the delimiter is found or max_bytes have been read. + + :param delimiter: the marker to look for in the stream + :param max_bytes: maximum number of bytes that will be read before raising + :exc:`~anyio.DelimiterNotFound` + :return: the bytes read (not including the delimiter) + :raises ~anyio.IncompleteRead: if the stream was closed before the delimiter + was found + :raises ~anyio.DelimiterNotFound: if the delimiter is not found within the + bytes read up to the maximum allowed + + """ + delimiter_size = len(delimiter) + offset = 0 + while True: + # Check if the delimiter can be found in the current buffer + index = self._buffer.find(delimiter, offset) + if index >= 0: + found = self._buffer[:index] + del self._buffer[: index + len(delimiter) :] + return bytes(found) + + # Check if the buffer is already at or over the limit + if len(self._buffer) >= max_bytes: + raise DelimiterNotFound(max_bytes) + + # Read more data into the buffer from the socket + try: + data = await self.receive_stream.receive() + except EndOfStream as exc: + raise IncompleteRead from exc + + # Move the offset forward and add the new data to the buffer + offset = max(len(self._buffer) - delimiter_size + 1, 0) + self._buffer.extend(data) + + +class BufferedByteStream(BufferedByteReceiveStream, ByteStream): + """ + A full-duplex variant of :class:`BufferedByteReceiveStream`. All writes are passed + through to the wrapped stream as-is. + """ + + def __init__(self, stream: AnyByteStream): + """ + :param stream: the stream to be wrapped + + """ + super().__init__(stream) + self._stream = stream + + @override + async def send_eof(self) -> None: + await self._stream.send_eof() + + @override + async def send(self, item: bytes) -> None: + await self._stream.send(item) + + +class BufferedConnectable(ByteStreamConnectable): + def __init__(self, connectable: AnyByteStreamConnectable): + """ + :param connectable: the connectable to wrap + + """ + self.connectable = connectable + + @override + async def connect(self) -> BufferedByteStream: + stream = await self.connectable.connect() + return BufferedByteStream(stream) diff --git a/backend/.venv/Lib/site-packages/anyio/streams/file.py b/backend/.venv/Lib/site-packages/anyio/streams/file.py new file mode 100644 index 0000000..82d2da8 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/streams/file.py @@ -0,0 +1,154 @@ +from __future__ import annotations + +__all__ = ( + "FileReadStream", + "FileStreamAttribute", + "FileWriteStream", +) + +from collections.abc import Callable, Mapping +from io import SEEK_SET, UnsupportedOperation +from os import PathLike +from pathlib import Path +from typing import Any, BinaryIO, cast + +from .. import ( + BrokenResourceError, + ClosedResourceError, + EndOfStream, + TypedAttributeSet, + to_thread, + typed_attribute, +) +from ..abc import ByteReceiveStream, ByteSendStream + + +class FileStreamAttribute(TypedAttributeSet): + #: the open file descriptor + file: BinaryIO = typed_attribute() + #: the path of the file on the file system, if available (file must be a real file) + path: Path = typed_attribute() + #: the file number, if available (file must be a real file or a TTY) + fileno: int = typed_attribute() + + +class _BaseFileStream: + def __init__(self, file: BinaryIO): + self._file = file + + async def aclose(self) -> None: + await to_thread.run_sync(self._file.close) + + @property + def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: + attributes: dict[Any, Callable[[], Any]] = { + FileStreamAttribute.file: lambda: self._file, + } + + if hasattr(self._file, "name"): + attributes[FileStreamAttribute.path] = lambda: Path(self._file.name) + + try: + self._file.fileno() + except UnsupportedOperation: + pass + else: + attributes[FileStreamAttribute.fileno] = lambda: self._file.fileno() + + return attributes + + +class FileReadStream(_BaseFileStream, ByteReceiveStream): + """ + A byte stream that reads from a file in the file system. + + :param file: a file that has been opened for reading in binary mode + + .. versionadded:: 3.0 + """ + + @classmethod + async def from_path(cls, path: str | PathLike[str]) -> FileReadStream: + """ + Create a file read stream by opening the given file. + + :param path: path of the file to read from + + """ + file = await to_thread.run_sync(Path(path).open, "rb") + return cls(cast(BinaryIO, file)) + + async def receive(self, max_bytes: int = 65536) -> bytes: + try: + data = await to_thread.run_sync(self._file.read, max_bytes) + except ValueError: + raise ClosedResourceError from None + except OSError as exc: + raise BrokenResourceError from exc + + if data: + return data + else: + raise EndOfStream + + async def seek(self, position: int, whence: int = SEEK_SET) -> int: + """ + Seek the file to the given position. + + .. seealso:: :meth:`io.IOBase.seek` + + .. note:: Not all file descriptors are seekable. + + :param position: position to seek the file to + :param whence: controls how ``position`` is interpreted + :return: the new absolute position + :raises OSError: if the file is not seekable + + """ + return await to_thread.run_sync(self._file.seek, position, whence) + + async def tell(self) -> int: + """ + Return the current stream position. + + .. note:: Not all file descriptors are seekable. + + :return: the current absolute position + :raises OSError: if the file is not seekable + + """ + return await to_thread.run_sync(self._file.tell) + + +class FileWriteStream(_BaseFileStream, ByteSendStream): + """ + A byte stream that writes to a file in the file system. + + :param file: a file that has been opened for writing in binary mode + + .. versionadded:: 3.0 + """ + + @classmethod + async def from_path( + cls, path: str | PathLike[str], append: bool = False + ) -> FileWriteStream: + """ + Create a file write stream by opening the given file for writing. + + :param path: path of the file to write to + :param append: if ``True``, open the file for appending; if ``False``, any + existing file at the given path will be truncated + + """ + mode = "ab" if append else "wb" + file = await to_thread.run_sync(Path(path).open, mode) + return cls(cast(BinaryIO, file)) + + async def send(self, item: bytes) -> None: + try: + await to_thread.run_sync(self._file.write, item) + except ValueError: + raise ClosedResourceError from None + except OSError as exc: + raise BrokenResourceError from exc diff --git a/backend/.venv/Lib/site-packages/anyio/streams/memory.py b/backend/.venv/Lib/site-packages/anyio/streams/memory.py new file mode 100644 index 0000000..a3fa0c3 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/streams/memory.py @@ -0,0 +1,325 @@ +from __future__ import annotations + +__all__ = ( + "MemoryObjectReceiveStream", + "MemoryObjectSendStream", + "MemoryObjectStreamStatistics", +) + +import warnings +from collections import OrderedDict, deque +from dataclasses import dataclass, field +from types import TracebackType +from typing import Generic, NamedTuple, TypeVar + +from .. import ( + BrokenResourceError, + ClosedResourceError, + EndOfStream, + WouldBlock, +) +from .._core._testing import TaskInfo, get_current_task +from ..abc import Event, ObjectReceiveStream, ObjectSendStream +from ..lowlevel import checkpoint + +T_Item = TypeVar("T_Item") +T_co = TypeVar("T_co", covariant=True) +T_contra = TypeVar("T_contra", contravariant=True) + + +class MemoryObjectStreamStatistics(NamedTuple): + current_buffer_used: int #: number of items stored in the buffer + #: maximum number of items that can be stored on this stream (or :data:`math.inf`) + max_buffer_size: float + open_send_streams: int #: number of unclosed clones of the send stream + open_receive_streams: int #: number of unclosed clones of the receive stream + #: number of tasks blocked on :meth:`MemoryObjectSendStream.send` + tasks_waiting_send: int + #: number of tasks blocked on :meth:`MemoryObjectReceiveStream.receive` + tasks_waiting_receive: int + + +@dataclass(eq=False) +class _MemoryObjectItemReceiver(Generic[T_Item]): + task_info: TaskInfo = field(init=False, default_factory=get_current_task) + item: T_Item = field(init=False) + + def __repr__(self) -> str: + # When item is not defined, we get following error with default __repr__: + # AttributeError: 'MemoryObjectItemReceiver' object has no attribute 'item' + item = getattr(self, "item", None) + return f"{self.__class__.__name__}(task_info={self.task_info}, item={item!r})" + + +@dataclass(eq=False) +class _MemoryObjectStreamState(Generic[T_Item]): + max_buffer_size: float = field() + buffer: deque[T_Item] = field(init=False, default_factory=deque) + open_send_channels: int = field(init=False, default=0) + open_receive_channels: int = field(init=False, default=0) + waiting_receivers: OrderedDict[Event, _MemoryObjectItemReceiver[T_Item]] = field( + init=False, default_factory=OrderedDict + ) + waiting_senders: OrderedDict[Event, T_Item] = field( + init=False, default_factory=OrderedDict + ) + + def statistics(self) -> MemoryObjectStreamStatistics: + return MemoryObjectStreamStatistics( + len(self.buffer), + self.max_buffer_size, + self.open_send_channels, + self.open_receive_channels, + len(self.waiting_senders), + len(self.waiting_receivers), + ) + + +@dataclass(eq=False) +class MemoryObjectReceiveStream(Generic[T_co], ObjectReceiveStream[T_co]): + _state: _MemoryObjectStreamState[T_co] + _closed: bool = field(init=False, default=False) + + def __post_init__(self) -> None: + self._state.open_receive_channels += 1 + + def receive_nowait(self) -> T_co: + """ + Receive the next item if it can be done without waiting. + + :return: the received item + :raises ~anyio.ClosedResourceError: if this send stream has been closed + :raises ~anyio.EndOfStream: if the buffer is empty and this stream has been + closed from the sending end + :raises ~anyio.WouldBlock: if there are no items in the buffer and no tasks + waiting to send + + """ + if self._closed: + raise ClosedResourceError + + if self._state.waiting_senders: + # Get the item from the next sender + send_event, item = self._state.waiting_senders.popitem(last=False) + self._state.buffer.append(item) + send_event.set() + + if self._state.buffer: + return self._state.buffer.popleft() + elif not self._state.open_send_channels: + raise EndOfStream + + raise WouldBlock + + async def receive(self) -> T_co: + await checkpoint() + try: + return self.receive_nowait() + except WouldBlock: + # Add ourselves in the queue + receive_event = Event() + receiver = _MemoryObjectItemReceiver[T_co]() + self._state.waiting_receivers[receive_event] = receiver + + try: + await receive_event.wait() + finally: + self._state.waiting_receivers.pop(receive_event, None) + + try: + return receiver.item + except AttributeError: + raise EndOfStream from None + + def clone(self) -> MemoryObjectReceiveStream[T_co]: + """ + Create a clone of this receive stream. + + Each clone can be closed separately. Only when all clones have been closed will + the receiving end of the memory stream be considered closed by the sending ends. + + :return: the cloned stream + + """ + if self._closed: + raise ClosedResourceError + + return MemoryObjectReceiveStream(_state=self._state) + + def close(self) -> None: + """ + Close the stream. + + This works the exact same way as :meth:`aclose`, but is provided as a special + case for the benefit of synchronous callbacks. + + """ + if not self._closed: + self._closed = True + self._state.open_receive_channels -= 1 + if self._state.open_receive_channels == 0: + send_events = list(self._state.waiting_senders.keys()) + for event in send_events: + event.set() + + async def aclose(self) -> None: + self.close() + + def statistics(self) -> MemoryObjectStreamStatistics: + """ + Return statistics about the current state of this stream. + + .. versionadded:: 3.0 + """ + return self._state.statistics() + + def __enter__(self) -> MemoryObjectReceiveStream[T_co]: + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self.close() + + def __del__(self) -> None: + if not self._closed: + warnings.warn( + f"Unclosed <{self.__class__.__name__} at {id(self):x}>", + ResourceWarning, + stacklevel=1, + source=self, + ) + + +@dataclass(eq=False) +class MemoryObjectSendStream(Generic[T_contra], ObjectSendStream[T_contra]): + _state: _MemoryObjectStreamState[T_contra] + _closed: bool = field(init=False, default=False) + + def __post_init__(self) -> None: + self._state.open_send_channels += 1 + + def send_nowait(self, item: T_contra) -> None: + """ + Send an item immediately if it can be done without waiting. + + :param item: the item to send + :raises ~anyio.ClosedResourceError: if this send stream has been closed + :raises ~anyio.BrokenResourceError: if the stream has been closed from the + receiving end + :raises ~anyio.WouldBlock: if the buffer is full and there are no tasks waiting + to receive + + """ + if self._closed: + raise ClosedResourceError + if not self._state.open_receive_channels: + raise BrokenResourceError + + while self._state.waiting_receivers: + receive_event, receiver = self._state.waiting_receivers.popitem(last=False) + if not receiver.task_info.has_pending_cancellation(): + receiver.item = item + receive_event.set() + return + + if len(self._state.buffer) < self._state.max_buffer_size: + self._state.buffer.append(item) + else: + raise WouldBlock + + async def send(self, item: T_contra) -> None: + """ + Send an item to the stream. + + If the buffer is full, this method blocks until there is again room in the + buffer or the item can be sent directly to a receiver. + + :param item: the item to send + :raises ~anyio.ClosedResourceError: if this send stream has been closed + :raises ~anyio.BrokenResourceError: if the stream has been closed from the + receiving end + + """ + await checkpoint() + try: + self.send_nowait(item) + except WouldBlock: + # Wait until there's someone on the receiving end + send_event = Event() + self._state.waiting_senders[send_event] = item + try: + await send_event.wait() + except BaseException: + self._state.waiting_senders.pop(send_event, None) + raise + + if send_event in self._state.waiting_senders: + del self._state.waiting_senders[send_event] + raise BrokenResourceError from None + + def clone(self) -> MemoryObjectSendStream[T_contra]: + """ + Create a clone of this send stream. + + Each clone can be closed separately. Only when all clones have been closed will + the sending end of the memory stream be considered closed by the receiving ends. + + :return: the cloned stream + + """ + if self._closed: + raise ClosedResourceError + + return MemoryObjectSendStream(_state=self._state) + + def close(self) -> None: + """ + Close the stream. + + This works the exact same way as :meth:`aclose`, but is provided as a special + case for the benefit of synchronous callbacks. + + """ + if not self._closed: + self._closed = True + self._state.open_send_channels -= 1 + if self._state.open_send_channels == 0: + receive_events = list(self._state.waiting_receivers.keys()) + self._state.waiting_receivers.clear() + for event in receive_events: + event.set() + + async def aclose(self) -> None: + self.close() + + def statistics(self) -> MemoryObjectStreamStatistics: + """ + Return statistics about the current state of this stream. + + .. versionadded:: 3.0 + """ + return self._state.statistics() + + def __enter__(self) -> MemoryObjectSendStream[T_contra]: + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self.close() + + def __del__(self) -> None: + if not self._closed: + warnings.warn( + f"Unclosed <{self.__class__.__name__} at {id(self):x}>", + ResourceWarning, + stacklevel=1, + source=self, + ) diff --git a/backend/.venv/Lib/site-packages/anyio/streams/stapled.py b/backend/.venv/Lib/site-packages/anyio/streams/stapled.py new file mode 100644 index 0000000..9248b68 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/streams/stapled.py @@ -0,0 +1,147 @@ +from __future__ import annotations + +__all__ = ( + "MultiListener", + "StapledByteStream", + "StapledObjectStream", +) + +from collections.abc import Callable, Mapping, Sequence +from dataclasses import dataclass +from typing import Any, Generic, TypeVar + +from ..abc import ( + ByteReceiveStream, + ByteSendStream, + ByteStream, + Listener, + ObjectReceiveStream, + ObjectSendStream, + ObjectStream, + TaskGroup, +) + +T_Item = TypeVar("T_Item") +T_Stream = TypeVar("T_Stream") + + +@dataclass(eq=False) +class StapledByteStream(ByteStream): + """ + Combines two byte streams into a single, bidirectional byte stream. + + Extra attributes will be provided from both streams, with the receive stream + providing the values in case of a conflict. + + :param ByteSendStream send_stream: the sending byte stream + :param ByteReceiveStream receive_stream: the receiving byte stream + """ + + send_stream: ByteSendStream + receive_stream: ByteReceiveStream + + async def receive(self, max_bytes: int = 65536) -> bytes: + return await self.receive_stream.receive(max_bytes) + + async def send(self, item: bytes) -> None: + await self.send_stream.send(item) + + async def send_eof(self) -> None: + await self.send_stream.aclose() + + async def aclose(self) -> None: + await self.send_stream.aclose() + await self.receive_stream.aclose() + + @property + def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: + return { + **self.send_stream.extra_attributes, + **self.receive_stream.extra_attributes, + } + + +@dataclass(eq=False) +class StapledObjectStream(Generic[T_Item], ObjectStream[T_Item]): + """ + Combines two object streams into a single, bidirectional object stream. + + Extra attributes will be provided from both streams, with the receive stream + providing the values in case of a conflict. + + :param ObjectSendStream send_stream: the sending object stream + :param ObjectReceiveStream receive_stream: the receiving object stream + """ + + send_stream: ObjectSendStream[T_Item] + receive_stream: ObjectReceiveStream[T_Item] + + async def receive(self) -> T_Item: + return await self.receive_stream.receive() + + async def send(self, item: T_Item) -> None: + await self.send_stream.send(item) + + async def send_eof(self) -> None: + await self.send_stream.aclose() + + async def aclose(self) -> None: + await self.send_stream.aclose() + await self.receive_stream.aclose() + + @property + def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: + return { + **self.send_stream.extra_attributes, + **self.receive_stream.extra_attributes, + } + + +@dataclass(eq=False) +class MultiListener(Generic[T_Stream], Listener[T_Stream]): + """ + Combines multiple listeners into one, serving connections from all of them at once. + + Any MultiListeners in the given collection of listeners will have their listeners + moved into this one. + + Extra attributes are provided from each listener, with each successive listener + overriding any conflicting attributes from the previous one. + + :param listeners: listeners to serve + :type listeners: Sequence[Listener[T_Stream]] + """ + + listeners: Sequence[Listener[T_Stream]] + + def __post_init__(self) -> None: + listeners: list[Listener[T_Stream]] = [] + for listener in self.listeners: + if isinstance(listener, MultiListener): + listeners.extend(listener.listeners) + del listener.listeners[:] # type: ignore[attr-defined] + else: + listeners.append(listener) + + self.listeners = listeners + + async def serve( + self, handler: Callable[[T_Stream], Any], task_group: TaskGroup | None = None + ) -> None: + from .. import create_task_group + + async with create_task_group() as tg: + for listener in self.listeners: + tg.start_soon(listener.serve, handler, task_group) + + async def aclose(self) -> None: + for listener in self.listeners: + await listener.aclose() + + @property + def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: + attributes: dict = {} + for listener in self.listeners: + attributes.update(listener.extra_attributes) + + return attributes diff --git a/backend/.venv/Lib/site-packages/anyio/streams/text.py b/backend/.venv/Lib/site-packages/anyio/streams/text.py new file mode 100644 index 0000000..296cd25 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/streams/text.py @@ -0,0 +1,176 @@ +from __future__ import annotations + +__all__ = ( + "TextConnectable", + "TextReceiveStream", + "TextSendStream", + "TextStream", +) + +import codecs +import sys +from collections.abc import Callable, Mapping +from dataclasses import InitVar, dataclass, field +from typing import Any + +from ..abc import ( + AnyByteReceiveStream, + AnyByteSendStream, + AnyByteStream, + AnyByteStreamConnectable, + ObjectReceiveStream, + ObjectSendStream, + ObjectStream, + ObjectStreamConnectable, +) + +if sys.version_info >= (3, 12): + from typing import override +else: + from typing_extensions import override + + +@dataclass(eq=False) +class TextReceiveStream(ObjectReceiveStream[str]): + """ + Stream wrapper that decodes bytes to strings using the given encoding. + + Decoding is done using :class:`~codecs.IncrementalDecoder` which returns any + completely received unicode characters as soon as they come in. + + :param transport_stream: any bytes-based receive stream + :param encoding: character encoding to use for decoding bytes to strings (defaults + to ``utf-8``) + :param errors: handling scheme for decoding errors (defaults to ``strict``; see the + `codecs module documentation`_ for a comprehensive list of options) + + .. _codecs module documentation: + https://docs.python.org/3/library/codecs.html#codec-objects + """ + + transport_stream: AnyByteReceiveStream + encoding: InitVar[str] = "utf-8" + errors: InitVar[str] = "strict" + _decoder: codecs.IncrementalDecoder = field(init=False) + + def __post_init__(self, encoding: str, errors: str) -> None: + decoder_class = codecs.getincrementaldecoder(encoding) + self._decoder = decoder_class(errors=errors) + + async def receive(self) -> str: + while True: + chunk = await self.transport_stream.receive() + decoded = self._decoder.decode(chunk) + if decoded: + return decoded + + async def aclose(self) -> None: + await self.transport_stream.aclose() + self._decoder.reset() + + @property + def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: + return self.transport_stream.extra_attributes + + +@dataclass(eq=False) +class TextSendStream(ObjectSendStream[str]): + """ + Sends strings to the wrapped stream as bytes using the given encoding. + + :param AnyByteSendStream transport_stream: any bytes-based send stream + :param str encoding: character encoding to use for encoding strings to bytes + (defaults to ``utf-8``) + :param str errors: handling scheme for encoding errors (defaults to ``strict``; see + the `codecs module documentation`_ for a comprehensive list of options) + + .. _codecs module documentation: + https://docs.python.org/3/library/codecs.html#codec-objects + """ + + transport_stream: AnyByteSendStream + encoding: InitVar[str] = "utf-8" + errors: str = "strict" + _encoder: Callable[..., tuple[bytes, int]] = field(init=False) + + def __post_init__(self, encoding: str) -> None: + self._encoder = codecs.getencoder(encoding) + + async def send(self, item: str) -> None: + encoded = self._encoder(item, self.errors)[0] + await self.transport_stream.send(encoded) + + async def aclose(self) -> None: + await self.transport_stream.aclose() + + @property + def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: + return self.transport_stream.extra_attributes + + +@dataclass(eq=False) +class TextStream(ObjectStream[str]): + """ + A bidirectional stream that decodes bytes to strings on receive and encodes strings + to bytes on send. + + Extra attributes will be provided from both streams, with the receive stream + providing the values in case of a conflict. + + :param AnyByteStream transport_stream: any bytes-based stream + :param str encoding: character encoding to use for encoding/decoding strings to/from + bytes (defaults to ``utf-8``) + :param str errors: handling scheme for encoding errors (defaults to ``strict``; see + the `codecs module documentation`_ for a comprehensive list of options) + + .. _codecs module documentation: + https://docs.python.org/3/library/codecs.html#codec-objects + """ + + transport_stream: AnyByteStream + encoding: InitVar[str] = "utf-8" + errors: InitVar[str] = "strict" + _receive_stream: TextReceiveStream = field(init=False) + _send_stream: TextSendStream = field(init=False) + + def __post_init__(self, encoding: str, errors: str) -> None: + self._receive_stream = TextReceiveStream( + self.transport_stream, encoding=encoding, errors=errors + ) + self._send_stream = TextSendStream( + self.transport_stream, encoding=encoding, errors=errors + ) + + async def receive(self) -> str: + return await self._receive_stream.receive() + + async def send(self, item: str) -> None: + await self._send_stream.send(item) + + async def send_eof(self) -> None: + await self.transport_stream.send_eof() + + async def aclose(self) -> None: + await self._send_stream.aclose() + await self._receive_stream.aclose() + + @property + def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: + return { + **self._send_stream.extra_attributes, + **self._receive_stream.extra_attributes, + } + + +class TextConnectable(ObjectStreamConnectable[str]): + def __init__(self, connectable: AnyByteStreamConnectable): + """ + :param connectable: the bytestream endpoint to wrap + + """ + self.connectable = connectable + + @override + async def connect(self) -> TextStream: + stream = await self.connectable.connect() + return TextStream(stream) diff --git a/backend/.venv/Lib/site-packages/anyio/streams/tls.py b/backend/.venv/Lib/site-packages/anyio/streams/tls.py new file mode 100644 index 0000000..b507488 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/streams/tls.py @@ -0,0 +1,424 @@ +from __future__ import annotations + +__all__ = ( + "TLSAttribute", + "TLSConnectable", + "TLSListener", + "TLSStream", +) + +import logging +import re +import ssl +import sys +from collections.abc import Callable, Mapping +from dataclasses import dataclass +from functools import wraps +from ssl import SSLContext +from typing import Any, TypeVar + +from .. import ( + BrokenResourceError, + EndOfStream, + aclose_forcefully, + get_cancelled_exc_class, + to_thread, +) +from .._core._typedattr import TypedAttributeSet, typed_attribute +from ..abc import ( + AnyByteStream, + AnyByteStreamConnectable, + ByteStream, + ByteStreamConnectable, + Listener, + TaskGroup, +) + +if sys.version_info >= (3, 10): + from typing import TypeAlias +else: + from typing_extensions import TypeAlias + +if sys.version_info >= (3, 11): + from typing import TypeVarTuple, Unpack +else: + from typing_extensions import TypeVarTuple, Unpack + +if sys.version_info >= (3, 12): + from typing import override +else: + from typing_extensions import override + +T_Retval = TypeVar("T_Retval") +PosArgsT = TypeVarTuple("PosArgsT") +_PCTRTT: TypeAlias = tuple[tuple[str, str], ...] +_PCTRTTT: TypeAlias = tuple[_PCTRTT, ...] + + +class TLSAttribute(TypedAttributeSet): + """Contains Transport Layer Security related attributes.""" + + #: the selected ALPN protocol + alpn_protocol: str | None = typed_attribute() + #: the channel binding for type ``tls-unique`` + channel_binding_tls_unique: bytes = typed_attribute() + #: the selected cipher + cipher: tuple[str, str, int] = typed_attribute() + #: the peer certificate in dictionary form (see :meth:`ssl.SSLSocket.getpeercert` + # for more information) + peer_certificate: None | (dict[str, str | _PCTRTTT | _PCTRTT]) = typed_attribute() + #: the peer certificate in binary form + peer_certificate_binary: bytes | None = typed_attribute() + #: ``True`` if this is the server side of the connection + server_side: bool = typed_attribute() + #: ciphers shared by the client during the TLS handshake (``None`` if this is the + #: client side) + shared_ciphers: list[tuple[str, str, int]] | None = typed_attribute() + #: the :class:`~ssl.SSLObject` used for encryption + ssl_object: ssl.SSLObject = typed_attribute() + #: ``True`` if this stream does (and expects) a closing TLS handshake when the + #: stream is being closed + standard_compatible: bool = typed_attribute() + #: the TLS protocol version (e.g. ``TLSv1.2``) + tls_version: str = typed_attribute() + + +@dataclass(eq=False) +class TLSStream(ByteStream): + """ + A stream wrapper that encrypts all sent data and decrypts received data. + + This class has no public initializer; use :meth:`wrap` instead. + All extra attributes from :class:`~TLSAttribute` are supported. + + :var AnyByteStream transport_stream: the wrapped stream + + """ + + transport_stream: AnyByteStream + standard_compatible: bool + _ssl_object: ssl.SSLObject + _read_bio: ssl.MemoryBIO + _write_bio: ssl.MemoryBIO + + @classmethod + async def wrap( + cls, + transport_stream: AnyByteStream, + *, + server_side: bool | None = None, + hostname: str | None = None, + ssl_context: ssl.SSLContext | None = None, + standard_compatible: bool = True, + ) -> TLSStream: + """ + Wrap an existing stream with Transport Layer Security. + + This performs a TLS handshake with the peer. + + :param transport_stream: a bytes-transporting stream to wrap + :param server_side: ``True`` if this is the server side of the connection, + ``False`` if this is the client side (if omitted, will be set to ``False`` + if ``hostname`` has been provided, ``False`` otherwise). Used only to create + a default context when an explicit context has not been provided. + :param hostname: host name of the peer (if host name checking is desired) + :param ssl_context: the SSLContext object to use (if not provided, a secure + default will be created) + :param standard_compatible: if ``False``, skip the closing handshake when + closing the connection, and don't raise an exception if the peer does the + same + :raises ~ssl.SSLError: if the TLS handshake fails + + """ + if server_side is None: + server_side = not hostname + + if not ssl_context: + purpose = ( + ssl.Purpose.CLIENT_AUTH if server_side else ssl.Purpose.SERVER_AUTH + ) + ssl_context = ssl.create_default_context(purpose) + + # Re-enable detection of unexpected EOFs if it was disabled by Python + if hasattr(ssl, "OP_IGNORE_UNEXPECTED_EOF"): + ssl_context.options &= ~ssl.OP_IGNORE_UNEXPECTED_EOF + + bio_in = ssl.MemoryBIO() + bio_out = ssl.MemoryBIO() + + # External SSLContext implementations may do blocking I/O in wrap_bio(), + # but the standard library implementation won't + if type(ssl_context) is ssl.SSLContext: + ssl_object = ssl_context.wrap_bio( + bio_in, bio_out, server_side=server_side, server_hostname=hostname + ) + else: + ssl_object = await to_thread.run_sync( + ssl_context.wrap_bio, + bio_in, + bio_out, + server_side, + hostname, + None, + ) + + wrapper = cls( + transport_stream=transport_stream, + standard_compatible=standard_compatible, + _ssl_object=ssl_object, + _read_bio=bio_in, + _write_bio=bio_out, + ) + await wrapper._call_sslobject_method(ssl_object.do_handshake) + return wrapper + + async def _call_sslobject_method( + self, func: Callable[[Unpack[PosArgsT]], T_Retval], *args: Unpack[PosArgsT] + ) -> T_Retval: + while True: + try: + result = func(*args) + except ssl.SSLWantReadError: + try: + # Flush any pending writes first + if self._write_bio.pending: + await self.transport_stream.send(self._write_bio.read()) + + data = await self.transport_stream.receive() + except EndOfStream: + self._read_bio.write_eof() + except OSError as exc: + self._read_bio.write_eof() + self._write_bio.write_eof() + raise BrokenResourceError from exc + else: + self._read_bio.write(data) + except ssl.SSLWantWriteError: + await self.transport_stream.send(self._write_bio.read()) + except ssl.SSLSyscallError as exc: + self._read_bio.write_eof() + self._write_bio.write_eof() + raise BrokenResourceError from exc + except ssl.SSLError as exc: + self._read_bio.write_eof() + self._write_bio.write_eof() + if isinstance(exc, ssl.SSLEOFError) or ( + exc.strerror and "UNEXPECTED_EOF_WHILE_READING" in exc.strerror + ): + if self.standard_compatible: + raise BrokenResourceError from exc + else: + raise EndOfStream from None + + raise + else: + # Flush any pending writes first + if self._write_bio.pending: + await self.transport_stream.send(self._write_bio.read()) + + return result + + async def unwrap(self) -> tuple[AnyByteStream, bytes]: + """ + Does the TLS closing handshake. + + :return: a tuple of (wrapped byte stream, bytes left in the read buffer) + + """ + await self._call_sslobject_method(self._ssl_object.unwrap) + self._read_bio.write_eof() + self._write_bio.write_eof() + return self.transport_stream, self._read_bio.read() + + async def aclose(self) -> None: + if self.standard_compatible: + try: + await self.unwrap() + except BaseException: + await aclose_forcefully(self.transport_stream) + raise + + await self.transport_stream.aclose() + + async def receive(self, max_bytes: int = 65536) -> bytes: + data = await self._call_sslobject_method(self._ssl_object.read, max_bytes) + if not data: + raise EndOfStream + + return data + + async def send(self, item: bytes) -> None: + await self._call_sslobject_method(self._ssl_object.write, item) + + async def send_eof(self) -> None: + tls_version = self.extra(TLSAttribute.tls_version) + match = re.match(r"TLSv(\d+)(?:\.(\d+))?", tls_version) + if match: + major, minor = int(match.group(1)), int(match.group(2) or 0) + if (major, minor) < (1, 3): + raise NotImplementedError( + f"send_eof() requires at least TLSv1.3; current " + f"session uses {tls_version}" + ) + + raise NotImplementedError( + "send_eof() has not yet been implemented for TLS streams" + ) + + @property + def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: + return { + **self.transport_stream.extra_attributes, + TLSAttribute.alpn_protocol: self._ssl_object.selected_alpn_protocol, + TLSAttribute.channel_binding_tls_unique: ( + self._ssl_object.get_channel_binding + ), + TLSAttribute.cipher: self._ssl_object.cipher, + TLSAttribute.peer_certificate: lambda: self._ssl_object.getpeercert(False), + TLSAttribute.peer_certificate_binary: lambda: self._ssl_object.getpeercert( + True + ), + TLSAttribute.server_side: lambda: self._ssl_object.server_side, + TLSAttribute.shared_ciphers: lambda: self._ssl_object.shared_ciphers() + if self._ssl_object.server_side + else None, + TLSAttribute.standard_compatible: lambda: self.standard_compatible, + TLSAttribute.ssl_object: lambda: self._ssl_object, + TLSAttribute.tls_version: self._ssl_object.version, + } + + +@dataclass(eq=False) +class TLSListener(Listener[TLSStream]): + """ + A convenience listener that wraps another listener and auto-negotiates a TLS session + on every accepted connection. + + If the TLS handshake times out or raises an exception, + :meth:`handle_handshake_error` is called to do whatever post-mortem processing is + deemed necessary. + + Supports only the :attr:`~TLSAttribute.standard_compatible` extra attribute. + + :param Listener listener: the listener to wrap + :param ssl_context: the SSL context object + :param standard_compatible: a flag passed through to :meth:`TLSStream.wrap` + :param handshake_timeout: time limit for the TLS handshake + (passed to :func:`~anyio.fail_after`) + """ + + listener: Listener[Any] + ssl_context: ssl.SSLContext + standard_compatible: bool = True + handshake_timeout: float = 30 + + @staticmethod + async def handle_handshake_error(exc: BaseException, stream: AnyByteStream) -> None: + """ + Handle an exception raised during the TLS handshake. + + This method does 3 things: + + #. Forcefully closes the original stream + #. Logs the exception (unless it was a cancellation exception) using the + ``anyio.streams.tls`` logger + #. Reraises the exception if it was a base exception or a cancellation exception + + :param exc: the exception + :param stream: the original stream + + """ + await aclose_forcefully(stream) + + # Log all except cancellation exceptions + if not isinstance(exc, get_cancelled_exc_class()): + # CPython (as of 3.11.5) returns incorrect `sys.exc_info()` here when using + # any asyncio implementation, so we explicitly pass the exception to log + # (https://github.com/python/cpython/issues/108668). Trio does not have this + # issue because it works around the CPython bug. + logging.getLogger(__name__).exception( + "Error during TLS handshake", exc_info=exc + ) + + # Only reraise base exceptions and cancellation exceptions + if not isinstance(exc, Exception) or isinstance(exc, get_cancelled_exc_class()): + raise + + async def serve( + self, + handler: Callable[[TLSStream], Any], + task_group: TaskGroup | None = None, + ) -> None: + @wraps(handler) + async def handler_wrapper(stream: AnyByteStream) -> None: + from .. import fail_after + + try: + with fail_after(self.handshake_timeout): + wrapped_stream = await TLSStream.wrap( + stream, + ssl_context=self.ssl_context, + standard_compatible=self.standard_compatible, + ) + except BaseException as exc: + await self.handle_handshake_error(exc, stream) + else: + await handler(wrapped_stream) + + await self.listener.serve(handler_wrapper, task_group) + + async def aclose(self) -> None: + await self.listener.aclose() + + @property + def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: + return { + TLSAttribute.standard_compatible: lambda: self.standard_compatible, + } + + +class TLSConnectable(ByteStreamConnectable): + """ + Wraps another connectable and does TLS negotiation after a successful connection. + + :param connectable: the connectable to wrap + :param hostname: host name of the server (if host name checking is desired) + :param ssl_context: the SSLContext object to use (if not provided, a secure default + will be created) + :param standard_compatible: if ``False``, skip the closing handshake when closing + the connection, and don't raise an exception if the server does the same + """ + + def __init__( + self, + connectable: AnyByteStreamConnectable, + *, + hostname: str | None = None, + ssl_context: ssl.SSLContext | None = None, + standard_compatible: bool = True, + ) -> None: + self.connectable = connectable + self.ssl_context: SSLContext = ssl_context or ssl.create_default_context( + ssl.Purpose.SERVER_AUTH + ) + if not isinstance(self.ssl_context, ssl.SSLContext): + raise TypeError( + "ssl_context must be an instance of ssl.SSLContext, not " + f"{type(self.ssl_context).__name__}" + ) + self.hostname = hostname + self.standard_compatible = standard_compatible + + @override + async def connect(self) -> TLSStream: + stream = await self.connectable.connect() + try: + return await TLSStream.wrap( + stream, + hostname=self.hostname, + ssl_context=self.ssl_context, + standard_compatible=self.standard_compatible, + ) + except BaseException: + await aclose_forcefully(stream) + raise diff --git a/backend/.venv/Lib/site-packages/anyio/to_interpreter.py b/backend/.venv/Lib/site-packages/anyio/to_interpreter.py new file mode 100644 index 0000000..694dbe7 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/to_interpreter.py @@ -0,0 +1,246 @@ +from __future__ import annotations + +__all__ = ( + "run_sync", + "current_default_interpreter_limiter", +) + +import atexit +import os +import sys +from collections import deque +from collections.abc import Callable +from typing import Any, Final, TypeVar + +from . import current_time, to_thread +from ._core._exceptions import BrokenWorkerInterpreter +from ._core._synchronization import CapacityLimiter +from .lowlevel import RunVar + +if sys.version_info >= (3, 11): + from typing import TypeVarTuple, Unpack +else: + from typing_extensions import TypeVarTuple, Unpack + +if sys.version_info >= (3, 14): + from concurrent.interpreters import ExecutionFailed, create + + def _interp_call( + func: Callable[..., Any], args: tuple[Any, ...] + ) -> tuple[Any, bool]: + try: + retval = func(*args) + except BaseException as exc: + return exc, True + else: + return retval, False + + class _Worker: + last_used: float = 0 + + def __init__(self) -> None: + self._interpreter = create() + + def destroy(self) -> None: + self._interpreter.close() + + def call( + self, + func: Callable[..., T_Retval], + args: tuple[Any, ...], + ) -> T_Retval: + try: + res, is_exception = self._interpreter.call(_interp_call, func, args) + except ExecutionFailed as exc: + raise BrokenWorkerInterpreter(exc.excinfo) from exc + + if is_exception: + raise res + + return res +elif sys.version_info >= (3, 13): + import _interpqueues + import _interpreters + + UNBOUND: Final = 2 # I have no clue how this works, but it was used in the stdlib + FMT_UNPICKLED: Final = 0 + FMT_PICKLED: Final = 1 + QUEUE_PICKLE_ARGS: Final = (FMT_PICKLED, UNBOUND) + QUEUE_UNPICKLE_ARGS: Final = (FMT_UNPICKLED, UNBOUND) + + _run_func = compile( + """ +import _interpqueues +from _interpreters import NotShareableError +from pickle import loads, dumps, HIGHEST_PROTOCOL + +QUEUE_PICKLE_ARGS = (1, 2) +QUEUE_UNPICKLE_ARGS = (0, 2) + +item = _interpqueues.get(queue_id)[0] +try: + func, args = loads(item) + retval = func(*args) +except BaseException as exc: + is_exception = True + retval = exc +else: + is_exception = False + +try: + _interpqueues.put(queue_id, (retval, is_exception), *QUEUE_UNPICKLE_ARGS) +except NotShareableError: + retval = dumps(retval, HIGHEST_PROTOCOL) + _interpqueues.put(queue_id, (retval, is_exception), *QUEUE_PICKLE_ARGS) + """, + "", + "exec", + ) + + class _Worker: + last_used: float = 0 + + def __init__(self) -> None: + self._interpreter_id = _interpreters.create() + self._queue_id = _interpqueues.create(1, *QUEUE_UNPICKLE_ARGS) + _interpreters.set___main___attrs( + self._interpreter_id, {"queue_id": self._queue_id} + ) + + def destroy(self) -> None: + _interpqueues.destroy(self._queue_id) + _interpreters.destroy(self._interpreter_id) + + def call( + self, + func: Callable[..., T_Retval], + args: tuple[Any, ...], + ) -> T_Retval: + import pickle + + item = pickle.dumps((func, args), pickle.HIGHEST_PROTOCOL) + _interpqueues.put(self._queue_id, item, *QUEUE_PICKLE_ARGS) + exc_info = _interpreters.exec(self._interpreter_id, _run_func) + if exc_info: + raise BrokenWorkerInterpreter(exc_info) + + res = _interpqueues.get(self._queue_id) + (res, is_exception), fmt = res[:2] + if fmt == FMT_PICKLED: + res = pickle.loads(res) + + if is_exception: + raise res + + return res +else: + + class _Worker: + last_used: float = 0 + + def __init__(self) -> None: + raise RuntimeError("subinterpreters require at least Python 3.13") + + def call( + self, + func: Callable[..., T_Retval], + args: tuple[Any, ...], + ) -> T_Retval: + raise NotImplementedError + + def destroy(self) -> None: + pass + + +DEFAULT_CPU_COUNT: Final = 8 # this is just an arbitrarily selected value +MAX_WORKER_IDLE_TIME = ( + 30 # seconds a subinterpreter can be idle before becoming eligible for pruning +) + +T_Retval = TypeVar("T_Retval") +PosArgsT = TypeVarTuple("PosArgsT") + +_idle_workers = RunVar[deque[_Worker]]("_available_workers") +_default_interpreter_limiter = RunVar[CapacityLimiter]("_default_interpreter_limiter") + + +def _stop_workers(workers: deque[_Worker]) -> None: + for worker in workers: + worker.destroy() + + workers.clear() + + +async def run_sync( + func: Callable[[Unpack[PosArgsT]], T_Retval], + *args: Unpack[PosArgsT], + limiter: CapacityLimiter | None = None, +) -> T_Retval: + """ + Call the given function with the given arguments in a subinterpreter. + + .. warning:: On Python 3.13, the :mod:`concurrent.interpreters` module was not yet + available, so the code path for that Python version relies on an undocumented, + private API. As such, it is recommended to not rely on this function for anything + mission-critical on Python 3.13. + + :param func: a callable + :param args: the positional arguments for the callable + :param limiter: capacity limiter to use to limit the total number of subinterpreters + running (if omitted, the default limiter is used) + :return: the result of the call + :raises BrokenWorkerInterpreter: if there's an internal error in a subinterpreter + + """ + if limiter is None: + limiter = current_default_interpreter_limiter() + + try: + idle_workers = _idle_workers.get() + except LookupError: + idle_workers = deque() + _idle_workers.set(idle_workers) + atexit.register(_stop_workers, idle_workers) + + async with limiter: + try: + worker = idle_workers.pop() + except IndexError: + worker = _Worker() + + try: + return await to_thread.run_sync( + worker.call, + func, + args, + limiter=limiter, + ) + finally: + # Prune workers that have been idle for too long + now = current_time() + while idle_workers: + if now - idle_workers[0].last_used <= MAX_WORKER_IDLE_TIME: + break + + await to_thread.run_sync(idle_workers.popleft().destroy, limiter=limiter) + + worker.last_used = current_time() + idle_workers.append(worker) + + +def current_default_interpreter_limiter() -> CapacityLimiter: + """ + Return the capacity limiter used by default to limit the number of concurrently + running subinterpreters. + + Defaults to the number of CPU cores. + + :return: a capacity limiter object + + """ + try: + return _default_interpreter_limiter.get() + except LookupError: + limiter = CapacityLimiter(os.cpu_count() or DEFAULT_CPU_COUNT) + _default_interpreter_limiter.set(limiter) + return limiter diff --git a/backend/.venv/Lib/site-packages/anyio/to_process.py b/backend/.venv/Lib/site-packages/anyio/to_process.py new file mode 100644 index 0000000..e6796cd --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/to_process.py @@ -0,0 +1,264 @@ +from __future__ import annotations + +__all__ = ( + "current_default_process_limiter", + "process_worker", + "run_sync", +) + +import os +import pickle +import subprocess +import sys +from collections import deque +from collections.abc import Callable +from importlib.util import module_from_spec, spec_from_file_location +from typing import TypeVar, cast + +from ._core._eventloop import current_time, get_async_backend, get_cancelled_exc_class +from ._core._exceptions import BrokenWorkerProcess +from ._core._subprocesses import open_process +from ._core._synchronization import CapacityLimiter +from ._core._tasks import CancelScope, fail_after +from .abc import ByteReceiveStream, ByteSendStream, Process +from .lowlevel import RunVar, checkpoint_if_cancelled +from .streams.buffered import BufferedByteReceiveStream + +if sys.version_info >= (3, 11): + from typing import TypeVarTuple, Unpack +else: + from typing_extensions import TypeVarTuple, Unpack + +WORKER_MAX_IDLE_TIME = 300 # 5 minutes + +T_Retval = TypeVar("T_Retval") +PosArgsT = TypeVarTuple("PosArgsT") + +_process_pool_workers: RunVar[set[Process]] = RunVar("_process_pool_workers") +_process_pool_idle_workers: RunVar[deque[tuple[Process, float]]] = RunVar( + "_process_pool_idle_workers" +) +_default_process_limiter: RunVar[CapacityLimiter] = RunVar("_default_process_limiter") + + +async def run_sync( # type: ignore[return] + func: Callable[[Unpack[PosArgsT]], T_Retval], + *args: Unpack[PosArgsT], + cancellable: bool = False, + limiter: CapacityLimiter | None = None, +) -> T_Retval: + """ + Call the given function with the given arguments in a worker process. + + If the ``cancellable`` option is enabled and the task waiting for its completion is + cancelled, the worker process running it will be abruptly terminated using SIGKILL + (or ``terminateProcess()`` on Windows). + + :param func: a callable + :param args: positional arguments for the callable + :param cancellable: ``True`` to allow cancellation of the operation while it's + running + :param limiter: capacity limiter to use to limit the total amount of processes + running (if omitted, the default limiter is used) + :return: an awaitable that yields the return value of the function. + + """ + + async def send_raw_command(pickled_cmd: bytes) -> object: + try: + await stdin.send(pickled_cmd) + response = await buffered.receive_until(b"\n", 50) + status, length = response.split(b" ") + if status not in (b"RETURN", b"EXCEPTION"): + raise RuntimeError( + f"Worker process returned unexpected response: {response!r}" + ) + + pickled_response = await buffered.receive_exactly(int(length)) + except BaseException as exc: + workers.discard(process) + try: + process.kill() + with CancelScope(shield=True): + await process.aclose() + except ProcessLookupError: + pass + + if isinstance(exc, get_cancelled_exc_class()): + raise + else: + raise BrokenWorkerProcess from exc + + retval = pickle.loads(pickled_response) + if status == b"EXCEPTION": + assert isinstance(retval, BaseException) + raise retval + else: + return retval + + # First pickle the request before trying to reserve a worker process + await checkpoint_if_cancelled() + request = pickle.dumps(("run", func, args), protocol=pickle.HIGHEST_PROTOCOL) + + # If this is the first run in this event loop thread, set up the necessary variables + try: + workers = _process_pool_workers.get() + idle_workers = _process_pool_idle_workers.get() + except LookupError: + workers = set() + idle_workers = deque() + _process_pool_workers.set(workers) + _process_pool_idle_workers.set(idle_workers) + get_async_backend().setup_process_pool_exit_at_shutdown(workers) + + async with limiter or current_default_process_limiter(): + # Pop processes from the pool (starting from the most recently used) until we + # find one that hasn't exited yet + process: Process + while idle_workers: + process, idle_since = idle_workers.pop() + if process.returncode is None: + stdin = cast(ByteSendStream, process.stdin) + buffered = BufferedByteReceiveStream( + cast(ByteReceiveStream, process.stdout) + ) + + # Prune any other workers that have been idle for WORKER_MAX_IDLE_TIME + # seconds or longer + now = current_time() + killed_processes: list[Process] = [] + while idle_workers: + if now - idle_workers[0][1] < WORKER_MAX_IDLE_TIME: + break + + process_to_kill, idle_since = idle_workers.popleft() + process_to_kill.kill() + workers.remove(process_to_kill) + killed_processes.append(process_to_kill) + + with CancelScope(shield=True): + for killed_process in killed_processes: + await killed_process.aclose() + + break + + workers.remove(process) + else: + command = [sys.executable, "-u", "-m", __name__] + process = await open_process( + command, stdin=subprocess.PIPE, stdout=subprocess.PIPE + ) + try: + stdin = cast(ByteSendStream, process.stdin) + buffered = BufferedByteReceiveStream( + cast(ByteReceiveStream, process.stdout) + ) + with fail_after(20): + message = await buffered.receive(6) + + if message != b"READY\n": + raise BrokenWorkerProcess( + f"Worker process returned unexpected response: {message!r}" + ) + + main_module_path = getattr(sys.modules["__main__"], "__file__", None) + pickled = pickle.dumps( + ("init", sys.path, main_module_path), + protocol=pickle.HIGHEST_PROTOCOL, + ) + await send_raw_command(pickled) + except (BrokenWorkerProcess, get_cancelled_exc_class()): + raise + except BaseException as exc: + process.kill() + raise BrokenWorkerProcess( + "Error during worker process initialization" + ) from exc + + workers.add(process) + + with CancelScope(shield=not cancellable): + try: + return cast(T_Retval, await send_raw_command(request)) + finally: + if process in workers: + idle_workers.append((process, current_time())) + + +def current_default_process_limiter() -> CapacityLimiter: + """ + Return the capacity limiter that is used by default to limit the number of worker + processes. + + :return: a capacity limiter object + + """ + try: + return _default_process_limiter.get() + except LookupError: + limiter = CapacityLimiter(os.cpu_count() or 2) + _default_process_limiter.set(limiter) + return limiter + + +def process_worker() -> None: + # Redirect standard streams to os.devnull so that user code won't interfere with the + # parent-worker communication + stdin = sys.stdin + stdout = sys.stdout + sys.stdin = open(os.devnull) + sys.stdout = open(os.devnull, "w") + + stdout.buffer.write(b"READY\n") + while True: + retval = exception = None + try: + command, *args = pickle.load(stdin.buffer) + except EOFError: + return + except BaseException as exc: + exception = exc + else: + if command == "run": + func, args = args + try: + retval = func(*args) + except BaseException as exc: + exception = exc + elif command == "init": + main_module_path: str | None + sys.path, main_module_path = args + del sys.modules["__main__"] + if main_module_path and os.path.isfile(main_module_path): + # Load the parent's main module but as __mp_main__ instead of + # __main__ (like multiprocessing does) to avoid infinite recursion + try: + spec = spec_from_file_location("__mp_main__", main_module_path) + if spec and spec.loader: + main = module_from_spec(spec) + spec.loader.exec_module(main) + sys.modules["__main__"] = main + except BaseException as exc: + exception = exc + try: + if exception is not None: + status = b"EXCEPTION" + pickled = pickle.dumps(exception, pickle.HIGHEST_PROTOCOL) + else: + status = b"RETURN" + pickled = pickle.dumps(retval, pickle.HIGHEST_PROTOCOL) + except BaseException as exc: + exception = exc + status = b"EXCEPTION" + pickled = pickle.dumps(exc, pickle.HIGHEST_PROTOCOL) + + stdout.buffer.write(b"%s %d\n" % (status, len(pickled))) + stdout.buffer.write(pickled) + + # Respect SIGTERM + if isinstance(exception, SystemExit): + raise exception + + +if __name__ == "__main__": + process_worker() diff --git a/backend/.venv/Lib/site-packages/anyio/to_thread.py b/backend/.venv/Lib/site-packages/anyio/to_thread.py new file mode 100644 index 0000000..1f05ed9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/anyio/to_thread.py @@ -0,0 +1,74 @@ +from __future__ import annotations + +__all__ = ( + "run_sync", + "current_default_thread_limiter", +) + +import sys +from collections.abc import Callable +from typing import TypeVar +from warnings import warn + +from ._core._eventloop import get_async_backend +from .abc import CapacityLimiter + +if sys.version_info >= (3, 11): + from typing import TypeVarTuple, Unpack +else: + from typing_extensions import TypeVarTuple, Unpack + +T_Retval = TypeVar("T_Retval") +PosArgsT = TypeVarTuple("PosArgsT") + + +async def run_sync( + func: Callable[[Unpack[PosArgsT]], T_Retval], + *args: Unpack[PosArgsT], + abandon_on_cancel: bool = False, + cancellable: bool | None = None, + limiter: CapacityLimiter | None = None, +) -> T_Retval: + """ + Call the given function with the given arguments in a worker thread. + + If the ``cancellable`` option is enabled and the task waiting for its completion is + cancelled, the thread will still run its course but its return value (or any raised + exception) will be ignored. + + :param func: a callable + :param args: positional arguments for the callable + :param abandon_on_cancel: ``True`` to abandon the thread (leaving it to run + unchecked on own) if the host task is cancelled, ``False`` to ignore + cancellations in the host task until the operation has completed in the worker + thread + :param cancellable: deprecated alias of ``abandon_on_cancel``; will override + ``abandon_on_cancel`` if both parameters are passed + :param limiter: capacity limiter to use to limit the total amount of threads running + (if omitted, the default limiter is used) + :return: an awaitable that yields the return value of the function. + + """ + if cancellable is not None: + abandon_on_cancel = cancellable + warn( + "The `cancellable=` keyword argument to `anyio.to_thread.run_sync` is " + "deprecated since AnyIO 4.1.0; use `abandon_on_cancel=` instead", + DeprecationWarning, + stacklevel=2, + ) + + return await get_async_backend().run_sync_in_worker_thread( + func, args, abandon_on_cancel=abandon_on_cancel, limiter=limiter + ) + + +def current_default_thread_limiter() -> CapacityLimiter: + """ + Return the capacity limiter that is used by default to limit the number of + concurrent threads. + + :return: a capacity limiter object + + """ + return get_async_backend().current_default_thread_limiter() diff --git a/backend/.venv/Lib/site-packages/click-8.3.1.dist-info/INSTALLER b/backend/.venv/Lib/site-packages/click-8.3.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/backend/.venv/Lib/site-packages/click-8.3.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/backend/.venv/Lib/site-packages/click-8.3.1.dist-info/METADATA b/backend/.venv/Lib/site-packages/click-8.3.1.dist-info/METADATA new file mode 100644 index 0000000..3f433af --- /dev/null +++ b/backend/.venv/Lib/site-packages/click-8.3.1.dist-info/METADATA @@ -0,0 +1,84 @@ +Metadata-Version: 2.4 +Name: click +Version: 8.3.1 +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.1.dist-info/RECORD b/backend/.venv/Lib/site-packages/click-8.3.1.dist-info/RECORD new file mode 100644 index 0000000..008d697 --- /dev/null +++ b/backend/.venv/Lib/site-packages/click-8.3.1.dist-info/RECORD @@ -0,0 +1,40 @@ +click-8.3.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +click-8.3.1.dist-info/METADATA,sha256=XZeBrMAE0ghTE88SjfrSDuSyNCpBPplxJR1tbwD9oZg,2621 +click-8.3.1.dist-info/RECORD,, +click-8.3.1.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82 +click-8.3.1.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=rgCb3On8X5A4200rA5L6i13u5iapmFer7sru57Jy6zA,27093 +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=U6Bfxt8GkjNDqyJ0HqXvluJHtyZ4sY5USAvM1Cdq7mQ,132105 +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=hqCEjNndU-nzW08nRAkBaVgfZp_FdCA9KxfIWlKYaMc,31037 +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.1.dist-info/WHEEL b/backend/.venv/Lib/site-packages/click-8.3.1.dist-info/WHEEL new file mode 100644 index 0000000..d8b9936 --- /dev/null +++ b/backend/.venv/Lib/site-packages/click-8.3.1.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.1.dist-info/licenses/LICENSE.txt b/backend/.venv/Lib/site-packages/click-8.3.1.dist-info/licenses/LICENSE.txt new file mode 100644 index 0000000..d12a849 --- /dev/null +++ b/backend/.venv/Lib/site-packages/click-8.3.1.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..967719cedfe0cac28ab2fd63e5a3962f4a92c2f9 GIT binary patch literal 4066 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 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..5d1034115f01d317b852323fc0b828c46c93c382 GIT binary patch literal 31554 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 IDWiq|ABNNlumAu6 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/click/__pycache__/_textwrap.cpython-312.pyc b/backend/.venv/Lib/site-packages/click/__pycache__/_textwrap.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0ce7b98df1c2d5970e4752fbbd8bb16de6d1b909 GIT binary patch literal 2414 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/click/__pycache__/_winconsole.cpython-312.pyc b/backend/.venv/Lib/site-packages/click/__pycache__/_winconsole.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7fc5997cc8cdd92e1abfc6e471048dc01d068c51 GIT binary patch literal 11759 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/click/__pycache__/core.cpython-312.pyc b/backend/.venv/Lib/site-packages/click/__pycache__/core.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..07d183ff584b6e797c6bad49b990a8f958a1d4c4 GIT binary patch literal 134390 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 XTK=|9^0u#psrcm?Wt}YkCd~f^48t6i literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/click/__pycache__/exceptions.cpython-312.pyc b/backend/.venv/Lib/site-packages/click/__pycache__/exceptions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e385b7055eece8f4222665d3be90f141504b5117 GIT binary patch literal 14771 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 HWK8xy4#0EV 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..df50dc133c8966a18a7a432c051618bd297fd6dc GIT binary patch literal 2959 zcmbVOO>7&-6`olxDT$;+MUfrXO_Xt(pE9vo$3=fYv~_L4PL&u+VC!N<1vT6miYqO5 ziJ2iO3Q8-v2Hc>B^yVCTXn~@Q;~skKwYQ?Z$Z!L@TN`kZTzoUC7AV|9``+wQrd79x zK7h0H^XAR_{T}}?KAtB)m8Ea`KNun8Q(O$lO(t~r_b|Ci1Q9eKExJf4&Yi$n%)mDj zxUKABmJ*p+Ee@_e`l_68MK%~|jV_K-;t-j=o*pia!HwxhoP(JtigA&<{D`mcU-%|O zNsJ8h!OfBwy_{Vvh)FSa*2Jxm!w=q@_vD(RDJbp9F)aZdYz42?!+_VD~{b*UGrHQnZ( zTnbl>KE^#S>V(D*SB`m+l1p{&t;tXe$UQcgcAYUK` zm9%7RisH24yhzlc_vj|kMT4eW5}E7i+ne-~bCC%5J^DS`cav|A_Q-nXBI(g`mS2Jg z&P&r#p=PEjS?W$^oy}6GRv24o`kHw>WOd0pS_;NB}4h- zqz*Tc8puN?Okd_}E2ypf7FT}IN39#3fHfk;nlflhrJ3${O*AAGExl&6%z8~9c3b{R z(}1y7h!1J6q&8r-A2P4W!xhL{<{J$hP2TlEW}Tx~;Ni!-n0TO)w_+9|*6!%$lQ@pD zYD=1CbvZ4uiuR(mTpsp#Dx^|jUCeo~EP(s}0@^sTfa!s%fkGT&2^sKsGR~JrVrpX7 zjfCL z$b%U-`xd=Zn*5;qe)q@z&kz3c*`Gc8QT@h|*Kd|i?2MlH$DQKgpS-zKc;&Ce0meU- z4&0fV*?Io-&8gYnJ+)JOb2mdK4?f6|;^aRcj3LKEjnXf@Tqf5_rzSJMnK)I*{I-yV z>0^L`@L&O@4wI|Iz?jgJ;A9oyXCDc=vIiim(98DICb^!%1SQY~G8?bH1L-NTB1735 zWW%8T2FPF?T~P->+I-nnXi7X z$rKl0Z_mgVVEc9W=_wczBhPK0yX8*baHl_U5B_IA0gHyM+9cb~Cb=-wRfO}aJ)DOQ zK(~vV^hv340j+X3KAuAq3we;jAI23LsI_QN$_Xq)4ZG<@0pMCA;41*GbB(m5_mBgD z7y;3|qEl3X6`(JoqZCJ31g=s&!~)9_M9~^Dw5=a))uS&5SvBZ1_F#U&wqdAIY-w@U zY67blVWnnZ7_Qm)06=pTbS1bN6t1PVsF#56tH}Er3{b^+GCIC9a_Dwx`iI5O^3VNr z;g9)Ow`T8+bvMDgI=v+&15emBk~ zAZkIYOe-m4?AD_wP%q=1i4?}!CPRD$4%FISune(lw;j7sU&J$P?!bp8J}jW5^lrjZ z#?w-quhkkIXx6e;QRiWDYQJZ73oa)E0X*W(Kp-#Js8{mz-$x8~;G0KkMc zo9K`fE#$ZgA}*5uI9P=Wv($QSe=d)HqZNrxAit%K0}H~2eiw!Z8A|D0^1`QN>Mr^G zy^MS1i(#GN6IGNQu literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/click/__pycache__/parser.cpython-312.pyc b/backend/.venv/Lib/site-packages/click/__pycache__/parser.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dcd3c70fdce008aef8db4c4b3e80f6375b22f8f8 GIT binary patch literal 20418 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/click/__pycache__/shell_completion.cpython-312.pyc b/backend/.venv/Lib/site-packages/click/__pycache__/shell_completion.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7193daa78bf9431169b46937549ec4e98415440a GIT binary patch literal 23293 zcmdsfd2k%pnP2xz&pp5l?t=i>96%(7Bp{x$2$EZ(Ku{trfeJ}oAgRG{xO-5-hF)E_rB}(f2^qRa(KGW9E{seaNIBHhxs`42*38< zc#gZyJ;_O#5>et_pGZcErk?E``lcMLdKnsdO(-mU>R-u8rN)HC2k89{O+e53vW zKZ`pNuNbIcaTns11C=c9Mm#VOU~v!P!GR!)dl9c1sA6#+;?)DyEbdR#jMfg+@|@=r z{z+k};zePg&c;2$NtG{hQs51nKCgj#DLBv|RSh&s)dNi|zXtiWR(>-}t3z77-28^! zsI`HmHXyaJAhm_1HX*gSAhp%T$?lN@=7Q$m(gvyJ%~q?Yjq(P$Rc?{mzHJ{6rH%3? zNu)|1PTHEEm$XgV^rB-RByE>Mm{GgbCAH(-A$3a~c;6@8FWratW@(4C8SgFmn)#Tt zQ`&;O&U}g!wmD9FPcoI($RE0l~nuj+jU+}r{&A(UjrH_-+f3q zKRzla)0Een8Xb)$B|Vy?Vu(5(QBvb$h&YdrQ8S2no`@>ZQ8_Iu_z|#voJ@@?F&RmM z92-u>49KH_a8CST?fJDkh+OBg!U*+W@<{v}M(P=qopek(Cxx`JV;q-tn7Na#tZRy& zu-Uk*E6Zj1tSxJQL(m(WbY}(0exZ}&l;*TGf~o36E1iku!-l0D){ zAl0~vF-tP7wtP9BX5H$;)%b`)(5E?7h7<~sE6r^VGwjej*ywbeCaBc{C$T3cj6`Ay zY@Jep8cL9YDgx}w61CbRZt122{PF8 z@#)^4GnZ1z1$8VMlg}ha(rQ;U7E6sM(}2FNSW1!4oQuXT$Vur;H(>YTnaASi&ZzOU z+=U7kqUUAx3l*y2DuO9)bu-u6x!kgIv1RA2_NA5w z7KNs%zUiIQ7w!bw=lhldTc;jfaRnA!4Y@$@7rvU=-nqv4eK!(IzWq~&S6tPz!|%D; z?zsKar>>r!IsJ{Zx7{01kTOQzbBTJ!*_pH7h}?F!QijjJhHkkS1?FSW8Gemu_H|C? z26%}Zuu1%YU9t@bL}4XoDaA#aOA%Eh#}ruw z8mMBl5YjI)ASOTrL5)h$G|>25YCO%rmt}T~r-o$)zLGo?9Z#h5CF3g4Iz2Ha1LgsQ z@uU=wMbomVj>)ljG+~gRVYHsWCT?eqP*;P4pi5(@6d%H9*xrch_}ExV!SK}K)FmP~ zQIQIXKt%eL#A!f%08v>p`p|Tubx1iE2mMhdKy-|Q0hkd@f^so3BunC@VUW9+BI6`N zV}$Lgb0cyry`6ASA6G0Ut160)t5gIyh^6a}rqc>=Pdti&CPn%cKR1pUUW%&8Eoq~5 zV`8iUstZ)q(Ug{_Kb6Gt6q8pr_#RrO+rf1ietD~ zg}AyM71CmCTurA&MVe2+N~+kGxI(*5bXYHAHB$s_s5G9SEyuvq`ebhknuAS66R25D zplNH4NIW@|>W>-6Ji}U|sXk&Vbd&`nz(q`S=D-wi5sS&l+VRU^8No^j_ywHQp9$_J z->+=K50GU+l@mis2tSl|3OW#IPJQiEqUelRDlL@kj$lynbR?2#C`R~hGov5HR1pD4 zTqV~UnigL2=9*gZ^5n!0_Nv=3Eqv3fw4qSU8X$hq@bJg4J%|W6CT;}p(r3h)L_Q~L zaZx8ZWed{7HswCNG&_zN#K9VInn35gO8tqVJ{eymf_y?S%%^$Xe5||y)KTjYOmVqD z&DG3I=IZk^&(BFqf%XM=JDW$?ra8tE(Ri{y>}5;&u_N7mC^^AaRI`Jiux0(&iJtcFw5$YbR~>k-I=Mjgs*7T7F3`mCP_U+P)kkT5&Re-wf!N(f-qE3VMqNa| zgJr+3)1VS^WN17Y3#*-B@d`tcL<)?ac=X80gB@GWB)1f#;rJK>7cc8H*Zg&`qZ5a* z*n9l(Cn8TDKXLfv!BEGQ{IAnn&rXK)++NB)*unBxTr3y`7>BTW@LW_KHcxI@?ARIB z`y!?_Pt}N3>M*bohBVPa6k-o;uzryq z^dtCFI$)6hSv_n!*xA9>CO?&-IBOJC*4km>G{qg>Nw2qHr*wFUsNh4#ET}P|i54N5 zQgM!pT}KM{SFeQ>i)#$4pVIJtZ}eY-)V5Q*;5tg`tsjmx5FLEG3RxVT$uE}?q4Oak z$tpWb!3viYHGzyROlPOKN$l8$5s{3lo-UfoSuq?IH*YqMeQ{?Aj&uSiIv*Mem%|nC zyl8D5nsj#dK6&CqU;nADooKpX{dG*q6e3E|P{Na;0<>X(eLcEIFO3E=GIRVOI{xIJK)zE3@T&F`=`5ho+ZFaq#$REr&B}|ir21Pq;$#`hZOL2L$njynd(8L(oBVc zjRWJJm|!y~Kn#P#ggPDyc`aya7ik3d>r(Lj-LyP}zT1JR=i@3gNcnc@lu1B(QCPz? zXPxpGD{7vUCA0`Ljt=2OwT8EDMEhBLpqFA-0^RC|sK`#ug0ebV55)`dI)98Fr1P2v z4mk?@9UBW5o~gx|X(AT|WH!A2vrkbrM8Xtfm?mp3b{gWBI+lP`6WSgU3(irqWvYlh zPeXVSJIt!5X|qKpR_H50rRa$OwF+h#(f2c@#DQ-4+Plu?Yte3gVh0Qb^JUBRKv49% zG_4cB;oJ&ber*~_d6fZF>`ZAOLlH@m36umj#05RRUWI`CN~Sz;$WAFBIbRe^#pHlX z3Q8`h72HU7l?UQOGAKrfC`|+-rs0i0;6(=DwC3=BCP&&%dKZg|b za1=Yp^h!(y)kRhkm33*%SS1_}rtsJ;9zyh-RfPd))KFXMl`h4h+Du)P6@{clK;zB&;oMt~Y=xk$xM z!WV1c{bdyn?1w61bUIT-yLa z*qv(>@v6u*k&s-OYw4U8-gh_YaxnnddfbSyY0e^Yol9GJBeVb|kHkw*1B`%^EqzAH z*aIZHB$(Emv{hk*dMtU~bi84-Imt^xmj4!Xga68Yk_)>s|BRGMB!rmya~)Z%;|XUP zju1&aH^G!idCX%QPt;TAhIM5K{m$6WJiS%pG`@?eabaI^3?-uHRn2FLYJec9E^LYn z;d=ZW+b+$e$bgZUtT_&y>^*wa6#PAEbVz2RbCLA#q4BZgOhfUWSs8ziHBbq*rntKh zha0XRxprjkf%#qY>DQls_4(y32N$;-d?)tq?xih{{3qoy+=AalNvFZeQFYpY78QP4%JLk@n#id-9-(R^gay7+Cr~9_wsYO z7IC?yYq6yZI;dCLUT*u)B?P^zoZvC^PZlnr8Xazh$YZa@V>#pE;T&?+myb?d4tj?Y;@i<1Xa1I zCT8epZCwvIs9_64XqgQ)EZaPrauCy19;e_j1O;2etTmb1a$CY-X;sqkVK@9-uy#4n zz6jHXw7mI&#mx^aZGLbu@Zf^`!S(1tTf(-X5)qI)g!=PU9t%77B-6&qBB_9Aq{doW zS3~jnXpM}_fv!cqfqjaD&IQDi`UC!6J#|{ zvu^TQO@AtV)Kn$QQlFxvl+qQ`YD!FBG=|Kk;uS1Y#7)adJ`ao*1wsq%P5ROmLZfAK z{!zyfE18cpX>UDs116IcJc*GyRTstH`YYz79WpJ5R`&9N>Ah=G3?ZW5lDTh#6`>S zUBbU;HCBOqH_Sw7@H?77$8}W?DZDnpHT-aB3f*1CSi# z0vqSjuUvll@{QU*Z@t<2j__BNe^L1pVX5-*Y5Se#t{bsid){eYYCb#@n6^(3p zflZ5nP4n&ZnWez41@|r;2?~$OPp2QZjE%s;249rf zSiJn}3T!AKC4R1el+enVk3~wpj}*qF6y_SG%wvxsJ`cn%dpI%@VeHVPJ!?PAT@_-s z^DzFLts#PeT4ZJ_d9uPAMvvEQFVzX;93x14IVLvmCUX*P^7xw+E)hHQv%*6-f6R)^ z&gsy6Ii+^~CT!`?-A*e2D@wdTN14q`-U4Fy3iyFx6wS zlAh36WyXjFsZR0svkg>wD1-Pe-Ofkii$cLq@TZd6=J#Re^TN*8$oZO=gr-%S9Y4HW z{e4S9$EwYSA8xNByi&nTeqosWYIc#yFAS4kZ3CJ7!YJL)OeVjuW%3K7IcMcZHiu*D znjNuK7OV6+ylah4$G)|o!x37;&)xJhbT{aAwCRJSp~diLJqAC+uk|D8Yal(PekrnJ zz$v@ng<>yI8@VO-G&cmv^hG~ZMjobI@=9J(Ee-glxy$^3A3TRo^Fu8(Z0wMnX=aqt zJfpE=4ELx=wZ7b zgv>_rxa2qw`MRtO?lk!)cnMk@)`;I)J1Zi&z=IM0T=I;NV^zsx5^<|-km!HDKWiTW zaV~w#vW(!vTQLhSpbH@Fs+Yw&0c)*Ur=F%Xq)C;+o;0B(dnAv!9+LM>pV=q;5ZS-7 zHT<7cBV5tXyv&qQG@WshzEg>1Y+bQTJ=2-O1orTulaEH8>N|1r=<$A7so>J7rX>)+ zO!ae}XQXZ6Gu_4uKQw+%rgt4gKpKEMsi`CcI{=C;5{Q_ZELDVCAGG>lG?U_E}pF!7Gk6Rf!7gCxs!AS4LvPa_mCHQ08Se(9BG<>MqWFfR2tI zqlGE%m+rcsxtmsMnyw$Xc3|GQRI_E;z2d7`@NLM|HqP{|)NQ=}+_mR&RZVjb&YxP? z*1HfqoNL&0{e^2UtU9>*jy29+Upal`uA6i*N3R`SXxn}3skhI*b#{60(Z#(-m-c>n zsrIqyz7=0^!3W<3@s$HFANbbq%^+!ZFI*UA)vsTfljqexN!%E}rGD?qonY;q+PYO6 z-?V4VZm+8cfop302cNU5dezSD*gu!JTg_Ee-3eALRG(T3K8YdzgTr1?sdJnLZ-QwR zC=MRNk3Z%=i(BHkw8gK^fNXpd;*^P4rUQ#zc>!&~mvJ0~pGny`wSZn6d3G=rH5@#s z6>&3$YKpc&SB*SP%in_B-@tvv?O%3pSaffISKysM?aZZ_=a&K-7u*}y&q+WH zkYaxA9YhL6$^6*MDH$cc3FS?Mo#fM&((yCu*^27fvb+Rwu^GhD!`z)I7o4I!D-79A za_wB&jRf{|a0+B&NthI#<;?s`+-3W-+$H{|qhIspOx4CDj9Jn(2YWN_fUyK60uno>GYt7H z6e+_zp2kM45$;ZLcd9nM7J7Z_t6OiJSq$|oRqda4-U-(H(Zkn|T{||HU98={6zrOI z_XD@@P?P-!jXc6n^~~bSd1gT)%;Vg$KpU+Z&$l?HDYo@%{C0qG zJCd1`lyU~KLTQF^v6;3aC|<`PpC^FcfSQ2k>iX;9YvI`qbBE@nS4LhQnLD!(*t+1} z%HY}H^AzI$6q$k{3WgDcE6TB7y2-&GIeGla6TN+rhjDf=)tBa1$ulsfYX}%->Tb%6 z|6-hXg@KhZkn~6-%qw3-FHBMPkdB`T>Y9QbH2htN{N_dOr$WbyuWIUWu0Aw%e8o}q zk*&>9N&HjwD#iZCL%hu)u7MpB@4=&Lo6a#&BSn0PvEuw1(TDQgUFsRU`dB{^cSGJ=abRh zXQKOnf$h3fMWZj3rRFG&f(tZmI+6&5+re)T3U8V^z9s-w?=}V;J9Jc~vj0a=)qe#3 z3+CbR31SNsf!IQx4&|}+Z!wxLaFSbuz3jQq&ToQar7~}zgu>UL8AF5=ZAc zN;YThN@Lb8IVdk{W0#PE5IiiN0m;T=@<%+K@iyWC!p?r>_mQjo3kqm(>`4Fh|H18=38!@xFx*pdCPO- z%0kWl1^@mPi(r)F7CtAru(*RGM?aHZ%+pLMxLQar3Xc3W!4G=TBA7=zmDQ?>)VHT_ zAs|yjK9#47($A7n9Jgk0chSz|U*%O)R$fMsX)91{t*>}itBOP~M&k*(n5JL#Qj1^< z$CiF{5#vO#HRXqH1M$*_bRK!OKFgCXC(G=g(NWC!gz4`V6?>S-(lb~zg+WU}4qrlD zf;Mjnk~e{_>pTUU3-c{tzBe#-KnNz|v}Ny$S?V@u@WH+7SLnz*Xx_r}(wPKPp?(uj z8fTYD^3_VcY+$^hPV)r}FCu10VxwTUi;7ARuLRvL>xp_}qP;!=L*GwxFkEt=dA3{u zQORhYEkU<9@M6gI5*DyNR=#0cfB z#{!t`NGi10mNS)SE$NVqfSC^;OQmolXiSV+i-NuVEO;?oNoXn9n*a7dVF3iYXl1T6 zgS0riXJu}Y%se;AFP*H1<*rt-%{KSe+D|BR@=fRfZtWCpl0u6GL4nS`LW??S-4qIb zLR+F=JGooQ`CFHL;-XKSuUqnMSrE3Y-vuJ)*a?2^=ZG-%qz&px63Ghp3VHNoamD>j z%k^gxipQ)ie|Jc7;FopYpVy^u+hNYI*OWb>^Y$8^BYO?xb~vS!Na`Eu{4RICXKf>1 zePo59$vyBK$@V8XQ?AFA<26j`B=ZoZOLE37VDsi)RMnjxddQIiehtG3`Eoat@nNB% zOI++?7lWK35JKkYiH*}`e-S&EH+up+&O-$TXPBrs8dupxy;vf}-d`C{;a*-!_ukD{ z5#ik*9Yb^SSH|UJ432^@GqF2wgzfASEbhCcQ@B_vM%AvkX&r=f9I5QO&f(&~1-QnI zO~4?X%v%mil@y&J`EryD-r|#g3ye@Cz$T@M%YL+a)+gxeegQeoUj_fKERg@ieWk!l(ztYnjMWPF~pRAi=b3CWV|H>?-7b#LS%|t>);$!E8f7>Z8O_u zhvpAYZ(H()r+RUNYO43P(3q=hnCgA8Kj-yN^{xsoN88Wp8mIem{=n5^GskAf-}kqE zXy@viR)d^BFm>!VcPqdae#8lmHt2FZ{;S>@@9ggD`>ySK-`&cH@M;C}K2}L}bF=Y~ z!2LkzIJDjVgKa#*qQl&hL#Hv;Lhe7y=Z|hvid6Xtq8CI-N}eg(G488m;&7H^;OB_t z4wBC+--?OPkQ4ZF_%1OS08()hbb=eH$hT+4KE2(vW%3vyeQ3!u&ZFf+Xt{jf_6vtO z7>X1qXbL5mbhX(`nkn0Km8E{!$9;1&80GdrAVjw1bHG0IO$&0vJ$8Io~o;3!eLfj4c z_Tz{$?r2*Km4%%Q@vPe&pkm}x!*Y#2*id`KLniUnoowKcLSBc=K49L*J)(RU3&i9z zm^8d`P)}&oKpGVSCtdC4WX-AUSkxRz>P`PlfVCnKU7@Y`QAhJZt^4?){=<(Q?e7B; zlTVi>ko}c#Hwm8j87k#qm38d|&PEQb8Bi-CzI-zeMdt1AxhmNw0;c{ z=Aq)RpOwG;%x&N1T%Z=B{?(qDo(12g1z{7y6&-=E_RsXs?R}-^<(?(~=Bd6Fcg0oT zjBi$1bT@s(IX&K-uX5SfzUafv{@0JadThye|My>5{?duXFP&KMo%qO(5-_t?RA2q_ z%$Mgj%^d%TvsHxe1e@pfzP9(xj`^;o;Es>%NcvTm~#a{A@di^0y-3b(_# zUN)qI89K9jnjii!9I!=EvY4>^!? z6QB{-5J9fHk1)avvRn~CN(4YP6u&I1#y+qO(D;~Ivb+tE-YHAHpLib7VRAck*n zqQCG3Y0cdg)6p6C)S;ZuKWkqOZdwe|(qjYksZ*QgV^KS()rzT|?Gvb-tsJ#e{oqH+ zP&x(lQL+^}z~#-b`Af(ql>@&N<~YMC&Osk($zYslnE<%tA=;y0(8=mF8R^)A54||@ zl=-DCS;wRuC3pe6kYpojrr_g4qz@@a?bvn-nZNv;bVlC+GGeB2#a_lehG>z4n}PF$ zmcO%eTQS`@&i34J%_~ba`gMxoQT`I^p%8zlxq!Ch3J#kKeWye7$VuR>f|~)FTan2e zDND+~r{V-lnt*AkaNHnbpxbBunv#9wTxbBD=D;^3z&hAzYP9E|5qNYmQCC7H3^-jx zF?@N6QzsDtk?`ZR29bE`wy%Q#*5&`&9IyEP#7DoY>!-f_tNM+vxo^~dxAMQ# z-#_D>c1)`|UvPHk%)Z(2>sPK_dCwR6slV!1z72D|^EL1L?#nf|PJbCGs})?s4&n+L z=A;E*=sn*<^H*-kZ;!k+vasc$1>qqb1q2MkeCRM{*#BQKKoSF>aF zx?z^oaw>Np6;W!8b93m#bGSQcZz?Bq!C5iDr;DH!RgKxPoUj~$6DjC!7 z*yIb~P0Sp_Q^^EGtyChBx@39pQ$wnL4+0k!rIgI{2aqQ4Z50KgB>X8zYXv7=xQgJj z0&xE$r^8Z??VtL3*B2t)r?e`_!0|*Jq7*JG;|f>ud_VL|#I+$wSprBLfr9-u-dYed zOkILo309T)MQROt3hd~h(C}ygm1Y^N9zGxBFZ@UseX9u{Pzr#HfP5Xp6=S_DY3ntY z!MW;Z0uehL1;hCAh8D=XJTu&=b{Gmqd=n=>C2!f8BW z>xY4LASkD(A_cpM{C^9O2ZdP+cVBqw(S-_eQP`C8G)>nmdzuzKO>^P-Q?Eb!>a*WH zz34f3>(Tc-2j8t>9?YS|KxqEt>(9LU%wnKxTKGj}b*{eY`h{y3rXTrLplNQ)YkO}8 z!nuaF>y!U-GPk*FdGo==&2-Ud&(h{cuN|K~Jl8&#UTJ8ay^`A)y4S#Ye-G`$V%FTc z+!S7H3g;SI=A;|D-|c`KOY_#doUOTjrAf@S-8W}Ph2@RA7B}v?b@J_J-g;(nH{aWB z^!fnTwrRPwYq7NpH*M&D`{rEN&fK1Tx$a#!yV|<%a;~;!dXcm(4;kl=mTlXxs?pfGy_|~Pjvu|Y)xpsIZSohK6JQt|B z=R&8ePw`AdzIV_Z^~d*Gs0-@n<9lB!DDtt|kBz!p9HkC3l)4h`!5bV^h*zH z$guNX`*-E!%ILytVaq z%R#brT$#BtcWfcBdBMGTr6NdQ)myG;U#w`K?_H|soI0}R=BgW~9e1FCubG!_^u6!f zm8)r-+qzKG@t(f}?upfnYks2$^Hg}>*IilwT|-~6e`f!j7rgv}5MtbW*k9u6u1GZX zdJ1+@K*}XO)@a3cQ|ucQY(W4C=S_;=pn$FJE{d^2l!k+u%nW)Xl$vQSV^K6dOohU4 z7Zp~{Qxk>|MQl9VF~vtQY7DN@sZ^q4M~Iv(~A_PiUQin>CKiM%}T$*HC_C#V5><_Zcq!Tj|?cL*uaa;M-aXQD-d>1Gfh* z1Vlsa#uWqziUJ z$i>(2(WUQ1Dk24cM8Tg@@Hzz~!!Zvs=7OTke=e`WW996sG)mZw&}jzSU>=TKavjTju$;4>=0& zK4E{5-!^;jE{E6Mi~J^j$86VK4zIh9@{M{9UaJpqb#1eUbf@8+3;X(S*B)QssxXv_ zrkuYq=c~uX;Jr2^E!6B>;{@IYnR~~cReKd5$a$LecW66%uQ=-097td5bn%^QwIRfg z@%6lOZI_b|tyS0ahxpZ9JyZ`XfHzwKyp0v0n49y}u6iiu<(w63K8j`d?R-0{L+{2- Vt9E+dzl*(B936KZ_|5j}e*;P$%D?~s literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/click/__pycache__/termui.cpython-312.pyc b/backend/.venv/Lib/site-packages/click/__pycache__/termui.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a37e4a8cd24030d100ee4dcc5c13c9b75ce52188 GIT binary patch literal 34646 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 b-Mysj{>s;(wqLv3t=9c*s8elc+2a2K6KEO; literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/click/__pycache__/testing.cpython-312.pyc b/backend/.venv/Lib/site-packages/click/__pycache__/testing.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6573e370410b9d86a947d1b1be3905c69da8de85 GIT binary patch literal 27388 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 G-1)z#S30`@ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/click/__pycache__/types.cpython-312.pyc b/backend/.venv/Lib/site-packages/click/__pycache__/types.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7262e87f023709823c4bcc77f62ef58474b238cf GIT binary patch literal 50058 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

Oc}E)~?Q|C(pdId@5Nq|4zC`K*u8W8c<3g!R zv8aKniGLL=l7A4fbXg;=R}}_v%athf(V-Rr_ke*1fOCxq!bV`jp5IxyZ7EDqgYCXG zSQcNi9h{}htAVa4gu2?5v47XH%i?Y_w^osH4v@F(nkQFQ6y8#hr`W*{>ozmwx#SQs zxU(bwhP+~|1~_#mn;-WJ!dw5sy34^Ke-9G`_a9te1f?cv^?>4VvK!7v&?KlP(z0Ai{`l`tD0%cWn_gRO4yRf z!J2S4k;^P? zphp3QNU5U*nXw71ym@C~aB(5j&!9+!#~TWFOFPKlF0ym7p@D#!O~etl_EZ85vW3W@ z`J89@zVL%AjbwAvrcR9zl>~c(%Rfl)C7)h$KLkaF(@c6a2Q+90R56xwLxSlp$((3N z*?=H3-mdF_>9s<1h6BlZD#3+9+}uI^q3b-X5#eay3bqro_c0``{w;o*N-+X0+{u9} z99i4AWr+;+3QT>M3BKU`vYiSq)9Vhs$km)zIERpK$NIvPouCDJ77wCma_HfTu>cPC zlkzP>Afo;X>4yl%e;om6#`X!$`W0Vb;_xqU2Z8+)VE2lunWn2vw<{VKDjMg`E>?t? zdwH?wti$fD`=q9RcF(o&t(yIl$3FAm9uIh@(*+9C+Sg9QKb-|fej3=4-6E7#Ww+th zwTY9zy<1K=9@o3km5_ByH5=YIM%O^r-P0=2t&hrmha9#aJE{*gIDfoR#M|`nB+|!4 zJ_;dr2R>tE>F{CbKnVO^JkugQ{SwPER=XzJIMn_UitV9#Cg{b4L{^#jt5!tdveSbU z&susMA>9rxBrlt@tLt267j9;G7l~s5b~N8SE`NohD)Nr(n+e~dDqp78zqUf}QD#3~ z2w>)7eR&Ph#&GZLOovZ_$g6VVMZ=A}MWO(CjPnpcrpXwtFC9L_E;c@K8n^kXU!i(D zoTd1$)MyvI$QsODWLbz>9P^~Z=KyOc=HwS2u(F+D2i1Q@KH|W%N?uT)xNFtp6GN-@Zn5TWRh!uK8%2CZ6gPb)(EB$-wi;3TOu#F< zSJ2RS>!bkqQ*SWqWYAMCRtFpR2>ueIMmP$IZc6?WmiGHIpmv_~T(A{%lSakj7f> 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..ee8225c --- /dev/null +++ b/backend/.venv/Lib/site-packages/click/_termui_impl.py @@ -0,0 +1,852 @@ +""" +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 + + # Produces a normalized absolute path string. + # multi-call binaries such as busybox derive their identity from the symlink + # less -> busybox. resolve() causes them to misbehave. (eg. less becomes busybox) + cmd_path = Path(cmd_filepath).absolute() + 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=False, + 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 + # Produces a normalized absolute path string. + # multi-call binaries such as busybox derive their identity from the symlink + # less -> busybox. resolve() causes them to misbehave. (eg. less becomes busybox) + cmd_path = Path(cmd_filepath).absolute() + + 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..57f549c --- /dev/null +++ b/backend/.venv/Lib/site-packages/click/core.py @@ -0,0 +1,3415 @@ +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: + default_value = param.get_default(ctx) + # We explicitly hide the :attr:`UNSET` value to the user, as we + # choose to make it an implementation detail. And because ``invoke`` + # has been designed as part of Click public API, we return ``None`` + # instead. Refs: + # https://github.com/pallets/click/issues/3066 + # https://github.com/pallets/click/issues/3065 + # https://github.com/pallets/click/pull/3068 + if default_value is UNSET: + default_value = None + kwargs[param.name] = param.type_cast_value( # type: ignore + ctx, default_value + ) + + # 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) + + # We now have all parameters' values into `ctx.params`, but the data may contain + # the `UNSET` sentinel. + # Convert `UNSET` to `None` to ensure that the user doesn't see `UNSET`. + # + # Waiting until after the initial parse to convert allows us to treat `UNSET` + # more like a missing value when multiple params use the same name. + # Refs: + # https://github.com/pallets/click/issues/3071 + # https://github.com/pallets/click/pull/3079 + for name, value in ctx.params.items(): + if value is UNSET: + ctx.params[name] = None + + 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: t.Any | t.Callable[[], t.Any] | None = 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 is None: + 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: + """ + # shelter `type_cast_value` from ever seeing an `UNSET` value by handling the + # cases in which `UNSET` gets special treatment explicitly at this layer + # + # Refs: + # https://github.com/pallets/click/issues/3069 + if value is UNSET: + if self.multiple or self.nargs == -1: + value = () + else: + 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 + + # Search for parameters with UNSET values in the context. + unset_keys = {k: None for k, v in ctx.params.items() if v is UNSET} + # No UNSET values, call the callback as usual. + if not unset_keys: + value = self.callback(ctx, self, value) + + # Legacy case: provide a temporarily manipulated context to the callback + # to hide UNSET values as None. + # + # Refs: + # https://github.com/pallets/click/issues/3136 + # https://github.com/pallets/click/pull/3137 + else: + # Add another layer to the context stack to clearly hint that the + # context is temporarily modified. + with ctx: + # Update the context parameters to replace UNSET with None. + ctx.params.update(unset_keys) + # Feed these fake context parameters to the callback. + value = self.callback(ctx, self, value) + # Restore the UNSET values in the context parameters. + ctx.params.update( + { + k: UNSET + for k in unset_keys + # Only restore keys that are present and still None, in case + # the callback modified other parameters. + if k in ctx.params and ctx.params[k] is None + } + ) + + 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 or ctx.params[self.name] is UNSET) + ): + # 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." + ) + ctx.params[self.name] = value + + 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.ParamType = 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 process_value(self, ctx: Context, value: t.Any) -> t.Any: + # process_value has to be overridden on Options in order to capture + # `value == UNSET` cases before `type_cast_value()` gets called. + # + # Refs: + # https://github.com/pallets/click/issues/3069 + if self.is_flag and not self.required and self.is_bool_flag and value is UNSET: + value = False + + if self.callback is not None: + value = self.callback(ctx, self, value) + + return value + + # in the normal case, rely on Parameter.process_value + return super().process_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..2e98a07 --- /dev/null +++ b/backend/.venv/Lib/site-packages/click/termui.py @@ -0,0 +1,883 @@ +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): ". + + .. versionchanged:: 8.3.1 + A space is no longer appended to the prompt. + + .. 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[:-1], nl=False, err=err) + # Echo the last character to stdout to work around an issue where + # readline causes backspace to clear the whole line. + return f(text[-1:]) + 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.3.1 + A space is no longer appended to the prompt. + + .. 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[:-1], nl=False, err=err) + # Echo the last character to stdout to work around an issue where + # readline causes backspace to clear the whole line. + value = visible_prompt_func(prompt[-1:]).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..7d0e794704b73f28d0df45d8b110478ed8d05f59 GIT binary patch literal 483 zcmXv~Jxe4(5bfUSnf;hu15wc2WRM+2#XwY0K@7yikAr5Q8E0B)ce;D&p51jXyI*m? z;eLyum^6q77l@f)W@PoL6});?kE(jqU9Ze7H!EkZOaaYh0qVGSaxX_IHA31m_#pd2PL5+LW$Z% zCI8IkGxrKzX_L#G)%>=03pXQMvnz4SCPI~ZVp*Y;)fG>OBZt~>NA~k#;KI{-T5%U0 zjEvPL!7koYR-EY{Land;3|G^Qbn_&caUFk5bhTm z>+BLtb5&;Pn5%JiEG{$H%lj}e$gjE0zQ3@-n0L%rI-I)Jw$$aQ;=5)J&iFUlMS#}; bWBiQHAJF*|TE0iik7()d%>1v|%!2v>qK}CJ 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..eaf5b642aac099e9ba2f01aa3b6f3ad8c2ab0bcb GIT binary patch literal 3936 zcmcgu&2JmW6`%d$_lHFKOLCgfvD1`^P1$YHrgB@Cq9|E0MH!-0#~Zra_3lPmiz3z8 zm0hX|Km$6&un#H{#5x*?4>5e{|Iv$uAcZsVt*5=&B~Lx|y;+hbg%~JWw+qZ~=DnGn zdGF2d&CFlp@d$x0SN)aE!i4-Ch2E!h8|}YA<32HoN=!i&Oi>k0NtH}_hp4it04iqM z4D1MM0O}yrL6OW7Gqgj@uoZeN`SYk@u8n{;I-rekZ49(=E8HI&<=O;jlLOiq*N%X8 zbU+&yi4}d^HC9c46zfY#km7x51f)n`8f~VshqhXgrB&O>tT)Wfnw43x>K4^q%gN-+ zmAQe{4aQDIiuzRxC4N{gKF|LS>Fgj!Uxwleq&pI`hxP!esSUgRVInx?xr8H(ck8 zZWxVC?$;TkL9Oa_-B`2gW;J)ys^6@Z?CVv>cC9n;!#pngnTM&3pe`w?k^17?lGMT_YS+gqY3`s79Mvg@u}zr zdw-zb#f|6Rw%Gf-cfbhb-Ul*i`njTI6(*TBWf8~Ksq5Ub-BlJ`v0UACDGLH~u)#SE zF3OHo`-I7LecfWpO}(~hIcRVulku4r(lonnyPCF@>IWm&(~ZMO=R81*bVB6tu|4_A zxzDDbrjOpg@aGE;e)4Vl-Dk(%dLTbAzd82)uJUZ;=$^c1KAiu{JKvo8;M)dDsl7ZaZqr;y>>8QJEScJl}SD= z?=e8x|9bh>{wb&i_B;r?F2F4iG)1Uos3oWssAZ@FW(aNuxCxqpY?wuOAU3Jfphj;# zT;ShHs{Y1fz7HL7c|WN{`Zn}1q3+<+y||Go$bdGlDY)2}c_p2`<44aEc%?+=?XcqsIF^C65GyeS5*#(v7b?|og_ zPo8}eI@`@)!NYSfE7Ckv9I_$$Lu_+C;5A6kB4Fy#pCe2n{04#V60*flYaT6xQ&1dC za!hMMdAltSK?lTheyZc>p;Ygk%I(Y0Gmz?-<|3rH1nDh9YAb5c45%S9sD{mu8ZpCa z)QqSxGpfeTn3^!-YSK)oBW6+^HAmExIjW}Nsg-6SjMxl3FT6Kl0q-q@48jQn%wi7% z=%EW9rmKf>@Kl745vmB+5PpZCA^aXe2Pi)}bRc+4nJNL1n6y}&X3Fehu~=q-tHn}j z;R=(dO3OtSoX^h|%S(AC7p~^ZOu2G#ZmGzW#bTwn#Nws7*^5hj3a$7Ni*gaBLc#Cj zQ=*vQeg4!a$GX2R7g0)bsk_w6Zd?*2e=fc>hzB>e0IpF4JRY2@06XOAkz=hQLZRQ9 z!PYdwY`?{a6rTsk(XrM%YA+%1RvB9*goR$~_PkFET+4vc|Nbwun1Yw3hm7}-*xq{x zNKo%I0w$M-XQ?-VfT8eA1PkF4gcXEU1RLQ7!WuxCE(0EnDh{LwvrzuisE%VS$1tiq zzGE$j>KI0K45R9|dQru-zCWsOK+mg_t*K-K{;R6uHft6?B|N+zJbWv9P)Io&JV^Y& z)FN`1Nz-%lEKpupoX?k7nA2Lzmr4ht@h6ytB4BRuXEAVWWVAJdPf@d61(HHl9m@AiR(zL4F<~!9+`X8i*rATGBrP zf^Y)iR2y3yI-!s-xf|#Zs5(a?!nxfe9RgKnJS~iU*6a|dI;YdZxZfV{oR)>uZn#6B gdJ!X$)ZOux{9Sm|uTpo9x0LU~>AP>-4)9q03ykVCC;$Ke 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..9dcf7d725c9ccc67b6dff38c2a2a9feeeba04af6 GIT binary patch literal 16403 zcmcgTZEzIFl{5SOG19KI`eKp92=uie1O^N?2(Uf@BV>aV1G3C!(Trfle#kQ;K*|b} z#K{Sp#3HVXM8bt7A!X@I3aFwAr!I9N<@@2QyQ>HPR{NtLv)mo$2@bP0#E1)!lFYAt%Q{L8X4qLh{VQaTFZ0oks6u?X&d)U$K2s^u-VWyi2 z=XB?gc5^5zh^s#XCPtJ+|9!p!QLm+13~lgKbfPSFV}@y=P=QwslHFAzn5sf5xWPcArTu;3I*P zA>Myh@(&2nUS1S~kyEnuXfV>n3t`y?7tPU7R3KNRr_Uf;&IKb}C?q@KKQIvVOS~xc zD#KK2L+a+~t8g(+@f30mI7W9HIm6pjw}~@CZRSi+TR1b+R(#)X8)t>u&cR!DJ2*Sk zPM+Z$Z&Mm?a)z8fM$YM!1U?WxDg*`wcwzXSgN1^3A{$^u0%L2%!QRtsK!kfPIw<+- z*g&rYFNaM5RuTdcaUdY@5s8HtKR?9wMFlnx3K3EPNfLr52PGc*AWzr;ph|3?5Dl|o zUOFA+*qU=fP~vNSHFfN{(?NJrP-Hni#GeXCJjY5=HaaK}TFueOSzeHMfel7PDG=%9 z>q&cWYGMhikYRZLl!a=XiqSF34_8Ww8Q=~lmy{uDitd0(DE2R4g5Q6RaD$UqWdnMZ z5kv)_Q8tNus86=4xb_r`7estKaPd#an|Jn{iwb9eJH32Qq+b#@0u!Qx5oF%RUXZJv zlOR%jgzKq4%SX=kvXU%-k9J=m{t!LX;vp`S82w?YwUZL^p#hj^J;h5n*#bV)XAlbEPc}sYVO~UBmK92{#p(B_5Mk`A zvd6B0N&z=D{Ku}MF=_n5l?!oc+EtgZ)d^kz_G&|f8#FU6_&wbT)i`CKVAyb#UG!fi zNW}~{>F?9ptB^O4?S4Nk9EV+I`udzdLbjNdQv5@`qV@n$nT4Xee$+LghUl#QCcm$R6;C_!XgC{HjhU71Nq zg-`=HQ#26-5j&>D83qJ0yX1hX)Bqv zl_zcG6Vi;Waxq6WGx88REyd9hnxiF6KKijwRyj)vH8J{|RWVw!sGxqEdX@ekq{RFM zI3y5B!|`g666hg=9ZXg~azCq#7{FE-RF~LEt)rw|6{V6Aj5Kwe8Zw@v&Kr+Y=V+g) zL(YBmc=P_oBZvI^U+L^>ZRu+B*%W(Wh>EfmjCfFpMr5NnB+3pDR^l-I{?s)ufH{#Z zK@kk)keu77`o>m4K$oJJ8H-4~uAHO%`xWekdio*^a=2jOlqq=60Yp3r70g*);duF# z@=?p2bM-ah`ta4^q|-O&DonU4;%D!9?w8*!PuA>xu>Bu9|LMfvpGY>pK3BYY-e9(` zn=4&={m|7zqldn*Q3Vz6?@cgkzkFt;+~rRw+P>;jPszLy{{JMRKL5tbGMR&7fkdjc(8y*m$(=KZLqK&tBqKp<_ahavJE0Hh~K0k0pDbbBD$&AbT=Yl zg+H+ws<){x3?{SfiNj>Bdcx4=jZZ8l^NV=(!V?Q^F2|}2tEwj!hk4z631!Ls!eBL* zJThA9>AXGW_Kmz(-^6qGZlhO67MBn~i7c?Lwcc@X8&5Z_{yYbQ~z zgG9Mb66KN@w>yV(0yLLnpmuRNP`kNYsPi}%)cKqnYR{0#moGapobQT4aK3fR@ZXYf z@<4bX#D~FoV|1$pr)soHLex4o8eyRi7d?!iVpUNIdZp7mizXO?=m^IK`yjfN1_mV(PeZH=@w7CQBAJRPS?CgmkXMS5;gJ}S z?Hi0h3=X5{g-Bae;^5&@dhhC<*K2F{?(E@WyL{_?wXX*@4mWP>e#2+jJDi8mH)>x$ zVSNK2R%q(z#mGr5ny$h;Eb`MaQ)c8WY5g$1R)aynPz8XJG<&T(>GT=!&?DxU`8+K+ zXiCaa2cg>H5eu;i7}aGJ4Z|8UGt_xnbV7d&I!TFHRZ$tSf%nw>hYF{tesqdi1?dQ0 z8e;&x9>rPcaI1~N9BFxa@*Z$xlSvPb8YGh_`N0ZiMZGD0oxwpt3z0LB|T0J|}UR zWL(0l_<&ciYDa7bU;#bUP`N;PiU{NIi-Q9LQCLKBvZ0TYi@;G!eAs_FAc9qvf@gU@ zuC!#^=>S}!mv%*Xp7W;(h)$pmt2?zQMi%Y#a6yJG(H3Hd0U}z#e1ZQcE{A0pgX^(% zxE=$yQCu0{H`z5^v<2>+e=IB>KYHb8+;qi1>X>&>?D~gmcHKJjVHiTid4thjFqcihyCTF>COq!IY^(^QLj2k$B!+`xN*rXZ6y)IT+ z8RL!(?oHJCv|&JKyHGoYI+%>ib(B*)9UTmDWankLI8%=@07KY`g$fqZZpvNoUhGor zp=;NKgt0ALOm^KqF?Awg+qHOQf=Wvy>c7C&E+tW87U5sgD-*c;eUOqg3DWZnX>7gq zNgw?_ozY(>_{r$6c?cM3s-)K`1_`$kzs!X-N?dVR^*)6{VKL47l@(Lh>6=BJ%_0rAE2gf~H;cMX zjId(rI(@UKSAK=D>-5c{Ui}rQ>-5c{j{8ShWyPGq^;uTQqK?)tt1M5QSdz3vuAg(`dhvNeI1=yM1R{?pwBMutI!8ukme8uq*-Of z9MaL8MQ`vz7IC;;F?}7~SwtTFa3EBKi$k#Nl?u^mX(nMSqVMFX;1yHX>6=BJO~12xwPNZzeY2?R$nJ`%>-5c{t|PfC zrmoXBi@J{7u9&(`-z@6OdyJRVxk&$KNTiO$XHj3?W9U#P9wRN$%XIy$q6{_-AUdHO81s3`P*PD|+-Sl(kS{{$V)!6#%;U*2CV zPhCfIvZycbEtaRQqd8gBm-iLRQ`gZPq#iW=9L{s4W-3+G-8wkU!x{0dCF@Z*yoX&? zNX`%}&?wuFw05?3`5W8YWjop5^22gkwlp0%uy22t3>#LE^C93eO*Xb1I3!y-UO958 zv0X4>i@B-2vH75Ef^{`7;9^rY9%*fn&HIkDwsy#tQ6m92*w_qBF( zHOi*u;)IG6p%P9iK^P`dg35PI3zb@kW6W!g!lYV9EpVo=J86 zS}WeU$X)7zX)rz*?-W{O0B|eduC8ptoCMi~XR+DKbOATBhF51U&$G7ez6}WCPk<$G z{N!}K*YIw`Pxj3lY6@~6yI0M+*CpNSZl0R0-jS@{k*L}^Zv?;}5x^$h?9Ck??7p%4 zUhVx&cQ+;0HqDy>hzBd)@ti9;H?1G!+{n3g{`Ol_Zzb03owp*;20;D3b_6@9yjA15 zS8{I_e^7d(6#8D6x{zS^%sUatAdtDjTswC?b~SeE*zKOFo<#Z1`5Xl1F45D4KsN$i zS6nx1KB&7?DbZk@gzo(d<{G|YPtSO7q6ybU)R?v>0w z*O+{+5#P2D5sH@RU5vmI1ZKX@$ka%J-95hwf!+nc1iN{DH8z)$Csrrj)whaomrj-5 zJAePe-3t$-L~Z+g86uPugvzA5^5(e@VmD&uqL=xp(@0_-^j}bw7ah4f@_F6Ogwg%%(|Bl1_E2U*Md>0)BnXGeB?Y;lau@GRT_2;-#t5;N(M22u~G|e4k{aj zaIw?|p~%3oOJ=WBZy_JrwIeZ=B*~M~k}@LC0}lF`tkRDMBUvRgnPZ7w=wq^q>g34A zx6XE=kO#E11Eh54biW}jb;PEeq~NZtoJW#D;9NvK29cBlmrV#X_k{+<)8xoS_&PKQ z7zr*oT1T|uyiA`#=-o!VuR*1FikQmHu;2j}Ay!u5 zXgH=$O+4n;02b2ADq`ajlck-7raOr10oRefSFifDvp}^4R?b>ZO20eZs$PAli5O1b z5QS%UbQp4#aJ)Xd66rYbxIsBzQ)U)3Ae7@c4DXdp0xMo&vg9Ja|8-~_F3g-mEkODu zfW&=Jr9A#S4LB9ATzX}qIbJZsRAUy3_Xpm1%LfN<9GtD({;+cUf+@TS%bZ_O~9 zVBV^BjHPBSQ^{~xWajGNO(BVxhEr1t4{)+eT5U$)R9a6_msipj>J4}iJhAP^XJ!>u zO?qH#BPKYzru0=8PIOIbsxhtPBI?XDJVR%u)n|O40wp$&7%m?$p{(heh?qgrlsWz8 z=_d~ve8%Cw*3Mv#Vv;R6v^oW+oN#;vIS8rbTIIY6j&YRpD>#b6v)KWX;TstuISm?_ zWwRO7b0j!4OP%W?4J~~E4yqu_LL-%txqydWL|!|5Hrbi#>yL`Pke>k=75--U9ch(q zeQ<;YuOUG4?LZ(RyA{g>2U@`hq)wlgWJc{9z*AhyDIq#IAj(EKjP_ZSvtmq;k}bW1 zf(WVD=5RpjJ&mzFBqhs6$ix-VMB{K$39G_4;C{F)Q}h>^!v}yOjzR_JQVf;vfs8Ac zXV$eQ=~@#vO}nZ_O>>2-W(%v5g;leK^~u8eN$IzR+u)#eRrz)ARqu~WFTFh4I<^(m zVwR~$G8OU4Ny{DcBL)xzsjqr;473Gh%zrtgS3* zE1TfrZMT~5m_9r(W81D+zf22-&WY&IMYsU#XNVckfE)`if^Hwo}bcG^V|X5Q70g?iS_@3phc-Wvspjm56VVo{jIq-EisR*+`2(0z2Vi z8|{&MZ0kF_7MPm}Dc(A{ZsM&+%%%nHGYmU#rkG-db(t;z2S8ZY2Nz2^jw)bAW-q|S z0xZ*VrNOZ1M+v~zOy`nj5OKe`AlH~qWZHl^hU#B@Y1qH zY0YBYUqHX%l1$cR>dJ2cD&j6t+Ki*j)+P&UCyVcFm@eEi+J+26!@e*6+6+^N>?&Ez zF4P~wu6$yxW036$`JAoklydxRA!g8H7N@0owP^V@s@$AJXGAO5U7x&a_ z=>H6K#cHVjjr#H;mGB-*HXi+`@n+{_-p^i}eDkNTU)wtI=C$p20@JH^0OUW3cz&y@ zhL-7FpOaVx(x{-fK5I}FG}ge5-g2xF>C5?g%tU#bdcWLkALT}Q0?7`~U#v{qbBZy(H$i@=yJ$4$SsqoiI_W(;xodVqLvlmIN1cy0G){XDPZu5rBCh=8w5}s&fY@z6>OW@N>3OuXkZy7rmuWyIyTpu`zBOWsnK%QvGQ*XTqrB9JB}0yM zWBywv%|gMaXEAfk0^gHZ@p}?b!IweOaFk}S09EPiW!-oVK7zw%!wAtFWEFS{Y6ujv z`k*;W7DcB5&8%a89z`oqT$?dQo#+&t*~&(T7I3fn{1F>xh}oP}AB-nv>w_O>z}gAf zhR|leW{T1H<|MARk2o^MpvAZ8_lntLjwMHtk`*P&@Hsk!3(zrb{Cu>~1r0L&vP>To z{t{s~pn`Ar=th}tlIdodZh?IMBM2G73eklVP{|A=SBbn|>=hvMNp>iAp+kKoq{xf-FNhC)E((`Ugcx%~K>=iwY~7iHnx)n8xcT-xZngQdo-*T!$ERM5fQn z^pJkO;YC0hF3ME#^aAhS0VbA%ms8Zc_nkezTeW7)Jm)EyXqhdoOP1C>^wiCni=K*LM_Rh@;P_W*qc}Eqm7?= zS5E{cj!YC!(v#1{&)zxw5q+oa!E+DRJ_tN0PI?Y}Qj_!?xzsY+IQk|bNdoGM_~AR1 z_v`Nh(TW+S5rXI3HA?7`QY&DY@);S5(9`|Eyrm*Ny}%{yf58lW8%znL_3AA()i9Wd zx)BTxe9MU;HH6kCG&dxKfiU}jU4EKJEHO(u#Ttzun72JKbH9!u;IvPJI714v6EJlY zJdHVGjafNj7C93!ouQ0Ph&;lr1r=Zu^Q9U?Fn-^Gr7Il5_{<%`UjZ)h?L-%4!{#kM zdunC(N@p{y?1Z-w<2zW5Vuj98Hj_^!g`Z&q(Lp!nd*cK33=$gdVI8V}*N(!q>6FWx4QOtZ-c; zV8}yOMgq<*Sx*XWc;&?kGYAC;50nZoM2rJc-@(8t+EX^Rc6|Mn^@*~!>HK{c56;DZ71XrjeYhE@5V5@?hB9ikrauzAz{u9vxBKb=4 zyaU@%zm-EsGucfMP>oYb_tBI6kZY`D<&(Ev$N|~bpnPt$M|c38P;SI_s30$!rvE_M ze@8ifN7?_C+BHM%`aRV)O||`=s)p2Vr|Y71&S*~<3qQ>*d^dP;-!seebjeuTGYbBm T4bX>-blF(-e^B^OUi5zePXJNF 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..20d45896cf8c52de629ccf674eb7563d19aac0dc GIT binary patch literal 3541 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 EKN4pbg8%>k literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/colorama/__pycache__/winterm.cpython-312.pyc b/backend/.venv/Lib/site-packages/colorama/__pycache__/winterm.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..05ddbfb8625624e25060c3f9138a17c350bbf117 GIT binary patch literal 9079 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 I%${`q7c+g8tpET3 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..08f57ef4a652614876a5bb760343f0b8b6f204cc GIT binary patch literal 189 zcmX@j%ge<81bQ*HnchJ9F^Gc>KC=KtrZZGBXfpb(WGG?+@;-yq{EBh5iYd=8$}TQQ zOiqo-%PJ|>O-xSCFU>2-%uClz&M!)hNlHx4PR&b+(JM>MD~s{TOo}PaEJ@V`YRFDZ zPc4o~&dG5r~UHjE~HW KjEqIhKo$U9Ff%~_ 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..dbedadd9f2ec668e6c945a8e3aedebf872c63b35 GIT binary patch literal 5458 zcmeHL-EUMy6ra2IV{f}{p_EFuTeS$N3;m#FrEEd8v`eX!B`GDycFktld&S-EN1b~M zZZ)P4m|%kOv1vj=O-wAQe}I30Z$7QI0dF*#@L+grTAqCJoSFUZ1#=%YoriN~&dl%3 z=e@r(^HXzkBZ1TxeLH!;L&y^>l#*P`Y~P2>648hzq)7y|D=lPP5m!cxhyu|>O-f4{ zIU;A2h>~$f+{`AY)l5UAK_EIw?Jv2k=!ggG9hGt^7io5paiS@Ai00N^Ya+KtTJ$}d zI{PLeRCN(uTq`ygNM6Vb{)VSm4*Ok}I;|V#Xxz{(DHBg-pSr;A7cJ>rJTYrY=W|rI z(OB3#ph^Vj>wtoPzL_Q;_>RPa2GK*7%oWw1Jq?A&wqSuO8Q!Uxn zaFUP&C!X21b6iQj$a9`N6vBSRYKa?$PR(%641GKwPg|0ipVKYT$Qzbom|AY$qz&MY z6?94;3YKK(=?@JYbobvMj1EU{=jg047fO3 z_TAF6x1y8D8&M-^>b(G%jo;LbXd;)+(Re1_Z^9}Y{c+gB7-swC@|JAq=GD1{meMBl zv2qJ^ZJY$LNH!JH(ELdC6;$8-v2WYH>-?tkm#&`gXV=x?$7+*J#fCb(4MSBqpcvA8P<`T_o2BB z1Yb_tjxAJEkJGW-?d(EpdEO-xes=~sTO_}=ci$85H8S;8BRv4dnn~f1*rdiF_uMmD zo>rtvJA!Pk$9&bbz-x|C;0g-&E;F}%bU$Mcr zIKX$?;P*Jdzh;Bq>i~b)2H#r2=ZSw`ctQ5foH(9gYJjUju1;_j;OZ@|PI5KGRgkG5 zhX*-4$l*Z_4{~^r!-E_i9Lo6HEDxtC#!=J_L$%~{lOv-SEpaL|X367Ip-|XTu7@Tk zFJFV;VDf6na$g!54~3^kENS%mNZ69EU6_~-S@KlqN@&_@o}3uJFwI=VLhoB1Rs>gA z;C0L;7F$>yca7zyBJ^qqOM6(U*j1$(yTlUr#kz*#j(`0=WI7CDMog0?Z_Gn+!B_Ry zudnpN%#DwLdlw1gw~m6^aex1V&gIUP$hvyG+Sak$u`;}__Ep>L+WD4!E2(vLpt_xR z*}L-Iy4qiD>sszwSy)#Gt8I4e?D{C#ige9K{m6T);61hq<33g8^O4tI@cLI_ggIbWW2YdE$?kZ4ZeW)euTaF@82gOo|VE2l5d88XoH}jFp%-f{9C~5 zs3nd~T(Xq#<*7>}la_LB3S-6{XSoeyIQ9fpb(p(qg1EZc5T53)m`8r$UHR!^Heyxk+pgB*tt8~{Gf#bW-w z?5V?2=d(!@*M;H}1eLIn6o;oB{*S=`p0XA8pwZ0T#wR=W(8OLzD8{*zy^i3uj*n{y zbHga`t)uu>a)wX$EPV%T_$FnHgV+=WL3lzM{~(9{B8Lm)@bBcvpDnFlr@l-rdLEZD k&y+L5;N4H25m1|-3q)$VyYRE<{Z&%GIKL?psgrf|4@-Q4EdT%j 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..3f88347896f1b9c07c5395ea0d940e0513bbc144 GIT binary patch literal 17997 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 BrWXJJ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/colorama/tests/__pycache__/initialise_test.cpython-312.pyc b/backend/.venv/Lib/site-packages/colorama/tests/__pycache__/initialise_test.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a719310326c2be315f60e3a1be6f812fc4893bad GIT binary patch literal 11645 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/colorama/tests/__pycache__/utils.cpython-312.pyc b/backend/.venv/Lib/site-packages/colorama/tests/__pycache__/utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..493011a73a475b3913a9bda74f270b198814fbf2 GIT binary patch literal 2461 zcmds2-A^1<6u);qc4wD`QkE5iNSDxxi?RfbVz4#YQl(Pe8sUY_CgZR(;==9>-aC|T z0|}BPrqQJIMf?{Cn)v36FFgA~6C25ZiHSAQH<~4>G(LFF%_O?ztc5 zckj99$L8iRfs)K#$`4C~{DzHck$t7|H7FZICps;VBF#{Wx=;{`Vn%dzu^?q6z{G-_ zkp(hFbg4{q*$}rxZ;njBMFW5a8_=LZb)`(U{Dm?Kv_lQ;5VXS$?J%^P8rn@IF%kI_ zM<=M$lCw$PQ=2guAj*Wz^5)FD*V8$F1-GJpqtXV-1~Ev6>LerRv`jK$Nl1uJ z2nHHjadL7hS2eCqfDToFDHvFy2_ZeXNj9k?aij1tN89-0snL<_qQ&O;yp}Vv=B&*J zv|P?wFm2e&K+a-Dc3R8L8K$01-Z0D?+4u6(S)R9z0T?g`Tj$xFRj`;=)CO&X+k9}r z&KG!czT^b*T(j-ct=8K9k{%L*l{uc*3fVmqt$;$(o06lbs;LzXRdvFuTD0_q0_qV} z{d7Sqcs(ovwoF0MjG_repehjOK@eq95vbhm**^<<~zf;hgYubwzQQmm&f*`kgKhY9dW$0t1l<%=?;Da zy-(+0-GN!0@jqTf~{T6bG1CQOl+LZElXs}58~G#{B3-aPQl?Gix}RJ1L529@9LB7`h7lqKbJ@e zoERdUE((-P!HSf8*?Uu*B8&71ywAh&=}3rahYmR{A54v2O?~*jdiDCmkG%ZtwjN+v(?{x{zmvWzItjLlu_9giF1PC_}e(imseEIY7 z&&GGooVzE*_ggx@FjvO*L(%oI`=PF%x`)2&yWc&sr!+qj$+A!#mO5 zd&>DoGJreXBafkDC)D*fe+A}UO{89@Tai@1_`RI!mVZz{+m<>3-0qfBeWC5%AR_&8 z>eb-(U=Z*`#0mSUzL1}0c;6f$Z!vs~-23S|?d34{y~k&=?zQXIiM-$_7rpHG78?R% zJaAqDaUfDkedcnmW3ZS{^=pRBg*2e$< 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..ab0bdb3dfdc1dead1218d2ada6a408b924f97aa3 GIT binary patch literal 6603 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 M;hqrphady=-&#$BqyPW_ 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..dde24a0 --- /dev/null +++ b/backend/.venv/Lib/site-packages/dotenv/__init__.py @@ -0,0 +1,51 @@ +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..a53e49956d765babec0b99a2c50df945b9ae49e2 GIT binary patch literal 1686 zcmZ`(-D}%c6udl-H5mbX3aT-i>tl3rUsoqO(2=iKwtx%w%e z&mtJ*+BNHE9-%+!WIS>sXwVOp)ZjdW~gnN z?L@IX{n#6fyqU-yo08?X!wt_(L}G>!aVrK5KOP(y^g2`lKq3aSRH7}0K`e@y7(E-Y z8PrB4u0jOhm6&8YO*;y$nP0<31K9jimQc~j1cga}fCW(1e{U^+T>Hu+n}M$zX3cGe zL0LBpFLFc6ZIlgSTWmqmwa={eT404{86Mcw8)i@&R(@I2EY}J(ZP9NJ z)6iTZO_c}OM!)fw|KQ*0ee{CAbO;WV@V*{yB%*FmbrX(?CZv)k!rcfIHfTxXLG4tJ z8&EgZqrq$mF;9xI&^)Qzh>zKre}o>h$126>ja)89uW=c&dV1WLIT4X1*WbW8nU^E) zV?O3uh)kc(#zM?JLRfgr9mjUhoX(9;a4_Gbio7;rVH~A-Qoj-F+30=~`uN_DU#5*0 zsJa@21m3qAL{_M;+ooFgh)N>YrA|F1Y?!vK1_rVGa50-zVcZVPdSs_m!*g3Ep)CWk zbkc|%(+vaF*Mq>sYUqKtuCEizP(wY~OrHkly7@oGn(Z07y{1CyHORfD8lL0mE?!Le zi8$=DdtCXh3Q$)Q2L5v;4qC|fp+OVA=~-?f&|3VGNT#4xQl#(}g=q?J10>QYa6r40 zR-&rp3|%PD!)w@cWX~x z*q4-J=dIqS-FQ!)-58?Og4yJXbEfROWtF=AJ9_zwqjYA&&#m7zqdJ zqzMyA({$U`w5KTD$52Fh$?~W{{tRWkW~Nx 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..c48d7f625c175c199a2141a238f3516ace58d8d8 GIT binary patch literal 354 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/dotenv/__pycache__/parser.cpython-312.pyc b/backend/.venv/Lib/site-packages/dotenv/__pycache__/parser.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6899fe27fcef8ee5257d625334d6a4f874af9602 GIT binary patch literal 9980 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 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..6fa41014832b6b0d0cce62e57e6708fdef62cd1f GIT binary patch literal 5022 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 I9u}4V1yXL@djJ3c literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/dotenv/__pycache__/version.cpython-312.pyc b/backend/.venv/Lib/site-packages/dotenv/__pycache__/version.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4ed501b19ca0a60877fe050e15be93638340107b GIT binary patch literal 206 zcmX@j%ge<81iCS{nPNctF^B^Lj8MjB4j^MXLkdF_LnWgoQx&VBo{^rRpC;oi?)dn! z)S}|d{Ji-1l?VE}0Tg8;;7iAY0BqpcEn0{A=a=S{Wag#oCg&HW#v~;s zXQ$?+#ORf!=9R_xWG2NFXO^Vu0yShOrl%Iiq~wlIYq;;_lhPbtkwwJTx+ Z+5vJ{G05E?m>C%vZ}5pWau=}xxd6baIF 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) + sys.exit(2) + + +@cli.command(name="list") +@click.pass_context +@click.option( + "--format", + "output_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_values(ctx: click.Context, output_format: str) -> None: + """Display all the stored key/value.""" + file = ctx.obj["FILE"] + + with stream_file(file) as stream: + values = dotenv_values(stream=stream) + + if output_format == "json": + click.echo(json.dumps(values, indent=2, sort_keys=True)) + else: + prefix = "export " if output_format == "export" else "" + for k in sorted(values): + v = values[k] + if v is not None: + if output_format in ("export", "shell"): + v = shlex.quote(v) + click.echo(f"{prefix}{k}={v}") + + +@cli.command(name="set") +@click.pass_context +@click.argument("key", required=True) +@click.argument("value", required=True) +def set_value(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: + sys.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: + sys.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: + sys.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.") + sys.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() + + sys.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..4e7edbb --- /dev/null +++ b/backend/.venv/Lib/site-packages/dotenv/ipython.py @@ -0,0 +1,50 @@ +from IPython.core.magic import Magics, line_magic, magics_class # type: ignore +from IPython.core.magic_arguments import ( + argument, + magic_arguments, + 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..1d6bf0b --- /dev/null +++ b/backend/.venv/Lib/site-packages/dotenv/main.py @@ -0,0 +1,435 @@ +import io +import logging +import os +import pathlib +import shutil +import stat +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 _load_dotenv_disabled() -> bool: + """ + Determine if dotenv loading has been disabled. + """ + if "PYTHON_DOTENV_DISABLED" not in os.environ: + return False + value = os.environ["PYTHON_DOTENV_DISABLED"].casefold() + return value in {"1", "true", "t", "yes", "y"} + + +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 _is_file_or_fifo(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 _is_file_or_fifo(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 the environment variable `PYTHON_DOTENV_DISABLED` is set to a truthy value, + .env loading is disabled. + """ + if _load_dotenv_disabled(): + logger.debug( + "python-dotenv: .env loading disabled by PYTHON_DOTENV_DISABLED environment variable" + ) + return False + + 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() + + +def _is_file_or_fifo(path: StrPath) -> bool: + """ + Return True if `path` exists and is either a regular file or a FIFO. + """ + if os.path.isfile(path): + return True + + try: + st = os.stat(path) + except (FileNotFoundError, OSError): + return False + + return stat.S_ISFIFO(st.st_mode) 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..eb100b4 --- /dev/null +++ b/backend/.venv/Lib/site-packages/dotenv/parser.py @@ -0,0 +1,182 @@ +import codecs +import re +from typing import ( + IO, + Iterator, + Match, + NamedTuple, + Optional, + Pattern, + Sequence, +) + + +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 == "'": + (value,) = reader.read_regex(_single_quoted_value) + return decode_escapes(_single_quote_escapes, value) + elif char == '"': + (value,) = reader.read_regex(_double_quoted_value) + return decode_escapes(_double_quote_escapes, value) + elif char in ("", "\n", "\r"): + return "" + 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..a955fda --- /dev/null +++ b/backend/.venv/Lib/site-packages/dotenv/version.py @@ -0,0 +1 @@ +__version__ = "1.2.1" diff --git a/backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/INSTALLER b/backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/METADATA b/backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/METADATA new file mode 100644 index 0000000..48ed40c --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/METADATA @@ -0,0 +1,562 @@ +Metadata-Version: 2.1 +Name: fastapi +Version: 0.115.6 +Summary: FastAPI framework, high performance, easy to learn, fast to code, ready for production +Author-Email: =?utf-8?q?Sebasti=C3=A1n_Ram=C3=ADrez?= +Classifier: Intended Audience :: Information Technology +Classifier: Intended Audience :: System Administrators +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python +Classifier: Topic :: Internet +Classifier: Topic :: Software Development :: Libraries :: Application Frameworks +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Software Development :: Libraries +Classifier: Topic :: Software Development +Classifier: Typing :: Typed +Classifier: Development Status :: 4 - Beta +Classifier: Environment :: Web Environment +Classifier: Framework :: AsyncIO +Classifier: Framework :: FastAPI +Classifier: Framework :: Pydantic +Classifier: Framework :: Pydantic :: 1 +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python :: 3 :: Only +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: Topic :: Internet :: WWW/HTTP :: HTTP Servers +Classifier: Topic :: Internet :: WWW/HTTP +Project-URL: Homepage, https://github.com/fastapi/fastapi +Project-URL: Documentation, https://fastapi.tiangolo.com/ +Project-URL: Repository, https://github.com/fastapi/fastapi +Project-URL: Issues, https://github.com/fastapi/fastapi/issues +Project-URL: Changelog, https://fastapi.tiangolo.com/release-notes/ +Requires-Python: >=3.8 +Requires-Dist: starlette<0.42.0,>=0.40.0 +Requires-Dist: pydantic!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0,>=1.7.4 +Requires-Dist: typing-extensions>=4.8.0 +Provides-Extra: standard +Requires-Dist: fastapi-cli[standard]>=0.0.5; extra == "standard" +Requires-Dist: httpx>=0.23.0; extra == "standard" +Requires-Dist: jinja2>=2.11.2; extra == "standard" +Requires-Dist: python-multipart>=0.0.7; extra == "standard" +Requires-Dist: email-validator>=2.0.0; extra == "standard" +Requires-Dist: uvicorn[standard]>=0.12.0; extra == "standard" +Provides-Extra: all +Requires-Dist: fastapi-cli[standard]>=0.0.5; extra == "all" +Requires-Dist: httpx>=0.23.0; extra == "all" +Requires-Dist: jinja2>=2.11.2; extra == "all" +Requires-Dist: python-multipart>=0.0.7; extra == "all" +Requires-Dist: itsdangerous>=1.1.0; extra == "all" +Requires-Dist: pyyaml>=5.3.1; extra == "all" +Requires-Dist: ujson!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,>=4.0.1; extra == "all" +Requires-Dist: orjson>=3.2.1; extra == "all" +Requires-Dist: email-validator>=2.0.0; extra == "all" +Requires-Dist: uvicorn[standard]>=0.12.0; extra == "all" +Requires-Dist: pydantic-settings>=2.0.0; extra == "all" +Requires-Dist: pydantic-extra-types>=2.0.0; extra == "all" +Description-Content-Type: text/markdown + +

+ FastAPI +

+

+ FastAPI framework, high performance, easy to learn, fast to code, ready for production +

+

+ + Test + + + Coverage + + + Package version + + + Supported Python versions + +

+ +--- + +**Documentation**: https://fastapi.tiangolo.com + +**Source Code**: https://github.com/fastapi/fastapi + +--- + +FastAPI is a modern, fast (high-performance), web framework for building APIs with Python based on standard Python type hints. + +The key features are: + +* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance). +* **Fast to code**: Increase the speed to develop features by about 200% to 300%. * +* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. * +* **Intuitive**: Great editor support. Completion everywhere. Less time debugging. +* **Easy**: Designed to be easy to use and learn. Less time reading docs. +* **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs. +* **Robust**: Get production-ready code. With automatic interactive documentation. +* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: OpenAPI (previously known as Swagger) and JSON Schema. + +* estimation based on tests on an internal development team, building production applications. + +## Sponsors + + + + + + + + + + + + + + + + + + + + + + + +Other sponsors + +## Opinions + +"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._" + +
Kabir Khan - Microsoft (ref)
+ +--- + +"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_" + +
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)
+ +--- + +"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_" + +
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
+ +--- + +"_I’m over the moon excited about **FastAPI**. It’s so fun!_" + +
Brian Okken - Python Bytes podcast host (ref)
+ +--- + +"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._" + +
Timothy Crosley - Hug creator (ref)
+ +--- + +"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_" + +"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_" + +
Ines Montani - Matthew Honnibal - Explosion AI founders - spaCy creators (ref) - (ref)
+ +--- + +"_If anyone is looking to build a production Python API, I would highly recommend **FastAPI**. It is **beautifully designed**, **simple to use** and **highly scalable**, it has become a **key component** in our API first development strategy and is driving many automations and services such as our Virtual TAC Engineer._" + +
Deon Pillsbury - Cisco (ref)
+ +--- + +## **Typer**, the FastAPI of CLIs + + + +If you are building a CLI app to be used in the terminal instead of a web API, check out **Typer**. + +**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀 + +## Requirements + +FastAPI stands on the shoulders of giants: + +* Starlette for the web parts. +* Pydantic for the data parts. + +## Installation + +Create and activate a virtual environment and then install FastAPI: + +
+ +```console +$ pip install "fastapi[standard]" + +---> 100% +``` + +
+ +**Note**: Make sure you put `"fastapi[standard]"` in quotes to ensure it works in all terminals. + +## Example + +### Create it + +* Create a file `main.py` with: + +```Python +from typing import Union + +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: Union[str, None] = None): + return {"item_id": item_id, "q": q} +``` + +
+Or use async def... + +If your code uses `async` / `await`, use `async def`: + +```Python hl_lines="9 14" +from typing import Union + +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +async def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +async def read_item(item_id: int, q: Union[str, None] = None): + return {"item_id": item_id, "q": q} +``` + +**Note**: + +If you don't know, check the _"In a hurry?"_ section about `async` and `await` in the docs. + +
+ +### Run it + +Run the server with: + +
+ +```console +$ fastapi dev main.py + + ╭────────── FastAPI CLI - Development mode ───────────╮ + │ │ + │ Serving at: http://127.0.0.1:8000 │ + │ │ + │ API docs: http://127.0.0.1:8000/docs │ + │ │ + │ Running in development mode, for production use: │ + │ │ + │ fastapi run │ + │ │ + ╰─────────────────────────────────────────────────────╯ + +INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp'] +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +INFO: Started reloader process [2248755] using WatchFiles +INFO: Started server process [2248757] +INFO: Waiting for application startup. +INFO: Application startup complete. +``` + +
+ +
+About the command fastapi dev main.py... + +The command `fastapi dev` reads your `main.py` file, detects the **FastAPI** app in it, and starts a server using Uvicorn. + +By default, `fastapi dev` will start with auto-reload enabled for local development. + +You can read more about it in the FastAPI CLI docs. + +
+ +### Check it + +Open your browser at http://127.0.0.1:8000/items/5?q=somequery. + +You will see the JSON response as: + +```JSON +{"item_id": 5, "q": "somequery"} +``` + +You already created an API that: + +* Receives HTTP requests in the _paths_ `/` and `/items/{item_id}`. +* Both _paths_ take `GET` operations (also known as HTTP _methods_). +* The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`. +* The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`. + +### Interactive API docs + +Now go to http://127.0.0.1:8000/docs. + +You will see the automatic interactive API documentation (provided by Swagger UI): + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) + +### Alternative API docs + +And now, go to http://127.0.0.1:8000/redoc. + +You will see the alternative automatic documentation (provided by ReDoc): + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) + +## Example upgrade + +Now modify the file `main.py` to receive a body from a `PUT` request. + +Declare the body using standard Python types, thanks to Pydantic. + +```Python hl_lines="4 9-12 25-27" +from typing import Union + +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + price: float + is_offer: Union[bool, None] = None + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: Union[str, None] = None): + return {"item_id": item_id, "q": q} + + +@app.put("/items/{item_id}") +def update_item(item_id: int, item: Item): + return {"item_name": item.name, "item_id": item_id} +``` + +The `fastapi dev` server should reload automatically. + +### Interactive API docs upgrade + +Now go to http://127.0.0.1:8000/docs. + +* The interactive API documentation will be automatically updated, including the new body: + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) + +* Click on the button "Try it out", it allows you to fill the parameters and directly interact with the API: + +![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png) + +* Then click on the "Execute" button, the user interface will communicate with your API, send the parameters, get the results and show them on the screen: + +![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png) + +### Alternative API docs upgrade + +And now, go to http://127.0.0.1:8000/redoc. + +* The alternative documentation will also reflect the new query parameter and body: + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) + +### Recap + +In summary, you declare **once** the types of parameters, body, etc. as function parameters. + +You do that with standard modern Python types. + +You don't have to learn a new syntax, the methods or classes of a specific library, etc. + +Just standard **Python**. + +For example, for an `int`: + +```Python +item_id: int +``` + +or for a more complex `Item` model: + +```Python +item: Item +``` + +...and with that single declaration you get: + +* Editor support, including: + * Completion. + * Type checks. +* Validation of data: + * Automatic and clear errors when the data is invalid. + * Validation even for deeply nested JSON objects. +* Conversion of input data: coming from the network to Python data and types. Reading from: + * JSON. + * Path parameters. + * Query parameters. + * Cookies. + * Headers. + * Forms. + * Files. +* Conversion of output data: converting from Python data and types to network data (as JSON): + * Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc). + * `datetime` objects. + * `UUID` objects. + * Database models. + * ...and many more. +* Automatic interactive API documentation, including 2 alternative user interfaces: + * Swagger UI. + * ReDoc. + +--- + +Coming back to the previous code example, **FastAPI** will: + +* Validate that there is an `item_id` in the path for `GET` and `PUT` requests. +* Validate that the `item_id` is of type `int` for `GET` and `PUT` requests. + * If it is not, the client will see a useful, clear error. +* Check if there is an optional query parameter named `q` (as in `http://127.0.0.1:8000/items/foo?q=somequery`) for `GET` requests. + * As the `q` parameter is declared with `= None`, it is optional. + * Without the `None` it would be required (as is the body in the case with `PUT`). +* For `PUT` requests to `/items/{item_id}`, read the body as JSON: + * Check that it has a required attribute `name` that should be a `str`. + * Check that it has a required attribute `price` that has to be a `float`. + * Check that it has an optional attribute `is_offer`, that should be a `bool`, if present. + * All this would also work for deeply nested JSON objects. +* Convert from and to JSON automatically. +* Document everything with OpenAPI, that can be used by: + * Interactive documentation systems. + * Automatic client code generation systems, for many languages. +* Provide 2 interactive documentation web interfaces directly. + +--- + +We just scratched the surface, but you already get the idea of how it all works. + +Try changing the line with: + +```Python + return {"item_name": item.name, "item_id": item_id} +``` + +...from: + +```Python + ... "item_name": item.name ... +``` + +...to: + +```Python + ... "item_price": item.price ... +``` + +...and see how your editor will auto-complete the attributes and know their types: + +![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) + +For a more complete example including more features, see the Tutorial - User Guide. + +**Spoiler alert**: the tutorial - user guide includes: + +* Declaration of **parameters** from other different places as: **headers**, **cookies**, **form fields** and **files**. +* How to set **validation constraints** as `maximum_length` or `regex`. +* A very powerful and easy to use **Dependency Injection** system. +* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth. +* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic). +* **GraphQL** integration with Strawberry and other libraries. +* Many extra features (thanks to Starlette) as: + * **WebSockets** + * extremely easy tests based on HTTPX and `pytest` + * **CORS** + * **Cookie Sessions** + * ...and more. + +## Performance + +Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as one of the fastest Python frameworks available, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*) + +To understand more about it, see the section Benchmarks. + +## Dependencies + +FastAPI depends on Pydantic and Starlette. + +### `standard` Dependencies + +When you install FastAPI with `pip install "fastapi[standard]"` it comes the `standard` group of optional dependencies: + +Used by Pydantic: + +* email-validator - for email validation. + +Used by Starlette: + +* httpx - Required if you want to use the `TestClient`. +* jinja2 - Required if you want to use the default template configuration. +* python-multipart - Required if you want to support form "parsing", with `request.form()`. + +Used by FastAPI / Starlette: + +* uvicorn - for the server that loads and serves your application. This includes `uvicorn[standard]`, which includes some dependencies (e.g. `uvloop`) needed for high performance serving. +* `fastapi-cli` - to provide the `fastapi` command. + +### Without `standard` Dependencies + +If you don't want to include the `standard` optional dependencies, you can install with `pip install fastapi` instead of `pip install "fastapi[standard]"`. + +### Additional Optional Dependencies + +There are some additional dependencies you might want to install. + +Additional optional Pydantic dependencies: + +* pydantic-settings - for settings management. +* pydantic-extra-types - for extra types to be used with Pydantic. + +Additional optional FastAPI dependencies: + +* orjson - Required if you want to use `ORJSONResponse`. +* ujson - Required if you want to use `UJSONResponse`. + +## License + +This project is licensed under the terms of the MIT license. diff --git a/backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/RECORD b/backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/RECORD new file mode 100644 index 0000000..ff4f6ac --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/RECORD @@ -0,0 +1,97 @@ +../../Scripts/fastapi.exe,sha256=x6EsvCVDLz2RAXzy7tf4JcVP4npYRtDCnnyVt2El3Nk,108412 +fastapi-0.115.6.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +fastapi-0.115.6.dist-info/METADATA,sha256=hkiGasWTGPXPzJYtw94H6jEmzovXW1eQtyrAl3mLy18,27300 +fastapi-0.115.6.dist-info/RECORD,, +fastapi-0.115.6.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +fastapi-0.115.6.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90 +fastapi-0.115.6.dist-info/entry_points.txt,sha256=GCf-WbIZxyGT4MUmrPGj1cOHYZoGsNPHAvNkT6hnGeA,61 +fastapi-0.115.6.dist-info/licenses/LICENSE,sha256=Tsif_IFIW5f-xYSy1KlhAy7v_oNEU4lP2cEnSQbMdE4,1086 +fastapi/__init__.py,sha256=uCwGoex-Lb7tS-9FjZ8q035mrHVcjn_0yfCMPlq6BRI,1081 +fastapi/__main__.py,sha256=bKePXLdO4SsVSM6r9SVoLickJDcR2c0cTOxZRKq26YQ,37 +fastapi/__pycache__/__init__.cpython-312.pyc,, +fastapi/__pycache__/__main__.cpython-312.pyc,, +fastapi/__pycache__/_compat.cpython-312.pyc,, +fastapi/__pycache__/applications.cpython-312.pyc,, +fastapi/__pycache__/background.cpython-312.pyc,, +fastapi/__pycache__/cli.cpython-312.pyc,, +fastapi/__pycache__/concurrency.cpython-312.pyc,, +fastapi/__pycache__/datastructures.cpython-312.pyc,, +fastapi/__pycache__/encoders.cpython-312.pyc,, +fastapi/__pycache__/exception_handlers.cpython-312.pyc,, +fastapi/__pycache__/exceptions.cpython-312.pyc,, +fastapi/__pycache__/logger.cpython-312.pyc,, +fastapi/__pycache__/param_functions.cpython-312.pyc,, +fastapi/__pycache__/params.cpython-312.pyc,, +fastapi/__pycache__/requests.cpython-312.pyc,, +fastapi/__pycache__/responses.cpython-312.pyc,, +fastapi/__pycache__/routing.cpython-312.pyc,, +fastapi/__pycache__/staticfiles.cpython-312.pyc,, +fastapi/__pycache__/templating.cpython-312.pyc,, +fastapi/__pycache__/testclient.cpython-312.pyc,, +fastapi/__pycache__/types.cpython-312.pyc,, +fastapi/__pycache__/utils.cpython-312.pyc,, +fastapi/__pycache__/websockets.cpython-312.pyc,, +fastapi/_compat.py,sha256=Rg7kA7uue4Z6yr8T7hf8b7G6PeC_06mK004Nnykijfk,23953 +fastapi/applications.py,sha256=Ix-o9pQAWhEDf9J0Q1hZ0nBB1uP72c-Y3oiYzvrwqiM,176316 +fastapi/background.py,sha256=rouLirxUANrcYC824MSMypXL_Qb2HYg2YZqaiEqbEKI,1768 +fastapi/cli.py,sha256=OYhZb0NR_deuT5ofyPF2NoNBzZDNOP8Salef2nk-HqA,418 +fastapi/concurrency.py,sha256=MirfowoSpkMQZ8j_g0ZxaQKpV6eB3G-dB5TgcXCrgEA,1424 +fastapi/datastructures.py,sha256=b2PEz77XGq-u3Ur1Inwk0AGjOsQZO49yF9C7IPJ15cY,5766 +fastapi/dependencies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +fastapi/dependencies/__pycache__/__init__.cpython-312.pyc,, +fastapi/dependencies/__pycache__/models.cpython-312.pyc,, +fastapi/dependencies/__pycache__/utils.cpython-312.pyc,, +fastapi/dependencies/models.py,sha256=Pjl6vx-4nZ5Tta9kJa3-RfQKkXtCpS09-FhMgs9eWNs,1507 +fastapi/dependencies/utils.py,sha256=UqN1H0k_4PCnP-nRYNpup1fdIuzEx1F5ZVO6WuVRx4E,35579 +fastapi/encoders.py,sha256=LvwYmFeOz4tVwvgBoC5rvZnbr7hZr73KGrU8O7zSptU,11068 +fastapi/exception_handlers.py,sha256=MBrIOA-ugjJDivIi4rSsUJBdTsjuzN76q4yh0q1COKw,1332 +fastapi/exceptions.py,sha256=taNixuFEXb67lI1bnX1ubq8y8TseJ4yoPlWjyP0fTzk,4969 +fastapi/logger.py,sha256=I9NNi3ov8AcqbsbC9wl1X-hdItKgYt2XTrx1f99Zpl4,54 +fastapi/middleware/__init__.py,sha256=oQDxiFVcc1fYJUOIFvphnK7pTT5kktmfL32QXpBFvvo,58 +fastapi/middleware/__pycache__/__init__.cpython-312.pyc,, +fastapi/middleware/__pycache__/cors.cpython-312.pyc,, +fastapi/middleware/__pycache__/gzip.cpython-312.pyc,, +fastapi/middleware/__pycache__/httpsredirect.cpython-312.pyc,, +fastapi/middleware/__pycache__/trustedhost.cpython-312.pyc,, +fastapi/middleware/__pycache__/wsgi.cpython-312.pyc,, +fastapi/middleware/cors.py,sha256=ynwjWQZoc_vbhzZ3_ZXceoaSrslHFHPdoM52rXr0WUU,79 +fastapi/middleware/gzip.py,sha256=xM5PcsH8QlAimZw4VDvcmTnqQamslThsfe3CVN2voa0,79 +fastapi/middleware/httpsredirect.py,sha256=rL8eXMnmLijwVkH7_400zHri1AekfeBd6D6qs8ix950,115 +fastapi/middleware/trustedhost.py,sha256=eE5XGRxGa7c5zPnMJDGp3BxaL25k5iVQlhnv-Pk0Pss,109 +fastapi/middleware/wsgi.py,sha256=Z3Ue-7wni4lUZMvH3G9ek__acgYdJstbnpZX_HQAboY,79 +fastapi/openapi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +fastapi/openapi/__pycache__/__init__.cpython-312.pyc,, +fastapi/openapi/__pycache__/constants.cpython-312.pyc,, +fastapi/openapi/__pycache__/docs.cpython-312.pyc,, +fastapi/openapi/__pycache__/models.cpython-312.pyc,, +fastapi/openapi/__pycache__/utils.cpython-312.pyc,, +fastapi/openapi/constants.py,sha256=adGzmis1L1HJRTE3kJ5fmHS_Noq6tIY6pWv_SFzoFDU,153 +fastapi/openapi/docs.py,sha256=XcQq-ZbQdC5sI0gIGu5MoHK1q-OFaqws7-ORTo6sjY4,10348 +fastapi/openapi/models.py,sha256=PqkxQiqcEgjKuhfUIWPZPQcyTcubtUCB3vcObLsB7VE,15397 +fastapi/openapi/utils.py,sha256=vpbAzWpuNaJL_ocBxt4jp0GUUwrDKNB1anyoAx69fhA,23177 +fastapi/param_functions.py,sha256=JHNPLIYvoAwdnZZavIVsxOat8x23fX_Kl33reh7HKl8,64019 +fastapi/params.py,sha256=g450axUBQgQJODdtM7WBxZbQj9Z64inFvadrgHikBbU,28237 +fastapi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +fastapi/requests.py,sha256=zayepKFcienBllv3snmWI20Gk0oHNVLU4DDhqXBb4LU,142 +fastapi/responses.py,sha256=QNQQlwpKhQoIPZTTWkpc9d_QGeGZ_aVQPaDV3nQ8m7c,1761 +fastapi/routing.py,sha256=WK06IwZeyRwxkdB4uHZ7JXinxtVOxM8Ke0tqHaDOvYA,176208 +fastapi/security/__init__.py,sha256=bO8pNmxqVRXUjfl2mOKiVZLn0FpBQ61VUYVjmppnbJw,881 +fastapi/security/__pycache__/__init__.cpython-312.pyc,, +fastapi/security/__pycache__/api_key.cpython-312.pyc,, +fastapi/security/__pycache__/base.cpython-312.pyc,, +fastapi/security/__pycache__/http.cpython-312.pyc,, +fastapi/security/__pycache__/oauth2.cpython-312.pyc,, +fastapi/security/__pycache__/open_id_connect_url.cpython-312.pyc,, +fastapi/security/__pycache__/utils.cpython-312.pyc,, +fastapi/security/api_key.py,sha256=_OqUUjEHG5_MT1IPAhXIGJRCPldTBdSww_DegFy_W8Y,9368 +fastapi/security/base.py,sha256=dl4pvbC-RxjfbWgPtCWd8MVU-7CB2SZ22rJDXVCXO6c,141 +fastapi/security/http.py,sha256=223bAV_d7NjI57Pzhbd_KlQTYlMyr5MoN1TW80rbxF8,13512 +fastapi/security/oauth2.py,sha256=BbXdQ_W2Pm5NIcpHGBSBa1u3t0EBLCgiYdOLfid1t4A,21585 +fastapi/security/open_id_connect_url.py,sha256=8vizZ2tGqEp1ur8SwtVgyHJhGAJ5AqahgcvSpaIioDI,2722 +fastapi/security/utils.py,sha256=bd8T0YM7UQD5ATKucr1bNtAvz_Y3__dVNAv5UebiPvc,293 +fastapi/staticfiles.py,sha256=iirGIt3sdY2QZXd36ijs3Cj-T0FuGFda3cd90kM9Ikw,69 +fastapi/templating.py,sha256=4zsuTWgcjcEainMJFAlW6-gnslm6AgOS1SiiDWfmQxk,76 +fastapi/testclient.py,sha256=nBvaAmX66YldReJNZXPOk1sfuo2Q6hs8bOvIaCep6LQ,66 +fastapi/types.py,sha256=nFb36sK3DSoqoyo7Miwy3meKK5UdFBgkAgLSzQlUVyI,383 +fastapi/utils.py,sha256=y8Bj5ttMaI9tS4D60OUgXqKnktBr99NdYUnHHV9LgoY,7948 +fastapi/websockets.py,sha256=419uncYObEKZG0YcrXscfQQYLSWoE10jqxVMetGdR98,222 diff --git a/backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/REQUESTED b/backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/WHEEL b/backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/WHEEL new file mode 100644 index 0000000..64b991e --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: pdm-backend (2.4.3) +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/entry_points.txt b/backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/entry_points.txt new file mode 100644 index 0000000..b81849e --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/entry_points.txt @@ -0,0 +1,5 @@ +[console_scripts] +fastapi = fastapi.cli:main + +[gui_scripts] + diff --git a/backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/licenses/LICENSE b/backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/licenses/LICENSE new file mode 100644 index 0000000..3e92463 --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi-0.115.6.dist-info/licenses/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2018 Sebastián Ramírez + +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/fastapi/__init__.py b/backend/.venv/Lib/site-packages/fastapi/__init__.py new file mode 100644 index 0000000..8239578 --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/__init__.py @@ -0,0 +1,25 @@ +"""FastAPI framework, high performance, easy to learn, fast to code, ready for production""" + +__version__ = "0.115.6" + +from starlette import status as status + +from .applications import FastAPI as FastAPI +from .background import BackgroundTasks as BackgroundTasks +from .datastructures import UploadFile as UploadFile +from .exceptions import HTTPException as HTTPException +from .exceptions import WebSocketException as WebSocketException +from .param_functions import Body as Body +from .param_functions import Cookie as Cookie +from .param_functions import Depends as Depends +from .param_functions import File as File +from .param_functions import Form as Form +from .param_functions import Header as Header +from .param_functions import Path as Path +from .param_functions import Query as Query +from .param_functions import Security as Security +from .requests import Request as Request +from .responses import Response as Response +from .routing import APIRouter as APIRouter +from .websockets import WebSocket as WebSocket +from .websockets import WebSocketDisconnect as WebSocketDisconnect diff --git a/backend/.venv/Lib/site-packages/fastapi/__main__.py b/backend/.venv/Lib/site-packages/fastapi/__main__.py new file mode 100644 index 0000000..fc36465 --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/__main__.py @@ -0,0 +1,3 @@ +from fastapi.cli import main + +main() diff --git a/backend/.venv/Lib/site-packages/fastapi/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..69b97d1cd8c30ee52b8069b16a21b2577d2c4279 GIT binary patch literal 1097 zcmYk5TTj$L6vwCRrF&o4Wp@D)`r?HMix?%5s8K)yi807UlSz|iXlJ2r+o>~CaC!1u z_!;~xegZeCF)=*wX5yRi!85}p_Tk^(IWy->&pFet)oKaB^T2-UKh7fbQyEv!$R+&# z3-B3v2qVwHhBxA6f{`$TGY0aqUM|RnIh@m+5AvajP0eOd2#dI=xe%1XGA?T_0#|TF zb1A5XHC)qN2Cn0}<_hpA9@Sh09>ZgrYrqZM&|C*@;-=zc?`IPTbdidZQRz} z3_9Tip3poVOomfi?5l-W2&F$c3ID=<2cYtT{tbqm-bCaiUH;9lgwzsSvCm}sy zygzRp`G-eVOnHy-kVGz>wXv*$t>kZQ6v7rd+LT z6L|#h+?#}Q6<^q;Zo+-3*xaEX5-Ox}?@$r5NT|d`XxI)*q)t%0{u)?mUK{Jaa9I>l zSH7OJhNk0q%ypb$*>R337f=WoMQ92SsDwlr=*zG|;yCbKqUsbpr(C6j>+bNpa@0H` zq5T~CoNy|*sdv$<_6S}82QMmbJti+J7F14fg zQY;YHg@LR11($JZt14kscK4V@$M!4#z!tuw3lPvJhg8_=#*x@xbR0kOrQ>wt!LaZo zgzFa2XZ#MFqAr%$0{N9O4C5QJf7Cjk%4g{I8JbVgN{Sw)XgNjCQ#6;Ng%mAnxM0wG TDOyU=T@Aq9?`W0Zf^7c)ddoX_ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/__pycache__/__main__.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/__pycache__/__main__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d9e53ddd25750379da0ff86b4a2dd7ab68208d17 GIT binary patch literal 244 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

0g+N6aSuE&;}hS1CkXC_8l3 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 a{pTUtA^xbs(%;N2H9PvZ8ke^4fd306z#1C> literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/__pycache__/applications.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/__pycache__/applications.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ce99cd40c80d6ced0f260ada2ba421e8db964ac8 GIT binary patch literal 84112 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/__pycache__/background.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/__pycache__/background.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c826debdeda444e9b05e514c2fe97c6a6fb6c9bf GIT binary patch literal 2370 zcmcIm&5smC6tAA1Z*~|~76rsm84{f)>`cO8*Gyc)f=Wop28C!cj_IxKuAXhSzpSd+ z*@Yz`kwiGCcrbV*#Dj+Tmv~`4XOreRrh=d(Ri`5`|9hxSMU9*-mm7H zN~Mh8JK0%qf6XKGlN=1cT-w=fL+1{%k*#^i*V>w&X=gM!&Um_?ZRb>9_ws(BUGR(T zqF-v4G?YQKWM}VdiI;XcgU%v5cLUjZn!B&3v)RppQT$B~j7+RA2Ags54Dmd&;!#73 ztEY*z)@5NYurCq5#tl6#Ee1g-h@f_?zZP0?=>lQIzZg*~)-G6y*F+Z6!R{7xK7<4) zYHK!XXKbyl+ZmdrIhv;hCvynaA=sj=4}(qS>@3Y+ekS!Y(b!;jd1hiF?b>;};1q8n zN3)AJrrLXMq7AJ*brBgQCZQx}A?Y%PZxLIe=TS?zVSqyiuZ*(9LZ*quDiOHvdLCY( z*aAGLjfo>D!vr(RqcGqUuM!T+G*B)%4Fnb;Sb~A)!l+SJ3vW?kV?SgRla;V1unT{I zR8y<(zCpNHyl@WNp~bNiGCW2cE6CrguL=?IRB$Xwzz z$2rWZ9GXTNz_DZa^$p@j9!&yTUS5ti#cG(u?Xb|tsb}o^QOLwZ2r7aTI1MtfCsBkK zhEsK;oXpzP!F}cmYQpVs9oHff+&cA%>$NZ!>;(2H=cG#)YBi&!l9xx(cf~3WBO26e zUf6Aj4N(Kl&<3@B&A`Jv+HWGxc6GluyDp0}D$4q~<^8KRzK-olxsZpeJB? zQnx{DTUphg2Khvi%>=+a^eLWl}wlr~MGKt|8ohXdjHI*w| z9@WNKrx#dP?)?o^>HZSjf4QVe3+h1@Pg**%G)BeaakcB5}t=sbm z!^?o~^4Kqw31}>jfFCb4o(d?=64vE$eyyLhN&ZV#W`aK?J5=F+_c(~pv^z+oq>0e2 z>=ybci_n(V)wVMCw6F6n+S0$!KGuL&v@1W4_FJ@pBE}&?>SO9i3Vs63|AxrFQ-{Rs z|D})NiNMQ{N#u=AjYPosDOw|rfGSEbJOG!RO#XRpYNP$b^0M& z;}NlFC%7#5EU_$jRD>IJXD#5yj=b+sJe|fm4c0s7-IWdpE|~>`HJ}XMNf~N_i@ zn}#i}96UW@Z$($5Qh5`rFl`ce4+wb9cqJ)wwU%x2tmxigUZ5 zf{aRBG|hnc)HLI=X#xfHJlUTz&G&o6OIHe}2~2I84Bl$Q;9ekBk^){9#0pZ3uu##( zl@t(*dY)+-8ru&_TwbqJOg>@iWl}==;TDL;H_%SzaIQFb`9N;|hrQ2zH#Kwn&Cm7Q zZ*NZ>`F^T8$YiHycJ+K^??5k9sylkAS{~#;b#M^voBm||*81R(934jcXYSNLtq-1; zqa&!i_m3B#w}U{i1H-MCj6HE)Y({VrNfI)rcm`e?=20PNW6VS<%J|^L;nEYh$J2=$ zlWqVnb6|g-prl}tKL!+3U!i1knS5M)CBgYshG8gC;V*$0=$fWIMEDnU{vn#*M)N;r ZD>tnVmac1$@+Yu5JHF|h*8f#5L%)6*6N{&(FS5(25zgI(KEK;us(*D<~EFxXaCR=9?Gm3 zQ`QX%!Te(?)Mv4!;0R=%)F3W|=ru^q<@O4WRcG1|Nc-Fa_?Mj`S?~bI1&v?=p3&X! zZzb+X5LfOJ_c<04r_>FSIL0iz>ZTFFila>BqsUz=3ZANvg_wuW);24Za!S+xl~g=4 zbApKO=m|4B<&?>+`eei;jmbUE6RyTD#Y6}^AVN3lo;|+1>5mgW6e$jf&t6E;!9kGd zJ8aMi5>EU+4u*t<{`wwad;TNZ_XU-tqb>}!j$ib8P5pU2op8OZ9316{OA6k=>2mXA zW&fZwb7}{J!}_d#@#D>J_4Ze%J+rFs9xhao+EKQ|i5zj(^{lK>sP1T0bf2_ZPZ9-Z#O;7@jX#u5FiiAii$Ep$u8uftM#&We<>>*uP?^@#_ zVAWJ8sVX8>f?NQpJPrBYQ2`aOg^D|c8%W4hm102eR8rTmwoDE|{5K{|*HQd}S8)3K*WD1MC0*->l zD2o*6IFX}qr4af;S!)teHd>*n@KZTTVK-rvD|SBb*n-W7qG2017*A0*nwIV>%x2sW z4tJxOCgc4k!}X6=O6)^}UxN^_j8QW3rl^dVMN`0X?6%9^5KK31U3|)!Q7Ac%1ru$2 z%6`dtLOQ2xVOsjQ$;(2|JH?X41apZ#>XLlX^>HSqxSelZws8}g07?+5{{Y@$gyE^h z;d}vm4>OB{NYKU#FjX|6c=)LIxVIrep8@|JBWoZU*$#Ik%^fkSpbO}$OYrxfK_c2@A#@gTW0r_EZ~T9qNF=<7 zRpPxul~l<@((@nnFP$4+a!HZrzJOHZt)8V-T80R>@O8NBEcu*NTKzPhMlA&mG)vO@Ymr0G5D8%0`nVsK8FsHD0yb}{8plCZlp#csQ%jS?^RO?#AF=KZhmm31*UXeIOmo#OUK8eED7N z@x=(>4NX!vVk%5;Bq`uj%+*@YYMEnP*1GG1+(WLoOevSO#$^e+v4)cR4u!)&a{0aCveX-CdVuNx5kCpW4Ga~X!j#1>@h%ujRW~kOqZs2o zl>P+`Zlb{_==dJ$+(RGip{u_Wg2{dW`6Bb9w?CO9H6J4FHPV5#oxt%$z8QG6Mq%)) bnpnKNqAXtBR8Kxr!BMBc+m}3k7Iyg;NdA$L literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/__pycache__/datastructures.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/__pycache__/datastructures.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a77b445481f4b77348c8567d40228fa1be9e3132 GIT binary patch literal 8143 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/__pycache__/exception_handlers.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/__pycache__/exception_handlers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..40ecd4aab280392607a59360fcfce47ece224af0 GIT binary patch literal 2072 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/__pycache__/params.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/__pycache__/params.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9d7bb552d256aeb8bc4d9b464cef1946a6df98bb GIT binary patch literal 25040 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/__pycache__/responses.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/__pycache__/responses.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fec34d4841f9e93e37d82ff7416a4915bca4bf5c GIT binary patch literal 2401 zcmds3O>7%Q6rT0&`e$p$ancqjL7n~})hMcRS4C>HB?p8!a5E%`s$6)py9OHx38^-WBS zZ|BY1H}Bi^x0#HBV7yU(*ZLuj(2so5A94hCwgB8kCNc#ZH3U@uL-;*EtnTO2_zBuKy zL8Z%F2D@QzmEcutWwp>GblIg1-7yGmtufcZwzWic+Qy!X8KIVLTOEQ;-P5^+$0{m8 z*mM?$x>+fHtL#C_)Y8r-F@lE)T7Mh|iQIoS<#xRNh=E*g%^%@6VLY0#DbnTIa@ zzYsBKMmoalImjT+m4Jbt0C*k-{>|OB{;Luq_Q!x1zG?p)odiM;VtxJsL&Zv`7?u8C zDLQ{s5VoqfZ*M6{aZ_r3#y(`sKgd#IbNb&u2@fy^EP%k68ou5G2qKPx|; zIR0?r_*cu1->N=@YofX<#zqxr^pq0xcZI$LQ7EVB08%FmqgW1vuXM3Y>kxZr<0XbyzG zXQt6~sW(ljODRtyq;HVfaJGK(RQOsrO<#li1o$xuq9+Q1u#NWrgidWoS9u$~w~gN1 zM&+I)3b`lJXipJ^u_sb)S5bs>!kyV&#P#lhw4mIn|As(4?Uhh+{8uChxvli*jcFb> z_eU=s8OOFVxf^9}9DBwN!?s^aQ)B3BY3d-_97{}1h?_49TpmnJ<;Bfo0?0oBD+y?s literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/__pycache__/routing.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/__pycache__/routing.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c36cba96d3e01ad10eb998b775d7c515fc6a8aa7 GIT binary patch literal 82043 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 BMIZnG literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/__pycache__/templating.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/__pycache__/templating.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e4722cf11b7776968766a176d579c6b780c0de2e GIT binary patch literal 247 zcmYLCF$%&!5WG!5L=Y|fM2bYP6t%Gvu@VHi=De(OCb@*WQ}HFf!MFH>6gF0Nf}NEc zR2*1#W_O0UG@A`Z=<%VN(!N#V2k%RsZ6YTYvlvpA!4iNSy}-X$?*PiyMCq;Q%`q!d z;n2hB7zES3)MJ zV;=2M@A*`%xK$2A3M68Kmahf16sr4gh>BxbA7pvFOL1iC)B`lOA`c$`u54^-B;JSR BMb-cS literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/__pycache__/testclient.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/__pycache__/testclient.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7b38fd3e08828151fea00450947979e6d6fe6381 GIT binary patch literal 242 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/_compat.py b/backend/.venv/Lib/site-packages/fastapi/_compat.py new file mode 100644 index 0000000..c07e4a3 --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/_compat.py @@ -0,0 +1,659 @@ +from collections import deque +from copy import copy +from dataclasses import dataclass, is_dataclass +from enum import Enum +from functools import lru_cache +from typing import ( + Any, + Callable, + Deque, + Dict, + FrozenSet, + List, + Mapping, + Sequence, + Set, + Tuple, + Type, + Union, +) + +from fastapi.exceptions import RequestErrorModel +from fastapi.types import IncEx, ModelNameMap, UnionType +from pydantic import BaseModel, create_model +from pydantic.version import VERSION as PYDANTIC_VERSION +from starlette.datastructures import UploadFile +from typing_extensions import Annotated, Literal, get_args, get_origin + +PYDANTIC_VERSION_MINOR_TUPLE = tuple(int(x) for x in PYDANTIC_VERSION.split(".")[:2]) +PYDANTIC_V2 = PYDANTIC_VERSION_MINOR_TUPLE[0] == 2 + + +sequence_annotation_to_type = { + Sequence: list, + List: list, + list: list, + Tuple: tuple, + tuple: tuple, + Set: set, + set: set, + FrozenSet: frozenset, + frozenset: frozenset, + Deque: deque, + deque: deque, +} + +sequence_types = tuple(sequence_annotation_to_type.keys()) + +Url: Type[Any] + +if PYDANTIC_V2: + from pydantic import PydanticSchemaGenerationError as PydanticSchemaGenerationError + from pydantic import TypeAdapter + from pydantic import ValidationError as ValidationError + from pydantic._internal._schema_generation_shared import ( # type: ignore[attr-defined] + GetJsonSchemaHandler as GetJsonSchemaHandler, + ) + from pydantic._internal._typing_extra import eval_type_lenient + from pydantic._internal._utils import lenient_issubclass as lenient_issubclass + from pydantic.fields import FieldInfo + from pydantic.json_schema import GenerateJsonSchema as GenerateJsonSchema + from pydantic.json_schema import JsonSchemaValue as JsonSchemaValue + from pydantic_core import CoreSchema as CoreSchema + from pydantic_core import PydanticUndefined, PydanticUndefinedType + from pydantic_core import Url as Url + + try: + from pydantic_core.core_schema import ( + with_info_plain_validator_function as with_info_plain_validator_function, + ) + except ImportError: # pragma: no cover + from pydantic_core.core_schema import ( + general_plain_validator_function as with_info_plain_validator_function, # noqa: F401 + ) + + RequiredParam = PydanticUndefined + Undefined = PydanticUndefined + UndefinedType = PydanticUndefinedType + evaluate_forwardref = eval_type_lenient + Validator = Any + + class BaseConfig: + pass + + class ErrorWrapper(Exception): + pass + + @dataclass + class ModelField: + field_info: FieldInfo + name: str + mode: Literal["validation", "serialization"] = "validation" + + @property + def alias(self) -> str: + a = self.field_info.alias + return a if a is not None else self.name + + @property + def required(self) -> bool: + return self.field_info.is_required() + + @property + def default(self) -> Any: + return self.get_default() + + @property + def type_(self) -> Any: + return self.field_info.annotation + + def __post_init__(self) -> None: + self._type_adapter: TypeAdapter[Any] = TypeAdapter( + Annotated[self.field_info.annotation, self.field_info] + ) + + def get_default(self) -> Any: + if self.field_info.is_required(): + return Undefined + return self.field_info.get_default(call_default_factory=True) + + def validate( + self, + value: Any, + values: Dict[str, Any] = {}, # noqa: B006 + *, + loc: Tuple[Union[int, str], ...] = (), + ) -> Tuple[Any, Union[List[Dict[str, Any]], None]]: + try: + return ( + self._type_adapter.validate_python(value, from_attributes=True), + None, + ) + except ValidationError as exc: + return None, _regenerate_error_with_loc( + errors=exc.errors(include_url=False), loc_prefix=loc + ) + + def serialize( + self, + value: Any, + *, + mode: Literal["json", "python"] = "json", + include: Union[IncEx, None] = None, + exclude: Union[IncEx, None] = None, + by_alias: bool = True, + exclude_unset: bool = False, + exclude_defaults: bool = False, + exclude_none: bool = False, + ) -> Any: + # What calls this code passes a value that already called + # self._type_adapter.validate_python(value) + return self._type_adapter.dump_python( + value, + mode=mode, + include=include, + exclude=exclude, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + + def __hash__(self) -> int: + # Each ModelField is unique for our purposes, to allow making a dict from + # ModelField to its JSON Schema. + return id(self) + + def get_annotation_from_field_info( + annotation: Any, field_info: FieldInfo, field_name: str + ) -> Any: + return annotation + + def _normalize_errors(errors: Sequence[Any]) -> List[Dict[str, Any]]: + return errors # type: ignore[return-value] + + def _model_rebuild(model: Type[BaseModel]) -> None: + model.model_rebuild() + + def _model_dump( + model: BaseModel, mode: Literal["json", "python"] = "json", **kwargs: Any + ) -> Any: + return model.model_dump(mode=mode, **kwargs) + + def _get_model_config(model: BaseModel) -> Any: + return model.model_config + + def get_schema_from_model_field( + *, + field: ModelField, + schema_generator: GenerateJsonSchema, + model_name_map: ModelNameMap, + field_mapping: Dict[ + Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue + ], + separate_input_output_schemas: bool = True, + ) -> Dict[str, Any]: + override_mode: Union[Literal["validation"], None] = ( + None if separate_input_output_schemas else "validation" + ) + # This expects that GenerateJsonSchema was already used to generate the definitions + json_schema = field_mapping[(field, override_mode or field.mode)] + if "$ref" not in json_schema: + # TODO remove when deprecating Pydantic v1 + # Ref: https://github.com/pydantic/pydantic/blob/d61792cc42c80b13b23e3ffa74bc37ec7c77f7d1/pydantic/schema.py#L207 + json_schema["title"] = ( + field.field_info.title or field.alias.title().replace("_", " ") + ) + return json_schema + + def get_compat_model_name_map(fields: List[ModelField]) -> ModelNameMap: + return {} + + def get_definitions( + *, + fields: List[ModelField], + schema_generator: GenerateJsonSchema, + model_name_map: ModelNameMap, + separate_input_output_schemas: bool = True, + ) -> Tuple[ + Dict[ + Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue + ], + Dict[str, Dict[str, Any]], + ]: + override_mode: Union[Literal["validation"], None] = ( + None if separate_input_output_schemas else "validation" + ) + inputs = [ + (field, override_mode or field.mode, field._type_adapter.core_schema) + for field in fields + ] + field_mapping, definitions = schema_generator.generate_definitions( + inputs=inputs + ) + return field_mapping, definitions # type: ignore[return-value] + + def is_scalar_field(field: ModelField) -> bool: + from fastapi import params + + return field_annotation_is_scalar( + field.field_info.annotation + ) and not isinstance(field.field_info, params.Body) + + def is_sequence_field(field: ModelField) -> bool: + return field_annotation_is_sequence(field.field_info.annotation) + + def is_scalar_sequence_field(field: ModelField) -> bool: + return field_annotation_is_scalar_sequence(field.field_info.annotation) + + def is_bytes_field(field: ModelField) -> bool: + return is_bytes_or_nonable_bytes_annotation(field.type_) + + def is_bytes_sequence_field(field: ModelField) -> bool: + return is_bytes_sequence_annotation(field.type_) + + def copy_field_info(*, field_info: FieldInfo, annotation: Any) -> FieldInfo: + cls = type(field_info) + merged_field_info = cls.from_annotation(annotation) + new_field_info = copy(field_info) + new_field_info.metadata = merged_field_info.metadata + new_field_info.annotation = merged_field_info.annotation + return new_field_info + + def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]: + origin_type = ( + get_origin(field.field_info.annotation) or field.field_info.annotation + ) + assert issubclass(origin_type, sequence_types) # type: ignore[arg-type] + return sequence_annotation_to_type[origin_type](value) # type: ignore[no-any-return] + + def get_missing_field_error(loc: Tuple[str, ...]) -> Dict[str, Any]: + error = ValidationError.from_exception_data( + "Field required", [{"type": "missing", "loc": loc, "input": {}}] + ).errors(include_url=False)[0] + error["input"] = None + return error # type: ignore[return-value] + + def create_body_model( + *, fields: Sequence[ModelField], model_name: str + ) -> Type[BaseModel]: + field_params = {f.name: (f.field_info.annotation, f.field_info) for f in fields} + BodyModel: Type[BaseModel] = create_model(model_name, **field_params) # type: ignore[call-overload] + return BodyModel + + def get_model_fields(model: Type[BaseModel]) -> List[ModelField]: + return [ + ModelField(field_info=field_info, name=name) + for name, field_info in model.model_fields.items() + ] + +else: + from fastapi.openapi.constants import REF_PREFIX as REF_PREFIX + from pydantic import AnyUrl as Url # noqa: F401 + from pydantic import ( # type: ignore[assignment] + BaseConfig as BaseConfig, # noqa: F401 + ) + from pydantic import ValidationError as ValidationError # noqa: F401 + from pydantic.class_validators import ( # type: ignore[no-redef] + Validator as Validator, # noqa: F401 + ) + from pydantic.error_wrappers import ( # type: ignore[no-redef] + ErrorWrapper as ErrorWrapper, # noqa: F401 + ) + from pydantic.errors import MissingError + from pydantic.fields import ( # type: ignore[attr-defined] + SHAPE_FROZENSET, + SHAPE_LIST, + SHAPE_SEQUENCE, + SHAPE_SET, + SHAPE_SINGLETON, + SHAPE_TUPLE, + SHAPE_TUPLE_ELLIPSIS, + ) + from pydantic.fields import FieldInfo as FieldInfo + from pydantic.fields import ( # type: ignore[no-redef,attr-defined] + ModelField as ModelField, # noqa: F401 + ) + + # Keeping old "Required" functionality from Pydantic V1, without + # shadowing typing.Required. + RequiredParam: Any = Ellipsis # type: ignore[no-redef] + from pydantic.fields import ( # type: ignore[no-redef,attr-defined] + Undefined as Undefined, + ) + from pydantic.fields import ( # type: ignore[no-redef, attr-defined] + UndefinedType as UndefinedType, # noqa: F401 + ) + from pydantic.schema import ( + field_schema, + get_flat_models_from_fields, + get_model_name_map, + model_process_schema, + ) + from pydantic.schema import ( # type: ignore[no-redef] # noqa: F401 + get_annotation_from_field_info as get_annotation_from_field_info, + ) + from pydantic.typing import ( # type: ignore[no-redef] + evaluate_forwardref as evaluate_forwardref, # noqa: F401 + ) + from pydantic.utils import ( # type: ignore[no-redef] + lenient_issubclass as lenient_issubclass, # noqa: F401 + ) + + GetJsonSchemaHandler = Any # type: ignore[assignment,misc] + JsonSchemaValue = Dict[str, Any] # type: ignore[misc] + CoreSchema = Any # type: ignore[assignment,misc] + + sequence_shapes = { + SHAPE_LIST, + SHAPE_SET, + SHAPE_FROZENSET, + SHAPE_TUPLE, + SHAPE_SEQUENCE, + SHAPE_TUPLE_ELLIPSIS, + } + sequence_shape_to_type = { + SHAPE_LIST: list, + SHAPE_SET: set, + SHAPE_TUPLE: tuple, + SHAPE_SEQUENCE: list, + SHAPE_TUPLE_ELLIPSIS: list, + } + + @dataclass + class GenerateJsonSchema: # type: ignore[no-redef] + ref_template: str + + class PydanticSchemaGenerationError(Exception): # type: ignore[no-redef] + pass + + def with_info_plain_validator_function( # type: ignore[misc] + function: Callable[..., Any], + *, + ref: Union[str, None] = None, + metadata: Any = None, + serialization: Any = None, + ) -> Any: + return {} + + def get_model_definitions( + *, + flat_models: Set[Union[Type[BaseModel], Type[Enum]]], + model_name_map: Dict[Union[Type[BaseModel], Type[Enum]], str], + ) -> Dict[str, Any]: + definitions: Dict[str, Dict[str, Any]] = {} + for model in flat_models: + m_schema, m_definitions, m_nested_models = model_process_schema( + model, model_name_map=model_name_map, ref_prefix=REF_PREFIX + ) + definitions.update(m_definitions) + model_name = model_name_map[model] + if "description" in m_schema: + m_schema["description"] = m_schema["description"].split("\f")[0] + definitions[model_name] = m_schema + return definitions + + def is_pv1_scalar_field(field: ModelField) -> bool: + from fastapi import params + + field_info = field.field_info + if not ( + field.shape == SHAPE_SINGLETON # type: ignore[attr-defined] + and not lenient_issubclass(field.type_, BaseModel) + and not lenient_issubclass(field.type_, dict) + and not field_annotation_is_sequence(field.type_) + and not is_dataclass(field.type_) + and not isinstance(field_info, params.Body) + ): + return False + if field.sub_fields: # type: ignore[attr-defined] + if not all( + is_pv1_scalar_field(f) + for f in field.sub_fields # type: ignore[attr-defined] + ): + return False + return True + + def is_pv1_scalar_sequence_field(field: ModelField) -> bool: + if (field.shape in sequence_shapes) and not lenient_issubclass( # type: ignore[attr-defined] + field.type_, BaseModel + ): + if field.sub_fields is not None: # type: ignore[attr-defined] + for sub_field in field.sub_fields: # type: ignore[attr-defined] + if not is_pv1_scalar_field(sub_field): + return False + return True + if _annotation_is_sequence(field.type_): + return True + return False + + def _normalize_errors(errors: Sequence[Any]) -> List[Dict[str, Any]]: + use_errors: List[Any] = [] + for error in errors: + if isinstance(error, ErrorWrapper): + new_errors = ValidationError( # type: ignore[call-arg] + errors=[error], model=RequestErrorModel + ).errors() + use_errors.extend(new_errors) + elif isinstance(error, list): + use_errors.extend(_normalize_errors(error)) + else: + use_errors.append(error) + return use_errors + + def _model_rebuild(model: Type[BaseModel]) -> None: + model.update_forward_refs() + + def _model_dump( + model: BaseModel, mode: Literal["json", "python"] = "json", **kwargs: Any + ) -> Any: + return model.dict(**kwargs) + + def _get_model_config(model: BaseModel) -> Any: + return model.__config__ # type: ignore[attr-defined] + + def get_schema_from_model_field( + *, + field: ModelField, + schema_generator: GenerateJsonSchema, + model_name_map: ModelNameMap, + field_mapping: Dict[ + Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue + ], + separate_input_output_schemas: bool = True, + ) -> Dict[str, Any]: + # This expects that GenerateJsonSchema was already used to generate the definitions + return field_schema( # type: ignore[no-any-return] + field, model_name_map=model_name_map, ref_prefix=REF_PREFIX + )[0] + + def get_compat_model_name_map(fields: List[ModelField]) -> ModelNameMap: + models = get_flat_models_from_fields(fields, known_models=set()) + return get_model_name_map(models) # type: ignore[no-any-return] + + def get_definitions( + *, + fields: List[ModelField], + schema_generator: GenerateJsonSchema, + model_name_map: ModelNameMap, + separate_input_output_schemas: bool = True, + ) -> Tuple[ + Dict[ + Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue + ], + Dict[str, Dict[str, Any]], + ]: + models = get_flat_models_from_fields(fields, known_models=set()) + return {}, get_model_definitions( + flat_models=models, model_name_map=model_name_map + ) + + def is_scalar_field(field: ModelField) -> bool: + return is_pv1_scalar_field(field) + + def is_sequence_field(field: ModelField) -> bool: + return field.shape in sequence_shapes or _annotation_is_sequence(field.type_) # type: ignore[attr-defined] + + def is_scalar_sequence_field(field: ModelField) -> bool: + return is_pv1_scalar_sequence_field(field) + + def is_bytes_field(field: ModelField) -> bool: + return lenient_issubclass(field.type_, bytes) + + def is_bytes_sequence_field(field: ModelField) -> bool: + return field.shape in sequence_shapes and lenient_issubclass(field.type_, bytes) # type: ignore[attr-defined] + + def copy_field_info(*, field_info: FieldInfo, annotation: Any) -> FieldInfo: + return copy(field_info) + + def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]: + return sequence_shape_to_type[field.shape](value) # type: ignore[no-any-return,attr-defined] + + def get_missing_field_error(loc: Tuple[str, ...]) -> Dict[str, Any]: + missing_field_error = ErrorWrapper(MissingError(), loc=loc) # type: ignore[call-arg] + new_error = ValidationError([missing_field_error], RequestErrorModel) + return new_error.errors()[0] # type: ignore[return-value] + + def create_body_model( + *, fields: Sequence[ModelField], model_name: str + ) -> Type[BaseModel]: + BodyModel = create_model(model_name) + for f in fields: + BodyModel.__fields__[f.name] = f # type: ignore[index] + return BodyModel + + def get_model_fields(model: Type[BaseModel]) -> List[ModelField]: + return list(model.__fields__.values()) # type: ignore[attr-defined] + + +def _regenerate_error_with_loc( + *, errors: Sequence[Any], loc_prefix: Tuple[Union[str, int], ...] +) -> List[Dict[str, Any]]: + updated_loc_errors: List[Any] = [ + {**err, "loc": loc_prefix + err.get("loc", ())} + for err in _normalize_errors(errors) + ] + + return updated_loc_errors + + +def _annotation_is_sequence(annotation: Union[Type[Any], None]) -> bool: + if lenient_issubclass(annotation, (str, bytes)): + return False + return lenient_issubclass(annotation, sequence_types) + + +def field_annotation_is_sequence(annotation: Union[Type[Any], None]) -> bool: + origin = get_origin(annotation) + if origin is Union or origin is UnionType: + for arg in get_args(annotation): + if field_annotation_is_sequence(arg): + return True + return False + return _annotation_is_sequence(annotation) or _annotation_is_sequence( + get_origin(annotation) + ) + + +def value_is_sequence(value: Any) -> bool: + return isinstance(value, sequence_types) and not isinstance(value, (str, bytes)) # type: ignore[arg-type] + + +def _annotation_is_complex(annotation: Union[Type[Any], None]) -> bool: + return ( + lenient_issubclass(annotation, (BaseModel, Mapping, UploadFile)) + or _annotation_is_sequence(annotation) + or is_dataclass(annotation) + ) + + +def field_annotation_is_complex(annotation: Union[Type[Any], None]) -> bool: + origin = get_origin(annotation) + if origin is Union or origin is UnionType: + return any(field_annotation_is_complex(arg) for arg in get_args(annotation)) + + return ( + _annotation_is_complex(annotation) + or _annotation_is_complex(origin) + or hasattr(origin, "__pydantic_core_schema__") + or hasattr(origin, "__get_pydantic_core_schema__") + ) + + +def field_annotation_is_scalar(annotation: Any) -> bool: + # handle Ellipsis here to make tuple[int, ...] work nicely + return annotation is Ellipsis or not field_annotation_is_complex(annotation) + + +def field_annotation_is_scalar_sequence(annotation: Union[Type[Any], None]) -> bool: + origin = get_origin(annotation) + if origin is Union or origin is UnionType: + at_least_one_scalar_sequence = False + for arg in get_args(annotation): + if field_annotation_is_scalar_sequence(arg): + at_least_one_scalar_sequence = True + continue + elif not field_annotation_is_scalar(arg): + return False + return at_least_one_scalar_sequence + return field_annotation_is_sequence(annotation) and all( + field_annotation_is_scalar(sub_annotation) + for sub_annotation in get_args(annotation) + ) + + +def is_bytes_or_nonable_bytes_annotation(annotation: Any) -> bool: + if lenient_issubclass(annotation, bytes): + return True + origin = get_origin(annotation) + if origin is Union or origin is UnionType: + for arg in get_args(annotation): + if lenient_issubclass(arg, bytes): + return True + return False + + +def is_uploadfile_or_nonable_uploadfile_annotation(annotation: Any) -> bool: + if lenient_issubclass(annotation, UploadFile): + return True + origin = get_origin(annotation) + if origin is Union or origin is UnionType: + for arg in get_args(annotation): + if lenient_issubclass(arg, UploadFile): + return True + return False + + +def is_bytes_sequence_annotation(annotation: Any) -> bool: + origin = get_origin(annotation) + if origin is Union or origin is UnionType: + at_least_one = False + for arg in get_args(annotation): + if is_bytes_sequence_annotation(arg): + at_least_one = True + continue + return at_least_one + return field_annotation_is_sequence(annotation) and all( + is_bytes_or_nonable_bytes_annotation(sub_annotation) + for sub_annotation in get_args(annotation) + ) + + +def is_uploadfile_sequence_annotation(annotation: Any) -> bool: + origin = get_origin(annotation) + if origin is Union or origin is UnionType: + at_least_one = False + for arg in get_args(annotation): + if is_uploadfile_sequence_annotation(arg): + at_least_one = True + continue + return at_least_one + return field_annotation_is_sequence(annotation) and all( + is_uploadfile_or_nonable_uploadfile_annotation(sub_annotation) + for sub_annotation in get_args(annotation) + ) + + +@lru_cache +def get_cached_model_fields(model: Type[BaseModel]) -> List[ModelField]: + return get_model_fields(model) diff --git a/backend/.venv/Lib/site-packages/fastapi/applications.py b/backend/.venv/Lib/site-packages/fastapi/applications.py new file mode 100644 index 0000000..6d427cd --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/applications.py @@ -0,0 +1,4585 @@ +from enum import Enum +from typing import ( + Any, + Awaitable, + Callable, + Coroutine, + Dict, + List, + Optional, + Sequence, + Type, + TypeVar, + Union, +) + +from fastapi import routing +from fastapi.datastructures import Default, DefaultPlaceholder +from fastapi.exception_handlers import ( + http_exception_handler, + request_validation_exception_handler, + websocket_request_validation_exception_handler, +) +from fastapi.exceptions import RequestValidationError, WebSocketRequestValidationError +from fastapi.logger import logger +from fastapi.openapi.docs import ( + get_redoc_html, + get_swagger_ui_html, + get_swagger_ui_oauth2_redirect_html, +) +from fastapi.openapi.utils import get_openapi +from fastapi.params import Depends +from fastapi.types import DecoratedCallable, IncEx +from fastapi.utils import generate_unique_id +from starlette.applications import Starlette +from starlette.datastructures import State +from starlette.exceptions import HTTPException +from starlette.middleware import Middleware +from starlette.middleware.base import BaseHTTPMiddleware +from starlette.requests import Request +from starlette.responses import HTMLResponse, JSONResponse, Response +from starlette.routing import BaseRoute +from starlette.types import ASGIApp, Lifespan, Receive, Scope, Send +from typing_extensions import Annotated, Doc, deprecated + +AppType = TypeVar("AppType", bound="FastAPI") + + +class FastAPI(Starlette): + """ + `FastAPI` app class, the main entrypoint to use FastAPI. + + Read more in the + [FastAPI docs for First Steps](https://fastapi.tiangolo.com/tutorial/first-steps/). + + ## Example + + ```python + from fastapi import FastAPI + + app = FastAPI() + ``` + """ + + def __init__( + self: AppType, + *, + debug: Annotated[ + bool, + Doc( + """ + Boolean indicating if debug tracebacks should be returned on server + errors. + + Read more in the + [Starlette docs for Applications](https://www.starlette.io/applications/#instantiating-the-application). + """ + ), + ] = False, + routes: Annotated[ + Optional[List[BaseRoute]], + Doc( + """ + **Note**: you probably shouldn't use this parameter, it is inherited + from Starlette and supported for compatibility. + + --- + + A list of routes to serve incoming HTTP and WebSocket requests. + """ + ), + deprecated( + """ + You normally wouldn't use this parameter with FastAPI, it is inherited + from Starlette and supported for compatibility. + + In FastAPI, you normally would use the *path operation methods*, + like `app.get()`, `app.post()`, etc. + """ + ), + ] = None, + title: Annotated[ + str, + Doc( + """ + The title of the API. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more in the + [FastAPI docs for Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/#metadata-for-api). + + **Example** + + ```python + from fastapi import FastAPI + + app = FastAPI(title="ChimichangApp") + ``` + """ + ), + ] = "FastAPI", + summary: Annotated[ + Optional[str], + Doc( + """ + A short summary of the API. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more in the + [FastAPI docs for Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/#metadata-for-api). + + **Example** + + ```python + from fastapi import FastAPI + + app = FastAPI(summary="Deadpond's favorite app. Nuff said.") + ``` + """ + ), + ] = None, + description: Annotated[ + str, + Doc( + ''' + A description of the API. Supports Markdown (using + [CommonMark syntax](https://commonmark.org/)). + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more in the + [FastAPI docs for Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/#metadata-for-api). + + **Example** + + ```python + from fastapi import FastAPI + + app = FastAPI( + description=""" + ChimichangApp API helps you do awesome stuff. 🚀 + + ## Items + + You can **read items**. + + ## Users + + You will be able to: + + * **Create users** (_not implemented_). + * **Read users** (_not implemented_). + + """ + ) + ``` + ''' + ), + ] = "", + version: Annotated[ + str, + Doc( + """ + The version of the API. + + **Note** This is the version of your application, not the version of + the OpenAPI specification nor the version of FastAPI being used. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more in the + [FastAPI docs for Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/#metadata-for-api). + + **Example** + + ```python + from fastapi import FastAPI + + app = FastAPI(version="0.0.1") + ``` + """ + ), + ] = "0.1.0", + openapi_url: Annotated[ + Optional[str], + Doc( + """ + The URL where the OpenAPI schema will be served from. + + If you set it to `None`, no OpenAPI schema will be served publicly, and + the default automatic endpoints `/docs` and `/redoc` will also be + disabled. + + Read more in the + [FastAPI docs for Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/#openapi-url). + + **Example** + + ```python + from fastapi import FastAPI + + app = FastAPI(openapi_url="/api/v1/openapi.json") + ``` + """ + ), + ] = "/openapi.json", + openapi_tags: Annotated[ + Optional[List[Dict[str, Any]]], + Doc( + """ + A list of tags used by OpenAPI, these are the same `tags` you can set + in the *path operations*, like: + + * `@app.get("/users/", tags=["users"])` + * `@app.get("/items/", tags=["items"])` + + The order of the tags can be used to specify the order shown in + tools like Swagger UI, used in the automatic path `/docs`. + + It's not required to specify all the tags used. + + The tags that are not declared MAY be organized randomly or based + on the tools' logic. Each tag name in the list MUST be unique. + + The value of each item is a `dict` containing: + + * `name`: The name of the tag. + * `description`: A short description of the tag. + [CommonMark syntax](https://commonmark.org/) MAY be used for rich + text representation. + * `externalDocs`: Additional external documentation for this tag. If + provided, it would contain a `dict` with: + * `description`: A short description of the target documentation. + [CommonMark syntax](https://commonmark.org/) MAY be used for + rich text representation. + * `url`: The URL for the target documentation. Value MUST be in + the form of a URL. + + Read more in the + [FastAPI docs for Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/#metadata-for-tags). + + **Example** + + ```python + from fastapi import FastAPI + + tags_metadata = [ + { + "name": "users", + "description": "Operations with users. The **login** logic is also here.", + }, + { + "name": "items", + "description": "Manage items. So _fancy_ they have their own docs.", + "externalDocs": { + "description": "Items external docs", + "url": "https://fastapi.tiangolo.com/", + }, + }, + ] + + app = FastAPI(openapi_tags=tags_metadata) + ``` + """ + ), + ] = None, + servers: Annotated[ + Optional[List[Dict[str, Union[str, Any]]]], + Doc( + """ + A `list` of `dict`s with connectivity information to a target server. + + You would use it, for example, if your application is served from + different domains and you want to use the same Swagger UI in the + browser to interact with each of them (instead of having multiple + browser tabs open). Or if you want to leave fixed the possible URLs. + + If the servers `list` is not provided, or is an empty `list`, the + default value would be a `dict` with a `url` value of `/`. + + Each item in the `list` is a `dict` containing: + + * `url`: A URL to the target host. This URL supports Server Variables + and MAY be relative, to indicate that the host location is relative + to the location where the OpenAPI document is being served. Variable + substitutions will be made when a variable is named in `{`brackets`}`. + * `description`: An optional string describing the host designated by + the URL. [CommonMark syntax](https://commonmark.org/) MAY be used for + rich text representation. + * `variables`: A `dict` between a variable name and its value. The value + is used for substitution in the server's URL template. + + Read more in the + [FastAPI docs for Behind a Proxy](https://fastapi.tiangolo.com/advanced/behind-a-proxy/#additional-servers). + + **Example** + + ```python + from fastapi import FastAPI + + app = FastAPI( + servers=[ + {"url": "https://stag.example.com", "description": "Staging environment"}, + {"url": "https://prod.example.com", "description": "Production environment"}, + ] + ) + ``` + """ + ), + ] = None, + dependencies: Annotated[ + Optional[Sequence[Depends]], + Doc( + """ + A list of global dependencies, they will be applied to each + *path operation*, including in sub-routers. + + Read more about it in the + [FastAPI docs for Global Dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/global-dependencies/). + + **Example** + + ```python + from fastapi import Depends, FastAPI + + from .dependencies import func_dep_1, func_dep_2 + + app = FastAPI(dependencies=[Depends(func_dep_1), Depends(func_dep_2)]) + ``` + """ + ), + ] = None, + default_response_class: Annotated[ + Type[Response], + Doc( + """ + The default response class to be used. + + Read more in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#default-response-class). + + **Example** + + ```python + from fastapi import FastAPI + from fastapi.responses import ORJSONResponse + + app = FastAPI(default_response_class=ORJSONResponse) + ``` + """ + ), + ] = Default(JSONResponse), + redirect_slashes: Annotated[ + bool, + Doc( + """ + Whether to detect and redirect slashes in URLs when the client doesn't + use the same format. + + **Example** + + ```python + from fastapi import FastAPI + + app = FastAPI(redirect_slashes=True) # the default + + @app.get("/items/") + async def read_items(): + return [{"item_id": "Foo"}] + ``` + + With this app, if a client goes to `/items` (without a trailing slash), + they will be automatically redirected with an HTTP status code of 307 + to `/items/`. + """ + ), + ] = True, + docs_url: Annotated[ + Optional[str], + Doc( + """ + The path to the automatic interactive API documentation. + It is handled in the browser by Swagger UI. + + The default URL is `/docs`. You can disable it by setting it to `None`. + + If `openapi_url` is set to `None`, this will be automatically disabled. + + Read more in the + [FastAPI docs for Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/#docs-urls). + + **Example** + + ```python + from fastapi import FastAPI + + app = FastAPI(docs_url="/documentation", redoc_url=None) + ``` + """ + ), + ] = "/docs", + redoc_url: Annotated[ + Optional[str], + Doc( + """ + The path to the alternative automatic interactive API documentation + provided by ReDoc. + + The default URL is `/redoc`. You can disable it by setting it to `None`. + + If `openapi_url` is set to `None`, this will be automatically disabled. + + Read more in the + [FastAPI docs for Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/#docs-urls). + + **Example** + + ```python + from fastapi import FastAPI + + app = FastAPI(docs_url="/documentation", redoc_url="redocumentation") + ``` + """ + ), + ] = "/redoc", + swagger_ui_oauth2_redirect_url: Annotated[ + Optional[str], + Doc( + """ + The OAuth2 redirect endpoint for the Swagger UI. + + By default it is `/docs/oauth2-redirect`. + + This is only used if you use OAuth2 (with the "Authorize" button) + with Swagger UI. + """ + ), + ] = "/docs/oauth2-redirect", + swagger_ui_init_oauth: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + OAuth2 configuration for the Swagger UI, by default shown at `/docs`. + + Read more about the available configuration options in the + [Swagger UI docs](https://swagger.io/docs/open-source-tools/swagger-ui/usage/oauth2/). + """ + ), + ] = None, + middleware: Annotated[ + Optional[Sequence[Middleware]], + Doc( + """ + List of middleware to be added when creating the application. + + In FastAPI you would normally do this with `app.add_middleware()` + instead. + + Read more in the + [FastAPI docs for Middleware](https://fastapi.tiangolo.com/tutorial/middleware/). + """ + ), + ] = None, + exception_handlers: Annotated[ + Optional[ + Dict[ + Union[int, Type[Exception]], + Callable[[Request, Any], Coroutine[Any, Any, Response]], + ] + ], + Doc( + """ + A dictionary with handlers for exceptions. + + In FastAPI, you would normally use the decorator + `@app.exception_handler()`. + + Read more in the + [FastAPI docs for Handling Errors](https://fastapi.tiangolo.com/tutorial/handling-errors/). + """ + ), + ] = None, + on_startup: Annotated[ + Optional[Sequence[Callable[[], Any]]], + Doc( + """ + A list of startup event handler functions. + + You should instead use the `lifespan` handlers. + + Read more in the [FastAPI docs for `lifespan`](https://fastapi.tiangolo.com/advanced/events/). + """ + ), + ] = None, + on_shutdown: Annotated[ + Optional[Sequence[Callable[[], Any]]], + Doc( + """ + A list of shutdown event handler functions. + + You should instead use the `lifespan` handlers. + + Read more in the + [FastAPI docs for `lifespan`](https://fastapi.tiangolo.com/advanced/events/). + """ + ), + ] = None, + lifespan: Annotated[ + Optional[Lifespan[AppType]], + Doc( + """ + A `Lifespan` context manager handler. This replaces `startup` and + `shutdown` functions with a single context manager. + + Read more in the + [FastAPI docs for `lifespan`](https://fastapi.tiangolo.com/advanced/events/). + """ + ), + ] = None, + terms_of_service: Annotated[ + Optional[str], + Doc( + """ + A URL to the Terms of Service for your API. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more at the + [FastAPI docs for Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/#metadata-for-api). + + **Example** + + ```python + app = FastAPI(terms_of_service="http://example.com/terms/") + ``` + """ + ), + ] = None, + contact: Annotated[ + Optional[Dict[str, Union[str, Any]]], + Doc( + """ + A dictionary with the contact information for the exposed API. + + It can contain several fields. + + * `name`: (`str`) The name of the contact person/organization. + * `url`: (`str`) A URL pointing to the contact information. MUST be in + the format of a URL. + * `email`: (`str`) The email address of the contact person/organization. + MUST be in the format of an email address. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more at the + [FastAPI docs for Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/#metadata-for-api). + + **Example** + + ```python + app = FastAPI( + contact={ + "name": "Deadpoolio the Amazing", + "url": "http://x-force.example.com/contact/", + "email": "dp@x-force.example.com", + } + ) + ``` + """ + ), + ] = None, + license_info: Annotated[ + Optional[Dict[str, Union[str, Any]]], + Doc( + """ + A dictionary with the license information for the exposed API. + + It can contain several fields. + + * `name`: (`str`) **REQUIRED** (if a `license_info` is set). The + license name used for the API. + * `identifier`: (`str`) An [SPDX](https://spdx.dev/) license expression + for the API. The `identifier` field is mutually exclusive of the `url` + field. Available since OpenAPI 3.1.0, FastAPI 0.99.0. + * `url`: (`str`) A URL to the license used for the API. This MUST be + the format of a URL. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more at the + [FastAPI docs for Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/#metadata-for-api). + + **Example** + + ```python + app = FastAPI( + license_info={ + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html", + } + ) + ``` + """ + ), + ] = None, + openapi_prefix: Annotated[ + str, + Doc( + """ + A URL prefix for the OpenAPI URL. + """ + ), + deprecated( + """ + "openapi_prefix" has been deprecated in favor of "root_path", which + follows more closely the ASGI standard, is simpler, and more + automatic. + """ + ), + ] = "", + root_path: Annotated[ + str, + Doc( + """ + A path prefix handled by a proxy that is not seen by the application + but is seen by external clients, which affects things like Swagger UI. + + Read more about it at the + [FastAPI docs for Behind a Proxy](https://fastapi.tiangolo.com/advanced/behind-a-proxy/). + + **Example** + + ```python + from fastapi import FastAPI + + app = FastAPI(root_path="/api/v1") + ``` + """ + ), + ] = "", + root_path_in_servers: Annotated[ + bool, + Doc( + """ + To disable automatically generating the URLs in the `servers` field + in the autogenerated OpenAPI using the `root_path`. + + Read more about it in the + [FastAPI docs for Behind a Proxy](https://fastapi.tiangolo.com/advanced/behind-a-proxy/#disable-automatic-server-from-root_path). + + **Example** + + ```python + from fastapi import FastAPI + + app = FastAPI(root_path_in_servers=False) + ``` + """ + ), + ] = True, + responses: Annotated[ + Optional[Dict[Union[int, str], Dict[str, Any]]], + Doc( + """ + Additional responses to be shown in OpenAPI. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Additional Responses in OpenAPI](https://fastapi.tiangolo.com/advanced/additional-responses/). + + And in the + [FastAPI docs for Bigger Applications](https://fastapi.tiangolo.com/tutorial/bigger-applications/#include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies). + """ + ), + ] = None, + callbacks: Annotated[ + Optional[List[BaseRoute]], + Doc( + """ + OpenAPI callbacks that should apply to all *path operations*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). + """ + ), + ] = None, + webhooks: Annotated[ + Optional[routing.APIRouter], + Doc( + """ + Add OpenAPI webhooks. This is similar to `callbacks` but it doesn't + depend on specific *path operations*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + **Note**: This is available since OpenAPI 3.1.0, FastAPI 0.99.0. + + Read more about it in the + [FastAPI docs for OpenAPI Webhooks](https://fastapi.tiangolo.com/advanced/openapi-webhooks/). + """ + ), + ] = None, + deprecated: Annotated[ + Optional[bool], + Doc( + """ + Mark all *path operations* as deprecated. You probably don't need it, + but it's available. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + include_in_schema: Annotated[ + bool, + Doc( + """ + To include (or not) all the *path operations* in the generated OpenAPI. + You probably don't need it, but it's available. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + """ + ), + ] = True, + swagger_ui_parameters: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + Parameters to configure Swagger UI, the autogenerated interactive API + documentation (by default at `/docs`). + + Read more about it in the + [FastAPI docs about how to Configure Swagger UI](https://fastapi.tiangolo.com/how-to/configure-swagger-ui/). + """ + ), + ] = None, + generate_unique_id_function: Annotated[ + Callable[[routing.APIRoute], str], + Doc( + """ + Customize the function used to generate unique IDs for the *path + operations* shown in the generated OpenAPI. + + This is particularly useful when automatically generating clients or + SDKs for your API. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = Default(generate_unique_id), + separate_input_output_schemas: Annotated[ + bool, + Doc( + """ + Whether to generate separate OpenAPI schemas for request body and + response body when the results would be more precise. + + This is particularly useful when automatically generating clients. + + For example, if you have a model like: + + ```python + from pydantic import BaseModel + + class Item(BaseModel): + name: str + tags: list[str] = [] + ``` + + When `Item` is used for input, a request body, `tags` is not required, + the client doesn't have to provide it. + + But when using `Item` for output, for a response body, `tags` is always + available because it has a default value, even if it's just an empty + list. So, the client should be able to always expect it. + + In this case, there would be two different schemas, one for input and + another one for output. + """ + ), + ] = True, + **extra: Annotated[ + Any, + Doc( + """ + Extra keyword arguments to be stored in the app, not used by FastAPI + anywhere. + """ + ), + ], + ) -> None: + self.debug = debug + self.title = title + self.summary = summary + self.description = description + self.version = version + self.terms_of_service = terms_of_service + self.contact = contact + self.license_info = license_info + self.openapi_url = openapi_url + self.openapi_tags = openapi_tags + self.root_path_in_servers = root_path_in_servers + self.docs_url = docs_url + self.redoc_url = redoc_url + self.swagger_ui_oauth2_redirect_url = swagger_ui_oauth2_redirect_url + self.swagger_ui_init_oauth = swagger_ui_init_oauth + self.swagger_ui_parameters = swagger_ui_parameters + self.servers = servers or [] + self.separate_input_output_schemas = separate_input_output_schemas + self.extra = extra + self.openapi_version: Annotated[ + str, + Doc( + """ + The version string of OpenAPI. + + FastAPI will generate OpenAPI version 3.1.0, and will output that as + the OpenAPI version. But some tools, even though they might be + compatible with OpenAPI 3.1.0, might not recognize it as a valid. + + So you could override this value to trick those tools into using + the generated OpenAPI. Have in mind that this is a hack. But if you + avoid using features added in OpenAPI 3.1.0, it might work for your + use case. + + This is not passed as a parameter to the `FastAPI` class to avoid + giving the false idea that FastAPI would generate a different OpenAPI + schema. It is only available as an attribute. + + **Example** + + ```python + from fastapi import FastAPI + + app = FastAPI() + + app.openapi_version = "3.0.2" + ``` + """ + ), + ] = "3.1.0" + self.openapi_schema: Optional[Dict[str, Any]] = None + if self.openapi_url: + assert self.title, "A title must be provided for OpenAPI, e.g.: 'My API'" + assert self.version, "A version must be provided for OpenAPI, e.g.: '2.1.0'" + # TODO: remove when discarding the openapi_prefix parameter + if openapi_prefix: + logger.warning( + '"openapi_prefix" has been deprecated in favor of "root_path", which ' + "follows more closely the ASGI standard, is simpler, and more " + "automatic. Check the docs at " + "https://fastapi.tiangolo.com/advanced/sub-applications/" + ) + self.webhooks: Annotated[ + routing.APIRouter, + Doc( + """ + The `app.webhooks` attribute is an `APIRouter` with the *path + operations* that will be used just for documentation of webhooks. + + Read more about it in the + [FastAPI docs for OpenAPI Webhooks](https://fastapi.tiangolo.com/advanced/openapi-webhooks/). + """ + ), + ] = webhooks or routing.APIRouter() + self.root_path = root_path or openapi_prefix + self.state: Annotated[ + State, + Doc( + """ + A state object for the application. This is the same object for the + entire application, it doesn't change from request to request. + + You normally wouldn't use this in FastAPI, for most of the cases you + would instead use FastAPI dependencies. + + This is simply inherited from Starlette. + + Read more about it in the + [Starlette docs for Applications](https://www.starlette.io/applications/#storing-state-on-the-app-instance). + """ + ), + ] = State() + self.dependency_overrides: Annotated[ + Dict[Callable[..., Any], Callable[..., Any]], + Doc( + """ + A dictionary with overrides for the dependencies. + + Each key is the original dependency callable, and the value is the + actual dependency that should be called. + + This is for testing, to replace expensive dependencies with testing + versions. + + Read more about it in the + [FastAPI docs for Testing Dependencies with Overrides](https://fastapi.tiangolo.com/advanced/testing-dependencies/). + """ + ), + ] = {} + self.router: routing.APIRouter = routing.APIRouter( + routes=routes, + redirect_slashes=redirect_slashes, + dependency_overrides_provider=self, + on_startup=on_startup, + on_shutdown=on_shutdown, + lifespan=lifespan, + default_response_class=default_response_class, + dependencies=dependencies, + callbacks=callbacks, + deprecated=deprecated, + include_in_schema=include_in_schema, + responses=responses, + generate_unique_id_function=generate_unique_id_function, + ) + self.exception_handlers: Dict[ + Any, Callable[[Request, Any], Union[Response, Awaitable[Response]]] + ] = {} if exception_handlers is None else dict(exception_handlers) + self.exception_handlers.setdefault(HTTPException, http_exception_handler) + self.exception_handlers.setdefault( + RequestValidationError, request_validation_exception_handler + ) + self.exception_handlers.setdefault( + WebSocketRequestValidationError, + # Starlette still has incorrect type specification for the handlers + websocket_request_validation_exception_handler, # type: ignore + ) + + self.user_middleware: List[Middleware] = ( + [] if middleware is None else list(middleware) + ) + self.middleware_stack: Union[ASGIApp, None] = None + self.setup() + + def openapi(self) -> Dict[str, Any]: + """ + Generate the OpenAPI schema of the application. This is called by FastAPI + internally. + + The first time it is called it stores the result in the attribute + `app.openapi_schema`, and next times it is called, it just returns that same + result. To avoid the cost of generating the schema every time. + + If you need to modify the generated OpenAPI schema, you could modify it. + + Read more in the + [FastAPI docs for OpenAPI](https://fastapi.tiangolo.com/how-to/extending-openapi/). + """ + if not self.openapi_schema: + self.openapi_schema = get_openapi( + title=self.title, + version=self.version, + openapi_version=self.openapi_version, + summary=self.summary, + description=self.description, + terms_of_service=self.terms_of_service, + contact=self.contact, + license_info=self.license_info, + routes=self.routes, + webhooks=self.webhooks.routes, + tags=self.openapi_tags, + servers=self.servers, + separate_input_output_schemas=self.separate_input_output_schemas, + ) + return self.openapi_schema + + def setup(self) -> None: + if self.openapi_url: + urls = (server_data.get("url") for server_data in self.servers) + server_urls = {url for url in urls if url} + + async def openapi(req: Request) -> JSONResponse: + root_path = req.scope.get("root_path", "").rstrip("/") + if root_path not in server_urls: + if root_path and self.root_path_in_servers: + self.servers.insert(0, {"url": root_path}) + server_urls.add(root_path) + return JSONResponse(self.openapi()) + + self.add_route(self.openapi_url, openapi, include_in_schema=False) + if self.openapi_url and self.docs_url: + + async def swagger_ui_html(req: Request) -> HTMLResponse: + root_path = req.scope.get("root_path", "").rstrip("/") + openapi_url = root_path + self.openapi_url + oauth2_redirect_url = self.swagger_ui_oauth2_redirect_url + if oauth2_redirect_url: + oauth2_redirect_url = root_path + oauth2_redirect_url + return get_swagger_ui_html( + openapi_url=openapi_url, + title=f"{self.title} - Swagger UI", + oauth2_redirect_url=oauth2_redirect_url, + init_oauth=self.swagger_ui_init_oauth, + swagger_ui_parameters=self.swagger_ui_parameters, + ) + + self.add_route(self.docs_url, swagger_ui_html, include_in_schema=False) + + if self.swagger_ui_oauth2_redirect_url: + + async def swagger_ui_redirect(req: Request) -> HTMLResponse: + return get_swagger_ui_oauth2_redirect_html() + + self.add_route( + self.swagger_ui_oauth2_redirect_url, + swagger_ui_redirect, + include_in_schema=False, + ) + if self.openapi_url and self.redoc_url: + + async def redoc_html(req: Request) -> HTMLResponse: + root_path = req.scope.get("root_path", "").rstrip("/") + openapi_url = root_path + self.openapi_url + return get_redoc_html( + openapi_url=openapi_url, title=f"{self.title} - ReDoc" + ) + + self.add_route(self.redoc_url, redoc_html, include_in_schema=False) + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if self.root_path: + scope["root_path"] = self.root_path + await super().__call__(scope, receive, send) + + def add_api_route( + self, + path: str, + endpoint: Callable[..., Any], + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + methods: Optional[List[str]] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[IncEx] = None, + response_model_exclude: Optional[IncEx] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Union[Type[Response], DefaultPlaceholder] = Default( + JSONResponse + ), + name: Optional[str] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( + generate_unique_id + ), + ) -> None: + self.router.add_api_route( + path, + endpoint=endpoint, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + methods=methods, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def api_route( + self, + path: str, + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + methods: Optional[List[str]] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[IncEx] = None, + response_model_exclude: Optional[IncEx] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Type[Response] = Default(JSONResponse), + name: Optional[str] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + def decorator(func: DecoratedCallable) -> DecoratedCallable: + self.router.add_api_route( + path, + func, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + methods=methods, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + return func + + return decorator + + def add_api_websocket_route( + self, + path: str, + endpoint: Callable[..., Any], + name: Optional[str] = None, + *, + dependencies: Optional[Sequence[Depends]] = None, + ) -> None: + self.router.add_api_websocket_route( + path, + endpoint, + name=name, + dependencies=dependencies, + ) + + def websocket( + self, + path: Annotated[ + str, + Doc( + """ + WebSocket path. + """ + ), + ], + name: Annotated[ + Optional[str], + Doc( + """ + A name for the WebSocket. Only used internally. + """ + ), + ] = None, + *, + dependencies: Annotated[ + Optional[Sequence[Depends]], + Doc( + """ + A list of dependencies (using `Depends()`) to be used for this + WebSocket. + + Read more about it in the + [FastAPI docs for WebSockets](https://fastapi.tiangolo.com/advanced/websockets/). + """ + ), + ] = None, + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Decorate a WebSocket function. + + Read more about it in the + [FastAPI docs for WebSockets](https://fastapi.tiangolo.com/advanced/websockets/). + + **Example** + + ```python + from fastapi import FastAPI, WebSocket + + app = FastAPI() + + @app.websocket("/ws") + async def websocket_endpoint(websocket: WebSocket): + await websocket.accept() + while True: + data = await websocket.receive_text() + await websocket.send_text(f"Message text was: {data}") + ``` + """ + + def decorator(func: DecoratedCallable) -> DecoratedCallable: + self.add_api_websocket_route( + path, + func, + name=name, + dependencies=dependencies, + ) + return func + + return decorator + + def include_router( + self, + router: Annotated[routing.APIRouter, Doc("The `APIRouter` to include.")], + *, + prefix: Annotated[str, Doc("An optional path prefix for the router.")] = "", + tags: Annotated[ + Optional[List[Union[str, Enum]]], + Doc( + """ + A list of tags to be applied to all the *path operations* in this + router. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + dependencies: Annotated[ + Optional[Sequence[Depends]], + Doc( + """ + A list of dependencies (using `Depends()`) to be applied to all the + *path operations* in this router. + + Read more about it in the + [FastAPI docs for Bigger Applications - Multiple Files](https://fastapi.tiangolo.com/tutorial/bigger-applications/#include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies). + + **Example** + + ```python + from fastapi import Depends, FastAPI + + from .dependencies import get_token_header + from .internal import admin + + app = FastAPI() + + app.include_router( + admin.router, + dependencies=[Depends(get_token_header)], + ) + ``` + """ + ), + ] = None, + responses: Annotated[ + Optional[Dict[Union[int, str], Dict[str, Any]]], + Doc( + """ + Additional responses to be shown in OpenAPI. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Additional Responses in OpenAPI](https://fastapi.tiangolo.com/advanced/additional-responses/). + + And in the + [FastAPI docs for Bigger Applications](https://fastapi.tiangolo.com/tutorial/bigger-applications/#include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies). + """ + ), + ] = None, + deprecated: Annotated[ + Optional[bool], + Doc( + """ + Mark all the *path operations* in this router as deprecated. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + **Example** + + ```python + from fastapi import FastAPI + + from .internal import old_api + + app = FastAPI() + + app.include_router( + old_api.router, + deprecated=True, + ) + ``` + """ + ), + ] = None, + include_in_schema: Annotated[ + bool, + Doc( + """ + Include (or not) all the *path operations* in this router in the + generated OpenAPI schema. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + + **Example** + + ```python + from fastapi import FastAPI + + from .internal import old_api + + app = FastAPI() + + app.include_router( + old_api.router, + include_in_schema=False, + ) + ``` + """ + ), + ] = True, + default_response_class: Annotated[ + Type[Response], + Doc( + """ + Default response class to be used for the *path operations* in this + router. + + Read more in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#default-response-class). + + **Example** + + ```python + from fastapi import FastAPI + from fastapi.responses import ORJSONResponse + + from .internal import old_api + + app = FastAPI() + + app.include_router( + old_api.router, + default_response_class=ORJSONResponse, + ) + ``` + """ + ), + ] = Default(JSONResponse), + callbacks: Annotated[ + Optional[List[BaseRoute]], + Doc( + """ + List of *path operations* that will be used as OpenAPI callbacks. + + This is only for OpenAPI documentation, the callbacks won't be used + directly. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). + """ + ), + ] = None, + generate_unique_id_function: Annotated[ + Callable[[routing.APIRoute], str], + Doc( + """ + Customize the function used to generate unique IDs for the *path + operations* shown in the generated OpenAPI. + + This is particularly useful when automatically generating clients or + SDKs for your API. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = Default(generate_unique_id), + ) -> None: + """ + Include an `APIRouter` in the same app. + + Read more about it in the + [FastAPI docs for Bigger Applications](https://fastapi.tiangolo.com/tutorial/bigger-applications/). + + ## Example + + ```python + from fastapi import FastAPI + + from .users import users_router + + app = FastAPI() + + app.include_router(users_router) + ``` + """ + self.router.include_router( + router, + prefix=prefix, + tags=tags, + dependencies=dependencies, + responses=responses, + deprecated=deprecated, + include_in_schema=include_in_schema, + default_response_class=default_response_class, + callbacks=callbacks, + generate_unique_id_function=generate_unique_id_function, + ) + + def get( + self, + path: Annotated[ + str, + Doc( + """ + The URL path to be used for this *path operation*. + + For example, in `http://example.com/items`, the path is `/items`. + """ + ), + ], + *, + response_model: Annotated[ + Any, + Doc( + """ + The type to use for the response. + + It could be any valid Pydantic *field* type. So, it doesn't have to + be a Pydantic model, it could be other things, like a `list`, `dict`, + etc. + + It will be used for: + + * Documentation: the generated OpenAPI (and the UI at `/docs`) will + show it as the response (JSON Schema). + * Serialization: you could return an arbitrary object and the + `response_model` would be used to serialize that object into the + corresponding JSON. + * Filtering: the JSON sent to the client will only contain the data + (fields) defined in the `response_model`. If you returned an object + that contains an attribute `password` but the `response_model` does + not include that field, the JSON sent to the client would not have + that `password`. + * Validation: whatever you return will be serialized with the + `response_model`, converting any data as necessary to generate the + corresponding JSON. But if the data in the object returned is not + valid, that would mean a violation of the contract with the client, + so it's an error from the API developer. So, FastAPI will raise an + error and return a 500 error code (Internal Server Error). + + Read more about it in the + [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). + """ + ), + ] = Default(None), + status_code: Annotated[ + Optional[int], + Doc( + """ + The default status code to be used for the response. + + You could override the status code by returning a response directly. + + Read more about it in the + [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). + """ + ), + ] = None, + tags: Annotated[ + Optional[List[Union[str, Enum]]], + Doc( + """ + A list of tags to be applied to the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). + """ + ), + ] = None, + dependencies: Annotated[ + Optional[Sequence[Depends]], + Doc( + """ + A list of dependencies (using `Depends()`) to be applied to the + *path operation*. + + Read more about it in the + [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). + """ + ), + ] = None, + summary: Annotated[ + Optional[str], + Doc( + """ + A summary for the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + A description for the *path operation*. + + If not provided, it will be extracted automatically from the docstring + of the *path operation function*. + + It can contain Markdown. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + response_description: Annotated[ + str, + Doc( + """ + The description for the default response. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = "Successful Response", + responses: Annotated[ + Optional[Dict[Union[int, str], Dict[str, Any]]], + Doc( + """ + Additional responses that could be returned by this *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + deprecated: Annotated[ + Optional[bool], + Doc( + """ + Mark this *path operation* as deprecated. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + operation_id: Annotated[ + Optional[str], + Doc( + """ + Custom operation ID to be used by this *path operation*. + + By default, it is generated automatically. + + If you provide a custom operation ID, you need to make sure it is + unique for the whole API. + + You can customize the + operation ID generation with the parameter + `generate_unique_id_function` in the `FastAPI` class. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = None, + response_model_include: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to include only certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_exclude: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to exclude certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_by_alias: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response model + should be serialized by alias when an alias is used. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = True, + response_model_exclude_unset: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that were not set and + have their default values. This is different from + `response_model_exclude_defaults` in that if the fields are set, + they will be included in the response, even if the value is the same + as the default. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_defaults: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that have the same value + as the default. This is different from `response_model_exclude_unset` + in that if the fields are set but contain the same default values, + they will be excluded from the response. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_none: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data should + exclude fields set to `None`. + + This is much simpler (less smart) than `response_model_exclude_unset` + and `response_model_exclude_defaults`. You probably want to use one of + those two instead of this one, as those allow returning `None` values + when it makes sense. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). + """ + ), + ] = False, + include_in_schema: Annotated[ + bool, + Doc( + """ + Include this *path operation* in the generated OpenAPI schema. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + """ + ), + ] = True, + response_class: Annotated[ + Type[Response], + Doc( + """ + Response class to be used for this *path operation*. + + This will not be used if you return a response directly. + + Read more about it in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). + """ + ), + ] = Default(JSONResponse), + name: Annotated[ + Optional[str], + Doc( + """ + Name for this *path operation*. Only used internally. + """ + ), + ] = None, + callbacks: Annotated[ + Optional[List[BaseRoute]], + Doc( + """ + List of *path operations* that will be used as OpenAPI callbacks. + + This is only for OpenAPI documentation, the callbacks won't be used + directly. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). + """ + ), + ] = None, + openapi_extra: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + Extra metadata to be included in the OpenAPI schema for this *path + operation*. + + Read more about it in the + [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). + """ + ), + ] = None, + generate_unique_id_function: Annotated[ + Callable[[routing.APIRoute], str], + Doc( + """ + Customize the function used to generate unique IDs for the *path + operations* shown in the generated OpenAPI. + + This is particularly useful when automatically generating clients or + SDKs for your API. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = Default(generate_unique_id), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Add a *path operation* using an HTTP GET operation. + + ## Example + + ```python + from fastapi import FastAPI + + app = FastAPI() + + @app.get("/items/") + def read_items(): + return [{"name": "Empanada"}, {"name": "Arepa"}] + ``` + """ + return self.router.get( + path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def put( + self, + path: Annotated[ + str, + Doc( + """ + The URL path to be used for this *path operation*. + + For example, in `http://example.com/items`, the path is `/items`. + """ + ), + ], + *, + response_model: Annotated[ + Any, + Doc( + """ + The type to use for the response. + + It could be any valid Pydantic *field* type. So, it doesn't have to + be a Pydantic model, it could be other things, like a `list`, `dict`, + etc. + + It will be used for: + + * Documentation: the generated OpenAPI (and the UI at `/docs`) will + show it as the response (JSON Schema). + * Serialization: you could return an arbitrary object and the + `response_model` would be used to serialize that object into the + corresponding JSON. + * Filtering: the JSON sent to the client will only contain the data + (fields) defined in the `response_model`. If you returned an object + that contains an attribute `password` but the `response_model` does + not include that field, the JSON sent to the client would not have + that `password`. + * Validation: whatever you return will be serialized with the + `response_model`, converting any data as necessary to generate the + corresponding JSON. But if the data in the object returned is not + valid, that would mean a violation of the contract with the client, + so it's an error from the API developer. So, FastAPI will raise an + error and return a 500 error code (Internal Server Error). + + Read more about it in the + [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). + """ + ), + ] = Default(None), + status_code: Annotated[ + Optional[int], + Doc( + """ + The default status code to be used for the response. + + You could override the status code by returning a response directly. + + Read more about it in the + [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). + """ + ), + ] = None, + tags: Annotated[ + Optional[List[Union[str, Enum]]], + Doc( + """ + A list of tags to be applied to the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). + """ + ), + ] = None, + dependencies: Annotated[ + Optional[Sequence[Depends]], + Doc( + """ + A list of dependencies (using `Depends()`) to be applied to the + *path operation*. + + Read more about it in the + [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). + """ + ), + ] = None, + summary: Annotated[ + Optional[str], + Doc( + """ + A summary for the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + A description for the *path operation*. + + If not provided, it will be extracted automatically from the docstring + of the *path operation function*. + + It can contain Markdown. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + response_description: Annotated[ + str, + Doc( + """ + The description for the default response. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = "Successful Response", + responses: Annotated[ + Optional[Dict[Union[int, str], Dict[str, Any]]], + Doc( + """ + Additional responses that could be returned by this *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + deprecated: Annotated[ + Optional[bool], + Doc( + """ + Mark this *path operation* as deprecated. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + operation_id: Annotated[ + Optional[str], + Doc( + """ + Custom operation ID to be used by this *path operation*. + + By default, it is generated automatically. + + If you provide a custom operation ID, you need to make sure it is + unique for the whole API. + + You can customize the + operation ID generation with the parameter + `generate_unique_id_function` in the `FastAPI` class. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = None, + response_model_include: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to include only certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_exclude: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to exclude certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_by_alias: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response model + should be serialized by alias when an alias is used. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = True, + response_model_exclude_unset: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that were not set and + have their default values. This is different from + `response_model_exclude_defaults` in that if the fields are set, + they will be included in the response, even if the value is the same + as the default. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_defaults: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that have the same value + as the default. This is different from `response_model_exclude_unset` + in that if the fields are set but contain the same default values, + they will be excluded from the response. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_none: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data should + exclude fields set to `None`. + + This is much simpler (less smart) than `response_model_exclude_unset` + and `response_model_exclude_defaults`. You probably want to use one of + those two instead of this one, as those allow returning `None` values + when it makes sense. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). + """ + ), + ] = False, + include_in_schema: Annotated[ + bool, + Doc( + """ + Include this *path operation* in the generated OpenAPI schema. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + """ + ), + ] = True, + response_class: Annotated[ + Type[Response], + Doc( + """ + Response class to be used for this *path operation*. + + This will not be used if you return a response directly. + + Read more about it in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). + """ + ), + ] = Default(JSONResponse), + name: Annotated[ + Optional[str], + Doc( + """ + Name for this *path operation*. Only used internally. + """ + ), + ] = None, + callbacks: Annotated[ + Optional[List[BaseRoute]], + Doc( + """ + List of *path operations* that will be used as OpenAPI callbacks. + + This is only for OpenAPI documentation, the callbacks won't be used + directly. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). + """ + ), + ] = None, + openapi_extra: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + Extra metadata to be included in the OpenAPI schema for this *path + operation*. + + Read more about it in the + [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). + """ + ), + ] = None, + generate_unique_id_function: Annotated[ + Callable[[routing.APIRoute], str], + Doc( + """ + Customize the function used to generate unique IDs for the *path + operations* shown in the generated OpenAPI. + + This is particularly useful when automatically generating clients or + SDKs for your API. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = Default(generate_unique_id), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Add a *path operation* using an HTTP PUT operation. + + ## Example + + ```python + from fastapi import FastAPI + from pydantic import BaseModel + + class Item(BaseModel): + name: str + description: str | None = None + + app = FastAPI() + + @app.put("/items/{item_id}") + def replace_item(item_id: str, item: Item): + return {"message": "Item replaced", "id": item_id} + ``` + """ + return self.router.put( + path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def post( + self, + path: Annotated[ + str, + Doc( + """ + The URL path to be used for this *path operation*. + + For example, in `http://example.com/items`, the path is `/items`. + """ + ), + ], + *, + response_model: Annotated[ + Any, + Doc( + """ + The type to use for the response. + + It could be any valid Pydantic *field* type. So, it doesn't have to + be a Pydantic model, it could be other things, like a `list`, `dict`, + etc. + + It will be used for: + + * Documentation: the generated OpenAPI (and the UI at `/docs`) will + show it as the response (JSON Schema). + * Serialization: you could return an arbitrary object and the + `response_model` would be used to serialize that object into the + corresponding JSON. + * Filtering: the JSON sent to the client will only contain the data + (fields) defined in the `response_model`. If you returned an object + that contains an attribute `password` but the `response_model` does + not include that field, the JSON sent to the client would not have + that `password`. + * Validation: whatever you return will be serialized with the + `response_model`, converting any data as necessary to generate the + corresponding JSON. But if the data in the object returned is not + valid, that would mean a violation of the contract with the client, + so it's an error from the API developer. So, FastAPI will raise an + error and return a 500 error code (Internal Server Error). + + Read more about it in the + [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). + """ + ), + ] = Default(None), + status_code: Annotated[ + Optional[int], + Doc( + """ + The default status code to be used for the response. + + You could override the status code by returning a response directly. + + Read more about it in the + [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). + """ + ), + ] = None, + tags: Annotated[ + Optional[List[Union[str, Enum]]], + Doc( + """ + A list of tags to be applied to the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). + """ + ), + ] = None, + dependencies: Annotated[ + Optional[Sequence[Depends]], + Doc( + """ + A list of dependencies (using `Depends()`) to be applied to the + *path operation*. + + Read more about it in the + [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). + """ + ), + ] = None, + summary: Annotated[ + Optional[str], + Doc( + """ + A summary for the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + A description for the *path operation*. + + If not provided, it will be extracted automatically from the docstring + of the *path operation function*. + + It can contain Markdown. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + response_description: Annotated[ + str, + Doc( + """ + The description for the default response. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = "Successful Response", + responses: Annotated[ + Optional[Dict[Union[int, str], Dict[str, Any]]], + Doc( + """ + Additional responses that could be returned by this *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + deprecated: Annotated[ + Optional[bool], + Doc( + """ + Mark this *path operation* as deprecated. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + operation_id: Annotated[ + Optional[str], + Doc( + """ + Custom operation ID to be used by this *path operation*. + + By default, it is generated automatically. + + If you provide a custom operation ID, you need to make sure it is + unique for the whole API. + + You can customize the + operation ID generation with the parameter + `generate_unique_id_function` in the `FastAPI` class. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = None, + response_model_include: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to include only certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_exclude: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to exclude certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_by_alias: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response model + should be serialized by alias when an alias is used. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = True, + response_model_exclude_unset: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that were not set and + have their default values. This is different from + `response_model_exclude_defaults` in that if the fields are set, + they will be included in the response, even if the value is the same + as the default. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_defaults: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that have the same value + as the default. This is different from `response_model_exclude_unset` + in that if the fields are set but contain the same default values, + they will be excluded from the response. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_none: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data should + exclude fields set to `None`. + + This is much simpler (less smart) than `response_model_exclude_unset` + and `response_model_exclude_defaults`. You probably want to use one of + those two instead of this one, as those allow returning `None` values + when it makes sense. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). + """ + ), + ] = False, + include_in_schema: Annotated[ + bool, + Doc( + """ + Include this *path operation* in the generated OpenAPI schema. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + """ + ), + ] = True, + response_class: Annotated[ + Type[Response], + Doc( + """ + Response class to be used for this *path operation*. + + This will not be used if you return a response directly. + + Read more about it in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). + """ + ), + ] = Default(JSONResponse), + name: Annotated[ + Optional[str], + Doc( + """ + Name for this *path operation*. Only used internally. + """ + ), + ] = None, + callbacks: Annotated[ + Optional[List[BaseRoute]], + Doc( + """ + List of *path operations* that will be used as OpenAPI callbacks. + + This is only for OpenAPI documentation, the callbacks won't be used + directly. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). + """ + ), + ] = None, + openapi_extra: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + Extra metadata to be included in the OpenAPI schema for this *path + operation*. + + Read more about it in the + [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). + """ + ), + ] = None, + generate_unique_id_function: Annotated[ + Callable[[routing.APIRoute], str], + Doc( + """ + Customize the function used to generate unique IDs for the *path + operations* shown in the generated OpenAPI. + + This is particularly useful when automatically generating clients or + SDKs for your API. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = Default(generate_unique_id), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Add a *path operation* using an HTTP POST operation. + + ## Example + + ```python + from fastapi import FastAPI + from pydantic import BaseModel + + class Item(BaseModel): + name: str + description: str | None = None + + app = FastAPI() + + @app.post("/items/") + def create_item(item: Item): + return {"message": "Item created"} + ``` + """ + return self.router.post( + path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def delete( + self, + path: Annotated[ + str, + Doc( + """ + The URL path to be used for this *path operation*. + + For example, in `http://example.com/items`, the path is `/items`. + """ + ), + ], + *, + response_model: Annotated[ + Any, + Doc( + """ + The type to use for the response. + + It could be any valid Pydantic *field* type. So, it doesn't have to + be a Pydantic model, it could be other things, like a `list`, `dict`, + etc. + + It will be used for: + + * Documentation: the generated OpenAPI (and the UI at `/docs`) will + show it as the response (JSON Schema). + * Serialization: you could return an arbitrary object and the + `response_model` would be used to serialize that object into the + corresponding JSON. + * Filtering: the JSON sent to the client will only contain the data + (fields) defined in the `response_model`. If you returned an object + that contains an attribute `password` but the `response_model` does + not include that field, the JSON sent to the client would not have + that `password`. + * Validation: whatever you return will be serialized with the + `response_model`, converting any data as necessary to generate the + corresponding JSON. But if the data in the object returned is not + valid, that would mean a violation of the contract with the client, + so it's an error from the API developer. So, FastAPI will raise an + error and return a 500 error code (Internal Server Error). + + Read more about it in the + [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). + """ + ), + ] = Default(None), + status_code: Annotated[ + Optional[int], + Doc( + """ + The default status code to be used for the response. + + You could override the status code by returning a response directly. + + Read more about it in the + [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). + """ + ), + ] = None, + tags: Annotated[ + Optional[List[Union[str, Enum]]], + Doc( + """ + A list of tags to be applied to the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). + """ + ), + ] = None, + dependencies: Annotated[ + Optional[Sequence[Depends]], + Doc( + """ + A list of dependencies (using `Depends()`) to be applied to the + *path operation*. + + Read more about it in the + [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). + """ + ), + ] = None, + summary: Annotated[ + Optional[str], + Doc( + """ + A summary for the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + A description for the *path operation*. + + If not provided, it will be extracted automatically from the docstring + of the *path operation function*. + + It can contain Markdown. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + response_description: Annotated[ + str, + Doc( + """ + The description for the default response. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = "Successful Response", + responses: Annotated[ + Optional[Dict[Union[int, str], Dict[str, Any]]], + Doc( + """ + Additional responses that could be returned by this *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + deprecated: Annotated[ + Optional[bool], + Doc( + """ + Mark this *path operation* as deprecated. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + operation_id: Annotated[ + Optional[str], + Doc( + """ + Custom operation ID to be used by this *path operation*. + + By default, it is generated automatically. + + If you provide a custom operation ID, you need to make sure it is + unique for the whole API. + + You can customize the + operation ID generation with the parameter + `generate_unique_id_function` in the `FastAPI` class. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = None, + response_model_include: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to include only certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_exclude: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to exclude certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_by_alias: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response model + should be serialized by alias when an alias is used. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = True, + response_model_exclude_unset: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that were not set and + have their default values. This is different from + `response_model_exclude_defaults` in that if the fields are set, + they will be included in the response, even if the value is the same + as the default. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_defaults: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that have the same value + as the default. This is different from `response_model_exclude_unset` + in that if the fields are set but contain the same default values, + they will be excluded from the response. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_none: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data should + exclude fields set to `None`. + + This is much simpler (less smart) than `response_model_exclude_unset` + and `response_model_exclude_defaults`. You probably want to use one of + those two instead of this one, as those allow returning `None` values + when it makes sense. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). + """ + ), + ] = False, + include_in_schema: Annotated[ + bool, + Doc( + """ + Include this *path operation* in the generated OpenAPI schema. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + """ + ), + ] = True, + response_class: Annotated[ + Type[Response], + Doc( + """ + Response class to be used for this *path operation*. + + This will not be used if you return a response directly. + + Read more about it in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). + """ + ), + ] = Default(JSONResponse), + name: Annotated[ + Optional[str], + Doc( + """ + Name for this *path operation*. Only used internally. + """ + ), + ] = None, + callbacks: Annotated[ + Optional[List[BaseRoute]], + Doc( + """ + List of *path operations* that will be used as OpenAPI callbacks. + + This is only for OpenAPI documentation, the callbacks won't be used + directly. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). + """ + ), + ] = None, + openapi_extra: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + Extra metadata to be included in the OpenAPI schema for this *path + operation*. + + Read more about it in the + [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). + """ + ), + ] = None, + generate_unique_id_function: Annotated[ + Callable[[routing.APIRoute], str], + Doc( + """ + Customize the function used to generate unique IDs for the *path + operations* shown in the generated OpenAPI. + + This is particularly useful when automatically generating clients or + SDKs for your API. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = Default(generate_unique_id), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Add a *path operation* using an HTTP DELETE operation. + + ## Example + + ```python + from fastapi import FastAPI + + app = FastAPI() + + @app.delete("/items/{item_id}") + def delete_item(item_id: str): + return {"message": "Item deleted"} + ``` + """ + return self.router.delete( + path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def options( + self, + path: Annotated[ + str, + Doc( + """ + The URL path to be used for this *path operation*. + + For example, in `http://example.com/items`, the path is `/items`. + """ + ), + ], + *, + response_model: Annotated[ + Any, + Doc( + """ + The type to use for the response. + + It could be any valid Pydantic *field* type. So, it doesn't have to + be a Pydantic model, it could be other things, like a `list`, `dict`, + etc. + + It will be used for: + + * Documentation: the generated OpenAPI (and the UI at `/docs`) will + show it as the response (JSON Schema). + * Serialization: you could return an arbitrary object and the + `response_model` would be used to serialize that object into the + corresponding JSON. + * Filtering: the JSON sent to the client will only contain the data + (fields) defined in the `response_model`. If you returned an object + that contains an attribute `password` but the `response_model` does + not include that field, the JSON sent to the client would not have + that `password`. + * Validation: whatever you return will be serialized with the + `response_model`, converting any data as necessary to generate the + corresponding JSON. But if the data in the object returned is not + valid, that would mean a violation of the contract with the client, + so it's an error from the API developer. So, FastAPI will raise an + error and return a 500 error code (Internal Server Error). + + Read more about it in the + [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). + """ + ), + ] = Default(None), + status_code: Annotated[ + Optional[int], + Doc( + """ + The default status code to be used for the response. + + You could override the status code by returning a response directly. + + Read more about it in the + [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). + """ + ), + ] = None, + tags: Annotated[ + Optional[List[Union[str, Enum]]], + Doc( + """ + A list of tags to be applied to the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). + """ + ), + ] = None, + dependencies: Annotated[ + Optional[Sequence[Depends]], + Doc( + """ + A list of dependencies (using `Depends()`) to be applied to the + *path operation*. + + Read more about it in the + [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). + """ + ), + ] = None, + summary: Annotated[ + Optional[str], + Doc( + """ + A summary for the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + A description for the *path operation*. + + If not provided, it will be extracted automatically from the docstring + of the *path operation function*. + + It can contain Markdown. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + response_description: Annotated[ + str, + Doc( + """ + The description for the default response. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = "Successful Response", + responses: Annotated[ + Optional[Dict[Union[int, str], Dict[str, Any]]], + Doc( + """ + Additional responses that could be returned by this *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + deprecated: Annotated[ + Optional[bool], + Doc( + """ + Mark this *path operation* as deprecated. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + operation_id: Annotated[ + Optional[str], + Doc( + """ + Custom operation ID to be used by this *path operation*. + + By default, it is generated automatically. + + If you provide a custom operation ID, you need to make sure it is + unique for the whole API. + + You can customize the + operation ID generation with the parameter + `generate_unique_id_function` in the `FastAPI` class. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = None, + response_model_include: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to include only certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_exclude: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to exclude certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_by_alias: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response model + should be serialized by alias when an alias is used. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = True, + response_model_exclude_unset: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that were not set and + have their default values. This is different from + `response_model_exclude_defaults` in that if the fields are set, + they will be included in the response, even if the value is the same + as the default. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_defaults: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that have the same value + as the default. This is different from `response_model_exclude_unset` + in that if the fields are set but contain the same default values, + they will be excluded from the response. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_none: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data should + exclude fields set to `None`. + + This is much simpler (less smart) than `response_model_exclude_unset` + and `response_model_exclude_defaults`. You probably want to use one of + those two instead of this one, as those allow returning `None` values + when it makes sense. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). + """ + ), + ] = False, + include_in_schema: Annotated[ + bool, + Doc( + """ + Include this *path operation* in the generated OpenAPI schema. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + """ + ), + ] = True, + response_class: Annotated[ + Type[Response], + Doc( + """ + Response class to be used for this *path operation*. + + This will not be used if you return a response directly. + + Read more about it in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). + """ + ), + ] = Default(JSONResponse), + name: Annotated[ + Optional[str], + Doc( + """ + Name for this *path operation*. Only used internally. + """ + ), + ] = None, + callbacks: Annotated[ + Optional[List[BaseRoute]], + Doc( + """ + List of *path operations* that will be used as OpenAPI callbacks. + + This is only for OpenAPI documentation, the callbacks won't be used + directly. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). + """ + ), + ] = None, + openapi_extra: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + Extra metadata to be included in the OpenAPI schema for this *path + operation*. + + Read more about it in the + [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). + """ + ), + ] = None, + generate_unique_id_function: Annotated[ + Callable[[routing.APIRoute], str], + Doc( + """ + Customize the function used to generate unique IDs for the *path + operations* shown in the generated OpenAPI. + + This is particularly useful when automatically generating clients or + SDKs for your API. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = Default(generate_unique_id), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Add a *path operation* using an HTTP OPTIONS operation. + + ## Example + + ```python + from fastapi import FastAPI + + app = FastAPI() + + @app.options("/items/") + def get_item_options(): + return {"additions": ["Aji", "Guacamole"]} + ``` + """ + return self.router.options( + path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def head( + self, + path: Annotated[ + str, + Doc( + """ + The URL path to be used for this *path operation*. + + For example, in `http://example.com/items`, the path is `/items`. + """ + ), + ], + *, + response_model: Annotated[ + Any, + Doc( + """ + The type to use for the response. + + It could be any valid Pydantic *field* type. So, it doesn't have to + be a Pydantic model, it could be other things, like a `list`, `dict`, + etc. + + It will be used for: + + * Documentation: the generated OpenAPI (and the UI at `/docs`) will + show it as the response (JSON Schema). + * Serialization: you could return an arbitrary object and the + `response_model` would be used to serialize that object into the + corresponding JSON. + * Filtering: the JSON sent to the client will only contain the data + (fields) defined in the `response_model`. If you returned an object + that contains an attribute `password` but the `response_model` does + not include that field, the JSON sent to the client would not have + that `password`. + * Validation: whatever you return will be serialized with the + `response_model`, converting any data as necessary to generate the + corresponding JSON. But if the data in the object returned is not + valid, that would mean a violation of the contract with the client, + so it's an error from the API developer. So, FastAPI will raise an + error and return a 500 error code (Internal Server Error). + + Read more about it in the + [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). + """ + ), + ] = Default(None), + status_code: Annotated[ + Optional[int], + Doc( + """ + The default status code to be used for the response. + + You could override the status code by returning a response directly. + + Read more about it in the + [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). + """ + ), + ] = None, + tags: Annotated[ + Optional[List[Union[str, Enum]]], + Doc( + """ + A list of tags to be applied to the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). + """ + ), + ] = None, + dependencies: Annotated[ + Optional[Sequence[Depends]], + Doc( + """ + A list of dependencies (using `Depends()`) to be applied to the + *path operation*. + + Read more about it in the + [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). + """ + ), + ] = None, + summary: Annotated[ + Optional[str], + Doc( + """ + A summary for the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + A description for the *path operation*. + + If not provided, it will be extracted automatically from the docstring + of the *path operation function*. + + It can contain Markdown. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + response_description: Annotated[ + str, + Doc( + """ + The description for the default response. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = "Successful Response", + responses: Annotated[ + Optional[Dict[Union[int, str], Dict[str, Any]]], + Doc( + """ + Additional responses that could be returned by this *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + deprecated: Annotated[ + Optional[bool], + Doc( + """ + Mark this *path operation* as deprecated. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + operation_id: Annotated[ + Optional[str], + Doc( + """ + Custom operation ID to be used by this *path operation*. + + By default, it is generated automatically. + + If you provide a custom operation ID, you need to make sure it is + unique for the whole API. + + You can customize the + operation ID generation with the parameter + `generate_unique_id_function` in the `FastAPI` class. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = None, + response_model_include: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to include only certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_exclude: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to exclude certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_by_alias: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response model + should be serialized by alias when an alias is used. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = True, + response_model_exclude_unset: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that were not set and + have their default values. This is different from + `response_model_exclude_defaults` in that if the fields are set, + they will be included in the response, even if the value is the same + as the default. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_defaults: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that have the same value + as the default. This is different from `response_model_exclude_unset` + in that if the fields are set but contain the same default values, + they will be excluded from the response. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_none: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data should + exclude fields set to `None`. + + This is much simpler (less smart) than `response_model_exclude_unset` + and `response_model_exclude_defaults`. You probably want to use one of + those two instead of this one, as those allow returning `None` values + when it makes sense. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). + """ + ), + ] = False, + include_in_schema: Annotated[ + bool, + Doc( + """ + Include this *path operation* in the generated OpenAPI schema. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + """ + ), + ] = True, + response_class: Annotated[ + Type[Response], + Doc( + """ + Response class to be used for this *path operation*. + + This will not be used if you return a response directly. + + Read more about it in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). + """ + ), + ] = Default(JSONResponse), + name: Annotated[ + Optional[str], + Doc( + """ + Name for this *path operation*. Only used internally. + """ + ), + ] = None, + callbacks: Annotated[ + Optional[List[BaseRoute]], + Doc( + """ + List of *path operations* that will be used as OpenAPI callbacks. + + This is only for OpenAPI documentation, the callbacks won't be used + directly. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). + """ + ), + ] = None, + openapi_extra: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + Extra metadata to be included in the OpenAPI schema for this *path + operation*. + + Read more about it in the + [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). + """ + ), + ] = None, + generate_unique_id_function: Annotated[ + Callable[[routing.APIRoute], str], + Doc( + """ + Customize the function used to generate unique IDs for the *path + operations* shown in the generated OpenAPI. + + This is particularly useful when automatically generating clients or + SDKs for your API. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = Default(generate_unique_id), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Add a *path operation* using an HTTP HEAD operation. + + ## Example + + ```python + from fastapi import FastAPI, Response + + app = FastAPI() + + @app.head("/items/", status_code=204) + def get_items_headers(response: Response): + response.headers["X-Cat-Dog"] = "Alone in the world" + ``` + """ + return self.router.head( + path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def patch( + self, + path: Annotated[ + str, + Doc( + """ + The URL path to be used for this *path operation*. + + For example, in `http://example.com/items`, the path is `/items`. + """ + ), + ], + *, + response_model: Annotated[ + Any, + Doc( + """ + The type to use for the response. + + It could be any valid Pydantic *field* type. So, it doesn't have to + be a Pydantic model, it could be other things, like a `list`, `dict`, + etc. + + It will be used for: + + * Documentation: the generated OpenAPI (and the UI at `/docs`) will + show it as the response (JSON Schema). + * Serialization: you could return an arbitrary object and the + `response_model` would be used to serialize that object into the + corresponding JSON. + * Filtering: the JSON sent to the client will only contain the data + (fields) defined in the `response_model`. If you returned an object + that contains an attribute `password` but the `response_model` does + not include that field, the JSON sent to the client would not have + that `password`. + * Validation: whatever you return will be serialized with the + `response_model`, converting any data as necessary to generate the + corresponding JSON. But if the data in the object returned is not + valid, that would mean a violation of the contract with the client, + so it's an error from the API developer. So, FastAPI will raise an + error and return a 500 error code (Internal Server Error). + + Read more about it in the + [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). + """ + ), + ] = Default(None), + status_code: Annotated[ + Optional[int], + Doc( + """ + The default status code to be used for the response. + + You could override the status code by returning a response directly. + + Read more about it in the + [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). + """ + ), + ] = None, + tags: Annotated[ + Optional[List[Union[str, Enum]]], + Doc( + """ + A list of tags to be applied to the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). + """ + ), + ] = None, + dependencies: Annotated[ + Optional[Sequence[Depends]], + Doc( + """ + A list of dependencies (using `Depends()`) to be applied to the + *path operation*. + + Read more about it in the + [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). + """ + ), + ] = None, + summary: Annotated[ + Optional[str], + Doc( + """ + A summary for the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + A description for the *path operation*. + + If not provided, it will be extracted automatically from the docstring + of the *path operation function*. + + It can contain Markdown. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + response_description: Annotated[ + str, + Doc( + """ + The description for the default response. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = "Successful Response", + responses: Annotated[ + Optional[Dict[Union[int, str], Dict[str, Any]]], + Doc( + """ + Additional responses that could be returned by this *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + deprecated: Annotated[ + Optional[bool], + Doc( + """ + Mark this *path operation* as deprecated. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + operation_id: Annotated[ + Optional[str], + Doc( + """ + Custom operation ID to be used by this *path operation*. + + By default, it is generated automatically. + + If you provide a custom operation ID, you need to make sure it is + unique for the whole API. + + You can customize the + operation ID generation with the parameter + `generate_unique_id_function` in the `FastAPI` class. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = None, + response_model_include: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to include only certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_exclude: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to exclude certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_by_alias: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response model + should be serialized by alias when an alias is used. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = True, + response_model_exclude_unset: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that were not set and + have their default values. This is different from + `response_model_exclude_defaults` in that if the fields are set, + they will be included in the response, even if the value is the same + as the default. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_defaults: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that have the same value + as the default. This is different from `response_model_exclude_unset` + in that if the fields are set but contain the same default values, + they will be excluded from the response. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_none: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data should + exclude fields set to `None`. + + This is much simpler (less smart) than `response_model_exclude_unset` + and `response_model_exclude_defaults`. You probably want to use one of + those two instead of this one, as those allow returning `None` values + when it makes sense. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). + """ + ), + ] = False, + include_in_schema: Annotated[ + bool, + Doc( + """ + Include this *path operation* in the generated OpenAPI schema. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + """ + ), + ] = True, + response_class: Annotated[ + Type[Response], + Doc( + """ + Response class to be used for this *path operation*. + + This will not be used if you return a response directly. + + Read more about it in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). + """ + ), + ] = Default(JSONResponse), + name: Annotated[ + Optional[str], + Doc( + """ + Name for this *path operation*. Only used internally. + """ + ), + ] = None, + callbacks: Annotated[ + Optional[List[BaseRoute]], + Doc( + """ + List of *path operations* that will be used as OpenAPI callbacks. + + This is only for OpenAPI documentation, the callbacks won't be used + directly. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). + """ + ), + ] = None, + openapi_extra: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + Extra metadata to be included in the OpenAPI schema for this *path + operation*. + + Read more about it in the + [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). + """ + ), + ] = None, + generate_unique_id_function: Annotated[ + Callable[[routing.APIRoute], str], + Doc( + """ + Customize the function used to generate unique IDs for the *path + operations* shown in the generated OpenAPI. + + This is particularly useful when automatically generating clients or + SDKs for your API. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = Default(generate_unique_id), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Add a *path operation* using an HTTP PATCH operation. + + ## Example + + ```python + from fastapi import FastAPI + from pydantic import BaseModel + + class Item(BaseModel): + name: str + description: str | None = None + + app = FastAPI() + + @app.patch("/items/") + def update_item(item: Item): + return {"message": "Item updated in place"} + ``` + """ + return self.router.patch( + path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def trace( + self, + path: Annotated[ + str, + Doc( + """ + The URL path to be used for this *path operation*. + + For example, in `http://example.com/items`, the path is `/items`. + """ + ), + ], + *, + response_model: Annotated[ + Any, + Doc( + """ + The type to use for the response. + + It could be any valid Pydantic *field* type. So, it doesn't have to + be a Pydantic model, it could be other things, like a `list`, `dict`, + etc. + + It will be used for: + + * Documentation: the generated OpenAPI (and the UI at `/docs`) will + show it as the response (JSON Schema). + * Serialization: you could return an arbitrary object and the + `response_model` would be used to serialize that object into the + corresponding JSON. + * Filtering: the JSON sent to the client will only contain the data + (fields) defined in the `response_model`. If you returned an object + that contains an attribute `password` but the `response_model` does + not include that field, the JSON sent to the client would not have + that `password`. + * Validation: whatever you return will be serialized with the + `response_model`, converting any data as necessary to generate the + corresponding JSON. But if the data in the object returned is not + valid, that would mean a violation of the contract with the client, + so it's an error from the API developer. So, FastAPI will raise an + error and return a 500 error code (Internal Server Error). + + Read more about it in the + [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). + """ + ), + ] = Default(None), + status_code: Annotated[ + Optional[int], + Doc( + """ + The default status code to be used for the response. + + You could override the status code by returning a response directly. + + Read more about it in the + [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). + """ + ), + ] = None, + tags: Annotated[ + Optional[List[Union[str, Enum]]], + Doc( + """ + A list of tags to be applied to the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). + """ + ), + ] = None, + dependencies: Annotated[ + Optional[Sequence[Depends]], + Doc( + """ + A list of dependencies (using `Depends()`) to be applied to the + *path operation*. + + Read more about it in the + [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). + """ + ), + ] = None, + summary: Annotated[ + Optional[str], + Doc( + """ + A summary for the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + A description for the *path operation*. + + If not provided, it will be extracted automatically from the docstring + of the *path operation function*. + + It can contain Markdown. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + response_description: Annotated[ + str, + Doc( + """ + The description for the default response. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = "Successful Response", + responses: Annotated[ + Optional[Dict[Union[int, str], Dict[str, Any]]], + Doc( + """ + Additional responses that could be returned by this *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + deprecated: Annotated[ + Optional[bool], + Doc( + """ + Mark this *path operation* as deprecated. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + operation_id: Annotated[ + Optional[str], + Doc( + """ + Custom operation ID to be used by this *path operation*. + + By default, it is generated automatically. + + If you provide a custom operation ID, you need to make sure it is + unique for the whole API. + + You can customize the + operation ID generation with the parameter + `generate_unique_id_function` in the `FastAPI` class. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = None, + response_model_include: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to include only certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_exclude: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to exclude certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_by_alias: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response model + should be serialized by alias when an alias is used. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = True, + response_model_exclude_unset: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that were not set and + have their default values. This is different from + `response_model_exclude_defaults` in that if the fields are set, + they will be included in the response, even if the value is the same + as the default. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_defaults: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that have the same value + as the default. This is different from `response_model_exclude_unset` + in that if the fields are set but contain the same default values, + they will be excluded from the response. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_none: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data should + exclude fields set to `None`. + + This is much simpler (less smart) than `response_model_exclude_unset` + and `response_model_exclude_defaults`. You probably want to use one of + those two instead of this one, as those allow returning `None` values + when it makes sense. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). + """ + ), + ] = False, + include_in_schema: Annotated[ + bool, + Doc( + """ + Include this *path operation* in the generated OpenAPI schema. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + """ + ), + ] = True, + response_class: Annotated[ + Type[Response], + Doc( + """ + Response class to be used for this *path operation*. + + This will not be used if you return a response directly. + + Read more about it in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). + """ + ), + ] = Default(JSONResponse), + name: Annotated[ + Optional[str], + Doc( + """ + Name for this *path operation*. Only used internally. + """ + ), + ] = None, + callbacks: Annotated[ + Optional[List[BaseRoute]], + Doc( + """ + List of *path operations* that will be used as OpenAPI callbacks. + + This is only for OpenAPI documentation, the callbacks won't be used + directly. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). + """ + ), + ] = None, + openapi_extra: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + Extra metadata to be included in the OpenAPI schema for this *path + operation*. + + Read more about it in the + [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). + """ + ), + ] = None, + generate_unique_id_function: Annotated[ + Callable[[routing.APIRoute], str], + Doc( + """ + Customize the function used to generate unique IDs for the *path + operations* shown in the generated OpenAPI. + + This is particularly useful when automatically generating clients or + SDKs for your API. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = Default(generate_unique_id), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Add a *path operation* using an HTTP TRACE operation. + + ## Example + + ```python + from fastapi import FastAPI + + app = FastAPI() + + @app.put("/items/{item_id}") + def trace_item(item_id: str): + return None + ``` + """ + return self.router.trace( + path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def websocket_route( + self, path: str, name: Union[str, None] = None + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + def decorator(func: DecoratedCallable) -> DecoratedCallable: + self.router.add_websocket_route(path, func, name=name) + return func + + return decorator + + @deprecated( + """ + on_event is deprecated, use lifespan event handlers instead. + + Read more about it in the + [FastAPI docs for Lifespan Events](https://fastapi.tiangolo.com/advanced/events/). + """ + ) + def on_event( + self, + event_type: Annotated[ + str, + Doc( + """ + The type of event. `startup` or `shutdown`. + """ + ), + ], + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Add an event handler for the application. + + `on_event` is deprecated, use `lifespan` event handlers instead. + + Read more about it in the + [FastAPI docs for Lifespan Events](https://fastapi.tiangolo.com/advanced/events/#alternative-events-deprecated). + """ + return self.router.on_event(event_type) + + def middleware( + self, + middleware_type: Annotated[ + str, + Doc( + """ + The type of middleware. Currently only supports `http`. + """ + ), + ], + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Add a middleware to the application. + + Read more about it in the + [FastAPI docs for Middleware](https://fastapi.tiangolo.com/tutorial/middleware/). + + ## Example + + ```python + import time + + from fastapi import FastAPI, Request + + app = FastAPI() + + + @app.middleware("http") + async def add_process_time_header(request: Request, call_next): + start_time = time.time() + response = await call_next(request) + process_time = time.time() - start_time + response.headers["X-Process-Time"] = str(process_time) + return response + ``` + """ + + def decorator(func: DecoratedCallable) -> DecoratedCallable: + self.add_middleware(BaseHTTPMiddleware, dispatch=func) + return func + + return decorator + + def exception_handler( + self, + exc_class_or_status_code: Annotated[ + Union[int, Type[Exception]], + Doc( + """ + The Exception class this would handle, or a status code. + """ + ), + ], + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Add an exception handler to the app. + + Read more about it in the + [FastAPI docs for Handling Errors](https://fastapi.tiangolo.com/tutorial/handling-errors/). + + ## Example + + ```python + from fastapi import FastAPI, Request + from fastapi.responses import JSONResponse + + + class UnicornException(Exception): + def __init__(self, name: str): + self.name = name + + + app = FastAPI() + + + @app.exception_handler(UnicornException) + async def unicorn_exception_handler(request: Request, exc: UnicornException): + return JSONResponse( + status_code=418, + content={"message": f"Oops! {exc.name} did something. There goes a rainbow..."}, + ) + ``` + """ + + def decorator(func: DecoratedCallable) -> DecoratedCallable: + self.add_exception_handler(exc_class_or_status_code, func) + return func + + return decorator diff --git a/backend/.venv/Lib/site-packages/fastapi/background.py b/backend/.venv/Lib/site-packages/fastapi/background.py new file mode 100644 index 0000000..203578a --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/background.py @@ -0,0 +1,59 @@ +from typing import Any, Callable + +from starlette.background import BackgroundTasks as StarletteBackgroundTasks +from typing_extensions import Annotated, Doc, ParamSpec + +P = ParamSpec("P") + + +class BackgroundTasks(StarletteBackgroundTasks): + """ + A collection of background tasks that will be called after a response has been + sent to the client. + + Read more about it in the + [FastAPI docs for Background Tasks](https://fastapi.tiangolo.com/tutorial/background-tasks/). + + ## Example + + ```python + from fastapi import BackgroundTasks, FastAPI + + app = FastAPI() + + + def write_notification(email: str, message=""): + with open("log.txt", mode="w") as email_file: + content = f"notification for {email}: {message}" + email_file.write(content) + + + @app.post("/send-notification/{email}") + async def send_notification(email: str, background_tasks: BackgroundTasks): + background_tasks.add_task(write_notification, email, message="some notification") + return {"message": "Notification sent in the background"} + ``` + """ + + def add_task( + self, + func: Annotated[ + Callable[P, Any], + Doc( + """ + The function to call after the response is sent. + + It can be a regular `def` function or an `async def` function. + """ + ), + ], + *args: P.args, + **kwargs: P.kwargs, + ) -> None: + """ + Add a function to be called in the background after the response is sent. + + Read more about it in the + [FastAPI docs for Background Tasks](https://fastapi.tiangolo.com/tutorial/background-tasks/). + """ + return super().add_task(func, *args, **kwargs) diff --git a/backend/.venv/Lib/site-packages/fastapi/cli.py b/backend/.venv/Lib/site-packages/fastapi/cli.py new file mode 100644 index 0000000..8d3301e --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/cli.py @@ -0,0 +1,13 @@ +try: + from fastapi_cli.cli import main as cli_main + +except ImportError: # pragma: no cover + cli_main = None # type: ignore + + +def main() -> None: + if not cli_main: # type: ignore[truthy-function] + message = 'To use the fastapi command, please install "fastapi[standard]":\n\n\tpip install "fastapi[standard]"\n' + print(message) + raise RuntimeError(message) # noqa: B904 + cli_main() diff --git a/backend/.venv/Lib/site-packages/fastapi/concurrency.py b/backend/.venv/Lib/site-packages/fastapi/concurrency.py new file mode 100644 index 0000000..3202c70 --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/concurrency.py @@ -0,0 +1,39 @@ +from contextlib import asynccontextmanager as asynccontextmanager +from typing import AsyncGenerator, ContextManager, TypeVar + +import anyio.to_thread +from anyio import CapacityLimiter +from starlette.concurrency import iterate_in_threadpool as iterate_in_threadpool # noqa +from starlette.concurrency import run_in_threadpool as run_in_threadpool # noqa +from starlette.concurrency import ( # noqa + run_until_first_complete as run_until_first_complete, +) + +_T = TypeVar("_T") + + +@asynccontextmanager +async def contextmanager_in_threadpool( + cm: ContextManager[_T], +) -> AsyncGenerator[_T, None]: + # blocking __exit__ from running waiting on a free thread + # can create race conditions/deadlocks if the context manager itself + # has its own internal pool (e.g. a database connection pool) + # to avoid this we let __exit__ run without a capacity limit + # since we're creating a new limiter for each call, any non-zero limit + # works (1 is arbitrary) + exit_limiter = CapacityLimiter(1) + try: + yield await run_in_threadpool(cm.__enter__) + except Exception as e: + ok = bool( + await anyio.to_thread.run_sync( + cm.__exit__, type(e), e, e.__traceback__, limiter=exit_limiter + ) + ) + if not ok: + raise e + else: + await anyio.to_thread.run_sync( + cm.__exit__, None, None, None, limiter=exit_limiter + ) diff --git a/backend/.venv/Lib/site-packages/fastapi/datastructures.py b/backend/.venv/Lib/site-packages/fastapi/datastructures.py new file mode 100644 index 0000000..cf8406b --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/datastructures.py @@ -0,0 +1,204 @@ +from typing import ( + Any, + BinaryIO, + Callable, + Dict, + Iterable, + Optional, + Type, + TypeVar, + cast, +) + +from fastapi._compat import ( + PYDANTIC_V2, + CoreSchema, + GetJsonSchemaHandler, + JsonSchemaValue, + with_info_plain_validator_function, +) +from starlette.datastructures import URL as URL # noqa: F401 +from starlette.datastructures import Address as Address # noqa: F401 +from starlette.datastructures import FormData as FormData # noqa: F401 +from starlette.datastructures import Headers as Headers # noqa: F401 +from starlette.datastructures import QueryParams as QueryParams # noqa: F401 +from starlette.datastructures import State as State # noqa: F401 +from starlette.datastructures import UploadFile as StarletteUploadFile +from typing_extensions import Annotated, Doc + + +class UploadFile(StarletteUploadFile): + """ + A file uploaded in a request. + + Define it as a *path operation function* (or dependency) parameter. + + If you are using a regular `def` function, you can use the `upload_file.file` + attribute to access the raw standard Python file (blocking, not async), useful and + needed for non-async code. + + Read more about it in the + [FastAPI docs for Request Files](https://fastapi.tiangolo.com/tutorial/request-files/). + + ## Example + + ```python + from typing import Annotated + + from fastapi import FastAPI, File, UploadFile + + app = FastAPI() + + + @app.post("/files/") + async def create_file(file: Annotated[bytes, File()]): + return {"file_size": len(file)} + + + @app.post("/uploadfile/") + async def create_upload_file(file: UploadFile): + return {"filename": file.filename} + ``` + """ + + file: Annotated[ + BinaryIO, + Doc("The standard Python file object (non-async)."), + ] + filename: Annotated[Optional[str], Doc("The original file name.")] + size: Annotated[Optional[int], Doc("The size of the file in bytes.")] + headers: Annotated[Headers, Doc("The headers of the request.")] + content_type: Annotated[ + Optional[str], Doc("The content type of the request, from the headers.") + ] + + async def write( + self, + data: Annotated[ + bytes, + Doc( + """ + The bytes to write to the file. + """ + ), + ], + ) -> None: + """ + Write some bytes to the file. + + You normally wouldn't use this from a file you read in a request. + + To be awaitable, compatible with async, this is run in threadpool. + """ + return await super().write(data) + + async def read( + self, + size: Annotated[ + int, + Doc( + """ + The number of bytes to read from the file. + """ + ), + ] = -1, + ) -> bytes: + """ + Read some bytes from the file. + + To be awaitable, compatible with async, this is run in threadpool. + """ + return await super().read(size) + + async def seek( + self, + offset: Annotated[ + int, + Doc( + """ + The position in bytes to seek to in the file. + """ + ), + ], + ) -> None: + """ + Move to a position in the file. + + Any next read or write will be done from that position. + + To be awaitable, compatible with async, this is run in threadpool. + """ + return await super().seek(offset) + + async def close(self) -> None: + """ + Close the file. + + To be awaitable, compatible with async, this is run in threadpool. + """ + return await super().close() + + @classmethod + def __get_validators__(cls: Type["UploadFile"]) -> Iterable[Callable[..., Any]]: + yield cls.validate + + @classmethod + def validate(cls: Type["UploadFile"], v: Any) -> Any: + if not isinstance(v, StarletteUploadFile): + raise ValueError(f"Expected UploadFile, received: {type(v)}") + return v + + @classmethod + def _validate(cls, __input_value: Any, _: Any) -> "UploadFile": + if not isinstance(__input_value, StarletteUploadFile): + raise ValueError(f"Expected UploadFile, received: {type(__input_value)}") + return cast(UploadFile, __input_value) + + if not PYDANTIC_V2: + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update({"type": "string", "format": "binary"}) + + @classmethod + def __get_pydantic_json_schema__( + cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler + ) -> JsonSchemaValue: + return {"type": "string", "format": "binary"} + + @classmethod + def __get_pydantic_core_schema__( + cls, source: Type[Any], handler: Callable[[Any], CoreSchema] + ) -> CoreSchema: + return with_info_plain_validator_function(cls._validate) + + +class DefaultPlaceholder: + """ + You shouldn't use this class directly. + + It's used internally to recognize when a default value has been overwritten, even + if the overridden default value was truthy. + """ + + def __init__(self, value: Any): + self.value = value + + def __bool__(self) -> bool: + return bool(self.value) + + def __eq__(self, o: object) -> bool: + return isinstance(o, DefaultPlaceholder) and o.value == self.value + + +DefaultType = TypeVar("DefaultType") + + +def Default(value: DefaultType) -> DefaultType: + """ + You shouldn't use this function directly. + + It's used internally to recognize when a default value has been overwritten, even + if the overridden default value was truthy. + """ + return DefaultPlaceholder(value) # type: ignore diff --git a/backend/.venv/Lib/site-packages/fastapi/dependencies/__init__.py b/backend/.venv/Lib/site-packages/fastapi/dependencies/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/fastapi/dependencies/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/dependencies/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dde4ef4d571d4cbecb5cf4bdef79ffd194dd539f GIT binary patch literal 195 zcmX@j%ge<81V%BonIQTxh(HIQS%4zb87dhx8U0o=6fpsLpFwJVB{^Hgl;;;^7Z)TZ zr^e)El@#kHCMV~Y=9OgTrRyf=7p2A|B_?O5=B32wm8IsD#rR|<#S~|jr0N1SWGAMl z7RRI|7MCOzWa_7+766r{<|SvQ7VF2yXXa&=#K-FuRNmsS$<0qG%}KQ@Vg*{s2*kx8 O#z$sGM#ds$APWGI$Tdy? literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/dependencies/__pycache__/models.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/dependencies/__pycache__/models.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a6d3e4614f35636d9abf34249f65afb127045ddb GIT binary patch literal 2738 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/dependencies/models.py b/backend/.venv/Lib/site-packages/fastapi/dependencies/models.py new file mode 100644 index 0000000..418c117 --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/dependencies/models.py @@ -0,0 +1,37 @@ +from dataclasses import dataclass, field +from typing import Any, Callable, List, Optional, Sequence, Tuple + +from fastapi._compat import ModelField +from fastapi.security.base import SecurityBase + + +@dataclass +class SecurityRequirement: + security_scheme: SecurityBase + scopes: Optional[Sequence[str]] = None + + +@dataclass +class Dependant: + path_params: List[ModelField] = field(default_factory=list) + query_params: List[ModelField] = field(default_factory=list) + header_params: List[ModelField] = field(default_factory=list) + cookie_params: List[ModelField] = field(default_factory=list) + body_params: List[ModelField] = field(default_factory=list) + dependencies: List["Dependant"] = field(default_factory=list) + security_requirements: List[SecurityRequirement] = field(default_factory=list) + name: Optional[str] = None + call: Optional[Callable[..., Any]] = None + request_param_name: Optional[str] = None + websocket_param_name: Optional[str] = None + http_connection_param_name: Optional[str] = None + response_param_name: Optional[str] = None + background_tasks_param_name: Optional[str] = None + security_scopes_param_name: Optional[str] = None + security_scopes: Optional[List[str]] = None + use_cache: bool = True + path: Optional[str] = None + cache_key: Tuple[Optional[Callable[..., Any]], Tuple[str, ...]] = field(init=False) + + def __post_init__(self) -> None: + self.cache_key = (self.call, tuple(sorted(set(self.security_scopes or [])))) diff --git a/backend/.venv/Lib/site-packages/fastapi/dependencies/utils.py b/backend/.venv/Lib/site-packages/fastapi/dependencies/utils.py new file mode 100644 index 0000000..e2866b4 --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/dependencies/utils.py @@ -0,0 +1,972 @@ +import inspect +from contextlib import AsyncExitStack, contextmanager +from copy import copy, deepcopy +from dataclasses import dataclass +from typing import ( + Any, + Callable, + Coroutine, + Dict, + ForwardRef, + List, + Mapping, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) + +import anyio +from fastapi import params +from fastapi._compat import ( + PYDANTIC_V2, + ErrorWrapper, + ModelField, + RequiredParam, + Undefined, + _regenerate_error_with_loc, + copy_field_info, + create_body_model, + evaluate_forwardref, + field_annotation_is_scalar, + get_annotation_from_field_info, + get_cached_model_fields, + get_missing_field_error, + is_bytes_field, + is_bytes_sequence_field, + is_scalar_field, + is_scalar_sequence_field, + is_sequence_field, + is_uploadfile_or_nonable_uploadfile_annotation, + is_uploadfile_sequence_annotation, + lenient_issubclass, + sequence_types, + serialize_sequence_value, + value_is_sequence, +) +from fastapi.background import BackgroundTasks +from fastapi.concurrency import ( + asynccontextmanager, + contextmanager_in_threadpool, +) +from fastapi.dependencies.models import Dependant, SecurityRequirement +from fastapi.logger import logger +from fastapi.security.base import SecurityBase +from fastapi.security.oauth2 import OAuth2, SecurityScopes +from fastapi.security.open_id_connect_url import OpenIdConnect +from fastapi.utils import create_model_field, get_path_param_names +from pydantic import BaseModel +from pydantic.fields import FieldInfo +from starlette.background import BackgroundTasks as StarletteBackgroundTasks +from starlette.concurrency import run_in_threadpool +from starlette.datastructures import ( + FormData, + Headers, + ImmutableMultiDict, + QueryParams, + UploadFile, +) +from starlette.requests import HTTPConnection, Request +from starlette.responses import Response +from starlette.websockets import WebSocket +from typing_extensions import Annotated, get_args, get_origin + +multipart_not_installed_error = ( + 'Form data requires "python-multipart" to be installed. \n' + 'You can install "python-multipart" with: \n\n' + "pip install python-multipart\n" +) +multipart_incorrect_install_error = ( + 'Form data requires "python-multipart" to be installed. ' + 'It seems you installed "multipart" instead. \n' + 'You can remove "multipart" with: \n\n' + "pip uninstall multipart\n\n" + 'And then install "python-multipart" with: \n\n' + "pip install python-multipart\n" +) + + +def ensure_multipart_is_installed() -> None: + try: + from python_multipart import __version__ + + # Import an attribute that can be mocked/deleted in testing + assert __version__ > "0.0.12" + except (ImportError, AssertionError): + try: + # __version__ is available in both multiparts, and can be mocked + from multipart import __version__ # type: ignore[no-redef,import-untyped] + + assert __version__ + try: + # parse_options_header is only available in the right multipart + from multipart.multipart import ( # type: ignore[import-untyped] + parse_options_header, + ) + + assert parse_options_header + except ImportError: + logger.error(multipart_incorrect_install_error) + raise RuntimeError(multipart_incorrect_install_error) from None + except ImportError: + logger.error(multipart_not_installed_error) + raise RuntimeError(multipart_not_installed_error) from None + + +def get_param_sub_dependant( + *, + param_name: str, + depends: params.Depends, + path: str, + security_scopes: Optional[List[str]] = None, +) -> Dependant: + assert depends.dependency + return get_sub_dependant( + depends=depends, + dependency=depends.dependency, + path=path, + name=param_name, + security_scopes=security_scopes, + ) + + +def get_parameterless_sub_dependant(*, depends: params.Depends, path: str) -> Dependant: + assert callable( + depends.dependency + ), "A parameter-less dependency must have a callable dependency" + return get_sub_dependant(depends=depends, dependency=depends.dependency, path=path) + + +def get_sub_dependant( + *, + depends: params.Depends, + dependency: Callable[..., Any], + path: str, + name: Optional[str] = None, + security_scopes: Optional[List[str]] = None, +) -> Dependant: + security_requirement = None + security_scopes = security_scopes or [] + if isinstance(depends, params.Security): + dependency_scopes = depends.scopes + security_scopes.extend(dependency_scopes) + if isinstance(dependency, SecurityBase): + use_scopes: List[str] = [] + if isinstance(dependency, (OAuth2, OpenIdConnect)): + use_scopes = security_scopes + security_requirement = SecurityRequirement( + security_scheme=dependency, scopes=use_scopes + ) + sub_dependant = get_dependant( + path=path, + call=dependency, + name=name, + security_scopes=security_scopes, + use_cache=depends.use_cache, + ) + if security_requirement: + sub_dependant.security_requirements.append(security_requirement) + return sub_dependant + + +CacheKey = Tuple[Optional[Callable[..., Any]], Tuple[str, ...]] + + +def get_flat_dependant( + dependant: Dependant, + *, + skip_repeats: bool = False, + visited: Optional[List[CacheKey]] = None, +) -> Dependant: + if visited is None: + visited = [] + visited.append(dependant.cache_key) + + flat_dependant = Dependant( + path_params=dependant.path_params.copy(), + query_params=dependant.query_params.copy(), + header_params=dependant.header_params.copy(), + cookie_params=dependant.cookie_params.copy(), + body_params=dependant.body_params.copy(), + security_requirements=dependant.security_requirements.copy(), + use_cache=dependant.use_cache, + path=dependant.path, + ) + for sub_dependant in dependant.dependencies: + if skip_repeats and sub_dependant.cache_key in visited: + continue + flat_sub = get_flat_dependant( + sub_dependant, skip_repeats=skip_repeats, visited=visited + ) + flat_dependant.path_params.extend(flat_sub.path_params) + flat_dependant.query_params.extend(flat_sub.query_params) + flat_dependant.header_params.extend(flat_sub.header_params) + flat_dependant.cookie_params.extend(flat_sub.cookie_params) + flat_dependant.body_params.extend(flat_sub.body_params) + flat_dependant.security_requirements.extend(flat_sub.security_requirements) + return flat_dependant + + +def _get_flat_fields_from_params(fields: List[ModelField]) -> List[ModelField]: + if not fields: + return fields + first_field = fields[0] + if len(fields) == 1 and lenient_issubclass(first_field.type_, BaseModel): + fields_to_extract = get_cached_model_fields(first_field.type_) + return fields_to_extract + return fields + + +def get_flat_params(dependant: Dependant) -> List[ModelField]: + flat_dependant = get_flat_dependant(dependant, skip_repeats=True) + path_params = _get_flat_fields_from_params(flat_dependant.path_params) + query_params = _get_flat_fields_from_params(flat_dependant.query_params) + header_params = _get_flat_fields_from_params(flat_dependant.header_params) + cookie_params = _get_flat_fields_from_params(flat_dependant.cookie_params) + return path_params + query_params + header_params + cookie_params + + +def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature: + signature = inspect.signature(call) + globalns = getattr(call, "__globals__", {}) + typed_params = [ + inspect.Parameter( + name=param.name, + kind=param.kind, + default=param.default, + annotation=get_typed_annotation(param.annotation, globalns), + ) + for param in signature.parameters.values() + ] + typed_signature = inspect.Signature(typed_params) + return typed_signature + + +def get_typed_annotation(annotation: Any, globalns: Dict[str, Any]) -> Any: + if isinstance(annotation, str): + annotation = ForwardRef(annotation) + annotation = evaluate_forwardref(annotation, globalns, globalns) + return annotation + + +def get_typed_return_annotation(call: Callable[..., Any]) -> Any: + signature = inspect.signature(call) + annotation = signature.return_annotation + + if annotation is inspect.Signature.empty: + return None + + globalns = getattr(call, "__globals__", {}) + return get_typed_annotation(annotation, globalns) + + +def get_dependant( + *, + path: str, + call: Callable[..., Any], + name: Optional[str] = None, + security_scopes: Optional[List[str]] = None, + use_cache: bool = True, +) -> Dependant: + path_param_names = get_path_param_names(path) + endpoint_signature = get_typed_signature(call) + signature_params = endpoint_signature.parameters + dependant = Dependant( + call=call, + name=name, + path=path, + security_scopes=security_scopes, + use_cache=use_cache, + ) + for param_name, param in signature_params.items(): + is_path_param = param_name in path_param_names + param_details = analyze_param( + param_name=param_name, + annotation=param.annotation, + value=param.default, + is_path_param=is_path_param, + ) + if param_details.depends is not None: + sub_dependant = get_param_sub_dependant( + param_name=param_name, + depends=param_details.depends, + path=path, + security_scopes=security_scopes, + ) + dependant.dependencies.append(sub_dependant) + continue + if add_non_field_param_to_dependency( + param_name=param_name, + type_annotation=param_details.type_annotation, + dependant=dependant, + ): + assert ( + param_details.field is None + ), f"Cannot specify multiple FastAPI annotations for {param_name!r}" + continue + assert param_details.field is not None + if isinstance(param_details.field.field_info, params.Body): + dependant.body_params.append(param_details.field) + else: + add_param_to_fields(field=param_details.field, dependant=dependant) + return dependant + + +def add_non_field_param_to_dependency( + *, param_name: str, type_annotation: Any, dependant: Dependant +) -> Optional[bool]: + if lenient_issubclass(type_annotation, Request): + dependant.request_param_name = param_name + return True + elif lenient_issubclass(type_annotation, WebSocket): + dependant.websocket_param_name = param_name + return True + elif lenient_issubclass(type_annotation, HTTPConnection): + dependant.http_connection_param_name = param_name + return True + elif lenient_issubclass(type_annotation, Response): + dependant.response_param_name = param_name + return True + elif lenient_issubclass(type_annotation, StarletteBackgroundTasks): + dependant.background_tasks_param_name = param_name + return True + elif lenient_issubclass(type_annotation, SecurityScopes): + dependant.security_scopes_param_name = param_name + return True + return None + + +@dataclass +class ParamDetails: + type_annotation: Any + depends: Optional[params.Depends] + field: Optional[ModelField] + + +def analyze_param( + *, + param_name: str, + annotation: Any, + value: Any, + is_path_param: bool, +) -> ParamDetails: + field_info = None + depends = None + type_annotation: Any = Any + use_annotation: Any = Any + if annotation is not inspect.Signature.empty: + use_annotation = annotation + type_annotation = annotation + # Extract Annotated info + if get_origin(use_annotation) is Annotated: + annotated_args = get_args(annotation) + type_annotation = annotated_args[0] + fastapi_annotations = [ + arg + for arg in annotated_args[1:] + if isinstance(arg, (FieldInfo, params.Depends)) + ] + fastapi_specific_annotations = [ + arg + for arg in fastapi_annotations + if isinstance(arg, (params.Param, params.Body, params.Depends)) + ] + if fastapi_specific_annotations: + fastapi_annotation: Union[FieldInfo, params.Depends, None] = ( + fastapi_specific_annotations[-1] + ) + else: + fastapi_annotation = None + # Set default for Annotated FieldInfo + if isinstance(fastapi_annotation, FieldInfo): + # Copy `field_info` because we mutate `field_info.default` below. + field_info = copy_field_info( + field_info=fastapi_annotation, annotation=use_annotation + ) + assert ( + field_info.default is Undefined or field_info.default is RequiredParam + ), ( + f"`{field_info.__class__.__name__}` default value cannot be set in" + f" `Annotated` for {param_name!r}. Set the default value with `=` instead." + ) + if value is not inspect.Signature.empty: + assert not is_path_param, "Path parameters cannot have default values" + field_info.default = value + else: + field_info.default = RequiredParam + # Get Annotated Depends + elif isinstance(fastapi_annotation, params.Depends): + depends = fastapi_annotation + # Get Depends from default value + if isinstance(value, params.Depends): + assert depends is None, ( + "Cannot specify `Depends` in `Annotated` and default value" + f" together for {param_name!r}" + ) + assert field_info is None, ( + "Cannot specify a FastAPI annotation in `Annotated` and `Depends` as a" + f" default value together for {param_name!r}" + ) + depends = value + # Get FieldInfo from default value + elif isinstance(value, FieldInfo): + assert field_info is None, ( + "Cannot specify FastAPI annotations in `Annotated` and default value" + f" together for {param_name!r}" + ) + field_info = value + if PYDANTIC_V2: + field_info.annotation = type_annotation + + # Get Depends from type annotation + if depends is not None and depends.dependency is None: + # Copy `depends` before mutating it + depends = copy(depends) + depends.dependency = type_annotation + + # Handle non-param type annotations like Request + if lenient_issubclass( + type_annotation, + ( + Request, + WebSocket, + HTTPConnection, + Response, + StarletteBackgroundTasks, + SecurityScopes, + ), + ): + assert depends is None, f"Cannot specify `Depends` for type {type_annotation!r}" + assert ( + field_info is None + ), f"Cannot specify FastAPI annotation for type {type_annotation!r}" + # Handle default assignations, neither field_info nor depends was not found in Annotated nor default value + elif field_info is None and depends is None: + default_value = value if value is not inspect.Signature.empty else RequiredParam + if is_path_param: + # We might check here that `default_value is RequiredParam`, but the fact is that the same + # parameter might sometimes be a path parameter and sometimes not. See + # `tests/test_infer_param_optionality.py` for an example. + field_info = params.Path(annotation=use_annotation) + elif is_uploadfile_or_nonable_uploadfile_annotation( + type_annotation + ) or is_uploadfile_sequence_annotation(type_annotation): + field_info = params.File(annotation=use_annotation, default=default_value) + elif not field_annotation_is_scalar(annotation=type_annotation): + field_info = params.Body(annotation=use_annotation, default=default_value) + else: + field_info = params.Query(annotation=use_annotation, default=default_value) + + field = None + # It's a field_info, not a dependency + if field_info is not None: + # Handle field_info.in_ + if is_path_param: + assert isinstance(field_info, params.Path), ( + f"Cannot use `{field_info.__class__.__name__}` for path param" + f" {param_name!r}" + ) + elif ( + isinstance(field_info, params.Param) + and getattr(field_info, "in_", None) is None + ): + field_info.in_ = params.ParamTypes.query + use_annotation_from_field_info = get_annotation_from_field_info( + use_annotation, + field_info, + param_name, + ) + if isinstance(field_info, params.Form): + ensure_multipart_is_installed() + if not field_info.alias and getattr(field_info, "convert_underscores", None): + alias = param_name.replace("_", "-") + else: + alias = field_info.alias or param_name + field_info.alias = alias + field = create_model_field( + name=param_name, + type_=use_annotation_from_field_info, + default=field_info.default, + alias=alias, + required=field_info.default in (RequiredParam, Undefined), + field_info=field_info, + ) + if is_path_param: + assert is_scalar_field( + field=field + ), "Path params must be of one of the supported types" + elif isinstance(field_info, params.Query): + assert ( + is_scalar_field(field) + or is_scalar_sequence_field(field) + or ( + lenient_issubclass(field.type_, BaseModel) + # For Pydantic v1 + and getattr(field, "shape", 1) == 1 + ) + ) + + return ParamDetails(type_annotation=type_annotation, depends=depends, field=field) + + +def add_param_to_fields(*, field: ModelField, dependant: Dependant) -> None: + field_info = field.field_info + field_info_in = getattr(field_info, "in_", None) + if field_info_in == params.ParamTypes.path: + dependant.path_params.append(field) + elif field_info_in == params.ParamTypes.query: + dependant.query_params.append(field) + elif field_info_in == params.ParamTypes.header: + dependant.header_params.append(field) + else: + assert ( + field_info_in == params.ParamTypes.cookie + ), f"non-body parameters must be in path, query, header or cookie: {field.name}" + dependant.cookie_params.append(field) + + +def is_coroutine_callable(call: Callable[..., Any]) -> bool: + if inspect.isroutine(call): + return inspect.iscoroutinefunction(call) + if inspect.isclass(call): + return False + dunder_call = getattr(call, "__call__", None) # noqa: B004 + return inspect.iscoroutinefunction(dunder_call) + + +def is_async_gen_callable(call: Callable[..., Any]) -> bool: + if inspect.isasyncgenfunction(call): + return True + dunder_call = getattr(call, "__call__", None) # noqa: B004 + return inspect.isasyncgenfunction(dunder_call) + + +def is_gen_callable(call: Callable[..., Any]) -> bool: + if inspect.isgeneratorfunction(call): + return True + dunder_call = getattr(call, "__call__", None) # noqa: B004 + return inspect.isgeneratorfunction(dunder_call) + + +async def solve_generator( + *, call: Callable[..., Any], stack: AsyncExitStack, sub_values: Dict[str, Any] +) -> Any: + if is_gen_callable(call): + cm = contextmanager_in_threadpool(contextmanager(call)(**sub_values)) + elif is_async_gen_callable(call): + cm = asynccontextmanager(call)(**sub_values) + return await stack.enter_async_context(cm) + + +@dataclass +class SolvedDependency: + values: Dict[str, Any] + errors: List[Any] + background_tasks: Optional[StarletteBackgroundTasks] + response: Response + dependency_cache: Dict[Tuple[Callable[..., Any], Tuple[str]], Any] + + +async def solve_dependencies( + *, + request: Union[Request, WebSocket], + dependant: Dependant, + body: Optional[Union[Dict[str, Any], FormData]] = None, + background_tasks: Optional[StarletteBackgroundTasks] = None, + response: Optional[Response] = None, + dependency_overrides_provider: Optional[Any] = None, + dependency_cache: Optional[Dict[Tuple[Callable[..., Any], Tuple[str]], Any]] = None, + async_exit_stack: AsyncExitStack, + embed_body_fields: bool, +) -> SolvedDependency: + values: Dict[str, Any] = {} + errors: List[Any] = [] + if response is None: + response = Response() + del response.headers["content-length"] + response.status_code = None # type: ignore + dependency_cache = dependency_cache or {} + sub_dependant: Dependant + for sub_dependant in dependant.dependencies: + sub_dependant.call = cast(Callable[..., Any], sub_dependant.call) + sub_dependant.cache_key = cast( + Tuple[Callable[..., Any], Tuple[str]], sub_dependant.cache_key + ) + call = sub_dependant.call + use_sub_dependant = sub_dependant + if ( + dependency_overrides_provider + and dependency_overrides_provider.dependency_overrides + ): + original_call = sub_dependant.call + call = getattr( + dependency_overrides_provider, "dependency_overrides", {} + ).get(original_call, original_call) + use_path: str = sub_dependant.path # type: ignore + use_sub_dependant = get_dependant( + path=use_path, + call=call, + name=sub_dependant.name, + security_scopes=sub_dependant.security_scopes, + ) + + solved_result = await solve_dependencies( + request=request, + dependant=use_sub_dependant, + body=body, + background_tasks=background_tasks, + response=response, + dependency_overrides_provider=dependency_overrides_provider, + dependency_cache=dependency_cache, + async_exit_stack=async_exit_stack, + embed_body_fields=embed_body_fields, + ) + background_tasks = solved_result.background_tasks + dependency_cache.update(solved_result.dependency_cache) + if solved_result.errors: + errors.extend(solved_result.errors) + continue + if sub_dependant.use_cache and sub_dependant.cache_key in dependency_cache: + solved = dependency_cache[sub_dependant.cache_key] + elif is_gen_callable(call) or is_async_gen_callable(call): + solved = await solve_generator( + call=call, stack=async_exit_stack, sub_values=solved_result.values + ) + elif is_coroutine_callable(call): + solved = await call(**solved_result.values) + else: + solved = await run_in_threadpool(call, **solved_result.values) + if sub_dependant.name is not None: + values[sub_dependant.name] = solved + if sub_dependant.cache_key not in dependency_cache: + dependency_cache[sub_dependant.cache_key] = solved + path_values, path_errors = request_params_to_args( + dependant.path_params, request.path_params + ) + query_values, query_errors = request_params_to_args( + dependant.query_params, request.query_params + ) + header_values, header_errors = request_params_to_args( + dependant.header_params, request.headers + ) + cookie_values, cookie_errors = request_params_to_args( + dependant.cookie_params, request.cookies + ) + values.update(path_values) + values.update(query_values) + values.update(header_values) + values.update(cookie_values) + errors += path_errors + query_errors + header_errors + cookie_errors + if dependant.body_params: + ( + body_values, + body_errors, + ) = await request_body_to_args( # body_params checked above + body_fields=dependant.body_params, + received_body=body, + embed_body_fields=embed_body_fields, + ) + values.update(body_values) + errors.extend(body_errors) + if dependant.http_connection_param_name: + values[dependant.http_connection_param_name] = request + if dependant.request_param_name and isinstance(request, Request): + values[dependant.request_param_name] = request + elif dependant.websocket_param_name and isinstance(request, WebSocket): + values[dependant.websocket_param_name] = request + if dependant.background_tasks_param_name: + if background_tasks is None: + background_tasks = BackgroundTasks() + values[dependant.background_tasks_param_name] = background_tasks + if dependant.response_param_name: + values[dependant.response_param_name] = response + if dependant.security_scopes_param_name: + values[dependant.security_scopes_param_name] = SecurityScopes( + scopes=dependant.security_scopes + ) + return SolvedDependency( + values=values, + errors=errors, + background_tasks=background_tasks, + response=response, + dependency_cache=dependency_cache, + ) + + +def _validate_value_with_model_field( + *, field: ModelField, value: Any, values: Dict[str, Any], loc: Tuple[str, ...] +) -> Tuple[Any, List[Any]]: + if value is None: + if field.required: + return None, [get_missing_field_error(loc=loc)] + else: + return deepcopy(field.default), [] + v_, errors_ = field.validate(value, values, loc=loc) + if isinstance(errors_, ErrorWrapper): + return None, [errors_] + elif isinstance(errors_, list): + new_errors = _regenerate_error_with_loc(errors=errors_, loc_prefix=()) + return None, new_errors + else: + return v_, [] + + +def _get_multidict_value( + field: ModelField, values: Mapping[str, Any], alias: Union[str, None] = None +) -> Any: + alias = alias or field.alias + if is_sequence_field(field) and isinstance(values, (ImmutableMultiDict, Headers)): + value = values.getlist(alias) + else: + value = values.get(alias, None) + if ( + value is None + or ( + isinstance(field.field_info, params.Form) + and isinstance(value, str) # For type checks + and value == "" + ) + or (is_sequence_field(field) and len(value) == 0) + ): + if field.required: + return + else: + return deepcopy(field.default) + return value + + +def request_params_to_args( + fields: Sequence[ModelField], + received_params: Union[Mapping[str, Any], QueryParams, Headers], +) -> Tuple[Dict[str, Any], List[Any]]: + values: Dict[str, Any] = {} + errors: List[Dict[str, Any]] = [] + + if not fields: + return values, errors + + first_field = fields[0] + fields_to_extract = fields + single_not_embedded_field = False + if len(fields) == 1 and lenient_issubclass(first_field.type_, BaseModel): + fields_to_extract = get_cached_model_fields(first_field.type_) + single_not_embedded_field = True + + params_to_process: Dict[str, Any] = {} + + processed_keys = set() + + for field in fields_to_extract: + alias = None + if isinstance(received_params, Headers): + # Handle fields extracted from a Pydantic Model for a header, each field + # doesn't have a FieldInfo of type Header with the default convert_underscores=True + convert_underscores = getattr(field.field_info, "convert_underscores", True) + if convert_underscores: + alias = ( + field.alias + if field.alias != field.name + else field.name.replace("_", "-") + ) + value = _get_multidict_value(field, received_params, alias=alias) + if value is not None: + params_to_process[field.name] = value + processed_keys.add(alias or field.alias) + processed_keys.add(field.name) + + for key, value in received_params.items(): + if key not in processed_keys: + params_to_process[key] = value + + if single_not_embedded_field: + field_info = first_field.field_info + assert isinstance( + field_info, params.Param + ), "Params must be subclasses of Param" + loc: Tuple[str, ...] = (field_info.in_.value,) + v_, errors_ = _validate_value_with_model_field( + field=first_field, value=params_to_process, values=values, loc=loc + ) + return {first_field.name: v_}, errors_ + + for field in fields: + value = _get_multidict_value(field, received_params) + field_info = field.field_info + assert isinstance( + field_info, params.Param + ), "Params must be subclasses of Param" + loc = (field_info.in_.value, field.alias) + v_, errors_ = _validate_value_with_model_field( + field=field, value=value, values=values, loc=loc + ) + if errors_: + errors.extend(errors_) + else: + values[field.name] = v_ + return values, errors + + +def _should_embed_body_fields(fields: List[ModelField]) -> bool: + if not fields: + return False + # More than one dependency could have the same field, it would show up as multiple + # fields but it's the same one, so count them by name + body_param_names_set = {field.name for field in fields} + # A top level field has to be a single field, not multiple + if len(body_param_names_set) > 1: + return True + first_field = fields[0] + # If it explicitly specifies it is embedded, it has to be embedded + if getattr(first_field.field_info, "embed", None): + return True + # If it's a Form (or File) field, it has to be a BaseModel to be top level + # otherwise it has to be embedded, so that the key value pair can be extracted + if isinstance(first_field.field_info, params.Form) and not lenient_issubclass( + first_field.type_, BaseModel + ): + return True + return False + + +async def _extract_form_body( + body_fields: List[ModelField], + received_body: FormData, +) -> Dict[str, Any]: + values = {} + first_field = body_fields[0] + first_field_info = first_field.field_info + + for field in body_fields: + value = _get_multidict_value(field, received_body) + if ( + isinstance(first_field_info, params.File) + and is_bytes_field(field) + and isinstance(value, UploadFile) + ): + value = await value.read() + elif ( + is_bytes_sequence_field(field) + and isinstance(first_field_info, params.File) + and value_is_sequence(value) + ): + # For types + assert isinstance(value, sequence_types) # type: ignore[arg-type] + results: List[Union[bytes, str]] = [] + + async def process_fn( + fn: Callable[[], Coroutine[Any, Any, Any]], + ) -> None: + result = await fn() + results.append(result) # noqa: B023 + + async with anyio.create_task_group() as tg: + for sub_value in value: + tg.start_soon(process_fn, sub_value.read) + value = serialize_sequence_value(field=field, value=results) + if value is not None: + values[field.alias] = value + for key, value in received_body.items(): + if key not in values: + values[key] = value + return values + + +async def request_body_to_args( + body_fields: List[ModelField], + received_body: Optional[Union[Dict[str, Any], FormData]], + embed_body_fields: bool, +) -> Tuple[Dict[str, Any], List[Dict[str, Any]]]: + values: Dict[str, Any] = {} + errors: List[Dict[str, Any]] = [] + assert body_fields, "request_body_to_args() should be called with fields" + single_not_embedded_field = len(body_fields) == 1 and not embed_body_fields + first_field = body_fields[0] + body_to_process = received_body + + fields_to_extract: List[ModelField] = body_fields + + if single_not_embedded_field and lenient_issubclass(first_field.type_, BaseModel): + fields_to_extract = get_cached_model_fields(first_field.type_) + + if isinstance(received_body, FormData): + body_to_process = await _extract_form_body(fields_to_extract, received_body) + + if single_not_embedded_field: + loc: Tuple[str, ...] = ("body",) + v_, errors_ = _validate_value_with_model_field( + field=first_field, value=body_to_process, values=values, loc=loc + ) + return {first_field.name: v_}, errors_ + for field in body_fields: + loc = ("body", field.alias) + value: Optional[Any] = None + if body_to_process is not None: + try: + value = body_to_process.get(field.alias) + # If the received body is a list, not a dict + except AttributeError: + errors.append(get_missing_field_error(loc)) + continue + v_, errors_ = _validate_value_with_model_field( + field=field, value=value, values=values, loc=loc + ) + if errors_: + errors.extend(errors_) + else: + values[field.name] = v_ + return values, errors + + +def get_body_field( + *, flat_dependant: Dependant, name: str, embed_body_fields: bool +) -> Optional[ModelField]: + """ + Get a ModelField representing the request body for a path operation, combining + all body parameters into a single field if necessary. + + Used to check if it's form data (with `isinstance(body_field, params.Form)`) + or JSON and to generate the JSON Schema for a request body. + + This is **not** used to validate/parse the request body, that's done with each + individual body parameter. + """ + if not flat_dependant.body_params: + return None + first_param = flat_dependant.body_params[0] + if not embed_body_fields: + return first_param + model_name = "Body_" + name + BodyModel = create_body_model( + fields=flat_dependant.body_params, model_name=model_name + ) + required = any(True for f in flat_dependant.body_params if f.required) + BodyFieldInfo_kwargs: Dict[str, Any] = { + "annotation": BodyModel, + "alias": "body", + } + if not required: + BodyFieldInfo_kwargs["default"] = None + if any(isinstance(f.field_info, params.File) for f in flat_dependant.body_params): + BodyFieldInfo: Type[params.Body] = params.File + elif any(isinstance(f.field_info, params.Form) for f in flat_dependant.body_params): + BodyFieldInfo = params.Form + else: + BodyFieldInfo = params.Body + + body_param_media_types = [ + f.field_info.media_type + for f in flat_dependant.body_params + if isinstance(f.field_info, params.Body) + ] + if len(set(body_param_media_types)) == 1: + BodyFieldInfo_kwargs["media_type"] = body_param_media_types[0] + final_field = create_model_field( + name="body", + type_=BodyModel, + required=required, + alias="body", + field_info=BodyFieldInfo(**BodyFieldInfo_kwargs), + ) + return final_field diff --git a/backend/.venv/Lib/site-packages/fastapi/encoders.py b/backend/.venv/Lib/site-packages/fastapi/encoders.py new file mode 100644 index 0000000..451ea07 --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/encoders.py @@ -0,0 +1,343 @@ +import dataclasses +import datetime +from collections import defaultdict, deque +from decimal import Decimal +from enum import Enum +from ipaddress import ( + IPv4Address, + IPv4Interface, + IPv4Network, + IPv6Address, + IPv6Interface, + IPv6Network, +) +from pathlib import Path, PurePath +from re import Pattern +from types import GeneratorType +from typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union +from uuid import UUID + +from fastapi.types import IncEx +from pydantic import BaseModel +from pydantic.color import Color +from pydantic.networks import AnyUrl, NameEmail +from pydantic.types import SecretBytes, SecretStr +from typing_extensions import Annotated, Doc + +from ._compat import PYDANTIC_V2, UndefinedType, Url, _model_dump + + +# Taken from Pydantic v1 as is +def isoformat(o: Union[datetime.date, datetime.time]) -> str: + return o.isoformat() + + +# Taken from Pydantic v1 as is +# TODO: pv2 should this return strings instead? +def decimal_encoder(dec_value: Decimal) -> Union[int, float]: + """ + Encodes a Decimal as int of there's no exponent, otherwise float + + This is useful when we use ConstrainedDecimal to represent Numeric(x,0) + where a integer (but not int typed) is used. Encoding this as a float + results in failed round-tripping between encode and parse. + Our Id type is a prime example of this. + + >>> decimal_encoder(Decimal("1.0")) + 1.0 + + >>> decimal_encoder(Decimal("1")) + 1 + """ + if dec_value.as_tuple().exponent >= 0: # type: ignore[operator] + return int(dec_value) + else: + return float(dec_value) + + +ENCODERS_BY_TYPE: Dict[Type[Any], Callable[[Any], Any]] = { + bytes: lambda o: o.decode(), + Color: str, + datetime.date: isoformat, + datetime.datetime: isoformat, + datetime.time: isoformat, + datetime.timedelta: lambda td: td.total_seconds(), + Decimal: decimal_encoder, + Enum: lambda o: o.value, + frozenset: list, + deque: list, + GeneratorType: list, + IPv4Address: str, + IPv4Interface: str, + IPv4Network: str, + IPv6Address: str, + IPv6Interface: str, + IPv6Network: str, + NameEmail: str, + Path: str, + Pattern: lambda o: o.pattern, + SecretBytes: str, + SecretStr: str, + set: list, + UUID: str, + Url: str, + AnyUrl: str, +} + + +def generate_encoders_by_class_tuples( + type_encoder_map: Dict[Any, Callable[[Any], Any]], +) -> Dict[Callable[[Any], Any], Tuple[Any, ...]]: + encoders_by_class_tuples: Dict[Callable[[Any], Any], Tuple[Any, ...]] = defaultdict( + tuple + ) + for type_, encoder in type_encoder_map.items(): + encoders_by_class_tuples[encoder] += (type_,) + return encoders_by_class_tuples + + +encoders_by_class_tuples = generate_encoders_by_class_tuples(ENCODERS_BY_TYPE) + + +def jsonable_encoder( + obj: Annotated[ + Any, + Doc( + """ + The input object to convert to JSON. + """ + ), + ], + include: Annotated[ + Optional[IncEx], + Doc( + """ + Pydantic's `include` parameter, passed to Pydantic models to set the + fields to include. + """ + ), + ] = None, + exclude: Annotated[ + Optional[IncEx], + Doc( + """ + Pydantic's `exclude` parameter, passed to Pydantic models to set the + fields to exclude. + """ + ), + ] = None, + by_alias: Annotated[ + bool, + Doc( + """ + Pydantic's `by_alias` parameter, passed to Pydantic models to define if + the output should use the alias names (when provided) or the Python + attribute names. In an API, if you set an alias, it's probably because you + want to use it in the result, so you probably want to leave this set to + `True`. + """ + ), + ] = True, + exclude_unset: Annotated[ + bool, + Doc( + """ + Pydantic's `exclude_unset` parameter, passed to Pydantic models to define + if it should exclude from the output the fields that were not explicitly + set (and that only had their default values). + """ + ), + ] = False, + exclude_defaults: Annotated[ + bool, + Doc( + """ + Pydantic's `exclude_defaults` parameter, passed to Pydantic models to define + if it should exclude from the output the fields that had the same default + value, even when they were explicitly set. + """ + ), + ] = False, + exclude_none: Annotated[ + bool, + Doc( + """ + Pydantic's `exclude_none` parameter, passed to Pydantic models to define + if it should exclude from the output any fields that have a `None` value. + """ + ), + ] = False, + custom_encoder: Annotated[ + Optional[Dict[Any, Callable[[Any], Any]]], + Doc( + """ + Pydantic's `custom_encoder` parameter, passed to Pydantic models to define + a custom encoder. + """ + ), + ] = None, + sqlalchemy_safe: Annotated[ + bool, + Doc( + """ + Exclude from the output any fields that start with the name `_sa`. + + This is mainly a hack for compatibility with SQLAlchemy objects, they + store internal SQLAlchemy-specific state in attributes named with `_sa`, + and those objects can't (and shouldn't be) serialized to JSON. + """ + ), + ] = True, +) -> Any: + """ + Convert any object to something that can be encoded in JSON. + + This is used internally by FastAPI to make sure anything you return can be + encoded as JSON before it is sent to the client. + + You can also use it yourself, for example to convert objects before saving them + in a database that supports only JSON. + + Read more about it in the + [FastAPI docs for JSON Compatible Encoder](https://fastapi.tiangolo.com/tutorial/encoder/). + """ + custom_encoder = custom_encoder or {} + if custom_encoder: + if type(obj) in custom_encoder: + return custom_encoder[type(obj)](obj) + else: + for encoder_type, encoder_instance in custom_encoder.items(): + if isinstance(obj, encoder_type): + return encoder_instance(obj) + if include is not None and not isinstance(include, (set, dict)): + include = set(include) + if exclude is not None and not isinstance(exclude, (set, dict)): + exclude = set(exclude) + if isinstance(obj, BaseModel): + # TODO: remove when deprecating Pydantic v1 + encoders: Dict[Any, Any] = {} + if not PYDANTIC_V2: + encoders = getattr(obj.__config__, "json_encoders", {}) # type: ignore[attr-defined] + if custom_encoder: + encoders.update(custom_encoder) + obj_dict = _model_dump( + obj, + mode="json", + include=include, + exclude=exclude, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_none=exclude_none, + exclude_defaults=exclude_defaults, + ) + if "__root__" in obj_dict: + obj_dict = obj_dict["__root__"] + return jsonable_encoder( + obj_dict, + exclude_none=exclude_none, + exclude_defaults=exclude_defaults, + # TODO: remove when deprecating Pydantic v1 + custom_encoder=encoders, + sqlalchemy_safe=sqlalchemy_safe, + ) + if dataclasses.is_dataclass(obj): + obj_dict = dataclasses.asdict(obj) + return jsonable_encoder( + obj_dict, + include=include, + exclude=exclude, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + custom_encoder=custom_encoder, + sqlalchemy_safe=sqlalchemy_safe, + ) + if isinstance(obj, Enum): + return obj.value + if isinstance(obj, PurePath): + return str(obj) + if isinstance(obj, (str, int, float, type(None))): + return obj + if isinstance(obj, UndefinedType): + return None + if isinstance(obj, dict): + encoded_dict = {} + allowed_keys = set(obj.keys()) + if include is not None: + allowed_keys &= set(include) + if exclude is not None: + allowed_keys -= set(exclude) + for key, value in obj.items(): + if ( + ( + not sqlalchemy_safe + or (not isinstance(key, str)) + or (not key.startswith("_sa")) + ) + and (value is not None or not exclude_none) + and key in allowed_keys + ): + encoded_key = jsonable_encoder( + key, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_none=exclude_none, + custom_encoder=custom_encoder, + sqlalchemy_safe=sqlalchemy_safe, + ) + encoded_value = jsonable_encoder( + value, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_none=exclude_none, + custom_encoder=custom_encoder, + sqlalchemy_safe=sqlalchemy_safe, + ) + encoded_dict[encoded_key] = encoded_value + return encoded_dict + if isinstance(obj, (list, set, frozenset, GeneratorType, tuple, deque)): + encoded_list = [] + for item in obj: + encoded_list.append( + jsonable_encoder( + item, + include=include, + exclude=exclude, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + custom_encoder=custom_encoder, + sqlalchemy_safe=sqlalchemy_safe, + ) + ) + return encoded_list + + if type(obj) in ENCODERS_BY_TYPE: + return ENCODERS_BY_TYPE[type(obj)](obj) + for encoder, classes_tuple in encoders_by_class_tuples.items(): + if isinstance(obj, classes_tuple): + return encoder(obj) + + try: + data = dict(obj) + except Exception as e: + errors: List[Exception] = [] + errors.append(e) + try: + data = vars(obj) + except Exception as e: + errors.append(e) + raise ValueError(errors) from e + return jsonable_encoder( + data, + include=include, + exclude=exclude, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + custom_encoder=custom_encoder, + sqlalchemy_safe=sqlalchemy_safe, + ) diff --git a/backend/.venv/Lib/site-packages/fastapi/exception_handlers.py b/backend/.venv/Lib/site-packages/fastapi/exception_handlers.py new file mode 100644 index 0000000..6c2ba7f --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/exception_handlers.py @@ -0,0 +1,34 @@ +from fastapi.encoders import jsonable_encoder +from fastapi.exceptions import RequestValidationError, WebSocketRequestValidationError +from fastapi.utils import is_body_allowed_for_status_code +from fastapi.websockets import WebSocket +from starlette.exceptions import HTTPException +from starlette.requests import Request +from starlette.responses import JSONResponse, Response +from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY, WS_1008_POLICY_VIOLATION + + +async def http_exception_handler(request: Request, exc: HTTPException) -> Response: + headers = getattr(exc, "headers", None) + if not is_body_allowed_for_status_code(exc.status_code): + return Response(status_code=exc.status_code, headers=headers) + return JSONResponse( + {"detail": exc.detail}, status_code=exc.status_code, headers=headers + ) + + +async def request_validation_exception_handler( + request: Request, exc: RequestValidationError +) -> JSONResponse: + return JSONResponse( + status_code=HTTP_422_UNPROCESSABLE_ENTITY, + content={"detail": jsonable_encoder(exc.errors())}, + ) + + +async def websocket_request_validation_exception_handler( + websocket: WebSocket, exc: WebSocketRequestValidationError +) -> None: + await websocket.close( + code=WS_1008_POLICY_VIOLATION, reason=jsonable_encoder(exc.errors()) + ) diff --git a/backend/.venv/Lib/site-packages/fastapi/exceptions.py b/backend/.venv/Lib/site-packages/fastapi/exceptions.py new file mode 100644 index 0000000..44d4ada --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/exceptions.py @@ -0,0 +1,176 @@ +from typing import Any, Dict, Optional, Sequence, Type, Union + +from pydantic import BaseModel, create_model +from starlette.exceptions import HTTPException as StarletteHTTPException +from starlette.exceptions import WebSocketException as StarletteWebSocketException +from typing_extensions import Annotated, Doc + + +class HTTPException(StarletteHTTPException): + """ + An HTTP exception you can raise in your own code to show errors to the client. + + This is for client errors, invalid authentication, invalid data, etc. Not for server + errors in your code. + + Read more about it in the + [FastAPI docs for Handling Errors](https://fastapi.tiangolo.com/tutorial/handling-errors/). + + ## Example + + ```python + from fastapi import FastAPI, HTTPException + + app = FastAPI() + + items = {"foo": "The Foo Wrestlers"} + + + @app.get("/items/{item_id}") + async def read_item(item_id: str): + if item_id not in items: + raise HTTPException(status_code=404, detail="Item not found") + return {"item": items[item_id]} + ``` + """ + + def __init__( + self, + status_code: Annotated[ + int, + Doc( + """ + HTTP status code to send to the client. + """ + ), + ], + detail: Annotated[ + Any, + Doc( + """ + Any data to be sent to the client in the `detail` key of the JSON + response. + """ + ), + ] = None, + headers: Annotated[ + Optional[Dict[str, str]], + Doc( + """ + Any headers to send to the client in the response. + """ + ), + ] = None, + ) -> None: + super().__init__(status_code=status_code, detail=detail, headers=headers) + + +class WebSocketException(StarletteWebSocketException): + """ + A WebSocket exception you can raise in your own code to show errors to the client. + + This is for client errors, invalid authentication, invalid data, etc. Not for server + errors in your code. + + Read more about it in the + [FastAPI docs for WebSockets](https://fastapi.tiangolo.com/advanced/websockets/). + + ## Example + + ```python + from typing import Annotated + + from fastapi import ( + Cookie, + FastAPI, + WebSocket, + WebSocketException, + status, + ) + + app = FastAPI() + + @app.websocket("/items/{item_id}/ws") + async def websocket_endpoint( + *, + websocket: WebSocket, + session: Annotated[str | None, Cookie()] = None, + item_id: str, + ): + if session is None: + raise WebSocketException(code=status.WS_1008_POLICY_VIOLATION) + await websocket.accept() + while True: + data = await websocket.receive_text() + await websocket.send_text(f"Session cookie is: {session}") + await websocket.send_text(f"Message text was: {data}, for item ID: {item_id}") + ``` + """ + + def __init__( + self, + code: Annotated[ + int, + Doc( + """ + A closing code from the + [valid codes defined in the specification](https://datatracker.ietf.org/doc/html/rfc6455#section-7.4.1). + """ + ), + ], + reason: Annotated[ + Union[str, None], + Doc( + """ + The reason to close the WebSocket connection. + + It is UTF-8-encoded data. The interpretation of the reason is up to the + application, it is not specified by the WebSocket specification. + + It could contain text that could be human-readable or interpretable + by the client code, etc. + """ + ), + ] = None, + ) -> None: + super().__init__(code=code, reason=reason) + + +RequestErrorModel: Type[BaseModel] = create_model("Request") +WebSocketErrorModel: Type[BaseModel] = create_model("WebSocket") + + +class FastAPIError(RuntimeError): + """ + A generic, FastAPI-specific error. + """ + + +class ValidationException(Exception): + def __init__(self, errors: Sequence[Any]) -> None: + self._errors = errors + + def errors(self) -> Sequence[Any]: + return self._errors + + +class RequestValidationError(ValidationException): + def __init__(self, errors: Sequence[Any], *, body: Any = None) -> None: + super().__init__(errors) + self.body = body + + +class WebSocketRequestValidationError(ValidationException): + pass + + +class ResponseValidationError(ValidationException): + def __init__(self, errors: Sequence[Any], *, body: Any = None) -> None: + super().__init__(errors) + self.body = body + + def __str__(self) -> str: + message = f"{len(self._errors)} validation errors:\n" + for err in self._errors: + message += f" {err}\n" + return message diff --git a/backend/.venv/Lib/site-packages/fastapi/logger.py b/backend/.venv/Lib/site-packages/fastapi/logger.py new file mode 100644 index 0000000..5b2c4ad --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/logger.py @@ -0,0 +1,3 @@ +import logging + +logger = logging.getLogger("fastapi") diff --git a/backend/.venv/Lib/site-packages/fastapi/middleware/__init__.py b/backend/.venv/Lib/site-packages/fastapi/middleware/__init__.py new file mode 100644 index 0000000..620296d --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/middleware/__init__.py @@ -0,0 +1 @@ +from starlette.middleware import Middleware as Middleware diff --git a/backend/.venv/Lib/site-packages/fastapi/middleware/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/middleware/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..246421b0954194ba65c53e8033b66aa925d68e30 GIT binary patch literal 251 zcmX@j%ge<81V%BonN~phF^B^LOi;#W0U%>KLkdF*V-7n0{A=a=S{Wag#oCg&HW#v~;sXQ$?+#ORf!=9R_xWG2NFXO^Vu0yShOrl%Ii zq$L7vDah1E*q|RDpP83g5+AQuP}SQfDX FIRK@wM<4(I literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/middleware/__pycache__/cors.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/middleware/__pycache__/cors.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..66ca4d787c1e63446c36eeb16d6098c23b3b4c48 GIT binary patch literal 256 zcmX@j%ge<81V%Bonf^ffF^B^LOi;#W0U%>KLkdF*V-7jIUh#v~;sXQ$?+#ORf!=9R_xWG2NFXO^Vu z0yShOrl%Iiq$L8aD#+AFSfdZJMz5gq7Kcr4eoARhs$CHW&@x6KE(S3^Ff%eT-eYhp HVgqsj8JtM! literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/middleware/__pycache__/gzip.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/middleware/__pycache__/gzip.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5544b9f6a51c8ab9a2d230e21b484dba5d7f07f8 GIT binary patch literal 256 zcmX@j%ge<81V%Bonf^ffF^B^LOi;#W0U%>KLkdF*V-7n7(HrN$&BCTFMSrNro!rRJ5z_+%!<6la#C z>H;-nC#I(s$D}0!tt!aWM_8i|vPQ3<@)n0pZhlH>PO4oI2hcJ`AT9KLkdF*V-7hD zpfM{MK7&mAmFjF2Q=VUxU0jfuoEnptRZ^^*n4FwnnpcvUm#&+fUz8e?l$e~InwJuz zSC*Pr7UPqd6jPj8lBx^Tke!&GS{##>2(+^xQy*cUK8k&M1(mlrY;yBcN^?@}ia3C_ YG6HciC>TC4Gcq!MV`5@tDq;h20cb5$E&u=k literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/middleware/__pycache__/trustedhost.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/middleware/__pycache__/trustedhost.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..50f15a9a7f704c80fabfb3484847548dc514f245 GIT binary patch literal 279 zcmX@j%ge<81V%BonYlpvF^B^LOi;#W0U%>KLkdF*V-7 zK7&m9mF#R4Q=VUxU0jfuoEnptRZ^^*n4FwnnpcvUm#&+fUz8e?l$e~InwJuzSC*Pr z7UPqd6jPj8lBx^Tke!&GS{##>2(+;vQy*cQK9X&E1(mlrY;yBcN^?@}ia3CFG6Hci UC;&b%Gcq!MV`5@tDq;h20k3;fZU6uP literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/middleware/__pycache__/wsgi.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/middleware/__pycache__/wsgi.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7c070e78fc1897da896a024f27baab3626327e9d GIT binary patch literal 256 zcmX@j%ge<81V%Bonf^ffF^B^LOi;#W0U%>KLkdF*V-7 z@L+dO-^`ShoYeBfqEtUkrdyK5C5c5jsU;<;dbw~3z4GGp%pzu>rj-nzL3)41I9tV( z=NDxc7bGU9#^hy{6ze7?C+C;um1O3n>n7(HrN$&BCTFMSrNro!rRJ5z_+%!<6la#C z>H;-nC#I(s$D}0!tt!aWM_8i|vPQ3<@)n0pZhlH>PO4oI2hcJ`AT9`1s7c%#!$cy@JYH95%W6DWy57c15f}+Zchk7{vI<%*e=C I#0+Es0As#0P5=M^ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/openapi/__pycache__/constants.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/openapi/__pycache__/constants.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ff7f98347c01ecb11e3e4051fa96f4de20bfc439 GIT binary patch literal 360 zcmX@j%ge<81V%BonKOa(V-N=hn4pZ$B0$D;h75)jhQ*9g3@MCJj44b}OqI-?_R9QbcKer%1FEy{E zSid+qBQ-a%SiedJt8jI0eoAUit)C|IEkR$`5D$Ns;P`OQ5RZ5#f0xKxTtTjG@c}@> zGvXExh#lhU8{p#@;<}RIGsw-q;+(Bw%JYk|iwhEyQ)BY7N{V$8laupH^GY)F(sh&b zi&A5f5|gu2^HO5;%2M;nVtg`_Vu~|MQgwkEvJ=x&i(}Ffi%Sv*An}2jk&*G1i0cIg!5h3P4O}<)bsKq#cz`kh De+Fz^ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/openapi/__pycache__/docs.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/openapi/__pycache__/docs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..21e707e212ded781ab7c553b893135dfc77b8ddc GIT binary patch literal 10810 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/openapi/__pycache__/models.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/openapi/__pycache__/models.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fdde680ed9692cac20c333b621a5e9c6ae0172ab GIT binary patch literal 22998 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/openapi/constants.py b/backend/.venv/Lib/site-packages/fastapi/openapi/constants.py new file mode 100644 index 0000000..d724ee3 --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/openapi/constants.py @@ -0,0 +1,3 @@ +METHODS_WITH_BODY = {"GET", "HEAD", "POST", "PUT", "DELETE", "PATCH"} +REF_PREFIX = "#/components/schemas/" +REF_TEMPLATE = "#/components/schemas/{model}" diff --git a/backend/.venv/Lib/site-packages/fastapi/openapi/docs.py b/backend/.venv/Lib/site-packages/fastapi/openapi/docs.py new file mode 100644 index 0000000..c2ec358 --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/openapi/docs.py @@ -0,0 +1,344 @@ +import json +from typing import Any, Dict, Optional + +from fastapi.encoders import jsonable_encoder +from starlette.responses import HTMLResponse +from typing_extensions import Annotated, Doc + +swagger_ui_default_parameters: Annotated[ + Dict[str, Any], + Doc( + """ + Default configurations for Swagger UI. + + You can use it as a template to add any other configurations needed. + """ + ), +] = { + "dom_id": "#swagger-ui", + "layout": "BaseLayout", + "deepLinking": True, + "showExtensions": True, + "showCommonExtensions": True, +} + + +def get_swagger_ui_html( + *, + openapi_url: Annotated[ + str, + Doc( + """ + The OpenAPI URL that Swagger UI should load and use. + + This is normally done automatically by FastAPI using the default URL + `/openapi.json`. + """ + ), + ], + title: Annotated[ + str, + Doc( + """ + The HTML `` content, normally shown in the browser tab. + """ + ), + ], + swagger_js_url: Annotated[ + str, + Doc( + """ + The URL to use to load the Swagger UI JavaScript. + + It is normally set to a CDN URL. + """ + ), + ] = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js", + swagger_css_url: Annotated[ + str, + Doc( + """ + The URL to use to load the Swagger UI CSS. + + It is normally set to a CDN URL. + """ + ), + ] = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css", + swagger_favicon_url: Annotated[ + str, + Doc( + """ + The URL of the favicon to use. It is normally shown in the browser tab. + """ + ), + ] = "https://fastapi.tiangolo.com/img/favicon.png", + oauth2_redirect_url: Annotated[ + Optional[str], + Doc( + """ + The OAuth2 redirect URL, it is normally automatically handled by FastAPI. + """ + ), + ] = None, + init_oauth: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + A dictionary with Swagger UI OAuth2 initialization configurations. + """ + ), + ] = None, + swagger_ui_parameters: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + Configuration parameters for Swagger UI. + + It defaults to [swagger_ui_default_parameters][fastapi.openapi.docs.swagger_ui_default_parameters]. + """ + ), + ] = None, +) -> HTMLResponse: + """ + Generate and return the HTML that loads Swagger UI for the interactive + API docs (normally served at `/docs`). + + You would only call this function yourself if you needed to override some parts, + for example the URLs to use to load Swagger UI's JavaScript and CSS. + + Read more about it in the + [FastAPI docs for Configure Swagger UI](https://fastapi.tiangolo.com/how-to/configure-swagger-ui/) + and the [FastAPI docs for Custom Docs UI Static Assets (Self-Hosting)](https://fastapi.tiangolo.com/how-to/custom-docs-ui-assets/). + """ + current_swagger_ui_parameters = swagger_ui_default_parameters.copy() + if swagger_ui_parameters: + current_swagger_ui_parameters.update(swagger_ui_parameters) + + html = f""" + <!DOCTYPE html> + <html> + <head> + <link type="text/css" rel="stylesheet" href="{swagger_css_url}"> + <link rel="shortcut icon" href="{swagger_favicon_url}"> + <title>{title} + + +

+
+ + + + + + """ + return HTMLResponse(html) + + +def get_redoc_html( + *, + openapi_url: Annotated[ + str, + Doc( + """ + The OpenAPI URL that ReDoc should load and use. + + This is normally done automatically by FastAPI using the default URL + `/openapi.json`. + """ + ), + ], + title: Annotated[ + str, + Doc( + """ + The HTML `` content, normally shown in the browser tab. + """ + ), + ], + redoc_js_url: Annotated[ + str, + Doc( + """ + The URL to use to load the ReDoc JavaScript. + + It is normally set to a CDN URL. + """ + ), + ] = "https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js", + redoc_favicon_url: Annotated[ + str, + Doc( + """ + The URL of the favicon to use. It is normally shown in the browser tab. + """ + ), + ] = "https://fastapi.tiangolo.com/img/favicon.png", + with_google_fonts: Annotated[ + bool, + Doc( + """ + Load and use Google Fonts. + """ + ), + ] = True, +) -> HTMLResponse: + """ + Generate and return the HTML response that loads ReDoc for the alternative + API docs (normally served at `/redoc`). + + You would only call this function yourself if you needed to override some parts, + for example the URLs to use to load ReDoc's JavaScript and CSS. + + Read more about it in the + [FastAPI docs for Custom Docs UI Static Assets (Self-Hosting)](https://fastapi.tiangolo.com/how-to/custom-docs-ui-assets/). + """ + html = f""" + <!DOCTYPE html> + <html> + <head> + <title>{title} + + + + """ + if with_google_fonts: + html += """ + + """ + html += f""" + + + + + + + + + + + """ + return HTMLResponse(html) + + +def get_swagger_ui_oauth2_redirect_html() -> HTMLResponse: + """ + Generate the HTML response with the OAuth2 redirection for Swagger UI. + + You normally don't need to use or change this. + """ + # copied from https://github.com/swagger-api/swagger-ui/blob/v4.14.0/dist/oauth2-redirect.html + html = """ + + + + Swagger UI: OAuth2 Redirect + + + + + + """ + return HTMLResponse(content=html) diff --git a/backend/.venv/Lib/site-packages/fastapi/openapi/models.py b/backend/.venv/Lib/site-packages/fastapi/openapi/models.py new file mode 100644 index 0000000..ed07b40 --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/openapi/models.py @@ -0,0 +1,445 @@ +from enum import Enum +from typing import Any, Callable, Dict, Iterable, List, Optional, Set, Type, Union + +from fastapi._compat import ( + PYDANTIC_V2, + CoreSchema, + GetJsonSchemaHandler, + JsonSchemaValue, + _model_rebuild, + with_info_plain_validator_function, +) +from fastapi.logger import logger +from pydantic import AnyUrl, BaseModel, Field +from typing_extensions import Annotated, Literal, TypedDict +from typing_extensions import deprecated as typing_deprecated + +try: + import email_validator + + assert email_validator # make autoflake ignore the unused import + from pydantic import EmailStr +except ImportError: # pragma: no cover + + class EmailStr(str): # type: ignore + @classmethod + def __get_validators__(cls) -> Iterable[Callable[..., Any]]: + yield cls.validate + + @classmethod + def validate(cls, v: Any) -> str: + logger.warning( + "email-validator not installed, email fields will be treated as str.\n" + "To install, run: pip install email-validator" + ) + return str(v) + + @classmethod + def _validate(cls, __input_value: Any, _: Any) -> str: + logger.warning( + "email-validator not installed, email fields will be treated as str.\n" + "To install, run: pip install email-validator" + ) + return str(__input_value) + + @classmethod + def __get_pydantic_json_schema__( + cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler + ) -> JsonSchemaValue: + return {"type": "string", "format": "email"} + + @classmethod + def __get_pydantic_core_schema__( + cls, source: Type[Any], handler: Callable[[Any], CoreSchema] + ) -> CoreSchema: + return with_info_plain_validator_function(cls._validate) + + +class BaseModelWithConfig(BaseModel): + if PYDANTIC_V2: + model_config = {"extra": "allow"} + + else: + + class Config: + extra = "allow" + + +class Contact(BaseModelWithConfig): + name: Optional[str] = None + url: Optional[AnyUrl] = None + email: Optional[EmailStr] = None + + +class License(BaseModelWithConfig): + name: str + identifier: Optional[str] = None + url: Optional[AnyUrl] = None + + +class Info(BaseModelWithConfig): + title: str + summary: Optional[str] = None + description: Optional[str] = None + termsOfService: Optional[str] = None + contact: Optional[Contact] = None + license: Optional[License] = None + version: str + + +class ServerVariable(BaseModelWithConfig): + enum: Annotated[Optional[List[str]], Field(min_length=1)] = None + default: str + description: Optional[str] = None + + +class Server(BaseModelWithConfig): + url: Union[AnyUrl, str] + description: Optional[str] = None + variables: Optional[Dict[str, ServerVariable]] = None + + +class Reference(BaseModel): + ref: str = Field(alias="$ref") + + +class Discriminator(BaseModel): + propertyName: str + mapping: Optional[Dict[str, str]] = None + + +class XML(BaseModelWithConfig): + name: Optional[str] = None + namespace: Optional[str] = None + prefix: Optional[str] = None + attribute: Optional[bool] = None + wrapped: Optional[bool] = None + + +class ExternalDocumentation(BaseModelWithConfig): + description: Optional[str] = None + url: AnyUrl + + +class Schema(BaseModelWithConfig): + # Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-the-json-schema-core-vocabu + # Core Vocabulary + schema_: Optional[str] = Field(default=None, alias="$schema") + vocabulary: Optional[str] = Field(default=None, alias="$vocabulary") + id: Optional[str] = Field(default=None, alias="$id") + anchor: Optional[str] = Field(default=None, alias="$anchor") + dynamicAnchor: Optional[str] = Field(default=None, alias="$dynamicAnchor") + ref: Optional[str] = Field(default=None, alias="$ref") + dynamicRef: Optional[str] = Field(default=None, alias="$dynamicRef") + defs: Optional[Dict[str, "SchemaOrBool"]] = Field(default=None, alias="$defs") + comment: Optional[str] = Field(default=None, alias="$comment") + # Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-a-vocabulary-for-applying-s + # A Vocabulary for Applying Subschemas + allOf: Optional[List["SchemaOrBool"]] = None + anyOf: Optional[List["SchemaOrBool"]] = None + oneOf: Optional[List["SchemaOrBool"]] = None + not_: Optional["SchemaOrBool"] = Field(default=None, alias="not") + if_: Optional["SchemaOrBool"] = Field(default=None, alias="if") + then: Optional["SchemaOrBool"] = None + else_: Optional["SchemaOrBool"] = Field(default=None, alias="else") + dependentSchemas: Optional[Dict[str, "SchemaOrBool"]] = None + prefixItems: Optional[List["SchemaOrBool"]] = None + # TODO: uncomment and remove below when deprecating Pydantic v1 + # It generales a list of schemas for tuples, before prefixItems was available + # items: Optional["SchemaOrBool"] = None + items: Optional[Union["SchemaOrBool", List["SchemaOrBool"]]] = None + contains: Optional["SchemaOrBool"] = None + properties: Optional[Dict[str, "SchemaOrBool"]] = None + patternProperties: Optional[Dict[str, "SchemaOrBool"]] = None + additionalProperties: Optional["SchemaOrBool"] = None + propertyNames: Optional["SchemaOrBool"] = None + unevaluatedItems: Optional["SchemaOrBool"] = None + unevaluatedProperties: Optional["SchemaOrBool"] = None + # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-structural + # A Vocabulary for Structural Validation + type: Optional[str] = None + enum: Optional[List[Any]] = None + const: Optional[Any] = None + multipleOf: Optional[float] = Field(default=None, gt=0) + maximum: Optional[float] = None + exclusiveMaximum: Optional[float] = None + minimum: Optional[float] = None + exclusiveMinimum: Optional[float] = None + maxLength: Optional[int] = Field(default=None, ge=0) + minLength: Optional[int] = Field(default=None, ge=0) + pattern: Optional[str] = None + maxItems: Optional[int] = Field(default=None, ge=0) + minItems: Optional[int] = Field(default=None, ge=0) + uniqueItems: Optional[bool] = None + maxContains: Optional[int] = Field(default=None, ge=0) + minContains: Optional[int] = Field(default=None, ge=0) + maxProperties: Optional[int] = Field(default=None, ge=0) + minProperties: Optional[int] = Field(default=None, ge=0) + required: Optional[List[str]] = None + dependentRequired: Optional[Dict[str, Set[str]]] = None + # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-vocabularies-for-semantic-c + # Vocabularies for Semantic Content With "format" + format: Optional[str] = None + # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-the-conten + # A Vocabulary for the Contents of String-Encoded Data + contentEncoding: Optional[str] = None + contentMediaType: Optional[str] = None + contentSchema: Optional["SchemaOrBool"] = None + # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-basic-meta + # A Vocabulary for Basic Meta-Data Annotations + title: Optional[str] = None + description: Optional[str] = None + default: Optional[Any] = None + deprecated: Optional[bool] = None + readOnly: Optional[bool] = None + writeOnly: Optional[bool] = None + examples: Optional[List[Any]] = None + # Ref: OpenAPI 3.1.0: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#schema-object + # Schema Object + discriminator: Optional[Discriminator] = None + xml: Optional[XML] = None + externalDocs: Optional[ExternalDocumentation] = None + example: Annotated[ + Optional[Any], + typing_deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = None + + +# Ref: https://json-schema.org/draft/2020-12/json-schema-core.html#name-json-schema-documents +# A JSON Schema MUST be an object or a boolean. +SchemaOrBool = Union[Schema, bool] + + +class Example(TypedDict, total=False): + summary: Optional[str] + description: Optional[str] + value: Optional[Any] + externalValue: Optional[AnyUrl] + + if PYDANTIC_V2: # type: ignore [misc] + __pydantic_config__ = {"extra": "allow"} + + else: + + class Config: + extra = "allow" + + +class ParameterInType(Enum): + query = "query" + header = "header" + path = "path" + cookie = "cookie" + + +class Encoding(BaseModelWithConfig): + contentType: Optional[str] = None + headers: Optional[Dict[str, Union["Header", Reference]]] = None + style: Optional[str] = None + explode: Optional[bool] = None + allowReserved: Optional[bool] = None + + +class MediaType(BaseModelWithConfig): + schema_: Optional[Union[Schema, Reference]] = Field(default=None, alias="schema") + example: Optional[Any] = None + examples: Optional[Dict[str, Union[Example, Reference]]] = None + encoding: Optional[Dict[str, Encoding]] = None + + +class ParameterBase(BaseModelWithConfig): + description: Optional[str] = None + required: Optional[bool] = None + deprecated: Optional[bool] = None + # Serialization rules for simple scenarios + style: Optional[str] = None + explode: Optional[bool] = None + allowReserved: Optional[bool] = None + schema_: Optional[Union[Schema, Reference]] = Field(default=None, alias="schema") + example: Optional[Any] = None + examples: Optional[Dict[str, Union[Example, Reference]]] = None + # Serialization rules for more complex scenarios + content: Optional[Dict[str, MediaType]] = None + + +class Parameter(ParameterBase): + name: str + in_: ParameterInType = Field(alias="in") + + +class Header(ParameterBase): + pass + + +class RequestBody(BaseModelWithConfig): + description: Optional[str] = None + content: Dict[str, MediaType] + required: Optional[bool] = None + + +class Link(BaseModelWithConfig): + operationRef: Optional[str] = None + operationId: Optional[str] = None + parameters: Optional[Dict[str, Union[Any, str]]] = None + requestBody: Optional[Union[Any, str]] = None + description: Optional[str] = None + server: Optional[Server] = None + + +class Response(BaseModelWithConfig): + description: str + headers: Optional[Dict[str, Union[Header, Reference]]] = None + content: Optional[Dict[str, MediaType]] = None + links: Optional[Dict[str, Union[Link, Reference]]] = None + + +class Operation(BaseModelWithConfig): + tags: Optional[List[str]] = None + summary: Optional[str] = None + description: Optional[str] = None + externalDocs: Optional[ExternalDocumentation] = None + operationId: Optional[str] = None + parameters: Optional[List[Union[Parameter, Reference]]] = None + requestBody: Optional[Union[RequestBody, Reference]] = None + # Using Any for Specification Extensions + responses: Optional[Dict[str, Union[Response, Any]]] = None + callbacks: Optional[Dict[str, Union[Dict[str, "PathItem"], Reference]]] = None + deprecated: Optional[bool] = None + security: Optional[List[Dict[str, List[str]]]] = None + servers: Optional[List[Server]] = None + + +class PathItem(BaseModelWithConfig): + ref: Optional[str] = Field(default=None, alias="$ref") + summary: Optional[str] = None + description: Optional[str] = None + get: Optional[Operation] = None + put: Optional[Operation] = None + post: Optional[Operation] = None + delete: Optional[Operation] = None + options: Optional[Operation] = None + head: Optional[Operation] = None + patch: Optional[Operation] = None + trace: Optional[Operation] = None + servers: Optional[List[Server]] = None + parameters: Optional[List[Union[Parameter, Reference]]] = None + + +class SecuritySchemeType(Enum): + apiKey = "apiKey" + http = "http" + oauth2 = "oauth2" + openIdConnect = "openIdConnect" + + +class SecurityBase(BaseModelWithConfig): + type_: SecuritySchemeType = Field(alias="type") + description: Optional[str] = None + + +class APIKeyIn(Enum): + query = "query" + header = "header" + cookie = "cookie" + + +class APIKey(SecurityBase): + type_: SecuritySchemeType = Field(default=SecuritySchemeType.apiKey, alias="type") + in_: APIKeyIn = Field(alias="in") + name: str + + +class HTTPBase(SecurityBase): + type_: SecuritySchemeType = Field(default=SecuritySchemeType.http, alias="type") + scheme: str + + +class HTTPBearer(HTTPBase): + scheme: Literal["bearer"] = "bearer" + bearerFormat: Optional[str] = None + + +class OAuthFlow(BaseModelWithConfig): + refreshUrl: Optional[str] = None + scopes: Dict[str, str] = {} + + +class OAuthFlowImplicit(OAuthFlow): + authorizationUrl: str + + +class OAuthFlowPassword(OAuthFlow): + tokenUrl: str + + +class OAuthFlowClientCredentials(OAuthFlow): + tokenUrl: str + + +class OAuthFlowAuthorizationCode(OAuthFlow): + authorizationUrl: str + tokenUrl: str + + +class OAuthFlows(BaseModelWithConfig): + implicit: Optional[OAuthFlowImplicit] = None + password: Optional[OAuthFlowPassword] = None + clientCredentials: Optional[OAuthFlowClientCredentials] = None + authorizationCode: Optional[OAuthFlowAuthorizationCode] = None + + +class OAuth2(SecurityBase): + type_: SecuritySchemeType = Field(default=SecuritySchemeType.oauth2, alias="type") + flows: OAuthFlows + + +class OpenIdConnect(SecurityBase): + type_: SecuritySchemeType = Field( + default=SecuritySchemeType.openIdConnect, alias="type" + ) + openIdConnectUrl: str + + +SecurityScheme = Union[APIKey, HTTPBase, OAuth2, OpenIdConnect, HTTPBearer] + + +class Components(BaseModelWithConfig): + schemas: Optional[Dict[str, Union[Schema, Reference]]] = None + responses: Optional[Dict[str, Union[Response, Reference]]] = None + parameters: Optional[Dict[str, Union[Parameter, Reference]]] = None + examples: Optional[Dict[str, Union[Example, Reference]]] = None + requestBodies: Optional[Dict[str, Union[RequestBody, Reference]]] = None + headers: Optional[Dict[str, Union[Header, Reference]]] = None + securitySchemes: Optional[Dict[str, Union[SecurityScheme, Reference]]] = None + links: Optional[Dict[str, Union[Link, Reference]]] = None + # Using Any for Specification Extensions + callbacks: Optional[Dict[str, Union[Dict[str, PathItem], Reference, Any]]] = None + pathItems: Optional[Dict[str, Union[PathItem, Reference]]] = None + + +class Tag(BaseModelWithConfig): + name: str + description: Optional[str] = None + externalDocs: Optional[ExternalDocumentation] = None + + +class OpenAPI(BaseModelWithConfig): + openapi: str + info: Info + jsonSchemaDialect: Optional[str] = None + servers: Optional[List[Server]] = None + # Using Any for Specification Extensions + paths: Optional[Dict[str, Union[PathItem, Any]]] = None + webhooks: Optional[Dict[str, Union[PathItem, Reference]]] = None + components: Optional[Components] = None + security: Optional[List[Dict[str, List[str]]]] = None + tags: Optional[List[Tag]] = None + externalDocs: Optional[ExternalDocumentation] = None + + +_model_rebuild(Schema) +_model_rebuild(Operation) +_model_rebuild(Encoding) diff --git a/backend/.venv/Lib/site-packages/fastapi/openapi/utils.py b/backend/.venv/Lib/site-packages/fastapi/openapi/utils.py new file mode 100644 index 0000000..947eca9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/openapi/utils.py @@ -0,0 +1,548 @@ +import http.client +import inspect +import warnings +from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, Type, Union, cast + +from fastapi import routing +from fastapi._compat import ( + GenerateJsonSchema, + JsonSchemaValue, + ModelField, + Undefined, + get_compat_model_name_map, + get_definitions, + get_schema_from_model_field, + lenient_issubclass, +) +from fastapi.datastructures import DefaultPlaceholder +from fastapi.dependencies.models import Dependant +from fastapi.dependencies.utils import ( + _get_flat_fields_from_params, + get_flat_dependant, + get_flat_params, +) +from fastapi.encoders import jsonable_encoder +from fastapi.openapi.constants import METHODS_WITH_BODY, REF_PREFIX, REF_TEMPLATE +from fastapi.openapi.models import OpenAPI +from fastapi.params import Body, ParamTypes +from fastapi.responses import Response +from fastapi.types import ModelNameMap +from fastapi.utils import ( + deep_dict_update, + generate_operation_id_for_path, + is_body_allowed_for_status_code, +) +from starlette.responses import JSONResponse +from starlette.routing import BaseRoute +from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY +from typing_extensions import Literal + +validation_error_definition = { + "title": "ValidationError", + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + "required": ["loc", "msg", "type"], +} + +validation_error_response_definition = { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": REF_PREFIX + "ValidationError"}, + } + }, +} + +status_code_ranges: Dict[str, str] = { + "1XX": "Information", + "2XX": "Success", + "3XX": "Redirection", + "4XX": "Client Error", + "5XX": "Server Error", + "DEFAULT": "Default Response", +} + + +def get_openapi_security_definitions( + flat_dependant: Dependant, +) -> Tuple[Dict[str, Any], List[Dict[str, Any]]]: + security_definitions = {} + operation_security = [] + for security_requirement in flat_dependant.security_requirements: + security_definition = jsonable_encoder( + security_requirement.security_scheme.model, + by_alias=True, + exclude_none=True, + ) + security_name = security_requirement.security_scheme.scheme_name + security_definitions[security_name] = security_definition + operation_security.append({security_name: security_requirement.scopes}) + return security_definitions, operation_security + + +def _get_openapi_operation_parameters( + *, + dependant: Dependant, + schema_generator: GenerateJsonSchema, + model_name_map: ModelNameMap, + field_mapping: Dict[ + Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue + ], + separate_input_output_schemas: bool = True, +) -> List[Dict[str, Any]]: + parameters = [] + flat_dependant = get_flat_dependant(dependant, skip_repeats=True) + path_params = _get_flat_fields_from_params(flat_dependant.path_params) + query_params = _get_flat_fields_from_params(flat_dependant.query_params) + header_params = _get_flat_fields_from_params(flat_dependant.header_params) + cookie_params = _get_flat_fields_from_params(flat_dependant.cookie_params) + parameter_groups = [ + (ParamTypes.path, path_params), + (ParamTypes.query, query_params), + (ParamTypes.header, header_params), + (ParamTypes.cookie, cookie_params), + ] + for param_type, param_group in parameter_groups: + for param in param_group: + field_info = param.field_info + # field_info = cast(Param, field_info) + if not getattr(field_info, "include_in_schema", True): + continue + param_schema = get_schema_from_model_field( + field=param, + schema_generator=schema_generator, + model_name_map=model_name_map, + field_mapping=field_mapping, + separate_input_output_schemas=separate_input_output_schemas, + ) + parameter = { + "name": param.alias, + "in": param_type.value, + "required": param.required, + "schema": param_schema, + } + if field_info.description: + parameter["description"] = field_info.description + openapi_examples = getattr(field_info, "openapi_examples", None) + example = getattr(field_info, "example", None) + if openapi_examples: + parameter["examples"] = jsonable_encoder(openapi_examples) + elif example != Undefined: + parameter["example"] = jsonable_encoder(example) + if getattr(field_info, "deprecated", None): + parameter["deprecated"] = True + parameters.append(parameter) + return parameters + + +def get_openapi_operation_request_body( + *, + body_field: Optional[ModelField], + schema_generator: GenerateJsonSchema, + model_name_map: ModelNameMap, + field_mapping: Dict[ + Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue + ], + separate_input_output_schemas: bool = True, +) -> Optional[Dict[str, Any]]: + if not body_field: + return None + assert isinstance(body_field, ModelField) + body_schema = get_schema_from_model_field( + field=body_field, + schema_generator=schema_generator, + model_name_map=model_name_map, + field_mapping=field_mapping, + separate_input_output_schemas=separate_input_output_schemas, + ) + field_info = cast(Body, body_field.field_info) + request_media_type = field_info.media_type + required = body_field.required + request_body_oai: Dict[str, Any] = {} + if required: + request_body_oai["required"] = required + request_media_content: Dict[str, Any] = {"schema": body_schema} + if field_info.openapi_examples: + request_media_content["examples"] = jsonable_encoder( + field_info.openapi_examples + ) + elif field_info.example != Undefined: + request_media_content["example"] = jsonable_encoder(field_info.example) + request_body_oai["content"] = {request_media_type: request_media_content} + return request_body_oai + + +def generate_operation_id( + *, route: routing.APIRoute, method: str +) -> str: # pragma: nocover + warnings.warn( + "fastapi.openapi.utils.generate_operation_id() was deprecated, " + "it is not used internally, and will be removed soon", + DeprecationWarning, + stacklevel=2, + ) + if route.operation_id: + return route.operation_id + path: str = route.path_format + return generate_operation_id_for_path(name=route.name, path=path, method=method) + + +def generate_operation_summary(*, route: routing.APIRoute, method: str) -> str: + if route.summary: + return route.summary + return route.name.replace("_", " ").title() + + +def get_openapi_operation_metadata( + *, route: routing.APIRoute, method: str, operation_ids: Set[str] +) -> Dict[str, Any]: + operation: Dict[str, Any] = {} + if route.tags: + operation["tags"] = route.tags + operation["summary"] = generate_operation_summary(route=route, method=method) + if route.description: + operation["description"] = route.description + operation_id = route.operation_id or route.unique_id + if operation_id in operation_ids: + message = ( + f"Duplicate Operation ID {operation_id} for function " + + f"{route.endpoint.__name__}" + ) + file_name = getattr(route.endpoint, "__globals__", {}).get("__file__") + if file_name: + message += f" at {file_name}" + warnings.warn(message, stacklevel=1) + operation_ids.add(operation_id) + operation["operationId"] = operation_id + if route.deprecated: + operation["deprecated"] = route.deprecated + return operation + + +def get_openapi_path( + *, + route: routing.APIRoute, + operation_ids: Set[str], + schema_generator: GenerateJsonSchema, + model_name_map: ModelNameMap, + field_mapping: Dict[ + Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue + ], + separate_input_output_schemas: bool = True, +) -> Tuple[Dict[str, Any], Dict[str, Any], Dict[str, Any]]: + path = {} + security_schemes: Dict[str, Any] = {} + definitions: Dict[str, Any] = {} + assert route.methods is not None, "Methods must be a list" + if isinstance(route.response_class, DefaultPlaceholder): + current_response_class: Type[Response] = route.response_class.value + else: + current_response_class = route.response_class + assert current_response_class, "A response class is needed to generate OpenAPI" + route_response_media_type: Optional[str] = current_response_class.media_type + if route.include_in_schema: + for method in route.methods: + operation = get_openapi_operation_metadata( + route=route, method=method, operation_ids=operation_ids + ) + parameters: List[Dict[str, Any]] = [] + flat_dependant = get_flat_dependant(route.dependant, skip_repeats=True) + security_definitions, operation_security = get_openapi_security_definitions( + flat_dependant=flat_dependant + ) + if operation_security: + operation.setdefault("security", []).extend(operation_security) + if security_definitions: + security_schemes.update(security_definitions) + operation_parameters = _get_openapi_operation_parameters( + dependant=route.dependant, + schema_generator=schema_generator, + model_name_map=model_name_map, + field_mapping=field_mapping, + separate_input_output_schemas=separate_input_output_schemas, + ) + parameters.extend(operation_parameters) + if parameters: + all_parameters = { + (param["in"], param["name"]): param for param in parameters + } + required_parameters = { + (param["in"], param["name"]): param + for param in parameters + if param.get("required") + } + # Make sure required definitions of the same parameter take precedence + # over non-required definitions + all_parameters.update(required_parameters) + operation["parameters"] = list(all_parameters.values()) + if method in METHODS_WITH_BODY: + request_body_oai = get_openapi_operation_request_body( + body_field=route.body_field, + schema_generator=schema_generator, + model_name_map=model_name_map, + field_mapping=field_mapping, + separate_input_output_schemas=separate_input_output_schemas, + ) + if request_body_oai: + operation["requestBody"] = request_body_oai + if route.callbacks: + callbacks = {} + for callback in route.callbacks: + if isinstance(callback, routing.APIRoute): + ( + cb_path, + cb_security_schemes, + cb_definitions, + ) = get_openapi_path( + route=callback, + operation_ids=operation_ids, + schema_generator=schema_generator, + model_name_map=model_name_map, + field_mapping=field_mapping, + separate_input_output_schemas=separate_input_output_schemas, + ) + callbacks[callback.name] = {callback.path: cb_path} + operation["callbacks"] = callbacks + if route.status_code is not None: + status_code = str(route.status_code) + else: + # It would probably make more sense for all response classes to have an + # explicit default status_code, and to extract it from them, instead of + # doing this inspection tricks, that would probably be in the future + # TODO: probably make status_code a default class attribute for all + # responses in Starlette + response_signature = inspect.signature(current_response_class.__init__) + status_code_param = response_signature.parameters.get("status_code") + if status_code_param is not None: + if isinstance(status_code_param.default, int): + status_code = str(status_code_param.default) + operation.setdefault("responses", {}).setdefault(status_code, {})[ + "description" + ] = route.response_description + if route_response_media_type and is_body_allowed_for_status_code( + route.status_code + ): + response_schema = {"type": "string"} + if lenient_issubclass(current_response_class, JSONResponse): + if route.response_field: + response_schema = get_schema_from_model_field( + field=route.response_field, + schema_generator=schema_generator, + model_name_map=model_name_map, + field_mapping=field_mapping, + separate_input_output_schemas=separate_input_output_schemas, + ) + else: + response_schema = {} + operation.setdefault("responses", {}).setdefault( + status_code, {} + ).setdefault("content", {}).setdefault(route_response_media_type, {})[ + "schema" + ] = response_schema + if route.responses: + operation_responses = operation.setdefault("responses", {}) + for ( + additional_status_code, + additional_response, + ) in route.responses.items(): + process_response = additional_response.copy() + process_response.pop("model", None) + status_code_key = str(additional_status_code).upper() + if status_code_key == "DEFAULT": + status_code_key = "default" + openapi_response = operation_responses.setdefault( + status_code_key, {} + ) + assert isinstance( + process_response, dict + ), "An additional response must be a dict" + field = route.response_fields.get(additional_status_code) + additional_field_schema: Optional[Dict[str, Any]] = None + if field: + additional_field_schema = get_schema_from_model_field( + field=field, + schema_generator=schema_generator, + model_name_map=model_name_map, + field_mapping=field_mapping, + separate_input_output_schemas=separate_input_output_schemas, + ) + media_type = route_response_media_type or "application/json" + additional_schema = ( + process_response.setdefault("content", {}) + .setdefault(media_type, {}) + .setdefault("schema", {}) + ) + deep_dict_update(additional_schema, additional_field_schema) + status_text: Optional[str] = status_code_ranges.get( + str(additional_status_code).upper() + ) or http.client.responses.get(int(additional_status_code)) + description = ( + process_response.get("description") + or openapi_response.get("description") + or status_text + or "Additional Response" + ) + deep_dict_update(openapi_response, process_response) + openapi_response["description"] = description + http422 = str(HTTP_422_UNPROCESSABLE_ENTITY) + all_route_params = get_flat_params(route.dependant) + if (all_route_params or route.body_field) and not any( + status in operation["responses"] + for status in [http422, "4XX", "default"] + ): + operation["responses"][http422] = { + "description": "Validation Error", + "content": { + "application/json": { + "schema": {"$ref": REF_PREFIX + "HTTPValidationError"} + } + }, + } + if "ValidationError" not in definitions: + definitions.update( + { + "ValidationError": validation_error_definition, + "HTTPValidationError": validation_error_response_definition, + } + ) + if route.openapi_extra: + deep_dict_update(operation, route.openapi_extra) + path[method.lower()] = operation + return path, security_schemes, definitions + + +def get_fields_from_routes( + routes: Sequence[BaseRoute], +) -> List[ModelField]: + body_fields_from_routes: List[ModelField] = [] + responses_from_routes: List[ModelField] = [] + request_fields_from_routes: List[ModelField] = [] + callback_flat_models: List[ModelField] = [] + for route in routes: + if getattr(route, "include_in_schema", None) and isinstance( + route, routing.APIRoute + ): + if route.body_field: + assert isinstance( + route.body_field, ModelField + ), "A request body must be a Pydantic Field" + body_fields_from_routes.append(route.body_field) + if route.response_field: + responses_from_routes.append(route.response_field) + if route.response_fields: + responses_from_routes.extend(route.response_fields.values()) + if route.callbacks: + callback_flat_models.extend(get_fields_from_routes(route.callbacks)) + params = get_flat_params(route.dependant) + request_fields_from_routes.extend(params) + + flat_models = callback_flat_models + list( + body_fields_from_routes + responses_from_routes + request_fields_from_routes + ) + return flat_models + + +def get_openapi( + *, + title: str, + version: str, + openapi_version: str = "3.1.0", + summary: Optional[str] = None, + description: Optional[str] = None, + routes: Sequence[BaseRoute], + webhooks: Optional[Sequence[BaseRoute]] = None, + tags: Optional[List[Dict[str, Any]]] = None, + servers: Optional[List[Dict[str, Union[str, Any]]]] = None, + terms_of_service: Optional[str] = None, + contact: Optional[Dict[str, Union[str, Any]]] = None, + license_info: Optional[Dict[str, Union[str, Any]]] = None, + separate_input_output_schemas: bool = True, +) -> Dict[str, Any]: + info: Dict[str, Any] = {"title": title, "version": version} + if summary: + info["summary"] = summary + if description: + info["description"] = description + if terms_of_service: + info["termsOfService"] = terms_of_service + if contact: + info["contact"] = contact + if license_info: + info["license"] = license_info + output: Dict[str, Any] = {"openapi": openapi_version, "info": info} + if servers: + output["servers"] = servers + components: Dict[str, Dict[str, Any]] = {} + paths: Dict[str, Dict[str, Any]] = {} + webhook_paths: Dict[str, Dict[str, Any]] = {} + operation_ids: Set[str] = set() + all_fields = get_fields_from_routes(list(routes or []) + list(webhooks or [])) + model_name_map = get_compat_model_name_map(all_fields) + schema_generator = GenerateJsonSchema(ref_template=REF_TEMPLATE) + field_mapping, definitions = get_definitions( + fields=all_fields, + schema_generator=schema_generator, + model_name_map=model_name_map, + separate_input_output_schemas=separate_input_output_schemas, + ) + for route in routes or []: + if isinstance(route, routing.APIRoute): + result = get_openapi_path( + route=route, + operation_ids=operation_ids, + schema_generator=schema_generator, + model_name_map=model_name_map, + field_mapping=field_mapping, + separate_input_output_schemas=separate_input_output_schemas, + ) + if result: + path, security_schemes, path_definitions = result + if path: + paths.setdefault(route.path_format, {}).update(path) + if security_schemes: + components.setdefault("securitySchemes", {}).update( + security_schemes + ) + if path_definitions: + definitions.update(path_definitions) + for webhook in webhooks or []: + if isinstance(webhook, routing.APIRoute): + result = get_openapi_path( + route=webhook, + operation_ids=operation_ids, + schema_generator=schema_generator, + model_name_map=model_name_map, + field_mapping=field_mapping, + separate_input_output_schemas=separate_input_output_schemas, + ) + if result: + path, security_schemes, path_definitions = result + if path: + webhook_paths.setdefault(webhook.path_format, {}).update(path) + if security_schemes: + components.setdefault("securitySchemes", {}).update( + security_schemes + ) + if path_definitions: + definitions.update(path_definitions) + if definitions: + components["schemas"] = {k: definitions[k] for k in sorted(definitions)} + if components: + output["components"] = components + output["paths"] = paths + if webhook_paths: + output["webhooks"] = webhook_paths + if tags: + output["tags"] = tags + return jsonable_encoder(OpenAPI(**output), by_alias=True, exclude_none=True) # type: ignore diff --git a/backend/.venv/Lib/site-packages/fastapi/param_functions.py b/backend/.venv/Lib/site-packages/fastapi/param_functions.py new file mode 100644 index 0000000..b362162 --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/param_functions.py @@ -0,0 +1,2360 @@ +from typing import Any, Callable, Dict, List, Optional, Sequence, Union + +from fastapi import params +from fastapi._compat import Undefined +from fastapi.openapi.models import Example +from typing_extensions import Annotated, Doc, deprecated + +_Unset: Any = Undefined + + +def Path( # noqa: N802 + default: Annotated[ + Any, + Doc( + """ + Default value if the parameter field is not set. + + This doesn't affect `Path` parameters as the value is always required. + The parameter is available only for compatibility. + """ + ), + ] = ..., + *, + default_factory: Annotated[ + Union[Callable[[], Any], None], + Doc( + """ + A callable to generate the default value. + + This doesn't affect `Path` parameters as the value is always required. + The parameter is available only for compatibility. + """ + ), + ] = _Unset, + alias: Annotated[ + Optional[str], + Doc( + """ + An alternative name for the parameter field. + + This will be used to extract the data and for the generated OpenAPI. + It is particularly useful when you can't use the name you want because it + is a Python reserved keyword or similar. + """ + ), + ] = None, + alias_priority: Annotated[ + Union[int, None], + Doc( + """ + Priority of the alias. This affects whether an alias generator is used. + """ + ), + ] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Annotated[ + Union[str, None], + Doc( + """ + 'Whitelist' validation step. The parameter field will be the single one + allowed by the alias or set of aliases defined. + """ + ), + ] = None, + serialization_alias: Annotated[ + Union[str, None], + Doc( + """ + 'Blacklist' validation step. The vanilla parameter field will be the + single one of the alias' or set of aliases' fields and all the other + fields will be ignored at serialization time. + """ + ), + ] = None, + title: Annotated[ + Optional[str], + Doc( + """ + Human-readable title. + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + Human-readable description. + """ + ), + ] = None, + gt: Annotated[ + Optional[float], + Doc( + """ + Greater than. If set, value must be greater than this. Only applicable to + numbers. + """ + ), + ] = None, + ge: Annotated[ + Optional[float], + Doc( + """ + Greater than or equal. If set, value must be greater than or equal to + this. Only applicable to numbers. + """ + ), + ] = None, + lt: Annotated[ + Optional[float], + Doc( + """ + Less than. If set, value must be less than this. Only applicable to numbers. + """ + ), + ] = None, + le: Annotated[ + Optional[float], + Doc( + """ + Less than or equal. If set, value must be less than or equal to this. + Only applicable to numbers. + """ + ), + ] = None, + min_length: Annotated[ + Optional[int], + Doc( + """ + Minimum length for strings. + """ + ), + ] = None, + max_length: Annotated[ + Optional[int], + Doc( + """ + Maximum length for strings. + """ + ), + ] = None, + pattern: Annotated[ + Optional[str], + Doc( + """ + RegEx pattern for strings. + """ + ), + ] = None, + regex: Annotated[ + Optional[str], + Doc( + """ + RegEx pattern for strings. + """ + ), + deprecated( + "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." + ), + ] = None, + discriminator: Annotated[ + Union[str, None], + Doc( + """ + Parameter field name for discriminating the type in a tagged union. + """ + ), + ] = None, + strict: Annotated[ + Union[bool, None], + Doc( + """ + If `True`, strict validation is applied to the field. + """ + ), + ] = _Unset, + multiple_of: Annotated[ + Union[float, None], + Doc( + """ + Value must be a multiple of this. Only applicable to numbers. + """ + ), + ] = _Unset, + allow_inf_nan: Annotated[ + Union[bool, None], + Doc( + """ + Allow `inf`, `-inf`, `nan`. Only applicable to numbers. + """ + ), + ] = _Unset, + max_digits: Annotated[ + Union[int, None], + Doc( + """ + Maximum number of allow digits for strings. + """ + ), + ] = _Unset, + decimal_places: Annotated[ + Union[int, None], + Doc( + """ + Maximum number of decimal places allowed for numbers. + """ + ), + ] = _Unset, + examples: Annotated[ + Optional[List[Any]], + Doc( + """ + Example values for this field. + """ + ), + ] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = _Unset, + openapi_examples: Annotated[ + Optional[Dict[str, Example]], + Doc( + """ + OpenAPI-specific examples. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Swagger UI (that provides the `/docs` interface) has better support for the + OpenAPI-specific examples than the JSON Schema `examples`, that's the main + use case for this. + + Read more about it in the + [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/#using-the-openapi_examples-parameter). + """ + ), + ] = None, + deprecated: Annotated[ + Union[deprecated, str, bool, None], + Doc( + """ + Mark this parameter field as deprecated. + + It will affect the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + include_in_schema: Annotated[ + bool, + Doc( + """ + To include (or not) this parameter field in the generated OpenAPI. + You probably don't need it, but it's available. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = True, + json_schema_extra: Annotated[ + Union[Dict[str, Any], None], + Doc( + """ + Any additional JSON schema data. + """ + ), + ] = None, + **extra: Annotated[ + Any, + Doc( + """ + Include extra fields used by the JSON Schema. + """ + ), + deprecated( + """ + The `extra` kwargs is deprecated. Use `json_schema_extra` instead. + """ + ), + ], +) -> Any: + """ + Declare a path parameter for a *path operation*. + + Read more about it in the + [FastAPI docs for Path Parameters and Numeric Validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/). + + ```python + from typing import Annotated + + from fastapi import FastAPI, Path + + app = FastAPI() + + + @app.get("/items/{item_id}") + async def read_items( + item_id: Annotated[int, Path(title="The ID of the item to get")], + ): + return {"item_id": item_id} + ``` + """ + return params.Path( + default=default, + default_factory=default_factory, + alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + pattern=pattern, + regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, + example=example, + examples=examples, + openapi_examples=openapi_examples, + deprecated=deprecated, + include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, + **extra, + ) + + +def Query( # noqa: N802 + default: Annotated[ + Any, + Doc( + """ + Default value if the parameter field is not set. + """ + ), + ] = Undefined, + *, + default_factory: Annotated[ + Union[Callable[[], Any], None], + Doc( + """ + A callable to generate the default value. + + This doesn't affect `Path` parameters as the value is always required. + The parameter is available only for compatibility. + """ + ), + ] = _Unset, + alias: Annotated[ + Optional[str], + Doc( + """ + An alternative name for the parameter field. + + This will be used to extract the data and for the generated OpenAPI. + It is particularly useful when you can't use the name you want because it + is a Python reserved keyword or similar. + """ + ), + ] = None, + alias_priority: Annotated[ + Union[int, None], + Doc( + """ + Priority of the alias. This affects whether an alias generator is used. + """ + ), + ] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Annotated[ + Union[str, None], + Doc( + """ + 'Whitelist' validation step. The parameter field will be the single one + allowed by the alias or set of aliases defined. + """ + ), + ] = None, + serialization_alias: Annotated[ + Union[str, None], + Doc( + """ + 'Blacklist' validation step. The vanilla parameter field will be the + single one of the alias' or set of aliases' fields and all the other + fields will be ignored at serialization time. + """ + ), + ] = None, + title: Annotated[ + Optional[str], + Doc( + """ + Human-readable title. + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + Human-readable description. + """ + ), + ] = None, + gt: Annotated[ + Optional[float], + Doc( + """ + Greater than. If set, value must be greater than this. Only applicable to + numbers. + """ + ), + ] = None, + ge: Annotated[ + Optional[float], + Doc( + """ + Greater than or equal. If set, value must be greater than or equal to + this. Only applicable to numbers. + """ + ), + ] = None, + lt: Annotated[ + Optional[float], + Doc( + """ + Less than. If set, value must be less than this. Only applicable to numbers. + """ + ), + ] = None, + le: Annotated[ + Optional[float], + Doc( + """ + Less than or equal. If set, value must be less than or equal to this. + Only applicable to numbers. + """ + ), + ] = None, + min_length: Annotated[ + Optional[int], + Doc( + """ + Minimum length for strings. + """ + ), + ] = None, + max_length: Annotated[ + Optional[int], + Doc( + """ + Maximum length for strings. + """ + ), + ] = None, + pattern: Annotated[ + Optional[str], + Doc( + """ + RegEx pattern for strings. + """ + ), + ] = None, + regex: Annotated[ + Optional[str], + Doc( + """ + RegEx pattern for strings. + """ + ), + deprecated( + "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." + ), + ] = None, + discriminator: Annotated[ + Union[str, None], + Doc( + """ + Parameter field name for discriminating the type in a tagged union. + """ + ), + ] = None, + strict: Annotated[ + Union[bool, None], + Doc( + """ + If `True`, strict validation is applied to the field. + """ + ), + ] = _Unset, + multiple_of: Annotated[ + Union[float, None], + Doc( + """ + Value must be a multiple of this. Only applicable to numbers. + """ + ), + ] = _Unset, + allow_inf_nan: Annotated[ + Union[bool, None], + Doc( + """ + Allow `inf`, `-inf`, `nan`. Only applicable to numbers. + """ + ), + ] = _Unset, + max_digits: Annotated[ + Union[int, None], + Doc( + """ + Maximum number of allow digits for strings. + """ + ), + ] = _Unset, + decimal_places: Annotated[ + Union[int, None], + Doc( + """ + Maximum number of decimal places allowed for numbers. + """ + ), + ] = _Unset, + examples: Annotated[ + Optional[List[Any]], + Doc( + """ + Example values for this field. + """ + ), + ] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = _Unset, + openapi_examples: Annotated[ + Optional[Dict[str, Example]], + Doc( + """ + OpenAPI-specific examples. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Swagger UI (that provides the `/docs` interface) has better support for the + OpenAPI-specific examples than the JSON Schema `examples`, that's the main + use case for this. + + Read more about it in the + [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/#using-the-openapi_examples-parameter). + """ + ), + ] = None, + deprecated: Annotated[ + Union[deprecated, str, bool, None], + Doc( + """ + Mark this parameter field as deprecated. + + It will affect the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + include_in_schema: Annotated[ + bool, + Doc( + """ + To include (or not) this parameter field in the generated OpenAPI. + You probably don't need it, but it's available. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = True, + json_schema_extra: Annotated[ + Union[Dict[str, Any], None], + Doc( + """ + Any additional JSON schema data. + """ + ), + ] = None, + **extra: Annotated[ + Any, + Doc( + """ + Include extra fields used by the JSON Schema. + """ + ), + deprecated( + """ + The `extra` kwargs is deprecated. Use `json_schema_extra` instead. + """ + ), + ], +) -> Any: + return params.Query( + default=default, + default_factory=default_factory, + alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + pattern=pattern, + regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, + example=example, + examples=examples, + openapi_examples=openapi_examples, + deprecated=deprecated, + include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, + **extra, + ) + + +def Header( # noqa: N802 + default: Annotated[ + Any, + Doc( + """ + Default value if the parameter field is not set. + """ + ), + ] = Undefined, + *, + default_factory: Annotated[ + Union[Callable[[], Any], None], + Doc( + """ + A callable to generate the default value. + + This doesn't affect `Path` parameters as the value is always required. + The parameter is available only for compatibility. + """ + ), + ] = _Unset, + alias: Annotated[ + Optional[str], + Doc( + """ + An alternative name for the parameter field. + + This will be used to extract the data and for the generated OpenAPI. + It is particularly useful when you can't use the name you want because it + is a Python reserved keyword or similar. + """ + ), + ] = None, + alias_priority: Annotated[ + Union[int, None], + Doc( + """ + Priority of the alias. This affects whether an alias generator is used. + """ + ), + ] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Annotated[ + Union[str, None], + Doc( + """ + 'Whitelist' validation step. The parameter field will be the single one + allowed by the alias or set of aliases defined. + """ + ), + ] = None, + serialization_alias: Annotated[ + Union[str, None], + Doc( + """ + 'Blacklist' validation step. The vanilla parameter field will be the + single one of the alias' or set of aliases' fields and all the other + fields will be ignored at serialization time. + """ + ), + ] = None, + convert_underscores: Annotated[ + bool, + Doc( + """ + Automatically convert underscores to hyphens in the parameter field name. + + Read more about it in the + [FastAPI docs for Header Parameters](https://fastapi.tiangolo.com/tutorial/header-params/#automatic-conversion) + """ + ), + ] = True, + title: Annotated[ + Optional[str], + Doc( + """ + Human-readable title. + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + Human-readable description. + """ + ), + ] = None, + gt: Annotated[ + Optional[float], + Doc( + """ + Greater than. If set, value must be greater than this. Only applicable to + numbers. + """ + ), + ] = None, + ge: Annotated[ + Optional[float], + Doc( + """ + Greater than or equal. If set, value must be greater than or equal to + this. Only applicable to numbers. + """ + ), + ] = None, + lt: Annotated[ + Optional[float], + Doc( + """ + Less than. If set, value must be less than this. Only applicable to numbers. + """ + ), + ] = None, + le: Annotated[ + Optional[float], + Doc( + """ + Less than or equal. If set, value must be less than or equal to this. + Only applicable to numbers. + """ + ), + ] = None, + min_length: Annotated[ + Optional[int], + Doc( + """ + Minimum length for strings. + """ + ), + ] = None, + max_length: Annotated[ + Optional[int], + Doc( + """ + Maximum length for strings. + """ + ), + ] = None, + pattern: Annotated[ + Optional[str], + Doc( + """ + RegEx pattern for strings. + """ + ), + ] = None, + regex: Annotated[ + Optional[str], + Doc( + """ + RegEx pattern for strings. + """ + ), + deprecated( + "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." + ), + ] = None, + discriminator: Annotated[ + Union[str, None], + Doc( + """ + Parameter field name for discriminating the type in a tagged union. + """ + ), + ] = None, + strict: Annotated[ + Union[bool, None], + Doc( + """ + If `True`, strict validation is applied to the field. + """ + ), + ] = _Unset, + multiple_of: Annotated[ + Union[float, None], + Doc( + """ + Value must be a multiple of this. Only applicable to numbers. + """ + ), + ] = _Unset, + allow_inf_nan: Annotated[ + Union[bool, None], + Doc( + """ + Allow `inf`, `-inf`, `nan`. Only applicable to numbers. + """ + ), + ] = _Unset, + max_digits: Annotated[ + Union[int, None], + Doc( + """ + Maximum number of allow digits for strings. + """ + ), + ] = _Unset, + decimal_places: Annotated[ + Union[int, None], + Doc( + """ + Maximum number of decimal places allowed for numbers. + """ + ), + ] = _Unset, + examples: Annotated[ + Optional[List[Any]], + Doc( + """ + Example values for this field. + """ + ), + ] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = _Unset, + openapi_examples: Annotated[ + Optional[Dict[str, Example]], + Doc( + """ + OpenAPI-specific examples. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Swagger UI (that provides the `/docs` interface) has better support for the + OpenAPI-specific examples than the JSON Schema `examples`, that's the main + use case for this. + + Read more about it in the + [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/#using-the-openapi_examples-parameter). + """ + ), + ] = None, + deprecated: Annotated[ + Union[deprecated, str, bool, None], + Doc( + """ + Mark this parameter field as deprecated. + + It will affect the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + include_in_schema: Annotated[ + bool, + Doc( + """ + To include (or not) this parameter field in the generated OpenAPI. + You probably don't need it, but it's available. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = True, + json_schema_extra: Annotated[ + Union[Dict[str, Any], None], + Doc( + """ + Any additional JSON schema data. + """ + ), + ] = None, + **extra: Annotated[ + Any, + Doc( + """ + Include extra fields used by the JSON Schema. + """ + ), + deprecated( + """ + The `extra` kwargs is deprecated. Use `json_schema_extra` instead. + """ + ), + ], +) -> Any: + return params.Header( + default=default, + default_factory=default_factory, + alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, + convert_underscores=convert_underscores, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + pattern=pattern, + regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, + example=example, + examples=examples, + openapi_examples=openapi_examples, + deprecated=deprecated, + include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, + **extra, + ) + + +def Cookie( # noqa: N802 + default: Annotated[ + Any, + Doc( + """ + Default value if the parameter field is not set. + """ + ), + ] = Undefined, + *, + default_factory: Annotated[ + Union[Callable[[], Any], None], + Doc( + """ + A callable to generate the default value. + + This doesn't affect `Path` parameters as the value is always required. + The parameter is available only for compatibility. + """ + ), + ] = _Unset, + alias: Annotated[ + Optional[str], + Doc( + """ + An alternative name for the parameter field. + + This will be used to extract the data and for the generated OpenAPI. + It is particularly useful when you can't use the name you want because it + is a Python reserved keyword or similar. + """ + ), + ] = None, + alias_priority: Annotated[ + Union[int, None], + Doc( + """ + Priority of the alias. This affects whether an alias generator is used. + """ + ), + ] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Annotated[ + Union[str, None], + Doc( + """ + 'Whitelist' validation step. The parameter field will be the single one + allowed by the alias or set of aliases defined. + """ + ), + ] = None, + serialization_alias: Annotated[ + Union[str, None], + Doc( + """ + 'Blacklist' validation step. The vanilla parameter field will be the + single one of the alias' or set of aliases' fields and all the other + fields will be ignored at serialization time. + """ + ), + ] = None, + title: Annotated[ + Optional[str], + Doc( + """ + Human-readable title. + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + Human-readable description. + """ + ), + ] = None, + gt: Annotated[ + Optional[float], + Doc( + """ + Greater than. If set, value must be greater than this. Only applicable to + numbers. + """ + ), + ] = None, + ge: Annotated[ + Optional[float], + Doc( + """ + Greater than or equal. If set, value must be greater than or equal to + this. Only applicable to numbers. + """ + ), + ] = None, + lt: Annotated[ + Optional[float], + Doc( + """ + Less than. If set, value must be less than this. Only applicable to numbers. + """ + ), + ] = None, + le: Annotated[ + Optional[float], + Doc( + """ + Less than or equal. If set, value must be less than or equal to this. + Only applicable to numbers. + """ + ), + ] = None, + min_length: Annotated[ + Optional[int], + Doc( + """ + Minimum length for strings. + """ + ), + ] = None, + max_length: Annotated[ + Optional[int], + Doc( + """ + Maximum length for strings. + """ + ), + ] = None, + pattern: Annotated[ + Optional[str], + Doc( + """ + RegEx pattern for strings. + """ + ), + ] = None, + regex: Annotated[ + Optional[str], + Doc( + """ + RegEx pattern for strings. + """ + ), + deprecated( + "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." + ), + ] = None, + discriminator: Annotated[ + Union[str, None], + Doc( + """ + Parameter field name for discriminating the type in a tagged union. + """ + ), + ] = None, + strict: Annotated[ + Union[bool, None], + Doc( + """ + If `True`, strict validation is applied to the field. + """ + ), + ] = _Unset, + multiple_of: Annotated[ + Union[float, None], + Doc( + """ + Value must be a multiple of this. Only applicable to numbers. + """ + ), + ] = _Unset, + allow_inf_nan: Annotated[ + Union[bool, None], + Doc( + """ + Allow `inf`, `-inf`, `nan`. Only applicable to numbers. + """ + ), + ] = _Unset, + max_digits: Annotated[ + Union[int, None], + Doc( + """ + Maximum number of allow digits for strings. + """ + ), + ] = _Unset, + decimal_places: Annotated[ + Union[int, None], + Doc( + """ + Maximum number of decimal places allowed for numbers. + """ + ), + ] = _Unset, + examples: Annotated[ + Optional[List[Any]], + Doc( + """ + Example values for this field. + """ + ), + ] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = _Unset, + openapi_examples: Annotated[ + Optional[Dict[str, Example]], + Doc( + """ + OpenAPI-specific examples. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Swagger UI (that provides the `/docs` interface) has better support for the + OpenAPI-specific examples than the JSON Schema `examples`, that's the main + use case for this. + + Read more about it in the + [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/#using-the-openapi_examples-parameter). + """ + ), + ] = None, + deprecated: Annotated[ + Union[deprecated, str, bool, None], + Doc( + """ + Mark this parameter field as deprecated. + + It will affect the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + include_in_schema: Annotated[ + bool, + Doc( + """ + To include (or not) this parameter field in the generated OpenAPI. + You probably don't need it, but it's available. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = True, + json_schema_extra: Annotated[ + Union[Dict[str, Any], None], + Doc( + """ + Any additional JSON schema data. + """ + ), + ] = None, + **extra: Annotated[ + Any, + Doc( + """ + Include extra fields used by the JSON Schema. + """ + ), + deprecated( + """ + The `extra` kwargs is deprecated. Use `json_schema_extra` instead. + """ + ), + ], +) -> Any: + return params.Cookie( + default=default, + default_factory=default_factory, + alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + pattern=pattern, + regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, + example=example, + examples=examples, + openapi_examples=openapi_examples, + deprecated=deprecated, + include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, + **extra, + ) + + +def Body( # noqa: N802 + default: Annotated[ + Any, + Doc( + """ + Default value if the parameter field is not set. + """ + ), + ] = Undefined, + *, + default_factory: Annotated[ + Union[Callable[[], Any], None], + Doc( + """ + A callable to generate the default value. + + This doesn't affect `Path` parameters as the value is always required. + The parameter is available only for compatibility. + """ + ), + ] = _Unset, + embed: Annotated[ + Union[bool, None], + Doc( + """ + When `embed` is `True`, the parameter will be expected in a JSON body as a + key instead of being the JSON body itself. + + This happens automatically when more than one `Body` parameter is declared. + + Read more about it in the + [FastAPI docs for Body - Multiple Parameters](https://fastapi.tiangolo.com/tutorial/body-multiple-params/#embed-a-single-body-parameter). + """ + ), + ] = None, + media_type: Annotated[ + str, + Doc( + """ + The media type of this parameter field. Changing it would affect the + generated OpenAPI, but currently it doesn't affect the parsing of the data. + """ + ), + ] = "application/json", + alias: Annotated[ + Optional[str], + Doc( + """ + An alternative name for the parameter field. + + This will be used to extract the data and for the generated OpenAPI. + It is particularly useful when you can't use the name you want because it + is a Python reserved keyword or similar. + """ + ), + ] = None, + alias_priority: Annotated[ + Union[int, None], + Doc( + """ + Priority of the alias. This affects whether an alias generator is used. + """ + ), + ] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Annotated[ + Union[str, None], + Doc( + """ + 'Whitelist' validation step. The parameter field will be the single one + allowed by the alias or set of aliases defined. + """ + ), + ] = None, + serialization_alias: Annotated[ + Union[str, None], + Doc( + """ + 'Blacklist' validation step. The vanilla parameter field will be the + single one of the alias' or set of aliases' fields and all the other + fields will be ignored at serialization time. + """ + ), + ] = None, + title: Annotated[ + Optional[str], + Doc( + """ + Human-readable title. + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + Human-readable description. + """ + ), + ] = None, + gt: Annotated[ + Optional[float], + Doc( + """ + Greater than. If set, value must be greater than this. Only applicable to + numbers. + """ + ), + ] = None, + ge: Annotated[ + Optional[float], + Doc( + """ + Greater than or equal. If set, value must be greater than or equal to + this. Only applicable to numbers. + """ + ), + ] = None, + lt: Annotated[ + Optional[float], + Doc( + """ + Less than. If set, value must be less than this. Only applicable to numbers. + """ + ), + ] = None, + le: Annotated[ + Optional[float], + Doc( + """ + Less than or equal. If set, value must be less than or equal to this. + Only applicable to numbers. + """ + ), + ] = None, + min_length: Annotated[ + Optional[int], + Doc( + """ + Minimum length for strings. + """ + ), + ] = None, + max_length: Annotated[ + Optional[int], + Doc( + """ + Maximum length for strings. + """ + ), + ] = None, + pattern: Annotated[ + Optional[str], + Doc( + """ + RegEx pattern for strings. + """ + ), + ] = None, + regex: Annotated[ + Optional[str], + Doc( + """ + RegEx pattern for strings. + """ + ), + deprecated( + "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." + ), + ] = None, + discriminator: Annotated[ + Union[str, None], + Doc( + """ + Parameter field name for discriminating the type in a tagged union. + """ + ), + ] = None, + strict: Annotated[ + Union[bool, None], + Doc( + """ + If `True`, strict validation is applied to the field. + """ + ), + ] = _Unset, + multiple_of: Annotated[ + Union[float, None], + Doc( + """ + Value must be a multiple of this. Only applicable to numbers. + """ + ), + ] = _Unset, + allow_inf_nan: Annotated[ + Union[bool, None], + Doc( + """ + Allow `inf`, `-inf`, `nan`. Only applicable to numbers. + """ + ), + ] = _Unset, + max_digits: Annotated[ + Union[int, None], + Doc( + """ + Maximum number of allow digits for strings. + """ + ), + ] = _Unset, + decimal_places: Annotated[ + Union[int, None], + Doc( + """ + Maximum number of decimal places allowed for numbers. + """ + ), + ] = _Unset, + examples: Annotated[ + Optional[List[Any]], + Doc( + """ + Example values for this field. + """ + ), + ] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = _Unset, + openapi_examples: Annotated[ + Optional[Dict[str, Example]], + Doc( + """ + OpenAPI-specific examples. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Swagger UI (that provides the `/docs` interface) has better support for the + OpenAPI-specific examples than the JSON Schema `examples`, that's the main + use case for this. + + Read more about it in the + [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/#using-the-openapi_examples-parameter). + """ + ), + ] = None, + deprecated: Annotated[ + Union[deprecated, str, bool, None], + Doc( + """ + Mark this parameter field as deprecated. + + It will affect the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + include_in_schema: Annotated[ + bool, + Doc( + """ + To include (or not) this parameter field in the generated OpenAPI. + You probably don't need it, but it's available. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = True, + json_schema_extra: Annotated[ + Union[Dict[str, Any], None], + Doc( + """ + Any additional JSON schema data. + """ + ), + ] = None, + **extra: Annotated[ + Any, + Doc( + """ + Include extra fields used by the JSON Schema. + """ + ), + deprecated( + """ + The `extra` kwargs is deprecated. Use `json_schema_extra` instead. + """ + ), + ], +) -> Any: + return params.Body( + default=default, + default_factory=default_factory, + embed=embed, + media_type=media_type, + alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + pattern=pattern, + regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, + example=example, + examples=examples, + openapi_examples=openapi_examples, + deprecated=deprecated, + include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, + **extra, + ) + + +def Form( # noqa: N802 + default: Annotated[ + Any, + Doc( + """ + Default value if the parameter field is not set. + """ + ), + ] = Undefined, + *, + default_factory: Annotated[ + Union[Callable[[], Any], None], + Doc( + """ + A callable to generate the default value. + + This doesn't affect `Path` parameters as the value is always required. + The parameter is available only for compatibility. + """ + ), + ] = _Unset, + media_type: Annotated[ + str, + Doc( + """ + The media type of this parameter field. Changing it would affect the + generated OpenAPI, but currently it doesn't affect the parsing of the data. + """ + ), + ] = "application/x-www-form-urlencoded", + alias: Annotated[ + Optional[str], + Doc( + """ + An alternative name for the parameter field. + + This will be used to extract the data and for the generated OpenAPI. + It is particularly useful when you can't use the name you want because it + is a Python reserved keyword or similar. + """ + ), + ] = None, + alias_priority: Annotated[ + Union[int, None], + Doc( + """ + Priority of the alias. This affects whether an alias generator is used. + """ + ), + ] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Annotated[ + Union[str, None], + Doc( + """ + 'Whitelist' validation step. The parameter field will be the single one + allowed by the alias or set of aliases defined. + """ + ), + ] = None, + serialization_alias: Annotated[ + Union[str, None], + Doc( + """ + 'Blacklist' validation step. The vanilla parameter field will be the + single one of the alias' or set of aliases' fields and all the other + fields will be ignored at serialization time. + """ + ), + ] = None, + title: Annotated[ + Optional[str], + Doc( + """ + Human-readable title. + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + Human-readable description. + """ + ), + ] = None, + gt: Annotated[ + Optional[float], + Doc( + """ + Greater than. If set, value must be greater than this. Only applicable to + numbers. + """ + ), + ] = None, + ge: Annotated[ + Optional[float], + Doc( + """ + Greater than or equal. If set, value must be greater than or equal to + this. Only applicable to numbers. + """ + ), + ] = None, + lt: Annotated[ + Optional[float], + Doc( + """ + Less than. If set, value must be less than this. Only applicable to numbers. + """ + ), + ] = None, + le: Annotated[ + Optional[float], + Doc( + """ + Less than or equal. If set, value must be less than or equal to this. + Only applicable to numbers. + """ + ), + ] = None, + min_length: Annotated[ + Optional[int], + Doc( + """ + Minimum length for strings. + """ + ), + ] = None, + max_length: Annotated[ + Optional[int], + Doc( + """ + Maximum length for strings. + """ + ), + ] = None, + pattern: Annotated[ + Optional[str], + Doc( + """ + RegEx pattern for strings. + """ + ), + ] = None, + regex: Annotated[ + Optional[str], + Doc( + """ + RegEx pattern for strings. + """ + ), + deprecated( + "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." + ), + ] = None, + discriminator: Annotated[ + Union[str, None], + Doc( + """ + Parameter field name for discriminating the type in a tagged union. + """ + ), + ] = None, + strict: Annotated[ + Union[bool, None], + Doc( + """ + If `True`, strict validation is applied to the field. + """ + ), + ] = _Unset, + multiple_of: Annotated[ + Union[float, None], + Doc( + """ + Value must be a multiple of this. Only applicable to numbers. + """ + ), + ] = _Unset, + allow_inf_nan: Annotated[ + Union[bool, None], + Doc( + """ + Allow `inf`, `-inf`, `nan`. Only applicable to numbers. + """ + ), + ] = _Unset, + max_digits: Annotated[ + Union[int, None], + Doc( + """ + Maximum number of allow digits for strings. + """ + ), + ] = _Unset, + decimal_places: Annotated[ + Union[int, None], + Doc( + """ + Maximum number of decimal places allowed for numbers. + """ + ), + ] = _Unset, + examples: Annotated[ + Optional[List[Any]], + Doc( + """ + Example values for this field. + """ + ), + ] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = _Unset, + openapi_examples: Annotated[ + Optional[Dict[str, Example]], + Doc( + """ + OpenAPI-specific examples. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Swagger UI (that provides the `/docs` interface) has better support for the + OpenAPI-specific examples than the JSON Schema `examples`, that's the main + use case for this. + + Read more about it in the + [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/#using-the-openapi_examples-parameter). + """ + ), + ] = None, + deprecated: Annotated[ + Union[deprecated, str, bool, None], + Doc( + """ + Mark this parameter field as deprecated. + + It will affect the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + include_in_schema: Annotated[ + bool, + Doc( + """ + To include (or not) this parameter field in the generated OpenAPI. + You probably don't need it, but it's available. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = True, + json_schema_extra: Annotated[ + Union[Dict[str, Any], None], + Doc( + """ + Any additional JSON schema data. + """ + ), + ] = None, + **extra: Annotated[ + Any, + Doc( + """ + Include extra fields used by the JSON Schema. + """ + ), + deprecated( + """ + The `extra` kwargs is deprecated. Use `json_schema_extra` instead. + """ + ), + ], +) -> Any: + return params.Form( + default=default, + default_factory=default_factory, + media_type=media_type, + alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + pattern=pattern, + regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, + example=example, + examples=examples, + openapi_examples=openapi_examples, + deprecated=deprecated, + include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, + **extra, + ) + + +def File( # noqa: N802 + default: Annotated[ + Any, + Doc( + """ + Default value if the parameter field is not set. + """ + ), + ] = Undefined, + *, + default_factory: Annotated[ + Union[Callable[[], Any], None], + Doc( + """ + A callable to generate the default value. + + This doesn't affect `Path` parameters as the value is always required. + The parameter is available only for compatibility. + """ + ), + ] = _Unset, + media_type: Annotated[ + str, + Doc( + """ + The media type of this parameter field. Changing it would affect the + generated OpenAPI, but currently it doesn't affect the parsing of the data. + """ + ), + ] = "multipart/form-data", + alias: Annotated[ + Optional[str], + Doc( + """ + An alternative name for the parameter field. + + This will be used to extract the data and for the generated OpenAPI. + It is particularly useful when you can't use the name you want because it + is a Python reserved keyword or similar. + """ + ), + ] = None, + alias_priority: Annotated[ + Union[int, None], + Doc( + """ + Priority of the alias. This affects whether an alias generator is used. + """ + ), + ] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Annotated[ + Union[str, None], + Doc( + """ + 'Whitelist' validation step. The parameter field will be the single one + allowed by the alias or set of aliases defined. + """ + ), + ] = None, + serialization_alias: Annotated[ + Union[str, None], + Doc( + """ + 'Blacklist' validation step. The vanilla parameter field will be the + single one of the alias' or set of aliases' fields and all the other + fields will be ignored at serialization time. + """ + ), + ] = None, + title: Annotated[ + Optional[str], + Doc( + """ + Human-readable title. + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + Human-readable description. + """ + ), + ] = None, + gt: Annotated[ + Optional[float], + Doc( + """ + Greater than. If set, value must be greater than this. Only applicable to + numbers. + """ + ), + ] = None, + ge: Annotated[ + Optional[float], + Doc( + """ + Greater than or equal. If set, value must be greater than or equal to + this. Only applicable to numbers. + """ + ), + ] = None, + lt: Annotated[ + Optional[float], + Doc( + """ + Less than. If set, value must be less than this. Only applicable to numbers. + """ + ), + ] = None, + le: Annotated[ + Optional[float], + Doc( + """ + Less than or equal. If set, value must be less than or equal to this. + Only applicable to numbers. + """ + ), + ] = None, + min_length: Annotated[ + Optional[int], + Doc( + """ + Minimum length for strings. + """ + ), + ] = None, + max_length: Annotated[ + Optional[int], + Doc( + """ + Maximum length for strings. + """ + ), + ] = None, + pattern: Annotated[ + Optional[str], + Doc( + """ + RegEx pattern for strings. + """ + ), + ] = None, + regex: Annotated[ + Optional[str], + Doc( + """ + RegEx pattern for strings. + """ + ), + deprecated( + "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." + ), + ] = None, + discriminator: Annotated[ + Union[str, None], + Doc( + """ + Parameter field name for discriminating the type in a tagged union. + """ + ), + ] = None, + strict: Annotated[ + Union[bool, None], + Doc( + """ + If `True`, strict validation is applied to the field. + """ + ), + ] = _Unset, + multiple_of: Annotated[ + Union[float, None], + Doc( + """ + Value must be a multiple of this. Only applicable to numbers. + """ + ), + ] = _Unset, + allow_inf_nan: Annotated[ + Union[bool, None], + Doc( + """ + Allow `inf`, `-inf`, `nan`. Only applicable to numbers. + """ + ), + ] = _Unset, + max_digits: Annotated[ + Union[int, None], + Doc( + """ + Maximum number of allow digits for strings. + """ + ), + ] = _Unset, + decimal_places: Annotated[ + Union[int, None], + Doc( + """ + Maximum number of decimal places allowed for numbers. + """ + ), + ] = _Unset, + examples: Annotated[ + Optional[List[Any]], + Doc( + """ + Example values for this field. + """ + ), + ] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = _Unset, + openapi_examples: Annotated[ + Optional[Dict[str, Example]], + Doc( + """ + OpenAPI-specific examples. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Swagger UI (that provides the `/docs` interface) has better support for the + OpenAPI-specific examples than the JSON Schema `examples`, that's the main + use case for this. + + Read more about it in the + [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/#using-the-openapi_examples-parameter). + """ + ), + ] = None, + deprecated: Annotated[ + Union[deprecated, str, bool, None], + Doc( + """ + Mark this parameter field as deprecated. + + It will affect the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + include_in_schema: Annotated[ + bool, + Doc( + """ + To include (or not) this parameter field in the generated OpenAPI. + You probably don't need it, but it's available. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = True, + json_schema_extra: Annotated[ + Union[Dict[str, Any], None], + Doc( + """ + Any additional JSON schema data. + """ + ), + ] = None, + **extra: Annotated[ + Any, + Doc( + """ + Include extra fields used by the JSON Schema. + """ + ), + deprecated( + """ + The `extra` kwargs is deprecated. Use `json_schema_extra` instead. + """ + ), + ], +) -> Any: + return params.File( + default=default, + default_factory=default_factory, + media_type=media_type, + alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + pattern=pattern, + regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, + example=example, + examples=examples, + openapi_examples=openapi_examples, + deprecated=deprecated, + include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, + **extra, + ) + + +def Depends( # noqa: N802 + dependency: Annotated[ + Optional[Callable[..., Any]], + Doc( + """ + A "dependable" callable (like a function). + + Don't call it directly, FastAPI will call it for you, just pass the object + directly. + """ + ), + ] = None, + *, + use_cache: Annotated[ + bool, + Doc( + """ + By default, after a dependency is called the first time in a request, if + the dependency is declared again for the rest of the request (for example + if the dependency is needed by several dependencies), the value will be + re-used for the rest of the request. + + Set `use_cache` to `False` to disable this behavior and ensure the + dependency is called again (if declared more than once) in the same request. + """ + ), + ] = True, +) -> Any: + """ + Declare a FastAPI dependency. + + It takes a single "dependable" callable (like a function). + + Don't call it directly, FastAPI will call it for you. + + Read more about it in the + [FastAPI docs for Dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/). + + **Example** + + ```python + from typing import Annotated + + from fastapi import Depends, FastAPI + + app = FastAPI() + + + async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100): + return {"q": q, "skip": skip, "limit": limit} + + + @app.get("/items/") + async def read_items(commons: Annotated[dict, Depends(common_parameters)]): + return commons + ``` + """ + return params.Depends(dependency=dependency, use_cache=use_cache) + + +def Security( # noqa: N802 + dependency: Annotated[ + Optional[Callable[..., Any]], + Doc( + """ + A "dependable" callable (like a function). + + Don't call it directly, FastAPI will call it for you, just pass the object + directly. + """ + ), + ] = None, + *, + scopes: Annotated[ + Optional[Sequence[str]], + Doc( + """ + OAuth2 scopes required for the *path operation* that uses this Security + dependency. + + The term "scope" comes from the OAuth2 specification, it seems to be + intentionally vague and interpretable. It normally refers to permissions, + in cases to roles. + + These scopes are integrated with OpenAPI (and the API docs at `/docs`). + So they are visible in the OpenAPI specification. + ) + """ + ), + ] = None, + use_cache: Annotated[ + bool, + Doc( + """ + By default, after a dependency is called the first time in a request, if + the dependency is declared again for the rest of the request (for example + if the dependency is needed by several dependencies), the value will be + re-used for the rest of the request. + + Set `use_cache` to `False` to disable this behavior and ensure the + dependency is called again (if declared more than once) in the same request. + """ + ), + ] = True, +) -> Any: + """ + Declare a FastAPI Security dependency. + + The only difference with a regular dependency is that it can declare OAuth2 + scopes that will be integrated with OpenAPI and the automatic UI docs (by default + at `/docs`). + + It takes a single "dependable" callable (like a function). + + Don't call it directly, FastAPI will call it for you. + + Read more about it in the + [FastAPI docs for Security](https://fastapi.tiangolo.com/tutorial/security/) and + in the + [FastAPI docs for OAuth2 scopes](https://fastapi.tiangolo.com/advanced/security/oauth2-scopes/). + + **Example** + + ```python + from typing import Annotated + + from fastapi import Security, FastAPI + + from .db import User + from .security import get_current_active_user + + app = FastAPI() + + @app.get("/users/me/items/") + async def read_own_items( + current_user: Annotated[User, Security(get_current_active_user, scopes=["items"])] + ): + return [{"item_id": "Foo", "owner": current_user.username}] + ``` + """ + return params.Security(dependency=dependency, scopes=scopes, use_cache=use_cache) diff --git a/backend/.venv/Lib/site-packages/fastapi/params.py b/backend/.venv/Lib/site-packages/fastapi/params.py new file mode 100644 index 0000000..8f5601d --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/params.py @@ -0,0 +1,786 @@ +import warnings +from enum import Enum +from typing import Any, Callable, Dict, List, Optional, Sequence, Union + +from fastapi.openapi.models import Example +from pydantic.fields import FieldInfo +from typing_extensions import Annotated, deprecated + +from ._compat import ( + PYDANTIC_V2, + PYDANTIC_VERSION_MINOR_TUPLE, + Undefined, +) + +_Unset: Any = Undefined + + +class ParamTypes(Enum): + query = "query" + header = "header" + path = "path" + cookie = "cookie" + + +class Param(FieldInfo): + in_: ParamTypes + + def __init__( + self, + default: Any = Undefined, + *, + default_factory: Union[Callable[[], Any], None] = _Unset, + annotation: Optional[Any] = None, + alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + pattern: Optional[str] = None, + regex: Annotated[ + Optional[str], + deprecated( + "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." + ), + ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = _Unset, + openapi_examples: Optional[Dict[str, Example]] = None, + deprecated: Union[deprecated, str, bool, None] = None, + include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, + **extra: Any, + ): + if example is not _Unset: + warnings.warn( + "`example` has been deprecated, please use `examples` instead", + category=DeprecationWarning, + stacklevel=4, + ) + self.example = example + self.include_in_schema = include_in_schema + self.openapi_examples = openapi_examples + kwargs = dict( + default=default, + default_factory=default_factory, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + discriminator=discriminator, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, + **extra, + ) + if examples is not None: + kwargs["examples"] = examples + if regex is not None: + warnings.warn( + "`regex` has been deprecated, please use `pattern` instead", + category=DeprecationWarning, + stacklevel=4, + ) + current_json_schema_extra = json_schema_extra or extra + if PYDANTIC_VERSION_MINOR_TUPLE < (2, 7): + self.deprecated = deprecated + else: + kwargs["deprecated"] = deprecated + if PYDANTIC_V2: + kwargs.update( + { + "annotation": annotation, + "alias_priority": alias_priority, + "validation_alias": validation_alias, + "serialization_alias": serialization_alias, + "strict": strict, + "json_schema_extra": current_json_schema_extra, + } + ) + kwargs["pattern"] = pattern or regex + else: + kwargs["regex"] = pattern or regex + kwargs.update(**current_json_schema_extra) + use_kwargs = {k: v for k, v in kwargs.items() if v is not _Unset} + + super().__init__(**use_kwargs) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self.default})" + + +class Path(Param): + in_ = ParamTypes.path + + def __init__( + self, + default: Any = ..., + *, + default_factory: Union[Callable[[], Any], None] = _Unset, + annotation: Optional[Any] = None, + alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + pattern: Optional[str] = None, + regex: Annotated[ + Optional[str], + deprecated( + "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." + ), + ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = _Unset, + openapi_examples: Optional[Dict[str, Example]] = None, + deprecated: Union[deprecated, str, bool, None] = None, + include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, + **extra: Any, + ): + assert default is ..., "Path parameters cannot have a default value" + self.in_ = self.in_ + super().__init__( + default=default, + default_factory=default_factory, + annotation=annotation, + alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + pattern=pattern, + regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, + deprecated=deprecated, + example=example, + examples=examples, + openapi_examples=openapi_examples, + include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, + **extra, + ) + + +class Query(Param): + in_ = ParamTypes.query + + def __init__( + self, + default: Any = Undefined, + *, + default_factory: Union[Callable[[], Any], None] = _Unset, + annotation: Optional[Any] = None, + alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + pattern: Optional[str] = None, + regex: Annotated[ + Optional[str], + deprecated( + "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." + ), + ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = _Unset, + openapi_examples: Optional[Dict[str, Example]] = None, + deprecated: Union[deprecated, str, bool, None] = None, + include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, + **extra: Any, + ): + super().__init__( + default=default, + default_factory=default_factory, + annotation=annotation, + alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + pattern=pattern, + regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, + deprecated=deprecated, + example=example, + examples=examples, + openapi_examples=openapi_examples, + include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, + **extra, + ) + + +class Header(Param): + in_ = ParamTypes.header + + def __init__( + self, + default: Any = Undefined, + *, + default_factory: Union[Callable[[], Any], None] = _Unset, + annotation: Optional[Any] = None, + alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, + convert_underscores: bool = True, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + pattern: Optional[str] = None, + regex: Annotated[ + Optional[str], + deprecated( + "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." + ), + ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = _Unset, + openapi_examples: Optional[Dict[str, Example]] = None, + deprecated: Union[deprecated, str, bool, None] = None, + include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, + **extra: Any, + ): + self.convert_underscores = convert_underscores + super().__init__( + default=default, + default_factory=default_factory, + annotation=annotation, + alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + pattern=pattern, + regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, + deprecated=deprecated, + example=example, + examples=examples, + openapi_examples=openapi_examples, + include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, + **extra, + ) + + +class Cookie(Param): + in_ = ParamTypes.cookie + + def __init__( + self, + default: Any = Undefined, + *, + default_factory: Union[Callable[[], Any], None] = _Unset, + annotation: Optional[Any] = None, + alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + pattern: Optional[str] = None, + regex: Annotated[ + Optional[str], + deprecated( + "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." + ), + ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = _Unset, + openapi_examples: Optional[Dict[str, Example]] = None, + deprecated: Union[deprecated, str, bool, None] = None, + include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, + **extra: Any, + ): + super().__init__( + default=default, + default_factory=default_factory, + annotation=annotation, + alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + pattern=pattern, + regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, + deprecated=deprecated, + example=example, + examples=examples, + openapi_examples=openapi_examples, + include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, + **extra, + ) + + +class Body(FieldInfo): + def __init__( + self, + default: Any = Undefined, + *, + default_factory: Union[Callable[[], Any], None] = _Unset, + annotation: Optional[Any] = None, + embed: Union[bool, None] = None, + media_type: str = "application/json", + alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + pattern: Optional[str] = None, + regex: Annotated[ + Optional[str], + deprecated( + "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." + ), + ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = _Unset, + openapi_examples: Optional[Dict[str, Example]] = None, + deprecated: Union[deprecated, str, bool, None] = None, + include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, + **extra: Any, + ): + self.embed = embed + self.media_type = media_type + if example is not _Unset: + warnings.warn( + "`example` has been deprecated, please use `examples` instead", + category=DeprecationWarning, + stacklevel=4, + ) + self.example = example + self.include_in_schema = include_in_schema + self.openapi_examples = openapi_examples + kwargs = dict( + default=default, + default_factory=default_factory, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + discriminator=discriminator, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, + **extra, + ) + if examples is not None: + kwargs["examples"] = examples + if regex is not None: + warnings.warn( + "`regex` has been deprecated, please use `pattern` instead", + category=DeprecationWarning, + stacklevel=4, + ) + current_json_schema_extra = json_schema_extra or extra + if PYDANTIC_VERSION_MINOR_TUPLE < (2, 7): + self.deprecated = deprecated + else: + kwargs["deprecated"] = deprecated + if PYDANTIC_V2: + kwargs.update( + { + "annotation": annotation, + "alias_priority": alias_priority, + "validation_alias": validation_alias, + "serialization_alias": serialization_alias, + "strict": strict, + "json_schema_extra": current_json_schema_extra, + } + ) + kwargs["pattern"] = pattern or regex + else: + kwargs["regex"] = pattern or regex + kwargs.update(**current_json_schema_extra) + + use_kwargs = {k: v for k, v in kwargs.items() if v is not _Unset} + + super().__init__(**use_kwargs) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self.default})" + + +class Form(Body): + def __init__( + self, + default: Any = Undefined, + *, + default_factory: Union[Callable[[], Any], None] = _Unset, + annotation: Optional[Any] = None, + media_type: str = "application/x-www-form-urlencoded", + alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + pattern: Optional[str] = None, + regex: Annotated[ + Optional[str], + deprecated( + "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." + ), + ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = _Unset, + openapi_examples: Optional[Dict[str, Example]] = None, + deprecated: Union[deprecated, str, bool, None] = None, + include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, + **extra: Any, + ): + super().__init__( + default=default, + default_factory=default_factory, + annotation=annotation, + media_type=media_type, + alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + pattern=pattern, + regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, + deprecated=deprecated, + example=example, + examples=examples, + openapi_examples=openapi_examples, + include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, + **extra, + ) + + +class File(Form): + def __init__( + self, + default: Any = Undefined, + *, + default_factory: Union[Callable[[], Any], None] = _Unset, + annotation: Optional[Any] = None, + media_type: str = "multipart/form-data", + alias: Optional[str] = None, + alias_priority: Union[int, None] = _Unset, + # TODO: update when deprecating Pydantic v1, import these types + # validation_alias: str | AliasPath | AliasChoices | None + validation_alias: Union[str, None] = None, + serialization_alias: Union[str, None] = None, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + pattern: Optional[str] = None, + regex: Annotated[ + Optional[str], + deprecated( + "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." + ), + ] = None, + discriminator: Union[str, None] = None, + strict: Union[bool, None] = _Unset, + multiple_of: Union[float, None] = _Unset, + allow_inf_nan: Union[bool, None] = _Unset, + max_digits: Union[int, None] = _Unset, + decimal_places: Union[int, None] = _Unset, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = _Unset, + openapi_examples: Optional[Dict[str, Example]] = None, + deprecated: Union[deprecated, str, bool, None] = None, + include_in_schema: bool = True, + json_schema_extra: Union[Dict[str, Any], None] = None, + **extra: Any, + ): + super().__init__( + default=default, + default_factory=default_factory, + annotation=annotation, + media_type=media_type, + alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + pattern=pattern, + regex=regex, + discriminator=discriminator, + strict=strict, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, + deprecated=deprecated, + example=example, + examples=examples, + openapi_examples=openapi_examples, + include_in_schema=include_in_schema, + json_schema_extra=json_schema_extra, + **extra, + ) + + +class Depends: + def __init__( + self, dependency: Optional[Callable[..., Any]] = None, *, use_cache: bool = True + ): + self.dependency = dependency + self.use_cache = use_cache + + def __repr__(self) -> str: + attr = getattr(self.dependency, "__name__", type(self.dependency).__name__) + cache = "" if self.use_cache else ", use_cache=False" + return f"{self.__class__.__name__}({attr}{cache})" + + +class Security(Depends): + def __init__( + self, + dependency: Optional[Callable[..., Any]] = None, + *, + scopes: Optional[Sequence[str]] = None, + use_cache: bool = True, + ): + super().__init__(dependency=dependency, use_cache=use_cache) + self.scopes = scopes or [] diff --git a/backend/.venv/Lib/site-packages/fastapi/py.typed b/backend/.venv/Lib/site-packages/fastapi/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/fastapi/requests.py b/backend/.venv/Lib/site-packages/fastapi/requests.py new file mode 100644 index 0000000..d16552c --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/requests.py @@ -0,0 +1,2 @@ +from starlette.requests import HTTPConnection as HTTPConnection # noqa: F401 +from starlette.requests import Request as Request # noqa: F401 diff --git a/backend/.venv/Lib/site-packages/fastapi/responses.py b/backend/.venv/Lib/site-packages/fastapi/responses.py new file mode 100644 index 0000000..6c8db6f --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/responses.py @@ -0,0 +1,48 @@ +from typing import Any + +from starlette.responses import FileResponse as FileResponse # noqa +from starlette.responses import HTMLResponse as HTMLResponse # noqa +from starlette.responses import JSONResponse as JSONResponse # noqa +from starlette.responses import PlainTextResponse as PlainTextResponse # noqa +from starlette.responses import RedirectResponse as RedirectResponse # noqa +from starlette.responses import Response as Response # noqa +from starlette.responses import StreamingResponse as StreamingResponse # noqa + +try: + import ujson +except ImportError: # pragma: nocover + ujson = None # type: ignore + + +try: + import orjson +except ImportError: # pragma: nocover + orjson = None # type: ignore + + +class UJSONResponse(JSONResponse): + """ + JSON response using the high-performance ujson library to serialize data to JSON. + + Read more about it in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/). + """ + + def render(self, content: Any) -> bytes: + assert ujson is not None, "ujson must be installed to use UJSONResponse" + return ujson.dumps(content, ensure_ascii=False).encode("utf-8") + + +class ORJSONResponse(JSONResponse): + """ + JSON response using the high-performance orjson library to serialize data to JSON. + + Read more about it in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/). + """ + + def render(self, content: Any) -> bytes: + assert orjson is not None, "orjson must be installed to use ORJSONResponse" + return orjson.dumps( + content, option=orjson.OPT_NON_STR_KEYS | orjson.OPT_SERIALIZE_NUMPY + ) diff --git a/backend/.venv/Lib/site-packages/fastapi/routing.py b/backend/.venv/Lib/site-packages/fastapi/routing.py new file mode 100644 index 0000000..8ea4bb2 --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/routing.py @@ -0,0 +1,4439 @@ +import asyncio +import dataclasses +import email.message +import inspect +import json +from contextlib import AsyncExitStack, asynccontextmanager +from enum import Enum, IntEnum +from typing import ( + Any, + AsyncIterator, + Callable, + Coroutine, + Dict, + List, + Mapping, + Optional, + Sequence, + Set, + Tuple, + Type, + Union, +) + +from fastapi import params +from fastapi._compat import ( + ModelField, + Undefined, + _get_model_config, + _model_dump, + _normalize_errors, + lenient_issubclass, +) +from fastapi.datastructures import Default, DefaultPlaceholder +from fastapi.dependencies.models import Dependant +from fastapi.dependencies.utils import ( + _should_embed_body_fields, + get_body_field, + get_dependant, + get_flat_dependant, + get_parameterless_sub_dependant, + get_typed_return_annotation, + solve_dependencies, +) +from fastapi.encoders import jsonable_encoder +from fastapi.exceptions import ( + FastAPIError, + RequestValidationError, + ResponseValidationError, + WebSocketRequestValidationError, +) +from fastapi.types import DecoratedCallable, IncEx +from fastapi.utils import ( + create_cloned_field, + create_model_field, + generate_unique_id, + get_value_or_default, + is_body_allowed_for_status_code, +) +from pydantic import BaseModel +from starlette import routing +from starlette.concurrency import run_in_threadpool +from starlette.exceptions import HTTPException +from starlette.requests import Request +from starlette.responses import JSONResponse, Response +from starlette.routing import ( + BaseRoute, + Match, + compile_path, + get_name, + request_response, + websocket_session, +) +from starlette.routing import Mount as Mount # noqa +from starlette.types import AppType, ASGIApp, Lifespan, Scope +from starlette.websockets import WebSocket +from typing_extensions import Annotated, Doc, deprecated + + +def _prepare_response_content( + res: Any, + *, + exclude_unset: bool, + exclude_defaults: bool = False, + exclude_none: bool = False, +) -> Any: + if isinstance(res, BaseModel): + read_with_orm_mode = getattr(_get_model_config(res), "read_with_orm_mode", None) + if read_with_orm_mode: + # Let from_orm extract the data from this model instead of converting + # it now to a dict. + # Otherwise, there's no way to extract lazy data that requires attribute + # access instead of dict iteration, e.g. lazy relationships. + return res + return _model_dump( + res, + by_alias=True, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + elif isinstance(res, list): + return [ + _prepare_response_content( + item, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + for item in res + ] + elif isinstance(res, dict): + return { + k: _prepare_response_content( + v, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + for k, v in res.items() + } + elif dataclasses.is_dataclass(res): + return dataclasses.asdict(res) + return res + + +def _merge_lifespan_context( + original_context: Lifespan[Any], nested_context: Lifespan[Any] +) -> Lifespan[Any]: + @asynccontextmanager + async def merged_lifespan( + app: AppType, + ) -> AsyncIterator[Optional[Mapping[str, Any]]]: + async with original_context(app) as maybe_original_state: + async with nested_context(app) as maybe_nested_state: + if maybe_nested_state is None and maybe_original_state is None: + yield None # old ASGI compatibility + else: + yield {**(maybe_nested_state or {}), **(maybe_original_state or {})} + + return merged_lifespan # type: ignore[return-value] + + +async def serialize_response( + *, + field: Optional[ModelField] = None, + response_content: Any, + include: Optional[IncEx] = None, + exclude: Optional[IncEx] = None, + by_alias: bool = True, + exclude_unset: bool = False, + exclude_defaults: bool = False, + exclude_none: bool = False, + is_coroutine: bool = True, +) -> Any: + if field: + errors = [] + if not hasattr(field, "serialize"): + # pydantic v1 + response_content = _prepare_response_content( + response_content, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + if is_coroutine: + value, errors_ = field.validate(response_content, {}, loc=("response",)) + else: + value, errors_ = await run_in_threadpool( + field.validate, response_content, {}, loc=("response",) + ) + if isinstance(errors_, list): + errors.extend(errors_) + elif errors_: + errors.append(errors_) + if errors: + raise ResponseValidationError( + errors=_normalize_errors(errors), body=response_content + ) + + if hasattr(field, "serialize"): + return field.serialize( + value, + include=include, + exclude=exclude, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + + return jsonable_encoder( + value, + include=include, + exclude=exclude, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + else: + return jsonable_encoder(response_content) + + +async def run_endpoint_function( + *, dependant: Dependant, values: Dict[str, Any], is_coroutine: bool +) -> Any: + # Only called by get_request_handler. Has been split into its own function to + # facilitate profiling endpoints, since inner functions are harder to profile. + assert dependant.call is not None, "dependant.call must be a function" + + if is_coroutine: + return await dependant.call(**values) + else: + return await run_in_threadpool(dependant.call, **values) + + +def get_request_handler( + dependant: Dependant, + body_field: Optional[ModelField] = None, + status_code: Optional[int] = None, + response_class: Union[Type[Response], DefaultPlaceholder] = Default(JSONResponse), + response_field: Optional[ModelField] = None, + response_model_include: Optional[IncEx] = None, + response_model_exclude: Optional[IncEx] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + dependency_overrides_provider: Optional[Any] = None, + embed_body_fields: bool = False, +) -> Callable[[Request], Coroutine[Any, Any, Response]]: + assert dependant.call is not None, "dependant.call must be a function" + is_coroutine = asyncio.iscoroutinefunction(dependant.call) + is_body_form = body_field and isinstance(body_field.field_info, params.Form) + if isinstance(response_class, DefaultPlaceholder): + actual_response_class: Type[Response] = response_class.value + else: + actual_response_class = response_class + + async def app(request: Request) -> Response: + response: Union[Response, None] = None + async with AsyncExitStack() as file_stack: + try: + body: Any = None + if body_field: + if is_body_form: + body = await request.form() + file_stack.push_async_callback(body.close) + else: + body_bytes = await request.body() + if body_bytes: + json_body: Any = Undefined + content_type_value = request.headers.get("content-type") + if not content_type_value: + json_body = await request.json() + else: + message = email.message.Message() + message["content-type"] = content_type_value + if message.get_content_maintype() == "application": + subtype = message.get_content_subtype() + if subtype == "json" or subtype.endswith("+json"): + json_body = await request.json() + if json_body != Undefined: + body = json_body + else: + body = body_bytes + except json.JSONDecodeError as e: + validation_error = RequestValidationError( + [ + { + "type": "json_invalid", + "loc": ("body", e.pos), + "msg": "JSON decode error", + "input": {}, + "ctx": {"error": e.msg}, + } + ], + body=e.doc, + ) + raise validation_error from e + except HTTPException: + # If a middleware raises an HTTPException, it should be raised again + raise + except Exception as e: + http_error = HTTPException( + status_code=400, detail="There was an error parsing the body" + ) + raise http_error from e + errors: List[Any] = [] + async with AsyncExitStack() as async_exit_stack: + solved_result = await solve_dependencies( + request=request, + dependant=dependant, + body=body, + dependency_overrides_provider=dependency_overrides_provider, + async_exit_stack=async_exit_stack, + embed_body_fields=embed_body_fields, + ) + errors = solved_result.errors + if not errors: + raw_response = await run_endpoint_function( + dependant=dependant, + values=solved_result.values, + is_coroutine=is_coroutine, + ) + if isinstance(raw_response, Response): + if raw_response.background is None: + raw_response.background = solved_result.background_tasks + response = raw_response + else: + response_args: Dict[str, Any] = { + "background": solved_result.background_tasks + } + # If status_code was set, use it, otherwise use the default from the + # response class, in the case of redirect it's 307 + current_status_code = ( + status_code + if status_code + else solved_result.response.status_code + ) + if current_status_code is not None: + response_args["status_code"] = current_status_code + if solved_result.response.status_code: + response_args["status_code"] = ( + solved_result.response.status_code + ) + content = await serialize_response( + field=response_field, + response_content=raw_response, + include=response_model_include, + exclude=response_model_exclude, + by_alias=response_model_by_alias, + exclude_unset=response_model_exclude_unset, + exclude_defaults=response_model_exclude_defaults, + exclude_none=response_model_exclude_none, + is_coroutine=is_coroutine, + ) + response = actual_response_class(content, **response_args) + if not is_body_allowed_for_status_code(response.status_code): + response.body = b"" + response.headers.raw.extend(solved_result.response.headers.raw) + if errors: + validation_error = RequestValidationError( + _normalize_errors(errors), body=body + ) + raise validation_error + if response is None: + raise FastAPIError( + "No response object was returned. There's a high chance that the " + "application code is raising an exception and a dependency with yield " + "has a block with a bare except, or a block with except Exception, " + "and is not raising the exception again. Read more about it in the " + "docs: https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#dependencies-with-yield-and-except" + ) + return response + + return app + + +def get_websocket_app( + dependant: Dependant, + dependency_overrides_provider: Optional[Any] = None, + embed_body_fields: bool = False, +) -> Callable[[WebSocket], Coroutine[Any, Any, Any]]: + async def app(websocket: WebSocket) -> None: + async with AsyncExitStack() as async_exit_stack: + # TODO: remove this scope later, after a few releases + # This scope fastapi_astack is no longer used by FastAPI, kept for + # compatibility, just in case + websocket.scope["fastapi_astack"] = async_exit_stack + solved_result = await solve_dependencies( + request=websocket, + dependant=dependant, + dependency_overrides_provider=dependency_overrides_provider, + async_exit_stack=async_exit_stack, + embed_body_fields=embed_body_fields, + ) + if solved_result.errors: + raise WebSocketRequestValidationError( + _normalize_errors(solved_result.errors) + ) + assert dependant.call is not None, "dependant.call must be a function" + await dependant.call(**solved_result.values) + + return app + + +class APIWebSocketRoute(routing.WebSocketRoute): + def __init__( + self, + path: str, + endpoint: Callable[..., Any], + *, + name: Optional[str] = None, + dependencies: Optional[Sequence[params.Depends]] = None, + dependency_overrides_provider: Optional[Any] = None, + ) -> None: + self.path = path + self.endpoint = endpoint + self.name = get_name(endpoint) if name is None else name + self.dependencies = list(dependencies or []) + self.path_regex, self.path_format, self.param_convertors = compile_path(path) + self.dependant = get_dependant(path=self.path_format, call=self.endpoint) + for depends in self.dependencies[::-1]: + self.dependant.dependencies.insert( + 0, + get_parameterless_sub_dependant(depends=depends, path=self.path_format), + ) + self._flat_dependant = get_flat_dependant(self.dependant) + self._embed_body_fields = _should_embed_body_fields( + self._flat_dependant.body_params + ) + self.app = websocket_session( + get_websocket_app( + dependant=self.dependant, + dependency_overrides_provider=dependency_overrides_provider, + embed_body_fields=self._embed_body_fields, + ) + ) + + def matches(self, scope: Scope) -> Tuple[Match, Scope]: + match, child_scope = super().matches(scope) + if match != Match.NONE: + child_scope["route"] = self + return match, child_scope + + +class APIRoute(routing.Route): + def __init__( + self, + path: str, + endpoint: Callable[..., Any], + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[params.Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + name: Optional[str] = None, + methods: Optional[Union[Set[str], List[str]]] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[IncEx] = None, + response_model_exclude: Optional[IncEx] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Union[Type[Response], DefaultPlaceholder] = Default( + JSONResponse + ), + dependency_overrides_provider: Optional[Any] = None, + callbacks: Optional[List[BaseRoute]] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Union[ + Callable[["APIRoute"], str], DefaultPlaceholder + ] = Default(generate_unique_id), + ) -> None: + self.path = path + self.endpoint = endpoint + if isinstance(response_model, DefaultPlaceholder): + return_annotation = get_typed_return_annotation(endpoint) + if lenient_issubclass(return_annotation, Response): + response_model = None + else: + response_model = return_annotation + self.response_model = response_model + self.summary = summary + self.response_description = response_description + self.deprecated = deprecated + self.operation_id = operation_id + self.response_model_include = response_model_include + self.response_model_exclude = response_model_exclude + self.response_model_by_alias = response_model_by_alias + self.response_model_exclude_unset = response_model_exclude_unset + self.response_model_exclude_defaults = response_model_exclude_defaults + self.response_model_exclude_none = response_model_exclude_none + self.include_in_schema = include_in_schema + self.response_class = response_class + self.dependency_overrides_provider = dependency_overrides_provider + self.callbacks = callbacks + self.openapi_extra = openapi_extra + self.generate_unique_id_function = generate_unique_id_function + self.tags = tags or [] + self.responses = responses or {} + self.name = get_name(endpoint) if name is None else name + self.path_regex, self.path_format, self.param_convertors = compile_path(path) + if methods is None: + methods = ["GET"] + self.methods: Set[str] = {method.upper() for method in methods} + if isinstance(generate_unique_id_function, DefaultPlaceholder): + current_generate_unique_id: Callable[[APIRoute], str] = ( + generate_unique_id_function.value + ) + else: + current_generate_unique_id = generate_unique_id_function + self.unique_id = self.operation_id or current_generate_unique_id(self) + # normalize enums e.g. http.HTTPStatus + if isinstance(status_code, IntEnum): + status_code = int(status_code) + self.status_code = status_code + if self.response_model: + assert is_body_allowed_for_status_code( + status_code + ), f"Status code {status_code} must not have a response body" + response_name = "Response_" + self.unique_id + self.response_field = create_model_field( + name=response_name, + type_=self.response_model, + mode="serialization", + ) + # Create a clone of the field, so that a Pydantic submodel is not returned + # as is just because it's an instance of a subclass of a more limited class + # e.g. UserInDB (containing hashed_password) could be a subclass of User + # that doesn't have the hashed_password. But because it's a subclass, it + # would pass the validation and be returned as is. + # By being a new field, no inheritance will be passed as is. A new model + # will always be created. + # TODO: remove when deprecating Pydantic v1 + self.secure_cloned_response_field: Optional[ModelField] = ( + create_cloned_field(self.response_field) + ) + else: + self.response_field = None # type: ignore + self.secure_cloned_response_field = None + self.dependencies = list(dependencies or []) + self.description = description or inspect.cleandoc(self.endpoint.__doc__ or "") + # if a "form feed" character (page break) is found in the description text, + # truncate description text to the content preceding the first "form feed" + self.description = self.description.split("\f")[0].strip() + response_fields = {} + for additional_status_code, response in self.responses.items(): + assert isinstance(response, dict), "An additional response must be a dict" + model = response.get("model") + if model: + assert is_body_allowed_for_status_code( + additional_status_code + ), f"Status code {additional_status_code} must not have a response body" + response_name = f"Response_{additional_status_code}_{self.unique_id}" + response_field = create_model_field( + name=response_name, type_=model, mode="serialization" + ) + response_fields[additional_status_code] = response_field + if response_fields: + self.response_fields: Dict[Union[int, str], ModelField] = response_fields + else: + self.response_fields = {} + + assert callable(endpoint), "An endpoint must be a callable" + self.dependant = get_dependant(path=self.path_format, call=self.endpoint) + for depends in self.dependencies[::-1]: + self.dependant.dependencies.insert( + 0, + get_parameterless_sub_dependant(depends=depends, path=self.path_format), + ) + self._flat_dependant = get_flat_dependant(self.dependant) + self._embed_body_fields = _should_embed_body_fields( + self._flat_dependant.body_params + ) + self.body_field = get_body_field( + flat_dependant=self._flat_dependant, + name=self.unique_id, + embed_body_fields=self._embed_body_fields, + ) + self.app = request_response(self.get_route_handler()) + + def get_route_handler(self) -> Callable[[Request], Coroutine[Any, Any, Response]]: + return get_request_handler( + dependant=self.dependant, + body_field=self.body_field, + status_code=self.status_code, + response_class=self.response_class, + response_field=self.secure_cloned_response_field, + response_model_include=self.response_model_include, + response_model_exclude=self.response_model_exclude, + response_model_by_alias=self.response_model_by_alias, + response_model_exclude_unset=self.response_model_exclude_unset, + response_model_exclude_defaults=self.response_model_exclude_defaults, + response_model_exclude_none=self.response_model_exclude_none, + dependency_overrides_provider=self.dependency_overrides_provider, + embed_body_fields=self._embed_body_fields, + ) + + def matches(self, scope: Scope) -> Tuple[Match, Scope]: + match, child_scope = super().matches(scope) + if match != Match.NONE: + child_scope["route"] = self + return match, child_scope + + +class APIRouter(routing.Router): + """ + `APIRouter` class, used to group *path operations*, for example to structure + an app in multiple files. It would then be included in the `FastAPI` app, or + in another `APIRouter` (ultimately included in the app). + + Read more about it in the + [FastAPI docs for Bigger Applications - Multiple Files](https://fastapi.tiangolo.com/tutorial/bigger-applications/). + + ## Example + + ```python + from fastapi import APIRouter, FastAPI + + app = FastAPI() + router = APIRouter() + + + @router.get("/users/", tags=["users"]) + async def read_users(): + return [{"username": "Rick"}, {"username": "Morty"}] + + + app.include_router(router) + ``` + """ + + def __init__( + self, + *, + prefix: Annotated[str, Doc("An optional path prefix for the router.")] = "", + tags: Annotated[ + Optional[List[Union[str, Enum]]], + Doc( + """ + A list of tags to be applied to all the *path operations* in this + router. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + dependencies: Annotated[ + Optional[Sequence[params.Depends]], + Doc( + """ + A list of dependencies (using `Depends()`) to be applied to all the + *path operations* in this router. + + Read more about it in the + [FastAPI docs for Bigger Applications - Multiple Files](https://fastapi.tiangolo.com/tutorial/bigger-applications/#include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies). + """ + ), + ] = None, + default_response_class: Annotated[ + Type[Response], + Doc( + """ + The default response class to be used. + + Read more in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#default-response-class). + """ + ), + ] = Default(JSONResponse), + responses: Annotated[ + Optional[Dict[Union[int, str], Dict[str, Any]]], + Doc( + """ + Additional responses to be shown in OpenAPI. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Additional Responses in OpenAPI](https://fastapi.tiangolo.com/advanced/additional-responses/). + + And in the + [FastAPI docs for Bigger Applications](https://fastapi.tiangolo.com/tutorial/bigger-applications/#include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies). + """ + ), + ] = None, + callbacks: Annotated[ + Optional[List[BaseRoute]], + Doc( + """ + OpenAPI callbacks that should apply to all *path operations* in this + router. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). + """ + ), + ] = None, + routes: Annotated[ + Optional[List[BaseRoute]], + Doc( + """ + **Note**: you probably shouldn't use this parameter, it is inherited + from Starlette and supported for compatibility. + + --- + + A list of routes to serve incoming HTTP and WebSocket requests. + """ + ), + deprecated( + """ + You normally wouldn't use this parameter with FastAPI, it is inherited + from Starlette and supported for compatibility. + + In FastAPI, you normally would use the *path operation methods*, + like `router.get()`, `router.post()`, etc. + """ + ), + ] = None, + redirect_slashes: Annotated[ + bool, + Doc( + """ + Whether to detect and redirect slashes in URLs when the client doesn't + use the same format. + """ + ), + ] = True, + default: Annotated[ + Optional[ASGIApp], + Doc( + """ + Default function handler for this router. Used to handle + 404 Not Found errors. + """ + ), + ] = None, + dependency_overrides_provider: Annotated[ + Optional[Any], + Doc( + """ + Only used internally by FastAPI to handle dependency overrides. + + You shouldn't need to use it. It normally points to the `FastAPI` app + object. + """ + ), + ] = None, + route_class: Annotated[ + Type[APIRoute], + Doc( + """ + Custom route (*path operation*) class to be used by this router. + + Read more about it in the + [FastAPI docs for Custom Request and APIRoute class](https://fastapi.tiangolo.com/how-to/custom-request-and-route/#custom-apiroute-class-in-a-router). + """ + ), + ] = APIRoute, + on_startup: Annotated[ + Optional[Sequence[Callable[[], Any]]], + Doc( + """ + A list of startup event handler functions. + + You should instead use the `lifespan` handlers. + + Read more in the [FastAPI docs for `lifespan`](https://fastapi.tiangolo.com/advanced/events/). + """ + ), + ] = None, + on_shutdown: Annotated[ + Optional[Sequence[Callable[[], Any]]], + Doc( + """ + A list of shutdown event handler functions. + + You should instead use the `lifespan` handlers. + + Read more in the + [FastAPI docs for `lifespan`](https://fastapi.tiangolo.com/advanced/events/). + """ + ), + ] = None, + # the generic to Lifespan[AppType] is the type of the top level application + # which the router cannot know statically, so we use typing.Any + lifespan: Annotated[ + Optional[Lifespan[Any]], + Doc( + """ + A `Lifespan` context manager handler. This replaces `startup` and + `shutdown` functions with a single context manager. + + Read more in the + [FastAPI docs for `lifespan`](https://fastapi.tiangolo.com/advanced/events/). + """ + ), + ] = None, + deprecated: Annotated[ + Optional[bool], + Doc( + """ + Mark all *path operations* in this router as deprecated. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + include_in_schema: Annotated[ + bool, + Doc( + """ + To include (or not) all the *path operations* in this router in the + generated OpenAPI. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + """ + ), + ] = True, + generate_unique_id_function: Annotated[ + Callable[[APIRoute], str], + Doc( + """ + Customize the function used to generate unique IDs for the *path + operations* shown in the generated OpenAPI. + + This is particularly useful when automatically generating clients or + SDKs for your API. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = Default(generate_unique_id), + ) -> None: + super().__init__( + routes=routes, + redirect_slashes=redirect_slashes, + default=default, + on_startup=on_startup, + on_shutdown=on_shutdown, + lifespan=lifespan, + ) + if prefix: + assert prefix.startswith("/"), "A path prefix must start with '/'" + assert not prefix.endswith( + "/" + ), "A path prefix must not end with '/', as the routes will start with '/'" + self.prefix = prefix + self.tags: List[Union[str, Enum]] = tags or [] + self.dependencies = list(dependencies or []) + self.deprecated = deprecated + self.include_in_schema = include_in_schema + self.responses = responses or {} + self.callbacks = callbacks or [] + self.dependency_overrides_provider = dependency_overrides_provider + self.route_class = route_class + self.default_response_class = default_response_class + self.generate_unique_id_function = generate_unique_id_function + + def route( + self, + path: str, + methods: Optional[List[str]] = None, + name: Optional[str] = None, + include_in_schema: bool = True, + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + def decorator(func: DecoratedCallable) -> DecoratedCallable: + self.add_route( + path, + func, + methods=methods, + name=name, + include_in_schema=include_in_schema, + ) + return func + + return decorator + + def add_api_route( + self, + path: str, + endpoint: Callable[..., Any], + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[params.Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + methods: Optional[Union[Set[str], List[str]]] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[IncEx] = None, + response_model_exclude: Optional[IncEx] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Union[Type[Response], DefaultPlaceholder] = Default( + JSONResponse + ), + name: Optional[str] = None, + route_class_override: Optional[Type[APIRoute]] = None, + callbacks: Optional[List[BaseRoute]] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Union[ + Callable[[APIRoute], str], DefaultPlaceholder + ] = Default(generate_unique_id), + ) -> None: + route_class = route_class_override or self.route_class + responses = responses or {} + combined_responses = {**self.responses, **responses} + current_response_class = get_value_or_default( + response_class, self.default_response_class + ) + current_tags = self.tags.copy() + if tags: + current_tags.extend(tags) + current_dependencies = self.dependencies.copy() + if dependencies: + current_dependencies.extend(dependencies) + current_callbacks = self.callbacks.copy() + if callbacks: + current_callbacks.extend(callbacks) + current_generate_unique_id = get_value_or_default( + generate_unique_id_function, self.generate_unique_id_function + ) + route = route_class( + self.prefix + path, + endpoint=endpoint, + response_model=response_model, + status_code=status_code, + tags=current_tags, + dependencies=current_dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=combined_responses, + deprecated=deprecated or self.deprecated, + methods=methods, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema and self.include_in_schema, + response_class=current_response_class, + name=name, + dependency_overrides_provider=self.dependency_overrides_provider, + callbacks=current_callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=current_generate_unique_id, + ) + self.routes.append(route) + + def api_route( + self, + path: str, + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[params.Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + methods: Optional[List[str]] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[IncEx] = None, + response_model_exclude: Optional[IncEx] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Type[Response] = Default(JSONResponse), + name: Optional[str] = None, + callbacks: Optional[List[BaseRoute]] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + def decorator(func: DecoratedCallable) -> DecoratedCallable: + self.add_api_route( + path, + func, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + methods=methods, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + return func + + return decorator + + def add_api_websocket_route( + self, + path: str, + endpoint: Callable[..., Any], + name: Optional[str] = None, + *, + dependencies: Optional[Sequence[params.Depends]] = None, + ) -> None: + current_dependencies = self.dependencies.copy() + if dependencies: + current_dependencies.extend(dependencies) + + route = APIWebSocketRoute( + self.prefix + path, + endpoint=endpoint, + name=name, + dependencies=current_dependencies, + dependency_overrides_provider=self.dependency_overrides_provider, + ) + self.routes.append(route) + + def websocket( + self, + path: Annotated[ + str, + Doc( + """ + WebSocket path. + """ + ), + ], + name: Annotated[ + Optional[str], + Doc( + """ + A name for the WebSocket. Only used internally. + """ + ), + ] = None, + *, + dependencies: Annotated[ + Optional[Sequence[params.Depends]], + Doc( + """ + A list of dependencies (using `Depends()`) to be used for this + WebSocket. + + Read more about it in the + [FastAPI docs for WebSockets](https://fastapi.tiangolo.com/advanced/websockets/). + """ + ), + ] = None, + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Decorate a WebSocket function. + + Read more about it in the + [FastAPI docs for WebSockets](https://fastapi.tiangolo.com/advanced/websockets/). + + **Example** + + ## Example + + ```python + from fastapi import APIRouter, FastAPI, WebSocket + + app = FastAPI() + router = APIRouter() + + @router.websocket("/ws") + async def websocket_endpoint(websocket: WebSocket): + await websocket.accept() + while True: + data = await websocket.receive_text() + await websocket.send_text(f"Message text was: {data}") + + app.include_router(router) + ``` + """ + + def decorator(func: DecoratedCallable) -> DecoratedCallable: + self.add_api_websocket_route( + path, func, name=name, dependencies=dependencies + ) + return func + + return decorator + + def websocket_route( + self, path: str, name: Union[str, None] = None + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + def decorator(func: DecoratedCallable) -> DecoratedCallable: + self.add_websocket_route(path, func, name=name) + return func + + return decorator + + def include_router( + self, + router: Annotated["APIRouter", Doc("The `APIRouter` to include.")], + *, + prefix: Annotated[str, Doc("An optional path prefix for the router.")] = "", + tags: Annotated[ + Optional[List[Union[str, Enum]]], + Doc( + """ + A list of tags to be applied to all the *path operations* in this + router. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + dependencies: Annotated[ + Optional[Sequence[params.Depends]], + Doc( + """ + A list of dependencies (using `Depends()`) to be applied to all the + *path operations* in this router. + + Read more about it in the + [FastAPI docs for Bigger Applications - Multiple Files](https://fastapi.tiangolo.com/tutorial/bigger-applications/#include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies). + """ + ), + ] = None, + default_response_class: Annotated[ + Type[Response], + Doc( + """ + The default response class to be used. + + Read more in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#default-response-class). + """ + ), + ] = Default(JSONResponse), + responses: Annotated[ + Optional[Dict[Union[int, str], Dict[str, Any]]], + Doc( + """ + Additional responses to be shown in OpenAPI. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Additional Responses in OpenAPI](https://fastapi.tiangolo.com/advanced/additional-responses/). + + And in the + [FastAPI docs for Bigger Applications](https://fastapi.tiangolo.com/tutorial/bigger-applications/#include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies). + """ + ), + ] = None, + callbacks: Annotated[ + Optional[List[BaseRoute]], + Doc( + """ + OpenAPI callbacks that should apply to all *path operations* in this + router. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). + """ + ), + ] = None, + deprecated: Annotated[ + Optional[bool], + Doc( + """ + Mark all *path operations* in this router as deprecated. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + include_in_schema: Annotated[ + bool, + Doc( + """ + Include (or not) all the *path operations* in this router in the + generated OpenAPI schema. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = True, + generate_unique_id_function: Annotated[ + Callable[[APIRoute], str], + Doc( + """ + Customize the function used to generate unique IDs for the *path + operations* shown in the generated OpenAPI. + + This is particularly useful when automatically generating clients or + SDKs for your API. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = Default(generate_unique_id), + ) -> None: + """ + Include another `APIRouter` in the same current `APIRouter`. + + Read more about it in the + [FastAPI docs for Bigger Applications](https://fastapi.tiangolo.com/tutorial/bigger-applications/). + + ## Example + + ```python + from fastapi import APIRouter, FastAPI + + app = FastAPI() + internal_router = APIRouter() + users_router = APIRouter() + + @users_router.get("/users/") + def read_users(): + return [{"name": "Rick"}, {"name": "Morty"}] + + internal_router.include_router(users_router) + app.include_router(internal_router) + ``` + """ + if prefix: + assert prefix.startswith("/"), "A path prefix must start with '/'" + assert not prefix.endswith( + "/" + ), "A path prefix must not end with '/', as the routes will start with '/'" + else: + for r in router.routes: + path = getattr(r, "path") # noqa: B009 + name = getattr(r, "name", "unknown") + if path is not None and not path: + raise FastAPIError( + f"Prefix and path cannot be both empty (path operation: {name})" + ) + if responses is None: + responses = {} + for route in router.routes: + if isinstance(route, APIRoute): + combined_responses = {**responses, **route.responses} + use_response_class = get_value_or_default( + route.response_class, + router.default_response_class, + default_response_class, + self.default_response_class, + ) + current_tags = [] + if tags: + current_tags.extend(tags) + if route.tags: + current_tags.extend(route.tags) + current_dependencies: List[params.Depends] = [] + if dependencies: + current_dependencies.extend(dependencies) + if route.dependencies: + current_dependencies.extend(route.dependencies) + current_callbacks = [] + if callbacks: + current_callbacks.extend(callbacks) + if route.callbacks: + current_callbacks.extend(route.callbacks) + current_generate_unique_id = get_value_or_default( + route.generate_unique_id_function, + router.generate_unique_id_function, + generate_unique_id_function, + self.generate_unique_id_function, + ) + self.add_api_route( + prefix + route.path, + route.endpoint, + response_model=route.response_model, + status_code=route.status_code, + tags=current_tags, + dependencies=current_dependencies, + summary=route.summary, + description=route.description, + response_description=route.response_description, + responses=combined_responses, + deprecated=route.deprecated or deprecated or self.deprecated, + methods=route.methods, + operation_id=route.operation_id, + response_model_include=route.response_model_include, + response_model_exclude=route.response_model_exclude, + response_model_by_alias=route.response_model_by_alias, + response_model_exclude_unset=route.response_model_exclude_unset, + response_model_exclude_defaults=route.response_model_exclude_defaults, + response_model_exclude_none=route.response_model_exclude_none, + include_in_schema=route.include_in_schema + and self.include_in_schema + and include_in_schema, + response_class=use_response_class, + name=route.name, + route_class_override=type(route), + callbacks=current_callbacks, + openapi_extra=route.openapi_extra, + generate_unique_id_function=current_generate_unique_id, + ) + elif isinstance(route, routing.Route): + methods = list(route.methods or []) + self.add_route( + prefix + route.path, + route.endpoint, + methods=methods, + include_in_schema=route.include_in_schema, + name=route.name, + ) + elif isinstance(route, APIWebSocketRoute): + current_dependencies = [] + if dependencies: + current_dependencies.extend(dependencies) + if route.dependencies: + current_dependencies.extend(route.dependencies) + self.add_api_websocket_route( + prefix + route.path, + route.endpoint, + dependencies=current_dependencies, + name=route.name, + ) + elif isinstance(route, routing.WebSocketRoute): + self.add_websocket_route( + prefix + route.path, route.endpoint, name=route.name + ) + for handler in router.on_startup: + self.add_event_handler("startup", handler) + for handler in router.on_shutdown: + self.add_event_handler("shutdown", handler) + self.lifespan_context = _merge_lifespan_context( + self.lifespan_context, + router.lifespan_context, + ) + + def get( + self, + path: Annotated[ + str, + Doc( + """ + The URL path to be used for this *path operation*. + + For example, in `http://example.com/items`, the path is `/items`. + """ + ), + ], + *, + response_model: Annotated[ + Any, + Doc( + """ + The type to use for the response. + + It could be any valid Pydantic *field* type. So, it doesn't have to + be a Pydantic model, it could be other things, like a `list`, `dict`, + etc. + + It will be used for: + + * Documentation: the generated OpenAPI (and the UI at `/docs`) will + show it as the response (JSON Schema). + * Serialization: you could return an arbitrary object and the + `response_model` would be used to serialize that object into the + corresponding JSON. + * Filtering: the JSON sent to the client will only contain the data + (fields) defined in the `response_model`. If you returned an object + that contains an attribute `password` but the `response_model` does + not include that field, the JSON sent to the client would not have + that `password`. + * Validation: whatever you return will be serialized with the + `response_model`, converting any data as necessary to generate the + corresponding JSON. But if the data in the object returned is not + valid, that would mean a violation of the contract with the client, + so it's an error from the API developer. So, FastAPI will raise an + error and return a 500 error code (Internal Server Error). + + Read more about it in the + [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). + """ + ), + ] = Default(None), + status_code: Annotated[ + Optional[int], + Doc( + """ + The default status code to be used for the response. + + You could override the status code by returning a response directly. + + Read more about it in the + [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). + """ + ), + ] = None, + tags: Annotated[ + Optional[List[Union[str, Enum]]], + Doc( + """ + A list of tags to be applied to the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). + """ + ), + ] = None, + dependencies: Annotated[ + Optional[Sequence[params.Depends]], + Doc( + """ + A list of dependencies (using `Depends()`) to be applied to the + *path operation*. + + Read more about it in the + [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). + """ + ), + ] = None, + summary: Annotated[ + Optional[str], + Doc( + """ + A summary for the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + A description for the *path operation*. + + If not provided, it will be extracted automatically from the docstring + of the *path operation function*. + + It can contain Markdown. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + response_description: Annotated[ + str, + Doc( + """ + The description for the default response. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = "Successful Response", + responses: Annotated[ + Optional[Dict[Union[int, str], Dict[str, Any]]], + Doc( + """ + Additional responses that could be returned by this *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + deprecated: Annotated[ + Optional[bool], + Doc( + """ + Mark this *path operation* as deprecated. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + operation_id: Annotated[ + Optional[str], + Doc( + """ + Custom operation ID to be used by this *path operation*. + + By default, it is generated automatically. + + If you provide a custom operation ID, you need to make sure it is + unique for the whole API. + + You can customize the + operation ID generation with the parameter + `generate_unique_id_function` in the `FastAPI` class. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = None, + response_model_include: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to include only certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_exclude: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to exclude certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_by_alias: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response model + should be serialized by alias when an alias is used. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = True, + response_model_exclude_unset: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that were not set and + have their default values. This is different from + `response_model_exclude_defaults` in that if the fields are set, + they will be included in the response, even if the value is the same + as the default. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_defaults: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that have the same value + as the default. This is different from `response_model_exclude_unset` + in that if the fields are set but contain the same default values, + they will be excluded from the response. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_none: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data should + exclude fields set to `None`. + + This is much simpler (less smart) than `response_model_exclude_unset` + and `response_model_exclude_defaults`. You probably want to use one of + those two instead of this one, as those allow returning `None` values + when it makes sense. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). + """ + ), + ] = False, + include_in_schema: Annotated[ + bool, + Doc( + """ + Include this *path operation* in the generated OpenAPI schema. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + """ + ), + ] = True, + response_class: Annotated[ + Type[Response], + Doc( + """ + Response class to be used for this *path operation*. + + This will not be used if you return a response directly. + + Read more about it in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). + """ + ), + ] = Default(JSONResponse), + name: Annotated[ + Optional[str], + Doc( + """ + Name for this *path operation*. Only used internally. + """ + ), + ] = None, + callbacks: Annotated[ + Optional[List[BaseRoute]], + Doc( + """ + List of *path operations* that will be used as OpenAPI callbacks. + + This is only for OpenAPI documentation, the callbacks won't be used + directly. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). + """ + ), + ] = None, + openapi_extra: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + Extra metadata to be included in the OpenAPI schema for this *path + operation*. + + Read more about it in the + [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). + """ + ), + ] = None, + generate_unique_id_function: Annotated[ + Callable[[APIRoute], str], + Doc( + """ + Customize the function used to generate unique IDs for the *path + operations* shown in the generated OpenAPI. + + This is particularly useful when automatically generating clients or + SDKs for your API. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = Default(generate_unique_id), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Add a *path operation* using an HTTP GET operation. + + ## Example + + ```python + from fastapi import APIRouter, FastAPI + + app = FastAPI() + router = APIRouter() + + @router.get("/items/") + def read_items(): + return [{"name": "Empanada"}, {"name": "Arepa"}] + + app.include_router(router) + ``` + """ + return self.api_route( + path=path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + methods=["GET"], + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def put( + self, + path: Annotated[ + str, + Doc( + """ + The URL path to be used for this *path operation*. + + For example, in `http://example.com/items`, the path is `/items`. + """ + ), + ], + *, + response_model: Annotated[ + Any, + Doc( + """ + The type to use for the response. + + It could be any valid Pydantic *field* type. So, it doesn't have to + be a Pydantic model, it could be other things, like a `list`, `dict`, + etc. + + It will be used for: + + * Documentation: the generated OpenAPI (and the UI at `/docs`) will + show it as the response (JSON Schema). + * Serialization: you could return an arbitrary object and the + `response_model` would be used to serialize that object into the + corresponding JSON. + * Filtering: the JSON sent to the client will only contain the data + (fields) defined in the `response_model`. If you returned an object + that contains an attribute `password` but the `response_model` does + not include that field, the JSON sent to the client would not have + that `password`. + * Validation: whatever you return will be serialized with the + `response_model`, converting any data as necessary to generate the + corresponding JSON. But if the data in the object returned is not + valid, that would mean a violation of the contract with the client, + so it's an error from the API developer. So, FastAPI will raise an + error and return a 500 error code (Internal Server Error). + + Read more about it in the + [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). + """ + ), + ] = Default(None), + status_code: Annotated[ + Optional[int], + Doc( + """ + The default status code to be used for the response. + + You could override the status code by returning a response directly. + + Read more about it in the + [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). + """ + ), + ] = None, + tags: Annotated[ + Optional[List[Union[str, Enum]]], + Doc( + """ + A list of tags to be applied to the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). + """ + ), + ] = None, + dependencies: Annotated[ + Optional[Sequence[params.Depends]], + Doc( + """ + A list of dependencies (using `Depends()`) to be applied to the + *path operation*. + + Read more about it in the + [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). + """ + ), + ] = None, + summary: Annotated[ + Optional[str], + Doc( + """ + A summary for the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + A description for the *path operation*. + + If not provided, it will be extracted automatically from the docstring + of the *path operation function*. + + It can contain Markdown. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + response_description: Annotated[ + str, + Doc( + """ + The description for the default response. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = "Successful Response", + responses: Annotated[ + Optional[Dict[Union[int, str], Dict[str, Any]]], + Doc( + """ + Additional responses that could be returned by this *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + deprecated: Annotated[ + Optional[bool], + Doc( + """ + Mark this *path operation* as deprecated. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + operation_id: Annotated[ + Optional[str], + Doc( + """ + Custom operation ID to be used by this *path operation*. + + By default, it is generated automatically. + + If you provide a custom operation ID, you need to make sure it is + unique for the whole API. + + You can customize the + operation ID generation with the parameter + `generate_unique_id_function` in the `FastAPI` class. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = None, + response_model_include: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to include only certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_exclude: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to exclude certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_by_alias: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response model + should be serialized by alias when an alias is used. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = True, + response_model_exclude_unset: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that were not set and + have their default values. This is different from + `response_model_exclude_defaults` in that if the fields are set, + they will be included in the response, even if the value is the same + as the default. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_defaults: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that have the same value + as the default. This is different from `response_model_exclude_unset` + in that if the fields are set but contain the same default values, + they will be excluded from the response. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_none: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data should + exclude fields set to `None`. + + This is much simpler (less smart) than `response_model_exclude_unset` + and `response_model_exclude_defaults`. You probably want to use one of + those two instead of this one, as those allow returning `None` values + when it makes sense. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). + """ + ), + ] = False, + include_in_schema: Annotated[ + bool, + Doc( + """ + Include this *path operation* in the generated OpenAPI schema. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + """ + ), + ] = True, + response_class: Annotated[ + Type[Response], + Doc( + """ + Response class to be used for this *path operation*. + + This will not be used if you return a response directly. + + Read more about it in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). + """ + ), + ] = Default(JSONResponse), + name: Annotated[ + Optional[str], + Doc( + """ + Name for this *path operation*. Only used internally. + """ + ), + ] = None, + callbacks: Annotated[ + Optional[List[BaseRoute]], + Doc( + """ + List of *path operations* that will be used as OpenAPI callbacks. + + This is only for OpenAPI documentation, the callbacks won't be used + directly. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). + """ + ), + ] = None, + openapi_extra: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + Extra metadata to be included in the OpenAPI schema for this *path + operation*. + + Read more about it in the + [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). + """ + ), + ] = None, + generate_unique_id_function: Annotated[ + Callable[[APIRoute], str], + Doc( + """ + Customize the function used to generate unique IDs for the *path + operations* shown in the generated OpenAPI. + + This is particularly useful when automatically generating clients or + SDKs for your API. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = Default(generate_unique_id), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Add a *path operation* using an HTTP PUT operation. + + ## Example + + ```python + from fastapi import APIRouter, FastAPI + from pydantic import BaseModel + + class Item(BaseModel): + name: str + description: str | None = None + + app = FastAPI() + router = APIRouter() + + @router.put("/items/{item_id}") + def replace_item(item_id: str, item: Item): + return {"message": "Item replaced", "id": item_id} + + app.include_router(router) + ``` + """ + return self.api_route( + path=path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + methods=["PUT"], + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def post( + self, + path: Annotated[ + str, + Doc( + """ + The URL path to be used for this *path operation*. + + For example, in `http://example.com/items`, the path is `/items`. + """ + ), + ], + *, + response_model: Annotated[ + Any, + Doc( + """ + The type to use for the response. + + It could be any valid Pydantic *field* type. So, it doesn't have to + be a Pydantic model, it could be other things, like a `list`, `dict`, + etc. + + It will be used for: + + * Documentation: the generated OpenAPI (and the UI at `/docs`) will + show it as the response (JSON Schema). + * Serialization: you could return an arbitrary object and the + `response_model` would be used to serialize that object into the + corresponding JSON. + * Filtering: the JSON sent to the client will only contain the data + (fields) defined in the `response_model`. If you returned an object + that contains an attribute `password` but the `response_model` does + not include that field, the JSON sent to the client would not have + that `password`. + * Validation: whatever you return will be serialized with the + `response_model`, converting any data as necessary to generate the + corresponding JSON. But if the data in the object returned is not + valid, that would mean a violation of the contract with the client, + so it's an error from the API developer. So, FastAPI will raise an + error and return a 500 error code (Internal Server Error). + + Read more about it in the + [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). + """ + ), + ] = Default(None), + status_code: Annotated[ + Optional[int], + Doc( + """ + The default status code to be used for the response. + + You could override the status code by returning a response directly. + + Read more about it in the + [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). + """ + ), + ] = None, + tags: Annotated[ + Optional[List[Union[str, Enum]]], + Doc( + """ + A list of tags to be applied to the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). + """ + ), + ] = None, + dependencies: Annotated[ + Optional[Sequence[params.Depends]], + Doc( + """ + A list of dependencies (using `Depends()`) to be applied to the + *path operation*. + + Read more about it in the + [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). + """ + ), + ] = None, + summary: Annotated[ + Optional[str], + Doc( + """ + A summary for the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + A description for the *path operation*. + + If not provided, it will be extracted automatically from the docstring + of the *path operation function*. + + It can contain Markdown. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + response_description: Annotated[ + str, + Doc( + """ + The description for the default response. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = "Successful Response", + responses: Annotated[ + Optional[Dict[Union[int, str], Dict[str, Any]]], + Doc( + """ + Additional responses that could be returned by this *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + deprecated: Annotated[ + Optional[bool], + Doc( + """ + Mark this *path operation* as deprecated. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + operation_id: Annotated[ + Optional[str], + Doc( + """ + Custom operation ID to be used by this *path operation*. + + By default, it is generated automatically. + + If you provide a custom operation ID, you need to make sure it is + unique for the whole API. + + You can customize the + operation ID generation with the parameter + `generate_unique_id_function` in the `FastAPI` class. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = None, + response_model_include: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to include only certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_exclude: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to exclude certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_by_alias: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response model + should be serialized by alias when an alias is used. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = True, + response_model_exclude_unset: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that were not set and + have their default values. This is different from + `response_model_exclude_defaults` in that if the fields are set, + they will be included in the response, even if the value is the same + as the default. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_defaults: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that have the same value + as the default. This is different from `response_model_exclude_unset` + in that if the fields are set but contain the same default values, + they will be excluded from the response. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_none: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data should + exclude fields set to `None`. + + This is much simpler (less smart) than `response_model_exclude_unset` + and `response_model_exclude_defaults`. You probably want to use one of + those two instead of this one, as those allow returning `None` values + when it makes sense. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). + """ + ), + ] = False, + include_in_schema: Annotated[ + bool, + Doc( + """ + Include this *path operation* in the generated OpenAPI schema. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + """ + ), + ] = True, + response_class: Annotated[ + Type[Response], + Doc( + """ + Response class to be used for this *path operation*. + + This will not be used if you return a response directly. + + Read more about it in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). + """ + ), + ] = Default(JSONResponse), + name: Annotated[ + Optional[str], + Doc( + """ + Name for this *path operation*. Only used internally. + """ + ), + ] = None, + callbacks: Annotated[ + Optional[List[BaseRoute]], + Doc( + """ + List of *path operations* that will be used as OpenAPI callbacks. + + This is only for OpenAPI documentation, the callbacks won't be used + directly. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). + """ + ), + ] = None, + openapi_extra: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + Extra metadata to be included in the OpenAPI schema for this *path + operation*. + + Read more about it in the + [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). + """ + ), + ] = None, + generate_unique_id_function: Annotated[ + Callable[[APIRoute], str], + Doc( + """ + Customize the function used to generate unique IDs for the *path + operations* shown in the generated OpenAPI. + + This is particularly useful when automatically generating clients or + SDKs for your API. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = Default(generate_unique_id), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Add a *path operation* using an HTTP POST operation. + + ## Example + + ```python + from fastapi import APIRouter, FastAPI + from pydantic import BaseModel + + class Item(BaseModel): + name: str + description: str | None = None + + app = FastAPI() + router = APIRouter() + + @router.post("/items/") + def create_item(item: Item): + return {"message": "Item created"} + + app.include_router(router) + ``` + """ + return self.api_route( + path=path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + methods=["POST"], + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def delete( + self, + path: Annotated[ + str, + Doc( + """ + The URL path to be used for this *path operation*. + + For example, in `http://example.com/items`, the path is `/items`. + """ + ), + ], + *, + response_model: Annotated[ + Any, + Doc( + """ + The type to use for the response. + + It could be any valid Pydantic *field* type. So, it doesn't have to + be a Pydantic model, it could be other things, like a `list`, `dict`, + etc. + + It will be used for: + + * Documentation: the generated OpenAPI (and the UI at `/docs`) will + show it as the response (JSON Schema). + * Serialization: you could return an arbitrary object and the + `response_model` would be used to serialize that object into the + corresponding JSON. + * Filtering: the JSON sent to the client will only contain the data + (fields) defined in the `response_model`. If you returned an object + that contains an attribute `password` but the `response_model` does + not include that field, the JSON sent to the client would not have + that `password`. + * Validation: whatever you return will be serialized with the + `response_model`, converting any data as necessary to generate the + corresponding JSON. But if the data in the object returned is not + valid, that would mean a violation of the contract with the client, + so it's an error from the API developer. So, FastAPI will raise an + error and return a 500 error code (Internal Server Error). + + Read more about it in the + [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). + """ + ), + ] = Default(None), + status_code: Annotated[ + Optional[int], + Doc( + """ + The default status code to be used for the response. + + You could override the status code by returning a response directly. + + Read more about it in the + [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). + """ + ), + ] = None, + tags: Annotated[ + Optional[List[Union[str, Enum]]], + Doc( + """ + A list of tags to be applied to the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). + """ + ), + ] = None, + dependencies: Annotated[ + Optional[Sequence[params.Depends]], + Doc( + """ + A list of dependencies (using `Depends()`) to be applied to the + *path operation*. + + Read more about it in the + [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). + """ + ), + ] = None, + summary: Annotated[ + Optional[str], + Doc( + """ + A summary for the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + A description for the *path operation*. + + If not provided, it will be extracted automatically from the docstring + of the *path operation function*. + + It can contain Markdown. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + response_description: Annotated[ + str, + Doc( + """ + The description for the default response. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = "Successful Response", + responses: Annotated[ + Optional[Dict[Union[int, str], Dict[str, Any]]], + Doc( + """ + Additional responses that could be returned by this *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + deprecated: Annotated[ + Optional[bool], + Doc( + """ + Mark this *path operation* as deprecated. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + operation_id: Annotated[ + Optional[str], + Doc( + """ + Custom operation ID to be used by this *path operation*. + + By default, it is generated automatically. + + If you provide a custom operation ID, you need to make sure it is + unique for the whole API. + + You can customize the + operation ID generation with the parameter + `generate_unique_id_function` in the `FastAPI` class. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = None, + response_model_include: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to include only certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_exclude: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to exclude certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_by_alias: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response model + should be serialized by alias when an alias is used. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = True, + response_model_exclude_unset: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that were not set and + have their default values. This is different from + `response_model_exclude_defaults` in that if the fields are set, + they will be included in the response, even if the value is the same + as the default. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_defaults: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that have the same value + as the default. This is different from `response_model_exclude_unset` + in that if the fields are set but contain the same default values, + they will be excluded from the response. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_none: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data should + exclude fields set to `None`. + + This is much simpler (less smart) than `response_model_exclude_unset` + and `response_model_exclude_defaults`. You probably want to use one of + those two instead of this one, as those allow returning `None` values + when it makes sense. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). + """ + ), + ] = False, + include_in_schema: Annotated[ + bool, + Doc( + """ + Include this *path operation* in the generated OpenAPI schema. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + """ + ), + ] = True, + response_class: Annotated[ + Type[Response], + Doc( + """ + Response class to be used for this *path operation*. + + This will not be used if you return a response directly. + + Read more about it in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). + """ + ), + ] = Default(JSONResponse), + name: Annotated[ + Optional[str], + Doc( + """ + Name for this *path operation*. Only used internally. + """ + ), + ] = None, + callbacks: Annotated[ + Optional[List[BaseRoute]], + Doc( + """ + List of *path operations* that will be used as OpenAPI callbacks. + + This is only for OpenAPI documentation, the callbacks won't be used + directly. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). + """ + ), + ] = None, + openapi_extra: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + Extra metadata to be included in the OpenAPI schema for this *path + operation*. + + Read more about it in the + [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). + """ + ), + ] = None, + generate_unique_id_function: Annotated[ + Callable[[APIRoute], str], + Doc( + """ + Customize the function used to generate unique IDs for the *path + operations* shown in the generated OpenAPI. + + This is particularly useful when automatically generating clients or + SDKs for your API. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = Default(generate_unique_id), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Add a *path operation* using an HTTP DELETE operation. + + ## Example + + ```python + from fastapi import APIRouter, FastAPI + + app = FastAPI() + router = APIRouter() + + @router.delete("/items/{item_id}") + def delete_item(item_id: str): + return {"message": "Item deleted"} + + app.include_router(router) + ``` + """ + return self.api_route( + path=path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + methods=["DELETE"], + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def options( + self, + path: Annotated[ + str, + Doc( + """ + The URL path to be used for this *path operation*. + + For example, in `http://example.com/items`, the path is `/items`. + """ + ), + ], + *, + response_model: Annotated[ + Any, + Doc( + """ + The type to use for the response. + + It could be any valid Pydantic *field* type. So, it doesn't have to + be a Pydantic model, it could be other things, like a `list`, `dict`, + etc. + + It will be used for: + + * Documentation: the generated OpenAPI (and the UI at `/docs`) will + show it as the response (JSON Schema). + * Serialization: you could return an arbitrary object and the + `response_model` would be used to serialize that object into the + corresponding JSON. + * Filtering: the JSON sent to the client will only contain the data + (fields) defined in the `response_model`. If you returned an object + that contains an attribute `password` but the `response_model` does + not include that field, the JSON sent to the client would not have + that `password`. + * Validation: whatever you return will be serialized with the + `response_model`, converting any data as necessary to generate the + corresponding JSON. But if the data in the object returned is not + valid, that would mean a violation of the contract with the client, + so it's an error from the API developer. So, FastAPI will raise an + error and return a 500 error code (Internal Server Error). + + Read more about it in the + [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). + """ + ), + ] = Default(None), + status_code: Annotated[ + Optional[int], + Doc( + """ + The default status code to be used for the response. + + You could override the status code by returning a response directly. + + Read more about it in the + [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). + """ + ), + ] = None, + tags: Annotated[ + Optional[List[Union[str, Enum]]], + Doc( + """ + A list of tags to be applied to the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). + """ + ), + ] = None, + dependencies: Annotated[ + Optional[Sequence[params.Depends]], + Doc( + """ + A list of dependencies (using `Depends()`) to be applied to the + *path operation*. + + Read more about it in the + [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). + """ + ), + ] = None, + summary: Annotated[ + Optional[str], + Doc( + """ + A summary for the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + A description for the *path operation*. + + If not provided, it will be extracted automatically from the docstring + of the *path operation function*. + + It can contain Markdown. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + response_description: Annotated[ + str, + Doc( + """ + The description for the default response. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = "Successful Response", + responses: Annotated[ + Optional[Dict[Union[int, str], Dict[str, Any]]], + Doc( + """ + Additional responses that could be returned by this *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + deprecated: Annotated[ + Optional[bool], + Doc( + """ + Mark this *path operation* as deprecated. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + operation_id: Annotated[ + Optional[str], + Doc( + """ + Custom operation ID to be used by this *path operation*. + + By default, it is generated automatically. + + If you provide a custom operation ID, you need to make sure it is + unique for the whole API. + + You can customize the + operation ID generation with the parameter + `generate_unique_id_function` in the `FastAPI` class. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = None, + response_model_include: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to include only certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_exclude: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to exclude certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_by_alias: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response model + should be serialized by alias when an alias is used. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = True, + response_model_exclude_unset: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that were not set and + have their default values. This is different from + `response_model_exclude_defaults` in that if the fields are set, + they will be included in the response, even if the value is the same + as the default. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_defaults: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that have the same value + as the default. This is different from `response_model_exclude_unset` + in that if the fields are set but contain the same default values, + they will be excluded from the response. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_none: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data should + exclude fields set to `None`. + + This is much simpler (less smart) than `response_model_exclude_unset` + and `response_model_exclude_defaults`. You probably want to use one of + those two instead of this one, as those allow returning `None` values + when it makes sense. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). + """ + ), + ] = False, + include_in_schema: Annotated[ + bool, + Doc( + """ + Include this *path operation* in the generated OpenAPI schema. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + """ + ), + ] = True, + response_class: Annotated[ + Type[Response], + Doc( + """ + Response class to be used for this *path operation*. + + This will not be used if you return a response directly. + + Read more about it in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). + """ + ), + ] = Default(JSONResponse), + name: Annotated[ + Optional[str], + Doc( + """ + Name for this *path operation*. Only used internally. + """ + ), + ] = None, + callbacks: Annotated[ + Optional[List[BaseRoute]], + Doc( + """ + List of *path operations* that will be used as OpenAPI callbacks. + + This is only for OpenAPI documentation, the callbacks won't be used + directly. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). + """ + ), + ] = None, + openapi_extra: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + Extra metadata to be included in the OpenAPI schema for this *path + operation*. + + Read more about it in the + [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). + """ + ), + ] = None, + generate_unique_id_function: Annotated[ + Callable[[APIRoute], str], + Doc( + """ + Customize the function used to generate unique IDs for the *path + operations* shown in the generated OpenAPI. + + This is particularly useful when automatically generating clients or + SDKs for your API. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = Default(generate_unique_id), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Add a *path operation* using an HTTP OPTIONS operation. + + ## Example + + ```python + from fastapi import APIRouter, FastAPI + + app = FastAPI() + router = APIRouter() + + @router.options("/items/") + def get_item_options(): + return {"additions": ["Aji", "Guacamole"]} + + app.include_router(router) + ``` + """ + return self.api_route( + path=path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + methods=["OPTIONS"], + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def head( + self, + path: Annotated[ + str, + Doc( + """ + The URL path to be used for this *path operation*. + + For example, in `http://example.com/items`, the path is `/items`. + """ + ), + ], + *, + response_model: Annotated[ + Any, + Doc( + """ + The type to use for the response. + + It could be any valid Pydantic *field* type. So, it doesn't have to + be a Pydantic model, it could be other things, like a `list`, `dict`, + etc. + + It will be used for: + + * Documentation: the generated OpenAPI (and the UI at `/docs`) will + show it as the response (JSON Schema). + * Serialization: you could return an arbitrary object and the + `response_model` would be used to serialize that object into the + corresponding JSON. + * Filtering: the JSON sent to the client will only contain the data + (fields) defined in the `response_model`. If you returned an object + that contains an attribute `password` but the `response_model` does + not include that field, the JSON sent to the client would not have + that `password`. + * Validation: whatever you return will be serialized with the + `response_model`, converting any data as necessary to generate the + corresponding JSON. But if the data in the object returned is not + valid, that would mean a violation of the contract with the client, + so it's an error from the API developer. So, FastAPI will raise an + error and return a 500 error code (Internal Server Error). + + Read more about it in the + [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). + """ + ), + ] = Default(None), + status_code: Annotated[ + Optional[int], + Doc( + """ + The default status code to be used for the response. + + You could override the status code by returning a response directly. + + Read more about it in the + [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). + """ + ), + ] = None, + tags: Annotated[ + Optional[List[Union[str, Enum]]], + Doc( + """ + A list of tags to be applied to the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). + """ + ), + ] = None, + dependencies: Annotated[ + Optional[Sequence[params.Depends]], + Doc( + """ + A list of dependencies (using `Depends()`) to be applied to the + *path operation*. + + Read more about it in the + [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). + """ + ), + ] = None, + summary: Annotated[ + Optional[str], + Doc( + """ + A summary for the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + A description for the *path operation*. + + If not provided, it will be extracted automatically from the docstring + of the *path operation function*. + + It can contain Markdown. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + response_description: Annotated[ + str, + Doc( + """ + The description for the default response. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = "Successful Response", + responses: Annotated[ + Optional[Dict[Union[int, str], Dict[str, Any]]], + Doc( + """ + Additional responses that could be returned by this *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + deprecated: Annotated[ + Optional[bool], + Doc( + """ + Mark this *path operation* as deprecated. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + operation_id: Annotated[ + Optional[str], + Doc( + """ + Custom operation ID to be used by this *path operation*. + + By default, it is generated automatically. + + If you provide a custom operation ID, you need to make sure it is + unique for the whole API. + + You can customize the + operation ID generation with the parameter + `generate_unique_id_function` in the `FastAPI` class. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = None, + response_model_include: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to include only certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_exclude: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to exclude certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_by_alias: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response model + should be serialized by alias when an alias is used. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = True, + response_model_exclude_unset: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that were not set and + have their default values. This is different from + `response_model_exclude_defaults` in that if the fields are set, + they will be included in the response, even if the value is the same + as the default. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_defaults: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that have the same value + as the default. This is different from `response_model_exclude_unset` + in that if the fields are set but contain the same default values, + they will be excluded from the response. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_none: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data should + exclude fields set to `None`. + + This is much simpler (less smart) than `response_model_exclude_unset` + and `response_model_exclude_defaults`. You probably want to use one of + those two instead of this one, as those allow returning `None` values + when it makes sense. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). + """ + ), + ] = False, + include_in_schema: Annotated[ + bool, + Doc( + """ + Include this *path operation* in the generated OpenAPI schema. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + """ + ), + ] = True, + response_class: Annotated[ + Type[Response], + Doc( + """ + Response class to be used for this *path operation*. + + This will not be used if you return a response directly. + + Read more about it in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). + """ + ), + ] = Default(JSONResponse), + name: Annotated[ + Optional[str], + Doc( + """ + Name for this *path operation*. Only used internally. + """ + ), + ] = None, + callbacks: Annotated[ + Optional[List[BaseRoute]], + Doc( + """ + List of *path operations* that will be used as OpenAPI callbacks. + + This is only for OpenAPI documentation, the callbacks won't be used + directly. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). + """ + ), + ] = None, + openapi_extra: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + Extra metadata to be included in the OpenAPI schema for this *path + operation*. + + Read more about it in the + [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). + """ + ), + ] = None, + generate_unique_id_function: Annotated[ + Callable[[APIRoute], str], + Doc( + """ + Customize the function used to generate unique IDs for the *path + operations* shown in the generated OpenAPI. + + This is particularly useful when automatically generating clients or + SDKs for your API. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = Default(generate_unique_id), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Add a *path operation* using an HTTP HEAD operation. + + ## Example + + ```python + from fastapi import APIRouter, FastAPI + from pydantic import BaseModel + + class Item(BaseModel): + name: str + description: str | None = None + + app = FastAPI() + router = APIRouter() + + @router.head("/items/", status_code=204) + def get_items_headers(response: Response): + response.headers["X-Cat-Dog"] = "Alone in the world" + + app.include_router(router) + ``` + """ + return self.api_route( + path=path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + methods=["HEAD"], + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def patch( + self, + path: Annotated[ + str, + Doc( + """ + The URL path to be used for this *path operation*. + + For example, in `http://example.com/items`, the path is `/items`. + """ + ), + ], + *, + response_model: Annotated[ + Any, + Doc( + """ + The type to use for the response. + + It could be any valid Pydantic *field* type. So, it doesn't have to + be a Pydantic model, it could be other things, like a `list`, `dict`, + etc. + + It will be used for: + + * Documentation: the generated OpenAPI (and the UI at `/docs`) will + show it as the response (JSON Schema). + * Serialization: you could return an arbitrary object and the + `response_model` would be used to serialize that object into the + corresponding JSON. + * Filtering: the JSON sent to the client will only contain the data + (fields) defined in the `response_model`. If you returned an object + that contains an attribute `password` but the `response_model` does + not include that field, the JSON sent to the client would not have + that `password`. + * Validation: whatever you return will be serialized with the + `response_model`, converting any data as necessary to generate the + corresponding JSON. But if the data in the object returned is not + valid, that would mean a violation of the contract with the client, + so it's an error from the API developer. So, FastAPI will raise an + error and return a 500 error code (Internal Server Error). + + Read more about it in the + [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). + """ + ), + ] = Default(None), + status_code: Annotated[ + Optional[int], + Doc( + """ + The default status code to be used for the response. + + You could override the status code by returning a response directly. + + Read more about it in the + [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). + """ + ), + ] = None, + tags: Annotated[ + Optional[List[Union[str, Enum]]], + Doc( + """ + A list of tags to be applied to the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). + """ + ), + ] = None, + dependencies: Annotated[ + Optional[Sequence[params.Depends]], + Doc( + """ + A list of dependencies (using `Depends()`) to be applied to the + *path operation*. + + Read more about it in the + [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). + """ + ), + ] = None, + summary: Annotated[ + Optional[str], + Doc( + """ + A summary for the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + A description for the *path operation*. + + If not provided, it will be extracted automatically from the docstring + of the *path operation function*. + + It can contain Markdown. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + response_description: Annotated[ + str, + Doc( + """ + The description for the default response. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = "Successful Response", + responses: Annotated[ + Optional[Dict[Union[int, str], Dict[str, Any]]], + Doc( + """ + Additional responses that could be returned by this *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + deprecated: Annotated[ + Optional[bool], + Doc( + """ + Mark this *path operation* as deprecated. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + operation_id: Annotated[ + Optional[str], + Doc( + """ + Custom operation ID to be used by this *path operation*. + + By default, it is generated automatically. + + If you provide a custom operation ID, you need to make sure it is + unique for the whole API. + + You can customize the + operation ID generation with the parameter + `generate_unique_id_function` in the `FastAPI` class. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = None, + response_model_include: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to include only certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_exclude: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to exclude certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_by_alias: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response model + should be serialized by alias when an alias is used. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = True, + response_model_exclude_unset: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that were not set and + have their default values. This is different from + `response_model_exclude_defaults` in that if the fields are set, + they will be included in the response, even if the value is the same + as the default. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_defaults: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that have the same value + as the default. This is different from `response_model_exclude_unset` + in that if the fields are set but contain the same default values, + they will be excluded from the response. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_none: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data should + exclude fields set to `None`. + + This is much simpler (less smart) than `response_model_exclude_unset` + and `response_model_exclude_defaults`. You probably want to use one of + those two instead of this one, as those allow returning `None` values + when it makes sense. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). + """ + ), + ] = False, + include_in_schema: Annotated[ + bool, + Doc( + """ + Include this *path operation* in the generated OpenAPI schema. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + """ + ), + ] = True, + response_class: Annotated[ + Type[Response], + Doc( + """ + Response class to be used for this *path operation*. + + This will not be used if you return a response directly. + + Read more about it in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). + """ + ), + ] = Default(JSONResponse), + name: Annotated[ + Optional[str], + Doc( + """ + Name for this *path operation*. Only used internally. + """ + ), + ] = None, + callbacks: Annotated[ + Optional[List[BaseRoute]], + Doc( + """ + List of *path operations* that will be used as OpenAPI callbacks. + + This is only for OpenAPI documentation, the callbacks won't be used + directly. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). + """ + ), + ] = None, + openapi_extra: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + Extra metadata to be included in the OpenAPI schema for this *path + operation*. + + Read more about it in the + [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). + """ + ), + ] = None, + generate_unique_id_function: Annotated[ + Callable[[APIRoute], str], + Doc( + """ + Customize the function used to generate unique IDs for the *path + operations* shown in the generated OpenAPI. + + This is particularly useful when automatically generating clients or + SDKs for your API. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = Default(generate_unique_id), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Add a *path operation* using an HTTP PATCH operation. + + ## Example + + ```python + from fastapi import APIRouter, FastAPI + from pydantic import BaseModel + + class Item(BaseModel): + name: str + description: str | None = None + + app = FastAPI() + router = APIRouter() + + @router.patch("/items/") + def update_item(item: Item): + return {"message": "Item updated in place"} + + app.include_router(router) + ``` + """ + return self.api_route( + path=path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + methods=["PATCH"], + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def trace( + self, + path: Annotated[ + str, + Doc( + """ + The URL path to be used for this *path operation*. + + For example, in `http://example.com/items`, the path is `/items`. + """ + ), + ], + *, + response_model: Annotated[ + Any, + Doc( + """ + The type to use for the response. + + It could be any valid Pydantic *field* type. So, it doesn't have to + be a Pydantic model, it could be other things, like a `list`, `dict`, + etc. + + It will be used for: + + * Documentation: the generated OpenAPI (and the UI at `/docs`) will + show it as the response (JSON Schema). + * Serialization: you could return an arbitrary object and the + `response_model` would be used to serialize that object into the + corresponding JSON. + * Filtering: the JSON sent to the client will only contain the data + (fields) defined in the `response_model`. If you returned an object + that contains an attribute `password` but the `response_model` does + not include that field, the JSON sent to the client would not have + that `password`. + * Validation: whatever you return will be serialized with the + `response_model`, converting any data as necessary to generate the + corresponding JSON. But if the data in the object returned is not + valid, that would mean a violation of the contract with the client, + so it's an error from the API developer. So, FastAPI will raise an + error and return a 500 error code (Internal Server Error). + + Read more about it in the + [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). + """ + ), + ] = Default(None), + status_code: Annotated[ + Optional[int], + Doc( + """ + The default status code to be used for the response. + + You could override the status code by returning a response directly. + + Read more about it in the + [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). + """ + ), + ] = None, + tags: Annotated[ + Optional[List[Union[str, Enum]]], + Doc( + """ + A list of tags to be applied to the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). + """ + ), + ] = None, + dependencies: Annotated[ + Optional[Sequence[params.Depends]], + Doc( + """ + A list of dependencies (using `Depends()`) to be applied to the + *path operation*. + + Read more about it in the + [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). + """ + ), + ] = None, + summary: Annotated[ + Optional[str], + Doc( + """ + A summary for the *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + A description for the *path operation*. + + If not provided, it will be extracted automatically from the docstring + of the *path operation function*. + + It can contain Markdown. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + response_description: Annotated[ + str, + Doc( + """ + The description for the default response. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = "Successful Response", + responses: Annotated[ + Optional[Dict[Union[int, str], Dict[str, Any]]], + Doc( + """ + Additional responses that could be returned by this *path operation*. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + deprecated: Annotated[ + Optional[bool], + Doc( + """ + Mark this *path operation* as deprecated. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + operation_id: Annotated[ + Optional[str], + Doc( + """ + Custom operation ID to be used by this *path operation*. + + By default, it is generated automatically. + + If you provide a custom operation ID, you need to make sure it is + unique for the whole API. + + You can customize the + operation ID generation with the parameter + `generate_unique_id_function` in the `FastAPI` class. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = None, + response_model_include: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to include only certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_exclude: Annotated[ + Optional[IncEx], + Doc( + """ + Configuration passed to Pydantic to exclude certain fields in the + response data. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = None, + response_model_by_alias: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response model + should be serialized by alias when an alias is used. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). + """ + ), + ] = True, + response_model_exclude_unset: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that were not set and + have their default values. This is different from + `response_model_exclude_defaults` in that if the fields are set, + they will be included in the response, even if the value is the same + as the default. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_defaults: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data + should have all the fields, including the ones that have the same value + as the default. This is different from `response_model_exclude_unset` + in that if the fields are set but contain the same default values, + they will be excluded from the response. + + When `True`, default values are omitted from the response. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). + """ + ), + ] = False, + response_model_exclude_none: Annotated[ + bool, + Doc( + """ + Configuration passed to Pydantic to define if the response data should + exclude fields set to `None`. + + This is much simpler (less smart) than `response_model_exclude_unset` + and `response_model_exclude_defaults`. You probably want to use one of + those two instead of this one, as those allow returning `None` values + when it makes sense. + + Read more about it in the + [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). + """ + ), + ] = False, + include_in_schema: Annotated[ + bool, + Doc( + """ + Include this *path operation* in the generated OpenAPI schema. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + """ + ), + ] = True, + response_class: Annotated[ + Type[Response], + Doc( + """ + Response class to be used for this *path operation*. + + This will not be used if you return a response directly. + + Read more about it in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). + """ + ), + ] = Default(JSONResponse), + name: Annotated[ + Optional[str], + Doc( + """ + Name for this *path operation*. Only used internally. + """ + ), + ] = None, + callbacks: Annotated[ + Optional[List[BaseRoute]], + Doc( + """ + List of *path operations* that will be used as OpenAPI callbacks. + + This is only for OpenAPI documentation, the callbacks won't be used + directly. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). + """ + ), + ] = None, + openapi_extra: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + Extra metadata to be included in the OpenAPI schema for this *path + operation*. + + Read more about it in the + [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). + """ + ), + ] = None, + generate_unique_id_function: Annotated[ + Callable[[APIRoute], str], + Doc( + """ + Customize the function used to generate unique IDs for the *path + operations* shown in the generated OpenAPI. + + This is particularly useful when automatically generating clients or + SDKs for your API. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = Default(generate_unique_id), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Add a *path operation* using an HTTP TRACE operation. + + ## Example + + ```python + from fastapi import APIRouter, FastAPI + from pydantic import BaseModel + + class Item(BaseModel): + name: str + description: str | None = None + + app = FastAPI() + router = APIRouter() + + @router.trace("/items/{item_id}") + def trace_item(item_id: str): + return None + + app.include_router(router) + ``` + """ + return self.api_route( + path=path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + methods=["TRACE"], + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + @deprecated( + """ + on_event is deprecated, use lifespan event handlers instead. + + Read more about it in the + [FastAPI docs for Lifespan Events](https://fastapi.tiangolo.com/advanced/events/). + """ + ) + def on_event( + self, + event_type: Annotated[ + str, + Doc( + """ + The type of event. `startup` or `shutdown`. + """ + ), + ], + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Add an event handler for the router. + + `on_event` is deprecated, use `lifespan` event handlers instead. + + Read more about it in the + [FastAPI docs for Lifespan Events](https://fastapi.tiangolo.com/advanced/events/#alternative-events-deprecated). + """ + + def decorator(func: DecoratedCallable) -> DecoratedCallable: + self.add_event_handler(event_type, func) + return func + + return decorator diff --git a/backend/.venv/Lib/site-packages/fastapi/security/__init__.py b/backend/.venv/Lib/site-packages/fastapi/security/__init__.py new file mode 100644 index 0000000..3aa6bf2 --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/security/__init__.py @@ -0,0 +1,15 @@ +from .api_key import APIKeyCookie as APIKeyCookie +from .api_key import APIKeyHeader as APIKeyHeader +from .api_key import APIKeyQuery as APIKeyQuery +from .http import HTTPAuthorizationCredentials as HTTPAuthorizationCredentials +from .http import HTTPBasic as HTTPBasic +from .http import HTTPBasicCredentials as HTTPBasicCredentials +from .http import HTTPBearer as HTTPBearer +from .http import HTTPDigest as HTTPDigest +from .oauth2 import OAuth2 as OAuth2 +from .oauth2 import OAuth2AuthorizationCodeBearer as OAuth2AuthorizationCodeBearer +from .oauth2 import OAuth2PasswordBearer as OAuth2PasswordBearer +from .oauth2 import OAuth2PasswordRequestForm as OAuth2PasswordRequestForm +from .oauth2 import OAuth2PasswordRequestFormStrict as OAuth2PasswordRequestFormStrict +from .oauth2 import SecurityScopes as SecurityScopes +from .open_id_connect_url import OpenIdConnect as OpenIdConnect diff --git a/backend/.venv/Lib/site-packages/fastapi/security/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/security/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fb853f7def8034712127bb069ff5dd2defa46fea GIT binary patch literal 847 zcmZ{i%Wl*#6o#F-By-DL+DfPrhz$z{X*y!W3PGVAgjzuD(5YBh5s~Yd)=Uzoj#Cs~ zglFIlcn97fQrNI!htwS_jy-MBEU>I!-|yq&$VV#iT9MBR}uQD&Go2U!R0rA zFDO8P6{5((mZiA@T)`E?Rp2VF8m@)4sE+G~>%ca)4covDb__ef4csu?0B+)@;bz#1 z+PH1F1>C_M!);&}yM{Z!UEDS70{3vwa2L3b`-XerAX>v~7Rvj>!7mH0KeUR@&TRiR z%cnvtIQ!@K7zvmJ-(JSwW=!T_Z|@x+&vr6(CM5q%6c_PSvVg^klQ4yNQ^$8n$|;zQ z8?(BpW!4#yrh;)V_$f;j-xw?MD&NDds zrH~PvdiTGm*`cA-j(Rl5A;mlg0#QvFYomL literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/security/__pycache__/api_key.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/security/__pycache__/api_key.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7a7fe21397148457430bcf33a653c023dbb3ad42 GIT binary patch literal 9439 zcmeHNUu+!38Q;A<-<{8ApMBU)fRIiTC-FteIROfiX#gi7B?25EX@#yXd+Xh?z0Th5 zF|%j;Qd1DkLt6Dus49h4JV1p6R;Xy-c&^lksxL`XDP{#~r9QNMyVS1K^3?B}**)K# z9g~Jq(KMTQcIKOJX1@8pZ@&4>?ESX8JFUQT@5CYdwIN0M6BeSUBh0M4519*!rC6$? zl+~iDVm{`?%34t?$BS`M)|`%VqL>i*xRWfWiYbxra5~HBVp`-APFFco%!qu_=`Qya zd&=2jR#jrkR}?FCR@KecsS_37_FTis$AZMz)5o8nwIC(m$6ct;oTO%z*?#S?!6}rxA3t^K>BkmKDw+Wy z`7C{*O1Tf&9M4ZD$^ZkZtdR5oA-Rb?N$LPeQVV+h)=Z_W?z4$v zr`1E#;2+@_Q*o>JY`oZ2i{<-*E@^^is+84?1@OQ$fd_~LR6&fYKSM#Mrhy(rsvNXS z3t=#=eJPM{q@lM!!9{?7e5qkL3Zk_MPv&jMLDLw7`wZ=FdZ10) z#cYfA)&zZQ!6;XpP}EYXRH^who-33y#k?{JmmIOn6_5EO6l5Pc21^liu#T}1t<9(f zFhTSZ&MNg`R4U|9)P6WGiNb<9H)kmL-ywA7sL?RGmSX+f+xfR$Jh$0`KZw!wj z;1k7o5~>Be2n{D0WD3h9vb*h?PPJ)CPE(iSg0o1p#D-~MxJbSYy2!0M!#l-9Im1L4Oq?lh`n(rgQy3)UlbLreWcXn zaV4S8b@OfwDkd&uN35za@QLLd1_(-IK)_Wm9AG2OOp(%>hm;7&#Ho)_rgY43I4$iX z^AO3!5W-WN{6@;ZUc@=Wb_}pAOdMhjEC7tanGeu&}mk( z*f~H9h+k7xM@m}rs$|}PuncpUG3Fr7g(#+NQ`$%w5Og_#X?vUZ2nuW7-NZfurhuTg zPW0ye2_}J>D1%Sf5bf3kn>T8l3{QCswi*!#QFGCDxxUM2`y|i+`CNkFiX5f}qYS1E z=w*YIWJZ804nCWNKiIRCm7hX#LGhzH#nNm*tv-0Pd}fim?XlIj)J1g>Fv{z(x6~h~ zi;9kYiDxmkpz=XgSyX0I5pC@~E3org8FSD&5m6T7P(s8o}s!1 zgg^ETEN|Vpl7#HJ`1jKFw6bl_@9rLZXXw4cQsL^}vCDhM&c%P9+PZw#(7E{cvjQXr z$#5YD3Aq874O75)IO%W0p8$+cC@Pq4QJn=s`!m}x$XX4UWCLT)Hk7}{c`KXYg#(g0wmuBV8pL- z-2~$W35xoC6nUV*7R$Z}14!GUH5qyd>x5)UV?&tV4M~s;w@8lj2ZJ`u zi6CsfIVE)pc=;2M{6+c4%gS=@&a1iImvg(X=JsCB?S1F|_ePgS-+N@~kt?}}&Luy{ z4uYM3_|kV@`fzaPhveQ%4~?&Cu`Ri}66?#=Q_9wD%h|zmJ^x%mwZ1Zz8|zn>GSU;X zKw-U*1W8?o{SG`7mqVZd9$=_ThC&DNNzZfGE-d2;Vh1omr!{i~Rjv&0FS@Yi_$myb#r8ABe2oe+S~ z39zz==|J7=tTZFo!(D3ABa-BVJ@rOTMgS}P88JTY!3`Nc)00ssU@Lan_(0Tz3WSjV z=79)LX15PRgfyR;u5%cY?zqWmNLsD^I3$~e=b?rDpzxbJ4MD^9lTgcm8y2IiIHkVI(s!pN&5S97~A=XSkey*>Np?AzX(-j&<~H;#qbL6q)ZOxkelgGdtz zWLAC!NrYpcTf?zKh+|Kx2LUr8j(tu0$;mgiU%BVNrL6}p_Z+Mzu_E=!z_b(jwtX_+ zJ;-;U3BYC$!1f@3%_4y90|0vvd8Rf4usEq(4Zt4pywf%{p1DB)YYO%o0kD$ua|~cZ z0Y5_k3)fW$-&=Hc`vxDrEw5 z_8Q`uQB1@Kf4q{s6;Y?u+NVRE4b4f^IRsbE>=5efx?u59ti|LqW*){wXc4Jg8w^Ao(YNBlB>bF&;k|9p54Y0Hp}tQGH2OUY z7gx?fZmlZ3spsOJHt1cekaybRb~@;jQt9v`0_x(v!^N$yyzs?aO?jCsKrqgv4I&4r zFUudaJj|YiTD+L&&q4w>xT^Y*a`&H=`#w?%;{WcCl#xFu`&JXG+IfE4ssgXoR7q90 doZq{u;CuC$Hi5;_RR!Ox--^lN-$hX<^Iv)Ecn1Ig literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/security/__pycache__/base.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/security/__pycache__/base.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..74e56dd5d833750698d31c81ae161e45383e0b78 GIT binary patch literal 509 zcmYjOJx{|h6nsunRP_T?1WcU}ONO=*BLW6MVu3D*C5mLZ$)kj}PKgsxcNm%b8xTK* z5r!%f6B8Sv0}>O@PLZ(W^PP3?**-tl>lL7}?e9eow7zTcH=G5TZxNY72q7E7hm1NVCuF;{ zizQ-~W)s_W5?zs(MsbM4ysCmr93hutgk5(jFLOgV&nujhB^x5~8t2!U7-|!##{avV znl>w(3n}ANq){vtd2E#?k1(f`;Kw`M@o(c~pvEFVUtXoEC4wN%WE#nSD~J>HdmE${YVA>iH^4u|)*~(MRQ92$hO))SlQXgZ-pIlF?MF1fMoz>qW}N^ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/security/__pycache__/http.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/security/__pycache__/http.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..251c7068a60fa0bfb93c5df9fe53a368348aa96b GIT binary patch literal 13745 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 S6Bb!MDW-VBe-jpA!}!0t&w8Z* literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/fastapi/security/__pycache__/oauth2.cpython-312.pyc b/backend/.venv/Lib/site-packages/fastapi/security/__pycache__/oauth2.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..12f234b16adbfa5098df5c4d5e9c137f5e9f8ef9 GIT binary patch literal 18261 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 Optional[str]: + api_key = request.query_params.get(self.model.name) + if not api_key: + if self.auto_error: + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" + ) + else: + return None + return api_key + + +class APIKeyHeader(APIKeyBase): + """ + API key authentication using a header. + + This defines the name of the header that should be provided in the request with + the API key and integrates that into the OpenAPI documentation. It extracts + the key value sent in the header automatically and provides it as the dependency + result. But it doesn't define how to send that key to the client. + + ## Usage + + Create an instance object and use that object as the dependency in `Depends()`. + + The dependency result will be a string containing the key value. + + ## Example + + ```python + from fastapi import Depends, FastAPI + from fastapi.security import APIKeyHeader + + app = FastAPI() + + header_scheme = APIKeyHeader(name="x-key") + + + @app.get("/items/") + async def read_items(key: str = Depends(header_scheme)): + return {"key": key} + ``` + """ + + def __init__( + self, + *, + name: Annotated[str, Doc("Header name.")], + scheme_name: Annotated[ + Optional[str], + Doc( + """ + Security scheme name. + + It will be included in the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + Security scheme description. + + It will be included in the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + auto_error: Annotated[ + bool, + Doc( + """ + By default, if the header is not provided, `APIKeyHeader` will + automatically cancel the request and send the client an error. + + If `auto_error` is set to `False`, when the header is not available, + instead of erroring out, the dependency result will be `None`. + + This is useful when you want to have optional authentication. + + It is also useful when you want to have authentication that can be + provided in one of multiple optional ways (for example, in a header or + in an HTTP Bearer token). + """ + ), + ] = True, + ): + self.model: APIKey = APIKey( + **{"in": APIKeyIn.header}, # type: ignore[arg-type] + name=name, + description=description, + ) + self.scheme_name = scheme_name or self.__class__.__name__ + self.auto_error = auto_error + + async def __call__(self, request: Request) -> Optional[str]: + api_key = request.headers.get(self.model.name) + if not api_key: + if self.auto_error: + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" + ) + else: + return None + return api_key + + +class APIKeyCookie(APIKeyBase): + """ + API key authentication using a cookie. + + This defines the name of the cookie that should be provided in the request with + the API key and integrates that into the OpenAPI documentation. It extracts + the key value sent in the cookie automatically and provides it as the dependency + result. But it doesn't define how to set that cookie. + + ## Usage + + Create an instance object and use that object as the dependency in `Depends()`. + + The dependency result will be a string containing the key value. + + ## Example + + ```python + from fastapi import Depends, FastAPI + from fastapi.security import APIKeyCookie + + app = FastAPI() + + cookie_scheme = APIKeyCookie(name="session") + + + @app.get("/items/") + async def read_items(session: str = Depends(cookie_scheme)): + return {"session": session} + ``` + """ + + def __init__( + self, + *, + name: Annotated[str, Doc("Cookie name.")], + scheme_name: Annotated[ + Optional[str], + Doc( + """ + Security scheme name. + + It will be included in the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + Security scheme description. + + It will be included in the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + auto_error: Annotated[ + bool, + Doc( + """ + By default, if the cookie is not provided, `APIKeyCookie` will + automatically cancel the request and send the client an error. + + If `auto_error` is set to `False`, when the cookie is not available, + instead of erroring out, the dependency result will be `None`. + + This is useful when you want to have optional authentication. + + It is also useful when you want to have authentication that can be + provided in one of multiple optional ways (for example, in a cookie or + in an HTTP Bearer token). + """ + ), + ] = True, + ): + self.model: APIKey = APIKey( + **{"in": APIKeyIn.cookie}, # type: ignore[arg-type] + name=name, + description=description, + ) + self.scheme_name = scheme_name or self.__class__.__name__ + self.auto_error = auto_error + + async def __call__(self, request: Request) -> Optional[str]: + api_key = request.cookies.get(self.model.name) + if not api_key: + if self.auto_error: + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" + ) + else: + return None + return api_key diff --git a/backend/.venv/Lib/site-packages/fastapi/security/base.py b/backend/.venv/Lib/site-packages/fastapi/security/base.py new file mode 100644 index 0000000..c43555d --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/security/base.py @@ -0,0 +1,6 @@ +from fastapi.openapi.models import SecurityBase as SecurityBaseModel + + +class SecurityBase: + model: SecurityBaseModel + scheme_name: str diff --git a/backend/.venv/Lib/site-packages/fastapi/security/http.py b/backend/.venv/Lib/site-packages/fastapi/security/http.py new file mode 100644 index 0000000..e06f3d6 --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/security/http.py @@ -0,0 +1,420 @@ +import binascii +from base64 import b64decode +from typing import Optional + +from fastapi.exceptions import HTTPException +from fastapi.openapi.models import HTTPBase as HTTPBaseModel +from fastapi.openapi.models import HTTPBearer as HTTPBearerModel +from fastapi.security.base import SecurityBase +from fastapi.security.utils import get_authorization_scheme_param +from pydantic import BaseModel +from starlette.requests import Request +from starlette.status import HTTP_401_UNAUTHORIZED, HTTP_403_FORBIDDEN +from typing_extensions import Annotated, Doc + + +class HTTPBasicCredentials(BaseModel): + """ + The HTTP Basic credentials given as the result of using `HTTPBasic` in a + dependency. + + Read more about it in the + [FastAPI docs for HTTP Basic Auth](https://fastapi.tiangolo.com/advanced/security/http-basic-auth/). + """ + + username: Annotated[str, Doc("The HTTP Basic username.")] + password: Annotated[str, Doc("The HTTP Basic password.")] + + +class HTTPAuthorizationCredentials(BaseModel): + """ + The HTTP authorization credentials in the result of using `HTTPBearer` or + `HTTPDigest` in a dependency. + + The HTTP authorization header value is split by the first space. + + The first part is the `scheme`, the second part is the `credentials`. + + For example, in an HTTP Bearer token scheme, the client will send a header + like: + + ``` + Authorization: Bearer deadbeef12346 + ``` + + In this case: + + * `scheme` will have the value `"Bearer"` + * `credentials` will have the value `"deadbeef12346"` + """ + + scheme: Annotated[ + str, + Doc( + """ + The HTTP authorization scheme extracted from the header value. + """ + ), + ] + credentials: Annotated[ + str, + Doc( + """ + The HTTP authorization credentials extracted from the header value. + """ + ), + ] + + +class HTTPBase(SecurityBase): + def __init__( + self, + *, + scheme: str, + scheme_name: Optional[str] = None, + description: Optional[str] = None, + auto_error: bool = True, + ): + self.model = HTTPBaseModel(scheme=scheme, description=description) + self.scheme_name = scheme_name or self.__class__.__name__ + self.auto_error = auto_error + + async def __call__( + self, request: Request + ) -> Optional[HTTPAuthorizationCredentials]: + authorization = request.headers.get("Authorization") + scheme, credentials = get_authorization_scheme_param(authorization) + if not (authorization and scheme and credentials): + if self.auto_error: + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" + ) + else: + return None + return HTTPAuthorizationCredentials(scheme=scheme, credentials=credentials) + + +class HTTPBasic(HTTPBase): + """ + HTTP Basic authentication. + + ## Usage + + Create an instance object and use that object as the dependency in `Depends()`. + + The dependency result will be an `HTTPBasicCredentials` object containing the + `username` and the `password`. + + Read more about it in the + [FastAPI docs for HTTP Basic Auth](https://fastapi.tiangolo.com/advanced/security/http-basic-auth/). + + ## Example + + ```python + from typing import Annotated + + from fastapi import Depends, FastAPI + from fastapi.security import HTTPBasic, HTTPBasicCredentials + + app = FastAPI() + + security = HTTPBasic() + + + @app.get("/users/me") + def read_current_user(credentials: Annotated[HTTPBasicCredentials, Depends(security)]): + return {"username": credentials.username, "password": credentials.password} + ``` + """ + + def __init__( + self, + *, + scheme_name: Annotated[ + Optional[str], + Doc( + """ + Security scheme name. + + It will be included in the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + realm: Annotated[ + Optional[str], + Doc( + """ + HTTP Basic authentication realm. + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + Security scheme description. + + It will be included in the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + auto_error: Annotated[ + bool, + Doc( + """ + By default, if the HTTP Basic authentication is not provided (a + header), `HTTPBasic` will automatically cancel the request and send the + client an error. + + If `auto_error` is set to `False`, when the HTTP Basic authentication + is not available, instead of erroring out, the dependency result will + be `None`. + + This is useful when you want to have optional authentication. + + It is also useful when you want to have authentication that can be + provided in one of multiple optional ways (for example, in HTTP Basic + authentication or in an HTTP Bearer token). + """ + ), + ] = True, + ): + self.model = HTTPBaseModel(scheme="basic", description=description) + self.scheme_name = scheme_name or self.__class__.__name__ + self.realm = realm + self.auto_error = auto_error + + async def __call__( # type: ignore + self, request: Request + ) -> Optional[HTTPBasicCredentials]: + authorization = request.headers.get("Authorization") + scheme, param = get_authorization_scheme_param(authorization) + if self.realm: + unauthorized_headers = {"WWW-Authenticate": f'Basic realm="{self.realm}"'} + else: + unauthorized_headers = {"WWW-Authenticate": "Basic"} + if not authorization or scheme.lower() != "basic": + if self.auto_error: + raise HTTPException( + status_code=HTTP_401_UNAUTHORIZED, + detail="Not authenticated", + headers=unauthorized_headers, + ) + else: + return None + invalid_user_credentials_exc = HTTPException( + status_code=HTTP_401_UNAUTHORIZED, + detail="Invalid authentication credentials", + headers=unauthorized_headers, + ) + try: + data = b64decode(param).decode("ascii") + except (ValueError, UnicodeDecodeError, binascii.Error): + raise invalid_user_credentials_exc # noqa: B904 + username, separator, password = data.partition(":") + if not separator: + raise invalid_user_credentials_exc + return HTTPBasicCredentials(username=username, password=password) + + +class HTTPBearer(HTTPBase): + """ + HTTP Bearer token authentication. + + ## Usage + + Create an instance object and use that object as the dependency in `Depends()`. + + The dependency result will be an `HTTPAuthorizationCredentials` object containing + the `scheme` and the `credentials`. + + ## Example + + ```python + from typing import Annotated + + from fastapi import Depends, FastAPI + from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer + + app = FastAPI() + + security = HTTPBearer() + + + @app.get("/users/me") + def read_current_user( + credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)] + ): + return {"scheme": credentials.scheme, "credentials": credentials.credentials} + ``` + """ + + def __init__( + self, + *, + bearerFormat: Annotated[Optional[str], Doc("Bearer token format.")] = None, + scheme_name: Annotated[ + Optional[str], + Doc( + """ + Security scheme name. + + It will be included in the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + Security scheme description. + + It will be included in the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + auto_error: Annotated[ + bool, + Doc( + """ + By default, if the HTTP Bearer token is not provided (in an + `Authorization` header), `HTTPBearer` will automatically cancel the + request and send the client an error. + + If `auto_error` is set to `False`, when the HTTP Bearer token + is not available, instead of erroring out, the dependency result will + be `None`. + + This is useful when you want to have optional authentication. + + It is also useful when you want to have authentication that can be + provided in one of multiple optional ways (for example, in an HTTP + Bearer token or in a cookie). + """ + ), + ] = True, + ): + self.model = HTTPBearerModel(bearerFormat=bearerFormat, description=description) + self.scheme_name = scheme_name or self.__class__.__name__ + self.auto_error = auto_error + + async def __call__( + self, request: Request + ) -> Optional[HTTPAuthorizationCredentials]: + authorization = request.headers.get("Authorization") + scheme, credentials = get_authorization_scheme_param(authorization) + if not (authorization and scheme and credentials): + if self.auto_error: + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" + ) + else: + return None + if scheme.lower() != "bearer": + if self.auto_error: + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, + detail="Invalid authentication credentials", + ) + else: + return None + return HTTPAuthorizationCredentials(scheme=scheme, credentials=credentials) + + +class HTTPDigest(HTTPBase): + """ + HTTP Digest authentication. + + ## Usage + + Create an instance object and use that object as the dependency in `Depends()`. + + The dependency result will be an `HTTPAuthorizationCredentials` object containing + the `scheme` and the `credentials`. + + ## Example + + ```python + from typing import Annotated + + from fastapi import Depends, FastAPI + from fastapi.security import HTTPAuthorizationCredentials, HTTPDigest + + app = FastAPI() + + security = HTTPDigest() + + + @app.get("/users/me") + def read_current_user( + credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)] + ): + return {"scheme": credentials.scheme, "credentials": credentials.credentials} + ``` + """ + + def __init__( + self, + *, + scheme_name: Annotated[ + Optional[str], + Doc( + """ + Security scheme name. + + It will be included in the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + Security scheme description. + + It will be included in the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + auto_error: Annotated[ + bool, + Doc( + """ + By default, if the HTTP Digest is not provided, `HTTPDigest` will + automatically cancel the request and send the client an error. + + If `auto_error` is set to `False`, when the HTTP Digest is not + available, instead of erroring out, the dependency result will + be `None`. + + This is useful when you want to have optional authentication. + + It is also useful when you want to have authentication that can be + provided in one of multiple optional ways (for example, in HTTP + Digest or in a cookie). + """ + ), + ] = True, + ): + self.model = HTTPBaseModel(scheme="digest", description=description) + self.scheme_name = scheme_name or self.__class__.__name__ + self.auto_error = auto_error + + async def __call__( + self, request: Request + ) -> Optional[HTTPAuthorizationCredentials]: + authorization = request.headers.get("Authorization") + scheme, credentials = get_authorization_scheme_param(authorization) + if not (authorization and scheme and credentials): + if self.auto_error: + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" + ) + else: + return None + if scheme.lower() != "digest": + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, + detail="Invalid authentication credentials", + ) + return HTTPAuthorizationCredentials(scheme=scheme, credentials=credentials) diff --git a/backend/.venv/Lib/site-packages/fastapi/security/oauth2.py b/backend/.venv/Lib/site-packages/fastapi/security/oauth2.py new file mode 100644 index 0000000..6adc55b --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/security/oauth2.py @@ -0,0 +1,638 @@ +from typing import Any, Dict, List, Optional, Union, cast + +from fastapi.exceptions import HTTPException +from fastapi.openapi.models import OAuth2 as OAuth2Model +from fastapi.openapi.models import OAuthFlows as OAuthFlowsModel +from fastapi.param_functions import Form +from fastapi.security.base import SecurityBase +from fastapi.security.utils import get_authorization_scheme_param +from starlette.requests import Request +from starlette.status import HTTP_401_UNAUTHORIZED, HTTP_403_FORBIDDEN + +# TODO: import from typing when deprecating Python 3.9 +from typing_extensions import Annotated, Doc + + +class OAuth2PasswordRequestForm: + """ + This is a dependency class to collect the `username` and `password` as form data + for an OAuth2 password flow. + + The OAuth2 specification dictates that for a password flow the data should be + collected using form data (instead of JSON) and that it should have the specific + fields `username` and `password`. + + All the initialization parameters are extracted from the request. + + Read more about it in the + [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). + + ## Example + + ```python + from typing import Annotated + + from fastapi import Depends, FastAPI + from fastapi.security import OAuth2PasswordRequestForm + + app = FastAPI() + + + @app.post("/login") + def login(form_data: Annotated[OAuth2PasswordRequestForm, Depends()]): + data = {} + data["scopes"] = [] + for scope in form_data.scopes: + data["scopes"].append(scope) + if form_data.client_id: + data["client_id"] = form_data.client_id + if form_data.client_secret: + data["client_secret"] = form_data.client_secret + return data + ``` + + Note that for OAuth2 the scope `items:read` is a single scope in an opaque string. + You could have custom internal logic to separate it by colon characters (`:`) or + similar, and get the two parts `items` and `read`. Many applications do that to + group and organize permissions, you could do it as well in your application, just + know that that it is application specific, it's not part of the specification. + """ + + def __init__( + self, + *, + grant_type: Annotated[ + Union[str, None], + Form(pattern="password"), + Doc( + """ + The OAuth2 spec says it is required and MUST be the fixed string + "password". Nevertheless, this dependency class is permissive and + allows not passing it. If you want to enforce it, use instead the + `OAuth2PasswordRequestFormStrict` dependency. + """ + ), + ] = None, + username: Annotated[ + str, + Form(), + Doc( + """ + `username` string. The OAuth2 spec requires the exact field name + `username`. + """ + ), + ], + password: Annotated[ + str, + Form(), + Doc( + """ + `password` string. The OAuth2 spec requires the exact field name + `password". + """ + ), + ], + scope: Annotated[ + str, + Form(), + Doc( + """ + A single string with actually several scopes separated by spaces. Each + scope is also a string. + + For example, a single string with: + + ```python + "items:read items:write users:read profile openid" + ```` + + would represent the scopes: + + * `items:read` + * `items:write` + * `users:read` + * `profile` + * `openid` + """ + ), + ] = "", + client_id: Annotated[ + Union[str, None], + Form(), + Doc( + """ + If there's a `client_id`, it can be sent as part of the form fields. + But the OAuth2 specification recommends sending the `client_id` and + `client_secret` (if any) using HTTP Basic auth. + """ + ), + ] = None, + client_secret: Annotated[ + Union[str, None], + Form(), + Doc( + """ + If there's a `client_password` (and a `client_id`), they can be sent + as part of the form fields. But the OAuth2 specification recommends + sending the `client_id` and `client_secret` (if any) using HTTP Basic + auth. + """ + ), + ] = None, + ): + self.grant_type = grant_type + self.username = username + self.password = password + self.scopes = scope.split() + self.client_id = client_id + self.client_secret = client_secret + + +class OAuth2PasswordRequestFormStrict(OAuth2PasswordRequestForm): + """ + This is a dependency class to collect the `username` and `password` as form data + for an OAuth2 password flow. + + The OAuth2 specification dictates that for a password flow the data should be + collected using form data (instead of JSON) and that it should have the specific + fields `username` and `password`. + + All the initialization parameters are extracted from the request. + + The only difference between `OAuth2PasswordRequestFormStrict` and + `OAuth2PasswordRequestForm` is that `OAuth2PasswordRequestFormStrict` requires the + client to send the form field `grant_type` with the value `"password"`, which + is required in the OAuth2 specification (it seems that for no particular reason), + while for `OAuth2PasswordRequestForm` `grant_type` is optional. + + Read more about it in the + [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). + + ## Example + + ```python + from typing import Annotated + + from fastapi import Depends, FastAPI + from fastapi.security import OAuth2PasswordRequestForm + + app = FastAPI() + + + @app.post("/login") + def login(form_data: Annotated[OAuth2PasswordRequestFormStrict, Depends()]): + data = {} + data["scopes"] = [] + for scope in form_data.scopes: + data["scopes"].append(scope) + if form_data.client_id: + data["client_id"] = form_data.client_id + if form_data.client_secret: + data["client_secret"] = form_data.client_secret + return data + ``` + + Note that for OAuth2 the scope `items:read` is a single scope in an opaque string. + You could have custom internal logic to separate it by colon characters (`:`) or + similar, and get the two parts `items` and `read`. Many applications do that to + group and organize permissions, you could do it as well in your application, just + know that that it is application specific, it's not part of the specification. + + + grant_type: the OAuth2 spec says it is required and MUST be the fixed string "password". + This dependency is strict about it. If you want to be permissive, use instead the + OAuth2PasswordRequestForm dependency class. + username: username string. The OAuth2 spec requires the exact field name "username". + password: password string. The OAuth2 spec requires the exact field name "password". + scope: Optional string. Several scopes (each one a string) separated by spaces. E.g. + "items:read items:write users:read profile openid" + client_id: optional string. OAuth2 recommends sending the client_id and client_secret (if any) + using HTTP Basic auth, as: client_id:client_secret + client_secret: optional string. OAuth2 recommends sending the client_id and client_secret (if any) + using HTTP Basic auth, as: client_id:client_secret + """ + + def __init__( + self, + grant_type: Annotated[ + str, + Form(pattern="password"), + Doc( + """ + The OAuth2 spec says it is required and MUST be the fixed string + "password". This dependency is strict about it. If you want to be + permissive, use instead the `OAuth2PasswordRequestForm` dependency + class. + """ + ), + ], + username: Annotated[ + str, + Form(), + Doc( + """ + `username` string. The OAuth2 spec requires the exact field name + `username`. + """ + ), + ], + password: Annotated[ + str, + Form(), + Doc( + """ + `password` string. The OAuth2 spec requires the exact field name + `password". + """ + ), + ], + scope: Annotated[ + str, + Form(), + Doc( + """ + A single string with actually several scopes separated by spaces. Each + scope is also a string. + + For example, a single string with: + + ```python + "items:read items:write users:read profile openid" + ```` + + would represent the scopes: + + * `items:read` + * `items:write` + * `users:read` + * `profile` + * `openid` + """ + ), + ] = "", + client_id: Annotated[ + Union[str, None], + Form(), + Doc( + """ + If there's a `client_id`, it can be sent as part of the form fields. + But the OAuth2 specification recommends sending the `client_id` and + `client_secret` (if any) using HTTP Basic auth. + """ + ), + ] = None, + client_secret: Annotated[ + Union[str, None], + Form(), + Doc( + """ + If there's a `client_password` (and a `client_id`), they can be sent + as part of the form fields. But the OAuth2 specification recommends + sending the `client_id` and `client_secret` (if any) using HTTP Basic + auth. + """ + ), + ] = None, + ): + super().__init__( + grant_type=grant_type, + username=username, + password=password, + scope=scope, + client_id=client_id, + client_secret=client_secret, + ) + + +class OAuth2(SecurityBase): + """ + This is the base class for OAuth2 authentication, an instance of it would be used + as a dependency. All other OAuth2 classes inherit from it and customize it for + each OAuth2 flow. + + You normally would not create a new class inheriting from it but use one of the + existing subclasses, and maybe compose them if you want to support multiple flows. + + Read more about it in the + [FastAPI docs for Security](https://fastapi.tiangolo.com/tutorial/security/). + """ + + def __init__( + self, + *, + flows: Annotated[ + Union[OAuthFlowsModel, Dict[str, Dict[str, Any]]], + Doc( + """ + The dictionary of OAuth2 flows. + """ + ), + ] = OAuthFlowsModel(), + scheme_name: Annotated[ + Optional[str], + Doc( + """ + Security scheme name. + + It will be included in the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + Security scheme description. + + It will be included in the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + auto_error: Annotated[ + bool, + Doc( + """ + By default, if no HTTP Authorization header is provided, required for + OAuth2 authentication, it will automatically cancel the request and + send the client an error. + + If `auto_error` is set to `False`, when the HTTP Authorization header + is not available, instead of erroring out, the dependency result will + be `None`. + + This is useful when you want to have optional authentication. + + It is also useful when you want to have authentication that can be + provided in one of multiple optional ways (for example, with OAuth2 + or in a cookie). + """ + ), + ] = True, + ): + self.model = OAuth2Model( + flows=cast(OAuthFlowsModel, flows), description=description + ) + self.scheme_name = scheme_name or self.__class__.__name__ + self.auto_error = auto_error + + async def __call__(self, request: Request) -> Optional[str]: + authorization = request.headers.get("Authorization") + if not authorization: + if self.auto_error: + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" + ) + else: + return None + return authorization + + +class OAuth2PasswordBearer(OAuth2): + """ + OAuth2 flow for authentication using a bearer token obtained with a password. + An instance of it would be used as a dependency. + + Read more about it in the + [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). + """ + + def __init__( + self, + tokenUrl: Annotated[ + str, + Doc( + """ + The URL to obtain the OAuth2 token. This would be the *path operation* + that has `OAuth2PasswordRequestForm` as a dependency. + """ + ), + ], + scheme_name: Annotated[ + Optional[str], + Doc( + """ + Security scheme name. + + It will be included in the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + scopes: Annotated[ + Optional[Dict[str, str]], + Doc( + """ + The OAuth2 scopes that would be required by the *path operations* that + use this dependency. + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + Security scheme description. + + It will be included in the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + auto_error: Annotated[ + bool, + Doc( + """ + By default, if no HTTP Authorization header is provided, required for + OAuth2 authentication, it will automatically cancel the request and + send the client an error. + + If `auto_error` is set to `False`, when the HTTP Authorization header + is not available, instead of erroring out, the dependency result will + be `None`. + + This is useful when you want to have optional authentication. + + It is also useful when you want to have authentication that can be + provided in one of multiple optional ways (for example, with OAuth2 + or in a cookie). + """ + ), + ] = True, + ): + if not scopes: + scopes = {} + flows = OAuthFlowsModel( + password=cast(Any, {"tokenUrl": tokenUrl, "scopes": scopes}) + ) + super().__init__( + flows=flows, + scheme_name=scheme_name, + description=description, + auto_error=auto_error, + ) + + async def __call__(self, request: Request) -> Optional[str]: + authorization = request.headers.get("Authorization") + scheme, param = get_authorization_scheme_param(authorization) + if not authorization or scheme.lower() != "bearer": + if self.auto_error: + raise HTTPException( + status_code=HTTP_401_UNAUTHORIZED, + detail="Not authenticated", + headers={"WWW-Authenticate": "Bearer"}, + ) + else: + return None + return param + + +class OAuth2AuthorizationCodeBearer(OAuth2): + """ + OAuth2 flow for authentication using a bearer token obtained with an OAuth2 code + flow. An instance of it would be used as a dependency. + """ + + def __init__( + self, + authorizationUrl: str, + tokenUrl: Annotated[ + str, + Doc( + """ + The URL to obtain the OAuth2 token. + """ + ), + ], + refreshUrl: Annotated[ + Optional[str], + Doc( + """ + The URL to refresh the token and obtain a new one. + """ + ), + ] = None, + scheme_name: Annotated[ + Optional[str], + Doc( + """ + Security scheme name. + + It will be included in the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + scopes: Annotated[ + Optional[Dict[str, str]], + Doc( + """ + The OAuth2 scopes that would be required by the *path operations* that + use this dependency. + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + Security scheme description. + + It will be included in the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + auto_error: Annotated[ + bool, + Doc( + """ + By default, if no HTTP Authorization header is provided, required for + OAuth2 authentication, it will automatically cancel the request and + send the client an error. + + If `auto_error` is set to `False`, when the HTTP Authorization header + is not available, instead of erroring out, the dependency result will + be `None`. + + This is useful when you want to have optional authentication. + + It is also useful when you want to have authentication that can be + provided in one of multiple optional ways (for example, with OAuth2 + or in a cookie). + """ + ), + ] = True, + ): + if not scopes: + scopes = {} + flows = OAuthFlowsModel( + authorizationCode=cast( + Any, + { + "authorizationUrl": authorizationUrl, + "tokenUrl": tokenUrl, + "refreshUrl": refreshUrl, + "scopes": scopes, + }, + ) + ) + super().__init__( + flows=flows, + scheme_name=scheme_name, + description=description, + auto_error=auto_error, + ) + + async def __call__(self, request: Request) -> Optional[str]: + authorization = request.headers.get("Authorization") + scheme, param = get_authorization_scheme_param(authorization) + if not authorization or scheme.lower() != "bearer": + if self.auto_error: + raise HTTPException( + status_code=HTTP_401_UNAUTHORIZED, + detail="Not authenticated", + headers={"WWW-Authenticate": "Bearer"}, + ) + else: + return None # pragma: nocover + return param + + +class SecurityScopes: + """ + This is a special class that you can define in a parameter in a dependency to + obtain the OAuth2 scopes required by all the dependencies in the same chain. + + This way, multiple dependencies can have different scopes, even when used in the + same *path operation*. And with this, you can access all the scopes required in + all those dependencies in a single place. + + Read more about it in the + [FastAPI docs for OAuth2 scopes](https://fastapi.tiangolo.com/advanced/security/oauth2-scopes/). + """ + + def __init__( + self, + scopes: Annotated[ + Optional[List[str]], + Doc( + """ + This will be filled by FastAPI. + """ + ), + ] = None, + ): + self.scopes: Annotated[ + List[str], + Doc( + """ + The list of all the scopes required by dependencies. + """ + ), + ] = scopes or [] + self.scope_str: Annotated[ + str, + Doc( + """ + All the scopes required by all the dependencies in a single string + separated by spaces, as defined in the OAuth2 specification. + """ + ), + ] = " ".join(self.scopes) diff --git a/backend/.venv/Lib/site-packages/fastapi/security/open_id_connect_url.py b/backend/.venv/Lib/site-packages/fastapi/security/open_id_connect_url.py new file mode 100644 index 0000000..c8cceb9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/security/open_id_connect_url.py @@ -0,0 +1,84 @@ +from typing import Optional + +from fastapi.openapi.models import OpenIdConnect as OpenIdConnectModel +from fastapi.security.base import SecurityBase +from starlette.exceptions import HTTPException +from starlette.requests import Request +from starlette.status import HTTP_403_FORBIDDEN +from typing_extensions import Annotated, Doc + + +class OpenIdConnect(SecurityBase): + """ + OpenID Connect authentication class. An instance of it would be used as a + dependency. + """ + + def __init__( + self, + *, + openIdConnectUrl: Annotated[ + str, + Doc( + """ + The OpenID Connect URL. + """ + ), + ], + scheme_name: Annotated[ + Optional[str], + Doc( + """ + Security scheme name. + + It will be included in the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + description: Annotated[ + Optional[str], + Doc( + """ + Security scheme description. + + It will be included in the generated OpenAPI (e.g. visible at `/docs`). + """ + ), + ] = None, + auto_error: Annotated[ + bool, + Doc( + """ + By default, if no HTTP Authorization header is provided, required for + OpenID Connect authentication, it will automatically cancel the request + and send the client an error. + + If `auto_error` is set to `False`, when the HTTP Authorization header + is not available, instead of erroring out, the dependency result will + be `None`. + + This is useful when you want to have optional authentication. + + It is also useful when you want to have authentication that can be + provided in one of multiple optional ways (for example, with OpenID + Connect or in a cookie). + """ + ), + ] = True, + ): + self.model = OpenIdConnectModel( + openIdConnectUrl=openIdConnectUrl, description=description + ) + self.scheme_name = scheme_name or self.__class__.__name__ + self.auto_error = auto_error + + async def __call__(self, request: Request) -> Optional[str]: + authorization = request.headers.get("Authorization") + if not authorization: + if self.auto_error: + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" + ) + else: + return None + return authorization diff --git a/backend/.venv/Lib/site-packages/fastapi/security/utils.py b/backend/.venv/Lib/site-packages/fastapi/security/utils.py new file mode 100644 index 0000000..fa7a450 --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/security/utils.py @@ -0,0 +1,10 @@ +from typing import Optional, Tuple + + +def get_authorization_scheme_param( + authorization_header_value: Optional[str], +) -> Tuple[str, str]: + if not authorization_header_value: + return "", "" + scheme, _, param = authorization_header_value.partition(" ") + return scheme, param diff --git a/backend/.venv/Lib/site-packages/fastapi/staticfiles.py b/backend/.venv/Lib/site-packages/fastapi/staticfiles.py new file mode 100644 index 0000000..299015d --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/staticfiles.py @@ -0,0 +1 @@ +from starlette.staticfiles import StaticFiles as StaticFiles # noqa diff --git a/backend/.venv/Lib/site-packages/fastapi/templating.py b/backend/.venv/Lib/site-packages/fastapi/templating.py new file mode 100644 index 0000000..0cb8684 --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/templating.py @@ -0,0 +1 @@ +from starlette.templating import Jinja2Templates as Jinja2Templates # noqa diff --git a/backend/.venv/Lib/site-packages/fastapi/testclient.py b/backend/.venv/Lib/site-packages/fastapi/testclient.py new file mode 100644 index 0000000..4012406 --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/testclient.py @@ -0,0 +1 @@ +from starlette.testclient import TestClient as TestClient # noqa diff --git a/backend/.venv/Lib/site-packages/fastapi/types.py b/backend/.venv/Lib/site-packages/fastapi/types.py new file mode 100644 index 0000000..3205654 --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/types.py @@ -0,0 +1,10 @@ +import types +from enum import Enum +from typing import Any, Callable, Dict, Set, Type, TypeVar, Union + +from pydantic import BaseModel + +DecoratedCallable = TypeVar("DecoratedCallable", bound=Callable[..., Any]) +UnionType = getattr(types, "UnionType", Union) +ModelNameMap = Dict[Union[Type[BaseModel], Type[Enum]], str] +IncEx = Union[Set[int], Set[str], Dict[int, Any], Dict[str, Any]] diff --git a/backend/.venv/Lib/site-packages/fastapi/utils.py b/backend/.venv/Lib/site-packages/fastapi/utils.py new file mode 100644 index 0000000..4c7350f --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/utils.py @@ -0,0 +1,220 @@ +import re +import warnings +from dataclasses import is_dataclass +from typing import ( + TYPE_CHECKING, + Any, + Dict, + MutableMapping, + Optional, + Set, + Type, + Union, + cast, +) +from weakref import WeakKeyDictionary + +import fastapi +from fastapi._compat import ( + PYDANTIC_V2, + BaseConfig, + ModelField, + PydanticSchemaGenerationError, + Undefined, + UndefinedType, + Validator, + lenient_issubclass, +) +from fastapi.datastructures import DefaultPlaceholder, DefaultType +from pydantic import BaseModel, create_model +from pydantic.fields import FieldInfo +from typing_extensions import Literal + +if TYPE_CHECKING: # pragma: nocover + from .routing import APIRoute + +# Cache for `create_cloned_field` +_CLONED_TYPES_CACHE: MutableMapping[Type[BaseModel], Type[BaseModel]] = ( + WeakKeyDictionary() +) + + +def is_body_allowed_for_status_code(status_code: Union[int, str, None]) -> bool: + if status_code is None: + return True + # Ref: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#patterned-fields-1 + if status_code in { + "default", + "1XX", + "2XX", + "3XX", + "4XX", + "5XX", + }: + return True + current_status_code = int(status_code) + return not (current_status_code < 200 or current_status_code in {204, 205, 304}) + + +def get_path_param_names(path: str) -> Set[str]: + return set(re.findall("{(.*?)}", path)) + + +def create_model_field( + name: str, + type_: Any, + class_validators: Optional[Dict[str, Validator]] = None, + default: Optional[Any] = Undefined, + required: Union[bool, UndefinedType] = Undefined, + model_config: Type[BaseConfig] = BaseConfig, + field_info: Optional[FieldInfo] = None, + alias: Optional[str] = None, + mode: Literal["validation", "serialization"] = "validation", +) -> ModelField: + class_validators = class_validators or {} + if PYDANTIC_V2: + field_info = field_info or FieldInfo( + annotation=type_, default=default, alias=alias + ) + else: + field_info = field_info or FieldInfo() + kwargs = {"name": name, "field_info": field_info} + if PYDANTIC_V2: + kwargs.update({"mode": mode}) + else: + kwargs.update( + { + "type_": type_, + "class_validators": class_validators, + "default": default, + "required": required, + "model_config": model_config, + "alias": alias, + } + ) + try: + return ModelField(**kwargs) # type: ignore[arg-type] + except (RuntimeError, PydanticSchemaGenerationError): + raise fastapi.exceptions.FastAPIError( + "Invalid args for response field! Hint: " + f"check that {type_} is a valid Pydantic field type. " + "If you are using a return type annotation that is not a valid Pydantic " + "field (e.g. Union[Response, dict, None]) you can disable generating the " + "response model from the type annotation with the path operation decorator " + "parameter response_model=None. Read more: " + "https://fastapi.tiangolo.com/tutorial/response-model/" + ) from None + + +def create_cloned_field( + field: ModelField, + *, + cloned_types: Optional[MutableMapping[Type[BaseModel], Type[BaseModel]]] = None, +) -> ModelField: + if PYDANTIC_V2: + return field + # cloned_types caches already cloned types to support recursive models and improve + # performance by avoiding unnecessary cloning + if cloned_types is None: + cloned_types = _CLONED_TYPES_CACHE + + original_type = field.type_ + if is_dataclass(original_type) and hasattr(original_type, "__pydantic_model__"): + original_type = original_type.__pydantic_model__ + use_type = original_type + if lenient_issubclass(original_type, BaseModel): + original_type = cast(Type[BaseModel], original_type) + use_type = cloned_types.get(original_type) + if use_type is None: + use_type = create_model(original_type.__name__, __base__=original_type) + cloned_types[original_type] = use_type + for f in original_type.__fields__.values(): + use_type.__fields__[f.name] = create_cloned_field( + f, cloned_types=cloned_types + ) + new_field = create_model_field(name=field.name, type_=use_type) + new_field.has_alias = field.has_alias # type: ignore[attr-defined] + new_field.alias = field.alias # type: ignore[misc] + new_field.class_validators = field.class_validators # type: ignore[attr-defined] + new_field.default = field.default # type: ignore[misc] + new_field.required = field.required # type: ignore[misc] + new_field.model_config = field.model_config # type: ignore[attr-defined] + new_field.field_info = field.field_info + new_field.allow_none = field.allow_none # type: ignore[attr-defined] + new_field.validate_always = field.validate_always # type: ignore[attr-defined] + if field.sub_fields: # type: ignore[attr-defined] + new_field.sub_fields = [ # type: ignore[attr-defined] + create_cloned_field(sub_field, cloned_types=cloned_types) + for sub_field in field.sub_fields # type: ignore[attr-defined] + ] + if field.key_field: # type: ignore[attr-defined] + new_field.key_field = create_cloned_field( # type: ignore[attr-defined] + field.key_field, # type: ignore[attr-defined] + cloned_types=cloned_types, + ) + new_field.validators = field.validators # type: ignore[attr-defined] + new_field.pre_validators = field.pre_validators # type: ignore[attr-defined] + new_field.post_validators = field.post_validators # type: ignore[attr-defined] + new_field.parse_json = field.parse_json # type: ignore[attr-defined] + new_field.shape = field.shape # type: ignore[attr-defined] + new_field.populate_validators() # type: ignore[attr-defined] + return new_field + + +def generate_operation_id_for_path( + *, name: str, path: str, method: str +) -> str: # pragma: nocover + warnings.warn( + "fastapi.utils.generate_operation_id_for_path() was deprecated, " + "it is not used internally, and will be removed soon", + DeprecationWarning, + stacklevel=2, + ) + operation_id = f"{name}{path}" + operation_id = re.sub(r"\W", "_", operation_id) + operation_id = f"{operation_id}_{method.lower()}" + return operation_id + + +def generate_unique_id(route: "APIRoute") -> str: + operation_id = f"{route.name}{route.path_format}" + operation_id = re.sub(r"\W", "_", operation_id) + assert route.methods + operation_id = f"{operation_id}_{list(route.methods)[0].lower()}" + return operation_id + + +def deep_dict_update(main_dict: Dict[Any, Any], update_dict: Dict[Any, Any]) -> None: + for key, value in update_dict.items(): + if ( + key in main_dict + and isinstance(main_dict[key], dict) + and isinstance(value, dict) + ): + deep_dict_update(main_dict[key], value) + elif ( + key in main_dict + and isinstance(main_dict[key], list) + and isinstance(update_dict[key], list) + ): + main_dict[key] = main_dict[key] + update_dict[key] + else: + main_dict[key] = value + + +def get_value_or_default( + first_item: Union[DefaultPlaceholder, DefaultType], + *extra_items: Union[DefaultPlaceholder, DefaultType], +) -> Union[DefaultPlaceholder, DefaultType]: + """ + Pass items or `DefaultPlaceholder`s by descending priority. + + The first one to _not_ be a `DefaultPlaceholder` will be returned. + + Otherwise, the first item (a `DefaultPlaceholder`) will be returned. + """ + items = (first_item,) + extra_items + for item in items: + if not isinstance(item, DefaultPlaceholder): + return item + return first_item diff --git a/backend/.venv/Lib/site-packages/fastapi/websockets.py b/backend/.venv/Lib/site-packages/fastapi/websockets.py new file mode 100644 index 0000000..55a4ac4 --- /dev/null +++ b/backend/.venv/Lib/site-packages/fastapi/websockets.py @@ -0,0 +1,3 @@ +from starlette.websockets import WebSocket as WebSocket # noqa +from starlette.websockets import WebSocketDisconnect as WebSocketDisconnect # noqa +from starlette.websockets import WebSocketState as WebSocketState # noqa diff --git a/backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/INSTALLER b/backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/METADATA b/backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/METADATA new file mode 100644 index 0000000..8a2f639 --- /dev/null +++ b/backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/METADATA @@ -0,0 +1,202 @@ +Metadata-Version: 2.4 +Name: h11 +Version: 0.16.0 +Summary: A pure-Python, bring-your-own-I/O implementation of HTTP/1.1 +Home-page: https://github.com/python-hyper/h11 +Author: Nathaniel J. Smith +Author-email: njs@pobox.com +License: MIT +Classifier: Development Status :: 3 - Alpha +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +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: Topic :: Internet :: WWW/HTTP +Classifier: Topic :: System :: Networking +Requires-Python: >=3.8 +License-File: LICENSE.txt +Dynamic: author +Dynamic: author-email +Dynamic: classifier +Dynamic: description +Dynamic: home-page +Dynamic: license +Dynamic: license-file +Dynamic: requires-python +Dynamic: summary + +h11 +=== + +.. image:: https://travis-ci.org/python-hyper/h11.svg?branch=master + :target: https://travis-ci.org/python-hyper/h11 + :alt: Automated test status + +.. image:: https://codecov.io/gh/python-hyper/h11/branch/master/graph/badge.svg + :target: https://codecov.io/gh/python-hyper/h11 + :alt: Test coverage + +.. image:: https://readthedocs.org/projects/h11/badge/?version=latest + :target: http://h11.readthedocs.io/en/latest/?badge=latest + :alt: Documentation Status + +This is a little HTTP/1.1 library written from scratch in Python, +heavily inspired by `hyper-h2 `_. + +It's a "bring-your-own-I/O" library; h11 contains no IO code +whatsoever. This means you can hook h11 up to your favorite network +API, and that could be anything you want: synchronous, threaded, +asynchronous, or your own implementation of `RFC 6214 +`_ -- h11 won't judge you. +(Compare this to the current state of the art, where every time a `new +network API `_ comes along then someone +gets to start over reimplementing the entire HTTP protocol from +scratch.) Cory Benfield made an `excellent blog post describing the +benefits of this approach +`_, or if you like video +then here's his `PyCon 2016 talk on the same theme +`_. + +This also means that h11 is not immediately useful out of the box: +it's a toolkit for building programs that speak HTTP, not something +that could directly replace ``requests`` or ``twisted.web`` or +whatever. But h11 makes it much easier to implement something like +``requests`` or ``twisted.web``. + +At a high level, working with h11 goes like this: + +1) First, create an ``h11.Connection`` object to track the state of a + single HTTP/1.1 connection. + +2) When you read data off the network, pass it to + ``conn.receive_data(...)``; you'll get back a list of objects + representing high-level HTTP "events". + +3) When you want to send a high-level HTTP event, create the + corresponding "event" object and pass it to ``conn.send(...)``; + this will give you back some bytes that you can then push out + through the network. + +For example, a client might instantiate and then send a +``h11.Request`` object, then zero or more ``h11.Data`` objects for the +request body (e.g., if this is a POST), and then a +``h11.EndOfMessage`` to indicate the end of the message. Then the +server would then send back a ``h11.Response``, some ``h11.Data``, and +its own ``h11.EndOfMessage``. If either side violates the protocol, +you'll get a ``h11.ProtocolError`` exception. + +h11 is suitable for implementing both servers and clients, and has a +pleasantly symmetric API: the events you send as a client are exactly +the ones that you receive as a server and vice-versa. + +`Here's an example of a tiny HTTP client +`_ + +It also has `a fine manual `_. + +FAQ +--- + +*Whyyyyy?* + +I wanted to play with HTTP in `Curio +`__ and `Trio +`__, which at the time didn't have any +HTTP libraries. So I thought, no big deal, Python has, like, a dozen +different implementations of HTTP, surely I can find one that's +reusable. I didn't find one, but I did find Cory's call-to-arms +blog-post. So I figured, well, fine, if I have to implement HTTP from +scratch, at least I can make sure no-one *else* has to ever again. + +*Should I use it?* + +Maybe. You should be aware that it's a very young project. But, it's +feature complete and has an exhaustive test-suite and complete docs, +so the next step is for people to try using it and see how it goes +:-). If you do then please let us know -- if nothing else we'll want +to talk to you before making any incompatible changes! + +*What are the features/limitations?* + +Roughly speaking, it's trying to be a robust, complete, and non-hacky +implementation of the first "chapter" of the HTTP/1.1 spec: `RFC 7230: +HTTP/1.1 Message Syntax and Routing +`_. That is, it mostly focuses on +implementing HTTP at the level of taking bytes on and off the wire, +and the headers related to that, and tries to be anal about spec +conformance. It doesn't know about higher-level concerns like URL +routing, conditional GETs, cross-origin cookie policies, or content +negotiation. But it does know how to take care of framing, +cross-version differences in keep-alive handling, and the "obsolete +line folding" rule, so you can focus your energies on the hard / +interesting parts for your application, and it tries to support the +full specification in the sense that any useful HTTP/1.1 conformant +application should be able to use h11. + +It's pure Python, and has no dependencies outside of the standard +library. + +It has a test suite with 100.0% coverage for both statements and +branches. + +Currently it supports Python 3 (testing on 3.8-3.12) and PyPy 3. +The last Python 2-compatible version was h11 0.11.x. +(Originally it had a Cython wrapper for `http-parser +`_ and a beautiful nested state +machine implemented with ``yield from`` to postprocess the output. But +I had to take these out -- the new *parser* needs fewer lines-of-code +than the old *parser wrapper*, is written in pure Python, uses no +exotic language syntax, and has more features. It's sad, really; that +old state machine was really slick. I just need a few sentences here +to mourn that.) + +I don't know how fast it is. I haven't benchmarked or profiled it yet, +so it's probably got a few pointless hot spots, and I've been trying +to err on the side of simplicity and robustness instead of +micro-optimization. But at the architectural level I tried hard to +avoid fundamentally bad decisions, e.g., I believe that all the +parsing algorithms remain linear-time even in the face of pathological +input like slowloris, and there are no byte-by-byte loops. (I also +believe that it maintains bounded memory usage in the face of +arbitrary/pathological input.) + +The whole library is ~800 lines-of-code. You can read and understand +the whole thing in less than an hour. Most of the energy invested in +this so far has been spent on trying to keep things simple by +minimizing special-cases and ad hoc state manipulation; even though it +is now quite small and simple, I'm still annoyed that I haven't +figured out how to make it even smaller and simpler. (Unfortunately, +HTTP does not lend itself to simplicity.) + +The API is ~feature complete and I don't expect the general outlines +to change much, but you can't judge an API's ergonomics until you +actually document and use it, so I'd expect some changes in the +details. + +*How do I try it?* + +.. code-block:: sh + + $ pip install h11 + $ git clone git@github.com:python-hyper/h11 + $ cd h11/examples + $ python basic-client.py + +and go from there. + +*License?* + +MIT + +*Code of conduct?* + +Contributors are requested to follow our `code of conduct +`_ in +all project spaces. diff --git a/backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/RECORD b/backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/RECORD new file mode 100644 index 0000000..fa60234 --- /dev/null +++ b/backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/RECORD @@ -0,0 +1,29 @@ +h11-0.16.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +h11-0.16.0.dist-info/METADATA,sha256=KPMmCYrAn8unm48YD5YIfIQf4kViFct7hyqcfVzRnWQ,8348 +h11-0.16.0.dist-info/RECORD,, +h11-0.16.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91 +h11-0.16.0.dist-info/licenses/LICENSE.txt,sha256=N9tbuFkm2yikJ6JYZ_ELEjIAOuob5pzLhRE4rbjm82E,1124 +h11-0.16.0.dist-info/top_level.txt,sha256=F7dC4jl3zeh8TGHEPaWJrMbeuoWbS379Gwdi-Yvdcis,4 +h11/__init__.py,sha256=iO1KzkSO42yZ6ffg-VMgbx_ZVTWGUY00nRYEWn-s3kY,1507 +h11/__pycache__/__init__.cpython-312.pyc,, +h11/__pycache__/_abnf.cpython-312.pyc,, +h11/__pycache__/_connection.cpython-312.pyc,, +h11/__pycache__/_events.cpython-312.pyc,, +h11/__pycache__/_headers.cpython-312.pyc,, +h11/__pycache__/_readers.cpython-312.pyc,, +h11/__pycache__/_receivebuffer.cpython-312.pyc,, +h11/__pycache__/_state.cpython-312.pyc,, +h11/__pycache__/_util.cpython-312.pyc,, +h11/__pycache__/_version.cpython-312.pyc,, +h11/__pycache__/_writers.cpython-312.pyc,, +h11/_abnf.py,sha256=ybixr0xsupnkA6GFAyMubuXF6Tc1lb_hF890NgCsfNc,4815 +h11/_connection.py,sha256=k9YRVf6koZqbttBW36xSWaJpWdZwa-xQVU9AHEo9DuI,26863 +h11/_events.py,sha256=I97aXoal1Wu7dkL548BANBUCkOIbe-x5CioYA9IBY14,11792 +h11/_headers.py,sha256=P7D-lBNxHwdLZPLimmYwrPG-9ZkjElvvJZJdZAgSP-4,10412 +h11/_readers.py,sha256=a4RypORUCC3d0q_kxPuBIM7jTD8iLt5X91TH0FsduN4,8590 +h11/_receivebuffer.py,sha256=xrspsdsNgWFxRfQcTXxR8RrdjRXXTK0Io5cQYWpJ1Ws,5252 +h11/_state.py,sha256=_5LG_BGR8FCcFQeBPH-TMHgm_-B-EUcWCnQof_9XjFE,13231 +h11/_util.py,sha256=LWkkjXyJaFlAy6Lt39w73UStklFT5ovcvo0TkY7RYuk,4888 +h11/_version.py,sha256=GVSsbPSPDcOuF6ptfIiXnVJoaEm3ygXbMnqlr_Giahw,686 +h11/_writers.py,sha256=oFKm6PtjeHfbj4RLX7VB7KDc1gIY53gXG3_HR9ltmTA,5081 +h11/py.typed,sha256=sow9soTwP9T_gEAQSVh7Gb8855h04Nwmhs2We-JRgZM,7 diff --git a/backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/WHEEL b/backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/WHEEL new file mode 100644 index 0000000..1eb3c49 --- /dev/null +++ b/backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: setuptools (78.1.0) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/licenses/LICENSE.txt b/backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/licenses/LICENSE.txt new file mode 100644 index 0000000..8f080ea --- /dev/null +++ b/backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/licenses/LICENSE.txt @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2016 Nathaniel J. Smith and other contributors + +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/h11-0.16.0.dist-info/top_level.txt b/backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/top_level.txt new file mode 100644 index 0000000..0d24def --- /dev/null +++ b/backend/.venv/Lib/site-packages/h11-0.16.0.dist-info/top_level.txt @@ -0,0 +1 @@ +h11 diff --git a/backend/.venv/Lib/site-packages/h11/__init__.py b/backend/.venv/Lib/site-packages/h11/__init__.py new file mode 100644 index 0000000..989e92c --- /dev/null +++ b/backend/.venv/Lib/site-packages/h11/__init__.py @@ -0,0 +1,62 @@ +# A highish-level implementation of the HTTP/1.1 wire protocol (RFC 7230), +# containing no networking code at all, loosely modelled on hyper-h2's generic +# implementation of HTTP/2 (and in particular the h2.connection.H2Connection +# class). There's still a bunch of subtle details you need to get right if you +# want to make this actually useful, because it doesn't implement all the +# semantics to check that what you're asking to write to the wire is sensible, +# but at least it gets you out of dealing with the wire itself. + +from h11._connection import Connection, NEED_DATA, PAUSED +from h11._events import ( + ConnectionClosed, + Data, + EndOfMessage, + Event, + InformationalResponse, + Request, + Response, +) +from h11._state import ( + CLIENT, + CLOSED, + DONE, + ERROR, + IDLE, + MIGHT_SWITCH_PROTOCOL, + MUST_CLOSE, + SEND_BODY, + SEND_RESPONSE, + SERVER, + SWITCHED_PROTOCOL, +) +from h11._util import LocalProtocolError, ProtocolError, RemoteProtocolError +from h11._version import __version__ + +PRODUCT_ID = "python-h11/" + __version__ + + +__all__ = ( + "Connection", + "NEED_DATA", + "PAUSED", + "ConnectionClosed", + "Data", + "EndOfMessage", + "Event", + "InformationalResponse", + "Request", + "Response", + "CLIENT", + "CLOSED", + "DONE", + "ERROR", + "IDLE", + "MUST_CLOSE", + "SEND_BODY", + "SEND_RESPONSE", + "SERVER", + "SWITCHED_PROTOCOL", + "ProtocolError", + "LocalProtocolError", + "RemoteProtocolError", +) diff --git a/backend/.venv/Lib/site-packages/h11/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/h11/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..553d4f56247e1a7f68bbf8f5937389a11ddc13c3 GIT binary patch literal 1069 zcma))&u`N(6vvbPN}Dw6uXWuz1{@|t58bpQ6CjNyVwKvaq#Xzo$;wi13yb5Dq(j>Y z{t7s8=WpS(t0g3)ow#k%WzP3wt!mKKCFKADZg zwQ>1{8J~oaFcLihi$KH)kibch6uB?qrEnUgaRy|t1SFgVS)2noECU%UK#BJxy*yTd zis!%_E`S0qf+8+~5-x)>u7C=j2lKcJs(1k`;2NmKF)42mFM%ao2X(v*mSbPqyMtH2 z3bQk4<%FpMcSjPqcbskHesZymB$Zpl_mLC1#HYEQu4_=+8g9`{e`{x;YYmAO|88h` zBt#>c((K5ldEFlwdtDTU_CBI%{RsIHt+xF=5@4IBvpo}qW8#O1N+xxw|tM!Z?iP z26|6}&kXG~Rb$iC2YsVA&}n9%n=f^fmaf8CXR`#X?Q(}Ww$~3xL>%JjK|lhk-kerU zgh_;MI2$5WAUr}r$Qp$3L>V7P2gGk4Y;3GIYC)2nX^`SzZ$k(&91=&CBges?PoQw* zIaH20jsi!Kqr_3+nCGZ+EO68~mN*tU>I}WceOh4E*P!#~9{-U+m3STT3kv^36P4rr zVPr?>c70{8;5Lyo7pIs+u6HFh7R~k2e7tgfg26I($?RUVoz@VxH7Y@9dme;eg-f<1 z{Cd&awBD28FdW+svi!GE*t8voO#I08_nQt0khN<&hsYmUYplT|tK;rkp&Owl3pivi zGqhO2bqHPGjUZebAJgn(OhywAJq;eP3L^W$F2i|J6vb&-5I0YSN7F=BOiTra3yx_y n&!;n7#8zDpyW*+P`7W&fQ0t%HoT?8$$mf|wCGk-TR$0d1iFXt5 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/h11/__pycache__/_abnf.cpython-312.pyc b/backend/.venv/Lib/site-packages/h11/__pycache__/_abnf.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a71fc23fb0c6c545597e90a548f6b4db10df1a68 GIT binary patch literal 1775 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/h11/__pycache__/_events.cpython-312.pyc b/backend/.venv/Lib/site-packages/h11/__pycache__/_events.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2943d8bbb1583db69f271ad96842c4d8532d3401 GIT binary patch literal 13215 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/h11/__pycache__/_readers.cpython-312.pyc b/backend/.venv/Lib/site-packages/h11/__pycache__/_readers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f167687d0e248883c9c019e0aa63a570974ab86d GIT binary patch literal 9642 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/h11/__pycache__/_receivebuffer.cpython-312.pyc b/backend/.venv/Lib/site-packages/h11/__pycache__/_receivebuffer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0a808a15b16a2d6f762cd7322ce3d904d4d2c16b GIT binary patch literal 4693 zcmcH+TTC0-_0G%KW55O*5=b@~UIk|%X?C;P4a%dNkTj$TX*WsJb!kU~XAEQfAa@3W zkx|hql}tBPKv@a*t4Nh9P^2bRD>a|}?~fg_3OgIANc+W~RU)<8kGAK`*yiO#>PN5S zbI(2Z-0O4Cd;V5eClVNa!)NvTK|;R4MS1WgWGe&65>biD#7WqhnJ@!uHqIuvFqh!N zd_o8d3{kmJChTH~Mq>5lYqn>V2fBZIUB(`>4i@&Xhn~PFAf0dLz*BKkESxq}h<4y5JhiMKyDh zCWj&ntjYtG$H8yw9DpTaR`wp3I5I@8&{PIiC3WK~VTEVyktVC`5XH?9Z+S-2rlwG; zq%A>K6;rVqDxOO`-ktP z=(sVVM6}^#%ryFxNF+6xH1*_YUnE7f;SnV=t|iss<5OC4YWSKyGHmFk)&~d1l~K(Y z9y@vRgiIY9kJvUoK9RQEvaBa{QStm8TA#G$>@EEKcApBO5#8_=US;!`GM<9ar1wLKRoL0=K?VB}_>rtihxqC&uv9 zo{?d;-7v(?ToB<^_PFFcNm8V!KCP)zaxyWZQ7ILbY(q*>no3CKm?o7HSLNUkqy@|l zv z&*pBg`8x9Mj{QMeNhRxW&(0vls!=UWRdxoPqFlIVk&B0;dq%8g4*`}c2ih%J4IGnI z`SBi5$syBI=B<8L*&;hDTv~wht{FHu%fTsc`G)N|!%Ws#C+1 zu-NrVdQ{R)NjIcODgm|51S9LoswTCo=O%{D7Cxs=-24xWp-o(bTo#v5rl}n)Xm^W` z>PgkfW#|GS-VPqC(W$PoVJg&w3a4t*mUjYhU5U%OI&E

>daG&&kdQcDq5PQqOd~ z&08vLci``hD1bTgS|mr>mK&A_UUv2uI{TmfsL*+C?Va;^ck6m{>r!knwv<{-Esy3; ze7x3tA?w}nHs{)(dk??r>RAasXW0R}LA z7l6G}xA|`fYuk%M;&u+V{Pw>&Ei%V;5H@vF8fi7ETVV9lL}n zqq~$cf_AZL_&kxjP^do&g&!J$#C#%mam{W6{DCFUq9@n2=9jX4-hvJDzTS=6hK2UUj_lP9 zUocy{KP_Qc*=gxAAWOva#&m+ttg_?aCO1h3G0|P@(Mc%BkWWdPyGN$EPsu$d#5>0N@a;;Aw&M9XyEraZXu0yL_q;=+4)6|Lc{n-*1%Hs zSwoO~;gPuCG7<+*!kjl03gYKYQb}mCY>6^7FX|+GD9To?EZ?0};?53j1YU~020e-Z zlOctSLMW<~;>R1*yQE3q!KH-2ZkNz9v>U;D2+&CMJc5e=R*7v&J3j0$XB(V=9pm=^ z?n8Cvgr1_v3c=;B6=5Zv@A;_Ee!572@GP~3Q_;-`M{}K91g4@3@qmK^y)E|v;%!Bj zTL|PLMFP{ZzJ*gU=oUIx-bYgB(~q7F7T&*%^v+_?C$z5|d>Sf*&TJ9Di|vxowEUA5 z_37!=RH5tK7J+r~$Bav8d3NhHfyqfPUW=ug#TjYCa+&D~NO8_v?f0YFEcoJ4;_zK& z)nI#~$2H4y{r0t6gVzR!E>Y~I9SvMT3{!OJbMA~|k8|_}&@kN@s6MbM!+cFVUlZ}~ xq^Cf7HoUEQ@z7jNafl(oBMa}@4iQ^vf6}|!yB7E`PyGLM#TW*h0-^l}{{=`K1wH@( literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/h11/__pycache__/_state.cpython-312.pyc b/backend/.venv/Lib/site-packages/h11/__pycache__/_state.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e705b80b44de33c2f718fab8022c20ea4c5e97e1 GIT binary patch literal 8457 zcmb6;ZEO=smeqFKX{YVjiJjQ_#DRQZJ~9D91_)mvHX#ral$b2z<<9ch9dP0}*>(pA z1P!}FC$pLpVedzRmeXW*(QOc%HY1I6jBcc3rTwwe&5t(2DOM}eA?^OS{bwee_HKUN zd)2nvF=j4XN?ujJ_v%&Et5@&6D*wC1Qcj@ky?iYC+XICB5kGRpo^5Q5=?PgR7fFOf zm>8L20?d>ypqtVM^iynroiYRrQ^tUCsw_~(kccj#k8%I3qb)XOnko;JPw@esAy-Jm z@GB-@){%Y^G2SJSGJzNPXWUa(9VcL+6cbR&izpS8!UM%zM6pte1t=9o6dR>jfnqD7 zR8mSMP^yY3Rg_`}ilc~Pr<7`-)D%%1l;Q-6tB6ufDYZbUE27j;NX#`4B z5yeF*+koOOqSOjH!6@*xpvFzDGQieRtRdgZ@{Q{dufkm4LY&$T)C(5DDl`a{LZje_ z>Y#3d|7}7Qw5uqN5$xI8k*#Z@L~z1?b(BOop#u6tU%?Ii8U)L@POwGwf=y_Kf5bHl zF2FgVU5j;;-O?C&`B7b9yHGFeh%_HnSC1=IHL+=>1$xNSVZG6?q;SJCQgk{ViYfY0K~fC<*_oK2u>QFjK`~s61L@BU_F@!fmq({m z4Niwcu?ym~G##Ff`9yJARJc(gE=A))%)=|jzQFn8fgqPboitanv8|8yp5ANPx<#RG%N{KjROM{%FA8cP4mY zWY|C4H$13RstBJ~Lm7M{Bf}$MTwJc;l(B4>0W1=M1egd3=;j!YPOJdb&=bAF1%vU> zln@Lm<-y?8bYwP$ZF4aAli5&Ar92@UDCPU%z9W~fPm7a@nNV1`9G{R9dqd&y^eis> z%HHs_C|v$H6rL2~k;@&|g!r|~gVB#KC!&(D7dlLat_X?CSNHAvAefLslF%_TN9RDn z-+}lI1Ax0E&2r*4Xi+@q+cYIep>QmeNNjm&R_Hz?)}fFl1XP?GTS%ec=h$dQK#7Ro zvUnRXmllr{5y5?IXyOsIW$~53Tv|L*LoL?x69&KAr>_3*zj4qy@1 zIZuLF5+M>&XnC5gftrowKs9EOMB?%-np@+ShKuT;SDtr{cyvR42><1if-n;d#iG{) zMW2A6@0x+g1(7V6xE__lSA#R+^vrZ36icXa$_7Gd>`;s}fF+(V3Y!pO;|W}kTXX}& zXc~=2rC{);t7!QhIm-9Im+%0%Lo(&0ep{0L)cTeq$9tK7y_jTQajkzk*7tk=H{GvB zepmwP4&O&36NC4F`PbLcaa##klBA{WQEh;(vGGvZC zVTL?<>WsuAz@{_@$D^X4M(v;^Mz35EL?HsLP#l6gY;OY62^1|J2av##-C1>5K!;%= zkq8QyBHe5(*2yL^TxCe20easd>kZ9G_C9})U+|{5+B9cg<2q7Y$A560R2Q2p2*;yZ z*bj|j3xd_=Z3xKOQn*^MhSMENow{Ij6@Tmk7GjQ=I-~cs01@y z$VdX?#T}Baquc(@!W47X_5{eEq|%!m011n@jZhbtQj48uo}z(5VYaaO;z?kH?LQ2a zq7OwPR4KU)_5pU&1~=uD6OKh;#>GeHX2<*VQ<~q3D%uW%fQoR_TT@)?8s|xIo|QeX zxDVgeS2w>dY+kQ zbN3e5I99?Oo)(a}3+9XoeD*s#XEISjj5(0yBl2S)#+Ku9dc*Asv9hYx>JuyO~cW`L|l}@jR=Vua3g|v2tTv_ zCcCqx{EbpJBK%}lNJy$@?uA|+gXV(70Thi+QQ?D{fh2I>+*nj!tvM$=Y(LG^tRYWJ!2Js&*vCB3iAp1g^#NUJ}7#q~lTv-44V zif`UDj@h|FZk*{@;(uJ%g{z=ks0jZnDtzp$Sssx2eWo(tpe|m>S&Hn~0PT zAS!NNkCb`(hylljE$x5iX^5F4JBXA&cr8R6WQbG--D%MRvy>0ks_dL8-quN$9Cw77 zz{^=tnb%EVI4&x1WPV^(PqW&{dBX_#neIBdq5p_nhx_o*&8~1L-Y&VXhT@SJJdWU| zyV0+>Z{2oZzbeGt7=Mq!2Qav41^^#m%oroZeE<~hoG?e<0z@22#H2(q_)w5)=f?4A zaVjK<^+0&XUKInCshHxzbv4!&*{gUSy4~DY>`>L<`~!z&H(Ks5pfAlgDytXy2mF#Z zWou3vGCI!WT6Y~-^`=~hpSPx5CtuX1T!YDhjEyw5WM-IB4rl9MM)* z=Lq-6pk)HnrlK;hkCME{Kz~$X+zGsa78MAqSxch%P>Eji%;Zk67iNwuFrOY(Ga|FX zM&O}PJ?)1`Vl%KiLBh8J-jpAyL9BQG#a7 z3O_L&#oUSBlFGv1f#9jE`1JRJ!1tYg+Ou?OeiTptchL6^d0kPpUcYUb{SE&)|84!A z{;-po%M^i9^6{)N;!8v^S*R;uJ7qyVn5>_ z^2^?rE>Ffl8u!9AsKNbN&%>U_*HZNztL(q8H;^_qQaH3w5Q2UjOw z?Ekjrbh1Bfw%tE>@7$WXDP?Y2y8g=C{@QB4f9u|@rPxdBuGhAjHvf7In{4iZH&kw5DiXFi21ags%v zk`~M>e^LtOmB-QRZeFmOw6(^kC3iIL4!K2PmR?=d2-X2fTx`5UHO6BePBm{7MPKUF zL=9)8nm4t3bOrBRl58LXtU4~-kb>d4a7?)AE)G=191*lkyz4`*&s*>J-0OMN{kZE{ z&6f_juKOk5je(`=!{_Y3@n7+)w`H3T;s}HgqO(+h!Pp%4Kl%A5GS`&+1Z+|@PMPbJ zt)1)6#z)fQv1fj{W`F+n3>TP#Fw~HGm@8=r7V)krHX=BN0DZ2AiHCR!ffvCU1fvMh zcEk$^Fq0B7ouLs~y)@!FiXWT15QpG@;Xm;WfV*Tv#~VIkGIct`zU7wX8=rT;dJOwk z{ToT6<is+by^K=`M%J`zI972OS2DmFVC*{S6iR__<76o8(($E zd(WiW2jseel;dos3^_RzVuIGj_BMm_?FGhUIG{e9)7&oQxJP<5@;mr`THTM2!bR*jPSR}2X18wGva zL_bfT1?htw-7&>ZQ!ju1nF4>z5r=RJHqAEsV$%sB0zbfnq>y6v#UsPx=fU~Hj}_t| zvQ`ho)vS&FI+VYt(0tDd^NqvF3eiUp_|?QdiY~lpM2rN~42tYS;f|_5w;UHIfdyky z;*SuGGJ1w#{_?S&FulwgIr);D{1d79Px8TcMl-LwQ}(urVNA(O%dY<>(0I#j`YOk- zLrXU_+QOL?uHcJXKBIjVak`c-70@=1aAr9x1xHvqvsxf?iCZapAzuak;HGmyGgE6CL4P|fiMyF0D_DmHq@F?y2l1biiV0BEcIGW}v7raZJ z<;$yGvi%ScW$U)(8o6R;nyZqlTbHlNj*c`}Ay+mpcgwb2X|8ceOmnqM`_r5yDP}57 z7GuVticOmvmd4X&$3pbA#j!9hn;VyIXG{ibIa~!zHEDD6@-a$HTedF`%jPb*yFYEI zUid^dx67U*!0Do#Re#-l@>6NG!&IExx?rXCa%1NP*~aKHrx>bHQ?ey_<6Z}x;~Nh< zHJk?O3gm51*Ag&%HMA zN&lUpg|Vf8?AVzu`YKO)@0?#ay>wQ#x2FxJWOo5)@z=pTXQrChCd@Oszcfe;bKpBj J;~CX={2w8u=-2=N literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/h11/__pycache__/_util.cpython-312.pyc b/backend/.venv/Lib/site-packages/h11/__pycache__/_util.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d11f62473428c17d2a7f6feafab12f4f4314fc42 GIT binary patch literal 4713 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/h11/__pycache__/_writers.cpython-312.pyc b/backend/.venv/Lib/site-packages/h11/__pycache__/_writers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2999a2d6f5115c522a2bcf922eb8cd438ecbbc48 GIT binary patch literal 6279 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" + r":" + r"{OWS}" + r"(?P{field_value})" + r"{OWS}".format(**globals()) +) + +# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#request.line +# +# request-line = method SP request-target SP HTTP-version CRLF +# method = token +# HTTP-version = HTTP-name "/" DIGIT "." DIGIT +# HTTP-name = %x48.54.54.50 ; "HTTP", case-sensitive +# +# request-target is complicated (see RFC 7230 sec 5.3) -- could be path, full +# URL, host+port (for connect), or even "*", but in any case we are guaranteed +# that it contists of the visible printing characters. +method = token +request_target = r"{vchar}+".format(**globals()) +http_version = r"HTTP/(?P[0-9]\.[0-9])" +request_line = ( + r"(?P{method})" + r" " + r"(?P{request_target})" + r" " + r"{http_version}".format(**globals()) +) + +# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#status.line +# +# status-line = HTTP-version SP status-code SP reason-phrase CRLF +# status-code = 3DIGIT +# reason-phrase = *( HTAB / SP / VCHAR / obs-text ) +status_code = r"[0-9]{3}" +reason_phrase = r"([ \t]|{vchar_or_obs_text})*".format(**globals()) +status_line = ( + r"{http_version}" + r" " + r"(?P{status_code})" + # However, there are apparently a few too many servers out there that just + # leave out the reason phrase: + # https://github.com/scrapy/scrapy/issues/345#issuecomment-281756036 + # https://github.com/seanmonstar/httparse/issues/29 + # so make it optional. ?: is a non-capturing group. + r"(?: (?P{reason_phrase}))?".format(**globals()) +) + +HEXDIG = r"[0-9A-Fa-f]" +# Actually +# +# chunk-size = 1*HEXDIG +# +# but we impose an upper-limit to avoid ridiculosity. len(str(2**64)) == 20 +chunk_size = r"({HEXDIG}){{1,20}}".format(**globals()) +# Actually +# +# chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-val ] ) +# +# but we aren't parsing the things so we don't really care. +chunk_ext = r";.*" +chunk_header = ( + r"(?P{chunk_size})" + r"(?P{chunk_ext})?" + r"{OWS}\r\n".format( + **globals() + ) # Even though the specification does not allow for extra whitespaces, + # we are lenient with trailing whitespaces because some servers on the wild use it. +) diff --git a/backend/.venv/Lib/site-packages/h11/_connection.py b/backend/.venv/Lib/site-packages/h11/_connection.py new file mode 100644 index 0000000..e37d82a --- /dev/null +++ b/backend/.venv/Lib/site-packages/h11/_connection.py @@ -0,0 +1,659 @@ +# This contains the main Connection class. Everything in h11 revolves around +# this. +from typing import ( + Any, + Callable, + cast, + Dict, + List, + Optional, + overload, + Tuple, + Type, + Union, +) + +from ._events import ( + ConnectionClosed, + Data, + EndOfMessage, + Event, + InformationalResponse, + Request, + Response, +) +from ._headers import get_comma_header, has_expect_100_continue, set_comma_header +from ._readers import READERS, ReadersType +from ._receivebuffer import ReceiveBuffer +from ._state import ( + _SWITCH_CONNECT, + _SWITCH_UPGRADE, + CLIENT, + ConnectionState, + DONE, + ERROR, + MIGHT_SWITCH_PROTOCOL, + SEND_BODY, + SERVER, + SWITCHED_PROTOCOL, +) +from ._util import ( # Import the internal things we need + LocalProtocolError, + RemoteProtocolError, + Sentinel, +) +from ._writers import WRITERS, WritersType + +# Everything in __all__ gets re-exported as part of the h11 public API. +__all__ = ["Connection", "NEED_DATA", "PAUSED"] + + +class NEED_DATA(Sentinel, metaclass=Sentinel): + pass + + +class PAUSED(Sentinel, metaclass=Sentinel): + pass + + +# If we ever have this much buffered without it making a complete parseable +# event, we error out. The only time we really buffer is when reading the +# request/response line + headers together, so this is effectively the limit on +# the size of that. +# +# Some precedents for defaults: +# - node.js: 80 * 1024 +# - tomcat: 8 * 1024 +# - IIS: 16 * 1024 +# - Apache: <8 KiB per line> +DEFAULT_MAX_INCOMPLETE_EVENT_SIZE = 16 * 1024 + + +# RFC 7230's rules for connection lifecycles: +# - If either side says they want to close the connection, then the connection +# must close. +# - HTTP/1.1 defaults to keep-alive unless someone says Connection: close +# - HTTP/1.0 defaults to close unless both sides say Connection: keep-alive +# (and even this is a mess -- e.g. if you're implementing a proxy then +# sending Connection: keep-alive is forbidden). +# +# We simplify life by simply not supporting keep-alive with HTTP/1.0 peers. So +# our rule is: +# - If someone says Connection: close, we will close +# - If someone uses HTTP/1.0, we will close. +def _keep_alive(event: Union[Request, Response]) -> bool: + connection = get_comma_header(event.headers, b"connection") + if b"close" in connection: + return False + if getattr(event, "http_version", b"1.1") < b"1.1": + return False + return True + + +def _body_framing( + request_method: bytes, event: Union[Request, Response] +) -> Tuple[str, Union[Tuple[()], Tuple[int]]]: + # Called when we enter SEND_BODY to figure out framing information for + # this body. + # + # These are the only two events that can trigger a SEND_BODY state: + assert type(event) in (Request, Response) + # Returns one of: + # + # ("content-length", count) + # ("chunked", ()) + # ("http/1.0", ()) + # + # which are (lookup key, *args) for constructing body reader/writer + # objects. + # + # Reference: https://tools.ietf.org/html/rfc7230#section-3.3.3 + # + # Step 1: some responses always have an empty body, regardless of what the + # headers say. + if type(event) is Response: + if ( + event.status_code in (204, 304) + or request_method == b"HEAD" + or (request_method == b"CONNECT" and 200 <= event.status_code < 300) + ): + return ("content-length", (0,)) + # Section 3.3.3 also lists another case -- responses with status_code + # < 200. For us these are InformationalResponses, not Responses, so + # they can't get into this function in the first place. + assert event.status_code >= 200 + + # Step 2: check for Transfer-Encoding (T-E beats C-L): + transfer_encodings = get_comma_header(event.headers, b"transfer-encoding") + if transfer_encodings: + assert transfer_encodings == [b"chunked"] + return ("chunked", ()) + + # Step 3: check for Content-Length + content_lengths = get_comma_header(event.headers, b"content-length") + if content_lengths: + return ("content-length", (int(content_lengths[0]),)) + + # Step 4: no applicable headers; fallback/default depends on type + if type(event) is Request: + return ("content-length", (0,)) + else: + return ("http/1.0", ()) + + +################################################################ +# +# The main Connection class +# +################################################################ + + +class Connection: + """An object encapsulating the state of an HTTP connection. + + Args: + our_role: If you're implementing a client, pass :data:`h11.CLIENT`. If + you're implementing a server, pass :data:`h11.SERVER`. + + max_incomplete_event_size (int): + The maximum number of bytes we're willing to buffer of an + incomplete event. In practice this mostly sets a limit on the + maximum size of the request/response line + headers. If this is + exceeded, then :meth:`next_event` will raise + :exc:`RemoteProtocolError`. + + """ + + def __init__( + self, + our_role: Type[Sentinel], + max_incomplete_event_size: int = DEFAULT_MAX_INCOMPLETE_EVENT_SIZE, + ) -> None: + self._max_incomplete_event_size = max_incomplete_event_size + # State and role tracking + if our_role not in (CLIENT, SERVER): + raise ValueError(f"expected CLIENT or SERVER, not {our_role!r}") + self.our_role = our_role + self.their_role: Type[Sentinel] + if our_role is CLIENT: + self.their_role = SERVER + else: + self.their_role = CLIENT + self._cstate = ConnectionState() + + # Callables for converting data->events or vice-versa given the + # current state + self._writer = self._get_io_object(self.our_role, None, WRITERS) + self._reader = self._get_io_object(self.their_role, None, READERS) + + # Holds any unprocessed received data + self._receive_buffer = ReceiveBuffer() + # If this is true, then it indicates that the incoming connection was + # closed *after* the end of whatever's in self._receive_buffer: + self._receive_buffer_closed = False + + # Extra bits of state that don't fit into the state machine. + # + # These two are only used to interpret framing headers for figuring + # out how to read/write response bodies. their_http_version is also + # made available as a convenient public API. + self.their_http_version: Optional[bytes] = None + self._request_method: Optional[bytes] = None + # This is pure flow-control and doesn't at all affect the set of legal + # transitions, so no need to bother ConnectionState with it: + self.client_is_waiting_for_100_continue = False + + @property + def states(self) -> Dict[Type[Sentinel], Type[Sentinel]]: + """A dictionary like:: + + {CLIENT: , SERVER: } + + See :ref:`state-machine` for details. + + """ + return dict(self._cstate.states) + + @property + def our_state(self) -> Type[Sentinel]: + """The current state of whichever role we are playing. See + :ref:`state-machine` for details. + """ + return self._cstate.states[self.our_role] + + @property + def their_state(self) -> Type[Sentinel]: + """The current state of whichever role we are NOT playing. See + :ref:`state-machine` for details. + """ + return self._cstate.states[self.their_role] + + @property + def they_are_waiting_for_100_continue(self) -> bool: + return self.their_role is CLIENT and self.client_is_waiting_for_100_continue + + def start_next_cycle(self) -> None: + """Attempt to reset our connection state for a new request/response + cycle. + + If both client and server are in :data:`DONE` state, then resets them + both to :data:`IDLE` state in preparation for a new request/response + cycle on this same connection. Otherwise, raises a + :exc:`LocalProtocolError`. + + See :ref:`keepalive-and-pipelining`. + + """ + old_states = dict(self._cstate.states) + self._cstate.start_next_cycle() + self._request_method = None + # self.their_http_version gets left alone, since it presumably lasts + # beyond a single request/response cycle + assert not self.client_is_waiting_for_100_continue + self._respond_to_state_changes(old_states) + + def _process_error(self, role: Type[Sentinel]) -> None: + old_states = dict(self._cstate.states) + self._cstate.process_error(role) + self._respond_to_state_changes(old_states) + + def _server_switch_event(self, event: Event) -> Optional[Type[Sentinel]]: + if type(event) is InformationalResponse and event.status_code == 101: + return _SWITCH_UPGRADE + if type(event) is Response: + if ( + _SWITCH_CONNECT in self._cstate.pending_switch_proposals + and 200 <= event.status_code < 300 + ): + return _SWITCH_CONNECT + return None + + # All events go through here + def _process_event(self, role: Type[Sentinel], event: Event) -> None: + # First, pass the event through the state machine to make sure it + # succeeds. + old_states = dict(self._cstate.states) + if role is CLIENT and type(event) is Request: + if event.method == b"CONNECT": + self._cstate.process_client_switch_proposal(_SWITCH_CONNECT) + if get_comma_header(event.headers, b"upgrade"): + self._cstate.process_client_switch_proposal(_SWITCH_UPGRADE) + server_switch_event = None + if role is SERVER: + server_switch_event = self._server_switch_event(event) + self._cstate.process_event(role, type(event), server_switch_event) + + # Then perform the updates triggered by it. + + if type(event) is Request: + self._request_method = event.method + + if role is self.their_role and type(event) in ( + Request, + Response, + InformationalResponse, + ): + event = cast(Union[Request, Response, InformationalResponse], event) + self.their_http_version = event.http_version + + # Keep alive handling + # + # RFC 7230 doesn't really say what one should do if Connection: close + # shows up on a 1xx InformationalResponse. I think the idea is that + # this is not supposed to happen. In any case, if it does happen, we + # ignore it. + if type(event) in (Request, Response) and not _keep_alive( + cast(Union[Request, Response], event) + ): + self._cstate.process_keep_alive_disabled() + + # 100-continue + if type(event) is Request and has_expect_100_continue(event): + self.client_is_waiting_for_100_continue = True + if type(event) in (InformationalResponse, Response): + self.client_is_waiting_for_100_continue = False + if role is CLIENT and type(event) in (Data, EndOfMessage): + self.client_is_waiting_for_100_continue = False + + self._respond_to_state_changes(old_states, event) + + def _get_io_object( + self, + role: Type[Sentinel], + event: Optional[Event], + io_dict: Union[ReadersType, WritersType], + ) -> Optional[Callable[..., Any]]: + # event may be None; it's only used when entering SEND_BODY + state = self._cstate.states[role] + if state is SEND_BODY: + # Special case: the io_dict has a dict of reader/writer factories + # that depend on the request/response framing. + framing_type, args = _body_framing( + cast(bytes, self._request_method), cast(Union[Request, Response], event) + ) + return io_dict[SEND_BODY][framing_type](*args) # type: ignore[index] + else: + # General case: the io_dict just has the appropriate reader/writer + # for this state + return io_dict.get((role, state)) # type: ignore[return-value] + + # This must be called after any action that might have caused + # self._cstate.states to change. + def _respond_to_state_changes( + self, + old_states: Dict[Type[Sentinel], Type[Sentinel]], + event: Optional[Event] = None, + ) -> None: + # Update reader/writer + if self.our_state != old_states[self.our_role]: + self._writer = self._get_io_object(self.our_role, event, WRITERS) + if self.their_state != old_states[self.their_role]: + self._reader = self._get_io_object(self.their_role, event, READERS) + + @property + def trailing_data(self) -> Tuple[bytes, bool]: + """Data that has been received, but not yet processed, represented as + a tuple with two elements, where the first is a byte-string containing + the unprocessed data itself, and the second is a bool that is True if + the receive connection was closed. + + See :ref:`switching-protocols` for discussion of why you'd want this. + """ + return (bytes(self._receive_buffer), self._receive_buffer_closed) + + def receive_data(self, data: bytes) -> None: + """Add data to our internal receive buffer. + + This does not actually do any processing on the data, just stores + it. To trigger processing, you have to call :meth:`next_event`. + + Args: + data (:term:`bytes-like object`): + The new data that was just received. + + Special case: If *data* is an empty byte-string like ``b""``, + then this indicates that the remote side has closed the + connection (end of file). Normally this is convenient, because + standard Python APIs like :meth:`file.read` or + :meth:`socket.recv` use ``b""`` to indicate end-of-file, while + other failures to read are indicated using other mechanisms + like raising :exc:`TimeoutError`. When using such an API you + can just blindly pass through whatever you get from ``read`` + to :meth:`receive_data`, and everything will work. + + But, if you have an API where reading an empty string is a + valid non-EOF condition, then you need to be aware of this and + make sure to check for such strings and avoid passing them to + :meth:`receive_data`. + + Returns: + Nothing, but after calling this you should call :meth:`next_event` + to parse the newly received data. + + Raises: + RuntimeError: + Raised if you pass an empty *data*, indicating EOF, and then + pass a non-empty *data*, indicating more data that somehow + arrived after the EOF. + + (Calling ``receive_data(b"")`` multiple times is fine, + and equivalent to calling it once.) + + """ + if data: + if self._receive_buffer_closed: + raise RuntimeError("received close, then received more data?") + self._receive_buffer += data + else: + self._receive_buffer_closed = True + + def _extract_next_receive_event( + self, + ) -> Union[Event, Type[NEED_DATA], Type[PAUSED]]: + state = self.their_state + # We don't pause immediately when they enter DONE, because even in + # DONE state we can still process a ConnectionClosed() event. But + # if we have data in our buffer, then we definitely aren't getting + # a ConnectionClosed() immediately and we need to pause. + if state is DONE and self._receive_buffer: + return PAUSED + if state is MIGHT_SWITCH_PROTOCOL or state is SWITCHED_PROTOCOL: + return PAUSED + assert self._reader is not None + event = self._reader(self._receive_buffer) + if event is None: + if not self._receive_buffer and self._receive_buffer_closed: + # In some unusual cases (basically just HTTP/1.0 bodies), EOF + # triggers an actual protocol event; in that case, we want to + # return that event, and then the state will change and we'll + # get called again to generate the actual ConnectionClosed(). + if hasattr(self._reader, "read_eof"): + event = self._reader.read_eof() + else: + event = ConnectionClosed() + if event is None: + event = NEED_DATA + return event # type: ignore[no-any-return] + + def next_event(self) -> Union[Event, Type[NEED_DATA], Type[PAUSED]]: + """Parse the next event out of our receive buffer, update our internal + state, and return it. + + This is a mutating operation -- think of it like calling :func:`next` + on an iterator. + + Returns: + : One of three things: + + 1) An event object -- see :ref:`events`. + + 2) The special constant :data:`NEED_DATA`, which indicates that + you need to read more data from your socket and pass it to + :meth:`receive_data` before this method will be able to return + any more events. + + 3) The special constant :data:`PAUSED`, which indicates that we + are not in a state where we can process incoming data (usually + because the peer has finished their part of the current + request/response cycle, and you have not yet called + :meth:`start_next_cycle`). See :ref:`flow-control` for details. + + Raises: + RemoteProtocolError: + The peer has misbehaved. You should close the connection + (possibly after sending some kind of 4xx response). + + Once this method returns :class:`ConnectionClosed` once, then all + subsequent calls will also return :class:`ConnectionClosed`. + + If this method raises any exception besides :exc:`RemoteProtocolError` + then that's a bug -- if it happens please file a bug report! + + If this method raises any exception then it also sets + :attr:`Connection.their_state` to :data:`ERROR` -- see + :ref:`error-handling` for discussion. + + """ + + if self.their_state is ERROR: + raise RemoteProtocolError("Can't receive data when peer state is ERROR") + try: + event = self._extract_next_receive_event() + if event not in [NEED_DATA, PAUSED]: + self._process_event(self.their_role, cast(Event, event)) + if event is NEED_DATA: + if len(self._receive_buffer) > self._max_incomplete_event_size: + # 431 is "Request header fields too large" which is pretty + # much the only situation where we can get here + raise RemoteProtocolError( + "Receive buffer too long", error_status_hint=431 + ) + if self._receive_buffer_closed: + # We're still trying to complete some event, but that's + # never going to happen because no more data is coming + raise RemoteProtocolError("peer unexpectedly closed connection") + return event + except BaseException as exc: + self._process_error(self.their_role) + if isinstance(exc, LocalProtocolError): + exc._reraise_as_remote_protocol_error() + else: + raise + + @overload + def send(self, event: ConnectionClosed) -> None: + ... + + @overload + def send( + self, event: Union[Request, InformationalResponse, Response, Data, EndOfMessage] + ) -> bytes: + ... + + @overload + def send(self, event: Event) -> Optional[bytes]: + ... + + def send(self, event: Event) -> Optional[bytes]: + """Convert a high-level event into bytes that can be sent to the peer, + while updating our internal state machine. + + Args: + event: The :ref:`event ` to send. + + Returns: + If ``type(event) is ConnectionClosed``, then returns + ``None``. Otherwise, returns a :term:`bytes-like object`. + + Raises: + LocalProtocolError: + Sending this event at this time would violate our + understanding of the HTTP/1.1 protocol. + + If this method raises any exception then it also sets + :attr:`Connection.our_state` to :data:`ERROR` -- see + :ref:`error-handling` for discussion. + + """ + data_list = self.send_with_data_passthrough(event) + if data_list is None: + return None + else: + return b"".join(data_list) + + def send_with_data_passthrough(self, event: Event) -> Optional[List[bytes]]: + """Identical to :meth:`send`, except that in situations where + :meth:`send` returns a single :term:`bytes-like object`, this instead + returns a list of them -- and when sending a :class:`Data` event, this + list is guaranteed to contain the exact object you passed in as + :attr:`Data.data`. See :ref:`sendfile` for discussion. + + """ + if self.our_state is ERROR: + raise LocalProtocolError("Can't send data when our state is ERROR") + try: + if type(event) is Response: + event = self._clean_up_response_headers_for_sending(event) + # We want to call _process_event before calling the writer, + # because if someone tries to do something invalid then this will + # give a sensible error message, while our writers all just assume + # they will only receive valid events. But, _process_event might + # change self._writer. So we have to do a little dance: + writer = self._writer + self._process_event(self.our_role, event) + if type(event) is ConnectionClosed: + return None + else: + # In any situation where writer is None, process_event should + # have raised ProtocolError + assert writer is not None + data_list: List[bytes] = [] + writer(event, data_list.append) + return data_list + except: + self._process_error(self.our_role) + raise + + def send_failed(self) -> None: + """Notify the state machine that we failed to send the data it gave + us. + + This causes :attr:`Connection.our_state` to immediately become + :data:`ERROR` -- see :ref:`error-handling` for discussion. + + """ + self._process_error(self.our_role) + + # When sending a Response, we take responsibility for a few things: + # + # - Sometimes you MUST set Connection: close. We take care of those + # times. (You can also set it yourself if you want, and if you do then + # we'll respect that and close the connection at the right time. But you + # don't have to worry about that unless you want to.) + # + # - The user has to set Content-Length if they want it. Otherwise, for + # responses that have bodies (e.g. not HEAD), then we will automatically + # select the right mechanism for streaming a body of unknown length, + # which depends on depending on the peer's HTTP version. + # + # This function's *only* responsibility is making sure headers are set up + # right -- everything downstream just looks at the headers. There are no + # side channels. + def _clean_up_response_headers_for_sending(self, response: Response) -> Response: + assert type(response) is Response + + headers = response.headers + need_close = False + + # HEAD requests need some special handling: they always act like they + # have Content-Length: 0, and that's how _body_framing treats + # them. But their headers are supposed to match what we would send if + # the request was a GET. (Technically there is one deviation allowed: + # we're allowed to leave out the framing headers -- see + # https://tools.ietf.org/html/rfc7231#section-4.3.2 . But it's just as + # easy to get them right.) + method_for_choosing_headers = cast(bytes, self._request_method) + if method_for_choosing_headers == b"HEAD": + method_for_choosing_headers = b"GET" + framing_type, _ = _body_framing(method_for_choosing_headers, response) + if framing_type in ("chunked", "http/1.0"): + # This response has a body of unknown length. + # If our peer is HTTP/1.1, we use Transfer-Encoding: chunked + # If our peer is HTTP/1.0, we use no framing headers, and close the + # connection afterwards. + # + # Make sure to clear Content-Length (in principle user could have + # set both and then we ignored Content-Length b/c + # Transfer-Encoding overwrote it -- this would be naughty of them, + # but the HTTP spec says that if our peer does this then we have + # to fix it instead of erroring out, so we'll accord the user the + # same respect). + headers = set_comma_header(headers, b"content-length", []) + if self.their_http_version is None or self.their_http_version < b"1.1": + # Either we never got a valid request and are sending back an + # error (their_http_version is None), so we assume the worst; + # or else we did get a valid HTTP/1.0 request, so we know that + # they don't understand chunked encoding. + headers = set_comma_header(headers, b"transfer-encoding", []) + # This is actually redundant ATM, since currently we + # unconditionally disable keep-alive when talking to HTTP/1.0 + # peers. But let's be defensive just in case we add + # Connection: keep-alive support later: + if self._request_method != b"HEAD": + need_close = True + else: + headers = set_comma_header(headers, b"transfer-encoding", [b"chunked"]) + + if not self._cstate.keep_alive or need_close: + # Make sure Connection: close is set + connection = set(get_comma_header(headers, b"connection")) + connection.discard(b"keep-alive") + connection.add(b"close") + headers = set_comma_header(headers, b"connection", sorted(connection)) + + return Response( + headers=headers, + status_code=response.status_code, + http_version=response.http_version, + reason=response.reason, + ) diff --git a/backend/.venv/Lib/site-packages/h11/_events.py b/backend/.venv/Lib/site-packages/h11/_events.py new file mode 100644 index 0000000..ca1c3ad --- /dev/null +++ b/backend/.venv/Lib/site-packages/h11/_events.py @@ -0,0 +1,369 @@ +# High level events that make up HTTP/1.1 conversations. Loosely inspired by +# the corresponding events in hyper-h2: +# +# http://python-hyper.org/h2/en/stable/api.html#events +# +# Don't subclass these. Stuff will break. + +import re +from abc import ABC +from dataclasses import dataclass +from typing import List, Tuple, Union + +from ._abnf import method, request_target +from ._headers import Headers, normalize_and_validate +from ._util import bytesify, LocalProtocolError, validate + +# Everything in __all__ gets re-exported as part of the h11 public API. +__all__ = [ + "Event", + "Request", + "InformationalResponse", + "Response", + "Data", + "EndOfMessage", + "ConnectionClosed", +] + +method_re = re.compile(method.encode("ascii")) +request_target_re = re.compile(request_target.encode("ascii")) + + +class Event(ABC): + """ + Base class for h11 events. + """ + + __slots__ = () + + +@dataclass(init=False, frozen=True) +class Request(Event): + """The beginning of an HTTP request. + + Fields: + + .. attribute:: method + + An HTTP method, e.g. ``b"GET"`` or ``b"POST"``. Always a byte + string. :term:`Bytes-like objects ` and native + strings containing only ascii characters will be automatically + converted to byte strings. + + .. attribute:: target + + The target of an HTTP request, e.g. ``b"/index.html"``, or one of the + more exotic formats described in `RFC 7320, section 5.3 + `_. Always a byte + string. :term:`Bytes-like objects ` and native + strings containing only ascii characters will be automatically + converted to byte strings. + + .. attribute:: headers + + Request headers, represented as a list of (name, value) pairs. See + :ref:`the header normalization rules ` for details. + + .. attribute:: http_version + + The HTTP protocol version, represented as a byte string like + ``b"1.1"``. See :ref:`the HTTP version normalization rules + ` for details. + + """ + + __slots__ = ("method", "headers", "target", "http_version") + + method: bytes + headers: Headers + target: bytes + http_version: bytes + + def __init__( + self, + *, + method: Union[bytes, str], + headers: Union[Headers, List[Tuple[bytes, bytes]], List[Tuple[str, str]]], + target: Union[bytes, str], + http_version: Union[bytes, str] = b"1.1", + _parsed: bool = False, + ) -> None: + super().__init__() + if isinstance(headers, Headers): + object.__setattr__(self, "headers", headers) + else: + object.__setattr__( + self, "headers", normalize_and_validate(headers, _parsed=_parsed) + ) + if not _parsed: + object.__setattr__(self, "method", bytesify(method)) + object.__setattr__(self, "target", bytesify(target)) + object.__setattr__(self, "http_version", bytesify(http_version)) + else: + object.__setattr__(self, "method", method) + object.__setattr__(self, "target", target) + object.__setattr__(self, "http_version", http_version) + + # "A server MUST respond with a 400 (Bad Request) status code to any + # HTTP/1.1 request message that lacks a Host header field and to any + # request message that contains more than one Host header field or a + # Host header field with an invalid field-value." + # -- https://tools.ietf.org/html/rfc7230#section-5.4 + host_count = 0 + for name, value in self.headers: + if name == b"host": + host_count += 1 + if self.http_version == b"1.1" and host_count == 0: + raise LocalProtocolError("Missing mandatory Host: header") + if host_count > 1: + raise LocalProtocolError("Found multiple Host: headers") + + validate(method_re, self.method, "Illegal method characters") + validate(request_target_re, self.target, "Illegal target characters") + + # This is an unhashable type. + __hash__ = None # type: ignore + + +@dataclass(init=False, frozen=True) +class _ResponseBase(Event): + __slots__ = ("headers", "http_version", "reason", "status_code") + + headers: Headers + http_version: bytes + reason: bytes + status_code: int + + def __init__( + self, + *, + headers: Union[Headers, List[Tuple[bytes, bytes]], List[Tuple[str, str]]], + status_code: int, + http_version: Union[bytes, str] = b"1.1", + reason: Union[bytes, str] = b"", + _parsed: bool = False, + ) -> None: + super().__init__() + if isinstance(headers, Headers): + object.__setattr__(self, "headers", headers) + else: + object.__setattr__( + self, "headers", normalize_and_validate(headers, _parsed=_parsed) + ) + if not _parsed: + object.__setattr__(self, "reason", bytesify(reason)) + object.__setattr__(self, "http_version", bytesify(http_version)) + if not isinstance(status_code, int): + raise LocalProtocolError("status code must be integer") + # Because IntEnum objects are instances of int, but aren't + # duck-compatible (sigh), see gh-72. + object.__setattr__(self, "status_code", int(status_code)) + else: + object.__setattr__(self, "reason", reason) + object.__setattr__(self, "http_version", http_version) + object.__setattr__(self, "status_code", status_code) + + self.__post_init__() + + def __post_init__(self) -> None: + pass + + # This is an unhashable type. + __hash__ = None # type: ignore + + +@dataclass(init=False, frozen=True) +class InformationalResponse(_ResponseBase): + """An HTTP informational response. + + Fields: + + .. attribute:: status_code + + The status code of this response, as an integer. For an + :class:`InformationalResponse`, this is always in the range [100, + 200). + + .. attribute:: headers + + Request headers, represented as a list of (name, value) pairs. See + :ref:`the header normalization rules ` for + details. + + .. attribute:: http_version + + The HTTP protocol version, represented as a byte string like + ``b"1.1"``. See :ref:`the HTTP version normalization rules + ` for details. + + .. attribute:: reason + + The reason phrase of this response, as a byte string. For example: + ``b"OK"``, or ``b"Not Found"``. + + """ + + def __post_init__(self) -> None: + if not (100 <= self.status_code < 200): + raise LocalProtocolError( + "InformationalResponse status_code should be in range " + "[100, 200), not {}".format(self.status_code) + ) + + # This is an unhashable type. + __hash__ = None # type: ignore + + +@dataclass(init=False, frozen=True) +class Response(_ResponseBase): + """The beginning of an HTTP response. + + Fields: + + .. attribute:: status_code + + The status code of this response, as an integer. For an + :class:`Response`, this is always in the range [200, + 1000). + + .. attribute:: headers + + Request headers, represented as a list of (name, value) pairs. See + :ref:`the header normalization rules ` for details. + + .. attribute:: http_version + + The HTTP protocol version, represented as a byte string like + ``b"1.1"``. See :ref:`the HTTP version normalization rules + ` for details. + + .. attribute:: reason + + The reason phrase of this response, as a byte string. For example: + ``b"OK"``, or ``b"Not Found"``. + + """ + + def __post_init__(self) -> None: + if not (200 <= self.status_code < 1000): + raise LocalProtocolError( + "Response status_code should be in range [200, 1000), not {}".format( + self.status_code + ) + ) + + # This is an unhashable type. + __hash__ = None # type: ignore + + +@dataclass(init=False, frozen=True) +class Data(Event): + """Part of an HTTP message body. + + Fields: + + .. attribute:: data + + A :term:`bytes-like object` containing part of a message body. Or, if + using the ``combine=False`` argument to :meth:`Connection.send`, then + any object that your socket writing code knows what to do with, and for + which calling :func:`len` returns the number of bytes that will be + written -- see :ref:`sendfile` for details. + + .. attribute:: chunk_start + + A marker that indicates whether this data object is from the start of a + chunked transfer encoding chunk. This field is ignored when when a Data + event is provided to :meth:`Connection.send`: it is only valid on + events emitted from :meth:`Connection.next_event`. You probably + shouldn't use this attribute at all; see + :ref:`chunk-delimiters-are-bad` for details. + + .. attribute:: chunk_end + + A marker that indicates whether this data object is the last for a + given chunked transfer encoding chunk. This field is ignored when when + a Data event is provided to :meth:`Connection.send`: it is only valid + on events emitted from :meth:`Connection.next_event`. You probably + shouldn't use this attribute at all; see + :ref:`chunk-delimiters-are-bad` for details. + + """ + + __slots__ = ("data", "chunk_start", "chunk_end") + + data: bytes + chunk_start: bool + chunk_end: bool + + def __init__( + self, data: bytes, chunk_start: bool = False, chunk_end: bool = False + ) -> None: + object.__setattr__(self, "data", data) + object.__setattr__(self, "chunk_start", chunk_start) + object.__setattr__(self, "chunk_end", chunk_end) + + # This is an unhashable type. + __hash__ = None # type: ignore + + +# XX FIXME: "A recipient MUST ignore (or consider as an error) any fields that +# are forbidden to be sent in a trailer, since processing them as if they were +# present in the header section might bypass external security filters." +# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#chunked.trailer.part +# Unfortunately, the list of forbidden fields is long and vague :-/ +@dataclass(init=False, frozen=True) +class EndOfMessage(Event): + """The end of an HTTP message. + + Fields: + + .. attribute:: headers + + Default value: ``[]`` + + Any trailing headers attached to this message, represented as a list of + (name, value) pairs. See :ref:`the header normalization rules + ` for details. + + Must be empty unless ``Transfer-Encoding: chunked`` is in use. + + """ + + __slots__ = ("headers",) + + headers: Headers + + def __init__( + self, + *, + headers: Union[ + Headers, List[Tuple[bytes, bytes]], List[Tuple[str, str]], None + ] = None, + _parsed: bool = False, + ) -> None: + super().__init__() + if headers is None: + headers = Headers([]) + elif not isinstance(headers, Headers): + headers = normalize_and_validate(headers, _parsed=_parsed) + + object.__setattr__(self, "headers", headers) + + # This is an unhashable type. + __hash__ = None # type: ignore + + +@dataclass(frozen=True) +class ConnectionClosed(Event): + """This event indicates that the sender has closed their outgoing + connection. + + Note that this does not necessarily mean that they can't *receive* further + data, because TCP connections are composed to two one-way channels which + can be closed independently. See :ref:`closing` for details. + + No fields. + """ + + pass diff --git a/backend/.venv/Lib/site-packages/h11/_headers.py b/backend/.venv/Lib/site-packages/h11/_headers.py new file mode 100644 index 0000000..31da3e2 --- /dev/null +++ b/backend/.venv/Lib/site-packages/h11/_headers.py @@ -0,0 +1,282 @@ +import re +from typing import AnyStr, cast, List, overload, Sequence, Tuple, TYPE_CHECKING, Union + +from ._abnf import field_name, field_value +from ._util import bytesify, LocalProtocolError, validate + +if TYPE_CHECKING: + from ._events import Request + +try: + from typing import Literal +except ImportError: + from typing_extensions import Literal # type: ignore + +CONTENT_LENGTH_MAX_DIGITS = 20 # allow up to 1 billion TB - 1 + + +# Facts +# ----- +# +# Headers are: +# keys: case-insensitive ascii +# values: mixture of ascii and raw bytes +# +# "Historically, HTTP has allowed field content with text in the ISO-8859-1 +# charset [ISO-8859-1], supporting other charsets only through use of +# [RFC2047] encoding. In practice, most HTTP header field values use only a +# subset of the US-ASCII charset [USASCII]. Newly defined header fields SHOULD +# limit their field values to US-ASCII octets. A recipient SHOULD treat other +# octets in field content (obs-text) as opaque data." +# And it deprecates all non-ascii values +# +# Leading/trailing whitespace in header names is forbidden +# +# Values get leading/trailing whitespace stripped +# +# Content-Disposition actually needs to contain unicode semantically; to +# accomplish this it has a terrifically weird way of encoding the filename +# itself as ascii (and even this still has lots of cross-browser +# incompatibilities) +# +# Order is important: +# "a proxy MUST NOT change the order of these field values when forwarding a +# message" +# (and there are several headers where the order indicates a preference) +# +# Multiple occurences of the same header: +# "A sender MUST NOT generate multiple header fields with the same field name +# in a message unless either the entire field value for that header field is +# defined as a comma-separated list [or the header is Set-Cookie which gets a +# special exception]" - RFC 7230. (cookies are in RFC 6265) +# +# So every header aside from Set-Cookie can be merged by b", ".join if it +# occurs repeatedly. But, of course, they can't necessarily be split by +# .split(b","), because quoting. +# +# Given all this mess (case insensitive, duplicates allowed, order is +# important, ...), there doesn't appear to be any standard way to handle +# headers in Python -- they're almost like dicts, but... actually just +# aren't. For now we punt and just use a super simple representation: headers +# are a list of pairs +# +# [(name1, value1), (name2, value2), ...] +# +# where all entries are bytestrings, names are lowercase and have no +# leading/trailing whitespace, and values are bytestrings with no +# leading/trailing whitespace. Searching and updating are done via naive O(n) +# methods. +# +# Maybe a dict-of-lists would be better? + +_content_length_re = re.compile(rb"[0-9]+") +_field_name_re = re.compile(field_name.encode("ascii")) +_field_value_re = re.compile(field_value.encode("ascii")) + + +class Headers(Sequence[Tuple[bytes, bytes]]): + """ + A list-like interface that allows iterating over headers as byte-pairs + of (lowercased-name, value). + + Internally we actually store the representation as three-tuples, + including both the raw original casing, in order to preserve casing + over-the-wire, and the lowercased name, for case-insensitive comparisions. + + r = Request( + method="GET", + target="/", + headers=[("Host", "example.org"), ("Connection", "keep-alive")], + http_version="1.1", + ) + assert r.headers == [ + (b"host", b"example.org"), + (b"connection", b"keep-alive") + ] + assert r.headers.raw_items() == [ + (b"Host", b"example.org"), + (b"Connection", b"keep-alive") + ] + """ + + __slots__ = "_full_items" + + def __init__(self, full_items: List[Tuple[bytes, bytes, bytes]]) -> None: + self._full_items = full_items + + def __bool__(self) -> bool: + return bool(self._full_items) + + def __eq__(self, other: object) -> bool: + return list(self) == list(other) # type: ignore + + def __len__(self) -> int: + return len(self._full_items) + + def __repr__(self) -> str: + return "" % repr(list(self)) + + def __getitem__(self, idx: int) -> Tuple[bytes, bytes]: # type: ignore[override] + _, name, value = self._full_items[idx] + return (name, value) + + def raw_items(self) -> List[Tuple[bytes, bytes]]: + return [(raw_name, value) for raw_name, _, value in self._full_items] + + +HeaderTypes = Union[ + List[Tuple[bytes, bytes]], + List[Tuple[bytes, str]], + List[Tuple[str, bytes]], + List[Tuple[str, str]], +] + + +@overload +def normalize_and_validate(headers: Headers, _parsed: Literal[True]) -> Headers: + ... + + +@overload +def normalize_and_validate(headers: HeaderTypes, _parsed: Literal[False]) -> Headers: + ... + + +@overload +def normalize_and_validate( + headers: Union[Headers, HeaderTypes], _parsed: bool = False +) -> Headers: + ... + + +def normalize_and_validate( + headers: Union[Headers, HeaderTypes], _parsed: bool = False +) -> Headers: + new_headers = [] + seen_content_length = None + saw_transfer_encoding = False + for name, value in headers: + # For headers coming out of the parser, we can safely skip some steps, + # because it always returns bytes and has already run these regexes + # over the data: + if not _parsed: + name = bytesify(name) + value = bytesify(value) + validate(_field_name_re, name, "Illegal header name {!r}", name) + validate(_field_value_re, value, "Illegal header value {!r}", value) + assert isinstance(name, bytes) + assert isinstance(value, bytes) + + raw_name = name + name = name.lower() + if name == b"content-length": + lengths = {length.strip() for length in value.split(b",")} + if len(lengths) != 1: + raise LocalProtocolError("conflicting Content-Length headers") + value = lengths.pop() + validate(_content_length_re, value, "bad Content-Length") + if len(value) > CONTENT_LENGTH_MAX_DIGITS: + raise LocalProtocolError("bad Content-Length") + if seen_content_length is None: + seen_content_length = value + new_headers.append((raw_name, name, value)) + elif seen_content_length != value: + raise LocalProtocolError("conflicting Content-Length headers") + elif name == b"transfer-encoding": + # "A server that receives a request message with a transfer coding + # it does not understand SHOULD respond with 501 (Not + # Implemented)." + # https://tools.ietf.org/html/rfc7230#section-3.3.1 + if saw_transfer_encoding: + raise LocalProtocolError( + "multiple Transfer-Encoding headers", error_status_hint=501 + ) + # "All transfer-coding names are case-insensitive" + # -- https://tools.ietf.org/html/rfc7230#section-4 + value = value.lower() + if value != b"chunked": + raise LocalProtocolError( + "Only Transfer-Encoding: chunked is supported", + error_status_hint=501, + ) + saw_transfer_encoding = True + new_headers.append((raw_name, name, value)) + else: + new_headers.append((raw_name, name, value)) + return Headers(new_headers) + + +def get_comma_header(headers: Headers, name: bytes) -> List[bytes]: + # Should only be used for headers whose value is a list of + # comma-separated, case-insensitive values. + # + # The header name `name` is expected to be lower-case bytes. + # + # Connection: meets these criteria (including cast insensitivity). + # + # Content-Length: technically is just a single value (1*DIGIT), but the + # standard makes reference to implementations that do multiple values, and + # using this doesn't hurt. Ditto, case insensitivity doesn't things either + # way. + # + # Transfer-Encoding: is more complex (allows for quoted strings), so + # splitting on , is actually wrong. For example, this is legal: + # + # Transfer-Encoding: foo; options="1,2", chunked + # + # and should be parsed as + # + # foo; options="1,2" + # chunked + # + # but this naive function will parse it as + # + # foo; options="1 + # 2" + # chunked + # + # However, this is okay because the only thing we are going to do with + # any Transfer-Encoding is reject ones that aren't just "chunked", so + # both of these will be treated the same anyway. + # + # Expect: the only legal value is the literal string + # "100-continue". Splitting on commas is harmless. Case insensitive. + # + out: List[bytes] = [] + for _, found_name, found_raw_value in headers._full_items: + if found_name == name: + found_raw_value = found_raw_value.lower() + for found_split_value in found_raw_value.split(b","): + found_split_value = found_split_value.strip() + if found_split_value: + out.append(found_split_value) + return out + + +def set_comma_header(headers: Headers, name: bytes, new_values: List[bytes]) -> Headers: + # The header name `name` is expected to be lower-case bytes. + # + # Note that when we store the header we use title casing for the header + # names, in order to match the conventional HTTP header style. + # + # Simply calling `.title()` is a blunt approach, but it's correct + # here given the cases where we're using `set_comma_header`... + # + # Connection, Content-Length, Transfer-Encoding. + new_headers: List[Tuple[bytes, bytes]] = [] + for found_raw_name, found_name, found_raw_value in headers._full_items: + if found_name != name: + new_headers.append((found_raw_name, found_raw_value)) + for new_value in new_values: + new_headers.append((name.title(), new_value)) + return normalize_and_validate(new_headers) + + +def has_expect_100_continue(request: "Request") -> bool: + # https://tools.ietf.org/html/rfc7231#section-5.1.1 + # "A server that receives a 100-continue expectation in an HTTP/1.0 request + # MUST ignore that expectation." + if request.http_version < b"1.1": + return False + expect = get_comma_header(request.headers, b"expect") + return b"100-continue" in expect diff --git a/backend/.venv/Lib/site-packages/h11/_readers.py b/backend/.venv/Lib/site-packages/h11/_readers.py new file mode 100644 index 0000000..576804c --- /dev/null +++ b/backend/.venv/Lib/site-packages/h11/_readers.py @@ -0,0 +1,250 @@ +# Code to read HTTP data +# +# Strategy: each reader is a callable which takes a ReceiveBuffer object, and +# either: +# 1) consumes some of it and returns an Event +# 2) raises a LocalProtocolError (for consistency -- e.g. we call validate() +# and it might raise a LocalProtocolError, so simpler just to always use +# this) +# 3) returns None, meaning "I need more data" +# +# If they have a .read_eof attribute, then this will be called if an EOF is +# received -- but this is optional. Either way, the actual ConnectionClosed +# event will be generated afterwards. +# +# READERS is a dict describing how to pick a reader. It maps states to either: +# - a reader +# - or, for body readers, a dict of per-framing reader factories + +import re +from typing import Any, Callable, Dict, Iterable, NoReturn, Optional, Tuple, Type, Union + +from ._abnf import chunk_header, header_field, request_line, status_line +from ._events import Data, EndOfMessage, InformationalResponse, Request, Response +from ._receivebuffer import ReceiveBuffer +from ._state import ( + CLIENT, + CLOSED, + DONE, + IDLE, + MUST_CLOSE, + SEND_BODY, + SEND_RESPONSE, + SERVER, +) +from ._util import LocalProtocolError, RemoteProtocolError, Sentinel, validate + +__all__ = ["READERS"] + +header_field_re = re.compile(header_field.encode("ascii")) +obs_fold_re = re.compile(rb"[ \t]+") + + +def _obsolete_line_fold(lines: Iterable[bytes]) -> Iterable[bytes]: + it = iter(lines) + last: Optional[bytes] = None + for line in it: + match = obs_fold_re.match(line) + if match: + if last is None: + raise LocalProtocolError("continuation line at start of headers") + if not isinstance(last, bytearray): + # Cast to a mutable type, avoiding copy on append to ensure O(n) time + last = bytearray(last) + last += b" " + last += line[match.end() :] + else: + if last is not None: + yield last + last = line + if last is not None: + yield last + + +def _decode_header_lines( + lines: Iterable[bytes], +) -> Iterable[Tuple[bytes, bytes]]: + for line in _obsolete_line_fold(lines): + matches = validate(header_field_re, line, "illegal header line: {!r}", line) + yield (matches["field_name"], matches["field_value"]) + + +request_line_re = re.compile(request_line.encode("ascii")) + + +def maybe_read_from_IDLE_client(buf: ReceiveBuffer) -> Optional[Request]: + lines = buf.maybe_extract_lines() + if lines is None: + if buf.is_next_line_obviously_invalid_request_line(): + raise LocalProtocolError("illegal request line") + return None + if not lines: + raise LocalProtocolError("no request line received") + matches = validate( + request_line_re, lines[0], "illegal request line: {!r}", lines[0] + ) + return Request( + headers=list(_decode_header_lines(lines[1:])), _parsed=True, **matches + ) + + +status_line_re = re.compile(status_line.encode("ascii")) + + +def maybe_read_from_SEND_RESPONSE_server( + buf: ReceiveBuffer, +) -> Union[InformationalResponse, Response, None]: + lines = buf.maybe_extract_lines() + if lines is None: + if buf.is_next_line_obviously_invalid_request_line(): + raise LocalProtocolError("illegal request line") + return None + if not lines: + raise LocalProtocolError("no response line received") + matches = validate(status_line_re, lines[0], "illegal status line: {!r}", lines[0]) + http_version = ( + b"1.1" if matches["http_version"] is None else matches["http_version"] + ) + reason = b"" if matches["reason"] is None else matches["reason"] + status_code = int(matches["status_code"]) + class_: Union[Type[InformationalResponse], Type[Response]] = ( + InformationalResponse if status_code < 200 else Response + ) + return class_( + headers=list(_decode_header_lines(lines[1:])), + _parsed=True, + status_code=status_code, + reason=reason, + http_version=http_version, + ) + + +class ContentLengthReader: + def __init__(self, length: int) -> None: + self._length = length + self._remaining = length + + def __call__(self, buf: ReceiveBuffer) -> Union[Data, EndOfMessage, None]: + if self._remaining == 0: + return EndOfMessage() + data = buf.maybe_extract_at_most(self._remaining) + if data is None: + return None + self._remaining -= len(data) + return Data(data=data) + + def read_eof(self) -> NoReturn: + raise RemoteProtocolError( + "peer closed connection without sending complete message body " + "(received {} bytes, expected {})".format( + self._length - self._remaining, self._length + ) + ) + + +chunk_header_re = re.compile(chunk_header.encode("ascii")) + + +class ChunkedReader: + def __init__(self) -> None: + self._bytes_in_chunk = 0 + # After reading a chunk, we have to throw away the trailing \r\n. + # This tracks the bytes that we need to match and throw away. + self._bytes_to_discard = b"" + self._reading_trailer = False + + def __call__(self, buf: ReceiveBuffer) -> Union[Data, EndOfMessage, None]: + if self._reading_trailer: + lines = buf.maybe_extract_lines() + if lines is None: + return None + return EndOfMessage(headers=list(_decode_header_lines(lines))) + if self._bytes_to_discard: + data = buf.maybe_extract_at_most(len(self._bytes_to_discard)) + if data is None: + return None + if data != self._bytes_to_discard[: len(data)]: + raise LocalProtocolError( + f"malformed chunk footer: {data!r} (expected {self._bytes_to_discard!r})" + ) + self._bytes_to_discard = self._bytes_to_discard[len(data) :] + if self._bytes_to_discard: + return None + # else, fall through and read some more + assert self._bytes_to_discard == b"" + if self._bytes_in_chunk == 0: + # We need to refill our chunk count + chunk_header = buf.maybe_extract_next_line() + if chunk_header is None: + return None + matches = validate( + chunk_header_re, + chunk_header, + "illegal chunk header: {!r}", + chunk_header, + ) + # XX FIXME: we discard chunk extensions. Does anyone care? + self._bytes_in_chunk = int(matches["chunk_size"], base=16) + if self._bytes_in_chunk == 0: + self._reading_trailer = True + return self(buf) + chunk_start = True + else: + chunk_start = False + assert self._bytes_in_chunk > 0 + data = buf.maybe_extract_at_most(self._bytes_in_chunk) + if data is None: + return None + self._bytes_in_chunk -= len(data) + if self._bytes_in_chunk == 0: + self._bytes_to_discard = b"\r\n" + chunk_end = True + else: + chunk_end = False + return Data(data=data, chunk_start=chunk_start, chunk_end=chunk_end) + + def read_eof(self) -> NoReturn: + raise RemoteProtocolError( + "peer closed connection without sending complete message body " + "(incomplete chunked read)" + ) + + +class Http10Reader: + def __call__(self, buf: ReceiveBuffer) -> Optional[Data]: + data = buf.maybe_extract_at_most(999999999) + if data is None: + return None + return Data(data=data) + + def read_eof(self) -> EndOfMessage: + return EndOfMessage() + + +def expect_nothing(buf: ReceiveBuffer) -> None: + if buf: + raise LocalProtocolError("Got data when expecting EOF") + return None + + +ReadersType = Dict[ + Union[Type[Sentinel], Tuple[Type[Sentinel], Type[Sentinel]]], + Union[Callable[..., Any], Dict[str, Callable[..., Any]]], +] + +READERS: ReadersType = { + (CLIENT, IDLE): maybe_read_from_IDLE_client, + (SERVER, IDLE): maybe_read_from_SEND_RESPONSE_server, + (SERVER, SEND_RESPONSE): maybe_read_from_SEND_RESPONSE_server, + (CLIENT, DONE): expect_nothing, + (CLIENT, MUST_CLOSE): expect_nothing, + (CLIENT, CLOSED): expect_nothing, + (SERVER, DONE): expect_nothing, + (SERVER, MUST_CLOSE): expect_nothing, + (SERVER, CLOSED): expect_nothing, + SEND_BODY: { + "chunked": ChunkedReader, + "content-length": ContentLengthReader, + "http/1.0": Http10Reader, + }, +} diff --git a/backend/.venv/Lib/site-packages/h11/_receivebuffer.py b/backend/.venv/Lib/site-packages/h11/_receivebuffer.py new file mode 100644 index 0000000..e5c4e08 --- /dev/null +++ b/backend/.venv/Lib/site-packages/h11/_receivebuffer.py @@ -0,0 +1,153 @@ +import re +import sys +from typing import List, Optional, Union + +__all__ = ["ReceiveBuffer"] + + +# Operations we want to support: +# - find next \r\n or \r\n\r\n (\n or \n\n are also acceptable), +# or wait until there is one +# - read at-most-N bytes +# Goals: +# - on average, do this fast +# - worst case, do this in O(n) where n is the number of bytes processed +# Plan: +# - store bytearray, offset, how far we've searched for a separator token +# - use the how-far-we've-searched data to avoid rescanning +# - while doing a stream of uninterrupted processing, advance offset instead +# of constantly copying +# WARNING: +# - I haven't benchmarked or profiled any of this yet. +# +# Note that starting in Python 3.4, deleting the initial n bytes from a +# bytearray is amortized O(n), thanks to some excellent work by Antoine +# Martin: +# +# https://bugs.python.org/issue19087 +# +# This means that if we only supported 3.4+, we could get rid of the code here +# involving self._start and self.compress, because it's doing exactly the same +# thing that bytearray now does internally. +# +# BUT unfortunately, we still support 2.7, and reading short segments out of a +# long buffer MUST be O(bytes read) to avoid DoS issues, so we can't actually +# delete this code. Yet: +# +# https://pythonclock.org/ +# +# (Two things to double-check first though: make sure PyPy also has the +# optimization, and benchmark to make sure it's a win, since we do have a +# slightly clever thing where we delay calling compress() until we've +# processed a whole event, which could in theory be slightly more efficient +# than the internal bytearray support.) +blank_line_regex = re.compile(b"\n\r?\n", re.MULTILINE) + + +class ReceiveBuffer: + def __init__(self) -> None: + self._data = bytearray() + self._next_line_search = 0 + self._multiple_lines_search = 0 + + def __iadd__(self, byteslike: Union[bytes, bytearray]) -> "ReceiveBuffer": + self._data += byteslike + return self + + def __bool__(self) -> bool: + return bool(len(self)) + + def __len__(self) -> int: + return len(self._data) + + # for @property unprocessed_data + def __bytes__(self) -> bytes: + return bytes(self._data) + + def _extract(self, count: int) -> bytearray: + # extracting an initial slice of the data buffer and return it + out = self._data[:count] + del self._data[:count] + + self._next_line_search = 0 + self._multiple_lines_search = 0 + + return out + + def maybe_extract_at_most(self, count: int) -> Optional[bytearray]: + """ + Extract a fixed number of bytes from the buffer. + """ + out = self._data[:count] + if not out: + return None + + return self._extract(count) + + def maybe_extract_next_line(self) -> Optional[bytearray]: + """ + Extract the first line, if it is completed in the buffer. + """ + # Only search in buffer space that we've not already looked at. + search_start_index = max(0, self._next_line_search - 1) + partial_idx = self._data.find(b"\r\n", search_start_index) + + if partial_idx == -1: + self._next_line_search = len(self._data) + return None + + # + 2 is to compensate len(b"\r\n") + idx = partial_idx + 2 + + return self._extract(idx) + + def maybe_extract_lines(self) -> Optional[List[bytearray]]: + """ + Extract everything up to the first blank line, and return a list of lines. + """ + # Handle the case where we have an immediate empty line. + if self._data[:1] == b"\n": + self._extract(1) + return [] + + if self._data[:2] == b"\r\n": + self._extract(2) + return [] + + # Only search in buffer space that we've not already looked at. + match = blank_line_regex.search(self._data, self._multiple_lines_search) + if match is None: + self._multiple_lines_search = max(0, len(self._data) - 2) + return None + + # Truncate the buffer and return it. + idx = match.span(0)[-1] + out = self._extract(idx) + lines = out.split(b"\n") + + for line in lines: + if line.endswith(b"\r"): + del line[-1] + + assert lines[-2] == lines[-1] == b"" + + del lines[-2:] + + return lines + + # In theory we should wait until `\r\n` before starting to validate + # incoming data. However it's interesting to detect (very) invalid data + # early given they might not even contain `\r\n` at all (hence only + # timeout will get rid of them). + # This is not a 100% effective detection but more of a cheap sanity check + # allowing for early abort in some useful cases. + # This is especially interesting when peer is messing up with HTTPS and + # sent us a TLS stream where we were expecting plain HTTP given all + # versions of TLS so far start handshake with a 0x16 message type code. + def is_next_line_obviously_invalid_request_line(self) -> bool: + try: + # HTTP header line must not contain non-printable characters + # and should not start with a space + return self._data[0] < 0x21 + except IndexError: + return False diff --git a/backend/.venv/Lib/site-packages/h11/_state.py b/backend/.venv/Lib/site-packages/h11/_state.py new file mode 100644 index 0000000..3ad444b --- /dev/null +++ b/backend/.venv/Lib/site-packages/h11/_state.py @@ -0,0 +1,365 @@ +################################################################ +# The core state machine +################################################################ +# +# Rule 1: everything that affects the state machine and state transitions must +# live here in this file. As much as possible goes into the table-based +# representation, but for the bits that don't quite fit, the actual code and +# state must nonetheless live here. +# +# Rule 2: this file does not know about what role we're playing; it only knows +# about HTTP request/response cycles in the abstract. This ensures that we +# don't cheat and apply different rules to local and remote parties. +# +# +# Theory of operation +# =================== +# +# Possibly the simplest way to think about this is that we actually have 5 +# different state machines here. Yes, 5. These are: +# +# 1) The client state, with its complicated automaton (see the docs) +# 2) The server state, with its complicated automaton (see the docs) +# 3) The keep-alive state, with possible states {True, False} +# 4) The SWITCH_CONNECT state, with possible states {False, True} +# 5) The SWITCH_UPGRADE state, with possible states {False, True} +# +# For (3)-(5), the first state listed is the initial state. +# +# (1)-(3) are stored explicitly in member variables. The last +# two are stored implicitly in the pending_switch_proposals set as: +# (state of 4) == (_SWITCH_CONNECT in pending_switch_proposals) +# (state of 5) == (_SWITCH_UPGRADE in pending_switch_proposals) +# +# And each of these machines has two different kinds of transitions: +# +# a) Event-triggered +# b) State-triggered +# +# Event triggered is the obvious thing that you'd think it is: some event +# happens, and if it's the right event at the right time then a transition +# happens. But there are somewhat complicated rules for which machines can +# "see" which events. (As a rule of thumb, if a machine "sees" an event, this +# means two things: the event can affect the machine, and if the machine is +# not in a state where it expects that event then it's an error.) These rules +# are: +# +# 1) The client machine sees all h11.events objects emitted by the client. +# +# 2) The server machine sees all h11.events objects emitted by the server. +# +# It also sees the client's Request event. +# +# And sometimes, server events are annotated with a _SWITCH_* event. For +# example, we can have a (Response, _SWITCH_CONNECT) event, which is +# different from a regular Response event. +# +# 3) The keep-alive machine sees the process_keep_alive_disabled() event +# (which is derived from Request/Response events), and this event +# transitions it from True -> False, or from False -> False. There's no way +# to transition back. +# +# 4&5) The _SWITCH_* machines transition from False->True when we get a +# Request that proposes the relevant type of switch (via +# process_client_switch_proposals), and they go from True->False when we +# get a Response that has no _SWITCH_* annotation. +# +# So that's event-triggered transitions. +# +# State-triggered transitions are less standard. What they do here is couple +# the machines together. The way this works is, when certain *joint* +# configurations of states are achieved, then we automatically transition to a +# new *joint* state. So, for example, if we're ever in a joint state with +# +# client: DONE +# keep-alive: False +# +# then the client state immediately transitions to: +# +# client: MUST_CLOSE +# +# This is fundamentally different from an event-based transition, because it +# doesn't matter how we arrived at the {client: DONE, keep-alive: False} state +# -- maybe the client transitioned SEND_BODY -> DONE, or keep-alive +# transitioned True -> False. Either way, once this precondition is satisfied, +# this transition is immediately triggered. +# +# What if two conflicting state-based transitions get enabled at the same +# time? In practice there's only one case where this arises (client DONE -> +# MIGHT_SWITCH_PROTOCOL versus DONE -> MUST_CLOSE), and we resolve it by +# explicitly prioritizing the DONE -> MIGHT_SWITCH_PROTOCOL transition. +# +# Implementation +# -------------- +# +# The event-triggered transitions for the server and client machines are all +# stored explicitly in a table. Ditto for the state-triggered transitions that +# involve just the server and client state. +# +# The transitions for the other machines, and the state-triggered transitions +# that involve the other machines, are written out as explicit Python code. +# +# It'd be nice if there were some cleaner way to do all this. This isn't +# *too* terrible, but I feel like it could probably be better. +# +# WARNING +# ------- +# +# The script that generates the state machine diagrams for the docs knows how +# to read out the EVENT_TRIGGERED_TRANSITIONS and STATE_TRIGGERED_TRANSITIONS +# tables. But it can't automatically read the transitions that are written +# directly in Python code. So if you touch those, you need to also update the +# script to keep it in sync! +from typing import cast, Dict, Optional, Set, Tuple, Type, Union + +from ._events import * +from ._util import LocalProtocolError, Sentinel + +# Everything in __all__ gets re-exported as part of the h11 public API. +__all__ = [ + "CLIENT", + "SERVER", + "IDLE", + "SEND_RESPONSE", + "SEND_BODY", + "DONE", + "MUST_CLOSE", + "CLOSED", + "MIGHT_SWITCH_PROTOCOL", + "SWITCHED_PROTOCOL", + "ERROR", +] + + +class CLIENT(Sentinel, metaclass=Sentinel): + pass + + +class SERVER(Sentinel, metaclass=Sentinel): + pass + + +# States +class IDLE(Sentinel, metaclass=Sentinel): + pass + + +class SEND_RESPONSE(Sentinel, metaclass=Sentinel): + pass + + +class SEND_BODY(Sentinel, metaclass=Sentinel): + pass + + +class DONE(Sentinel, metaclass=Sentinel): + pass + + +class MUST_CLOSE(Sentinel, metaclass=Sentinel): + pass + + +class CLOSED(Sentinel, metaclass=Sentinel): + pass + + +class ERROR(Sentinel, metaclass=Sentinel): + pass + + +# Switch types +class MIGHT_SWITCH_PROTOCOL(Sentinel, metaclass=Sentinel): + pass + + +class SWITCHED_PROTOCOL(Sentinel, metaclass=Sentinel): + pass + + +class _SWITCH_UPGRADE(Sentinel, metaclass=Sentinel): + pass + + +class _SWITCH_CONNECT(Sentinel, metaclass=Sentinel): + pass + + +EventTransitionType = Dict[ + Type[Sentinel], + Dict[ + Type[Sentinel], + Dict[Union[Type[Event], Tuple[Type[Event], Type[Sentinel]]], Type[Sentinel]], + ], +] + +EVENT_TRIGGERED_TRANSITIONS: EventTransitionType = { + CLIENT: { + IDLE: {Request: SEND_BODY, ConnectionClosed: CLOSED}, + SEND_BODY: {Data: SEND_BODY, EndOfMessage: DONE}, + DONE: {ConnectionClosed: CLOSED}, + MUST_CLOSE: {ConnectionClosed: CLOSED}, + CLOSED: {ConnectionClosed: CLOSED}, + MIGHT_SWITCH_PROTOCOL: {}, + SWITCHED_PROTOCOL: {}, + ERROR: {}, + }, + SERVER: { + IDLE: { + ConnectionClosed: CLOSED, + Response: SEND_BODY, + # Special case: server sees client Request events, in this form + (Request, CLIENT): SEND_RESPONSE, + }, + SEND_RESPONSE: { + InformationalResponse: SEND_RESPONSE, + Response: SEND_BODY, + (InformationalResponse, _SWITCH_UPGRADE): SWITCHED_PROTOCOL, + (Response, _SWITCH_CONNECT): SWITCHED_PROTOCOL, + }, + SEND_BODY: {Data: SEND_BODY, EndOfMessage: DONE}, + DONE: {ConnectionClosed: CLOSED}, + MUST_CLOSE: {ConnectionClosed: CLOSED}, + CLOSED: {ConnectionClosed: CLOSED}, + SWITCHED_PROTOCOL: {}, + ERROR: {}, + }, +} + +StateTransitionType = Dict[ + Tuple[Type[Sentinel], Type[Sentinel]], Dict[Type[Sentinel], Type[Sentinel]] +] + +# NB: there are also some special-case state-triggered transitions hard-coded +# into _fire_state_triggered_transitions below. +STATE_TRIGGERED_TRANSITIONS: StateTransitionType = { + # (Client state, Server state) -> new states + # Protocol negotiation + (MIGHT_SWITCH_PROTOCOL, SWITCHED_PROTOCOL): {CLIENT: SWITCHED_PROTOCOL}, + # Socket shutdown + (CLOSED, DONE): {SERVER: MUST_CLOSE}, + (CLOSED, IDLE): {SERVER: MUST_CLOSE}, + (ERROR, DONE): {SERVER: MUST_CLOSE}, + (DONE, CLOSED): {CLIENT: MUST_CLOSE}, + (IDLE, CLOSED): {CLIENT: MUST_CLOSE}, + (DONE, ERROR): {CLIENT: MUST_CLOSE}, +} + + +class ConnectionState: + def __init__(self) -> None: + # Extra bits of state that don't quite fit into the state model. + + # If this is False then it enables the automatic DONE -> MUST_CLOSE + # transition. Don't set this directly; call .keep_alive_disabled() + self.keep_alive = True + + # This is a subset of {UPGRADE, CONNECT}, containing the proposals + # made by the client for switching protocols. + self.pending_switch_proposals: Set[Type[Sentinel]] = set() + + self.states: Dict[Type[Sentinel], Type[Sentinel]] = {CLIENT: IDLE, SERVER: IDLE} + + def process_error(self, role: Type[Sentinel]) -> None: + self.states[role] = ERROR + self._fire_state_triggered_transitions() + + def process_keep_alive_disabled(self) -> None: + self.keep_alive = False + self._fire_state_triggered_transitions() + + def process_client_switch_proposal(self, switch_event: Type[Sentinel]) -> None: + self.pending_switch_proposals.add(switch_event) + self._fire_state_triggered_transitions() + + def process_event( + self, + role: Type[Sentinel], + event_type: Type[Event], + server_switch_event: Optional[Type[Sentinel]] = None, + ) -> None: + _event_type: Union[Type[Event], Tuple[Type[Event], Type[Sentinel]]] = event_type + if server_switch_event is not None: + assert role is SERVER + if server_switch_event not in self.pending_switch_proposals: + raise LocalProtocolError( + "Received server _SWITCH_UPGRADE event without a pending proposal" + ) + _event_type = (event_type, server_switch_event) + if server_switch_event is None and _event_type is Response: + self.pending_switch_proposals = set() + self._fire_event_triggered_transitions(role, _event_type) + # Special case: the server state does get to see Request + # events. + if _event_type is Request: + assert role is CLIENT + self._fire_event_triggered_transitions(SERVER, (Request, CLIENT)) + self._fire_state_triggered_transitions() + + def _fire_event_triggered_transitions( + self, + role: Type[Sentinel], + event_type: Union[Type[Event], Tuple[Type[Event], Type[Sentinel]]], + ) -> None: + state = self.states[role] + try: + new_state = EVENT_TRIGGERED_TRANSITIONS[role][state][event_type] + except KeyError: + event_type = cast(Type[Event], event_type) + raise LocalProtocolError( + "can't handle event type {} when role={} and state={}".format( + event_type.__name__, role, self.states[role] + ) + ) from None + self.states[role] = new_state + + def _fire_state_triggered_transitions(self) -> None: + # We apply these rules repeatedly until converging on a fixed point + while True: + start_states = dict(self.states) + + # It could happen that both these special-case transitions are + # enabled at the same time: + # + # DONE -> MIGHT_SWITCH_PROTOCOL + # DONE -> MUST_CLOSE + # + # For example, this will always be true of a HTTP/1.0 client + # requesting CONNECT. If this happens, the protocol switch takes + # priority. From there the client will either go to + # SWITCHED_PROTOCOL, in which case it's none of our business when + # they close the connection, or else the server will deny the + # request, in which case the client will go back to DONE and then + # from there to MUST_CLOSE. + if self.pending_switch_proposals: + if self.states[CLIENT] is DONE: + self.states[CLIENT] = MIGHT_SWITCH_PROTOCOL + + if not self.pending_switch_proposals: + if self.states[CLIENT] is MIGHT_SWITCH_PROTOCOL: + self.states[CLIENT] = DONE + + if not self.keep_alive: + for role in (CLIENT, SERVER): + if self.states[role] is DONE: + self.states[role] = MUST_CLOSE + + # Tabular state-triggered transitions + joint_state = (self.states[CLIENT], self.states[SERVER]) + changes = STATE_TRIGGERED_TRANSITIONS.get(joint_state, {}) + self.states.update(changes) + + if self.states == start_states: + # Fixed point reached + return + + def start_next_cycle(self) -> None: + if self.states != {CLIENT: DONE, SERVER: DONE}: + raise LocalProtocolError( + f"not in a reusable state. self.states={self.states}" + ) + # Can't reach DONE/DONE with any of these active, but still, let's be + # sure. + assert self.keep_alive + assert not self.pending_switch_proposals + self.states = {CLIENT: IDLE, SERVER: IDLE} diff --git a/backend/.venv/Lib/site-packages/h11/_util.py b/backend/.venv/Lib/site-packages/h11/_util.py new file mode 100644 index 0000000..6718445 --- /dev/null +++ b/backend/.venv/Lib/site-packages/h11/_util.py @@ -0,0 +1,135 @@ +from typing import Any, Dict, NoReturn, Pattern, Tuple, Type, TypeVar, Union + +__all__ = [ + "ProtocolError", + "LocalProtocolError", + "RemoteProtocolError", + "validate", + "bytesify", +] + + +class ProtocolError(Exception): + """Exception indicating a violation of the HTTP/1.1 protocol. + + This as an abstract base class, with two concrete base classes: + :exc:`LocalProtocolError`, which indicates that you tried to do something + that HTTP/1.1 says is illegal, and :exc:`RemoteProtocolError`, which + indicates that the remote peer tried to do something that HTTP/1.1 says is + illegal. See :ref:`error-handling` for details. + + In addition to the normal :exc:`Exception` features, it has one attribute: + + .. attribute:: error_status_hint + + This gives a suggestion as to what status code a server might use if + this error occurred as part of a request. + + For a :exc:`RemoteProtocolError`, this is useful as a suggestion for + how you might want to respond to a misbehaving peer, if you're + implementing a server. + + For a :exc:`LocalProtocolError`, this can be taken as a suggestion for + how your peer might have responded to *you* if h11 had allowed you to + continue. + + The default is 400 Bad Request, a generic catch-all for protocol + violations. + + """ + + def __init__(self, msg: str, error_status_hint: int = 400) -> None: + if type(self) is ProtocolError: + raise TypeError("tried to directly instantiate ProtocolError") + Exception.__init__(self, msg) + self.error_status_hint = error_status_hint + + +# Strategy: there are a number of public APIs where a LocalProtocolError can +# be raised (send(), all the different event constructors, ...), and only one +# public API where RemoteProtocolError can be raised +# (receive_data()). Therefore we always raise LocalProtocolError internally, +# and then receive_data will translate this into a RemoteProtocolError. +# +# Internally: +# LocalProtocolError is the generic "ProtocolError". +# Externally: +# LocalProtocolError is for local errors and RemoteProtocolError is for +# remote errors. +class LocalProtocolError(ProtocolError): + def _reraise_as_remote_protocol_error(self) -> NoReturn: + # After catching a LocalProtocolError, use this method to re-raise it + # as a RemoteProtocolError. This method must be called from inside an + # except: block. + # + # An easy way to get an equivalent RemoteProtocolError is just to + # modify 'self' in place. + self.__class__ = RemoteProtocolError # type: ignore + # But the re-raising is somewhat non-trivial -- you might think that + # now that we've modified the in-flight exception object, that just + # doing 'raise' to re-raise it would be enough. But it turns out that + # this doesn't work, because Python tracks the exception type + # (exc_info[0]) separately from the exception object (exc_info[1]), + # and we only modified the latter. So we really do need to re-raise + # the new type explicitly. + # On py3, the traceback is part of the exception object, so our + # in-place modification preserved it and we can just re-raise: + raise self + + +class RemoteProtocolError(ProtocolError): + pass + + +def validate( + regex: Pattern[bytes], data: bytes, msg: str = "malformed data", *format_args: Any +) -> Dict[str, bytes]: + match = regex.fullmatch(data) + if not match: + if format_args: + msg = msg.format(*format_args) + raise LocalProtocolError(msg) + return match.groupdict() + + +# Sentinel values +# +# - Inherit identity-based comparison and hashing from object +# - Have a nice repr +# - Have a *bonus property*: type(sentinel) is sentinel +# +# The bonus property is useful if you want to take the return value from +# next_event() and do some sort of dispatch based on type(event). + +_T_Sentinel = TypeVar("_T_Sentinel", bound="Sentinel") + + +class Sentinel(type): + def __new__( + cls: Type[_T_Sentinel], + name: str, + bases: Tuple[type, ...], + namespace: Dict[str, Any], + **kwds: Any + ) -> _T_Sentinel: + assert bases == (Sentinel,) + v = super().__new__(cls, name, bases, namespace, **kwds) + v.__class__ = v # type: ignore + return v + + def __repr__(self) -> str: + return self.__name__ + + +# Used for methods, request targets, HTTP versions, header names, and header +# values. Accepts ascii-strings, or bytes/bytearray/memoryview/..., and always +# returns bytes. +def bytesify(s: Union[bytes, bytearray, memoryview, int, str]) -> bytes: + # Fast-path: + if type(s) is bytes: + return s + if isinstance(s, str): + s = s.encode("ascii") + if isinstance(s, int): + raise TypeError("expected bytes-like object, not int") + return bytes(s) diff --git a/backend/.venv/Lib/site-packages/h11/_version.py b/backend/.venv/Lib/site-packages/h11/_version.py new file mode 100644 index 0000000..76e7327 --- /dev/null +++ b/backend/.venv/Lib/site-packages/h11/_version.py @@ -0,0 +1,16 @@ +# This file must be kept very simple, because it is consumed from several +# places -- it is imported by h11/__init__.py, execfile'd by setup.py, etc. + +# We use a simple scheme: +# 1.0.0 -> 1.0.0+dev -> 1.1.0 -> 1.1.0+dev +# where the +dev versions are never released into the wild, they're just what +# we stick into the VCS in between releases. +# +# This is compatible with PEP 440: +# http://legacy.python.org/dev/peps/pep-0440/ +# via the use of the "local suffix" "+dev", which is disallowed on index +# servers and causes 1.0.0+dev to sort after plain 1.0.0, which is what we +# want. (Contrast with the special suffix 1.0.0.dev, which sorts *before* +# 1.0.0.) + +__version__ = "0.16.0" diff --git a/backend/.venv/Lib/site-packages/h11/_writers.py b/backend/.venv/Lib/site-packages/h11/_writers.py new file mode 100644 index 0000000..939cdb9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/h11/_writers.py @@ -0,0 +1,145 @@ +# Code to read HTTP data +# +# Strategy: each writer takes an event + a write-some-bytes function, which is +# calls. +# +# WRITERS is a dict describing how to pick a reader. It maps states to either: +# - a writer +# - or, for body writers, a dict of framin-dependent writer factories + +from typing import Any, Callable, Dict, List, Tuple, Type, Union + +from ._events import Data, EndOfMessage, Event, InformationalResponse, Request, Response +from ._headers import Headers +from ._state import CLIENT, IDLE, SEND_BODY, SEND_RESPONSE, SERVER +from ._util import LocalProtocolError, Sentinel + +__all__ = ["WRITERS"] + +Writer = Callable[[bytes], Any] + + +def write_headers(headers: Headers, write: Writer) -> None: + # "Since the Host field-value is critical information for handling a + # request, a user agent SHOULD generate Host as the first header field + # following the request-line." - RFC 7230 + raw_items = headers._full_items + for raw_name, name, value in raw_items: + if name == b"host": + write(b"%s: %s\r\n" % (raw_name, value)) + for raw_name, name, value in raw_items: + if name != b"host": + write(b"%s: %s\r\n" % (raw_name, value)) + write(b"\r\n") + + +def write_request(request: Request, write: Writer) -> None: + if request.http_version != b"1.1": + raise LocalProtocolError("I only send HTTP/1.1") + write(b"%s %s HTTP/1.1\r\n" % (request.method, request.target)) + write_headers(request.headers, write) + + +# Shared between InformationalResponse and Response +def write_any_response( + response: Union[InformationalResponse, Response], write: Writer +) -> None: + if response.http_version != b"1.1": + raise LocalProtocolError("I only send HTTP/1.1") + status_bytes = str(response.status_code).encode("ascii") + # We don't bother sending ascii status messages like "OK"; they're + # optional and ignored by the protocol. (But the space after the numeric + # status code is mandatory.) + # + # XX FIXME: could at least make an effort to pull out the status message + # from stdlib's http.HTTPStatus table. Or maybe just steal their enums + # (either by import or copy/paste). We already accept them as status codes + # since they're of type IntEnum < int. + write(b"HTTP/1.1 %s %s\r\n" % (status_bytes, response.reason)) + write_headers(response.headers, write) + + +class BodyWriter: + def __call__(self, event: Event, write: Writer) -> None: + if type(event) is Data: + self.send_data(event.data, write) + elif type(event) is EndOfMessage: + self.send_eom(event.headers, write) + else: # pragma: no cover + assert False + + def send_data(self, data: bytes, write: Writer) -> None: + pass + + def send_eom(self, headers: Headers, write: Writer) -> None: + pass + + +# +# These are all careful not to do anything to 'data' except call len(data) and +# write(data). This allows us to transparently pass-through funny objects, +# like placeholder objects referring to files on disk that will be sent via +# sendfile(2). +# +class ContentLengthWriter(BodyWriter): + def __init__(self, length: int) -> None: + self._length = length + + def send_data(self, data: bytes, write: Writer) -> None: + self._length -= len(data) + if self._length < 0: + raise LocalProtocolError("Too much data for declared Content-Length") + write(data) + + def send_eom(self, headers: Headers, write: Writer) -> None: + if self._length != 0: + raise LocalProtocolError("Too little data for declared Content-Length") + if headers: + raise LocalProtocolError("Content-Length and trailers don't mix") + + +class ChunkedWriter(BodyWriter): + def send_data(self, data: bytes, write: Writer) -> None: + # if we encoded 0-length data in the naive way, it would look like an + # end-of-message. + if not data: + return + write(b"%x\r\n" % len(data)) + write(data) + write(b"\r\n") + + def send_eom(self, headers: Headers, write: Writer) -> None: + write(b"0\r\n") + write_headers(headers, write) + + +class Http10Writer(BodyWriter): + def send_data(self, data: bytes, write: Writer) -> None: + write(data) + + def send_eom(self, headers: Headers, write: Writer) -> None: + if headers: + raise LocalProtocolError("can't send trailers to HTTP/1.0 client") + # no need to close the socket ourselves, that will be taken care of by + # Connection: close machinery + + +WritersType = Dict[ + Union[Tuple[Type[Sentinel], Type[Sentinel]], Type[Sentinel]], + Union[ + Dict[str, Type[BodyWriter]], + Callable[[Union[InformationalResponse, Response], Writer], None], + Callable[[Request, Writer], None], + ], +] + +WRITERS: WritersType = { + (CLIENT, IDLE): write_request, + (SERVER, IDLE): write_any_response, + (SERVER, SEND_RESPONSE): write_any_response, + SEND_BODY: { + "chunked": ChunkedWriter, + "content-length": ContentLengthWriter, + "http/1.0": Http10Writer, + }, +} diff --git a/backend/.venv/Lib/site-packages/h11/py.typed b/backend/.venv/Lib/site-packages/h11/py.typed new file mode 100644 index 0000000..f5642f7 --- /dev/null +++ b/backend/.venv/Lib/site-packages/h11/py.typed @@ -0,0 +1 @@ +Marker diff --git a/backend/.venv/Lib/site-packages/httptools-0.7.1.dist-info/INSTALLER b/backend/.venv/Lib/site-packages/httptools-0.7.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/backend/.venv/Lib/site-packages/httptools-0.7.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/backend/.venv/Lib/site-packages/httptools-0.7.1.dist-info/METADATA b/backend/.venv/Lib/site-packages/httptools-0.7.1.dist-info/METADATA new file mode 100644 index 0000000..6e7d27d --- /dev/null +++ b/backend/.venv/Lib/site-packages/httptools-0.7.1.dist-info/METADATA @@ -0,0 +1,130 @@ +Metadata-Version: 2.4 +Name: httptools +Version: 0.7.1 +Summary: A collection of framework independent HTTP protocol utils. +Author-email: Yury Selivanov +License-Expression: MIT +Project-URL: Homepage, https://github.com/MagicStack/httptools +Platform: macOS +Platform: POSIX +Platform: Windows +Classifier: Intended Audience :: Developers +Classifier: Programming Language :: Python :: 3 +Classifier: Operating System :: POSIX +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Environment :: Web Environment +Classifier: Development Status :: 5 - Production/Stable +Requires-Python: >=3.9 +Description-Content-Type: text/markdown +License-File: LICENSE +Provides-Extra: test +Dynamic: license-file +Dynamic: platform + +![Tests](https://github.com/MagicStack/httptools/workflows/Tests/badge.svg) + +httptools is a Python binding for the nodejs HTTP parser. + +The package is available on PyPI: `pip install httptools`. + + +# APIs + +httptools contains two classes `httptools.HttpRequestParser`, +`httptools.HttpResponseParser` (fulfilled through +[llhttp](https://github.com/nodejs/llhttp)) and a function for +parsing URLs `httptools.parse_url` (through +[http-parse](https://github.com/nodejs/http-parser) for now). +See unittests for examples. + + +```python + +class HttpRequestParser: + + def __init__(self, protocol): + """HttpRequestParser + + protocol -- a Python object with the following methods + (all optional): + + - on_message_begin() + - on_url(url: bytes) + - on_header(name: bytes, value: bytes) + - on_headers_complete() + - on_body(body: bytes) + - on_message_complete() + - on_chunk_header() + - on_chunk_complete() + - on_status(status: bytes) + """ + + def get_http_version(self) -> str: + """Return an HTTP protocol version.""" + + def should_keep_alive(self) -> bool: + """Return ``True`` if keep-alive mode is preferred.""" + + def should_upgrade(self) -> bool: + """Return ``True`` if the parsed request is a valid Upgrade request. + The method exposes a flag set just before on_headers_complete. + Calling this method earlier will only yield `False`. + """ + + def feed_data(self, data: bytes): + """Feed data to the parser. + + Will eventually trigger callbacks on the ``protocol`` + object. + + On HTTP upgrade, this method will raise an + ``HttpParserUpgrade`` exception, with its sole argument + set to the offset of the non-HTTP data in ``data``. + """ + + def get_method(self) -> bytes: + """Return HTTP request method (GET, HEAD, etc)""" + + +class HttpResponseParser: + + """Has all methods except ``get_method()`` that + HttpRequestParser has.""" + + def get_status_code(self) -> int: + """Return the status code of the HTTP response""" + + +def parse_url(url: bytes): + """Parse URL strings into a structured Python object. + + Returns an instance of ``httptools.URL`` class with the + following attributes: + + - schema: bytes + - host: bytes + - port: int + - path: bytes + - query: bytes + - fragment: bytes + - userinfo: bytes + """ +``` + + +# Development + +1. Clone this repository with + `git clone --recursive git@github.com:MagicStack/httptools.git` + +2. Create a virtual environment with Python 3: + `python3 -m venv envname` + +3. Activate the environment with `source envname/bin/activate` + +4. Run `make` and `make test`. + + +# License + +MIT. diff --git a/backend/.venv/Lib/site-packages/httptools-0.7.1.dist-info/RECORD b/backend/.venv/Lib/site-packages/httptools-0.7.1.dist-info/RECORD new file mode 100644 index 0000000..8616e4d --- /dev/null +++ b/backend/.venv/Lib/site-packages/httptools-0.7.1.dist-info/RECORD @@ -0,0 +1,25 @@ +httptools-0.7.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +httptools-0.7.1.dist-info/METADATA,sha256=SDOnsarDrAxgLgiOHmAxC9OnA4Ca9XEeI6DB1McUYKU,3602 +httptools-0.7.1.dist-info/RECORD,, +httptools-0.7.1.dist-info/WHEEL,sha256=8UP9x9puWI0P1V_d7K2oMTBqfeLNm21CTzZ_Ptr0NXU,101 +httptools-0.7.1.dist-info/licenses/LICENSE,sha256=HAKLBZ16WOFMzaOMq87WmMWR_mFP--T3IUMERuhsjWk,1114 +httptools-0.7.1.dist-info/top_level.txt,sha256=APjJKTbZcj0OQ4fdgf2eTCk82nK1n2BFXOD7ky41MPY,10 +httptools/__init__.py,sha256=uWLIa0nghlhLGoS8My_6YVhUlFbv3FhYsvxYpZHecS8,153 +httptools/__pycache__/__init__.cpython-312.pyc,, +httptools/__pycache__/_version.cpython-312.pyc,, +httptools/_version.py,sha256=L1qOIEGz2abHAuE9FSwFU6Q3tDr3nhuABOTtgE9ISv0,588 +httptools/parser/__init__.py,sha256=mXOisHGQtSCaaFE1RNgTtEhEnqhMqi9jFWaAGSIUktY,207 +httptools/parser/__pycache__/__init__.cpython-312.pyc,, +httptools/parser/__pycache__/errors.cpython-312.pyc,, +httptools/parser/__pycache__/protocol.cpython-312.pyc,, +httptools/parser/cparser.pxd,sha256=XOczyt3PFtYc1r-GVKecEkN5zvBD78NXfd2JhyKOKBg,5144 +httptools/parser/errors.py,sha256=fQeEGiZ6AQH7SIa-7uzMs5QggoXr0A8YBPVHmafSw5Q,596 +httptools/parser/parser.cp312-win_amd64.pyd,sha256=wEGy73nXDbxcPRWwYaLMdghZVp8RdhMzx4wQ8nd1lJs,124928 +httptools/parser/parser.pyi,sha256=ipY5DWsoBI-XSUw_GONH2l1WkG97vQlB6aSnE4ilmcI,1918 +httptools/parser/parser.pyx,sha256=jgDH58PbHrXpT4wGDptP02tGsceOo9qHYSJBdpK5ZEs,15576 +httptools/parser/protocol.py,sha256=tGhmbKw2mlmwWmfo400sugh9F6ghjBSG4R84OJEpR-4,557 +httptools/parser/python.pxd,sha256=-pIXNLe1u3u3X51ORUUoHRBMsntzRlQa3z2iBqljTHU,144 +httptools/parser/url_cparser.pxd,sha256=rvPJV7S96tTqKMT0Bk4jHgMy2U0rNY5_NsPa7KG5lio,810 +httptools/parser/url_parser.cp312-win_amd64.pyd,sha256=88yuR0w15716AwF5VBDhj_YEk8G3Rzi4_o6jscpMhC4,53248 +httptools/parser/url_parser.pyi,sha256=YFt6ooO5GGv_IG7-Mq1vZHi3jBIMWAquUv87TPyMTBU,592 +httptools/parser/url_parser.pyx,sha256=_ZmJwXC2kh6Rh6FLQTy3nGBiZBBPAX9O-pWtGlgS-44,3866 diff --git a/backend/.venv/Lib/site-packages/httptools-0.7.1.dist-info/WHEEL b/backend/.venv/Lib/site-packages/httptools-0.7.1.dist-info/WHEEL new file mode 100644 index 0000000..10ac2c2 --- /dev/null +++ b/backend/.venv/Lib/site-packages/httptools-0.7.1.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/httptools-0.7.1.dist-info/licenses/LICENSE b/backend/.venv/Lib/site-packages/httptools-0.7.1.dist-info/licenses/LICENSE new file mode 100644 index 0000000..79a03ca --- /dev/null +++ b/backend/.venv/Lib/site-packages/httptools-0.7.1.dist-info/licenses/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2015 MagicStack Inc. http://magic.io + +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/httptools-0.7.1.dist-info/top_level.txt b/backend/.venv/Lib/site-packages/httptools-0.7.1.dist-info/top_level.txt new file mode 100644 index 0000000..bef3b40 --- /dev/null +++ b/backend/.venv/Lib/site-packages/httptools-0.7.1.dist-info/top_level.txt @@ -0,0 +1 @@ +httptools diff --git a/backend/.venv/Lib/site-packages/httptools/__init__.py b/backend/.venv/Lib/site-packages/httptools/__init__.py new file mode 100644 index 0000000..972053e --- /dev/null +++ b/backend/.venv/Lib/site-packages/httptools/__init__.py @@ -0,0 +1,6 @@ +from . import parser +from .parser import * # NOQA + +from ._version import __version__ # NOQA + +__all__ = parser.__all__ + ('__version__',) # NOQA diff --git a/backend/.venv/Lib/site-packages/httptools/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/httptools/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..91cecf33e7517188130e10e45620ecb65916e771 GIT binary patch literal 335 zcmYL_u}Z{15QcZM7cZP1SZE~{mhnjJMQyYcTOlkgxnw!_ve^y0dy%uVw6Z*W1PhVTBWpR+HfT)Jq!H?Y3$~j zpzCVCm3>N6At=2^ODECy`SCuvRJt%#nlU1$)tIKCmt%s9v`2WlM^4mlHoJRO~2xt ztzydai?WLg5|dM7^0G>bbrX}5^GoweGV{`Plk8-)^SeMJ~-1Ue|T(E&>skT_bxDH&6=z DH2iDT literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/httptools/parser/__pycache__/errors.cpython-312.pyc b/backend/.venv/Lib/site-packages/httptools/parser/__pycache__/errors.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0e2d431bd9cdef3c69c1a449902dcb661a646cda GIT binary patch literal 1209 zcma)*F;Ck-6vyxEB(_6BU_dQWD|O8f*sIbG2(?HQRV^%$rPE=bf*a#=&zF>J42&JR z!N`jEDE$JJ*M0${q)Vs1cLtoQL9&PEzkmO`zwPJeAMJLNz|r%!q63SNUwCnU)bGUf z8;A=Ml0LD>TN2W95?X@Z*oEJ>47GvQg!MpeL+d~rbF^lt1Js?PbwfR%%{kgIbO~r{ z?rzSc-CgcB^3FT0(+^x_LhUFeRsN&|+dPhscrYxCXQi>5jCmY|pETE_>@oMf(8n?? z-1YzV9)8>_tku#wOb3dGBDn7yp6T7iv<2dV2-2s}L2E+0mV!=`{cAgS8B6$yU@UJk zb|S-3jJn0xml2N(=bB70=#Rhs(*G*eFiUwL{N%IFdOQf^DA7?e=mk;d>}Ia7#gOfjI+(uv~5#h-?EK#Vjjp85AHR^4}VU6)?Bp=%J9ms zhC{KhFh;epn1l{0bWAaP<-tT=Ilcyq7ssQcu&kme;}KPk$2VUbkB-8!hN6r|R5`u@ zix!w^n`W#hEi(q15{x%?O-kE|g1I>Z>=8=uXKm Kz2CUkjMQICJL;YQ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/httptools/parser/__pycache__/protocol.cpython-312.pyc b/backend/.venv/Lib/site-packages/httptools/parser/__pycache__/protocol.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..890f401ac0038c603ec6bad580b9b7cd5886adc7 GIT binary patch literal 1839 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 Obc(0RE5Dyt4g5E2@AWkR literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/httptools/parser/parser.pyi b/backend/.venv/Lib/site-packages/httptools/parser/parser.pyi new file mode 100644 index 0000000..8a714bf --- /dev/null +++ b/backend/.venv/Lib/site-packages/httptools/parser/parser.pyi @@ -0,0 +1,57 @@ +from typing import Union, Any +from array import array +from .protocol import HTTPProtocol + +class HttpParser: + def __init__(self, protocol: Union[HTTPProtocol, Any]) -> None: + """ + protocol -- a Python object with the following methods + (all optional): + + - on_message_begin() + - on_url(url: bytes) + - on_header(name: bytes, value: bytes) + - on_headers_complete() + - on_body(body: bytes) + - on_message_complete() + - on_chunk_header() + - on_chunk_complete() + - on_status(status: bytes) + """ + + def get_http_version(self) -> str: + """Return an HTTP protocol version.""" + ... + + def should_keep_alive(self) -> bool: + """Return ``True`` if keep-alive mode is preferred.""" + ... + + def should_upgrade(self) -> bool: + """Return ``True`` if the parsed request is a valid Upgrade request. + The method exposes a flag set just before on_headers_complete. + Calling this method earlier will only yield `False`.""" + ... + + def feed_data(self, data: Union[bytes, bytearray, memoryview, array]) -> None: + """Feed data to the parser. + + Will eventually trigger callbacks on the ``protocol`` + object. + + On HTTP upgrade, this method will raise an + ``HttpParserUpgrade`` exception, with its sole argument + set to the offset of the non-HTTP data in ``data``. + """ + +class HttpRequestParser(HttpParser): + """Used for parsing http requests from the server's side""" + + def get_method(self) -> bytes: + """Return HTTP request method (GET, HEAD, etc)""" + +class HttpResponseParser(HttpParser): + """Used for parsing http requests from the client's side""" + + def get_status_code(self) -> int: + """Return the status code of the HTTP response""" diff --git a/backend/.venv/Lib/site-packages/httptools/parser/parser.pyx b/backend/.venv/Lib/site-packages/httptools/parser/parser.pyx new file mode 100644 index 0000000..2fa5026 --- /dev/null +++ b/backend/.venv/Lib/site-packages/httptools/parser/parser.pyx @@ -0,0 +1,436 @@ +#cython: language_level=3 + +from __future__ import print_function +from typing import Optional + +from cpython.mem cimport PyMem_Malloc, PyMem_Free +from cpython cimport PyObject_GetBuffer, PyBuffer_Release, PyBUF_SIMPLE, \ + Py_buffer, PyBytes_AsString + +from .python cimport PyMemoryView_Check, PyMemoryView_GET_BUFFER + + +from .errors import (HttpParserError, + HttpParserCallbackError, + HttpParserInvalidStatusError, + HttpParserInvalidMethodError, + HttpParserInvalidURLError, + HttpParserUpgrade) + +cimport cython +from . cimport cparser + + +__all__ = ('HttpRequestParser', 'HttpResponseParser') + + +@cython.internal +cdef class HttpParser: + + cdef: + cparser.llhttp_t* _cparser + cparser.llhttp_settings_t* _csettings + + bytes _current_header_name + bytes _current_header_value + + _proto_on_url, _proto_on_status, _proto_on_body, \ + _proto_on_header, _proto_on_headers_complete, \ + _proto_on_message_complete, _proto_on_chunk_header, \ + _proto_on_chunk_complete, _proto_on_message_begin + + object _last_error + + Py_buffer py_buf + + def __cinit__(self): + self._cparser = \ + PyMem_Malloc(sizeof(cparser.llhttp_t)) + if self._cparser is NULL: + raise MemoryError() + + self._csettings = \ + PyMem_Malloc(sizeof(cparser.llhttp_settings_t)) + if self._csettings is NULL: + raise MemoryError() + + def __dealloc__(self): + PyMem_Free(self._cparser) + PyMem_Free(self._csettings) + + cdef _init(self, protocol, cparser.llhttp_type_t mode): + cparser.llhttp_settings_init(self._csettings) + + cparser.llhttp_init(self._cparser, mode, self._csettings) + self._cparser.data = self + + self._current_header_name = None + self._current_header_value = None + + self._proto_on_header = getattr(protocol, 'on_header', None) + if self._proto_on_header is not None: + self._csettings.on_header_field = cb_on_header_field + self._csettings.on_header_value = cb_on_header_value + self._proto_on_headers_complete = getattr( + protocol, 'on_headers_complete', None) + self._csettings.on_headers_complete = cb_on_headers_complete + + self._proto_on_body = getattr(protocol, 'on_body', None) + if self._proto_on_body is not None: + self._csettings.on_body = cb_on_body + + self._proto_on_message_begin = getattr( + protocol, 'on_message_begin', None) + if self._proto_on_message_begin is not None: + self._csettings.on_message_begin = cb_on_message_begin + + self._proto_on_message_complete = getattr( + protocol, 'on_message_complete', None) + if self._proto_on_message_complete is not None: + self._csettings.on_message_complete = cb_on_message_complete + + self._proto_on_chunk_header = getattr( + protocol, 'on_chunk_header', None) + self._csettings.on_chunk_header = cb_on_chunk_header + + self._proto_on_chunk_complete = getattr( + protocol, 'on_chunk_complete', None) + self._csettings.on_chunk_complete = cb_on_chunk_complete + + self._last_error = None + + cdef _maybe_call_on_header(self): + if self._current_header_value is not None: + current_header_name = self._current_header_name + current_header_value = self._current_header_value + + self._current_header_name = self._current_header_value = None + + if self._proto_on_header is not None: + self._proto_on_header(current_header_name, + current_header_value) + + cdef _on_header_field(self, bytes field): + self._maybe_call_on_header() + if self._current_header_name is None: + self._current_header_name = field + else: + self._current_header_name += field + + cdef _on_header_value(self, bytes val): + if self._current_header_value is None: + self._current_header_value = val + else: + # This is unlikely, as mostly HTTP headers are one-line + self._current_header_value += val + + cdef _on_headers_complete(self): + self._maybe_call_on_header() + + if self._proto_on_headers_complete is not None: + self._proto_on_headers_complete() + + cdef _on_chunk_header(self): + if (self._current_header_value is not None or + self._current_header_name is not None): + raise HttpParserError('invalid headers state') + + if self._proto_on_chunk_header is not None: + self._proto_on_chunk_header() + + cdef _on_chunk_complete(self): + self._maybe_call_on_header() + + if self._proto_on_chunk_complete is not None: + self._proto_on_chunk_complete() + + ### Public API ### + + def set_dangerous_leniencies( + self, + lenient_headers: Optional[bool] = None, + lenient_chunked_length: Optional[bool] = None, + lenient_keep_alive: Optional[bool] = None, + lenient_transfer_encoding: Optional[bool] = None, + lenient_version: Optional[bool] = None, + lenient_data_after_close: Optional[bool] = None, + lenient_optional_lf_after_cr: Optional[bool] = None, + lenient_optional_cr_before_lf: Optional[bool] = None, + lenient_optional_crlf_after_chunk: Optional[bool] = None, + lenient_spaces_after_chunk_size: Optional[bool] = None, + ): + cdef cparser.llhttp_t* parser = self._cparser + if lenient_headers is not None: + cparser.llhttp_set_lenient_headers( + parser, lenient_headers) + if lenient_chunked_length is not None: + cparser.llhttp_set_lenient_chunked_length( + parser, lenient_chunked_length) + if lenient_keep_alive is not None: + cparser.llhttp_set_lenient_keep_alive( + parser, lenient_keep_alive) + if lenient_transfer_encoding is not None: + cparser.llhttp_set_lenient_transfer_encoding( + parser, lenient_transfer_encoding) + if lenient_version is not None: + cparser.llhttp_set_lenient_version( + parser, lenient_version) + if lenient_data_after_close is not None: + cparser.llhttp_set_lenient_data_after_close( + parser, lenient_data_after_close) + if lenient_optional_lf_after_cr is not None: + cparser.llhttp_set_lenient_optional_lf_after_cr( + parser, lenient_optional_lf_after_cr) + if lenient_optional_cr_before_lf is not None: + cparser.llhttp_set_lenient_optional_cr_before_lf( + parser, lenient_optional_cr_before_lf) + if lenient_optional_crlf_after_chunk is not None: + cparser.llhttp_set_lenient_optional_crlf_after_chunk( + parser, lenient_optional_crlf_after_chunk) + if lenient_spaces_after_chunk_size is not None: + cparser.llhttp_set_lenient_spaces_after_chunk_size( + parser, lenient_spaces_after_chunk_size) + + def get_http_version(self): + cdef cparser.llhttp_t* parser = self._cparser + return '{}.{}'.format(parser.http_major, parser.http_minor) + + def should_keep_alive(self): + return bool(cparser.llhttp_should_keep_alive(self._cparser)) + + def should_upgrade(self): + cdef cparser.llhttp_t* parser = self._cparser + return bool(parser.upgrade) + + def feed_data(self, data): + cdef: + size_t data_len + cparser.llhttp_errno_t err + Py_buffer *buf + bint owning_buf = False + const char* err_pos + + if PyMemoryView_Check(data): + buf = PyMemoryView_GET_BUFFER(data) + data_len = buf.len + err = cparser.llhttp_execute( + self._cparser, + buf.buf, + data_len) + + else: + buf = &self.py_buf + PyObject_GetBuffer(data, buf, PyBUF_SIMPLE) + owning_buf = True + data_len = buf.len + + err = cparser.llhttp_execute( + self._cparser, + buf.buf, + data_len) + + try: + if self._cparser.upgrade == 1 and err == cparser.HPE_PAUSED_UPGRADE: + err_pos = cparser.llhttp_get_error_pos(self._cparser) + + # Immediately free the parser from "error" state, simulating + # http-parser behavior here because 1) we never had the API to + # allow users manually "resume after upgrade", and 2) the use + # case for resuming parsing is very rare. + cparser.llhttp_resume_after_upgrade(self._cparser) + + # The err_pos here is specific for the input buf. So if we ever + # switch to the llhttp behavior (re-raise HttpParserUpgrade for + # successive calls to feed_data() until resume_after_upgrade is + # called), we have to store the result and keep our own state. + raise HttpParserUpgrade(err_pos - buf.buf) + finally: + if owning_buf: + PyBuffer_Release(buf) + + if err != cparser.HPE_OK: + ex = parser_error_from_errno( + self._cparser, + self._cparser.error) + if isinstance(ex, HttpParserCallbackError): + if self._last_error is not None: + ex.__context__ = self._last_error + self._last_error = None + raise ex + + +cdef class HttpRequestParser(HttpParser): + + def __init__(self, protocol): + self._init(protocol, cparser.HTTP_REQUEST) + + self._proto_on_url = getattr(protocol, 'on_url', None) + if self._proto_on_url is not None: + self._csettings.on_url = cb_on_url + + def get_method(self): + cdef cparser.llhttp_t* parser = self._cparser + return cparser.llhttp_method_name( parser.method) + + +cdef class HttpResponseParser(HttpParser): + + def __init__(self, protocol): + self._init(protocol, cparser.HTTP_RESPONSE) + + self._proto_on_status = getattr(protocol, 'on_status', None) + if self._proto_on_status is not None: + self._csettings.on_status = cb_on_status + + def get_status_code(self): + cdef cparser.llhttp_t* parser = self._cparser + return parser.status_code + + +cdef int cb_on_message_begin(cparser.llhttp_t* parser) except -1: + cdef HttpParser pyparser = parser.data + try: + pyparser._proto_on_message_begin() + except BaseException as ex: + pyparser._last_error = ex + return -1 + else: + return 0 + + +cdef int cb_on_url(cparser.llhttp_t* parser, + const char *at, size_t length) except -1: + cdef HttpParser pyparser = parser.data + try: + pyparser._proto_on_url(at[:length]) + except BaseException as ex: + cparser.llhttp_set_error_reason(parser, "`on_url` callback error") + pyparser._last_error = ex + return cparser.HPE_USER + else: + return 0 + + +cdef int cb_on_status(cparser.llhttp_t* parser, + const char *at, size_t length) except -1: + cdef HttpParser pyparser = parser.data + try: + pyparser._proto_on_status(at[:length]) + except BaseException as ex: + cparser.llhttp_set_error_reason(parser, "`on_status` callback error") + pyparser._last_error = ex + return cparser.HPE_USER + else: + return 0 + + +cdef int cb_on_header_field(cparser.llhttp_t* parser, + const char *at, size_t length) except -1: + cdef HttpParser pyparser = parser.data + try: + pyparser._on_header_field(at[:length]) + except BaseException as ex: + cparser.llhttp_set_error_reason(parser, "`on_header_field` callback error") + pyparser._last_error = ex + return cparser.HPE_USER + else: + return 0 + + +cdef int cb_on_header_value(cparser.llhttp_t* parser, + const char *at, size_t length) except -1: + cdef HttpParser pyparser = parser.data + try: + pyparser._on_header_value(at[:length]) + except BaseException as ex: + cparser.llhttp_set_error_reason(parser, "`on_header_value` callback error") + pyparser._last_error = ex + return cparser.HPE_USER + else: + return 0 + + +cdef int cb_on_headers_complete(cparser.llhttp_t* parser) except -1: + cdef HttpParser pyparser = parser.data + try: + pyparser._on_headers_complete() + except BaseException as ex: + pyparser._last_error = ex + return -1 + else: + if pyparser._cparser.upgrade: + return 1 + else: + return 0 + + +cdef int cb_on_body(cparser.llhttp_t* parser, + const char *at, size_t length) except -1: + cdef HttpParser pyparser = parser.data + try: + pyparser._proto_on_body(at[:length]) + except BaseException as ex: + cparser.llhttp_set_error_reason(parser, "`on_body` callback error") + pyparser._last_error = ex + return cparser.HPE_USER + else: + return 0 + + +cdef int cb_on_message_complete(cparser.llhttp_t* parser) except -1: + cdef HttpParser pyparser = parser.data + try: + pyparser._proto_on_message_complete() + except BaseException as ex: + pyparser._last_error = ex + return -1 + else: + return 0 + + +cdef int cb_on_chunk_header(cparser.llhttp_t* parser) except -1: + cdef HttpParser pyparser = parser.data + try: + pyparser._on_chunk_header() + except BaseException as ex: + pyparser._last_error = ex + return -1 + else: + return 0 + + +cdef int cb_on_chunk_complete(cparser.llhttp_t* parser) except -1: + cdef HttpParser pyparser = parser.data + try: + pyparser._on_chunk_complete() + except BaseException as ex: + pyparser._last_error = ex + return -1 + else: + return 0 + + +cdef parser_error_from_errno(cparser.llhttp_t* parser, cparser.llhttp_errno_t errno): + cdef bytes reason = cparser.llhttp_get_error_reason(parser) + + if errno in (cparser.HPE_CB_MESSAGE_BEGIN, + cparser.HPE_CB_HEADERS_COMPLETE, + cparser.HPE_CB_MESSAGE_COMPLETE, + cparser.HPE_CB_CHUNK_HEADER, + cparser.HPE_CB_CHUNK_COMPLETE, + cparser.HPE_USER): + cls = HttpParserCallbackError + + elif errno == cparser.HPE_INVALID_STATUS: + cls = HttpParserInvalidStatusError + + elif errno == cparser.HPE_INVALID_METHOD: + cls = HttpParserInvalidMethodError + + elif errno == cparser.HPE_INVALID_URL: + cls = HttpParserInvalidURLError + + else: + cls = HttpParserError + + return cls(reason.decode('latin-1')) diff --git a/backend/.venv/Lib/site-packages/httptools/parser/protocol.py b/backend/.venv/Lib/site-packages/httptools/parser/protocol.py new file mode 100644 index 0000000..c3b4234 --- /dev/null +++ b/backend/.venv/Lib/site-packages/httptools/parser/protocol.py @@ -0,0 +1,15 @@ +from typing import Protocol + + +class HTTPProtocol(Protocol): + """Used for providing static type-checking when parsing through the http protocol""" + + def on_message_begin() -> None: ... + def on_url(url: bytes) -> None: ... + def on_header(name: bytes, value: bytes) -> None: ... + def on_headers_complete() -> None: ... + def on_body(body: bytes) -> None: ... + def on_message_complete() -> None: ... + def on_chunk_header() -> None: ... + def on_chunk_complete() -> None: ... + def on_status(status: bytes) -> None: ... diff --git a/backend/.venv/Lib/site-packages/httptools/parser/python.pxd b/backend/.venv/Lib/site-packages/httptools/parser/python.pxd new file mode 100644 index 0000000..8e95925 --- /dev/null +++ b/backend/.venv/Lib/site-packages/httptools/parser/python.pxd @@ -0,0 +1,6 @@ +cimport cpython + + +cdef extern from "Python.h": + cpython.Py_buffer* PyMemoryView_GET_BUFFER(object) + bint PyMemoryView_Check(object) diff --git a/backend/.venv/Lib/site-packages/httptools/parser/url_cparser.pxd b/backend/.venv/Lib/site-packages/httptools/parser/url_cparser.pxd new file mode 100644 index 0000000..ab9265a --- /dev/null +++ b/backend/.venv/Lib/site-packages/httptools/parser/url_cparser.pxd @@ -0,0 +1,31 @@ +from libc.stdint cimport uint16_t + + +cdef extern from "http_parser.h": + # URL Parser + + enum http_parser_url_fields: + UF_SCHEMA = 0, + UF_HOST = 1, + UF_PORT = 2, + UF_PATH = 3, + UF_QUERY = 4, + UF_FRAGMENT = 5, + UF_USERINFO = 6, + UF_MAX = 7 + + struct http_parser_url_field_data: + uint16_t off + uint16_t len + + struct http_parser_url: + uint16_t field_set + uint16_t port + http_parser_url_field_data[UF_MAX] field_data + + void http_parser_url_init(http_parser_url *u) + + int http_parser_parse_url(const char *buf, + size_t buflen, + int is_connect, + http_parser_url *u) diff --git a/backend/.venv/Lib/site-packages/httptools/parser/url_parser.cp312-win_amd64.pyd b/backend/.venv/Lib/site-packages/httptools/parser/url_parser.cp312-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..1c639ab5f6794df2c8523e19cf77cc9debfc032f GIT binary patch literal 53248 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 N@;p`c)O$S|{{vyr=1l+q literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/httptools/parser/url_parser.pyi b/backend/.venv/Lib/site-packages/httptools/parser/url_parser.pyi new file mode 100644 index 0000000..f3d3488 --- /dev/null +++ b/backend/.venv/Lib/site-packages/httptools/parser/url_parser.pyi @@ -0,0 +1,27 @@ +from typing import Union +from array import array + +class URL: + schema: bytes + host: bytes + port: int + path: bytes + query: bytes + fragment: bytes + userinfo: bytes + +def parse_url(url: Union[bytes, bytearray, memoryview, array]) -> URL: + """Parse URL strings into a structured Python object. + + Returns an instance of ``httptools.URL`` class with the + following attributes: + + - schema: bytes + - host: bytes + - port: int + - path: bytes + - query: bytes + - fragment: bytes + - userinfo: bytes + """ + ... diff --git a/backend/.venv/Lib/site-packages/httptools/parser/url_parser.pyx b/backend/.venv/Lib/site-packages/httptools/parser/url_parser.pyx new file mode 100644 index 0000000..49908f3 --- /dev/null +++ b/backend/.venv/Lib/site-packages/httptools/parser/url_parser.pyx @@ -0,0 +1,108 @@ +#cython: language_level=3 + +from __future__ import print_function +from cpython.mem cimport PyMem_Malloc, PyMem_Free +from cpython cimport PyObject_GetBuffer, PyBuffer_Release, PyBUF_SIMPLE, \ + Py_buffer + +from .errors import HttpParserInvalidURLError + +cimport cython +from . cimport url_cparser as uparser + +__all__ = ('parse_url',) + +@cython.freelist(250) +cdef class URL: + cdef readonly bytes schema + cdef readonly bytes host + cdef readonly object port + cdef readonly bytes path + cdef readonly bytes query + cdef readonly bytes fragment + cdef readonly bytes userinfo + + def __cinit__(self, bytes schema, bytes host, object port, bytes path, + bytes query, bytes fragment, bytes userinfo): + + self.schema = schema + self.host = host + self.port = port + self.path = path + self.query = query + self.fragment = fragment + self.userinfo = userinfo + + def __repr__(self): + return ('' + .format(self.schema, self.host, self.port, self.path, + self.query, self.fragment, self.userinfo)) + + +def parse_url(url): + cdef: + Py_buffer py_buf + char* buf_data + uparser.http_parser_url* parsed + int res + bytes schema = None + bytes host = None + object port = None + bytes path = None + bytes query = None + bytes fragment = None + bytes userinfo = None + object result = None + int off + int ln + + parsed = \ + PyMem_Malloc(sizeof(uparser.http_parser_url)) + uparser.http_parser_url_init(parsed) + + PyObject_GetBuffer(url, &py_buf, PyBUF_SIMPLE) + try: + buf_data = py_buf.buf + res = uparser.http_parser_parse_url(buf_data, py_buf.len, 0, parsed) + + if res == 0: + if parsed.field_set & (1 << uparser.UF_SCHEMA): + off = parsed.field_data[uparser.UF_SCHEMA].off + ln = parsed.field_data[uparser.UF_SCHEMA].len + schema = buf_data[off:off+ln] + + if parsed.field_set & (1 << uparser.UF_HOST): + off = parsed.field_data[uparser.UF_HOST].off + ln = parsed.field_data[uparser.UF_HOST].len + host = buf_data[off:off+ln] + + if parsed.field_set & (1 << uparser.UF_PORT): + port = parsed.port + + if parsed.field_set & (1 << uparser.UF_PATH): + off = parsed.field_data[uparser.UF_PATH].off + ln = parsed.field_data[uparser.UF_PATH].len + path = buf_data[off:off+ln] + + if parsed.field_set & (1 << uparser.UF_QUERY): + off = parsed.field_data[uparser.UF_QUERY].off + ln = parsed.field_data[uparser.UF_QUERY].len + query = buf_data[off:off+ln] + + if parsed.field_set & (1 << uparser.UF_FRAGMENT): + off = parsed.field_data[uparser.UF_FRAGMENT].off + ln = parsed.field_data[uparser.UF_FRAGMENT].len + fragment = buf_data[off:off+ln] + + if parsed.field_set & (1 << uparser.UF_USERINFO): + off = parsed.field_data[uparser.UF_USERINFO].off + ln = parsed.field_data[uparser.UF_USERINFO].len + userinfo = buf_data[off:off+ln] + + return URL(schema, host, port, path, query, fragment, userinfo) + else: + raise HttpParserInvalidURLError("invalid url {!r}".format(url)) + finally: + PyBuffer_Release(&py_buf) + PyMem_Free(parsed) diff --git a/backend/.venv/Lib/site-packages/idna-3.11.dist-info/INSTALLER b/backend/.venv/Lib/site-packages/idna-3.11.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/backend/.venv/Lib/site-packages/idna-3.11.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/backend/.venv/Lib/site-packages/idna-3.11.dist-info/METADATA b/backend/.venv/Lib/site-packages/idna-3.11.dist-info/METADATA new file mode 100644 index 0000000..7a4a4b7 --- /dev/null +++ b/backend/.venv/Lib/site-packages/idna-3.11.dist-info/METADATA @@ -0,0 +1,209 @@ +Metadata-Version: 2.4 +Name: idna +Version: 3.11 +Summary: Internationalized Domain Names in Applications (IDNA) +Author-email: Kim Davies +Requires-Python: >=3.8 +Description-Content-Type: text/x-rst +License-Expression: BSD-3-Clause +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: System Administrators +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.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 :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Internet :: Name Service (DNS) +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Utilities +License-File: LICENSE.md +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 `Internationalized Domain Names in +Applications (IDNA) `_ +and `Unicode IDNA Compatibility Processing +`_. + +The latest versions of these standards supplied here provide +more comprehensive language coverage and reduce the potential of +allowing domains with known security vulnerabilities. This library +is a suitable replacement for the “encodings.idna” +module that comes with the Python standard library, but which +only supports an older superseded IDNA specification from 2003. + +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 via the +typical mechanisms, such as: + +.. 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 ASCII compatible encoding +(known as A-labels), or to Unicode strings (known as U-labels) +respectively. + +.. code-block:: pycon + + >>> import idna + >>> idna.encode('ドメイン.テスト') + b'xn--eckwd4c7c.xn--zckzah' + >>> print(idna.decode('xn--eckwd4c7c.xn--zckzah')) + ドメイン.テスト + +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) ++++++++++++++++++++++++++++++++ + +This library provides support for `Unicode IDNA Compatibility +Processing `_ which normalizes input from +different potential ways a user may input a domain prior to performing the IDNA +conversion operations. This functionality, known as a +`mapping `_, is considered by the +specification to be a local user-interface issue distinct from IDNA +conversion functionality. + +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 + + +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 position in the string (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 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.8 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. + Support for older versions are likely to be removed from new releases + as automated tests can no longer easily be run, i.e. once the Python + version is officially end-of-life. + +* **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. + +* **Transitional processing**. Unicode 16.0.0 removed transitional + processing so the `transitional` argument for the encode() method + no longer has any effect and will be removed at a later date. + diff --git a/backend/.venv/Lib/site-packages/idna-3.11.dist-info/RECORD b/backend/.venv/Lib/site-packages/idna-3.11.dist-info/RECORD new file mode 100644 index 0000000..1203f10 --- /dev/null +++ b/backend/.venv/Lib/site-packages/idna-3.11.dist-info/RECORD @@ -0,0 +1,22 @@ +idna-3.11.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +idna-3.11.dist-info/METADATA,sha256=fCwSww9SuiN8TIHllFSASUQCW55hAs8dzKnr9RaEEbA,8378 +idna-3.11.dist-info/RECORD,, +idna-3.11.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82 +idna-3.11.dist-info/licenses/LICENSE.md,sha256=t6M2q_OwThgOwGXN0W5wXQeeHMehT5EKpukYfza5zYc,1541 +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=M2SGWN7cs_6B32QmKTyTN6xQGZeYQgQ2wiX3_DR6loE,3438 +idna/compat.py,sha256=RzLy6QQCdl9784aFhb2EX9EKGCJjg0P3PilGdeXXcx8,316 +idna/core.py,sha256=P26_XVycuMTZ1R2mNK1ZREVzM5mvTzdabBXfyZVU1Lc,13246 +idna/idnadata.py,sha256=SG8jhaGE53iiD6B49pt2pwTv_UvClciWE-N54oR2p4U,79623 +idna/intranges.py,sha256=amUtkdhYcQG8Zr-CoMM_kVRacxkivC1WgxN1b63KKdU,1898 +idna/package_data.py,sha256=_CUavOxobnbyNG2FLyHoN8QHP3QM9W1tKuw7eq9QwBk,21 +idna/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +idna/uts46data.py,sha256=H9J35VkD0F9L9mKOqjeNGd2A-Va6FlPoz6Jz4K7h-ps,243725 diff --git a/backend/.venv/Lib/site-packages/idna-3.11.dist-info/WHEEL b/backend/.venv/Lib/site-packages/idna-3.11.dist-info/WHEEL new file mode 100644 index 0000000..d8b9936 --- /dev/null +++ b/backend/.venv/Lib/site-packages/idna-3.11.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/idna-3.11.dist-info/licenses/LICENSE.md b/backend/.venv/Lib/site-packages/idna-3.11.dist-info/licenses/LICENSE.md new file mode 100644 index 0000000..256ba90 --- /dev/null +++ b/backend/.venv/Lib/site-packages/idna-3.11.dist-info/licenses/LICENSE.md @@ -0,0 +1,31 @@ +BSD 3-Clause License + +Copyright (c) 2013-2025, 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/__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..0ff5339d66bcf8f909de4b7337841a77c35e0e8f GIT binary patch literal 877 zcmbu7J&)5c7{~22O`E3adwUFs4T%iBTMz>RBq$6gp&J;jNS2$J*4Nms9JkPsPr=T{ zXW<)IVq#)LoX|;3*hyhHBo;jU@;v|8|L5_`r#S8aJLc(QmNx+S;*#IPI|f(U2Jb-* za##Qk5#%27cmp-Kk9^)lO&*|tw@{0>QJaS-%E5sG*hb$N_p-a|d!M}0m(13pAU zK0+ht{Jdh!CumZ|jbh4YXa>OwDbe)p%5_pYUG+ZDe6pET~; 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..96c6f06e636059ef9faf4084381fc9beebe35864 GIT binary patch literal 4967 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 Osn2{mw0@Pk?BNeN7sRdr literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/idna/__pycache__/core.cpython-312.pyc b/backend/.venv/Lib/site-packages/idna/__pycache__/core.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..95cdef068bd377eda06c2064469a0c6aa0c9c966 GIT binary patch literal 16134 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�nk9PH;i9#D`zT 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 AnE(I) literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/idna/__pycache__/idnadata.cpython-312.pyc b/backend/.venv/Lib/site-packages/idna/__pycache__/idnadata.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ab3d15d84e66d22d0bc36cdea0d2dce90491d794 GIT binary patch literal 100906 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/idna/__pycache__/package_data.cpython-312.pyc b/backend/.venv/Lib/site-packages/idna/__pycache__/package_data.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..caeafe1bdf455f4bb8e51533f855c5f59de38d62 GIT binary patch literal 208 zcmX@j%ge<81iCS{nW8}YF^B^Lj8MjB4j^MXLkdF_LnWgoQx%J`o}raWt9}`CMGB6m*$mZ=B4W<=NF~MBqb(i zr{<-^=#{1BmBsjECdCwImZa(eHDo8IrxwR#rsO5+LwWHji6x181(mlrY;yBcN^?@} cir9eGfSgtga`^{lMn=XPd?Jn9MJzxr08N=WGynhq 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..bbe4fbfef736d466f22da73bfedfad969c5e9294 GIT binary patch literal 161836 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 F{|75vFw_75 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/idna/codec.py b/backend/.venv/Lib/site-packages/idna/codec.py new file mode 100644 index 0000000..cbc2e4f --- /dev/null +++ b/backend/.venv/Lib/site-packages/idna/codec.py @@ -0,0 +1,122 @@ +import codecs +import re +from typing import Any, Optional, Tuple + +from .core import IDNAError, alabel, decode, encode, ulabel + +_unicode_dots_re = re.compile("[\u002e\u3002\uff0e\uff61]") + + +class Codec(codecs.Codec): + def encode(self, data: str, errors: str = "strict") -> 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, # type: ignore + 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..8177bf7 --- /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 = 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..ded47ca --- /dev/null +++ b/backend/.venv/Lib/site-packages/idna/idnadata.py @@ -0,0 +1,4309 @@ +# This file is automatically generated by tools/idna-data + +__version__ = "16.0.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, + 0x897: 84, + 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, + 0x10D69: 84, + 0x10D6A: 84, + 0x10D6B: 84, + 0x10D6C: 84, + 0x10D6D: 84, + 0x10EAB: 84, + 0x10EAC: 84, + 0x10EC2: 82, + 0x10EC3: 68, + 0x10EC4: 68, + 0x10EFC: 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, + 0x113BB: 84, + 0x113BC: 84, + 0x113BD: 84, + 0x113BE: 84, + 0x113BF: 84, + 0x113C0: 84, + 0x113CE: 84, + 0x113D0: 84, + 0x113D2: 84, + 0x113E1: 84, + 0x113E2: 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, + 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, + 0x11F5A: 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, + 0x1611E: 84, + 0x1611F: 84, + 0x16120: 84, + 0x16121: 84, + 0x16122: 84, + 0x16123: 84, + 0x16124: 84, + 0x16125: 84, + 0x16126: 84, + 0x16127: 84, + 0x16128: 84, + 0x16129: 84, + 0x1612D: 84, + 0x1612E: 84, + 0x1612F: 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, + 0x1E5EE: 84, + 0x1E5EF: 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, + 0x897000008E2, + 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, + 0x1C8A00001C8B, + 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, + 0xA7CD0000A7CE, + 0xA7D10000A7D2, + 0xA7D30000A7D4, + 0xA7D50000A7D6, + 0xA7D70000A7D8, + 0xA7D90000A7DA, + 0xA7DB0000A7DC, + 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, + 0x105C0000105F4, + 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, + 0x10D4000010D50, + 0x10D6900010D6E, + 0x10D6F00010D86, + 0x10E8000010EAA, + 0x10EAB00010EAD, + 0x10EB000010EB2, + 0x10EC200010EC5, + 0x10EFC00010F1D, + 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, + 0x113800001138A, + 0x1138B0001138C, + 0x1138E0001138F, + 0x11390000113B6, + 0x113B7000113C1, + 0x113C2000113C3, + 0x113C5000113C6, + 0x113C7000113CB, + 0x113CC000113D4, + 0x113E1000113E3, + 0x114000001144B, + 0x114500001145A, + 0x1145E00011462, + 0x11480000114C6, + 0x114C7000114C8, + 0x114D0000114DA, + 0x11580000115B6, + 0x115B8000115C1, + 0x115D8000115DE, + 0x1160000011641, + 0x1164400011645, + 0x116500001165A, + 0x11680000116B9, + 0x116C0000116CA, + 0x116D0000116E4, + 0x117000001171B, + 0x1171D0001172C, + 0x117300001173A, + 0x1174000011747, + 0x118000001183B, + 0x118C0000118EA, + 0x118FF00011907, + 0x119090001190A, + 0x1190C00011914, + 0x1191500011917, + 0x1191800011936, + 0x1193700011939, + 0x1193B00011944, + 0x119500001195A, + 0x119A0000119A8, + 0x119AA000119D8, + 0x119DA000119E2, + 0x119E3000119E5, + 0x11A0000011A3F, + 0x11A4700011A48, + 0x11A5000011A9A, + 0x11A9D00011A9E, + 0x11AB000011AF9, + 0x11BC000011BE1, + 0x11BF000011BFA, + 0x11C0000011C09, + 0x11C0A00011C37, + 0x11C3800011C41, + 0x11C5000011C5A, + 0x11C7200011C90, + 0x11C9200011CA8, + 0x11CA900011CB7, + 0x11D0000011D07, + 0x11D0800011D0A, + 0x11D0B00011D37, + 0x11D3A00011D3B, + 0x11D3C00011D3E, + 0x11D3F00011D48, + 0x11D5000011D5A, + 0x11D6000011D66, + 0x11D6700011D69, + 0x11D6A00011D8F, + 0x11D9000011D92, + 0x11D9300011D99, + 0x11DA000011DAA, + 0x11EE000011EF7, + 0x11F0000011F11, + 0x11F1200011F3B, + 0x11F3E00011F43, + 0x11F5000011F5B, + 0x11FB000011FB1, + 0x120000001239A, + 0x1248000012544, + 0x12F9000012FF1, + 0x1300000013430, + 0x1344000013456, + 0x13460000143FB, + 0x1440000014647, + 0x161000001613A, + 0x1680000016A39, + 0x16A4000016A5F, + 0x16A6000016A6A, + 0x16A7000016ABF, + 0x16AC000016ACA, + 0x16AD000016AEE, + 0x16AF000016AF5, + 0x16B0000016B37, + 0x16B4000016B44, + 0x16B5000016B5A, + 0x16B6300016B78, + 0x16B7D00016B90, + 0x16D4000016D6D, + 0x16D7000016D7A, + 0x16E6000016E80, + 0x16F0000016F4B, + 0x16F4F00016F88, + 0x16F8F00016FA0, + 0x16FE000016FE2, + 0x16FE300016FE5, + 0x16FF000016FF2, + 0x17000000187F8, + 0x1880000018CD6, + 0x18CFF00018D09, + 0x1AFF00001AFF4, + 0x1AFF50001AFFC, + 0x1AFFD0001AFFF, + 0x1B0000001B123, + 0x1B1320001B133, + 0x1B1500001B153, + 0x1B1550001B156, + 0x1B1640001B168, + 0x1B1700001B2FC, + 0x1BC000001BC6B, + 0x1BC700001BC7D, + 0x1BC800001BC89, + 0x1BC900001BC9A, + 0x1BC9D0001BC9F, + 0x1CCF00001CCFA, + 0x1CF000001CF2E, + 0x1CF300001CF47, + 0x1DA000001DA37, + 0x1DA3B0001DA6D, + 0x1DA750001DA76, + 0x1DA840001DA85, + 0x1DA9B0001DAA0, + 0x1DAA10001DAB0, + 0x1DF000001DF1F, + 0x1DF250001DF2B, + 0x1E0000001E007, + 0x1E0080001E019, + 0x1E01B0001E022, + 0x1E0230001E025, + 0x1E0260001E02B, + 0x1E08F0001E090, + 0x1E1000001E12D, + 0x1E1300001E13E, + 0x1E1400001E14A, + 0x1E14E0001E14F, + 0x1E2900001E2AF, + 0x1E2C00001E2FA, + 0x1E4D00001E4FA, + 0x1E5D00001E5FB, + 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..7272c8d --- /dev/null +++ b/backend/.venv/Lib/site-packages/idna/package_data.py @@ -0,0 +1 @@ +__version__ = "3.11" 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..4610b71 --- /dev/null +++ b/backend/.venv/Lib/site-packages/idna/uts46data.py @@ -0,0 +1,8841 @@ +# 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__ = "16.0.0" + + +def _seg_0() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x0, "V"), + (0x1, "V"), + (0x2, "V"), + (0x3, "V"), + (0x4, "V"), + (0x5, "V"), + (0x6, "V"), + (0x7, "V"), + (0x8, "V"), + (0x9, "V"), + (0xA, "V"), + (0xB, "V"), + (0xC, "V"), + (0xD, "V"), + (0xE, "V"), + (0xF, "V"), + (0x10, "V"), + (0x11, "V"), + (0x12, "V"), + (0x13, "V"), + (0x14, "V"), + (0x15, "V"), + (0x16, "V"), + (0x17, "V"), + (0x18, "V"), + (0x19, "V"), + (0x1A, "V"), + (0x1B, "V"), + (0x1C, "V"), + (0x1D, "V"), + (0x1E, "V"), + (0x1F, "V"), + (0x20, "V"), + (0x21, "V"), + (0x22, "V"), + (0x23, "V"), + (0x24, "V"), + (0x25, "V"), + (0x26, "V"), + (0x27, "V"), + (0x28, "V"), + (0x29, "V"), + (0x2A, "V"), + (0x2B, "V"), + (0x2C, "V"), + (0x2D, "V"), + (0x2E, "V"), + (0x2F, "V"), + (0x30, "V"), + (0x31, "V"), + (0x32, "V"), + (0x33, "V"), + (0x34, "V"), + (0x35, "V"), + (0x36, "V"), + (0x37, "V"), + (0x38, "V"), + (0x39, "V"), + (0x3A, "V"), + (0x3B, "V"), + (0x3C, "V"), + (0x3D, "V"), + (0x3E, "V"), + (0x3F, "V"), + (0x40, "V"), + (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, "V"), + (0x5C, "V"), + (0x5D, "V"), + (0x5E, "V"), + (0x5F, "V"), + (0x60, "V"), + (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, "V"), + (0x7C, "V"), + (0x7D, "V"), + (0x7E, "V"), + (0x7F, "V"), + (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, "M", " "), + (0xA1, "V"), + (0xA2, "V"), + (0xA3, "V"), + (0xA4, "V"), + (0xA5, "V"), + (0xA6, "V"), + (0xA7, "V"), + (0xA8, "M", " ̈"), + (0xA9, "V"), + (0xAA, "M", "a"), + (0xAB, "V"), + (0xAC, "V"), + (0xAD, "I"), + (0xAE, "V"), + (0xAF, "M", " ̄"), + (0xB0, "V"), + (0xB1, "V"), + (0xB2, "M", "2"), + (0xB3, "M", "3"), + (0xB4, "M", " ́"), + (0xB5, "M", "μ"), + (0xB6, "V"), + (0xB7, "V"), + (0xB8, "M", " ̧"), + (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, "M", " ̆"), + (0x2D9, "M", " ̇"), + (0x2DA, "M", " ̊"), + (0x2DB, "M", " ̨"), + (0x2DC, "M", " ̃"), + (0x2DD, "M", " ̋"), + (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, "M", " ι"), + (0x37B, "V"), + (0x37E, "M", ";"), + (0x37F, "M", "ϳ"), + (0x380, "X"), + (0x384, "M", " ́"), + (0x385, "M", " ̈́"), + (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, "M", "ӏ"), + (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"), + (0x897, "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, "M", "ⴀ"), + (0x10A1, "M", "ⴁ"), + (0x10A2, "M", "ⴂ"), + (0x10A3, "M", "ⴃ"), + (0x10A4, "M", "ⴄ"), + (0x10A5, "M", "ⴅ"), + (0x10A6, "M", "ⴆ"), + (0x10A7, "M", "ⴇ"), + (0x10A8, "M", "ⴈ"), + (0x10A9, "M", "ⴉ"), + (0x10AA, "M", "ⴊ"), + (0x10AB, "M", "ⴋ"), + (0x10AC, "M", "ⴌ"), + (0x10AD, "M", "ⴍ"), + (0x10AE, "M", "ⴎ"), + (0x10AF, "M", "ⴏ"), + (0x10B0, "M", "ⴐ"), + (0x10B1, "M", "ⴑ"), + (0x10B2, "M", "ⴒ"), + (0x10B3, "M", "ⴓ"), + (0x10B4, "M", "ⴔ"), + (0x10B5, "M", "ⴕ"), + (0x10B6, "M", "ⴖ"), + (0x10B7, "M", "ⴗ"), + (0x10B8, "M", "ⴘ"), + (0x10B9, "M", "ⴙ"), + (0x10BA, "M", "ⴚ"), + (0x10BB, "M", "ⴛ"), + (0x10BC, "M", "ⴜ"), + (0x10BD, "M", "ⴝ"), + (0x10BE, "M", "ⴞ"), + (0x10BF, "M", "ⴟ"), + (0x10C0, "M", "ⴠ"), + (0x10C1, "M", "ⴡ"), + (0x10C2, "M", "ⴢ"), + (0x10C3, "M", "ⴣ"), + (0x10C4, "M", "ⴤ"), + (0x10C5, "M", "ⴥ"), + ] + + +def _seg_14() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x10C6, "X"), + (0x10C7, "M", "ⴧ"), + (0x10C8, "X"), + (0x10CD, "M", "ⴭ"), + (0x10CE, "X"), + (0x10D0, "V"), + (0x10FC, "M", "ნ"), + (0x10FD, "V"), + (0x115F, "I"), + (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"), + (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, "I"), + (0x17B6, "V"), + (0x17DE, "X"), + (0x17E0, "V"), + (0x17EA, "X"), + (0x17F0, "V"), + (0x17FA, "X"), + (0x1800, "V"), + (0x180B, "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"), + ] + + +def _seg_15() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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"), + (0x1B4E, "V"), + (0x1BF4, "X"), + (0x1BFC, "V"), + (0x1C38, "X"), + (0x1C3B, "V"), + (0x1C4A, "X"), + (0x1C4D, "V"), + (0x1C80, "M", "в"), + (0x1C81, "M", "д"), + (0x1C82, "M", "о"), + (0x1C83, "M", "с"), + (0x1C84, "M", "т"), + (0x1C86, "M", "ъ"), + (0x1C87, "M", "ѣ"), + (0x1C88, "M", "ꙋ"), + (0x1C89, "M", "ᲊ"), + (0x1C8A, "V"), + (0x1C8B, "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"), + ] + + +def _seg_16() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "ɔ"), + (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"), + ] + + +def _seg_17() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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"), + (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"), + ] + + +def _seg_18() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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"), + (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", "ỏ"), + ] + + +def _seg_19() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "ự"), + (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", "ὕ"), + ] + + +def _seg_20() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "ἇι"), + (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, "M", " ̓"), + (0x1FBE, "M", "ι"), + (0x1FBF, "M", " ̓"), + (0x1FC0, "M", " ͂"), + (0x1FC1, "M", " ̈͂"), + (0x1FC2, "M", "ὴι"), + (0x1FC3, "M", "ηι"), + (0x1FC4, "M", "ήι"), + (0x1FC5, "X"), + (0x1FC6, "V"), + (0x1FC7, "M", "ῆι"), + (0x1FC8, "M", "ὲ"), + (0x1FC9, "M", "έ"), + (0x1FCA, "M", "ὴ"), + ] + + +def _seg_21() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1FCB, "M", "ή"), + (0x1FCC, "M", "ηι"), + (0x1FCD, "M", " ̓̀"), + (0x1FCE, "M", " ̓́"), + (0x1FCF, "M", " ̓͂"), + (0x1FD0, "V"), + (0x1FD3, "M", "ΐ"), + (0x1FD4, "X"), + (0x1FD6, "V"), + (0x1FD8, "M", "ῐ"), + (0x1FD9, "M", "ῑ"), + (0x1FDA, "M", "ὶ"), + (0x1FDB, "M", "ί"), + (0x1FDC, "X"), + (0x1FDD, "M", " ̔̀"), + (0x1FDE, "M", " ̔́"), + (0x1FDF, "M", " ̔͂"), + (0x1FE0, "V"), + (0x1FE3, "M", "ΰ"), + (0x1FE4, "V"), + (0x1FE8, "M", "ῠ"), + (0x1FE9, "M", "ῡ"), + (0x1FEA, "M", "ὺ"), + (0x1FEB, "M", "ύ"), + (0x1FEC, "M", "ῥ"), + (0x1FED, "M", " ̈̀"), + (0x1FEE, "M", " ̈́"), + (0x1FEF, "M", "`"), + (0x1FF0, "X"), + (0x1FF2, "M", "ὼι"), + (0x1FF3, "M", "ωι"), + (0x1FF4, "M", "ώι"), + (0x1FF5, "X"), + (0x1FF6, "V"), + (0x1FF7, "M", "ῶι"), + (0x1FF8, "M", "ὸ"), + (0x1FF9, "M", "ό"), + (0x1FFA, "M", "ὼ"), + (0x1FFB, "M", "ώ"), + (0x1FFC, "M", "ωι"), + (0x1FFD, "M", " ́"), + (0x1FFE, "M", " ̔"), + (0x1FFF, "X"), + (0x2000, "M", " "), + (0x200B, "I"), + (0x200C, "D", ""), + (0x200E, "X"), + (0x2010, "V"), + (0x2011, "M", "‐"), + (0x2012, "V"), + (0x2017, "M", " ̳"), + (0x2018, "V"), + (0x2024, "X"), + (0x2027, "V"), + (0x2028, "X"), + (0x202F, "M", " "), + (0x2030, "V"), + (0x2033, "M", "′′"), + (0x2034, "M", "′′′"), + (0x2035, "V"), + (0x2036, "M", "‵‵"), + (0x2037, "M", "‵‵‵"), + (0x2038, "V"), + (0x203C, "M", "!!"), + (0x203D, "V"), + (0x203E, "M", " ̅"), + (0x203F, "V"), + (0x2047, "M", "??"), + (0x2048, "M", "?!"), + (0x2049, "M", "!?"), + (0x204A, "V"), + (0x2057, "M", "′′′′"), + (0x2058, "V"), + (0x205F, "M", " "), + (0x2060, "I"), + (0x2065, "X"), + (0x206A, "I"), + (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, "M", "+"), + (0x207B, "M", "−"), + (0x207C, "M", "="), + (0x207D, "M", "("), + (0x207E, "M", ")"), + (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"), + ] + + +def _seg_22() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x2088, "M", "8"), + (0x2089, "M", "9"), + (0x208A, "M", "+"), + (0x208B, "M", "−"), + (0x208C, "M", "="), + (0x208D, "M", "("), + (0x208E, "M", ")"), + (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, "M", "a/c"), + (0x2101, "M", "a/s"), + (0x2102, "M", "c"), + (0x2103, "M", "°c"), + (0x2104, "V"), + (0x2105, "M", "c/o"), + (0x2106, "M", "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, "M", "ⅎ"), + (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"), + ] + + +def _seg_23() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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"), + (0x217D, "M", "c"), + (0x217E, "M", "d"), + (0x217F, "M", "m"), + (0x2180, "V"), + (0x2183, "M", "ↄ"), + (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"), + (0x242A, "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, "M", "(1)"), + (0x2475, "M", "(2)"), + (0x2476, "M", "(3)"), + (0x2477, "M", "(4)"), + (0x2478, "M", "(5)"), + (0x2479, "M", "(6)"), + (0x247A, "M", "(7)"), + (0x247B, "M", "(8)"), + (0x247C, "M", "(9)"), + (0x247D, "M", "(10)"), + (0x247E, "M", "(11)"), + (0x247F, "M", "(12)"), + (0x2480, "M", "(13)"), + (0x2481, "M", "(14)"), + (0x2482, "M", "(15)"), + (0x2483, "M", "(16)"), + (0x2484, "M", "(17)"), + (0x2485, "M", "(18)"), + (0x2486, "M", "(19)"), + (0x2487, "M", "(20)"), + (0x2488, "X"), + (0x249C, "M", "(a)"), + (0x249D, "M", "(b)"), + (0x249E, "M", "(c)"), + (0x249F, "M", "(d)"), + ] + + +def _seg_24() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x24A0, "M", "(e)"), + (0x24A1, "M", "(f)"), + (0x24A2, "M", "(g)"), + (0x24A3, "M", "(h)"), + (0x24A4, "M", "(i)"), + (0x24A5, "M", "(j)"), + (0x24A6, "M", "(k)"), + (0x24A7, "M", "(l)"), + (0x24A8, "M", "(m)"), + (0x24A9, "M", "(n)"), + (0x24AA, "M", "(o)"), + (0x24AB, "M", "(p)"), + (0x24AC, "M", "(q)"), + (0x24AD, "M", "(r)"), + (0x24AE, "M", "(s)"), + (0x24AF, "M", "(t)"), + (0x24B0, "M", "(u)"), + (0x24B1, "M", "(v)"), + (0x24B2, "M", "(w)"), + (0x24B3, "M", "(x)"), + (0x24B4, "M", "(y)"), + (0x24B5, "M", "(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"), + (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, "M", "::="), + (0x2A75, "M", "=="), + (0x2A76, "M", "==="), + (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", "ⰻ"), + ] + + +def _seg_25() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "ⱜ"), + (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"), + ] + + +def _seg_26() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "ⳇ"), + (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"), + ] + + +def _seg_27() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "卩"), + (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", "牛"), + ] + + +def _seg_28() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "而"), + (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", "鬲"), + ] + + +def _seg_29() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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, "M", " "), + (0x3001, "V"), + (0x3002, "M", "."), + (0x3003, "V"), + (0x3036, "M", "〒"), + (0x3037, "V"), + (0x3038, "M", "十"), + (0x3039, "M", "卄"), + (0x303A, "M", "卅"), + (0x303B, "V"), + (0x3040, "X"), + (0x3041, "V"), + (0x3097, "X"), + (0x3099, "V"), + (0x309B, "M", " ゙"), + (0x309C, "M", " ゚"), + (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, "I"), + (0x3165, "M", "ᄔ"), + (0x3166, "M", "ᄕ"), + (0x3167, "M", "ᇇ"), + ] + + +def _seg_30() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "ᆅ"), + (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"), + (0x31E6, "X"), + (0x31F0, "V"), + (0x3200, "M", "(ᄀ)"), + (0x3201, "M", "(ᄂ)"), + (0x3202, "M", "(ᄃ)"), + (0x3203, "M", "(ᄅ)"), + (0x3204, "M", "(ᄆ)"), + (0x3205, "M", "(ᄇ)"), + (0x3206, "M", "(ᄉ)"), + (0x3207, "M", "(ᄋ)"), + (0x3208, "M", "(ᄌ)"), + (0x3209, "M", "(ᄎ)"), + (0x320A, "M", "(ᄏ)"), + (0x320B, "M", "(ᄐ)"), + (0x320C, "M", "(ᄑ)"), + (0x320D, "M", "(ᄒ)"), + (0x320E, "M", "(가)"), + (0x320F, "M", "(나)"), + (0x3210, "M", "(다)"), + (0x3211, "M", "(라)"), + (0x3212, "M", "(마)"), + (0x3213, "M", "(바)"), + (0x3214, "M", "(사)"), + (0x3215, "M", "(아)"), + (0x3216, "M", "(자)"), + (0x3217, "M", "(차)"), + (0x3218, "M", "(카)"), + (0x3219, "M", "(타)"), + (0x321A, "M", "(파)"), + (0x321B, "M", "(하)"), + (0x321C, "M", "(주)"), + (0x321D, "M", "(오전)"), + (0x321E, "M", "(오후)"), + (0x321F, "X"), + (0x3220, "M", "(一)"), + (0x3221, "M", "(二)"), + (0x3222, "M", "(三)"), + (0x3223, "M", "(四)"), + (0x3224, "M", "(五)"), + (0x3225, "M", "(六)"), + (0x3226, "M", "(七)"), + (0x3227, "M", "(八)"), + (0x3228, "M", "(九)"), + (0x3229, "M", "(十)"), + ] + + +def _seg_31() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x322A, "M", "(月)"), + (0x322B, "M", "(火)"), + (0x322C, "M", "(水)"), + (0x322D, "M", "(木)"), + (0x322E, "M", "(金)"), + (0x322F, "M", "(土)"), + (0x3230, "M", "(日)"), + (0x3231, "M", "(株)"), + (0x3232, "M", "(有)"), + (0x3233, "M", "(社)"), + (0x3234, "M", "(名)"), + (0x3235, "M", "(特)"), + (0x3236, "M", "(財)"), + (0x3237, "M", "(祝)"), + (0x3238, "M", "(労)"), + (0x3239, "M", "(代)"), + (0x323A, "M", "(呼)"), + (0x323B, "M", "(学)"), + (0x323C, "M", "(監)"), + (0x323D, "M", "(企)"), + (0x323E, "M", "(資)"), + (0x323F, "M", "(協)"), + (0x3240, "M", "(祭)"), + (0x3241, "M", "(休)"), + (0x3242, "M", "(自)"), + (0x3243, "M", "(至)"), + (0x3244, "M", "問"), + (0x3245, "M", "幼"), + (0x3246, "M", "文"), + (0x3247, "M", "箏"), + (0x3248, "V"), + (0x3250, "M", "pte"), + (0x3251, "M", "21"), + (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", "名"), + ] + + +def _seg_32() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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"), + (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", "ル"), + ] + + +def _seg_33() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "グラムトン"), + (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点"), + ] + + +def _seg_34() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "大正"), + (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ω"), + ] + + +def _seg_35() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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日"), + (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", "ꙟ"), + ] + + +def _seg_36() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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"), + (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"), + ] + + +def _seg_37() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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"), + (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"), + ] + + +def _seg_38() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xA7C9, "M", "ꟊ"), + (0xA7CA, "V"), + (0xA7CB, "M", "ɤ"), + (0xA7CC, "M", "ꟍ"), + (0xA7CD, "V"), + (0xA7CE, "X"), + (0xA7D0, "M", "ꟑ"), + (0xA7D1, "V"), + (0xA7D2, "X"), + (0xA7D3, "V"), + (0xA7D4, "X"), + (0xA7D5, "V"), + (0xA7D6, "M", "ꟗ"), + (0xA7D7, "V"), + (0xA7D8, "M", "ꟙ"), + (0xA7D9, "V"), + (0xA7DA, "M", "ꟛ"), + (0xA7DB, "V"), + (0xA7DC, "M", "ƛ"), + (0xA7DD, "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"), + (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", "Ꮇ"), + ] + + +def _seg_39() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "Ꮮ"), + (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", "濫"), + ] + + +def _seg_40() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "雷"), + (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", "閭"), + ] + + +def _seg_41() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "玲"), + (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", "離"), + ] + + +def _seg_42() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "晴"), + (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", "禎"), + ] + + +def _seg_43() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "塚"), + (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", "調"), + ] + + +def _seg_44() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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"), + (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, "M", "+"), + (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", "پ"), + ] + + +def _seg_45() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "ى"), + (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", "قح"), + ] + + +def _seg_46() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "يي"), + (0xFC5B, "M", "ذٰ"), + (0xFC5C, "M", "رٰ"), + (0xFC5D, "M", "ىٰ"), + (0xFC5E, "M", " ٌّ"), + (0xFC5F, "M", " ٍّ"), + (0xFC60, "M", " َّ"), + (0xFC61, "M", " ُّ"), + (0xFC62, "M", " ِّ"), + (0xFC63, "M", " ّٰ"), + (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", "ئج"), + ] + + +def _seg_47() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "فج"), + (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", "سى"), + ] + + +def _seg_48() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "صي"), + (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", "فخم"), + ] + + +def _seg_49() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "شحي"), + (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, "M", "صلى الله عليه وسلم"), + (0xFDFB, "M", "جل جلاله"), + (0xFDFC, "M", "ریال"), + (0xFDFD, "V"), + (0xFE00, "I"), + (0xFE10, "M", ","), + (0xFE11, "M", "、"), + (0xFE12, "X"), + (0xFE13, "M", ":"), + (0xFE14, "M", ";"), + (0xFE15, "M", "!"), + (0xFE16, "M", "?"), + (0xFE17, "M", "〖"), + (0xFE18, "M", "〗"), + (0xFE19, "X"), + (0xFE20, "V"), + (0xFE30, "X"), + (0xFE31, "M", "—"), + (0xFE32, "M", "–"), + ] + + +def _seg_50() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFE33, "M", "_"), + (0xFE35, "M", "("), + (0xFE36, "M", ")"), + (0xFE37, "M", "{"), + (0xFE38, "M", "}"), + (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, "M", "["), + (0xFE48, "M", "]"), + (0xFE49, "M", " ̅"), + (0xFE4D, "M", "_"), + (0xFE50, "M", ","), + (0xFE51, "M", "、"), + (0xFE52, "X"), + (0xFE54, "M", ";"), + (0xFE55, "M", ":"), + (0xFE56, "M", "?"), + (0xFE57, "M", "!"), + (0xFE58, "M", "—"), + (0xFE59, "M", "("), + (0xFE5A, "M", ")"), + (0xFE5B, "M", "{"), + (0xFE5C, "M", "}"), + (0xFE5D, "M", "〔"), + (0xFE5E, "M", "〕"), + (0xFE5F, "M", "#"), + (0xFE60, "M", "&"), + (0xFE61, "M", "*"), + (0xFE62, "M", "+"), + (0xFE63, "M", "-"), + (0xFE64, "M", "<"), + (0xFE65, "M", ">"), + (0xFE66, "M", "="), + (0xFE67, "X"), + (0xFE68, "M", "\\"), + (0xFE69, "M", "$"), + (0xFE6A, "M", "%"), + (0xFE6B, "M", "@"), + (0xFE6C, "X"), + (0xFE70, "M", " ً"), + (0xFE71, "M", "ـً"), + (0xFE72, "M", " ٌ"), + (0xFE73, "V"), + (0xFE74, "M", " ٍ"), + (0xFE75, "X"), + (0xFE76, "M", " َ"), + (0xFE77, "M", "ـَ"), + (0xFE78, "M", " ُ"), + (0xFE79, "M", "ـُ"), + (0xFE7A, "M", " ِ"), + (0xFE7B, "M", "ـِ"), + (0xFE7C, "M", " ّ"), + (0xFE7D, "M", "ـّ"), + (0xFE7E, "M", " ْ"), + (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", "و"), + ] + + +def _seg_51() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFEEF, "M", "ى"), + (0xFEF1, "M", "ي"), + (0xFEF5, "M", "لآ"), + (0xFEF7, "M", "لأ"), + (0xFEF9, "M", "لإ"), + (0xFEFB, "M", "لا"), + (0xFEFD, "X"), + (0xFEFF, "I"), + (0xFF00, "X"), + (0xFF01, "M", "!"), + (0xFF02, "M", '"'), + (0xFF03, "M", "#"), + (0xFF04, "M", "$"), + (0xFF05, "M", "%"), + (0xFF06, "M", "&"), + (0xFF07, "M", "'"), + (0xFF08, "M", "("), + (0xFF09, "M", ")"), + (0xFF0A, "M", "*"), + (0xFF0B, "M", "+"), + (0xFF0C, "M", ","), + (0xFF0D, "M", "-"), + (0xFF0E, "M", "."), + (0xFF0F, "M", "/"), + (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, "M", ":"), + (0xFF1B, "M", ";"), + (0xFF1C, "M", "<"), + (0xFF1D, "M", "="), + (0xFF1E, "M", ">"), + (0xFF1F, "M", "?"), + (0xFF20, "M", "@"), + (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, "M", "["), + (0xFF3C, "M", "\\"), + (0xFF3D, "M", "]"), + (0xFF3E, "M", "^"), + (0xFF3F, "M", "_"), + (0xFF40, "M", "`"), + (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, "M", "{"), + ] + + +def _seg_52() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFF5C, "M", "|"), + (0xFF5D, "M", "}"), + (0xFF5E, "M", "~"), + (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", "ツ"), + (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, "I"), + (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"), + ] + + +def _seg_53() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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, "M", " ̄"), + (0xFFE4, "M", "¦"), + (0xFFE5, "M", "¥"), + (0xFFE6, "M", "₩"), + (0xFFE7, "X"), + (0xFFE8, "M", "│"), + (0xFFE9, "M", "←"), + (0xFFEA, "M", "↑"), + (0xFFEB, "M", "→"), + (0xFFEC, "M", "↓"), + (0xFFED, "M", "■"), + (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", "𐐶"), + ] + + +def _seg_54() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "𐓡"), + (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", "𐖱"), + ] + + +def _seg_55() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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"), + (0x105C0, "V"), + (0x105F4, "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", "ɗ"), + (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"), + ] + + +def _seg_56() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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"), + (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", "𐳭"), + ] + + +def _seg_57() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x10CAE, "M", "𐳮"), + (0x10CAF, "M", "𐳯"), + (0x10CB0, "M", "𐳰"), + (0x10CB1, "M", "𐳱"), + (0x10CB2, "M", "𐳲"), + (0x10CB3, "X"), + (0x10CC0, "V"), + (0x10CF3, "X"), + (0x10CFA, "V"), + (0x10D28, "X"), + (0x10D30, "V"), + (0x10D3A, "X"), + (0x10D40, "V"), + (0x10D50, "M", "𐵰"), + (0x10D51, "M", "𐵱"), + (0x10D52, "M", "𐵲"), + (0x10D53, "M", "𐵳"), + (0x10D54, "M", "𐵴"), + (0x10D55, "M", "𐵵"), + (0x10D56, "M", "𐵶"), + (0x10D57, "M", "𐵷"), + (0x10D58, "M", "𐵸"), + (0x10D59, "M", "𐵹"), + (0x10D5A, "M", "𐵺"), + (0x10D5B, "M", "𐵻"), + (0x10D5C, "M", "𐵼"), + (0x10D5D, "M", "𐵽"), + (0x10D5E, "M", "𐵾"), + (0x10D5F, "M", "𐵿"), + (0x10D60, "M", "𐶀"), + (0x10D61, "M", "𐶁"), + (0x10D62, "M", "𐶂"), + (0x10D63, "M", "𐶃"), + (0x10D64, "M", "𐶄"), + (0x10D65, "M", "𐶅"), + (0x10D66, "X"), + (0x10D69, "V"), + (0x10D86, "X"), + (0x10D8E, "V"), + (0x10D90, "X"), + (0x10E60, "V"), + (0x10E7F, "X"), + (0x10E80, "V"), + (0x10EAA, "X"), + (0x10EAB, "V"), + (0x10EAE, "X"), + (0x10EB0, "V"), + (0x10EB2, "X"), + (0x10EC2, "V"), + (0x10EC5, "X"), + (0x10EFC, "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"), + (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"), + ] + + +def _seg_58() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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"), + (0x11380, "V"), + (0x1138A, "X"), + (0x1138B, "V"), + (0x1138C, "X"), + (0x1138E, "V"), + (0x1138F, "X"), + (0x11390, "V"), + (0x113B6, "X"), + (0x113B7, "V"), + (0x113C1, "X"), + (0x113C2, "V"), + (0x113C3, "X"), + (0x113C5, "V"), + (0x113C6, "X"), + (0x113C7, "V"), + (0x113CB, "X"), + (0x113CC, "V"), + (0x113D6, "X"), + (0x113D7, "V"), + (0x113D9, "X"), + (0x113E1, "V"), + (0x113E3, "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"), + (0x116D0, "V"), + (0x116E4, "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", "𑣊"), + (0x118AB, "M", "𑣋"), + (0x118AC, "M", "𑣌"), + (0x118AD, "M", "𑣍"), + (0x118AE, "M", "𑣎"), + (0x118AF, "M", "𑣏"), + ] + + +def _seg_59() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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"), + (0x11BC0, "V"), + (0x11BE2, "X"), + (0x11BF0, "V"), + (0x11BFA, "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"), + (0x11F5B, "X"), + ] + + +def _seg_60() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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"), + (0x13460, "V"), + (0x143FB, "X"), + (0x14400, "V"), + (0x14647, "X"), + (0x16100, "V"), + (0x1613A, "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"), + (0x16D40, "V"), + (0x16D7A, "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"), + (0x18CFF, "V"), + (0x18D09, "X"), + ] + + +def _seg_61() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1AFF0, "V"), + (0x1AFF4, "X"), + (0x1AFF5, "V"), + (0x1AFFC, "X"), + (0x1AFFD, "V"), + (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"), + (0x1CC00, "V"), + (0x1CCD6, "M", "a"), + (0x1CCD7, "M", "b"), + (0x1CCD8, "M", "c"), + (0x1CCD9, "M", "d"), + (0x1CCDA, "M", "e"), + (0x1CCDB, "M", "f"), + (0x1CCDC, "M", "g"), + (0x1CCDD, "M", "h"), + (0x1CCDE, "M", "i"), + (0x1CCDF, "M", "j"), + (0x1CCE0, "M", "k"), + (0x1CCE1, "M", "l"), + (0x1CCE2, "M", "m"), + (0x1CCE3, "M", "n"), + (0x1CCE4, "M", "o"), + (0x1CCE5, "M", "p"), + (0x1CCE6, "M", "q"), + (0x1CCE7, "M", "r"), + (0x1CCE8, "M", "s"), + (0x1CCE9, "M", "t"), + (0x1CCEA, "M", "u"), + (0x1CCEB, "M", "v"), + (0x1CCEC, "M", "w"), + (0x1CCED, "M", "x"), + (0x1CCEE, "M", "y"), + (0x1CCEF, "M", "z"), + (0x1CCF0, "M", "0"), + (0x1CCF1, "M", "1"), + (0x1CCF2, "M", "2"), + (0x1CCF3, "M", "3"), + (0x1CCF4, "M", "4"), + (0x1CCF5, "M", "5"), + (0x1CCF6, "M", "6"), + (0x1CCF7, "M", "7"), + (0x1CCF8, "M", "8"), + (0x1CCF9, "M", "9"), + (0x1CCFA, "X"), + (0x1CD00, "V"), + (0x1CEB4, "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, "I"), + (0x1D17B, "V"), + (0x1D1BB, "M", "𝆹𝅥"), + (0x1D1BC, "M", "𝆺𝅥"), + (0x1D1BD, "M", "𝆹𝅥𝅮"), + (0x1D1BE, "M", "𝆺𝅥𝅮"), + (0x1D1BF, "M", "𝆹𝅥𝅯"), + (0x1D1C0, "M", "𝆺𝅥𝅯"), + (0x1D1C1, "V"), + (0x1D1EB, "X"), + (0x1D200, "V"), + (0x1D246, "X"), + ] + + +def _seg_62() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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"), + (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"), + ] + + +def _seg_63() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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"), + (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"), + ] + + +def _seg_64() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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"), + (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"), + ] + + +def _seg_65() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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"), + (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"), + ] + + +def _seg_66() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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"), + (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"), + ] + + +def _seg_67() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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"), + (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"), + ] + + +def _seg_68() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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"), + (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", "σ"), + ] + + +def _seg_69() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "η"), + (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", "ε"), + ] + + +def _seg_70() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "ω"), + (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", "χ"), + ] + + +def _seg_71() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "κ"), + (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"), + ] + + +def _seg_72() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "ж"), + (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", "ұ"), + ] + + +def _seg_73() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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"), + (0x1E5D0, "V"), + (0x1E5FB, "X"), + (0x1E5FF, "V"), + (0x1E600, "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", "𞤯"), + (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", "ش"), + ] + + +def _seg_74() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "س"), + (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", "د"), + ] + + +def _seg_75() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "ذ"), + (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, "M", "0,"), + (0x1F102, "M", "1,"), + (0x1F103, "M", "2,"), + (0x1F104, "M", "3,"), + (0x1F105, "M", "4,"), + (0x1F106, "M", "5,"), + (0x1F107, "M", "6,"), + (0x1F108, "M", "7,"), + (0x1F109, "M", "8,"), + (0x1F10A, "M", "9,"), + (0x1F10B, "V"), + (0x1F110, "M", "(a)"), + (0x1F111, "M", "(b)"), + (0x1F112, "M", "(c)"), + (0x1F113, "M", "(d)"), + (0x1F114, "M", "(e)"), + (0x1F115, "M", "(f)"), + (0x1F116, "M", "(g)"), + (0x1F117, "M", "(h)"), + (0x1F118, "M", "(i)"), + (0x1F119, "M", "(j)"), + (0x1F11A, "M", "(k)"), + (0x1F11B, "M", "(l)"), + (0x1F11C, "M", "(m)"), + (0x1F11D, "M", "(n)"), + (0x1F11E, "M", "(o)"), + (0x1F11F, "M", "(p)"), + (0x1F120, "M", "(q)"), + (0x1F121, "M", "(r)"), + (0x1F122, "M", "(s)"), + (0x1F123, "M", "(t)"), + (0x1F124, "M", "(u)"), + (0x1F125, "M", "(v)"), + ] + + +def _seg_76() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1F126, "M", "(w)"), + (0x1F127, "M", "(x)"), + (0x1F128, "M", "(y)"), + (0x1F129, "M", "(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"), + (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"), + ] + + +def _seg_77() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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"), + (0x1F8BC, "X"), + (0x1F8C0, "V"), + (0x1F8C2, "X"), + (0x1F900, "V"), + (0x1FA54, "X"), + (0x1FA60, "V"), + (0x1FA6E, "X"), + (0x1FA70, "V"), + (0x1FA7D, "X"), + (0x1FA80, "V"), + (0x1FA8A, "X"), + (0x1FA8F, "V"), + (0x1FAC7, "X"), + (0x1FACE, "V"), + (0x1FADD, "X"), + (0x1FADF, "V"), + (0x1FAEA, "X"), + (0x1FAF0, "V"), + (0x1FAF9, "X"), + (0x1FB00, "V"), + (0x1FB93, "X"), + (0x1FB94, "V"), + (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", "免"), + ] + + +def _seg_78() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "咢"), + (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, "M", "㛼"), + (0x2F869, "M", "嬈"), + (0x2F86A, "M", "嬾"), + (0x2F86C, "M", "𡧈"), + (0x2F86D, "M", "寃"), + (0x2F86E, "M", "寘"), + (0x2F86F, "M", "寧"), + (0x2F870, "M", "寳"), + (0x2F871, "M", "𡬘"), + (0x2F872, "M", "寿"), + (0x2F873, "M", "将"), + (0x2F874, "M", "当"), + (0x2F875, "M", "尢"), + (0x2F876, "M", "㞁"), + ] + + +def _seg_79() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "慎"), + (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", "杓"), + ] + + +def _seg_80() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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", "滇"), + (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, "M", "𤎫"), + (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", "𥃳"), + ] + + +def _seg_81() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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, "M", "竮"), + (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", "𦉇"), + (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", "䔫"), + ] + + +def _seg_82() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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, "M", "䗗"), + (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", "起"), + (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", "鳽"), + ] + + +def _seg_83() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (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() + + _seg_82() + + _seg_83() +) # type: Tuple[Union[Tuple[int, str], Tuple[int, str, str]], ...] diff --git a/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/AUTHORS.txt b/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/AUTHORS.txt new file mode 100644 index 0000000..8ccefbc --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/AUTHORS.txt @@ -0,0 +1,799 @@ +@Switch01 +A_Rog +Aakanksha Agrawal +Abhinav Sagar +ABHYUDAY PRATAP SINGH +abs51295 +AceGentile +Adam Chainz +Adam Tse +Adam Wentz +admin +Adolfo Ochagavía +Adrien Morison +Agus +ahayrapetyan +Ahilya +AinsworthK +Akash Srivastava +Alan Yee +Albert Tugushev +Albert-Guan +albertg +Alberto Sottile +Aleks Bunin +Ales Erjavec +Alethea Flowers +Alex Gaynor +Alex Grönholm +Alex Hedges +Alex Loosley +Alex Morega +Alex Stachowiak +Alexander Shtyrov +Alexandre Conrad +Alexey Popravka +Aleš Erjavec +Alli +Ami Fischman +Ananya Maiti +Anatoly Techtonik +Anders Kaseorg +Andre Aguiar +Andreas Lutro +Andrei Geacar +Andrew Gaul +Andrew Shymanel +Andrey Bienkowski +Andrey Bulgakov +Andrés Delfino +Andy Freeland +Andy Kluger +Ani Hayrapetyan +Aniruddha Basak +Anish Tambe +Anrs Hu +Anthony Sottile +Antoine Musso +Anton Ovchinnikov +Anton Patrushev +Anton Zelenov +Antonio Alvarado Hernandez +Antony Lee +Antti Kaihola +Anubhav Patel +Anudit Nagar +Anuj Godase +AQNOUCH Mohammed +AraHaan +arena +arenasys +Arindam Choudhury +Armin Ronacher +Arnon Yaari +Artem +Arun Babu Neelicattu +Ashley Manton +Ashwin Ramaswami +atse +Atsushi Odagiri +Avinash Karhana +Avner Cohen +Awit (Ah-Wit) Ghirmai +Baptiste Mispelon +Barney Gale +barneygale +Bartek Ogryczak +Bastian Venthur +Ben Bodenmiller +Ben Darnell +Ben Hoyt +Ben Mares +Ben Rosser +Bence Nagy +Benjamin Peterson +Benjamin VanEvery +Benoit Pierre +Berker Peksag +Bernard +Bernard Tyers +Bernardo B. Marques +Bernhard M. Wiedemann +Bertil Hatt +Bhavam Vidyarthi +Blazej Michalik +Bogdan Opanchuk +BorisZZZ +Brad Erickson +Bradley Ayers +Branch Vincent +Brandon L. Reiss +Brandt Bucher +Brannon Dorsey +Brett Randall +Brett Rosen +Brian Cristante +Brian Rosner +briantracy +BrownTruck +Bruno Oliveira +Bruno Renié +Bruno S +Bstrdsmkr +Buck Golemon +burrows +Bussonnier Matthias +bwoodsend +c22 +Caleb Martinez +Calvin Smith +Carl Meyer +Carlos Liam +Carol Willing +Carter Thayer +Cass +Chandrasekhar Atina +Charlie Marsh +Chih-Hsuan Yen +Chris Brinker +Chris Hunt +Chris Jerdonek +Chris Kuehl +Chris Markiewicz +Chris McDonough +Chris Pawley +Chris Pryer +Chris Wolfe +Christian Clauss +Christian Heimes +Christian Oudard +Christoph Reiter +Christopher Hunt +Christopher Snyder +chrysle +cjc7373 +Clark Boylan +Claudio Jolowicz +Clay McClure +Cody +Cody Soyland +Colin Watson +Collin Anderson +Connor Osborn +Cooper Lees +Cooper Ry Lees +Cory Benfield +Cory Wright +Craig Kerstiens +Cristian Sorinel +Cristina +Cristina Muñoz +ctg123 +Curtis Doty +cytolentino +Daan De Meyer +Dale +Damian +Damian Quiroga +Damian Shaw +Dan Black +Dan Savilonis +Dan Sully +Dane Hillard +daniel +Daniel Collins +Daniel Hahler +Daniel Holth +Daniel Jost +Daniel Katz +Daniel Shaulov +Daniele Esposti +Daniele Nicolodi +Daniele Procida +Daniil Konovalenko +Danny Hermes +Danny McClanahan +Darren Kavanagh +Dav Clark +Dave Abrahams +Dave Jones +David Aguilar +David Black +David Bordeynik +David Caro +David D Lowe +David Evans +David Hewitt +David Linke +David Poggi +David Poznik +David Pursehouse +David Runge +David Tucker +David Wales +Davidovich +ddelange +Deepak Sharma +Deepyaman Datta +Denise Yu +dependabot[bot] +derwolfe +Desetude +Devesh Kumar Singh +devsagul +Diego Caraballo +Diego Ramirez +DiegoCaraballo +Dimitri Merejkowsky +Dimitri Papadopoulos +Dimitri Papadopoulos Orfanos +Dirk Stolle +Dmitry Gladkov +Dmitry Volodin +Domen Kožar +Dominic Davis-Foster +Donald Stufft +Dongweiming +doron zarhi +Dos Moonen +Douglas Thor +DrFeathers +Dustin Ingram +Dustin Rodrigues +Dwayne Bailey +Ed Morley +Edgar Ramírez +Edgar Ramírez Mondragón +Ee Durbin +Efflam Lemaillet +efflamlemaillet +Eitan Adler +ekristina +elainechan +Eli Schwartz +Elisha Hollander +Ellen Marie Dash +Emil Burzo +Emil Styrke +Emmanuel Arias +Endoh Takanao +enoch +Erdinc Mutlu +Eric Cousineau +Eric Gillingham +Eric Hanchrow +Eric Hopper +Erik M. Bray +Erik Rose +Erwin Janssen +Eugene Vereshchagin +everdimension +Federico +Felipe Peter +Felix Yan +fiber-space +Filip Kokosiński +Filipe Laíns +Finn Womack +finnagin +Flavio Amurrio +Florian Briand +Florian Rathgeber +Francesco +Francesco Montesano +Fredrik Orderud +Frost Ming +Gabriel Curio +Gabriel de Perthuis +Garry Polley +gavin +gdanielson +Geoffrey Sneddon +George Song +Georgi Valkov +Georgy Pchelkin +ghost +Giftlin Rajaiah +gizmoguy1 +gkdoc +Godefroid Chapelle +Gopinath M +GOTO Hayato +gousaiyang +gpiks +Greg Roodt +Greg Ward +Guilherme Espada +Guillaume Seguin +gutsytechster +Guy Rozendorn +Guy Tuval +gzpan123 +Hanjun Kim +Hari Charan +Harsh Vardhan +harupy +Harutaka Kawamura +hauntsaninja +Henrich Hartzer +Henry Schreiner +Herbert Pfennig +Holly Stotelmyer +Honnix +Hsiaoming Yang +Hugo Lopes Tavares +Hugo van Kemenade +Hugues Bruant +Hynek Schlawack +Ian Bicking +Ian Cordasco +Ian Lee +Ian Stapleton Cordasco +Ian Wienand +Igor Kuzmitshov +Igor Sobreira +Ikko Ashimine +Ilan Schnell +Illia Volochii +Ilya Baryshev +Inada Naoki +Ionel Cristian Mărieș +Ionel Maries Cristian +Itamar Turner-Trauring +Ivan Pozdeev +J. Nick Koston +Jacob Kim +Jacob Walls +Jaime Sanz +jakirkham +Jakub Kuczys +Jakub Stasiak +Jakub Vysoky +Jakub Wilk +James Cleveland +James Curtin +James Firth +James Gerity +James Polley +Jan Pokorný +Jannis Leidel +Jarek Potiuk +jarondl +Jason Curtis +Jason R. Coombs +JasonMo +JasonMo1 +Jay Graves +Jean Abou Samra +Jean-Christophe Fillion-Robin +Jeff Barber +Jeff Dairiki +Jeff Widman +Jelmer Vernooij +jenix21 +Jeremy Fleischman +Jeremy Stanley +Jeremy Zafran +Jesse Rittner +Jiashuo Li +Jim Fisher +Jim Garrison +Jinzhe Zeng +Jiun Bae +Jivan Amara +Joe Bylund +Joe Michelini +John Paton +John Sirois +John T. Wodder II +John-Scott Atlakson +johnthagen +Jon Banafato +Jon Dufresne +Jon Parise +Jonas Nockert +Jonathan Herbert +Joonatan Partanen +Joost Molenaar +Jorge Niedbalski +Joseph Bylund +Joseph Long +Josh Bronson +Josh Cannon +Josh Hansen +Josh Schneier +Joshua +Juan Luis Cano Rodríguez +Juanjo Bazán +Judah Rand +Julian Berman +Julian Gethmann +Julien Demoor +Jussi Kukkonen +jwg4 +Jyrki Pulliainen +Kai Chen +Kai Mueller +Kamal Bin Mustafa +kasium +kaustav haldar +keanemind +Keith Maxwell +Kelsey Hightower +Kenneth Belitzky +Kenneth Reitz +Kevin Burke +Kevin Carter +Kevin Frommelt +Kevin R Patterson +Kexuan Sun +Kit Randel +Klaas van Schelven +KOLANICH +konstin +kpinc +Krishna Oza +Kumar McMillan +Kuntal Majumder +Kurt McKee +Kyle Persohn +lakshmanaram +Laszlo Kiss-Kollar +Laurent Bristiel +Laurent LAPORTE +Laurie O +Laurie Opperman +layday +Leon Sasson +Lev Givon +Lincoln de Sousa +Lipis +lorddavidiii +Loren Carvalho +Lucas Cimon +Ludovic Gasc +Luis Medel +Lukas Geiger +Lukas Juhrich +Luke Macken +Luo Jiebin +luojiebin +luz.paz +László Kiss Kollár +M00nL1ght +Marc Abramowitz +Marc Tamlyn +Marcus Smith +Mariatta +Mark Kohler +Mark McLoughlin +Mark Williams +Markus Hametner +Martey Dodoo +Martin Fischer +Martin Häcker +Martin Pavlasek +Masaki +Masklinn +Matej Stuchlik +Mathew Jennings +Mathieu Bridon +Mathieu Kniewallner +Matt Bacchi +Matt Good +Matt Maker +Matt Robenolt +Matt Wozniski +matthew +Matthew Einhorn +Matthew Feickert +Matthew Gilliard +Matthew Hughes +Matthew Iversen +Matthew Treinish +Matthew Trumbell +Matthew Willson +Matthias Bussonnier +mattip +Maurits van Rees +Max W Chase +Maxim Kurnikov +Maxime Rouyrre +mayeut +mbaluna +mdebi +memoselyk +meowmeowcat +Michael +Michael Aquilina +Michael E. Karpeles +Michael Klich +Michael Mintz +Michael Williamson +michaelpacer +Michał Górny +Mickaël Schoentgen +Miguel Araujo Perez +Mihir Singh +Mike +Mike Hendricks +Min RK +MinRK +Miro Hrončok +Monica Baluna +montefra +Monty Taylor +morotti +mrKazzila +Muha Ajjan +Nadav Wexler +Nahuel Ambrosini +Nate Coraor +Nate Prewitt +Nathan Houghton +Nathaniel J. Smith +Nehal J Wani +Neil Botelho +Nguyễn Gia Phong +Nicholas Serra +Nick Coghlan +Nick Stenning +Nick Timkovich +Nicolas Bock +Nicole Harris +Nikhil Benesch +Nikhil Ladha +Nikita Chepanov +Nikolay Korolev +Nipunn Koorapati +Nitesh Sharma +Niyas Sait +Noah +Noah Gorny +Nowell Strite +NtaleGrey +nvdv +OBITORASU +Ofek Lev +ofrinevo +Oliver Freund +Oliver Jeeves +Oliver Mannion +Oliver Tonnhofer +Olivier Girardot +Olivier Grisel +Ollie Rutherfurd +OMOTO Kenji +Omry Yadan +onlinejudge95 +Oren Held +Oscar Benjamin +Oz N Tiram +Pachwenko +Patrick Dubroy +Patrick Jenkins +Patrick Lawson +patricktokeeffe +Patrik Kopkan +Paul Ganssle +Paul Kehrer +Paul Moore +Paul Nasrat +Paul Oswald +Paul van der Linden +Paulus Schoutsen +Pavel Safronov +Pavithra Eswaramoorthy +Pawel Jasinski +Paweł Szramowski +Pekka Klärck +Peter Gessler +Peter Lisák +Peter Shen +Peter Waller +Petr Viktorin +petr-tik +Phaneendra Chiruvella +Phil Elson +Phil Freo +Phil Pennock +Phil Whelan +Philip Jägenstedt +Philip Molloy +Philippe Ombredanne +Pi Delport +Pierre-Yves Rofes +Pieter Degroote +pip +Prabakaran Kumaresshan +Prabhjyotsing Surjit Singh Sodhi +Prabhu Marappan +Pradyun Gedam +Prashant Sharma +Pratik Mallya +pre-commit-ci[bot] +Preet Thakkar +Preston Holmes +Przemek Wrzos +Pulkit Goyal +q0w +Qiangning Hong +Qiming Xu +Quentin Lee +Quentin Pradet +R. David Murray +Rafael Caricio +Ralf Schmitt +Ran Benita +Razzi Abuissa +rdb +Reece Dunham +Remi Rampin +Rene Dudfield +Riccardo Magliocchetti +Riccardo Schirone +Richard Jones +Richard Si +Ricky Ng-Adam +Rishi +rmorotti +RobberPhex +Robert Collins +Robert McGibbon +Robert Pollak +Robert T. McGibbon +robin elisha robinson +Roey Berman +Rohan Jain +Roman Bogorodskiy +Roman Donchenko +Romuald Brunet +ronaudinho +Ronny Pfannschmidt +Rory McCann +Ross Brattain +Roy Wellington Ⅳ +Ruairidh MacLeod +Russell Keith-Magee +Ryan Shepherd +Ryan Wooden +ryneeverett +S. Guliaev +Sachi King +Salvatore Rinchiera +sandeepkiran-js +Sander Van Balen +Savio Jomton +schlamar +Scott Kitterman +Sean +seanj +Sebastian Jordan +Sebastian Schaetz +Segev Finer +SeongSoo Cho +Sergey Vasilyev +Seth Michael Larson +Seth Woodworth +Shahar Epstein +Shantanu +shenxianpeng +shireenrao +Shivansh-007 +Shixian Sheng +Shlomi Fish +Shovan Maity +Simeon Visser +Simon Cross +Simon Pichugin +sinoroc +sinscary +snook92 +socketubs +Sorin Sbarnea +Srinivas Nyayapati +Srishti Hegde +Stavros Korokithakis +Stefan Scherfke +Stefano Rivera +Stephan Erb +Stephen Rosen +stepshal +Steve (Gadget) Barnes +Steve Barnes +Steve Dower +Steve Kowalik +Steven Myint +Steven Silvester +stonebig +studioj +Stéphane Bidoul +Stéphane Bidoul (ACSONE) +Stéphane Klein +Sumana Harihareswara +Surbhi Sharma +Sviatoslav Sydorenko +Sviatoslav Sydorenko (Святослав Сидоренко) +Swat009 +Sylvain +Takayuki SHIMIZUKAWA +Taneli Hukkinen +tbeswick +Thiago +Thijs Triemstra +Thomas Fenzl +Thomas Grainger +Thomas Guettler +Thomas Johansson +Thomas Kluyver +Thomas Smith +Thomas VINCENT +Tim D. Smith +Tim Gates +Tim Harder +Tim Heap +tim smith +tinruufu +Tobias Hermann +Tom Forbes +Tom Freudenheim +Tom V +Tomas Hrnciar +Tomas Orsava +Tomer Chachamu +Tommi Enenkel | AnB +Tomáš Hrnčiar +Tony Beswick +Tony Narlock +Tony Zhaocheng Tan +TonyBeswick +toonarmycaptain +Toshio Kuratomi +toxinu +Travis Swicegood +Tushar Sadhwani +Tzu-ping Chung +Valentin Haenel +Victor Stinner +victorvpaulo +Vikram - Google +Viktor Szépe +Ville Skyttä +Vinay Sajip +Vincent Philippon +Vinicyus Macedo +Vipul Kumar +Vitaly Babiy +Vladimir Fokow +Vladimir Rutsky +W. Trevor King +Wil Tan +Wilfred Hughes +William Edwards +William ML Leslie +William T Olson +William Woodruff +Wilson Mo +wim glenn +Winson Luk +Wolfgang Maier +Wu Zhenyu +XAMES3 +Xavier Fernandez +Xianpeng Shen +xoviat +xtreak +YAMAMOTO Takashi +Yen Chi Hsuan +Yeray Diaz Diaz +Yoval P +Yu Jian +Yuan Jing Vincent Yan +Yusuke Hayashi +Zearin +Zhiping Deng +ziebam +Zvezdan Petkovic +Łukasz Langa +Роман Донченко +Семён Марьясин diff --git a/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/INSTALLER b/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/LICENSE.txt b/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/LICENSE.txt new file mode 100644 index 0000000..8e7b65e --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008-present The pip developers (see AUTHORS.txt file) + +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/pip-24.3.1.dist-info/METADATA b/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/METADATA new file mode 100644 index 0000000..9e5aa3a --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/METADATA @@ -0,0 +1,90 @@ +Metadata-Version: 2.1 +Name: pip +Version: 24.3.1 +Summary: The PyPA recommended tool for installing Python packages. +Author-email: The pip developers +License: MIT +Project-URL: Homepage, https://pip.pypa.io/ +Project-URL: Documentation, https://pip.pypa.io +Project-URL: Source, https://github.com/pypa/pip +Project-URL: Changelog, https://pip.pypa.io/en/stable/news/ +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Topic :: Software Development :: Build Tools +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +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 +Requires-Python: >=3.8 +Description-Content-Type: text/x-rst +License-File: LICENSE.txt +License-File: AUTHORS.txt + +pip - The Python Package Installer +================================== + +.. |pypi-version| image:: https://img.shields.io/pypi/v/pip.svg + :target: https://pypi.org/project/pip/ + :alt: PyPI + +.. |python-versions| image:: https://img.shields.io/pypi/pyversions/pip + :target: https://pypi.org/project/pip + :alt: PyPI - Python Version + +.. |docs-badge| image:: https://readthedocs.org/projects/pip/badge/?version=latest + :target: https://pip.pypa.io/en/latest + :alt: Documentation + +|pypi-version| |python-versions| |docs-badge| + +pip is the `package installer`_ for Python. You can use pip to install packages from the `Python Package Index`_ and other indexes. + +Please take a look at our documentation for how to install and use pip: + +* `Installation`_ +* `Usage`_ + +We release updates regularly, with a new version every 3 months. Find more details in our documentation: + +* `Release notes`_ +* `Release process`_ + +If you find bugs, need help, or want to talk to the developers, please use our mailing lists or chat rooms: + +* `Issue tracking`_ +* `Discourse channel`_ +* `User IRC`_ + +If you want to get involved head over to GitHub to get the source code, look at our development documentation and feel free to jump on the developer mailing lists and chat rooms: + +* `GitHub page`_ +* `Development documentation`_ +* `Development IRC`_ + +Code of Conduct +--------------- + +Everyone interacting in the pip project's codebases, issue trackers, chat +rooms, and mailing lists is expected to follow the `PSF Code of Conduct`_. + +.. _package installer: https://packaging.python.org/guides/tool-recommendations/ +.. _Python Package Index: https://pypi.org +.. _Installation: https://pip.pypa.io/en/stable/installation/ +.. _Usage: https://pip.pypa.io/en/stable/ +.. _Release notes: https://pip.pypa.io/en/stable/news.html +.. _Release process: https://pip.pypa.io/en/latest/development/release-process/ +.. _GitHub page: https://github.com/pypa/pip +.. _Development documentation: https://pip.pypa.io/en/latest/development +.. _Issue tracking: https://github.com/pypa/pip/issues +.. _Discourse channel: https://discuss.python.org/c/packaging +.. _User IRC: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa +.. _Development IRC: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa-dev +.. _PSF Code of Conduct: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md diff --git a/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/RECORD b/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/RECORD new file mode 100644 index 0000000..d0d1da7 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/RECORD @@ -0,0 +1,853 @@ +../../Scripts/pip.exe,sha256=Z_qgSuohPGAXtnVEwfy_OyT59SBh4ifL2UnmvHJQexA,108423 +../../Scripts/pip3.12.exe,sha256=Z_qgSuohPGAXtnVEwfy_OyT59SBh4ifL2UnmvHJQexA,108423 +../../Scripts/pip3.exe,sha256=Z_qgSuohPGAXtnVEwfy_OyT59SBh4ifL2UnmvHJQexA,108423 +pip-24.3.1.dist-info/AUTHORS.txt,sha256=Cbb630k8EL9FkBzX9Vpi6hpYWrLSlh08eXodL5u0eLI,10925 +pip-24.3.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pip-24.3.1.dist-info/LICENSE.txt,sha256=Y0MApmnUmurmWxLGxIySTFGkzfPR_whtw0VtyLyqIQQ,1093 +pip-24.3.1.dist-info/METADATA,sha256=V8iCNK1GYbC82PWsLMsASDh9AO4veocRlM4Pn9q2KFI,3677 +pip-24.3.1.dist-info/RECORD,, +pip-24.3.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip-24.3.1.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91 +pip-24.3.1.dist-info/entry_points.txt,sha256=eeIjuzfnfR2PrhbjnbzFU6MnSS70kZLxwaHHq6M-bD0,87 +pip-24.3.1.dist-info/top_level.txt,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pip/__init__.py,sha256=faXY_neeYrA_88plEhkyhwAaYeds7wu5U1iGwP24J0s,357 +pip/__main__.py,sha256=WzbhHXTbSE6gBY19mNN9m4s5o_365LOvTYSgqgbdBhE,854 +pip/__pip-runner__.py,sha256=cPPWuJ6NK_k-GzfvlejLFgwzmYUROmpAR6QC3Q-vkXQ,1450 +pip/__pycache__/__init__.cpython-312.pyc,, +pip/__pycache__/__main__.cpython-312.pyc,, +pip/__pycache__/__pip-runner__.cpython-312.pyc,, +pip/_internal/__init__.py,sha256=MfcoOluDZ8QMCFYal04IqOJ9q6m2V7a0aOsnI-WOxUo,513 +pip/_internal/__pycache__/__init__.cpython-312.pyc,, +pip/_internal/__pycache__/build_env.cpython-312.pyc,, +pip/_internal/__pycache__/cache.cpython-312.pyc,, +pip/_internal/__pycache__/configuration.cpython-312.pyc,, +pip/_internal/__pycache__/exceptions.cpython-312.pyc,, +pip/_internal/__pycache__/main.cpython-312.pyc,, +pip/_internal/__pycache__/pyproject.cpython-312.pyc,, +pip/_internal/__pycache__/self_outdated_check.cpython-312.pyc,, +pip/_internal/__pycache__/wheel_builder.cpython-312.pyc,, +pip/_internal/build_env.py,sha256=wsTPOWyPTKvUREUcO585OU01kbQufpdigY8fVHv3WIw,10584 +pip/_internal/cache.py,sha256=Jb698p5PNigRtpW5o26wQNkkUv4MnQ94mc471wL63A0,10369 +pip/_internal/cli/__init__.py,sha256=FkHBgpxxb-_gd6r1FjnNhfMOzAUYyXoXKJ6abijfcFU,132 +pip/_internal/cli/__pycache__/__init__.cpython-312.pyc,, +pip/_internal/cli/__pycache__/autocompletion.cpython-312.pyc,, +pip/_internal/cli/__pycache__/base_command.cpython-312.pyc,, +pip/_internal/cli/__pycache__/cmdoptions.cpython-312.pyc,, +pip/_internal/cli/__pycache__/command_context.cpython-312.pyc,, +pip/_internal/cli/__pycache__/index_command.cpython-312.pyc,, +pip/_internal/cli/__pycache__/main.cpython-312.pyc,, +pip/_internal/cli/__pycache__/main_parser.cpython-312.pyc,, +pip/_internal/cli/__pycache__/parser.cpython-312.pyc,, +pip/_internal/cli/__pycache__/progress_bars.cpython-312.pyc,, +pip/_internal/cli/__pycache__/req_command.cpython-312.pyc,, +pip/_internal/cli/__pycache__/spinners.cpython-312.pyc,, +pip/_internal/cli/__pycache__/status_codes.cpython-312.pyc,, +pip/_internal/cli/autocompletion.py,sha256=Lli3Mr6aDNu7ZkJJFFvwD2-hFxNI6Avz8OwMyS5TVrs,6865 +pip/_internal/cli/base_command.py,sha256=F8nUcSM-Y-MQljJUe724-yxmc5viFXHyM_zH70NmIh4,8289 +pip/_internal/cli/cmdoptions.py,sha256=mDqBr0d0hoztbRJs-PWtcKpqNAc7khU6ZpoesZKocT8,30110 +pip/_internal/cli/command_context.py,sha256=RHgIPwtObh5KhMrd3YZTkl8zbVG-6Okml7YbFX4Ehg0,774 +pip/_internal/cli/index_command.py,sha256=-0oPTruZGkLSMrWDleZ6UtcKP3G-SImRRuhH0RfVE3o,5631 +pip/_internal/cli/main.py,sha256=BDZef-bWe9g9Jpr4OVs4dDf-845HJsKw835T7AqEnAc,2817 +pip/_internal/cli/main_parser.py,sha256=laDpsuBDl6kyfywp9eMMA9s84jfH2TJJn-vmL0GG90w,4338 +pip/_internal/cli/parser.py,sha256=VCMtduzECUV87KaHNu-xJ-wLNL82yT3x16V4XBxOAqI,10825 +pip/_internal/cli/progress_bars.py,sha256=VgydyqjZvfhqpuNcFDn00QNuA9GxRe9CKrRG8jhPuKU,2723 +pip/_internal/cli/req_command.py,sha256=DqeFhmUMs6o6Ev8qawAcOoYNdAZsfyKS0MZI5jsJYwQ,12250 +pip/_internal/cli/spinners.py,sha256=hIJ83GerdFgFCdobIA23Jggetegl_uC4Sp586nzFbPE,5118 +pip/_internal/cli/status_codes.py,sha256=sEFHUaUJbqv8iArL3HAtcztWZmGOFX01hTesSytDEh0,116 +pip/_internal/commands/__init__.py,sha256=5oRO9O3dM2vGuh0bFw4HOVletryrz5HHMmmPWwJrH9U,3882 +pip/_internal/commands/__pycache__/__init__.cpython-312.pyc,, +pip/_internal/commands/__pycache__/cache.cpython-312.pyc,, +pip/_internal/commands/__pycache__/check.cpython-312.pyc,, +pip/_internal/commands/__pycache__/completion.cpython-312.pyc,, +pip/_internal/commands/__pycache__/configuration.cpython-312.pyc,, +pip/_internal/commands/__pycache__/debug.cpython-312.pyc,, +pip/_internal/commands/__pycache__/download.cpython-312.pyc,, +pip/_internal/commands/__pycache__/freeze.cpython-312.pyc,, +pip/_internal/commands/__pycache__/hash.cpython-312.pyc,, +pip/_internal/commands/__pycache__/help.cpython-312.pyc,, +pip/_internal/commands/__pycache__/index.cpython-312.pyc,, +pip/_internal/commands/__pycache__/inspect.cpython-312.pyc,, +pip/_internal/commands/__pycache__/install.cpython-312.pyc,, +pip/_internal/commands/__pycache__/list.cpython-312.pyc,, +pip/_internal/commands/__pycache__/search.cpython-312.pyc,, +pip/_internal/commands/__pycache__/show.cpython-312.pyc,, +pip/_internal/commands/__pycache__/uninstall.cpython-312.pyc,, +pip/_internal/commands/__pycache__/wheel.cpython-312.pyc,, +pip/_internal/commands/cache.py,sha256=xg76_ZFEBC6zoQ3gXLRfMZJft4z2a0RwH4GEFZC6nnU,7944 +pip/_internal/commands/check.py,sha256=Hr_4eiMd9cgVDgEvjtIdw915NmL7ROIWW8enkr8slPQ,2268 +pip/_internal/commands/completion.py,sha256=HT4lD0bgsflHq2IDgYfiEdp7IGGtE7s6MgI3xn0VQEw,4287 +pip/_internal/commands/configuration.py,sha256=n98enwp6y0b5G6fiRQjaZo43FlJKYve_daMhN-4BRNc,9766 +pip/_internal/commands/debug.py,sha256=DNDRgE9YsKrbYzU0s3VKi8rHtKF4X13CJ_br_8PUXO0,6797 +pip/_internal/commands/download.py,sha256=0qB0nys6ZEPsog451lDsjL5Bx7Z97t-B80oFZKhpzKM,5273 +pip/_internal/commands/freeze.py,sha256=2Vt72BYTSm9rzue6d8dNzt8idxWK4Db6Hd-anq7GQ80,3203 +pip/_internal/commands/hash.py,sha256=EVVOuvGtoPEdFi8SNnmdqlCQrhCxV-kJsdwtdcCnXGQ,1703 +pip/_internal/commands/help.py,sha256=gcc6QDkcgHMOuAn5UxaZwAStsRBrnGSn_yxjS57JIoM,1132 +pip/_internal/commands/index.py,sha256=RAXxmJwFhVb5S1BYzb5ifX3sn9Na8v2CCVYwSMP8pao,4731 +pip/_internal/commands/inspect.py,sha256=PGrY9TRTRCM3y5Ml8Bdk8DEOXquWRfscr4DRo1LOTPc,3189 +pip/_internal/commands/install.py,sha256=iqesiLIZc6Op9uihMQFYRhAA2DQRZUxbM4z1BwXoFls,29428 +pip/_internal/commands/list.py,sha256=oiIzSjLP6__d7dIS3q0Xb5ywsaOThBWRqMyjjKzkPdM,12769 +pip/_internal/commands/search.py,sha256=fWkUQVx_gm8ebbFAlCgqtxKXT9rNahpJ-BI__3HNZpg,5626 +pip/_internal/commands/show.py,sha256=IG9L5uo8w6UA4tI_IlmaxLCoNKPa5JNJCljj3NWs0OE,7507 +pip/_internal/commands/uninstall.py,sha256=7pOR7enK76gimyxQbzxcG1OsyLXL3DvX939xmM8Fvtg,3892 +pip/_internal/commands/wheel.py,sha256=eJRhr_qoNNxWAkkdJCNiQM7CXd4E1_YyQhsqJnBPGGg,6414 +pip/_internal/configuration.py,sha256=XkAiBS0hpzsM-LF0Qu5hvPWO_Bs67-oQKRYFBuMbESs,14006 +pip/_internal/distributions/__init__.py,sha256=Hq6kt6gXBgjNit5hTTWLAzeCNOKoB-N0pGYSqehrli8,858 +pip/_internal/distributions/__pycache__/__init__.cpython-312.pyc,, +pip/_internal/distributions/__pycache__/base.cpython-312.pyc,, +pip/_internal/distributions/__pycache__/installed.cpython-312.pyc,, +pip/_internal/distributions/__pycache__/sdist.cpython-312.pyc,, +pip/_internal/distributions/__pycache__/wheel.cpython-312.pyc,, +pip/_internal/distributions/base.py,sha256=QeB9qvKXDIjLdPBDE5fMgpfGqMMCr-govnuoQnGuiF8,1783 +pip/_internal/distributions/installed.py,sha256=QinHFbWAQ8oE0pbD8MFZWkwlnfU1QYTccA1vnhrlYOU,842 +pip/_internal/distributions/sdist.py,sha256=PlcP4a6-R6c98XnOM-b6Lkb3rsvh9iG4ok8shaanrzs,6751 +pip/_internal/distributions/wheel.py,sha256=THBYfnv7VVt8mYhMYUtH13S1E7FDwtDyDfmUcl8ai0E,1317 +pip/_internal/exceptions.py,sha256=2_byISIv3kSnI_9T-Esfxrt0LnTRgcUHyxu0twsHjQY,26481 +pip/_internal/index/__init__.py,sha256=vpt-JeTZefh8a-FC22ZeBSXFVbuBcXSGiILhQZJaNpQ,30 +pip/_internal/index/__pycache__/__init__.cpython-312.pyc,, +pip/_internal/index/__pycache__/collector.cpython-312.pyc,, +pip/_internal/index/__pycache__/package_finder.cpython-312.pyc,, +pip/_internal/index/__pycache__/sources.cpython-312.pyc,, +pip/_internal/index/collector.py,sha256=RdPO0JLAlmyBWPAWYHPyRoGjz3GNAeTngCNkbGey_mE,16265 +pip/_internal/index/package_finder.py,sha256=yRC4xsyudwKnNoU6IXvNoyqYo5ScT7lB6Wa-z2eh7cs,37666 +pip/_internal/index/sources.py,sha256=lPBLK5Xiy8Q6IQMio26Wl7ocfZOKkgGklIBNyUJ23fI,8632 +pip/_internal/locations/__init__.py,sha256=UaAxeZ_f93FyouuFf4p7SXYF-4WstXuEvd3LbmPCAno,14925 +pip/_internal/locations/__pycache__/__init__.cpython-312.pyc,, +pip/_internal/locations/__pycache__/_distutils.cpython-312.pyc,, +pip/_internal/locations/__pycache__/_sysconfig.cpython-312.pyc,, +pip/_internal/locations/__pycache__/base.cpython-312.pyc,, +pip/_internal/locations/_distutils.py,sha256=x6nyVLj7X11Y4khIdf-mFlxMl2FWadtVEgeb8upc_WI,6013 +pip/_internal/locations/_sysconfig.py,sha256=IGzds60qsFneRogC-oeBaY7bEh3lPt_v47kMJChQXsU,7724 +pip/_internal/locations/base.py,sha256=RQiPi1d4FVM2Bxk04dQhXZ2PqkeljEL2fZZ9SYqIQ78,2556 +pip/_internal/main.py,sha256=r-UnUe8HLo5XFJz8inTcOOTiu_sxNhgHb6VwlGUllOI,340 +pip/_internal/metadata/__init__.py,sha256=9pU3W3s-6HtjFuYhWcLTYVmSaziklPv7k2x8p7X1GmA,4339 +pip/_internal/metadata/__pycache__/__init__.cpython-312.pyc,, +pip/_internal/metadata/__pycache__/_json.cpython-312.pyc,, +pip/_internal/metadata/__pycache__/base.cpython-312.pyc,, +pip/_internal/metadata/__pycache__/pkg_resources.cpython-312.pyc,, +pip/_internal/metadata/_json.py,sha256=P0cAJrH_mtmMZvlZ16ZXm_-izA4lpr5wy08laICuiaA,2644 +pip/_internal/metadata/base.py,sha256=ft0K5XNgI4ETqZnRv2-CtvgYiMOMAeGMAzxT-f6VLJA,25298 +pip/_internal/metadata/importlib/__init__.py,sha256=jUUidoxnHcfITHHaAWG1G2i5fdBYklv_uJcjo2x7VYE,135 +pip/_internal/metadata/importlib/__pycache__/__init__.cpython-312.pyc,, +pip/_internal/metadata/importlib/__pycache__/_compat.cpython-312.pyc,, +pip/_internal/metadata/importlib/__pycache__/_dists.cpython-312.pyc,, +pip/_internal/metadata/importlib/__pycache__/_envs.cpython-312.pyc,, +pip/_internal/metadata/importlib/_compat.py,sha256=c6av8sP8BBjAZuFSJow1iWfygUXNM3xRTCn5nqw6B9M,2796 +pip/_internal/metadata/importlib/_dists.py,sha256=anh0mLI-FYRPUhAdipd0Va3YJJc6HelCKQ0bFhY10a0,8017 +pip/_internal/metadata/importlib/_envs.py,sha256=UUB980XSrDWrMpQ1_G45i0r8Hqlg_tg3IPQ63mEqbNc,7431 +pip/_internal/metadata/pkg_resources.py,sha256=U07ETAINSGeSRBfWUG93E4tZZbaW_f7PGzEqZN0hulc,10542 +pip/_internal/models/__init__.py,sha256=3DHUd_qxpPozfzouoqa9g9ts1Czr5qaHfFxbnxriepM,63 +pip/_internal/models/__pycache__/__init__.cpython-312.pyc,, +pip/_internal/models/__pycache__/candidate.cpython-312.pyc,, +pip/_internal/models/__pycache__/direct_url.cpython-312.pyc,, +pip/_internal/models/__pycache__/format_control.cpython-312.pyc,, +pip/_internal/models/__pycache__/index.cpython-312.pyc,, +pip/_internal/models/__pycache__/installation_report.cpython-312.pyc,, +pip/_internal/models/__pycache__/link.cpython-312.pyc,, +pip/_internal/models/__pycache__/scheme.cpython-312.pyc,, +pip/_internal/models/__pycache__/search_scope.cpython-312.pyc,, +pip/_internal/models/__pycache__/selection_prefs.cpython-312.pyc,, +pip/_internal/models/__pycache__/target_python.cpython-312.pyc,, +pip/_internal/models/__pycache__/wheel.cpython-312.pyc,, +pip/_internal/models/candidate.py,sha256=zzgFRuw_kWPjKpGw7LC0ZUMD2CQ2EberUIYs8izjdCA,753 +pip/_internal/models/direct_url.py,sha256=uBtY2HHd3TO9cKQJWh0ThvE5FRr-MWRYChRU4IG9HZE,6578 +pip/_internal/models/format_control.py,sha256=wtsQqSK9HaUiNxQEuB-C62eVimw6G4_VQFxV9-_KDBE,2486 +pip/_internal/models/index.py,sha256=tYnL8oxGi4aSNWur0mG8DAP7rC6yuha_MwJO8xw0crI,1030 +pip/_internal/models/installation_report.py,sha256=zRVZoaz-2vsrezj_H3hLOhMZCK9c7TbzWgC-jOalD00,2818 +pip/_internal/models/link.py,sha256=jHax9O-9zlSzEwjBCDkx0OXjKXwBDwOuPwn-PsR8dCs,21034 +pip/_internal/models/scheme.py,sha256=PakmHJM3e8OOWSZFtfz1Az7f1meONJnkGuQxFlt3wBE,575 +pip/_internal/models/search_scope.py,sha256=67NEnsYY84784S-MM7ekQuo9KXLH-7MzFntXjapvAo0,4531 +pip/_internal/models/selection_prefs.py,sha256=qaFfDs3ciqoXPg6xx45N1jPLqccLJw4N0s4P0PyHTQ8,2015 +pip/_internal/models/target_python.py,sha256=2XaH2rZ5ZF-K5wcJbEMGEl7SqrTToDDNkrtQ2v_v_-Q,4271 +pip/_internal/models/wheel.py,sha256=G7dND_s4ebPkEL7RJ1qCY0QhUUWIIK6AnjWgRATF5no,4539 +pip/_internal/network/__init__.py,sha256=jf6Tt5nV_7zkARBrKojIXItgejvoegVJVKUbhAa5Ioc,50 +pip/_internal/network/__pycache__/__init__.cpython-312.pyc,, +pip/_internal/network/__pycache__/auth.cpython-312.pyc,, +pip/_internal/network/__pycache__/cache.cpython-312.pyc,, +pip/_internal/network/__pycache__/download.cpython-312.pyc,, +pip/_internal/network/__pycache__/lazy_wheel.cpython-312.pyc,, +pip/_internal/network/__pycache__/session.cpython-312.pyc,, +pip/_internal/network/__pycache__/utils.cpython-312.pyc,, +pip/_internal/network/__pycache__/xmlrpc.cpython-312.pyc,, +pip/_internal/network/auth.py,sha256=D4gASjUrqoDFlSt6gQ767KAAjv6PUyJU0puDlhXNVRE,20809 +pip/_internal/network/cache.py,sha256=48A971qCzKNFvkb57uGEk7-0xaqPS0HWj2711QNTxkU,3935 +pip/_internal/network/download.py,sha256=FLOP29dPYECBiAi7eEjvAbNkyzaKNqbyjOT2m8HPW8U,6048 +pip/_internal/network/lazy_wheel.py,sha256=PBdoMoNQQIA84Fhgne38jWF52W4x_KtsHjxgv4dkRKA,7622 +pip/_internal/network/session.py,sha256=XmanBKjVwPFmh1iJ58q6TDh9xabH37gREuQJ_feuZGA,18741 +pip/_internal/network/utils.py,sha256=Inaxel-NxBu4PQWkjyErdnfewsFCcgHph7dzR1-FboY,4088 +pip/_internal/network/xmlrpc.py,sha256=sAxzOacJ-N1NXGPvap9jC3zuYWSnnv3GXtgR2-E2APA,1838 +pip/_internal/operations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/operations/__pycache__/__init__.cpython-312.pyc,, +pip/_internal/operations/__pycache__/check.cpython-312.pyc,, +pip/_internal/operations/__pycache__/freeze.cpython-312.pyc,, +pip/_internal/operations/__pycache__/prepare.cpython-312.pyc,, +pip/_internal/operations/build/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/operations/build/__pycache__/__init__.cpython-312.pyc,, +pip/_internal/operations/build/__pycache__/build_tracker.cpython-312.pyc,, +pip/_internal/operations/build/__pycache__/metadata.cpython-312.pyc,, +pip/_internal/operations/build/__pycache__/metadata_editable.cpython-312.pyc,, +pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-312.pyc,, +pip/_internal/operations/build/__pycache__/wheel.cpython-312.pyc,, +pip/_internal/operations/build/__pycache__/wheel_editable.cpython-312.pyc,, +pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-312.pyc,, +pip/_internal/operations/build/build_tracker.py,sha256=-ARW_TcjHCOX7D2NUOGntB4Fgc6b4aolsXkAK6BWL7w,4774 +pip/_internal/operations/build/metadata.py,sha256=9S0CUD8U3QqZeXp-Zyt8HxwU90lE4QrnYDgrqZDzBnc,1422 +pip/_internal/operations/build/metadata_editable.py,sha256=VLL7LvntKE8qxdhUdEJhcotFzUsOSI8NNS043xULKew,1474 +pip/_internal/operations/build/metadata_legacy.py,sha256=8i6i1QZX9m_lKPStEFsHKM0MT4a-CD408JOw99daLmo,2190 +pip/_internal/operations/build/wheel.py,sha256=sT12FBLAxDC6wyrDorh8kvcZ1jG5qInCRWzzP-UkJiQ,1075 +pip/_internal/operations/build/wheel_editable.py,sha256=yOtoH6zpAkoKYEUtr8FhzrYnkNHQaQBjWQ2HYae1MQg,1417 +pip/_internal/operations/build/wheel_legacy.py,sha256=K-6kNhmj-1xDF45ny1yheMerF0ui4EoQCLzEoHh6-tc,3045 +pip/_internal/operations/check.py,sha256=L24vRL8VWbyywdoeAhM89WCd8zLTnjIbULlKelUgIec,5912 +pip/_internal/operations/freeze.py,sha256=V59yEyCSz_YhZuhH09-6aV_zvYBMrS_IxFFNqn2QzlA,9864 +pip/_internal/operations/install/__init__.py,sha256=mX7hyD2GNBO2mFGokDQ30r_GXv7Y_PLdtxcUv144e-s,51 +pip/_internal/operations/install/__pycache__/__init__.cpython-312.pyc,, +pip/_internal/operations/install/__pycache__/editable_legacy.cpython-312.pyc,, +pip/_internal/operations/install/__pycache__/wheel.cpython-312.pyc,, +pip/_internal/operations/install/editable_legacy.py,sha256=PoEsNEPGbIZ2yQphPsmYTKLOCMs4gv5OcCdzW124NcA,1283 +pip/_internal/operations/install/wheel.py,sha256=X5Iz9yUg5LlK5VNQ9g2ikc6dcRu8EPi_SUi5iuEDRgo,27615 +pip/_internal/operations/prepare.py,sha256=joWJwPkuqGscQgVNImLK71e9hRapwKvRCM8HclysmvU,28118 +pip/_internal/pyproject.py,sha256=rw4fwlptDp1hZgYoplwbAGwWA32sWQkp7ysf8Ju6iXc,7287 +pip/_internal/req/__init__.py,sha256=HxBFtZy_BbCclLgr26waMtpzYdO5T3vxePvpGAXSt5s,2653 +pip/_internal/req/__pycache__/__init__.cpython-312.pyc,, +pip/_internal/req/__pycache__/constructors.cpython-312.pyc,, +pip/_internal/req/__pycache__/req_file.cpython-312.pyc,, +pip/_internal/req/__pycache__/req_install.cpython-312.pyc,, +pip/_internal/req/__pycache__/req_set.cpython-312.pyc,, +pip/_internal/req/__pycache__/req_uninstall.cpython-312.pyc,, +pip/_internal/req/constructors.py,sha256=v1qzCN1mIldwx-nCrPc8JO4lxkm3Fv8M5RWvt8LISjc,18430 +pip/_internal/req/req_file.py,sha256=gOOJTzL-mDRPcQhjwqjDrjn4V-3rK9TnEFnU3v8RA4Q,18752 +pip/_internal/req/req_install.py,sha256=yhT98NGDoAEk03jznTJnYCznzhiMEEA2ocgsUG_dcNU,35788 +pip/_internal/req/req_set.py,sha256=j3esG0s6SzoVReX9rWn4rpYNtyET_fwxbwJPRimvRxo,2858 +pip/_internal/req/req_uninstall.py,sha256=qzDIxJo-OETWqGais7tSMCDcWbATYABT-Tid3ityF0s,23853 +pip/_internal/resolution/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/resolution/__pycache__/__init__.cpython-312.pyc,, +pip/_internal/resolution/__pycache__/base.cpython-312.pyc,, +pip/_internal/resolution/base.py,sha256=qlmh325SBVfvG6Me9gc5Nsh5sdwHBwzHBq6aEXtKsLA,583 +pip/_internal/resolution/legacy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/resolution/legacy/__pycache__/__init__.cpython-312.pyc,, +pip/_internal/resolution/legacy/__pycache__/resolver.cpython-312.pyc,, +pip/_internal/resolution/legacy/resolver.py,sha256=3HZiJBRd1FTN6jQpI4qRO8-TbLYeIbUTS6PFvXnXs2w,24068 +pip/_internal/resolution/resolvelib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-312.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/base.cpython-312.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-312.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-312.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-312.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-312.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-312.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-312.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-312.pyc,, +pip/_internal/resolution/resolvelib/base.py,sha256=DCf669FsqyQY5uqXeePDHQY1e4QO-pBzWH8O0s9-K94,5023 +pip/_internal/resolution/resolvelib/candidates.py,sha256=5UZ1upNnmqsP-nmEZaDYxaBgCoejw_e2WVGmmAvBxXc,20001 +pip/_internal/resolution/resolvelib/factory.py,sha256=511CaUR41LqjALuFafLVfx15WRvMhxYTdjQCoSvp4gw,32661 +pip/_internal/resolution/resolvelib/found_candidates.py,sha256=9hrTyQqFvl9I7Tji79F1AxHv39Qh1rkJ_7deSHSMfQc,6383 +pip/_internal/resolution/resolvelib/provider.py,sha256=bcsFnYvlmtB80cwVdW1fIwgol8ZNr1f1VHyRTkz47SM,9935 +pip/_internal/resolution/resolvelib/reporter.py,sha256=00JtoXEkTlw0-rl_sl54d71avwOsJHt9GGHcrj5Sza0,3168 +pip/_internal/resolution/resolvelib/requirements.py,sha256=7JG4Z72e5Yk4vU0S5ulGvbqTy4FMQGYhY5zQhX9zTtY,8065 +pip/_internal/resolution/resolvelib/resolver.py,sha256=nLJOsVMEVi2gQUVJoUFKMZAeu2f7GRMjGMvNSWyz0Bc,12592 +pip/_internal/self_outdated_check.py,sha256=pkjQixuWyQ1vrVxZAaYD6SSHgXuFUnHZybXEWTkh0S0,8145 +pip/_internal/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/utils/__pycache__/__init__.cpython-312.pyc,, +pip/_internal/utils/__pycache__/_jaraco_text.cpython-312.pyc,, +pip/_internal/utils/__pycache__/_log.cpython-312.pyc,, +pip/_internal/utils/__pycache__/appdirs.cpython-312.pyc,, +pip/_internal/utils/__pycache__/compat.cpython-312.pyc,, +pip/_internal/utils/__pycache__/compatibility_tags.cpython-312.pyc,, +pip/_internal/utils/__pycache__/datetime.cpython-312.pyc,, +pip/_internal/utils/__pycache__/deprecation.cpython-312.pyc,, +pip/_internal/utils/__pycache__/direct_url_helpers.cpython-312.pyc,, +pip/_internal/utils/__pycache__/egg_link.cpython-312.pyc,, +pip/_internal/utils/__pycache__/encoding.cpython-312.pyc,, +pip/_internal/utils/__pycache__/entrypoints.cpython-312.pyc,, +pip/_internal/utils/__pycache__/filesystem.cpython-312.pyc,, +pip/_internal/utils/__pycache__/filetypes.cpython-312.pyc,, +pip/_internal/utils/__pycache__/glibc.cpython-312.pyc,, +pip/_internal/utils/__pycache__/hashes.cpython-312.pyc,, +pip/_internal/utils/__pycache__/logging.cpython-312.pyc,, +pip/_internal/utils/__pycache__/misc.cpython-312.pyc,, +pip/_internal/utils/__pycache__/packaging.cpython-312.pyc,, +pip/_internal/utils/__pycache__/retry.cpython-312.pyc,, +pip/_internal/utils/__pycache__/setuptools_build.cpython-312.pyc,, +pip/_internal/utils/__pycache__/subprocess.cpython-312.pyc,, +pip/_internal/utils/__pycache__/temp_dir.cpython-312.pyc,, +pip/_internal/utils/__pycache__/unpacking.cpython-312.pyc,, +pip/_internal/utils/__pycache__/urls.cpython-312.pyc,, +pip/_internal/utils/__pycache__/virtualenv.cpython-312.pyc,, +pip/_internal/utils/__pycache__/wheel.cpython-312.pyc,, +pip/_internal/utils/_jaraco_text.py,sha256=M15uUPIh5NpP1tdUGBxRau6q1ZAEtI8-XyLEETscFfE,3350 +pip/_internal/utils/_log.py,sha256=-jHLOE_THaZz5BFcCnoSL9EYAtJ0nXem49s9of4jvKw,1015 +pip/_internal/utils/appdirs.py,sha256=swgcTKOm3daLeXTW6v5BUS2Ti2RvEnGRQYH_yDXklAo,1665 +pip/_internal/utils/compat.py,sha256=ckkFveBiYQjRWjkNsajt_oWPS57tJvE8XxoC4OIYgCY,2399 +pip/_internal/utils/compatibility_tags.py,sha256=OWq5axHpW-MEEPztGdvgADrgJPAcV9a88Rxm4Z8VBs8,6272 +pip/_internal/utils/datetime.py,sha256=m21Y3wAtQc-ji6Veb6k_M5g6A0ZyFI4egchTdnwh-pQ,242 +pip/_internal/utils/deprecation.py,sha256=k7Qg_UBAaaTdyq82YVARA6D7RmcGTXGv7fnfcgigj4Q,3707 +pip/_internal/utils/direct_url_helpers.py,sha256=r2MRtkVDACv9AGqYODBUC9CjwgtsUU1s68hmgfCJMtA,3196 +pip/_internal/utils/egg_link.py,sha256=0FePZoUYKv4RGQ2t6x7w5Z427wbA_Uo3WZnAkrgsuqo,2463 +pip/_internal/utils/encoding.py,sha256=qqsXDtiwMIjXMEiIVSaOjwH5YmirCaK-dIzb6-XJsL0,1169 +pip/_internal/utils/entrypoints.py,sha256=YlhLTRl2oHBAuqhc-zmL7USS67TPWVHImjeAQHreZTQ,3064 +pip/_internal/utils/filesystem.py,sha256=ajvA-q4ocliW9kPp8Yquh-4vssXbu-UKbo5FV9V4X64,4950 +pip/_internal/utils/filetypes.py,sha256=i8XAQ0eFCog26Fw9yV0Yb1ygAqKYB1w9Cz9n0fj8gZU,716 +pip/_internal/utils/glibc.py,sha256=vUkWq_1pJuzcYNcGKLlQmABoUiisK8noYY1yc8Wq4w4,3734 +pip/_internal/utils/hashes.py,sha256=XGGLL0AG8-RhWnyz87xF6MFZ--BKadHU35D47eApCKI,4972 +pip/_internal/utils/logging.py,sha256=7BFKB1uFjdxD5crM-GtwA5T2qjbQ2LPD-gJDuJeDNTg,11606 +pip/_internal/utils/misc.py,sha256=NRV0_2fFhzy1jhvInSBv4dqCmTwct8PV7Kp0m-BPRGM,23530 +pip/_internal/utils/packaging.py,sha256=iI3LH43lVNR4hWBOqF6lFsZq4aycb2j0UcHlmDmcqUg,2109 +pip/_internal/utils/retry.py,sha256=mhFbykXjhTnZfgzeuy-vl9c8nECnYn_CMtwNJX2tYzQ,1392 +pip/_internal/utils/setuptools_build.py,sha256=ouXpud-jeS8xPyTPsXJ-m34NPvK5os45otAzdSV_IJE,4435 +pip/_internal/utils/subprocess.py,sha256=EsvqSRiSMHF98T8Txmu6NLU3U--MpTTQjtNgKP0P--M,8988 +pip/_internal/utils/temp_dir.py,sha256=5qOXe8M4JeY6vaFQM867d5zkp1bSwMZ-KT5jymmP0Zg,9310 +pip/_internal/utils/unpacking.py,sha256=eyDkSsk4nW8ZfiSjNzJduCznpHyaGHVv3ak_LMGsiEM,11951 +pip/_internal/utils/urls.py,sha256=qceSOZb5lbNDrHNsv7_S4L4Ytszja5NwPKUMnZHbYnM,1599 +pip/_internal/utils/virtualenv.py,sha256=S6f7csYorRpiD6cvn3jISZYc3I8PJC43H5iMFpRAEDU,3456 +pip/_internal/utils/wheel.py,sha256=b442jkydFHjXzDy6cMR7MpzWBJ1Q82hR5F33cmcHV3g,4494 +pip/_internal/vcs/__init__.py,sha256=UAqvzpbi0VbZo3Ub6skEeZAw-ooIZR-zX_WpCbxyCoU,596 +pip/_internal/vcs/__pycache__/__init__.cpython-312.pyc,, +pip/_internal/vcs/__pycache__/bazaar.cpython-312.pyc,, +pip/_internal/vcs/__pycache__/git.cpython-312.pyc,, +pip/_internal/vcs/__pycache__/mercurial.cpython-312.pyc,, +pip/_internal/vcs/__pycache__/subversion.cpython-312.pyc,, +pip/_internal/vcs/__pycache__/versioncontrol.cpython-312.pyc,, +pip/_internal/vcs/bazaar.py,sha256=EKStcQaKpNu0NK4p5Q10Oc4xb3DUxFw024XrJy40bFQ,3528 +pip/_internal/vcs/git.py,sha256=3tpc9LQA_J4IVW5r5NvWaaSeDzcmJOrSFZN0J8vIKfU,18177 +pip/_internal/vcs/mercurial.py,sha256=oULOhzJ2Uie-06d1omkL-_Gc6meGaUkyogvqG9ZCyPs,5249 +pip/_internal/vcs/subversion.py,sha256=ddTugHBqHzV3ebKlU5QXHPN4gUqlyXbOx8q8NgXKvs8,11735 +pip/_internal/vcs/versioncontrol.py,sha256=cvf_-hnTAjQLXJ3d17FMNhQfcO1AcKWUF10tfrYyP-c,22440 +pip/_internal/wheel_builder.py,sha256=DL3A8LKeRj_ACp11WS5wSgASgPFqeyAeXJKdXfmaWXU,11799 +pip/_vendor/__init__.py,sha256=JYuAXvClhInxIrA2FTp5p-uuWVL7WV6-vEpTs46-Qh4,4873 +pip/_vendor/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/__pycache__/typing_extensions.cpython-312.pyc,, +pip/_vendor/cachecontrol/__init__.py,sha256=GiYoagwPEiJ_xR_lbwWGaoCiPtF_rz4isjfjdDAgHU4,676 +pip/_vendor/cachecontrol/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-312.pyc,, +pip/_vendor/cachecontrol/__pycache__/adapter.cpython-312.pyc,, +pip/_vendor/cachecontrol/__pycache__/cache.cpython-312.pyc,, +pip/_vendor/cachecontrol/__pycache__/controller.cpython-312.pyc,, +pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-312.pyc,, +pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-312.pyc,, +pip/_vendor/cachecontrol/__pycache__/serialize.cpython-312.pyc,, +pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-312.pyc,, +pip/_vendor/cachecontrol/_cmd.py,sha256=iist2EpzJvDVIhMAxXq8iFnTBsiZAd6iplxfmNboNyk,1737 +pip/_vendor/cachecontrol/adapter.py,sha256=fByO_Pd_EOemjWbuocvBWdN85xT0q_TBm2lxS6vD4fk,6355 +pip/_vendor/cachecontrol/cache.py,sha256=OTQj72tUf8C1uEgczdl3Gc8vkldSzsTITKtDGKMx4z8,1952 +pip/_vendor/cachecontrol/caches/__init__.py,sha256=dtrrroK5BnADR1GWjCZ19aZ0tFsMfvFBtLQQU1sp_ag,303 +pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-312.pyc,, +pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-312.pyc,, +pip/_vendor/cachecontrol/caches/file_cache.py,sha256=9AlmmTJc6cslb6k5z_6q0sGPHVrMj8zv-uWy-simmfE,5406 +pip/_vendor/cachecontrol/caches/redis_cache.py,sha256=9rmqwtYu_ljVkW6_oLqbC7EaX_a8YT_yLuna-eS0dgo,1386 +pip/_vendor/cachecontrol/controller.py,sha256=o-ejGJlBmpKK8QQLyTPJj0t7siU8XVHXuV8MCybCxQ8,18575 +pip/_vendor/cachecontrol/filewrapper.py,sha256=STttGmIPBvZzt2b51dUOwoWX5crcMCpKZOisM3f5BNc,4292 +pip/_vendor/cachecontrol/heuristics.py,sha256=IYe4QmHERWsMvtxNrp920WeaIsaTTyqLB14DSheSbtY,4834 +pip/_vendor/cachecontrol/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/cachecontrol/serialize.py,sha256=HQd2IllQ05HzPkVLMXTF2uX5mjEQjDBkxCqUJUODpZk,5163 +pip/_vendor/cachecontrol/wrapper.py,sha256=hsGc7g8QGQTT-4f8tgz3AM5qwScg6FO0BSdLSRdEvpU,1417 +pip/_vendor/certifi/__init__.py,sha256=p_GYZrjUwPBUhpLlCZoGb0miKBKSqDAyZC5DvIuqbHQ,94 +pip/_vendor/certifi/__main__.py,sha256=1k3Cr95vCxxGRGDljrW3wMdpZdL3Nhf0u1n-k2qdsCY,255 +pip/_vendor/certifi/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/certifi/__pycache__/__main__.cpython-312.pyc,, +pip/_vendor/certifi/__pycache__/core.cpython-312.pyc,, +pip/_vendor/certifi/cacert.pem,sha256=lO3rZukXdPyuk6BWUJFOKQliWaXH6HGh9l1GGrUgG0c,299427 +pip/_vendor/certifi/core.py,sha256=2SRT5rIcQChFDbe37BQa-kULxAgJ8qN6l1jfqTp4HIs,4486 +pip/_vendor/certifi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/distlib/__init__.py,sha256=dcwgYGYGQqAEawBXPDtIx80DO_3cOmFv8HTc8JMzknQ,625 +pip/_vendor/distlib/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/distlib/__pycache__/compat.cpython-312.pyc,, +pip/_vendor/distlib/__pycache__/database.cpython-312.pyc,, +pip/_vendor/distlib/__pycache__/index.cpython-312.pyc,, +pip/_vendor/distlib/__pycache__/locators.cpython-312.pyc,, +pip/_vendor/distlib/__pycache__/manifest.cpython-312.pyc,, +pip/_vendor/distlib/__pycache__/markers.cpython-312.pyc,, +pip/_vendor/distlib/__pycache__/metadata.cpython-312.pyc,, +pip/_vendor/distlib/__pycache__/resources.cpython-312.pyc,, +pip/_vendor/distlib/__pycache__/scripts.cpython-312.pyc,, +pip/_vendor/distlib/__pycache__/util.cpython-312.pyc,, +pip/_vendor/distlib/__pycache__/version.cpython-312.pyc,, +pip/_vendor/distlib/__pycache__/wheel.cpython-312.pyc,, +pip/_vendor/distlib/compat.py,sha256=2jRSjRI4o-vlXeTK2BCGIUhkc6e9ZGhSsacRM5oseTw,41467 +pip/_vendor/distlib/database.py,sha256=mHy_LxiXIsIVRb-T0-idBrVLw3Ffij5teHCpbjmJ9YU,51160 +pip/_vendor/distlib/index.py,sha256=lTbw268rRhj8dw1sib3VZ_0EhSGgoJO3FKJzSFMOaeA,20797 +pip/_vendor/distlib/locators.py,sha256=oBeAZpFuPQSY09MgNnLfQGGAXXvVO96BFpZyKMuK4tM,51026 +pip/_vendor/distlib/manifest.py,sha256=3qfmAmVwxRqU1o23AlfXrQGZzh6g_GGzTAP_Hb9C5zQ,14168 +pip/_vendor/distlib/markers.py,sha256=X6sDvkFGcYS8gUW8hfsWuKEKAqhQZAJ7iXOMLxRYjYk,5164 +pip/_vendor/distlib/metadata.py,sha256=zil3sg2EUfLXVigljY2d_03IJt-JSs7nX-73fECMX2s,38724 +pip/_vendor/distlib/resources.py,sha256=LwbPksc0A1JMbi6XnuPdMBUn83X7BPuFNWqPGEKI698,10820 +pip/_vendor/distlib/scripts.py,sha256=BJliaDAZaVB7WAkwokgC3HXwLD2iWiHaVI50H7C6eG8,18608 +pip/_vendor/distlib/t32.exe,sha256=a0GV5kCoWsMutvliiCKmIgV98eRZ33wXoS-XrqvJQVs,97792 +pip/_vendor/distlib/t64-arm.exe,sha256=68TAa32V504xVBnufojh0PcenpR3U4wAqTqf-MZqbPw,182784 +pip/_vendor/distlib/t64.exe,sha256=gaYY8hy4fbkHYTTnA4i26ct8IQZzkBG2pRdy0iyuBrc,108032 +pip/_vendor/distlib/util.py,sha256=vMPGvsS4j9hF6Y9k3Tyom1aaHLb0rFmZAEyzeAdel9w,66682 +pip/_vendor/distlib/version.py,sha256=s5VIs8wBn0fxzGxWM_aA2ZZyx525HcZbMvcTlTyZ3Rg,23727 +pip/_vendor/distlib/w32.exe,sha256=R4csx3-OGM9kL4aPIzQKRo5TfmRSHZo6QWyLhDhNBks,91648 +pip/_vendor/distlib/w64-arm.exe,sha256=xdyYhKj0WDcVUOCb05blQYvzdYIKMbmJn2SZvzkcey4,168448 +pip/_vendor/distlib/w64.exe,sha256=ejGf-rojoBfXseGLpya6bFTFPWRG21X5KvU8J5iU-K0,101888 +pip/_vendor/distlib/wheel.py,sha256=DFIVguEQHCdxnSdAO0dfFsgMcvVZitg7bCOuLwZ7A_s,43979 +pip/_vendor/distro/__init__.py,sha256=2fHjF-SfgPvjyNZ1iHh_wjqWdR_Yo5ODHwZC0jLBPhc,981 +pip/_vendor/distro/__main__.py,sha256=bu9d3TifoKciZFcqRBuygV3GSuThnVD_m2IK4cz96Vs,64 +pip/_vendor/distro/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/distro/__pycache__/__main__.cpython-312.pyc,, +pip/_vendor/distro/__pycache__/distro.cpython-312.pyc,, +pip/_vendor/distro/distro.py,sha256=XqbefacAhDT4zr_trnbA15eY8vdK4GTghgmvUGrEM_4,49430 +pip/_vendor/distro/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/idna/__init__.py,sha256=KJQN1eQBr8iIK5SKrJ47lXvxG0BJ7Lm38W4zT0v_8lk,849 +pip/_vendor/idna/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/idna/__pycache__/codec.cpython-312.pyc,, +pip/_vendor/idna/__pycache__/compat.cpython-312.pyc,, +pip/_vendor/idna/__pycache__/core.cpython-312.pyc,, +pip/_vendor/idna/__pycache__/idnadata.cpython-312.pyc,, +pip/_vendor/idna/__pycache__/intranges.cpython-312.pyc,, +pip/_vendor/idna/__pycache__/package_data.cpython-312.pyc,, +pip/_vendor/idna/__pycache__/uts46data.cpython-312.pyc,, +pip/_vendor/idna/codec.py,sha256=PS6m-XmdST7Wj7J7ulRMakPDt5EBJyYrT3CPtjh-7t4,3426 +pip/_vendor/idna/compat.py,sha256=0_sOEUMT4CVw9doD3vyRhX80X19PwqFoUBs7gWsFME4,321 +pip/_vendor/idna/core.py,sha256=lyhpoe2vulEaB_65xhXmoKgO-xUqFDvcwxu5hpNNO4E,12663 +pip/_vendor/idna/idnadata.py,sha256=dqRwytzkjIHMBa2R1lYvHDwACenZPt8eGVu1Y8UBE-E,78320 +pip/_vendor/idna/intranges.py,sha256=YBr4fRYuWH7kTKS2tXlFjM24ZF1Pdvcir-aywniInqg,1881 +pip/_vendor/idna/package_data.py,sha256=Tkt0KnIeyIlnHddOaz9WSkkislNgokJAuE-p5GorMqo,21 +pip/_vendor/idna/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/idna/uts46data.py,sha256=1KuksWqLuccPXm2uyRVkhfiFLNIhM_H2m4azCcnOqEU,206503 +pip/_vendor/msgpack/__init__.py,sha256=gsMP7JTECZNUSjvOyIbdhNOkpB9Z8BcGwabVGY2UcdQ,1077 +pip/_vendor/msgpack/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/msgpack/__pycache__/exceptions.cpython-312.pyc,, +pip/_vendor/msgpack/__pycache__/ext.cpython-312.pyc,, +pip/_vendor/msgpack/__pycache__/fallback.cpython-312.pyc,, +pip/_vendor/msgpack/exceptions.py,sha256=dCTWei8dpkrMsQDcjQk74ATl9HsIBH0ybt8zOPNqMYc,1081 +pip/_vendor/msgpack/ext.py,sha256=fKp00BqDLjUtZnPd70Llr138zk8JsCuSpJkkZ5S4dt8,5629 +pip/_vendor/msgpack/fallback.py,sha256=wdUWJkWX2gzfRW9BBCTOuIE1Wvrf5PtBtR8ZtY7G_EE,33175 +pip/_vendor/packaging/__init__.py,sha256=dtw2bNmWCQ9WnMoK3bk_elL1svSlikXtLpZhCFIB9SE,496 +pip/_vendor/packaging/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/packaging/__pycache__/_elffile.cpython-312.pyc,, +pip/_vendor/packaging/__pycache__/_manylinux.cpython-312.pyc,, +pip/_vendor/packaging/__pycache__/_musllinux.cpython-312.pyc,, +pip/_vendor/packaging/__pycache__/_parser.cpython-312.pyc,, +pip/_vendor/packaging/__pycache__/_structures.cpython-312.pyc,, +pip/_vendor/packaging/__pycache__/_tokenizer.cpython-312.pyc,, +pip/_vendor/packaging/__pycache__/markers.cpython-312.pyc,, +pip/_vendor/packaging/__pycache__/metadata.cpython-312.pyc,, +pip/_vendor/packaging/__pycache__/requirements.cpython-312.pyc,, +pip/_vendor/packaging/__pycache__/specifiers.cpython-312.pyc,, +pip/_vendor/packaging/__pycache__/tags.cpython-312.pyc,, +pip/_vendor/packaging/__pycache__/utils.cpython-312.pyc,, +pip/_vendor/packaging/__pycache__/version.cpython-312.pyc,, +pip/_vendor/packaging/_elffile.py,sha256=_LcJW4YNKywYsl4169B2ukKRqwxjxst_8H0FRVQKlz8,3282 +pip/_vendor/packaging/_manylinux.py,sha256=Xo4V0PZz8sbuVCbTni0t1CR0AHeir_7ib4lTmV8scD4,9586 +pip/_vendor/packaging/_musllinux.py,sha256=p9ZqNYiOItGee8KcZFeHF_YcdhVwGHdK6r-8lgixvGQ,2694 +pip/_vendor/packaging/_parser.py,sha256=s_TvTvDNK0NrM2QB3VKThdWFM4Nc0P6JnkObkl3MjpM,10236 +pip/_vendor/packaging/_structures.py,sha256=q3eVNmbWJGG_S0Dit_S3Ao8qQqz_5PYTXFAKBZe5yr4,1431 +pip/_vendor/packaging/_tokenizer.py,sha256=J6v5H7Jzvb-g81xp_2QACKwO7LxHQA6ikryMU7zXwN8,5273 +pip/_vendor/packaging/markers.py,sha256=dWKSqn5Sp-jDmOG-W3GfLHKjwhf1IsznbT71VlBoB5M,10671 +pip/_vendor/packaging/metadata.py,sha256=KINuSkJ12u-SyoKNTy_pHNGAfMUtxNvZ53qA1zAKcKI,32349 +pip/_vendor/packaging/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/packaging/requirements.py,sha256=gYyRSAdbrIyKDY66ugIDUQjRMvxkH2ALioTmX3tnL6o,2947 +pip/_vendor/packaging/specifiers.py,sha256=HfGgfNJRvrzC759gnnoojHyiWs_DYmcw5PEh5jHH-YE,39738 +pip/_vendor/packaging/tags.py,sha256=Fo6_cit95-7QfcMb16XtI7AUiSMgdwA_hCO_9lV2pz4,21388 +pip/_vendor/packaging/utils.py,sha256=NAdYUwnlAOpkat_RthavX8a07YuVxgGL_vwrx73GSDM,5287 +pip/_vendor/packaging/version.py,sha256=wE4sSVlF-d1H6HFC1vszEe35CwTig_fh4HHIFg95hFE,16210 +pip/_vendor/pkg_resources/__init__.py,sha256=jrhDRbOubP74QuPXxd7U7Po42PH2l-LZ2XfcO7llpZ4,124463 +pip/_vendor/pkg_resources/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/platformdirs/__init__.py,sha256=FTA6LGNm40GwNZt3gG3uLAacWvf2E_2HTmH0rAALGR8,22285 +pip/_vendor/platformdirs/__main__.py,sha256=jBJ8zb7Mpx5ebcqF83xrpO94MaeCpNGHVf9cvDN2JLg,1505 +pip/_vendor/platformdirs/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/platformdirs/__pycache__/__main__.cpython-312.pyc,, +pip/_vendor/platformdirs/__pycache__/android.cpython-312.pyc,, +pip/_vendor/platformdirs/__pycache__/api.cpython-312.pyc,, +pip/_vendor/platformdirs/__pycache__/macos.cpython-312.pyc,, +pip/_vendor/platformdirs/__pycache__/unix.cpython-312.pyc,, +pip/_vendor/platformdirs/__pycache__/version.cpython-312.pyc,, +pip/_vendor/platformdirs/__pycache__/windows.cpython-312.pyc,, +pip/_vendor/platformdirs/android.py,sha256=xZXY9Jd46WOsxT2U6-5HsNtDZ-IQqxcEUrBLl3hYk4o,9016 +pip/_vendor/platformdirs/api.py,sha256=QBYdUac2eC521ek_y53uD1Dcq-lJX8IgSRVd4InC6uc,8996 +pip/_vendor/platformdirs/macos.py,sha256=wftsbsvq6nZ0WORXSiCrZNkRHz_WKuktl0a6mC7MFkI,5580 +pip/_vendor/platformdirs/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/platformdirs/unix.py,sha256=Cci9Wqt35dAMsg6HT9nRGHSBW5obb0pR3AE1JJnsCXg,10643 +pip/_vendor/platformdirs/version.py,sha256=r7F76tZRjgQKzrpx_I0_ZMQOMU-PS7eGnHD7zEK3KB0,411 +pip/_vendor/platformdirs/windows.py,sha256=IFpiohUBwxPtCzlyKwNtxyW4Jk8haa6W8o59mfrDXVo,10125 +pip/_vendor/pygments/__init__.py,sha256=7N1oiaWulw_nCsTY4EEixYLz15pWY5u4uPAFFi-ielU,2983 +pip/_vendor/pygments/__main__.py,sha256=isIhBxLg65nLlXukG4VkMuPfNdd7gFzTZ_R_z3Q8diY,353 +pip/_vendor/pygments/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/pygments/__pycache__/__main__.cpython-312.pyc,, +pip/_vendor/pygments/__pycache__/cmdline.cpython-312.pyc,, +pip/_vendor/pygments/__pycache__/console.cpython-312.pyc,, +pip/_vendor/pygments/__pycache__/filter.cpython-312.pyc,, +pip/_vendor/pygments/__pycache__/formatter.cpython-312.pyc,, +pip/_vendor/pygments/__pycache__/lexer.cpython-312.pyc,, +pip/_vendor/pygments/__pycache__/modeline.cpython-312.pyc,, +pip/_vendor/pygments/__pycache__/plugin.cpython-312.pyc,, +pip/_vendor/pygments/__pycache__/regexopt.cpython-312.pyc,, +pip/_vendor/pygments/__pycache__/scanner.cpython-312.pyc,, +pip/_vendor/pygments/__pycache__/sphinxext.cpython-312.pyc,, +pip/_vendor/pygments/__pycache__/style.cpython-312.pyc,, +pip/_vendor/pygments/__pycache__/token.cpython-312.pyc,, +pip/_vendor/pygments/__pycache__/unistring.cpython-312.pyc,, +pip/_vendor/pygments/__pycache__/util.cpython-312.pyc,, +pip/_vendor/pygments/cmdline.py,sha256=LIVzmAunlk9sRJJp54O4KRy9GDIN4Wu13v9p9QzfGPM,23656 +pip/_vendor/pygments/console.py,sha256=yhP9UsLAVmWKVQf2446JJewkA7AiXeeTf4Ieg3Oi2fU,1718 +pip/_vendor/pygments/filter.py,sha256=_ADNPCskD8_GmodHi6_LoVgPU3Zh336aBCT5cOeTMs0,1910 +pip/_vendor/pygments/filters/__init__.py,sha256=RdedK2KWKXlKwR7cvkfr3NUj9YiZQgMgilRMFUg2jPA,40392 +pip/_vendor/pygments/filters/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/pygments/formatter.py,sha256=jDWBTndlBH2Z5IYZFVDnP0qn1CaTQjTWt7iAGtCnJEg,4390 +pip/_vendor/pygments/formatters/__init__.py,sha256=8No-NUs8rBTSSBJIv4hSEQt2M0cFB4hwAT0snVc2QGE,5385 +pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-312.pyc,, +pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-312.pyc,, +pip/_vendor/pygments/formatters/__pycache__/groff.cpython-312.pyc,, +pip/_vendor/pygments/formatters/__pycache__/html.cpython-312.pyc,, +pip/_vendor/pygments/formatters/__pycache__/img.cpython-312.pyc,, +pip/_vendor/pygments/formatters/__pycache__/irc.cpython-312.pyc,, +pip/_vendor/pygments/formatters/__pycache__/latex.cpython-312.pyc,, +pip/_vendor/pygments/formatters/__pycache__/other.cpython-312.pyc,, +pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-312.pyc,, +pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-312.pyc,, +pip/_vendor/pygments/formatters/__pycache__/svg.cpython-312.pyc,, +pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-312.pyc,, +pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-312.pyc,, +pip/_vendor/pygments/formatters/_mapping.py,sha256=1Cw37FuQlNacnxRKmtlPX4nyLoX9_ttko5ZwscNUZZ4,4176 +pip/_vendor/pygments/formatters/bbcode.py,sha256=3JQLI45tcrQ_kRUMjuab6C7Hb0XUsbVWqqbSn9cMjkI,3320 +pip/_vendor/pygments/formatters/groff.py,sha256=M39k0PaSSZRnxWjqBSVPkF0mu1-Vr7bm6RsFvs-CNN4,5106 +pip/_vendor/pygments/formatters/html.py,sha256=SE2jc3YCqbMS3rZW9EAmDlAUhdVxJ52gA4dileEvCGU,35669 +pip/_vendor/pygments/formatters/img.py,sha256=MwA4xWPLOwh6j7Yc6oHzjuqSPt0M1fh5r-5BTIIUfsU,23287 +pip/_vendor/pygments/formatters/irc.py,sha256=dp1Z0l_ObJ5NFh9MhqLGg5ptG5hgJqedT2Vkutt9v0M,4981 +pip/_vendor/pygments/formatters/latex.py,sha256=XMmhOCqUKDBQtG5mGJNAFYxApqaC5puo5cMmPfK3944,19306 +pip/_vendor/pygments/formatters/other.py,sha256=56PMJOliin-rAUdnRM0i1wsV1GdUPd_dvQq0_UPfF9c,5034 +pip/_vendor/pygments/formatters/pangomarkup.py,sha256=y16U00aVYYEFpeCfGXlYBSMacG425CbfoG8oKbKegIg,2218 +pip/_vendor/pygments/formatters/rtf.py,sha256=ZT90dmcKyJboIB0mArhL7IhE467GXRN0G7QAUgG03To,11957 +pip/_vendor/pygments/formatters/svg.py,sha256=KKsiophPupHuxm0So-MsbQEWOT54IAiSF7hZPmxtKXE,7174 +pip/_vendor/pygments/formatters/terminal.py,sha256=AojNG4MlKq2L6IsC_VnXHu4AbHCBn9Otog6u45XvxeI,4674 +pip/_vendor/pygments/formatters/terminal256.py,sha256=kGkNUVo3FpwjytIDS0if79EuUoroAprcWt3igrcIqT0,11753 +pip/_vendor/pygments/lexer.py,sha256=TYHDt___gNW4axTl2zvPZff-VQi8fPaIh5OKRcVSjUM,35349 +pip/_vendor/pygments/lexers/__init__.py,sha256=pIlxyQJuu_syh9lE080cq8ceVbEVcKp0osAFU5fawJU,12115 +pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-312.pyc,, +pip/_vendor/pygments/lexers/__pycache__/python.cpython-312.pyc,, +pip/_vendor/pygments/lexers/_mapping.py,sha256=61-h3zr103m01OS5BUq_AfUiL9YI06Ves9ipQ7k4vr4,76097 +pip/_vendor/pygments/lexers/python.py,sha256=2J_YJrPTr_A6fJY_qKiKv0GpgPwHMrlMSeo59qN3fe4,53687 +pip/_vendor/pygments/modeline.py,sha256=gtRYZBS-CKOCDXHhGZqApboHBaZwGH8gznN3O6nuxj4,1005 +pip/_vendor/pygments/plugin.py,sha256=ioeJ3QeoJ-UQhZpY9JL7vbxsTVuwwM7BCu-Jb8nN0AU,1891 +pip/_vendor/pygments/regexopt.py,sha256=Hky4EB13rIXEHQUNkwmCrYqtIlnXDehNR3MztafZ43w,3072 +pip/_vendor/pygments/scanner.py,sha256=NDy3ofK_fHRFK4hIDvxpamG871aewqcsIb6sgTi7Fhk,3092 +pip/_vendor/pygments/sphinxext.py,sha256=iOptJBcqOGPwMEJ2p70PvwpZPIGdvdZ8dxvq6kzxDgA,7981 +pip/_vendor/pygments/style.py,sha256=rSCZWFpg1_DwFMXDU0nEVmAcBHpuQGf9RxvOPPQvKLQ,6420 +pip/_vendor/pygments/styles/__init__.py,sha256=qUk6_1z5KmT8EdJFZYgESmG6P_HJF_2vVrDD7HSCGYY,2042 +pip/_vendor/pygments/styles/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/pygments/styles/__pycache__/_mapping.cpython-312.pyc,, +pip/_vendor/pygments/styles/_mapping.py,sha256=6lovFUE29tz6EsV3XYY4hgozJ7q1JL7cfO3UOlgnS8w,3312 +pip/_vendor/pygments/token.py,sha256=qZwT7LSPy5YBY3JgDjut642CCy7JdQzAfmqD9NmT5j0,6226 +pip/_vendor/pygments/unistring.py,sha256=p5c1i-HhoIhWemy9CUsaN9o39oomYHNxXll0Xfw6tEA,63208 +pip/_vendor/pygments/util.py,sha256=2tj2nS1X9_OpcuSjf8dOET2bDVZhs8cEKd_uT6-Fgg8,10031 +pip/_vendor/pyproject_hooks/__init__.py,sha256=kCehmy0UaBa9oVMD7ZIZrnswfnP3LXZ5lvnNJAL5JBM,491 +pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/pyproject_hooks/__pycache__/_compat.cpython-312.pyc,, +pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-312.pyc,, +pip/_vendor/pyproject_hooks/_compat.py,sha256=by6evrYnqkisiM-MQcvOKs5bgDMzlOSgZqRHNqf04zE,138 +pip/_vendor/pyproject_hooks/_impl.py,sha256=61GJxzQip0IInhuO69ZI5GbNQ82XEDUB_1Gg5_KtUoc,11920 +pip/_vendor/pyproject_hooks/_in_process/__init__.py,sha256=9gQATptbFkelkIy0OfWFEACzqxXJMQDWCH9rBOAZVwQ,546 +pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-312.pyc,, +pip/_vendor/pyproject_hooks/_in_process/_in_process.py,sha256=m2b34c917IW5o-Q_6TYIHlsK9lSUlNiyrITTUH_zwew,10927 +pip/_vendor/requests/__init__.py,sha256=HlB_HzhrzGtfD_aaYUwUh1zWXLZ75_YCLyit75d0Vz8,5057 +pip/_vendor/requests/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/requests/__pycache__/__version__.cpython-312.pyc,, +pip/_vendor/requests/__pycache__/_internal_utils.cpython-312.pyc,, +pip/_vendor/requests/__pycache__/adapters.cpython-312.pyc,, +pip/_vendor/requests/__pycache__/api.cpython-312.pyc,, +pip/_vendor/requests/__pycache__/auth.cpython-312.pyc,, +pip/_vendor/requests/__pycache__/certs.cpython-312.pyc,, +pip/_vendor/requests/__pycache__/compat.cpython-312.pyc,, +pip/_vendor/requests/__pycache__/cookies.cpython-312.pyc,, +pip/_vendor/requests/__pycache__/exceptions.cpython-312.pyc,, +pip/_vendor/requests/__pycache__/help.cpython-312.pyc,, +pip/_vendor/requests/__pycache__/hooks.cpython-312.pyc,, +pip/_vendor/requests/__pycache__/models.cpython-312.pyc,, +pip/_vendor/requests/__pycache__/packages.cpython-312.pyc,, +pip/_vendor/requests/__pycache__/sessions.cpython-312.pyc,, +pip/_vendor/requests/__pycache__/status_codes.cpython-312.pyc,, +pip/_vendor/requests/__pycache__/structures.cpython-312.pyc,, +pip/_vendor/requests/__pycache__/utils.cpython-312.pyc,, +pip/_vendor/requests/__version__.py,sha256=FVfglgZmNQnmYPXpOohDU58F5EUb_-VnSTaAesS187g,435 +pip/_vendor/requests/_internal_utils.py,sha256=nMQymr4hs32TqVo5AbCrmcJEhvPUh7xXlluyqwslLiQ,1495 +pip/_vendor/requests/adapters.py,sha256=J7VeVxKBvawbtlX2DERVo05J9BXTcWYLMHNd1Baa-bk,27607 +pip/_vendor/requests/api.py,sha256=_Zb9Oa7tzVIizTKwFrPjDEY9ejtm_OnSRERnADxGsQs,6449 +pip/_vendor/requests/auth.py,sha256=kF75tqnLctZ9Mf_hm9TZIj4cQWnN5uxRz8oWsx5wmR0,10186 +pip/_vendor/requests/certs.py,sha256=PVPooB0jP5hkZEULSCwC074532UFbR2Ptgu0I5zwmCs,575 +pip/_vendor/requests/compat.py,sha256=Mo9f9xZpefod8Zm-n9_StJcVTmwSukXR2p3IQyyVXvU,1485 +pip/_vendor/requests/cookies.py,sha256=bNi-iqEj4NPZ00-ob-rHvzkvObzN3lEpgw3g6paS3Xw,18590 +pip/_vendor/requests/exceptions.py,sha256=D1wqzYWne1mS2rU43tP9CeN1G7QAy7eqL9o1god6Ejw,4272 +pip/_vendor/requests/help.py,sha256=hRKaf9u0G7fdwrqMHtF3oG16RKktRf6KiwtSq2Fo1_0,3813 +pip/_vendor/requests/hooks.py,sha256=CiuysiHA39V5UfcCBXFIx83IrDpuwfN9RcTUgv28ftQ,733 +pip/_vendor/requests/models.py,sha256=x4K4CmH-lC0l2Kb-iPfMN4dRXxHEcbOaEWBL_i09AwI,35483 +pip/_vendor/requests/packages.py,sha256=_ZQDCJTJ8SP3kVWunSqBsRZNPzj2c1WFVqbdr08pz3U,1057 +pip/_vendor/requests/sessions.py,sha256=ykTI8UWGSltOfH07HKollH7kTBGw4WhiBVaQGmckTw4,30495 +pip/_vendor/requests/status_codes.py,sha256=iJUAeA25baTdw-6PfD0eF4qhpINDJRJI-yaMqxs4LEI,4322 +pip/_vendor/requests/structures.py,sha256=-IbmhVz06S-5aPSZuUthZ6-6D9XOjRuTXHOabY041XM,2912 +pip/_vendor/requests/utils.py,sha256=L79vnFbzJ3SFLKtJwpoWe41Tozi3RlZv94pY1TFIyow,33631 +pip/_vendor/resolvelib/__init__.py,sha256=h509TdEcpb5-44JonaU3ex2TM15GVBLjM9CNCPwnTTs,537 +pip/_vendor/resolvelib/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/resolvelib/__pycache__/providers.cpython-312.pyc,, +pip/_vendor/resolvelib/__pycache__/reporters.cpython-312.pyc,, +pip/_vendor/resolvelib/__pycache__/resolvers.cpython-312.pyc,, +pip/_vendor/resolvelib/__pycache__/structs.cpython-312.pyc,, +pip/_vendor/resolvelib/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-312.pyc,, +pip/_vendor/resolvelib/compat/collections_abc.py,sha256=uy8xUZ-NDEw916tugUXm8HgwCGiMO0f-RcdnpkfXfOs,156 +pip/_vendor/resolvelib/providers.py,sha256=fuuvVrCetu5gsxPB43ERyjfO8aReS3rFQHpDgiItbs4,5871 +pip/_vendor/resolvelib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/resolvelib/reporters.py,sha256=TSbRmWzTc26w0ggsV1bxVpeWDB8QNIre6twYl7GIZBE,1601 +pip/_vendor/resolvelib/resolvers.py,sha256=G8rsLZSq64g5VmIq-lB7UcIJ1gjAxIQJmTF4REZleQ0,20511 +pip/_vendor/resolvelib/structs.py,sha256=0_1_XO8z_CLhegP3Vpf9VJ3zJcfLm0NOHRM-i0Ykz3o,4963 +pip/_vendor/rich/__init__.py,sha256=dRxjIL-SbFVY0q3IjSMrfgBTHrm1LZDgLOygVBwiYZc,6090 +pip/_vendor/rich/__main__.py,sha256=eO7Cq8JnrgG8zVoeImiAs92q3hXNMIfp0w5lMsO7Q2Y,8477 +pip/_vendor/rich/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/__main__.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/_cell_widths.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/_emoji_codes.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/_emoji_replace.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/_export_format.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/_extension.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/_fileno.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/_inspect.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/_log_render.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/_loop.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/_null_file.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/_palettes.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/_pick.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/_ratio.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/_spinners.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/_stack.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/_timer.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/_win32_console.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/_windows.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/_windows_renderer.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/_wrap.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/abc.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/align.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/ansi.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/bar.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/box.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/cells.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/color.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/color_triplet.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/columns.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/console.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/constrain.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/containers.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/control.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/default_styles.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/diagnose.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/emoji.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/errors.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/file_proxy.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/filesize.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/highlighter.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/json.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/jupyter.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/layout.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/live.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/live_render.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/logging.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/markup.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/measure.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/padding.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/pager.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/palette.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/panel.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/pretty.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/progress.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/progress_bar.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/prompt.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/protocol.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/region.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/repr.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/rule.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/scope.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/screen.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/segment.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/spinner.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/status.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/style.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/styled.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/syntax.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/table.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/terminal_theme.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/text.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/theme.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/themes.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/traceback.cpython-312.pyc,, +pip/_vendor/rich/__pycache__/tree.cpython-312.pyc,, +pip/_vendor/rich/_cell_widths.py,sha256=fbmeyetEdHjzE_Vx2l1uK7tnPOhMs2X1lJfO3vsKDpA,10209 +pip/_vendor/rich/_emoji_codes.py,sha256=hu1VL9nbVdppJrVoijVshRlcRRe_v3dju3Mmd2sKZdY,140235 +pip/_vendor/rich/_emoji_replace.py,sha256=n-kcetsEUx2ZUmhQrfeMNc-teeGhpuSQ5F8VPBsyvDo,1064 +pip/_vendor/rich/_export_format.py,sha256=RI08pSrm5tBSzPMvnbTqbD9WIalaOoN5d4M1RTmLq1Y,2128 +pip/_vendor/rich/_extension.py,sha256=Xt47QacCKwYruzjDi-gOBq724JReDj9Cm9xUi5fr-34,265 +pip/_vendor/rich/_fileno.py,sha256=HWZxP5C2ajMbHryvAQZseflVfQoGzsKOHzKGsLD8ynQ,799 +pip/_vendor/rich/_inspect.py,sha256=oZJGw31e64dwXSCmrDnvZbwVb1ZKhWfU8wI3VWohjJk,9695 +pip/_vendor/rich/_log_render.py,sha256=1ByI0PA1ZpxZY3CGJOK54hjlq4X-Bz_boIjIqCd8Kns,3225 +pip/_vendor/rich/_loop.py,sha256=hV_6CLdoPm0va22Wpw4zKqM0RYsz3TZxXj0PoS-9eDQ,1236 +pip/_vendor/rich/_null_file.py,sha256=tGSXk_v-IZmbj1GAzHit8A3kYIQMiCpVsCFfsC-_KJ4,1387 +pip/_vendor/rich/_palettes.py,sha256=cdev1JQKZ0JvlguV9ipHgznTdnvlIzUFDBb0It2PzjI,7063 +pip/_vendor/rich/_pick.py,sha256=evDt8QN4lF5CiwrUIXlOJCntitBCOsI3ZLPEIAVRLJU,423 +pip/_vendor/rich/_ratio.py,sha256=Zt58apszI6hAAcXPpgdWKpu3c31UBWebOeR4mbyptvU,5471 +pip/_vendor/rich/_spinners.py,sha256=U2r1_g_1zSjsjiUdAESc2iAMc3i4ri_S8PYP6kQ5z1I,19919 +pip/_vendor/rich/_stack.py,sha256=-C8OK7rxn3sIUdVwxZBBpeHhIzX0eI-VM3MemYfaXm0,351 +pip/_vendor/rich/_timer.py,sha256=zelxbT6oPFZnNrwWPpc1ktUeAT-Vc4fuFcRZLQGLtMI,417 +pip/_vendor/rich/_win32_console.py,sha256=P0vxI2fcndym1UU1S37XAzQzQnkyY7YqAKmxm24_gug,22820 +pip/_vendor/rich/_windows.py,sha256=aBwaD_S56SbgopIvayVmpk0Y28uwY2C5Bab1wl3Bp-I,1925 +pip/_vendor/rich/_windows_renderer.py,sha256=t74ZL3xuDCP3nmTp9pH1L5LiI2cakJuQRQleHCJerlk,2783 +pip/_vendor/rich/_wrap.py,sha256=FlSsom5EX0LVkA3KWy34yHnCfLtqX-ZIepXKh-70rpc,3404 +pip/_vendor/rich/abc.py,sha256=ON-E-ZqSSheZ88VrKX2M3PXpFbGEUUZPMa_Af0l-4f0,890 +pip/_vendor/rich/align.py,sha256=sCUkisXkQfoq-IQPyBELfJ8l7LihZJX3HbH8K7Cie-M,10368 +pip/_vendor/rich/ansi.py,sha256=iD6532QYqnBm6hADulKjrV8l8kFJ-9fEVooHJHH3hMg,6906 +pip/_vendor/rich/bar.py,sha256=ldbVHOzKJOnflVNuv1xS7g6dLX2E3wMnXkdPbpzJTcs,3263 +pip/_vendor/rich/box.py,sha256=nr5fYIUghB_iUCEq6y0Z3LlCT8gFPDrzN9u2kn7tJl4,10831 +pip/_vendor/rich/cells.py,sha256=aMmGK4BjXhgE6_JF1ZEGmW3O7mKkE8g84vUnj4Et4To,4780 +pip/_vendor/rich/color.py,sha256=bCRATVdRe5IClJ6Hl62de2PKQ_U4i2MZ4ugjUEg7Tao,18223 +pip/_vendor/rich/color_triplet.py,sha256=3lhQkdJbvWPoLDO-AnYImAWmJvV5dlgYNCVZ97ORaN4,1054 +pip/_vendor/rich/columns.py,sha256=HUX0KcMm9dsKNi11fTbiM_h2iDtl8ySCaVcxlalEzq8,7131 +pip/_vendor/rich/console.py,sha256=deFZIubq2M9A2MCsKFAsFQlWDvcOMsGuUA07QkOaHIw,99173 +pip/_vendor/rich/constrain.py,sha256=1VIPuC8AgtKWrcncQrjBdYqA3JVWysu6jZo1rrh7c7Q,1288 +pip/_vendor/rich/containers.py,sha256=c_56TxcedGYqDepHBMTuZdUIijitAQgnox-Qde0Z1qo,5502 +pip/_vendor/rich/control.py,sha256=DSkHTUQLorfSERAKE_oTAEUFefZnZp4bQb4q8rHbKws,6630 +pip/_vendor/rich/default_styles.py,sha256=-Fe318kMVI_IwciK5POpThcO0-9DYJ67TZAN6DlmlmM,8082 +pip/_vendor/rich/diagnose.py,sha256=an6uouwhKPAlvQhYpNNpGq9EJysfMIOvvCbO3oSoR24,972 +pip/_vendor/rich/emoji.py,sha256=omTF9asaAnsM4yLY94eR_9dgRRSm1lHUszX20D1yYCQ,2501 +pip/_vendor/rich/errors.py,sha256=5pP3Kc5d4QJ_c0KFsxrfyhjiPVe7J1zOqSFbFAzcV-Y,642 +pip/_vendor/rich/file_proxy.py,sha256=Tl9THMDZ-Pk5Wm8sI1gGg_U5DhusmxD-FZ0fUbcU0W0,1683 +pip/_vendor/rich/filesize.py,sha256=9fTLAPCAwHmBXdRv7KZU194jSgNrRb6Wx7RIoBgqeKY,2508 +pip/_vendor/rich/highlighter.py,sha256=6ZAjUcNhBRajBCo9umFUclyi2xL0-55JL7S0vYGUJu4,9585 +pip/_vendor/rich/json.py,sha256=vVEoKdawoJRjAFayPwXkMBPLy7RSTs-f44wSQDR2nJ0,5031 +pip/_vendor/rich/jupyter.py,sha256=QyoKoE_8IdCbrtiSHp9TsTSNyTHY0FO5whE7jOTd9UE,3252 +pip/_vendor/rich/layout.py,sha256=ajkSFAtEVv9EFTcFs-w4uZfft7nEXhNzL7ZVdgrT5rI,14004 +pip/_vendor/rich/live.py,sha256=vUcnJV2LMSK3sQNaILbm0-_B8BpAeiHfcQMAMLfpRe0,14271 +pip/_vendor/rich/live_render.py,sha256=zJtB471jGziBtEwxc54x12wEQtH4BuQr1SA8v9kU82w,3666 +pip/_vendor/rich/logging.py,sha256=uB-cB-3Q4bmXDLLpbOWkmFviw-Fde39zyMV6tKJ2WHQ,11903 +pip/_vendor/rich/markup.py,sha256=3euGKP5s41NCQwaSjTnJxus5iZMHjxpIM0W6fCxra38,8451 +pip/_vendor/rich/measure.py,sha256=HmrIJX8sWRTHbgh8MxEay_83VkqNW_70s8aKP5ZcYI8,5305 +pip/_vendor/rich/padding.py,sha256=kTFGsdGe0os7tXLnHKpwTI90CXEvrceeZGCshmJy5zw,4970 +pip/_vendor/rich/pager.py,sha256=SO_ETBFKbg3n_AgOzXm41Sv36YxXAyI3_R-KOY2_uSc,828 +pip/_vendor/rich/palette.py,sha256=lInvR1ODDT2f3UZMfL1grq7dY_pDdKHw4bdUgOGaM4Y,3396 +pip/_vendor/rich/panel.py,sha256=2Fd1V7e1kHxlPFIusoHY5T7-Cs0RpkrihgVG9ZVqJ4g,10705 +pip/_vendor/rich/pretty.py,sha256=5oIHP_CGWnHEnD0zMdW5qfGC5kHqIKn7zH_eC4crULE,35848 +pip/_vendor/rich/progress.py,sha256=P02xi7T2Ua3qq17o83bkshe4c0v_45cg8VyTj6US6Vg,59715 +pip/_vendor/rich/progress_bar.py,sha256=L4jw8E6Qb_x-jhOrLVhkuMaPmiAhFIl8jHQbWFrKuR8,8164 +pip/_vendor/rich/prompt.py,sha256=wdOn2X8XTJKnLnlw6PoMY7xG4iUPp3ezt4O5gqvpV-E,11304 +pip/_vendor/rich/protocol.py,sha256=5hHHDDNHckdk8iWH5zEbi-zuIVSF5hbU2jIo47R7lTE,1391 +pip/_vendor/rich/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/rich/region.py,sha256=rNT9xZrVZTYIXZC0NYn41CJQwYNbR-KecPOxTgQvB8Y,166 +pip/_vendor/rich/repr.py,sha256=5MZJZmONgC6kud-QW-_m1okXwL2aR6u6y-pUcUCJz28,4431 +pip/_vendor/rich/rule.py,sha256=0fNaS_aERa3UMRc3T5WMpN_sumtDxfaor2y3of1ftBk,4602 +pip/_vendor/rich/scope.py,sha256=TMUU8qo17thyqQCPqjDLYpg_UU1k5qVd-WwiJvnJVas,2843 +pip/_vendor/rich/screen.py,sha256=YoeReESUhx74grqb0mSSb9lghhysWmFHYhsbMVQjXO8,1591 +pip/_vendor/rich/segment.py,sha256=hU1ueeXqI6YeFa08K9DAjlF2QLxcJY9pwZx7RsXavlk,24246 +pip/_vendor/rich/spinner.py,sha256=15koCmF0DQeD8-k28Lpt6X_zJQUlzEhgo_6A6uy47lc,4339 +pip/_vendor/rich/status.py,sha256=kkPph3YeAZBo-X-4wPp8gTqZyU466NLwZBA4PZTTewo,4424 +pip/_vendor/rich/style.py,sha256=3hiocH_4N8vwRm3-8yFWzM7tSwjjEven69XqWasSQwM,27073 +pip/_vendor/rich/styled.py,sha256=eZNnzGrI4ki_54pgY3Oj0T-x3lxdXTYh4_ryDB24wBU,1258 +pip/_vendor/rich/syntax.py,sha256=TnZDuOD4DeHFbkaVEAji1gf8qgAlMU9Boe_GksMGCkk,35475 +pip/_vendor/rich/table.py,sha256=nGEvAZHF4dy1vT9h9Gj9O5qhSQO3ODAxJv0RY1vnIB8,39680 +pip/_vendor/rich/terminal_theme.py,sha256=1j5-ufJfnvlAo5Qsi_ACZiXDmwMXzqgmFByObT9-yJY,3370 +pip/_vendor/rich/text.py,sha256=5rQ3zvNrg5UZKNLecbh7fiw9v3HeFulNVtRY_CBDjjE,47312 +pip/_vendor/rich/theme.py,sha256=belFJogzA0W0HysQabKaHOc3RWH2ko3fQAJhoN-AFdo,3777 +pip/_vendor/rich/themes.py,sha256=0xgTLozfabebYtcJtDdC5QkX5IVUEaviqDUJJh4YVFk,102 +pip/_vendor/rich/traceback.py,sha256=CUpxYLjQWIb6vQQ6O72X0hvDV6caryGqU6UweHgOyCY,29601 +pip/_vendor/rich/tree.py,sha256=meAOUU6sYnoBEOX2ILrPLY9k5bWrWNQKkaiEFvHinXM,9167 +pip/_vendor/tomli/__init__.py,sha256=JhUwV66DB1g4Hvt1UQCVMdfCu-IgAV8FXmvDU9onxd4,396 +pip/_vendor/tomli/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/tomli/__pycache__/_parser.cpython-312.pyc,, +pip/_vendor/tomli/__pycache__/_re.cpython-312.pyc,, +pip/_vendor/tomli/__pycache__/_types.cpython-312.pyc,, +pip/_vendor/tomli/_parser.py,sha256=g9-ENaALS-B8dokYpCuzUFalWlog7T-SIYMjLZSWrtM,22633 +pip/_vendor/tomli/_re.py,sha256=dbjg5ChZT23Ka9z9DHOXfdtSpPwUfdgMXnj8NOoly-w,2943 +pip/_vendor/tomli/_types.py,sha256=-GTG2VUqkpxwMqzmVO4F7ybKddIbAnuAHXfmWQcTi3Q,254 +pip/_vendor/tomli/py.typed,sha256=8PjyZ1aVoQpRVvt71muvuq5qE-jTFZkK-GLHkhdebmc,26 +pip/_vendor/truststore/__init__.py,sha256=WIDeyzWm7EVX44g354M25vpRXbeY1lsPH6EmUJUcq4o,1264 +pip/_vendor/truststore/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/truststore/__pycache__/_api.cpython-312.pyc,, +pip/_vendor/truststore/__pycache__/_macos.cpython-312.pyc,, +pip/_vendor/truststore/__pycache__/_openssl.cpython-312.pyc,, +pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-312.pyc,, +pip/_vendor/truststore/__pycache__/_windows.cpython-312.pyc,, +pip/_vendor/truststore/_api.py,sha256=GeXRNTlxPZ3kif4kNoh6JY0oE4QRzTGcgXr6l_X_Gk0,10555 +pip/_vendor/truststore/_macos.py,sha256=nZlLkOmszUE0g6ryRwBVGY5COzPyudcsiJtDWarM5LQ,20503 +pip/_vendor/truststore/_openssl.py,sha256=LLUZ7ZGaio-i5dpKKjKCSeSufmn6T8pi9lDcFnvSyq0,2324 +pip/_vendor/truststore/_ssl_constants.py,sha256=NUD4fVKdSD02ri7-db0tnO0VqLP9aHuzmStcW7tAl08,1130 +pip/_vendor/truststore/_windows.py,sha256=rAHyKYD8M7t-bXfG8VgOVa3TpfhVhbt4rZQlO45YuP8,17993 +pip/_vendor/truststore/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/typing_extensions.py,sha256=78hFl0HpDY-ylHUVCnWdU5nTHxUP2-S-3wEZk6CQmLk,134499 +pip/_vendor/urllib3/__init__.py,sha256=iXLcYiJySn0GNbWOOZDDApgBL1JgP44EZ8i1760S8Mc,3333 +pip/_vendor/urllib3/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/urllib3/__pycache__/_collections.cpython-312.pyc,, +pip/_vendor/urllib3/__pycache__/_version.cpython-312.pyc,, +pip/_vendor/urllib3/__pycache__/connection.cpython-312.pyc,, +pip/_vendor/urllib3/__pycache__/connectionpool.cpython-312.pyc,, +pip/_vendor/urllib3/__pycache__/exceptions.cpython-312.pyc,, +pip/_vendor/urllib3/__pycache__/fields.cpython-312.pyc,, +pip/_vendor/urllib3/__pycache__/filepost.cpython-312.pyc,, +pip/_vendor/urllib3/__pycache__/poolmanager.cpython-312.pyc,, +pip/_vendor/urllib3/__pycache__/request.cpython-312.pyc,, +pip/_vendor/urllib3/__pycache__/response.cpython-312.pyc,, +pip/_vendor/urllib3/_collections.py,sha256=pyASJJhW7wdOpqJj9QJA8FyGRfr8E8uUUhqUvhF0728,11372 +pip/_vendor/urllib3/_version.py,sha256=t9wGB6ooOTXXgiY66K1m6BZS1CJyXHAU8EoWDTe6Shk,64 +pip/_vendor/urllib3/connection.py,sha256=ttIA909BrbTUzwkqEe_TzZVh4JOOj7g61Ysei2mrwGg,20314 +pip/_vendor/urllib3/connectionpool.py,sha256=e2eiAwNbFNCKxj4bwDKNK-w7HIdSz3OmMxU_TIt-evQ,40408 +pip/_vendor/urllib3/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-312.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-312.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-312.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-312.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-312.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-312.pyc,, +pip/_vendor/urllib3/contrib/_appengine_environ.py,sha256=bDbyOEhW2CKLJcQqAKAyrEHN-aklsyHFKq6vF8ZFsmk,957 +pip/_vendor/urllib3/contrib/_securetransport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-312.pyc,, +pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-312.pyc,, +pip/_vendor/urllib3/contrib/_securetransport/bindings.py,sha256=4Xk64qIkPBt09A5q-RIFUuDhNc9mXilVapm7WnYnzRw,17632 +pip/_vendor/urllib3/contrib/_securetransport/low_level.py,sha256=B2JBB2_NRP02xK6DCa1Pa9IuxrPwxzDzZbixQkb7U9M,13922 +pip/_vendor/urllib3/contrib/appengine.py,sha256=VR68eAVE137lxTgjBDwCna5UiBZTOKa01Aj_-5BaCz4,11036 +pip/_vendor/urllib3/contrib/ntlmpool.py,sha256=NlfkW7WMdW8ziqudopjHoW299og1BTWi0IeIibquFwk,4528 +pip/_vendor/urllib3/contrib/pyopenssl.py,sha256=hDJh4MhyY_p-oKlFcYcQaVQRDv6GMmBGuW9yjxyeejM,17081 +pip/_vendor/urllib3/contrib/securetransport.py,sha256=Fef1IIUUFHqpevzXiDPbIGkDKchY2FVKeVeLGR1Qq3g,34446 +pip/_vendor/urllib3/contrib/socks.py,sha256=aRi9eWXo9ZEb95XUxef4Z21CFlnnjbEiAo9HOseoMt4,7097 +pip/_vendor/urllib3/exceptions.py,sha256=0Mnno3KHTNfXRfY7638NufOPkUb6mXOm-Lqj-4x2w8A,8217 +pip/_vendor/urllib3/fields.py,sha256=kvLDCg_JmH1lLjUUEY_FLS8UhY7hBvDPuVETbY8mdrM,8579 +pip/_vendor/urllib3/filepost.py,sha256=5b_qqgRHVlL7uLtdAYBzBh-GHmU5AfJVt_2N0XS3PeY,2440 +pip/_vendor/urllib3/packages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/urllib3/packages/__pycache__/six.cpython-312.pyc,, +pip/_vendor/urllib3/packages/backports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-312.pyc,, +pip/_vendor/urllib3/packages/backports/__pycache__/weakref_finalize.cpython-312.pyc,, +pip/_vendor/urllib3/packages/backports/makefile.py,sha256=nbzt3i0agPVP07jqqgjhaYjMmuAi_W5E0EywZivVO8E,1417 +pip/_vendor/urllib3/packages/backports/weakref_finalize.py,sha256=tRCal5OAhNSRyb0DhHp-38AtIlCsRP8BxF3NX-6rqIA,5343 +pip/_vendor/urllib3/packages/six.py,sha256=b9LM0wBXv7E7SrbCjAm4wwN-hrH-iNxv18LgWNMMKPo,34665 +pip/_vendor/urllib3/poolmanager.py,sha256=aWyhXRtNO4JUnCSVVqKTKQd8EXTvUm1VN9pgs2bcONo,19990 +pip/_vendor/urllib3/request.py,sha256=YTWFNr7QIwh7E1W9dde9LM77v2VWTJ5V78XuTTw7D1A,6691 +pip/_vendor/urllib3/response.py,sha256=fmDJAFkG71uFTn-sVSTh2Iw0WmcXQYqkbRjihvwBjU8,30641 +pip/_vendor/urllib3/util/__init__.py,sha256=JEmSmmqqLyaw8P51gUImZh8Gwg9i1zSe-DoqAitn2nc,1155 +pip/_vendor/urllib3/util/__pycache__/__init__.cpython-312.pyc,, +pip/_vendor/urllib3/util/__pycache__/connection.cpython-312.pyc,, +pip/_vendor/urllib3/util/__pycache__/proxy.cpython-312.pyc,, +pip/_vendor/urllib3/util/__pycache__/queue.cpython-312.pyc,, +pip/_vendor/urllib3/util/__pycache__/request.cpython-312.pyc,, +pip/_vendor/urllib3/util/__pycache__/response.cpython-312.pyc,, +pip/_vendor/urllib3/util/__pycache__/retry.cpython-312.pyc,, +pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-312.pyc,, +pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-312.pyc,, +pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-312.pyc,, +pip/_vendor/urllib3/util/__pycache__/timeout.cpython-312.pyc,, +pip/_vendor/urllib3/util/__pycache__/url.cpython-312.pyc,, +pip/_vendor/urllib3/util/__pycache__/wait.cpython-312.pyc,, +pip/_vendor/urllib3/util/connection.py,sha256=5Lx2B1PW29KxBn2T0xkN1CBgRBa3gGVJBKoQoRogEVk,4901 +pip/_vendor/urllib3/util/proxy.py,sha256=zUvPPCJrp6dOF0N4GAVbOcl6o-4uXKSrGiTkkr5vUS4,1605 +pip/_vendor/urllib3/util/queue.py,sha256=nRgX8_eX-_VkvxoX096QWoz8Ps0QHUAExILCY_7PncM,498 +pip/_vendor/urllib3/util/request.py,sha256=C0OUt2tcU6LRiQJ7YYNP9GvPrSvl7ziIBekQ-5nlBZk,3997 +pip/_vendor/urllib3/util/response.py,sha256=GJpg3Egi9qaJXRwBh5wv-MNuRWan5BIu40oReoxWP28,3510 +pip/_vendor/urllib3/util/retry.py,sha256=6ENvOZ8PBDzh8kgixpql9lIrb2dxH-k7ZmBanJF2Ng4,22050 +pip/_vendor/urllib3/util/ssl_.py,sha256=QDuuTxPSCj1rYtZ4xpD7Ux-r20TD50aHyqKyhQ7Bq4A,17460 +pip/_vendor/urllib3/util/ssl_match_hostname.py,sha256=Ir4cZVEjmAk8gUAIHWSi7wtOO83UCYABY2xFD1Ql_WA,5758 +pip/_vendor/urllib3/util/ssltransport.py,sha256=NA-u5rMTrDFDFC8QzRKUEKMG0561hOD4qBTr3Z4pv6E,6895 +pip/_vendor/urllib3/util/timeout.py,sha256=cwq4dMk87mJHSBktK1miYJ-85G-3T3RmT20v7SFCpno,10168 +pip/_vendor/urllib3/util/url.py,sha256=lCAE7M5myA8EDdW0sJuyyZhVB9K_j38ljWhHAnFaWoE,14296 +pip/_vendor/urllib3/util/wait.py,sha256=fOX0_faozG2P7iVojQoE1mbydweNyTcm-hXEfFrTtLI,5403 +pip/_vendor/vendor.txt,sha256=43152uDtpsunEE29vmLqqKZUosdrbvzIFkzscLB55Cg,332 +pip/py.typed,sha256=EBVvvPRTn_eIpz5e5QztSCdrMX7Qwd7VP93RSoIlZ2I,286 diff --git a/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/REQUESTED b/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/WHEEL b/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/WHEEL new file mode 100644 index 0000000..da25d7b --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: setuptools (75.2.0) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/entry_points.txt b/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/entry_points.txt new file mode 100644 index 0000000..25fcf7e --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/entry_points.txt @@ -0,0 +1,3 @@ +[console_scripts] +pip = pip._internal.cli.main:main +pip3 = pip._internal.cli.main:main diff --git a/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/top_level.txt b/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/top_level.txt new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip-24.3.1.dist-info/top_level.txt @@ -0,0 +1 @@ +pip diff --git a/backend/.venv/Lib/site-packages/pip/__init__.py b/backend/.venv/Lib/site-packages/pip/__init__.py new file mode 100644 index 0000000..efefccf --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/__init__.py @@ -0,0 +1,13 @@ +from typing import List, Optional + +__version__ = "24.3.1" + + +def main(args: Optional[List[str]] = None) -> int: + """This is an internal API only meant for use by pip's own console scripts. + + For additional details, see https://github.com/pypa/pip/issues/7498. + """ + from pip._internal.utils.entrypoints import _wrapper + + return _wrapper(args) diff --git a/backend/.venv/Lib/site-packages/pip/__main__.py b/backend/.venv/Lib/site-packages/pip/__main__.py new file mode 100644 index 0000000..5991326 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/__main__.py @@ -0,0 +1,24 @@ +import os +import sys + +# Remove '' and current working directory from the first entry +# of sys.path, if present to avoid using current directory +# in pip commands check, freeze, install, list and show, +# when invoked as python -m pip +if sys.path[0] in ("", os.getcwd()): + sys.path.pop(0) + +# If we are running from a wheel, add the wheel to sys.path +# This allows the usage python pip-*.whl/pip install pip-*.whl +if __package__ == "": + # __file__ is pip-*.whl/pip/__main__.py + # first dirname call strips of '/__main__.py', second strips off '/pip' + # Resulting path is the name of the wheel itself + # Add that to sys.path so we can import pip + path = os.path.dirname(os.path.dirname(__file__)) + sys.path.insert(0, path) + +if __name__ == "__main__": + from pip._internal.cli.main import main as _main + + sys.exit(_main()) diff --git a/backend/.venv/Lib/site-packages/pip/__pip-runner__.py b/backend/.venv/Lib/site-packages/pip/__pip-runner__.py new file mode 100644 index 0000000..c633787 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/__pip-runner__.py @@ -0,0 +1,50 @@ +"""Execute exactly this copy of pip, within a different environment. + +This file is named as it is, to ensure that this module can't be imported via +an import statement. +""" + +# /!\ This version compatibility check section must be Python 2 compatible. /!\ + +import sys + +# Copied from pyproject.toml +PYTHON_REQUIRES = (3, 8) + + +def version_str(version): # type: ignore + return ".".join(str(v) for v in version) + + +if sys.version_info[:2] < PYTHON_REQUIRES: + raise SystemExit( + "This version of pip does not support python {} (requires >={}).".format( + version_str(sys.version_info[:2]), version_str(PYTHON_REQUIRES) + ) + ) + +# From here on, we can use Python 3 features, but the syntax must remain +# Python 2 compatible. + +import runpy # noqa: E402 +from importlib.machinery import PathFinder # noqa: E402 +from os.path import dirname # noqa: E402 + +PIP_SOURCES_ROOT = dirname(dirname(__file__)) + + +class PipImportRedirectingFinder: + @classmethod + def find_spec(self, fullname, path=None, target=None): # type: ignore + if fullname != "pip": + return None + + spec = PathFinder.find_spec(fullname, [PIP_SOURCES_ROOT], target) + assert spec, (PIP_SOURCES_ROOT, fullname) + return spec + + +sys.meta_path.insert(0, PipImportRedirectingFinder()) + +assert __name__ == "__main__", "Cannot run __pip-runner__.py as a non-main module" +runpy.run_module("pip", run_name="__main__", alter_sys=True) diff --git a/backend/.venv/Lib/site-packages/pip/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..db7be5e73f539dc6414e3697d64ec7dfc4ca6793 GIT binary patch literal 689 zcmX|9L5mYH6i#NQ)7rX<3c`BO=tT;426a()(FIWiVO^E=R0oE1l5Jz#Oh_`Vv#hWO z4}uqOyZ!^kpW;QYb5Zf+ZKZng&i99r!l znO%cq7cs=}2#s+UkG-yk5%an}tFwT69P?liFwR+x*ERzdzN~e_(r-6@IFhzk1#80C zs_{@+kxM$-3a>0hSEI}8RX}y$RH5d!&@zJ_{+kb(^VwMlppTj7^j~0%JhY9s(T4-{ z25S3TyH5tf5Li?aAuZRSLT*30PjWdb$(U1V$!4xeVL0iPLCi083u%Sycd}gbq(`$Mmn?}UTuzcT(Myc5yaNY@w9ifAnoL1k*ffn) zSp{P%q;3I!2yRY5*g?OWsJ8sAb?VLC*Q=j`#TjhE9oF0RDzv2nE$s%Q0|-?sO($F% z7;BnVzOlOU;SO`g_edXgIQNfLjho|~6(hc?PeSQNXW9_tx7VI7}& Z^?Wbb+jx8A^YIJ&2K{RJe^x?hQBN{~DZU|+1Qd+;Nj*aS5m=Er;Le=g!$?K! zlT4t`U5G$HV?=6Q0dVhgjWawLxgqoP`X9_hq!i`4^beoorxk{n0G0aE5Ob#~A|E@w z#HWYNbURbeBH*(@#`NEJc|9A=C(=d`paA7#zXbgr1C~_Pwx(OEnnw%^lpkY~?J?O4 zJcb?3f6C%b>NnO1lO5Y(8C7+(MoVi_Rb>gHyO!3bqRWbIic(y+JnH(QB2IW^($Srw zs#`wgT(j6P^`g*m#d~0}V|9kft zhV4>inOmS1QHmXEb(E^Uta!Rl3nOQq!X>XpA69e%mb}@v$*M_jyOUf&{CV#kUj{Nl z=m1g&kRD_KCpOC6^5#PKMmQG+p}QTt3EsZ=e17(eJo}v=E_IhSs@-Zh{;D=e0zMaB z-jgQ=X~>Rkm3pPEO0V*MZnv~k+O6zVK9u)o=Jzw#*6&0&Yu#G75c*&7#X~u>`Fu~F c`hn*Uadv%CH10io{rDTcFh~HNb|<*CKidGeDgXcg literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/__pycache__/__pip-runner__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/__pycache__/__pip-runner__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e6558b7da90ba74080ff37c840761259a61bca43 GIT binary patch literal 2207 zcmaJ>O-vhC5T3WY{>QNsLm;GSHcFb}3Y(IqN)!=Nm6C*{1p-7>U8>cx`wVOBU1xVq zFae1oq^44(a;OTuC6_8Gt<+=ZSwR>>~tV^;$Qqk)rh+9+t@nq>Ijs%WPI-H{#mM&Y%0=OS+VnF(Vo&Q zQ89{T(a4HLt=K8v)bO7!%A%@ev(%)zEmD0(GY!3f`*b)w#!RwWo{G5Ya)GL%Y>AqU zVy9>uc-ktN6g|tf>%L&9B|NRj`m44$fo6rGVcKXmqsd`eZ^)u$%QkiI*k(ZwCb?}E z{Wb%H(s((h00BRyshvWGNFuqtTKvaI<(6R{-T|*x-V2RFk{@(P`UQ_~pi$l9RUqhf z9zKczED(lPm*$D*<4dwi2z<6*fHHi?-y}&gm?REw*=CY+xb*7|nXwqCMDg$U`_7Hu zG|XwMC@XYa&)HT=RurS8+nPR^QVf%hPsqwN)z$Iz3>JF)U2S6A(rlVSgK2q^TI2XE zU6O=6WtMcEnv#?*mYq<~B-QC`(d?ajd4`&nX6OBpe}UXgaQehC_?xE}9YKPGrv|CRPU6XSE_* zgssTF&(D5(c7wUDCOWH;&Wg}kLltbZGR$45W2WJtfizJyDB{PkMXOX~fDnsid&E}1Tf+wx>$QI#AB(YL@5P4}U(fV8L&}QuTM(p^V%MZIQRMKz#c(NKB zxGg-2B`U%0hX+sI3szdXtHJKu_Es!$J7O{zVp@Y3Zcvg~n3Cj#CCMERxNnlA8zs4( z07?-hFI!fDA|}*&u=kPN!dcY?ig`2m61DnC&jo|R3rq(rnv#n#Jt>fN-d&eqmoz|$)kLZS@jv`Q()<*V?HmLmd=mXQ zx(Ur2(7bYOqwQ3+?es%<^GP7Ka_&LkNCieJM@Op214p(XzUbS8_y)vRTJE%eZ~qKE H^^E@kz^*2s literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/__init__.py b/backend/.venv/Lib/site-packages/pip/_internal/__init__.py new file mode 100644 index 0000000..1a5b7f8 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/__init__.py @@ -0,0 +1,18 @@ +from typing import List, Optional + +from pip._internal.utils import _log + +# init_logging() must be called before any call to logging.getLogger() +# which happens at import of most modules. +_log.init_logging() + + +def main(args: Optional[List[str]] = None) -> int: + """This is preserved for old console scripts that may still be referencing + it. + + For additional details, see https://github.com/pypa/pip/issues/7498. + """ + from pip._internal.utils.entrypoints import _wrapper + + return _wrapper(args) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..552aaf8bf546857a0c8f9354ba1b9a3f72d1019e GIT binary patch literal 789 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

JN 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/__pycache__/cache.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/__pycache__/cache.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f72f3b2a190c59efd9831db9ce661e336e5960d7 GIT binary patch literal 12669 zcmcIqTW}lKdENyUAZ{dh0V#r_sHI3sghauTEL)fQrVDj(B>EybvJs^yh+R^kaA9^A zqKJW9Ipa*IR*9&#sp!dr={8eSqjaK7JFPm?2giA++r9vzT+$nQqPFgI{LmTLq{puN z((gaJSb!AdIGyPk@|?40&p9}k|MLC+zyDlc@8OV6e(TA^YyBMe@AObk4zsc>@f>%9 zleh>c@scgcM|f7+A~sgqBX(8_5doz==}0*vPM-P-$-0y);!3$A?vy9uNqHk)*6v99 zQuUGgR70d8<&XGTn={#%YKko8byqTwYK^qAx;xpHS{GTz>YikKDi{f} zx;NR8S|3@T>Wp-jPb2d)4k3Ci1P^FZ`Ti6q&NVilU*(5c{Zn;P98L(JV6 zjqhh|L9}&LjSo%QLhEx)hhp(_vUoCQ+)6Rti-F_fFsSAe_ zaZMLaBvegzJvXi;GU-?{WY_JdW21UwBCW~FxFREurei5tZ>es%AS){RW6Gv@ES*Uw z;<02RC$pYt3>;5iK!bGVoGd4gB$6`CfOhxcgd)eamy{$e=0qZW9;Jiz3fc7f({gIu z=#fz-^?D7DQbLKIPoyOk9lhgNeN@Xtvr01O%_xb{L^?dCX3{z@=}s&)tEA)Rov;&i zBB!%mo z9o;FX;~7cT-RIL5vABFTJ*KJKWAS(< zo7NKP(e3e!BA*?O#m~!W>1_CdoW5}OL}K`?n$YC!7;qkxsGc29j6V`(R0KkMBu-Qs z9-q`bQCd%w_NnyZ$2#z@?m>2$`^e?H=DFgT-Z?AW?s%{Fp6j{G2bR3e*Pgoa)J*rA z{crTo?wRk{Ht!u+@IGGjK0fc=TM+gxV<;D=tejkCWqBHv?}HL#4)TX1*#o&_lLg5x z2_wQ3H^NJf*L@L(^`YH5*UGrpg0Q!K)W$bOl4I~9G1n58m4;>k7W{RSrR7_+PMnN>vm{~A>F5D zhs!)Osn9MILMtEBDSu2y`Z1kGs7?={dz7ZgWVPss5*sDW35iIeiRnLqs(Nend{)28 z#7u&P9Li42syvEJcSA-;*)DV^O(9FVgFUK5+r+LSqei_oIx1^XgBh8oW4&_gP5P|$ zavNq)Zz8+Qm3&;=`kBKEosSheA1eeNpK>pH{Uj(0-oClspM`FQ3R|CE>>v1<`=)#9 z__TB*eLY?D^`X;(x9_gE53d&b4;K3m;w8OUY2ZTp=KJ?gxeLv`MOWX_wx{N|Jws1h zimv_@AJ^PDb9}yO^OUpX;hNiLY%@*M9W&pYJun-a`PSU#+fBE3&TYGW;ZE$%@azCSSKGkB!U0u4ABrXAQB$B8@3iB5+}o)RiIAPZ{oj1NLobwTpjSj|o{$j1?t zDYjAW6pgB$)112^aV`n}2YF>Fc%`ojATSVIUc6D}t)7RuYmPWp6t{gF^mfUScjSc; z+jZMjmw>iQj#C`1HV&yrPZON76*GjKhWKitt7jAei615LqHM=&C5()O9_U-IO9IBB zf-x59DF>-TJStaskL}*f>-=xCw`&{cP`YSh|z%X?J*=26A zQ+#vijiEyO*1PSe3%iaL!pErc{OR|OP1S$kZC`9@ojQKs-?HHEEBgCprFs9hDPhT5 ze{Ii|J=dPR^5jh5p0{gh&%VFS{XF+h@4Y=o=Ua{y_Z*!IO}{cL+zs><_8cv?94q*a zE&7|L-2eTloeLc2*}8wx<2~@Guu9evUo)y{L!}z>m8H{n`4FFb%mQ4NY!I~!&=+8g zAwnb(&?Tjci8NEQbm-xmyxuaD(T=CalMGkO(x9Sbl$*B7k(+4AP%nqEgxosg_#U{z zZ{np&vJ)t$p?kier{L-_n8R1i5_$vl-8i70EJd~0s2UeAq@2FqW@E-?RWZge0&O%_ zy-6`Kg3XHZMNp7BAZCCMl!=52z`#(cN`QeO1tODipc2Shb{;!wPU5h&j4eNX+z&@xp^0h^N-npf_kKfj$$_%u z;b@b%of*WQ|z2Ppo>B+-+8b0@;#)yZlG>%1D$-=(Bho;{G`x2HV)LUnw zUf^DaVBN5CJylqi;a!GheNft7z426n_=DMW?4EO*4;a)&N_>J0LIb&uWMQw#U@+J` z$)p-)vhJ%8XfHNU8-Z5jInPa+veTxJax^Gn2Wl!wh1JL}xOS-)2u#p`Mr2=9K;TU9 zeUn3(USB13h{kCCxnWWe3m=r@u`J{Q2?$w?;s0dyg~rm8VkQmaRe~TH z5GUla?E-OQiCIf#Knlf~p8~U`Km`LLR1!^{7ULP%ut^i_StIGE(qb}`fjeMS%#K?# z8Pl9gXll5!)-!;I>EtAlm&|Y@29Y$!&*C@CpN8PW!=!jFb^(h`VsiD!JA|J!{q#7-ZjVAhF8<{wlh@V4SLIrqFCe2$h=r3%oN_QG9K-Em3lYLhO zfCPg7A$yhbc?KO!b~n@xll-|&53u_KN;yd*$=3%w-NiMvE;Mc}Hg28UJ>R%v%CYEg zx%TQGyjpN=n0oaif77*zD-+l9SMoE53H{6+EBK$hoxSUSvfz5s5XF`bT&1&#eVM5E z2qNMJU?0pKn+k*NRF!|K%3yLl48rCeWpChN?%P0OXTjZ(r<*&Y! z7si^Z-x_s{BzM!AR2hlisvEK9!Ea3pTwX9wt+hO?0=LiNgfF@2G_-Z)w;CxemNfD( zu{73Mu2sshjg@-2maoG}652v4@1|Uy;(9pE64bq%0wd%V?&?2Ha2M^ba1(sUHk3Pa zd^8Q84Ym+fRg~hqzt?|Bp*^SjWLD{R5lKO4-gkIjglD7k}pss@PpCe zP@_T+(ttN~_KFXgE--`Dnaqri!d2ps}dN z3)JG#%Xp)L!iXzj<+e|G{?)&Jv1Q%VH$Lj#b^D3=?q>?FuEoC4Lf^h(-@ZG&g=fC` zFMVf zU|TV;ZEk2j@H>k%a6_q1XlnkCYC=0DlRHFg+l?b$q=`}3!ZE^&&V+CM$H zZf@|=LmB+Y1|EC;ZAN-)Py<|uErAn-G%X_HD z_RAjkp+_9Q4D-lC^~#HAS58rOnzENDBLkxf5Fe&T27VbdCNabiuyTfKFC(i)y#&k^ z%0}pggbb+n17Sx=-~m;EU{Mg}MNx7#JDwu+ih|H9ic){bafD~^l`2*El|5DfEPFH% zEL9D;Nk1FMzm-T_Qd;gs_5g&nGqX*fl1DEle?4Kz($Sha@!^jT9$T2B|9J+^5*I-&xCJlF=2i|EFvKrpQRqiZeJw`7V znBIr( z0pJND7M8|HDXd8tZ)xDlD@Nt!j>^=DJzBe(1f@c6l9z@h=*;;Ce3n!w=}UZ^ra)KjcnfwPmYVlyr7bEdo1OgFrtxpQ$ry?yKyCp73xl-pF&rxyQw$x*y&C2En85#g1MS{>5#N zpztnr!;klN;;qEO=6%J@`{uj%FLWO$b|1KR_;j)RG-+dR_ky>-=YJCk zwk&k*EOzZ&3~XHp>@Eg&-x)0gcFzZnEZc1xo2P{zc}ot?x9tlEgTRJQIVXldEjL_m zSPY!R80h31C$FQ{`nlWD)cgsD?0-tov&~eoG0x^wZ25*t^=H8P&rlMm=rW@5)g zG9ke+jJgb~{4|+)>{*0D%1jv8cND=+c_a%BB}y_L;FAWx9jLNFWm4p(5gI2|?jh6& zD2ZUH7>98mgO8TkmzbZx^9X{{FnpoN$%19xsOsThWkuBt^YS`v63;tb2|E}A+=lv9(Wn1|F zTm99Cu3le9t2J(FRoo`GY0Zvm^!YVS`$Nk5D6`D0RbB)uICczu9`0}iuCSNCBcibC zW#(sq4Q}aS3^$W?ExMmp&sZ(WbRbi6t2B+ZDBWAtPhF#6Uck(`hSfX%H?*mbAY-=N zy7dcfTZ?V*u-xvv^Xh!t(3E%4+g9*)F^g%@-?8A|SoCi!xHcMhX)1ZPV(SRr!Q*d7 ziF7PK<*N@S&u4k1zKV|p$%YSs%wuA4#9C0CIAKj9r^wfsU8tUY(h+jz{-zS9VN!CC z!4Kw3{5pXf02L+}NjMI{Qy6C7e6ZUQ4I~450H0|wQ^#<`QG`pJfa_tE#H`>~Yd(Bu z!U$DXVy2U>;+=!%jf6ynPEUt;hD44GAtJ;$oan&Nti&=8Atd^K3*U^brJ+B4Af4-pR& zn}5&Hf0ZxJ@+VcSMuyAbx*sDFUz5tZT1f(zTb4mB8vx_IYX;-77A|KtfMpd_#sF*A zXl35P?HZvdmTLL)2&vZ^o2SoDYRp+d?{0+hYuOVRXL<6_WvRfj z=!RwS)$4^17B+;*&J`Qt>QTd%sInm(L&^jepj(Ie>T+pap-)#CaJIC??_?Ie6&Gv+75}As;hu6k<1p zz6WEri}L$ayG+?*l#!*Pe3!DSM zd)|!z`Soo}!A*wmVeVTC+Yc7EAAIjYBN< zuyJ>B#5kH51HmeTvK<6o?7S!45%D{}Y!z{Z;94)MWH`VQ{o-reawwBG*i{&k1i z?7wVtpdM;jYwWy42U^P&I884|fEb~2ay}XUKxP7w*u}R~8qjz=CF7$g$++tuQ@1me zy^O5dV|axcDJ#$m9T|(03y72Z?2fPzCl4EO@^Hz+JNA*!5C!=RQIwoiM~EE7?Nerx z+aa1kaIwmXh}Km>aFGSUmk|UPOKlyF02_j`Y6v}5+>Z1FuVeG{)}njEvX>tBa?a+G zt=;h~KL_t7m3I zga(o-iwEfKtVj7%+pt`ABdA7vVB_l7__P8+`EbQ!VE810HG7ez#R3H8ime|pXPF?E zt3t5|y>s;hY<*$Ny;yNWu34?o4~`2}AtA220Y^`;P=-O=Ou#T1#OS)0&SeW_WHd1| z$p9OSBEL^BqGPu`y{u3L|3(HQ9_y3CX{)%h(73cnt zYyUMjFwYJAC-*{;d*MTF-+yrXKI9(zklXqpH}Gq2@I!9LeRs#yx&?Pf(cLk#ci!E5 z*?GT3EO3n_r=8z7-8-$$9Gbp(J&eyp_U43ftBH0z?XhVgLXD literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/__pycache__/configuration.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/__pycache__/configuration.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6115941edf650988a7b5a4d022207621d765fdc3 GIT binary patch literal 17634 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/__pycache__/pyproject.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/__pycache__/pyproject.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8adb5ea0d9369fd97efb9e556f7eccb5ce9b7af1 GIT binary patch literal 5120 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 C;yn%k literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d6d882391b2dbdd33e86536fc0196e43c120bd07 GIT binary patch literal 13617 zcmb_CX>c3ob-TD0H$VaeFOgh{q(txlDayL2qtYxs#d5V|PZLb{cu69a~8g+tYXg2uumDsal=3)AmO)!}NAXA-`oKkQG|glkCIng}Fo!?nq}a2+Yz67|W3a0AKP6OG9=;WZ@h zNHisz!_6e`Otd7~FiY~T#M5$`EZiEX+fC{em?kLy$+B`Ylpj^gHhw4K1WYYZyNA@Wd^KR&F=XM^ zLfu|cw+=_-3{ck!b^AzN8`QPKsOw>VI}i)ELCZ0N$|4i z@wh0-)?;H*Je`UrWb?`Ku>>D9$W^guDxHeQqKSBhkEEhWUiPo3I>!ql^Z`)!;nX<* zoRk09GdqT)zo2qq0+4aw+PJ|gnc_?VPV zC&WlB!ADb(s4y%-s|U6;5fR7Fj0x!&FJhJJB%d7H58o*U-xP;;j76o9h?I_u3kfJ1 z&&9+{bH~@CJ(<3q?UB&wu3%5Ow6?1UDr8!eEdq=wq+;sX#jj17;ctZh-QDn-qa?je zQqL(xjUvpdCrfD@Kub?hK{_+Kp9jiG##1~}n>4};EWB9!AV7eLbo#8wCgNv#HkxAj z;o(R;HIxq7?JPV4V^JZRWW@pYWVwfwW}#Z-L+pXja0tjb-P0f1NZ^A;*>ncBPj*H$ zOc8;XEg~O<6A+|@W|*>w%V9rzcHh9M^J(F%I2MiZr&6Pm*b|M#(&H%!rqvTm3;d}w z(b!o&#hnVB<5TBOJsv-EN{mZ<4|F&i9p=STWAU+Gm@cdijzOoGw)IB@p^!~`X=xxn=Td(dZc-I#k8*-)%ccGP%jROBo*`DHg zPNB@0zWvZ@fkm8C`@UHu63Bn>Ug`>7y8YnFx&fmp~h%4oTA${C=qwOrP6 z8oQ<`z)r&$Mt~!NR)bJdQ5oI2vKC8%6MDEmUw?v{GzLwXy~hbr>huDX@%h8WiX-Xq z1jnA?2|JTm_!4P0s<5=s!A!@Av+=Ppq_K9fo8`uN7Ml|SALS;Ylg|A@Cxcem4xb7c zB;b&(aZ%ZC*#f6_m=|Od(xhx6tj8{<$Ay@3gsmD=kQ-HYBu2(2;gF8Pv5aVqL4&XX z*W3Xw5kCdX3T=?cu86XP2q7AwAL@D#=Iij9rb>3o>iF)3=P%sx_=}AFyV>WnA2@23 zoYj|(UOZa#4ivqLywc#Yvs&p7971fQ|}kd?4Mwm2c1C?X}!V;R8I%){i;Wp zg&q~^M=h%Wp(uO{U_W0?35Fxo^A9-tB59LsTDMAP_W?7gaF#V@KLxx%!JMT>HRW0x z0@4Ry^ezKYvjACPzceZYeq$h9t-=ne<5%82-{(hqO|3cw<4qZ+j8csTlQn4TQpO7! zGw%}_vzj%j%%=i>0@VkZlL!Ku=YTsAu{VYa59lZoG)6GUjaUA62FaccF z!p225dM+AIp#A}1DUMyiIXZ#_7w8i#r^#AQ zO$ktmWDBr9P#lCNtRni8Dg()J5n+~~(^=HC9)RP?8`YbyVbKBfyCGHBsiTVvS^LgagnRhQIh%@B-H8Mb-!m zaemX4-G9Ct7$kDKiRULS@0&X`duZ<14~~^Al)rXv=MQ$~tSvcDOVLw(>B0*aa@MAq z3rm6e#Xw&^(0ASUi@G=Je$nzqOChjl#_@rtA!luv`Bu>pSakH|9a{UEH`d$`-@5ST zg$2i8(N~Ln)#1Lh?S*aA$7Z&vTzJvDHt$_q@U}j8czXX#>k?Bx-?qTOus)cGvx=|| z*`cTiWJxPzIm&S&%l{EFEBG&6@g%4U*%Zp>2cH6i&>`tky{w!GO>jQ-vkwERPi0)M zX=53)#uF6ubZGG9^vm=FMUYdE4r+hpW59wr0xCP`@=;+@ISDMN$BJHy!dw8s4Lwjs zECcc0id>kX(fp0nw9DDiMmW#VURb2zzCNO0L2| zLGCZZ3R zz)yBv^DQ*?6#XrW{*8J6#_O%W=y;=};NLN0Lkg&?vcJ1>^yp)bO%_18S_)?`6YJP1-2W(~>TQBoyf6$?CHK z4zEg?DU+njhOBASufdj64d;|us?}<ASFQ!-Ri}+yPNytc z%d|sk)M~h8tG7`SvT^ccE!teCm@HGS=k)rsr(mBuB|JMykBa*sp@K*rZSO?SveB6= zuE+XQqc+;}^dvP&wNerqUgT+`gessdbJp@Q^;5%?wcI;vE%!Q4O&Fh{&eK8LpiE_g zUqd6FMfouvVo_s_O1#KEdEiO*kw^Mi)rZjy3<<_zP&TL1Qm{%uRx5y$ z5f%t9*^m}x6P`rbib4)2DxmfxAW;fv`^ZMHIAlgeD4?Mwdz0#XBU&|5zJSJ+fIJ)g z39u~CT2nDTXjANpC$QeFJ6aUS3w>TTq1Qup;G1BB!2+w%N5Bg+&I?~b6vm`DEaD(2 zhRLJIVh8q)4^2kWDPA}Y?JvMzjDTR6rj}~fUlo5o@yf(sT)5s}sM#_-xMX#`c;?dZ z#o##KLP!U?(H|aZnV71)Mm++?#Xnn=wMyd9mPb%~@MZW@!CPM0)wvX2<^R)ZcG!IN&qNc2KUy#wFrE zvM66gb}3$}G;zm?vU@m@J`+tu)G|@=Vmi|Xgh*#Z82kjjAQ&xX!NAce@O)2MfMr0P z@{}1RjjDSE^L{f$Q)R}S1?3=X%$k5Ls={K*%9-$|u?m{{wpFOg8UzoFqqAn{XDvfy zt)OJUA6SNN0szbCo?;&2sxW3PFiTw9swd05rm9FZ^$f+CrkD%NB+Lra^R&ijTB(g- zE1n0j_YACxre6H2!hm2Nx`859Yp90|UusUk@hR}^1py~x(6AjOBGF-fL*0a;-s7G^IGC7`wZ zbA)>zUenaabyV~Ei_m( zI0OeeV4tzyH&XW6kAV$T&kg~5u+=R&Yv+yg;RR<0Fb8KKXR4VQfY+z@f|S$u3B@2{ z_a*m5chT8Zbov3~r9&4F6`ihoHZyQIC*}43q2vLu&+hvH^-R+rKx3?GUs%5-=h+I( z0!OI6G|`v>3`wz|(m^k2+4_Bg34-n}N{-#Yht zshdvQUfOuGX5F5h#+y6MkpHF0yw}D2((BphF#fV--9C%)R~9qmW4ew9SWpZQCUF%G z&vK2C_=8j?v6-4O1A*%Y75b>p7un&$E$FkHA+7FH;Sj6%j9@D0jA#_eW7PwCVa53@ zV=#t?;xIiFhe_DBoPkx^0l-mV9hFy}HIM2{ro5on%^KsHvZTJbOhc`>!vE*-wlDL9 zJZQW?d9GRxW>G;)1+idwz#1*Dsg!`4>~nu3pj|aU^}Pke<}61pA;6gT4^< zGM$BZTW0Iw;Z&N0mwI{>b*M*ChfpknQ%;M1f*>0wRst&b5cA7yS=Nz2eYt+%EI`Fy zW;DN6wXSFDt_<0XUJefY69m*nVto)TAZ`cZgHwdsvw%oQ!z;6CAH*uq(jmfG6}bb% z?m>CK3uZ4upmkR}2cGR{|K=@Flc_zSyBqbPQ8s5-l-=c+uO`9E;yqX^pdG19&ps~l z5hV~Rq@Y%ID+SGSM?|~8BRrbU!c+J{{YXGdRv3eqTtA+|P#Hw8${`cQts^{%K*tft zG@6d51Y{cER~&%=Z9+CB)1cZS6+(=ZpWxyUYm;Q#fr%JTbX>VgjgF$?poU+aiYY|2 zglD1Was>hRoj8J?K$NPF1b0xjae$e80IeEhvJm#+Q^V4T5C?dogKPE>ro<)^hH(sh zy^k>e1p<+{cHp3zWM{jr7emRlZwH}<=c_eS)Vx}~O##ric@ z>RzfVu4!3Z6Uwg%6*qJ)ZrGLIu&dax?n=)~J)mDSSI^o(n`rL)@~{ov#hSXgr)Qro zHm_Z5?#(y%78{!v8@J^fw-sA@ip^ccK=WL3HhIs*G`MGul&VqZajadcZ@g0bQte`W zFkc_M)>)|EJac5JuHg#v5_84*lJjc#dPAXZ=gi@fp~_Xg)E>H)DYOsdz3VR9=MUog z9kY)4BiC#T-hQ=I^dByQ9~YduMSpYA-vIALe@EUAp0Un*4og)vYDu-&FSlm%^~{2I zZ?TrWKTK2h_PnjFbdILHK6LypIh*EVS9dQs`@to9|6ACev$cJCZ-l1&O`lL^n2omm zTl4{I?lUI%1QfjfP%;9{XZPc3&(B1RVtxO>hQlV~uQ%`MKIAgI(^U_JcU`u_wE5k@ z+Cw|d?`}0?%}z7ayhj@$|DMTw*u|{y&7sysG%c__R%lue;FR?1I%l6UJj5t^X#5r= zp6<`hqF0R?MVoWg^SY_bohQv;5~25kJizl?K^B3Is63;(pG~WQ3o;Kdg36NR8ETTz z46&ef5aRSv=$>ghKAu9ufhDXGBI+!;6rpmiOwHJ&G?GrOYK2P{PBoktfzut6jj{9G z$qajtm@x_l#7Ve2I+|5<2f@(5>pX;YDclV?5aEUb>J=xZwnGHB+A@9Qo}Dr~zI*h!qd9M{ z5}8;qf$M=W*DP6Ui*UT!cfQ^FPUvRnzm4cl0LI||bjjgIM*={&FF7wdb2VFU_};2} zvu?q<_XCd~y$Cg*kznSVb$hC*o7KTRyNx$@(eRd?aJfLg=d(ihM~Wa6`2xH#swtX= zsbOl!aDtMcNqI&QV%3A!%mz{BWLMgv`u$yz}ZMJEMQ>Gr_{EjU42Vk+sLx}Ivw+Jrv^ z7~L75VW+6))qAKU7PzOk~+wMs;mh>jBqtbpLF* z4tkZHElkB;Y#Cb1sTP-cv{kDqr=T;dUl1H6?`JI!h55(?2Ic3RL1tmsL+HuOSt`*} z*1Vs(1YC5OiWyD=FM1GN%o<+wngC`>pKp1`zioNw=*$B~xBT&=XTddu=jn59r|&6l zrx*wWocDQnYq_8`Gf#9lMIVH_d3MxC2A2DR65#7aKTw5ev@{ZxSaCcSgSZ*!lo$^t zz9sN)6Fi6u<7^K@p(u=cf5nTG>0GH@Dh{GpI+0L(_1cvwqKO*1*%h}>&`#L||GSUC z>nNOii-j-m(=LG@jo7pgx_Za#fpNNz99vTjx4{-0@1{e@L|N`9K{# zn5j8|yC{l7w`ZZd1YjA{kHsi zs95l}7Hb>kCT1rVYddb$cI3Prx!R7Rw`I}0KJSIO{odPk$J@N=(a|i5(&5jPp zfZl`EdV~r!+g}aoJwo}K?FHum>4CSy8s`Udj?SE^^Zrwy%?4)H{O>1^(o|r_|9oPn z0s|u2Vt==9!@*wTuid_bJKVo<`5vR(zv(p}+{OeC$xH+&FBXZ&3|@`{RZ3>kVh96W z#Hy1G0xygsMOdUsynQF2q9CA#D4?nt02-G z+?o#I1p;#HZ91o z#6nlMR^KsD21D>iKRn)u6Oa$8UrC1{Unit~b;8D0@2&!ojEgZ62vE%WRZCZ3mfdt# z7z3(3a`Vb%sG$0_XQGG8YbpWhHa@yADo+cpB#DGS%2g{d=og-BaD(G<<;JHqLc*w# z2;tr`117~7ur}F#__4ub#}Dk=0}+mOIFw^AO3~xIIG&J%6Hr60pO70*)= zh6DH_JRgIo3gah!1T+r_XMB|+_c#=eY2BGjbK?nqx9|qEqrxRV4Wbfamo)vcfu>D& zEfnqfkaB-W**>IPA5r}Us{h}qV;@m_{*CJVh&uWab>ueHd7J9KP3^l)4c^A$&f8S~ zN7TS=>ga8JZ@EqN-KN&wu{F%pF4`LMwubp_1zX#+<&LL*M!1x@n8`KlxN-cg({G+G zc#cjx@3?)J_vh-n^8W5?TyE2WeCS}#e=zTUY}!$>nCXuB))EED)wa8sl)TNfw`glD z86myn1$zWiFkCG5yA0+a7(w@vc1Z7-ZFkL(mYhbqPp#}zEBi{$Cc27LLVCySn&F=N z#$7YyOOMhnx`wnsdZ((fWQG*Su-#=a$2QRRT+N0O1?lw@B)M_&E|y9It#p9&g!GQr zS29BiJzZ5L26I-*UpH@@-CnX`$xhY4CDqx(B?p$A6kP0bVa`oi+%vJ~PT%!l>2Z2L zP5TK_%n+=Y0kkSIh7>`%DA;VIXh(Dol67kMT%Z?7OfA ss41=6MRyge8vr6-9V!{2MD_qubtRZ9uLMiwm0$_RtGefc9HG4b1CR1P*#H0l literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/build_env.py b/backend/.venv/Lib/site-packages/pip/_internal/build_env.py new file mode 100644 index 0000000..0f1e266 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/build_env.py @@ -0,0 +1,319 @@ +"""Build Environment used for isolation during sdist building +""" + +import logging +import os +import pathlib +import site +import sys +import textwrap +from collections import OrderedDict +from types import TracebackType +from typing import TYPE_CHECKING, Iterable, List, Optional, Set, Tuple, Type, Union + +from pip._vendor.certifi import where +from pip._vendor.packaging.version import Version + +from pip import __file__ as pip_location +from pip._internal.cli.spinners import open_spinner +from pip._internal.locations import get_platlib, get_purelib, get_scheme +from pip._internal.metadata import get_default_environment, get_environment +from pip._internal.utils.logging import VERBOSE +from pip._internal.utils.packaging import get_requirement +from pip._internal.utils.subprocess import call_subprocess +from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds + +if TYPE_CHECKING: + from pip._internal.index.package_finder import PackageFinder + +logger = logging.getLogger(__name__) + + +def _dedup(a: str, b: str) -> Union[Tuple[str], Tuple[str, str]]: + return (a, b) if a != b else (a,) + + +class _Prefix: + def __init__(self, path: str) -> None: + self.path = path + self.setup = False + scheme = get_scheme("", prefix=path) + self.bin_dir = scheme.scripts + self.lib_dirs = _dedup(scheme.purelib, scheme.platlib) + + +def get_runnable_pip() -> str: + """Get a file to pass to a Python executable, to run the currently-running pip. + + This is used to run a pip subprocess, for installing requirements into the build + environment. + """ + source = pathlib.Path(pip_location).resolve().parent + + if not source.is_dir(): + # This would happen if someone is using pip from inside a zip file. In that + # case, we can use that directly. + return str(source) + + return os.fsdecode(source / "__pip-runner__.py") + + +def _get_system_sitepackages() -> Set[str]: + """Get system site packages + + Usually from site.getsitepackages, + but fallback on `get_purelib()/get_platlib()` if unavailable + (e.g. in a virtualenv created by virtualenv<20) + + Returns normalized set of strings. + """ + if hasattr(site, "getsitepackages"): + system_sites = site.getsitepackages() + else: + # virtualenv < 20 overwrites site.py without getsitepackages + # fallback on get_purelib/get_platlib. + # this is known to miss things, but shouldn't in the cases + # where getsitepackages() has been removed (inside a virtualenv) + system_sites = [get_purelib(), get_platlib()] + return {os.path.normcase(path) for path in system_sites} + + +class BuildEnvironment: + """Creates and manages an isolated environment to install build deps""" + + def __init__(self) -> None: + temp_dir = TempDirectory(kind=tempdir_kinds.BUILD_ENV, globally_managed=True) + + self._prefixes = OrderedDict( + (name, _Prefix(os.path.join(temp_dir.path, name))) + for name in ("normal", "overlay") + ) + + self._bin_dirs: List[str] = [] + self._lib_dirs: List[str] = [] + for prefix in reversed(list(self._prefixes.values())): + self._bin_dirs.append(prefix.bin_dir) + self._lib_dirs.extend(prefix.lib_dirs) + + # Customize site to: + # - ensure .pth files are honored + # - prevent access to system site packages + system_sites = _get_system_sitepackages() + + self._site_dir = os.path.join(temp_dir.path, "site") + if not os.path.exists(self._site_dir): + os.mkdir(self._site_dir) + with open( + os.path.join(self._site_dir, "sitecustomize.py"), "w", encoding="utf-8" + ) as fp: + fp.write( + textwrap.dedent( + """ + import os, site, sys + + # First, drop system-sites related paths. + original_sys_path = sys.path[:] + known_paths = set() + for path in {system_sites!r}: + site.addsitedir(path, known_paths=known_paths) + system_paths = set( + os.path.normcase(path) + for path in sys.path[len(original_sys_path):] + ) + original_sys_path = [ + path for path in original_sys_path + if os.path.normcase(path) not in system_paths + ] + sys.path = original_sys_path + + # Second, add lib directories. + # ensuring .pth file are processed. + for path in {lib_dirs!r}: + assert not path in sys.path + site.addsitedir(path) + """ + ).format(system_sites=system_sites, lib_dirs=self._lib_dirs) + ) + + def __enter__(self) -> None: + self._save_env = { + name: os.environ.get(name, None) + for name in ("PATH", "PYTHONNOUSERSITE", "PYTHONPATH") + } + + path = self._bin_dirs[:] + old_path = self._save_env["PATH"] + if old_path: + path.extend(old_path.split(os.pathsep)) + + pythonpath = [self._site_dir] + + os.environ.update( + { + "PATH": os.pathsep.join(path), + "PYTHONNOUSERSITE": "1", + "PYTHONPATH": os.pathsep.join(pythonpath), + } + ) + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + for varname, old_value in self._save_env.items(): + if old_value is None: + os.environ.pop(varname, None) + else: + os.environ[varname] = old_value + + def check_requirements( + self, reqs: Iterable[str] + ) -> Tuple[Set[Tuple[str, str]], Set[str]]: + """Return 2 sets: + - conflicting requirements: set of (installed, wanted) reqs tuples + - missing requirements: set of reqs + """ + missing = set() + conflicting = set() + if reqs: + env = ( + get_environment(self._lib_dirs) + if hasattr(self, "_lib_dirs") + else get_default_environment() + ) + for req_str in reqs: + req = get_requirement(req_str) + # We're explicitly evaluating with an empty extra value, since build + # environments are not provided any mechanism to select specific extras. + if req.marker is not None and not req.marker.evaluate({"extra": ""}): + continue + dist = env.get_distribution(req.name) + if not dist: + missing.add(req_str) + continue + if isinstance(dist.version, Version): + installed_req_str = f"{req.name}=={dist.version}" + else: + installed_req_str = f"{req.name}==={dist.version}" + if not req.specifier.contains(dist.version, prereleases=True): + conflicting.add((installed_req_str, req_str)) + # FIXME: Consider direct URL? + return conflicting, missing + + def install_requirements( + self, + finder: "PackageFinder", + requirements: Iterable[str], + prefix_as_string: str, + *, + kind: str, + ) -> None: + prefix = self._prefixes[prefix_as_string] + assert not prefix.setup + prefix.setup = True + if not requirements: + return + self._install_requirements( + get_runnable_pip(), + finder, + requirements, + prefix, + kind=kind, + ) + + @staticmethod + def _install_requirements( + pip_runnable: str, + finder: "PackageFinder", + requirements: Iterable[str], + prefix: _Prefix, + *, + kind: str, + ) -> None: + args: List[str] = [ + sys.executable, + pip_runnable, + "install", + "--ignore-installed", + "--no-user", + "--prefix", + prefix.path, + "--no-warn-script-location", + "--disable-pip-version-check", + # The prefix specified two lines above, thus + # target from config file or env var should be ignored + "--target", + "", + ] + if logger.getEffectiveLevel() <= logging.DEBUG: + args.append("-vv") + elif logger.getEffectiveLevel() <= VERBOSE: + args.append("-v") + for format_control in ("no_binary", "only_binary"): + formats = getattr(finder.format_control, format_control) + args.extend( + ( + "--" + format_control.replace("_", "-"), + ",".join(sorted(formats or {":none:"})), + ) + ) + + index_urls = finder.index_urls + if index_urls: + args.extend(["-i", index_urls[0]]) + for extra_index in index_urls[1:]: + args.extend(["--extra-index-url", extra_index]) + else: + args.append("--no-index") + for link in finder.find_links: + args.extend(["--find-links", link]) + + for host in finder.trusted_hosts: + args.extend(["--trusted-host", host]) + if finder.allow_all_prereleases: + args.append("--pre") + if finder.prefer_binary: + args.append("--prefer-binary") + args.append("--") + args.extend(requirements) + extra_environ = {"_PIP_STANDALONE_CERT": where()} + with open_spinner(f"Installing {kind}") as spinner: + call_subprocess( + args, + command_desc=f"pip subprocess to install {kind}", + spinner=spinner, + extra_environ=extra_environ, + ) + + +class NoOpBuildEnvironment(BuildEnvironment): + """A no-op drop-in replacement for BuildEnvironment""" + + def __init__(self) -> None: + pass + + def __enter__(self) -> None: + pass + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + pass + + def cleanup(self) -> None: + pass + + def install_requirements( + self, + finder: "PackageFinder", + requirements: Iterable[str], + prefix_as_string: str, + *, + kind: str, + ) -> None: + raise NotImplementedError() diff --git a/backend/.venv/Lib/site-packages/pip/_internal/cache.py b/backend/.venv/Lib/site-packages/pip/_internal/cache.py new file mode 100644 index 0000000..6b45126 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/cache.py @@ -0,0 +1,290 @@ +"""Cache Management +""" + +import hashlib +import json +import logging +import os +from pathlib import Path +from typing import Any, Dict, List, Optional + +from pip._vendor.packaging.tags import Tag, interpreter_name, interpreter_version +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.exceptions import InvalidWheelFilename +from pip._internal.models.direct_url import DirectUrl +from pip._internal.models.link import Link +from pip._internal.models.wheel import Wheel +from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds +from pip._internal.utils.urls import path_to_url + +logger = logging.getLogger(__name__) + +ORIGIN_JSON_NAME = "origin.json" + + +def _hash_dict(d: Dict[str, str]) -> str: + """Return a stable sha224 of a dictionary.""" + s = json.dumps(d, sort_keys=True, separators=(",", ":"), ensure_ascii=True) + return hashlib.sha224(s.encode("ascii")).hexdigest() + + +class Cache: + """An abstract class - provides cache directories for data from links + + :param cache_dir: The root of the cache. + """ + + def __init__(self, cache_dir: str) -> None: + super().__init__() + assert not cache_dir or os.path.isabs(cache_dir) + self.cache_dir = cache_dir or None + + def _get_cache_path_parts(self, link: Link) -> List[str]: + """Get parts of part that must be os.path.joined with cache_dir""" + + # We want to generate an url to use as our cache key, we don't want to + # just reuse the URL because it might have other items in the fragment + # and we don't care about those. + key_parts = {"url": link.url_without_fragment} + if link.hash_name is not None and link.hash is not None: + key_parts[link.hash_name] = link.hash + if link.subdirectory_fragment: + key_parts["subdirectory"] = link.subdirectory_fragment + + # Include interpreter name, major and minor version in cache key + # to cope with ill-behaved sdists that build a different wheel + # depending on the python version their setup.py is being run on, + # and don't encode the difference in compatibility tags. + # https://github.com/pypa/pip/issues/7296 + key_parts["interpreter_name"] = interpreter_name() + key_parts["interpreter_version"] = interpreter_version() + + # Encode our key url with sha224, we'll use this because it has similar + # security properties to sha256, but with a shorter total output (and + # thus less secure). However the differences don't make a lot of + # difference for our use case here. + hashed = _hash_dict(key_parts) + + # We want to nest the directories some to prevent having a ton of top + # level directories where we might run out of sub directories on some + # FS. + parts = [hashed[:2], hashed[2:4], hashed[4:6], hashed[6:]] + + return parts + + def _get_candidates(self, link: Link, canonical_package_name: str) -> List[Any]: + can_not_cache = not self.cache_dir or not canonical_package_name or not link + if can_not_cache: + return [] + + path = self.get_path_for_link(link) + if os.path.isdir(path): + return [(candidate, path) for candidate in os.listdir(path)] + return [] + + def get_path_for_link(self, link: Link) -> str: + """Return a directory to store cached items in for link.""" + raise NotImplementedError() + + def get( + self, + link: Link, + package_name: Optional[str], + supported_tags: List[Tag], + ) -> Link: + """Returns a link to a cached item if it exists, otherwise returns the + passed link. + """ + raise NotImplementedError() + + +class SimpleWheelCache(Cache): + """A cache of wheels for future installs.""" + + def __init__(self, cache_dir: str) -> None: + super().__init__(cache_dir) + + def get_path_for_link(self, link: Link) -> str: + """Return a directory to store cached wheels for link + + Because there are M wheels for any one sdist, we provide a directory + to cache them in, and then consult that directory when looking up + cache hits. + + We only insert things into the cache if they have plausible version + numbers, so that we don't contaminate the cache with things that were + not unique. E.g. ./package might have dozens of installs done for it + and build a version of 0.0...and if we built and cached a wheel, we'd + end up using the same wheel even if the source has been edited. + + :param link: The link of the sdist for which this will cache wheels. + """ + parts = self._get_cache_path_parts(link) + assert self.cache_dir + # Store wheels within the root cache_dir + return os.path.join(self.cache_dir, "wheels", *parts) + + def get( + self, + link: Link, + package_name: Optional[str], + supported_tags: List[Tag], + ) -> Link: + candidates = [] + + if not package_name: + return link + + canonical_package_name = canonicalize_name(package_name) + for wheel_name, wheel_dir in self._get_candidates(link, canonical_package_name): + try: + wheel = Wheel(wheel_name) + except InvalidWheelFilename: + continue + if canonicalize_name(wheel.name) != canonical_package_name: + logger.debug( + "Ignoring cached wheel %s for %s as it " + "does not match the expected distribution name %s.", + wheel_name, + link, + package_name, + ) + continue + if not wheel.supported(supported_tags): + # Built for a different python/arch/etc + continue + candidates.append( + ( + wheel.support_index_min(supported_tags), + wheel_name, + wheel_dir, + ) + ) + + if not candidates: + return link + + _, wheel_name, wheel_dir = min(candidates) + return Link(path_to_url(os.path.join(wheel_dir, wheel_name))) + + +class EphemWheelCache(SimpleWheelCache): + """A SimpleWheelCache that creates it's own temporary cache directory""" + + def __init__(self) -> None: + self._temp_dir = TempDirectory( + kind=tempdir_kinds.EPHEM_WHEEL_CACHE, + globally_managed=True, + ) + + super().__init__(self._temp_dir.path) + + +class CacheEntry: + def __init__( + self, + link: Link, + persistent: bool, + ): + self.link = link + self.persistent = persistent + self.origin: Optional[DirectUrl] = None + origin_direct_url_path = Path(self.link.file_path).parent / ORIGIN_JSON_NAME + if origin_direct_url_path.exists(): + try: + self.origin = DirectUrl.from_json( + origin_direct_url_path.read_text(encoding="utf-8") + ) + except Exception as e: + logger.warning( + "Ignoring invalid cache entry origin file %s for %s (%s)", + origin_direct_url_path, + link.filename, + e, + ) + + +class WheelCache(Cache): + """Wraps EphemWheelCache and SimpleWheelCache into a single Cache + + This Cache allows for gracefully degradation, using the ephem wheel cache + when a certain link is not found in the simple wheel cache first. + """ + + def __init__(self, cache_dir: str) -> None: + super().__init__(cache_dir) + self._wheel_cache = SimpleWheelCache(cache_dir) + self._ephem_cache = EphemWheelCache() + + def get_path_for_link(self, link: Link) -> str: + return self._wheel_cache.get_path_for_link(link) + + def get_ephem_path_for_link(self, link: Link) -> str: + return self._ephem_cache.get_path_for_link(link) + + def get( + self, + link: Link, + package_name: Optional[str], + supported_tags: List[Tag], + ) -> Link: + cache_entry = self.get_cache_entry(link, package_name, supported_tags) + if cache_entry is None: + return link + return cache_entry.link + + def get_cache_entry( + self, + link: Link, + package_name: Optional[str], + supported_tags: List[Tag], + ) -> Optional[CacheEntry]: + """Returns a CacheEntry with a link to a cached item if it exists or + None. The cache entry indicates if the item was found in the persistent + or ephemeral cache. + """ + retval = self._wheel_cache.get( + link=link, + package_name=package_name, + supported_tags=supported_tags, + ) + if retval is not link: + return CacheEntry(retval, persistent=True) + + retval = self._ephem_cache.get( + link=link, + package_name=package_name, + supported_tags=supported_tags, + ) + if retval is not link: + return CacheEntry(retval, persistent=False) + + return None + + @staticmethod + def record_download_origin(cache_dir: str, download_info: DirectUrl) -> None: + origin_path = Path(cache_dir) / ORIGIN_JSON_NAME + if origin_path.exists(): + try: + origin = DirectUrl.from_json(origin_path.read_text(encoding="utf-8")) + except Exception as e: + logger.warning( + "Could not read origin file %s in cache entry (%s). " + "Will attempt to overwrite it.", + origin_path, + e, + ) + else: + # TODO: use DirectUrl.equivalent when + # https://github.com/pypa/pip/pull/10564 is merged. + if origin.url != download_info.url: + logger.warning( + "Origin URL %s in cache entry %s does not match download URL " + "%s. This is likely a pip bug or a cache corruption issue. " + "Will overwrite it with the new value.", + origin.url, + cache_dir, + download_info.url, + ) + origin_path.write_text(download_info.to_json(), encoding="utf-8") diff --git a/backend/.venv/Lib/site-packages/pip/_internal/cli/__init__.py b/backend/.venv/Lib/site-packages/pip/_internal/cli/__init__.py new file mode 100644 index 0000000..e589bb9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/cli/__init__.py @@ -0,0 +1,4 @@ +"""Subpackage containing all of pip's command line interface related code +""" + +# This file intentionally does not import submodules diff --git a/backend/.venv/Lib/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2a72aff296d99ecf163a785ec00295d3ccf7f2e0 GIT binary patch literal 280 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c74e357e8615f8a871480d690f4dcb43ed64d094 GIT binary patch literal 10196 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 X)be-pTjJR@ZeQvnm&h|qC9-; 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 SNqrGn8LjMj<%vNwbo?)1I%#nL literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/cli/__pycache__/parser.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/cli/__pycache__/parser.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..72fcc7b91f139e0adb4c1815ab5ce489ab627326 GIT binary patch literal 15042 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d0a9ec98c889ba51fa6667ec66ddc5fa21559175 GIT binary patch literal 3846 zcmahMTTC0-^^V8$uszsd^Dq!#@@NxR!D%*4$wqmIK$hK-#}-(r>t$sPo@+3SXRJHp z5U5d5ln>ZlHI}y8P^llOx*v%`rSvbKtLCRte@tKnozQky-H%4ih`C<#*0zeht`P>B1d>DzeqcAan<*NM$sXsLV`)fwf2T zWZ49p^(MSoF2QB_1fLZWLRL(O4CP}rU)G=SX9I~qR!T_OxNIQ(9%G24`Aa&S&-&bB047=&5O;bWfhrKweGAfg1={hZ{{#)L}z8(DE%*(3*;Oziu>6gqNy{&0pt-Hl1I%k+z@EPbv zS7N*^_9>dCjA_{R4PYG;#WIL3zF`4Ii51MDUCmh;LsvAL8_DN19P``03kvBow0u^# zgZ;*|t{IBzu3yV&csMhQt84L1VvG}Pns(5|sylVVxr`1Ut}gu}__|fa8%8o&d{I+! zCU*5kC}{|1m5iRz$E$pi5u)g38k6B1b~$5=9T-w9d?}O7z+qq+8pl>LqpMiA6nYX{ zq#Kn}jwvK*&E&A{HNj?^C)mmpJq7OL3=cpNeh1;V^&F^!hylkcz%xx9LC6$-1TOW! zVMXXBQ}CGQEmszt=|L5rV=cDIgjBCfwYVCMQ~71#0sR^bOQ_5UxtcBC9*XPgHJ&s# z=he>?Jm2uGx;+{~dnkLqvTe0kv%2ABximlLwIVLH;8lI9Kg0Ztnd1uFWRpwZp4EWW z;;!5is?scwX5mH(>~fuZ6LWllI|(;lK>g_50|?Ct1>qyl9R?`eB#n}nMuE55T~a}C zEnW_~`WW=VAusaLK!?9=>I^*aabz;n9tOP)-(%1Wy3W3hrkUTc(@ZRM#r7EbZ1>1S z#+1zoBd@8lp=&ep7?$(kqH;!;tqClvIIZM0OU@c9j@xWTPtP8CCs+0VxQfjb$vCm} z?oTbnoZ3m5v%OkI$Kw_2zd8?Y%bC=vZ5CUK9VR#pK{S!fVUjd)%Fxwk)O&13en!29 zvRj6wXn+WcdQH(&I2N?IG(@IF=u49z1=MRun1Xr==z|lQP6>TfA_1^PMOBm3Jkm&) zd_Jc_G})|%^_WQLbCPBX=o1ne7q*acQh{lU?pbYtDoAEjn@dgP^(m9akX#-AQTtAh zP8(#(%qb~6s!v*Gw~|U3dEJ7@?oJs5kB%v+DXgob@oQMWHhL*DHflo5c7wo_GLFsB zTqbu6LK?yt^3t)CmO18rItdYN#&a`vI7u=oxUlN=Q#y%*8BzF|e+Te4^wm5nOGs)g zT2BJ)CGVwD$E8((f%eY>q0RcHBK}ZX;J%QWOD(;t(uGZ_b?LkJ*fr_srqs47?c0>P zR;B%$Qpc*)RSxjS{EI@l9yK)W5@~vWa5r~zF~2HxRAkF_Ld3ryJP)J#=u%55)bsGi zE1{nG*EfRA>%p#-VAoyt;~T4oPdz%ma`?=OeD;&KO2Mwx;Nbj#?Q3}2)Uj}JBi!=d z;D*$A`|9G=rGe$)hfNO>3s*mtPJPLt=FS%^@`rCn7o-0*JK?}LFP!Q-#r*E{k-nqs zXD+~FA|A?V^<%51N#J&^t!WHoBJRwjv96u-2b5hkD?dYHpNb}y- z0)RVc`%WfzayhIBP1dq~l>n2<6rh%*J+pA%?)@;|rsx0M0nJ-6&z0Hmn^muuzXO>n z4bUI++N?Qa+PrD0M&7cyX#x>NGeq8;hQymzIwcTK#oYx7gF zZ3{#Yp*B==Vd;E~qq)=~^r{KGFS0p;6?KMACbnWiB`Y}z>4%i3b{1QLwgxA)N-IE) z!lp^DubPP}XKdJWCUORN=+Ar)KqXK3JzV?8Y#G6{+~-UW`?u(-ETT~T{J@4(|K1zL z-ua80kaO4*RxSlCN`2%M0wzpw77Lc|di*7^WInM??F!XrOjE z1LSLAJ&Y`x_MI_|V%+SF0c^>NE*oQ$IAuY_R4h3KYqyG8h77@`Vp1ul)xJ`8GkDzZ zr|&l8bZDlmfNZ6KJz7y^DN`88y6kp$GAKMSO_bb$xFbp0z?S=-?eb-_;LYSLP{GA~ z>Aaq@3_~+*A*T>4qi9aOaGb&RQl;cPuUpLjI!`;oQKP)Qux@HG_Qdg5!_vHQxS#gt5Pf!zuPGoFNEsv0Ct>tfu!)g3*6 z(;UzqfY4^K(l9u!gVQTG9Rh6~>^4W4TYckDedA`Ol{cLjwcB?yEomO7M=g4JXqIJvs zGk`M7Fw9d_{}lQEf(F;o;0ten@w`AT_-7kpPW%b=eAa&O?oaOFUnNV2PCmT;3HRF@ zr9-c+v=5X}w9M~kUWGDT%r6>c7Vt8ULgBJNF%bnK#S@F&WglJn5g%H}7uBWy61*q3 ze=9(#uQL&*u_g~V$XBHVx)NWO@=2e* literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c8d73a40d79f41d98de218c0c9a156a1b4e3da46 GIT binary patch literal 12243 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

yg!13wX!V|%tA`e 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 UKrK0MZa^bBJ^KQc=!8fA0E+r*egFUf literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/cli/autocompletion.py b/backend/.venv/Lib/site-packages/pip/_internal/cli/autocompletion.py new file mode 100644 index 0000000..f3f70ac --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/cli/autocompletion.py @@ -0,0 +1,176 @@ +"""Logic that powers autocompletion installed by ``pip completion``. +""" + +import optparse +import os +import sys +from itertools import chain +from typing import Any, Iterable, List, Optional + +from pip._internal.cli.main_parser import create_main_parser +from pip._internal.commands import commands_dict, create_command +from pip._internal.metadata import get_default_environment + + +def autocomplete() -> None: + """Entry Point for completion of main and subcommand options.""" + # Don't complete if user hasn't sourced bash_completion file. + if "PIP_AUTO_COMPLETE" not in os.environ: + return + # Don't complete if autocompletion environment variables + # are not present + if not os.environ.get("COMP_WORDS") or not os.environ.get("COMP_CWORD"): + return + cwords = os.environ["COMP_WORDS"].split()[1:] + cword = int(os.environ["COMP_CWORD"]) + try: + current = cwords[cword - 1] + except IndexError: + current = "" + + parser = create_main_parser() + subcommands = list(commands_dict) + options = [] + + # subcommand + subcommand_name: Optional[str] = None + for word in cwords: + if word in subcommands: + subcommand_name = word + break + # subcommand options + if subcommand_name is not None: + # special case: 'help' subcommand has no options + if subcommand_name == "help": + sys.exit(1) + # special case: list locally installed dists for show and uninstall + should_list_installed = not current.startswith("-") and subcommand_name in [ + "show", + "uninstall", + ] + if should_list_installed: + env = get_default_environment() + lc = current.lower() + installed = [ + dist.canonical_name + for dist in env.iter_installed_distributions(local_only=True) + if dist.canonical_name.startswith(lc) + and dist.canonical_name not in cwords[1:] + ] + # if there are no dists installed, fall back to option completion + if installed: + for dist in installed: + print(dist) + sys.exit(1) + + should_list_installables = ( + not current.startswith("-") and subcommand_name == "install" + ) + if should_list_installables: + for path in auto_complete_paths(current, "path"): + print(path) + sys.exit(1) + + subcommand = create_command(subcommand_name) + + for opt in subcommand.parser.option_list_all: + if opt.help != optparse.SUPPRESS_HELP: + options += [ + (opt_str, opt.nargs) for opt_str in opt._long_opts + opt._short_opts + ] + + # filter out previously specified options from available options + prev_opts = [x.split("=")[0] for x in cwords[1 : cword - 1]] + options = [(x, v) for (x, v) in options if x not in prev_opts] + # filter options by current input + options = [(k, v) for k, v in options if k.startswith(current)] + # get completion type given cwords and available subcommand options + completion_type = get_path_completion_type( + cwords, + cword, + subcommand.parser.option_list_all, + ) + # get completion files and directories if ``completion_type`` is + # ````, ``

`` or ```` + if completion_type: + paths = auto_complete_paths(current, completion_type) + options = [(path, 0) for path in paths] + for option in options: + opt_label = option[0] + # append '=' to options which require args + if option[1] and option[0][:2] == "--": + opt_label += "=" + print(opt_label) + else: + # show main parser options only when necessary + + opts = [i.option_list for i in parser.option_groups] + opts.append(parser.option_list) + flattened_opts = chain.from_iterable(opts) + if current.startswith("-"): + for opt in flattened_opts: + if opt.help != optparse.SUPPRESS_HELP: + subcommands += opt._long_opts + opt._short_opts + else: + # get completion type given cwords and all available options + completion_type = get_path_completion_type(cwords, cword, flattened_opts) + if completion_type: + subcommands = list(auto_complete_paths(current, completion_type)) + + print(" ".join([x for x in subcommands if x.startswith(current)])) + sys.exit(1) + + +def get_path_completion_type( + cwords: List[str], cword: int, opts: Iterable[Any] +) -> Optional[str]: + """Get the type of path completion (``file``, ``dir``, ``path`` or None) + + :param cwords: same as the environmental variable ``COMP_WORDS`` + :param cword: same as the environmental variable ``COMP_CWORD`` + :param opts: The available options to check + :return: path completion type (``file``, ``dir``, ``path`` or None) + """ + if cword < 2 or not cwords[cword - 2].startswith("-"): + return None + for opt in opts: + if opt.help == optparse.SUPPRESS_HELP: + continue + for o in str(opt).split("/"): + if cwords[cword - 2].split("=")[0] == o: + if not opt.metavar or any( + x in ("path", "file", "dir") for x in opt.metavar.split("/") + ): + return opt.metavar + return None + + +def auto_complete_paths(current: str, completion_type: str) -> Iterable[str]: + """If ``completion_type`` is ``file`` or ``path``, list all regular files + and directories starting with ``current``; otherwise only list directories + starting with ``current``. + + :param current: The word to be completed + :param completion_type: path completion type(``file``, ``path`` or ``dir``) + :return: A generator of regular files and/or directories + """ + directory, filename = os.path.split(current) + current_path = os.path.abspath(directory) + # Don't complete paths if they can't be accessed + if not os.access(current_path, os.R_OK): + return + filename = os.path.normcase(filename) + # list all files that start with ``filename`` + file_list = ( + x for x in os.listdir(current_path) if os.path.normcase(x).startswith(filename) + ) + for f in file_list: + opt = os.path.join(current_path, f) + comp_file = os.path.normcase(os.path.join(directory, f)) + # complete regular files when there is not ```` after option + # complete directories when there is ````, ```` or + # ````after option + if completion_type != "dir" and os.path.isfile(opt): + yield comp_file + elif os.path.isdir(opt): + yield os.path.join(comp_file, "") diff --git a/backend/.venv/Lib/site-packages/pip/_internal/cli/base_command.py b/backend/.venv/Lib/site-packages/pip/_internal/cli/base_command.py new file mode 100644 index 0000000..bc1ab65 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/cli/base_command.py @@ -0,0 +1,231 @@ +"""Base Command class, and related routines""" + +import logging +import logging.config +import optparse +import os +import sys +import traceback +from optparse import Values +from typing import List, Optional, Tuple + +from pip._vendor.rich import reconfigure +from pip._vendor.rich import traceback as rich_traceback + +from pip._internal.cli import cmdoptions +from pip._internal.cli.command_context import CommandContextMixIn +from pip._internal.cli.parser import ConfigOptionParser, UpdatingDefaultsHelpFormatter +from pip._internal.cli.status_codes import ( + ERROR, + PREVIOUS_BUILD_DIR_ERROR, + UNKNOWN_ERROR, + VIRTUALENV_NOT_FOUND, +) +from pip._internal.exceptions import ( + BadCommand, + CommandError, + DiagnosticPipError, + InstallationError, + NetworkConnectionError, + PreviousBuildDirError, +) +from pip._internal.utils.filesystem import check_path_owner +from pip._internal.utils.logging import BrokenStdoutLoggingError, setup_logging +from pip._internal.utils.misc import get_prog, normalize_path +from pip._internal.utils.temp_dir import TempDirectoryTypeRegistry as TempDirRegistry +from pip._internal.utils.temp_dir import global_tempdir_manager, tempdir_registry +from pip._internal.utils.virtualenv import running_under_virtualenv + +__all__ = ["Command"] + +logger = logging.getLogger(__name__) + + +class Command(CommandContextMixIn): + usage: str = "" + ignore_require_venv: bool = False + + def __init__(self, name: str, summary: str, isolated: bool = False) -> None: + super().__init__() + + self.name = name + self.summary = summary + self.parser = ConfigOptionParser( + usage=self.usage, + prog=f"{get_prog()} {name}", + formatter=UpdatingDefaultsHelpFormatter(), + add_help_option=False, + name=name, + description=self.__doc__, + isolated=isolated, + ) + + self.tempdir_registry: Optional[TempDirRegistry] = None + + # Commands should add options to this option group + optgroup_name = f"{self.name.capitalize()} Options" + self.cmd_opts = optparse.OptionGroup(self.parser, optgroup_name) + + # Add the general options + gen_opts = cmdoptions.make_option_group( + cmdoptions.general_group, + self.parser, + ) + self.parser.add_option_group(gen_opts) + + self.add_options() + + def add_options(self) -> None: + pass + + def handle_pip_version_check(self, options: Values) -> None: + """ + This is a no-op so that commands by default do not do the pip version + check. + """ + # Make sure we do the pip version check if the index_group options + # are present. + assert not hasattr(options, "no_index") + + def run(self, options: Values, args: List[str]) -> int: + raise NotImplementedError + + def _run_wrapper(self, level_number: int, options: Values, args: List[str]) -> int: + def _inner_run() -> int: + try: + return self.run(options, args) + finally: + self.handle_pip_version_check(options) + + if options.debug_mode: + rich_traceback.install(show_locals=True) + return _inner_run() + + try: + status = _inner_run() + assert isinstance(status, int) + return status + except DiagnosticPipError as exc: + logger.error("%s", exc, extra={"rich": True}) + logger.debug("Exception information:", exc_info=True) + + return ERROR + except PreviousBuildDirError as exc: + logger.critical(str(exc)) + logger.debug("Exception information:", exc_info=True) + + return PREVIOUS_BUILD_DIR_ERROR + except ( + InstallationError, + BadCommand, + NetworkConnectionError, + ) as exc: + logger.critical(str(exc)) + logger.debug("Exception information:", exc_info=True) + + return ERROR + except CommandError as exc: + logger.critical("%s", exc) + logger.debug("Exception information:", exc_info=True) + + return ERROR + except BrokenStdoutLoggingError: + # Bypass our logger and write any remaining messages to + # stderr because stdout no longer works. + print("ERROR: Pipe to stdout was broken", file=sys.stderr) + if level_number <= logging.DEBUG: + traceback.print_exc(file=sys.stderr) + + return ERROR + except KeyboardInterrupt: + logger.critical("Operation cancelled by user") + logger.debug("Exception information:", exc_info=True) + + return ERROR + except BaseException: + logger.critical("Exception:", exc_info=True) + + return UNKNOWN_ERROR + + def parse_args(self, args: List[str]) -> Tuple[Values, List[str]]: + # factored out for testability + return self.parser.parse_args(args) + + def main(self, args: List[str]) -> int: + try: + with self.main_context(): + return self._main(args) + finally: + logging.shutdown() + + def _main(self, args: List[str]) -> int: + # We must initialize this before the tempdir manager, otherwise the + # configuration would not be accessible by the time we clean up the + # tempdir manager. + self.tempdir_registry = self.enter_context(tempdir_registry()) + # Intentionally set as early as possible so globally-managed temporary + # directories are available to the rest of the code. + self.enter_context(global_tempdir_manager()) + + options, args = self.parse_args(args) + + # Set verbosity so that it can be used elsewhere. + self.verbosity = options.verbose - options.quiet + + reconfigure(no_color=options.no_color) + level_number = setup_logging( + verbosity=self.verbosity, + no_color=options.no_color, + user_log_file=options.log, + ) + + always_enabled_features = set(options.features_enabled) & set( + cmdoptions.ALWAYS_ENABLED_FEATURES + ) + if always_enabled_features: + logger.warning( + "The following features are always enabled: %s. ", + ", ".join(sorted(always_enabled_features)), + ) + + # Make sure that the --python argument isn't specified after the + # subcommand. We can tell, because if --python was specified, + # we should only reach this point if we're running in the created + # subprocess, which has the _PIP_RUNNING_IN_SUBPROCESS environment + # variable set. + if options.python and "_PIP_RUNNING_IN_SUBPROCESS" not in os.environ: + logger.critical( + "The --python option must be placed before the pip subcommand name" + ) + sys.exit(ERROR) + + # TODO: Try to get these passing down from the command? + # without resorting to os.environ to hold these. + # This also affects isolated builds and it should. + + if options.no_input: + os.environ["PIP_NO_INPUT"] = "1" + + if options.exists_action: + os.environ["PIP_EXISTS_ACTION"] = " ".join(options.exists_action) + + if options.require_venv and not self.ignore_require_venv: + # If a venv is required check if it can really be found + if not running_under_virtualenv(): + logger.critical("Could not find an activated virtualenv (required).") + sys.exit(VIRTUALENV_NOT_FOUND) + + if options.cache_dir: + options.cache_dir = normalize_path(options.cache_dir) + if not check_path_owner(options.cache_dir): + logger.warning( + "The directory '%s' or its parent directory is not owned " + "or is not writable by the current user. The cache " + "has been disabled. Check the permissions and owner of " + "that directory. If executing pip with sudo, you should " + "use sudo's -H flag.", + options.cache_dir, + ) + options.cache_dir = None + + return self._run_wrapper(level_number, options, args) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/cli/cmdoptions.py b/backend/.venv/Lib/site-packages/pip/_internal/cli/cmdoptions.py new file mode 100644 index 0000000..0b7cff7 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/cli/cmdoptions.py @@ -0,0 +1,1075 @@ +""" +shared options and groups + +The principle here is to define options once, but *not* instantiate them +globally. One reason being that options with action='append' can carry state +between parses. pip parses general options twice internally, and shouldn't +pass on state. To be consistent, all options will follow this design. +""" + +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False + +import importlib.util +import logging +import os +import textwrap +from functools import partial +from optparse import SUPPRESS_HELP, Option, OptionGroup, OptionParser, Values +from textwrap import dedent +from typing import Any, Callable, Dict, Optional, Tuple + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.cli.parser import ConfigOptionParser +from pip._internal.exceptions import CommandError +from pip._internal.locations import USER_CACHE_DIR, get_src_prefix +from pip._internal.models.format_control import FormatControl +from pip._internal.models.index import PyPI +from pip._internal.models.target_python import TargetPython +from pip._internal.utils.hashes import STRONG_HASHES +from pip._internal.utils.misc import strtobool + +logger = logging.getLogger(__name__) + + +def raise_option_error(parser: OptionParser, option: Option, msg: str) -> None: + """ + Raise an option parsing error using parser.error(). + + Args: + parser: an OptionParser instance. + option: an Option instance. + msg: the error text. + """ + msg = f"{option} error: {msg}" + msg = textwrap.fill(" ".join(msg.split())) + parser.error(msg) + + +def make_option_group(group: Dict[str, Any], parser: ConfigOptionParser) -> OptionGroup: + """ + Return an OptionGroup object + group -- assumed to be dict with 'name' and 'options' keys + parser -- an optparse Parser + """ + option_group = OptionGroup(parser, group["name"]) + for option in group["options"]: + option_group.add_option(option()) + return option_group + + +def check_dist_restriction(options: Values, check_target: bool = False) -> None: + """Function for determining if custom platform options are allowed. + + :param options: The OptionParser options. + :param check_target: Whether or not to check if --target is being used. + """ + dist_restriction_set = any( + [ + options.python_version, + options.platforms, + options.abis, + options.implementation, + ] + ) + + binary_only = FormatControl(set(), {":all:"}) + sdist_dependencies_allowed = ( + options.format_control != binary_only and not options.ignore_dependencies + ) + + # Installations or downloads using dist restrictions must not combine + # source distributions and dist-specific wheels, as they are not + # guaranteed to be locally compatible. + if dist_restriction_set and sdist_dependencies_allowed: + raise CommandError( + "When restricting platform and interpreter constraints using " + "--python-version, --platform, --abi, or --implementation, " + "either --no-deps must be set, or --only-binary=:all: must be " + "set and --no-binary must not be set (or must be set to " + ":none:)." + ) + + if check_target: + if not options.dry_run and dist_restriction_set and not options.target_dir: + raise CommandError( + "Can not use any platform or abi specific options unless " + "installing via '--target' or using '--dry-run'" + ) + + +def _path_option_check(option: Option, opt: str, value: str) -> str: + return os.path.expanduser(value) + + +def _package_name_option_check(option: Option, opt: str, value: str) -> str: + return canonicalize_name(value) + + +class PipOption(Option): + TYPES = Option.TYPES + ("path", "package_name") + TYPE_CHECKER = Option.TYPE_CHECKER.copy() + TYPE_CHECKER["package_name"] = _package_name_option_check + TYPE_CHECKER["path"] = _path_option_check + + +########### +# options # +########### + +help_: Callable[..., Option] = partial( + Option, + "-h", + "--help", + dest="help", + action="help", + help="Show help.", +) + +debug_mode: Callable[..., Option] = partial( + Option, + "--debug", + dest="debug_mode", + action="store_true", + default=False, + help=( + "Let unhandled exceptions propagate outside the main subroutine, " + "instead of logging them to stderr." + ), +) + +isolated_mode: Callable[..., Option] = partial( + Option, + "--isolated", + dest="isolated_mode", + action="store_true", + default=False, + help=( + "Run pip in an isolated mode, ignoring environment variables and user " + "configuration." + ), +) + +require_virtualenv: Callable[..., Option] = partial( + Option, + "--require-virtualenv", + "--require-venv", + dest="require_venv", + action="store_true", + default=False, + help=( + "Allow pip to only run in a virtual environment; " + "exit with an error otherwise." + ), +) + +override_externally_managed: Callable[..., Option] = partial( + Option, + "--break-system-packages", + dest="override_externally_managed", + action="store_true", + help="Allow pip to modify an EXTERNALLY-MANAGED Python installation", +) + +python: Callable[..., Option] = partial( + Option, + "--python", + dest="python", + help="Run pip with the specified Python interpreter.", +) + +verbose: Callable[..., Option] = partial( + Option, + "-v", + "--verbose", + dest="verbose", + action="count", + default=0, + help="Give more output. Option is additive, and can be used up to 3 times.", +) + +no_color: Callable[..., Option] = partial( + Option, + "--no-color", + dest="no_color", + action="store_true", + default=False, + help="Suppress colored output.", +) + +version: Callable[..., Option] = partial( + Option, + "-V", + "--version", + dest="version", + action="store_true", + help="Show version and exit.", +) + +quiet: Callable[..., Option] = partial( + Option, + "-q", + "--quiet", + dest="quiet", + action="count", + default=0, + help=( + "Give less output. Option is additive, and can be used up to 3" + " times (corresponding to WARNING, ERROR, and CRITICAL logging" + " levels)." + ), +) + +progress_bar: Callable[..., Option] = partial( + Option, + "--progress-bar", + dest="progress_bar", + type="choice", + choices=["on", "off", "raw"], + default="on", + help="Specify whether the progress bar should be used [on, off, raw] (default: on)", +) + +log: Callable[..., Option] = partial( + PipOption, + "--log", + "--log-file", + "--local-log", + dest="log", + metavar="path", + type="path", + help="Path to a verbose appending log.", +) + +no_input: Callable[..., Option] = partial( + Option, + # Don't ask for input + "--no-input", + dest="no_input", + action="store_true", + default=False, + help="Disable prompting for input.", +) + +keyring_provider: Callable[..., Option] = partial( + Option, + "--keyring-provider", + dest="keyring_provider", + choices=["auto", "disabled", "import", "subprocess"], + default="auto", + help=( + "Enable the credential lookup via the keyring library if user input is allowed." + " Specify which mechanism to use [disabled, import, subprocess]." + " (default: disabled)" + ), +) + +proxy: Callable[..., Option] = partial( + Option, + "--proxy", + dest="proxy", + type="str", + default="", + help="Specify a proxy in the form scheme://[user:passwd@]proxy.server:port.", +) + +retries: Callable[..., Option] = partial( + Option, + "--retries", + dest="retries", + type="int", + default=5, + help="Maximum number of retries each connection should attempt " + "(default %default times).", +) + +timeout: Callable[..., Option] = partial( + Option, + "--timeout", + "--default-timeout", + metavar="sec", + dest="timeout", + type="float", + default=15, + help="Set the socket timeout (default %default seconds).", +) + + +def exists_action() -> Option: + return Option( + # Option when path already exist + "--exists-action", + dest="exists_action", + type="choice", + choices=["s", "i", "w", "b", "a"], + default=[], + action="append", + metavar="action", + help="Default action when a path already exists: " + "(s)witch, (i)gnore, (w)ipe, (b)ackup, (a)bort.", + ) + + +cert: Callable[..., Option] = partial( + PipOption, + "--cert", + dest="cert", + type="path", + metavar="path", + help=( + "Path to PEM-encoded CA certificate bundle. " + "If provided, overrides the default. " + "See 'SSL Certificate Verification' in pip documentation " + "for more information." + ), +) + +client_cert: Callable[..., Option] = partial( + PipOption, + "--client-cert", + dest="client_cert", + type="path", + default=None, + metavar="path", + help="Path to SSL client certificate, a single file containing the " + "private key and the certificate in PEM format.", +) + +index_url: Callable[..., Option] = partial( + Option, + "-i", + "--index-url", + "--pypi-url", + dest="index_url", + metavar="URL", + default=PyPI.simple_url, + help="Base URL of the Python Package Index (default %default). " + "This should point to a repository compliant with PEP 503 " + "(the simple repository API) or a local directory laid out " + "in the same format.", +) + + +def extra_index_url() -> Option: + return Option( + "--extra-index-url", + dest="extra_index_urls", + metavar="URL", + action="append", + default=[], + help="Extra URLs of package indexes to use in addition to " + "--index-url. Should follow the same rules as " + "--index-url.", + ) + + +no_index: Callable[..., Option] = partial( + Option, + "--no-index", + dest="no_index", + action="store_true", + default=False, + help="Ignore package index (only looking at --find-links URLs instead).", +) + + +def find_links() -> Option: + return Option( + "-f", + "--find-links", + dest="find_links", + action="append", + default=[], + metavar="url", + help="If a URL or path to an html file, then parse for links to " + "archives such as sdist (.tar.gz) or wheel (.whl) files. " + "If a local path or file:// URL that's a directory, " + "then look for archives in the directory listing. " + "Links to VCS project URLs are not supported.", + ) + + +def trusted_host() -> Option: + return Option( + "--trusted-host", + dest="trusted_hosts", + action="append", + metavar="HOSTNAME", + default=[], + help="Mark this host or host:port pair as trusted, even though it " + "does not have valid or any HTTPS.", + ) + + +def constraints() -> Option: + return Option( + "-c", + "--constraint", + dest="constraints", + action="append", + default=[], + metavar="file", + help="Constrain versions using the given constraints file. " + "This option can be used multiple times.", + ) + + +def requirements() -> Option: + return Option( + "-r", + "--requirement", + dest="requirements", + action="append", + default=[], + metavar="file", + help="Install from the given requirements file. " + "This option can be used multiple times.", + ) + + +def editable() -> Option: + return Option( + "-e", + "--editable", + dest="editables", + action="append", + default=[], + metavar="path/url", + help=( + "Install a project in editable mode (i.e. setuptools " + '"develop mode") from a local project path or a VCS url.' + ), + ) + + +def _handle_src(option: Option, opt_str: str, value: str, parser: OptionParser) -> None: + value = os.path.abspath(value) + setattr(parser.values, option.dest, value) + + +src: Callable[..., Option] = partial( + PipOption, + "--src", + "--source", + "--source-dir", + "--source-directory", + dest="src_dir", + type="path", + metavar="dir", + default=get_src_prefix(), + action="callback", + callback=_handle_src, + help="Directory to check out editable projects into. " + 'The default in a virtualenv is "/src". ' + 'The default for global installs is "/src".', +) + + +def _get_format_control(values: Values, option: Option) -> Any: + """Get a format_control object.""" + return getattr(values, option.dest) + + +def _handle_no_binary( + option: Option, opt_str: str, value: str, parser: OptionParser +) -> None: + existing = _get_format_control(parser.values, option) + FormatControl.handle_mutual_excludes( + value, + existing.no_binary, + existing.only_binary, + ) + + +def _handle_only_binary( + option: Option, opt_str: str, value: str, parser: OptionParser +) -> None: + existing = _get_format_control(parser.values, option) + FormatControl.handle_mutual_excludes( + value, + existing.only_binary, + existing.no_binary, + ) + + +def no_binary() -> Option: + format_control = FormatControl(set(), set()) + return Option( + "--no-binary", + dest="format_control", + action="callback", + callback=_handle_no_binary, + type="str", + default=format_control, + help="Do not use binary packages. Can be supplied multiple times, and " + 'each time adds to the existing value. Accepts either ":all:" to ' + 'disable all binary packages, ":none:" to empty the set (notice ' + "the colons), or one or more package names with commas between " + "them (no colons). Note that some packages are tricky to compile " + "and may fail to install when this option is used on them.", + ) + + +def only_binary() -> Option: + format_control = FormatControl(set(), set()) + return Option( + "--only-binary", + dest="format_control", + action="callback", + callback=_handle_only_binary, + type="str", + default=format_control, + help="Do not use source packages. Can be supplied multiple times, and " + 'each time adds to the existing value. Accepts either ":all:" to ' + 'disable all source packages, ":none:" to empty the set, or one ' + "or more package names with commas between them. Packages " + "without binary distributions will fail to install when this " + "option is used on them.", + ) + + +platforms: Callable[..., Option] = partial( + Option, + "--platform", + dest="platforms", + metavar="platform", + action="append", + default=None, + help=( + "Only use wheels compatible with . Defaults to the " + "platform of the running system. Use this option multiple times to " + "specify multiple platforms supported by the target interpreter." + ), +) + + +# This was made a separate function for unit-testing purposes. +def _convert_python_version(value: str) -> Tuple[Tuple[int, ...], Optional[str]]: + """ + Convert a version string like "3", "37", or "3.7.3" into a tuple of ints. + + :return: A 2-tuple (version_info, error_msg), where `error_msg` is + non-None if and only if there was a parsing error. + """ + if not value: + # The empty string is the same as not providing a value. + return (None, None) + + parts = value.split(".") + if len(parts) > 3: + return ((), "at most three version parts are allowed") + + if len(parts) == 1: + # Then we are in the case of "3" or "37". + value = parts[0] + if len(value) > 1: + parts = [value[0], value[1:]] + + try: + version_info = tuple(int(part) for part in parts) + except ValueError: + return ((), "each version part must be an integer") + + return (version_info, None) + + +def _handle_python_version( + option: Option, opt_str: str, value: str, parser: OptionParser +) -> None: + """ + Handle a provided --python-version value. + """ + version_info, error_msg = _convert_python_version(value) + if error_msg is not None: + msg = f"invalid --python-version value: {value!r}: {error_msg}" + raise_option_error(parser, option=option, msg=msg) + + parser.values.python_version = version_info + + +python_version: Callable[..., Option] = partial( + Option, + "--python-version", + dest="python_version", + metavar="python_version", + action="callback", + callback=_handle_python_version, + type="str", + default=None, + help=dedent( + """\ + The Python interpreter version to use for wheel and "Requires-Python" + compatibility checks. Defaults to a version derived from the running + interpreter. The version can be specified using up to three dot-separated + integers (e.g. "3" for 3.0.0, "3.7" for 3.7.0, or "3.7.3"). A major-minor + version can also be given as a string without dots (e.g. "37" for 3.7.0). + """ + ), +) + + +implementation: Callable[..., Option] = partial( + Option, + "--implementation", + dest="implementation", + metavar="implementation", + default=None, + help=( + "Only use wheels compatible with Python " + "implementation , e.g. 'pp', 'jy', 'cp', " + " or 'ip'. If not specified, then the current " + "interpreter implementation is used. Use 'py' to force " + "implementation-agnostic wheels." + ), +) + + +abis: Callable[..., Option] = partial( + Option, + "--abi", + dest="abis", + metavar="abi", + action="append", + default=None, + help=( + "Only use wheels compatible with Python abi , e.g. 'pypy_41'. " + "If not specified, then the current interpreter abi tag is used. " + "Use this option multiple times to specify multiple abis supported " + "by the target interpreter. Generally you will need to specify " + "--implementation, --platform, and --python-version when using this " + "option." + ), +) + + +def add_target_python_options(cmd_opts: OptionGroup) -> None: + cmd_opts.add_option(platforms()) + cmd_opts.add_option(python_version()) + cmd_opts.add_option(implementation()) + cmd_opts.add_option(abis()) + + +def make_target_python(options: Values) -> TargetPython: + target_python = TargetPython( + platforms=options.platforms, + py_version_info=options.python_version, + abis=options.abis, + implementation=options.implementation, + ) + + return target_python + + +def prefer_binary() -> Option: + return Option( + "--prefer-binary", + dest="prefer_binary", + action="store_true", + default=False, + help=( + "Prefer binary packages over source packages, even if the " + "source packages are newer." + ), + ) + + +cache_dir: Callable[..., Option] = partial( + PipOption, + "--cache-dir", + dest="cache_dir", + default=USER_CACHE_DIR, + metavar="dir", + type="path", + help="Store the cache data in .", +) + + +def _handle_no_cache_dir( + option: Option, opt: str, value: str, parser: OptionParser +) -> None: + """ + Process a value provided for the --no-cache-dir option. + + This is an optparse.Option callback for the --no-cache-dir option. + """ + # The value argument will be None if --no-cache-dir is passed via the + # command-line, since the option doesn't accept arguments. However, + # the value can be non-None if the option is triggered e.g. by an + # environment variable, like PIP_NO_CACHE_DIR=true. + if value is not None: + # Then parse the string value to get argument error-checking. + try: + strtobool(value) + except ValueError as exc: + raise_option_error(parser, option=option, msg=str(exc)) + + # Originally, setting PIP_NO_CACHE_DIR to a value that strtobool() + # converted to 0 (like "false" or "no") caused cache_dir to be disabled + # rather than enabled (logic would say the latter). Thus, we disable + # the cache directory not just on values that parse to True, but (for + # backwards compatibility reasons) also on values that parse to False. + # In other words, always set it to False if the option is provided in + # some (valid) form. + parser.values.cache_dir = False + + +no_cache: Callable[..., Option] = partial( + Option, + "--no-cache-dir", + dest="cache_dir", + action="callback", + callback=_handle_no_cache_dir, + help="Disable the cache.", +) + +no_deps: Callable[..., Option] = partial( + Option, + "--no-deps", + "--no-dependencies", + dest="ignore_dependencies", + action="store_true", + default=False, + help="Don't install package dependencies.", +) + +ignore_requires_python: Callable[..., Option] = partial( + Option, + "--ignore-requires-python", + dest="ignore_requires_python", + action="store_true", + help="Ignore the Requires-Python information.", +) + +no_build_isolation: Callable[..., Option] = partial( + Option, + "--no-build-isolation", + dest="build_isolation", + action="store_false", + default=True, + help="Disable isolation when building a modern source distribution. " + "Build dependencies specified by PEP 518 must be already installed " + "if this option is used.", +) + +check_build_deps: Callable[..., Option] = partial( + Option, + "--check-build-dependencies", + dest="check_build_deps", + action="store_true", + default=False, + help="Check the build dependencies when PEP517 is used.", +) + + +def _handle_no_use_pep517( + option: Option, opt: str, value: str, parser: OptionParser +) -> None: + """ + Process a value provided for the --no-use-pep517 option. + + This is an optparse.Option callback for the no_use_pep517 option. + """ + # Since --no-use-pep517 doesn't accept arguments, the value argument + # will be None if --no-use-pep517 is passed via the command-line. + # However, the value can be non-None if the option is triggered e.g. + # by an environment variable, for example "PIP_NO_USE_PEP517=true". + if value is not None: + msg = """A value was passed for --no-use-pep517, + probably using either the PIP_NO_USE_PEP517 environment variable + or the "no-use-pep517" config file option. Use an appropriate value + of the PIP_USE_PEP517 environment variable or the "use-pep517" + config file option instead. + """ + raise_option_error(parser, option=option, msg=msg) + + # If user doesn't wish to use pep517, we check if setuptools and wheel are installed + # and raise error if it is not. + packages = ("setuptools", "wheel") + if not all(importlib.util.find_spec(package) for package in packages): + msg = ( + f"It is not possible to use --no-use-pep517 " + f"without {' and '.join(packages)} installed." + ) + raise_option_error(parser, option=option, msg=msg) + + # Otherwise, --no-use-pep517 was passed via the command-line. + parser.values.use_pep517 = False + + +use_pep517: Any = partial( + Option, + "--use-pep517", + dest="use_pep517", + action="store_true", + default=None, + help="Use PEP 517 for building source distributions " + "(use --no-use-pep517 to force legacy behaviour).", +) + +no_use_pep517: Any = partial( + Option, + "--no-use-pep517", + dest="use_pep517", + action="callback", + callback=_handle_no_use_pep517, + default=None, + help=SUPPRESS_HELP, +) + + +def _handle_config_settings( + option: Option, opt_str: str, value: str, parser: OptionParser +) -> None: + key, sep, val = value.partition("=") + if sep != "=": + parser.error(f"Arguments to {opt_str} must be of the form KEY=VAL") + dest = getattr(parser.values, option.dest) + if dest is None: + dest = {} + setattr(parser.values, option.dest, dest) + if key in dest: + if isinstance(dest[key], list): + dest[key].append(val) + else: + dest[key] = [dest[key], val] + else: + dest[key] = val + + +config_settings: Callable[..., Option] = partial( + Option, + "-C", + "--config-settings", + dest="config_settings", + type=str, + action="callback", + callback=_handle_config_settings, + metavar="settings", + help="Configuration settings to be passed to the PEP 517 build backend. " + "Settings take the form KEY=VALUE. Use multiple --config-settings options " + "to pass multiple keys to the backend.", +) + +build_options: Callable[..., Option] = partial( + Option, + "--build-option", + dest="build_options", + metavar="options", + action="append", + help="Extra arguments to be supplied to 'setup.py bdist_wheel'.", +) + +global_options: Callable[..., Option] = partial( + Option, + "--global-option", + dest="global_options", + action="append", + metavar="options", + help="Extra global options to be supplied to the setup.py " + "call before the install or bdist_wheel command.", +) + +no_clean: Callable[..., Option] = partial( + Option, + "--no-clean", + action="store_true", + default=False, + help="Don't clean up build directories.", +) + +pre: Callable[..., Option] = partial( + Option, + "--pre", + action="store_true", + default=False, + help="Include pre-release and development versions. By default, " + "pip only finds stable versions.", +) + +disable_pip_version_check: Callable[..., Option] = partial( + Option, + "--disable-pip-version-check", + dest="disable_pip_version_check", + action="store_true", + default=False, + help="Don't periodically check PyPI to determine whether a new version " + "of pip is available for download. Implied with --no-index.", +) + +root_user_action: Callable[..., Option] = partial( + Option, + "--root-user-action", + dest="root_user_action", + default="warn", + choices=["warn", "ignore"], + help="Action if pip is run as a root user [warn, ignore] (default: warn)", +) + + +def _handle_merge_hash( + option: Option, opt_str: str, value: str, parser: OptionParser +) -> None: + """Given a value spelled "algo:digest", append the digest to a list + pointed to in a dict by the algo name.""" + if not parser.values.hashes: + parser.values.hashes = {} + try: + algo, digest = value.split(":", 1) + except ValueError: + parser.error( + f"Arguments to {opt_str} must be a hash name " + "followed by a value, like --hash=sha256:" + "abcde..." + ) + if algo not in STRONG_HASHES: + parser.error( + "Allowed hash algorithms for {} are {}.".format( + opt_str, ", ".join(STRONG_HASHES) + ) + ) + parser.values.hashes.setdefault(algo, []).append(digest) + + +hash: Callable[..., Option] = partial( + Option, + "--hash", + # Hash values eventually end up in InstallRequirement.hashes due to + # __dict__ copying in process_line(). + dest="hashes", + action="callback", + callback=_handle_merge_hash, + type="string", + help="Verify that the package's archive matches this " + "hash before installing. Example: --hash=sha256:abcdef...", +) + + +require_hashes: Callable[..., Option] = partial( + Option, + "--require-hashes", + dest="require_hashes", + action="store_true", + default=False, + help="Require a hash to check each requirement against, for " + "repeatable installs. This option is implied when any package in a " + "requirements file has a --hash option.", +) + + +list_path: Callable[..., Option] = partial( + PipOption, + "--path", + dest="path", + type="path", + action="append", + help="Restrict to the specified installation path for listing " + "packages (can be used multiple times).", +) + + +def check_list_path_option(options: Values) -> None: + if options.path and (options.user or options.local): + raise CommandError("Cannot combine '--path' with '--user' or '--local'") + + +list_exclude: Callable[..., Option] = partial( + PipOption, + "--exclude", + dest="excludes", + action="append", + metavar="package", + type="package_name", + help="Exclude specified package from the output", +) + + +no_python_version_warning: Callable[..., Option] = partial( + Option, + "--no-python-version-warning", + dest="no_python_version_warning", + action="store_true", + default=False, + help="Silence deprecation warnings for upcoming unsupported Pythons.", +) + + +# Features that are now always on. A warning is printed if they are used. +ALWAYS_ENABLED_FEATURES = [ + "truststore", # always on since 24.2 + "no-binary-enable-wheel-cache", # always on since 23.1 +] + +use_new_feature: Callable[..., Option] = partial( + Option, + "--use-feature", + dest="features_enabled", + metavar="feature", + action="append", + default=[], + choices=[ + "fast-deps", + ] + + ALWAYS_ENABLED_FEATURES, + help="Enable new functionality, that may be backward incompatible.", +) + +use_deprecated_feature: Callable[..., Option] = partial( + Option, + "--use-deprecated", + dest="deprecated_features_enabled", + metavar="feature", + action="append", + default=[], + choices=[ + "legacy-resolver", + "legacy-certs", + ], + help=("Enable deprecated functionality, that will be removed in the future."), +) + + +########## +# groups # +########## + +general_group: Dict[str, Any] = { + "name": "General Options", + "options": [ + help_, + debug_mode, + isolated_mode, + require_virtualenv, + python, + verbose, + version, + quiet, + log, + no_input, + keyring_provider, + proxy, + retries, + timeout, + exists_action, + trusted_host, + cert, + client_cert, + cache_dir, + no_cache, + disable_pip_version_check, + no_color, + no_python_version_warning, + use_new_feature, + use_deprecated_feature, + ], +} + +index_group: Dict[str, Any] = { + "name": "Package Index Options", + "options": [ + index_url, + extra_index_url, + no_index, + find_links, + ], +} diff --git a/backend/.venv/Lib/site-packages/pip/_internal/cli/command_context.py b/backend/.venv/Lib/site-packages/pip/_internal/cli/command_context.py new file mode 100644 index 0000000..139995a --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/cli/command_context.py @@ -0,0 +1,27 @@ +from contextlib import ExitStack, contextmanager +from typing import ContextManager, Generator, TypeVar + +_T = TypeVar("_T", covariant=True) + + +class CommandContextMixIn: + def __init__(self) -> None: + super().__init__() + self._in_main_context = False + self._main_context = ExitStack() + + @contextmanager + def main_context(self) -> Generator[None, None, None]: + assert not self._in_main_context + + self._in_main_context = True + try: + with self._main_context: + yield + finally: + self._in_main_context = False + + def enter_context(self, context_provider: ContextManager[_T]) -> _T: + assert self._in_main_context + + return self._main_context.enter_context(context_provider) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/cli/index_command.py b/backend/.venv/Lib/site-packages/pip/_internal/cli/index_command.py new file mode 100644 index 0000000..db105d0 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/cli/index_command.py @@ -0,0 +1,170 @@ +""" +Contains command classes which may interact with an index / the network. + +Unlike its sister module, req_command, this module still uses lazy imports +so commands which don't always hit the network (e.g. list w/o --outdated or +--uptodate) don't need waste time importing PipSession and friends. +""" + +import logging +import os +import sys +from optparse import Values +from typing import TYPE_CHECKING, List, Optional + +from pip._vendor import certifi + +from pip._internal.cli.base_command import Command +from pip._internal.cli.command_context import CommandContextMixIn + +if TYPE_CHECKING: + from ssl import SSLContext + + from pip._internal.network.session import PipSession + +logger = logging.getLogger(__name__) + + +def _create_truststore_ssl_context() -> Optional["SSLContext"]: + if sys.version_info < (3, 10): + logger.debug("Disabling truststore because Python version isn't 3.10+") + return None + + try: + import ssl + except ImportError: + logger.warning("Disabling truststore since ssl support is missing") + return None + + try: + from pip._vendor import truststore + except ImportError: + logger.warning("Disabling truststore because platform isn't supported") + return None + + ctx = truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + ctx.load_verify_locations(certifi.where()) + return ctx + + +class SessionCommandMixin(CommandContextMixIn): + """ + A class mixin for command classes needing _build_session(). + """ + + def __init__(self) -> None: + super().__init__() + self._session: Optional[PipSession] = None + + @classmethod + def _get_index_urls(cls, options: Values) -> Optional[List[str]]: + """Return a list of index urls from user-provided options.""" + index_urls = [] + if not getattr(options, "no_index", False): + url = getattr(options, "index_url", None) + if url: + index_urls.append(url) + urls = getattr(options, "extra_index_urls", None) + if urls: + index_urls.extend(urls) + # Return None rather than an empty list + return index_urls or None + + def get_default_session(self, options: Values) -> "PipSession": + """Get a default-managed session.""" + if self._session is None: + self._session = self.enter_context(self._build_session(options)) + # there's no type annotation on requests.Session, so it's + # automatically ContextManager[Any] and self._session becomes Any, + # then https://github.com/python/mypy/issues/7696 kicks in + assert self._session is not None + return self._session + + def _build_session( + self, + options: Values, + retries: Optional[int] = None, + timeout: Optional[int] = None, + ) -> "PipSession": + from pip._internal.network.session import PipSession + + cache_dir = options.cache_dir + assert not cache_dir or os.path.isabs(cache_dir) + + if "legacy-certs" not in options.deprecated_features_enabled: + ssl_context = _create_truststore_ssl_context() + else: + ssl_context = None + + session = PipSession( + cache=os.path.join(cache_dir, "http-v2") if cache_dir else None, + retries=retries if retries is not None else options.retries, + trusted_hosts=options.trusted_hosts, + index_urls=self._get_index_urls(options), + ssl_context=ssl_context, + ) + + # Handle custom ca-bundles from the user + if options.cert: + session.verify = options.cert + + # Handle SSL client certificate + if options.client_cert: + session.cert = options.client_cert + + # Handle timeouts + if options.timeout or timeout: + session.timeout = timeout if timeout is not None else options.timeout + + # Handle configured proxies + if options.proxy: + session.proxies = { + "http": options.proxy, + "https": options.proxy, + } + session.trust_env = False + + # Determine if we can prompt the user for authentication or not + session.auth.prompting = not options.no_input + session.auth.keyring_provider = options.keyring_provider + + return session + + +def _pip_self_version_check(session: "PipSession", options: Values) -> None: + from pip._internal.self_outdated_check import pip_self_version_check as check + + check(session, options) + + +class IndexGroupCommand(Command, SessionCommandMixin): + """ + Abstract base class for commands with the index_group options. + + This also corresponds to the commands that permit the pip version check. + """ + + def handle_pip_version_check(self, options: Values) -> None: + """ + Do the pip version check if not disabled. + + This overrides the default behavior of not doing the check. + """ + # Make sure the index_group options are present. + assert hasattr(options, "no_index") + + if options.disable_pip_version_check or options.no_index: + return + + try: + # Otherwise, check if we're using the latest version of pip available. + session = self._build_session( + options, + retries=0, + timeout=min(5, options.timeout), + ) + with session: + _pip_self_version_check(session, options) + except Exception: + logger.warning("There was an error checking the latest version of pip.") + logger.debug("See below for error", exc_info=True) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/cli/main.py b/backend/.venv/Lib/site-packages/pip/_internal/cli/main.py new file mode 100644 index 0000000..563ac79 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/cli/main.py @@ -0,0 +1,80 @@ +"""Primary application entrypoint. +""" + +import locale +import logging +import os +import sys +import warnings +from typing import List, Optional + +from pip._internal.cli.autocompletion import autocomplete +from pip._internal.cli.main_parser import parse_command +from pip._internal.commands import create_command +from pip._internal.exceptions import PipError +from pip._internal.utils import deprecation + +logger = logging.getLogger(__name__) + + +# Do not import and use main() directly! Using it directly is actively +# discouraged by pip's maintainers. The name, location and behavior of +# this function is subject to change, so calling it directly is not +# portable across different pip versions. + +# In addition, running pip in-process is unsupported and unsafe. This is +# elaborated in detail at +# https://pip.pypa.io/en/stable/user_guide/#using-pip-from-your-program. +# That document also provides suggestions that should work for nearly +# all users that are considering importing and using main() directly. + +# However, we know that certain users will still want to invoke pip +# in-process. If you understand and accept the implications of using pip +# in an unsupported manner, the best approach is to use runpy to avoid +# depending on the exact location of this entry point. + +# The following example shows how to use runpy to invoke pip in that +# case: +# +# sys.argv = ["pip", your, args, here] +# runpy.run_module("pip", run_name="__main__") +# +# Note that this will exit the process after running, unlike a direct +# call to main. As it is not safe to do any processing after calling +# main, this should not be an issue in practice. + + +def main(args: Optional[List[str]] = None) -> int: + if args is None: + args = sys.argv[1:] + + # Suppress the pkg_resources deprecation warning + # Note - we use a module of .*pkg_resources to cover + # the normal case (pip._vendor.pkg_resources) and the + # devendored case (a bare pkg_resources) + warnings.filterwarnings( + action="ignore", category=DeprecationWarning, module=".*pkg_resources" + ) + + # Configure our deprecation warnings to be sent through loggers + deprecation.install_warning_logger() + + autocomplete() + + try: + cmd_name, cmd_args = parse_command(args) + except PipError as exc: + sys.stderr.write(f"ERROR: {exc}") + sys.stderr.write(os.linesep) + sys.exit(1) + + # Needed for locale.getpreferredencoding(False) to work + # in pip._internal.utils.encoding.auto_decode + try: + locale.setlocale(locale.LC_ALL, "") + except locale.Error as e: + # setlocale can apparently crash if locale are uninitialized + logger.debug("Ignoring error %s when setting locale", e) + command = create_command(cmd_name, isolated=("--isolated" in cmd_args)) + + return command.main(cmd_args) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/cli/main_parser.py b/backend/.venv/Lib/site-packages/pip/_internal/cli/main_parser.py new file mode 100644 index 0000000..5ade356 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/cli/main_parser.py @@ -0,0 +1,134 @@ +"""A single place for constructing and exposing the main parser +""" + +import os +import subprocess +import sys +from typing import List, Optional, Tuple + +from pip._internal.build_env import get_runnable_pip +from pip._internal.cli import cmdoptions +from pip._internal.cli.parser import ConfigOptionParser, UpdatingDefaultsHelpFormatter +from pip._internal.commands import commands_dict, get_similar_commands +from pip._internal.exceptions import CommandError +from pip._internal.utils.misc import get_pip_version, get_prog + +__all__ = ["create_main_parser", "parse_command"] + + +def create_main_parser() -> ConfigOptionParser: + """Creates and returns the main parser for pip's CLI""" + + parser = ConfigOptionParser( + usage="\n%prog [options]", + add_help_option=False, + formatter=UpdatingDefaultsHelpFormatter(), + name="global", + prog=get_prog(), + ) + parser.disable_interspersed_args() + + parser.version = get_pip_version() + + # add the general options + gen_opts = cmdoptions.make_option_group(cmdoptions.general_group, parser) + parser.add_option_group(gen_opts) + + # so the help formatter knows + parser.main = True # type: ignore + + # create command listing for description + description = [""] + [ + f"{name:27} {command_info.summary}" + for name, command_info in commands_dict.items() + ] + parser.description = "\n".join(description) + + return parser + + +def identify_python_interpreter(python: str) -> Optional[str]: + # If the named file exists, use it. + # If it's a directory, assume it's a virtual environment and + # look for the environment's Python executable. + if os.path.exists(python): + if os.path.isdir(python): + # bin/python for Unix, Scripts/python.exe for Windows + # Try both in case of odd cases like cygwin. + for exe in ("bin/python", "Scripts/python.exe"): + py = os.path.join(python, exe) + if os.path.exists(py): + return py + else: + return python + + # Could not find the interpreter specified + return None + + +def parse_command(args: List[str]) -> Tuple[str, List[str]]: + parser = create_main_parser() + + # Note: parser calls disable_interspersed_args(), so the result of this + # call is to split the initial args into the general options before the + # subcommand and everything else. + # For example: + # args: ['--timeout=5', 'install', '--user', 'INITools'] + # general_options: ['--timeout==5'] + # args_else: ['install', '--user', 'INITools'] + general_options, args_else = parser.parse_args(args) + + # --python + if general_options.python and "_PIP_RUNNING_IN_SUBPROCESS" not in os.environ: + # Re-invoke pip using the specified Python interpreter + interpreter = identify_python_interpreter(general_options.python) + if interpreter is None: + raise CommandError( + f"Could not locate Python interpreter {general_options.python}" + ) + + pip_cmd = [ + interpreter, + get_runnable_pip(), + ] + pip_cmd.extend(args) + + # Set a flag so the child doesn't re-invoke itself, causing + # an infinite loop. + os.environ["_PIP_RUNNING_IN_SUBPROCESS"] = "1" + returncode = 0 + try: + proc = subprocess.run(pip_cmd) + returncode = proc.returncode + except (subprocess.SubprocessError, OSError) as exc: + raise CommandError(f"Failed to run pip under {interpreter}: {exc}") + sys.exit(returncode) + + # --version + if general_options.version: + sys.stdout.write(parser.version) + sys.stdout.write(os.linesep) + sys.exit() + + # pip || pip help -> print_help() + if not args_else or (args_else[0] == "help" and len(args_else) == 1): + parser.print_help() + sys.exit() + + # the subcommand name + cmd_name = args_else[0] + + if cmd_name not in commands_dict: + guess = get_similar_commands(cmd_name) + + msg = [f'unknown command "{cmd_name}"'] + if guess: + msg.append(f'maybe you meant "{guess}"') + + raise CommandError(" - ".join(msg)) + + # all the args without the subcommand + cmd_args = args[:] + cmd_args.remove(cmd_name) + + return cmd_name, cmd_args diff --git a/backend/.venv/Lib/site-packages/pip/_internal/cli/parser.py b/backend/.venv/Lib/site-packages/pip/_internal/cli/parser.py new file mode 100644 index 0000000..bc4aca0 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/cli/parser.py @@ -0,0 +1,294 @@ +"""Base option parser setup""" + +import logging +import optparse +import shutil +import sys +import textwrap +from contextlib import suppress +from typing import Any, Dict, Generator, List, NoReturn, Optional, Tuple + +from pip._internal.cli.status_codes import UNKNOWN_ERROR +from pip._internal.configuration import Configuration, ConfigurationError +from pip._internal.utils.misc import redact_auth_from_url, strtobool + +logger = logging.getLogger(__name__) + + +class PrettyHelpFormatter(optparse.IndentedHelpFormatter): + """A prettier/less verbose help formatter for optparse.""" + + def __init__(self, *args: Any, **kwargs: Any) -> None: + # help position must be aligned with __init__.parseopts.description + kwargs["max_help_position"] = 30 + kwargs["indent_increment"] = 1 + kwargs["width"] = shutil.get_terminal_size()[0] - 2 + super().__init__(*args, **kwargs) + + def format_option_strings(self, option: optparse.Option) -> str: + return self._format_option_strings(option) + + def _format_option_strings( + self, option: optparse.Option, mvarfmt: str = " <{}>", optsep: str = ", " + ) -> str: + """ + Return a comma-separated list of option strings and metavars. + + :param option: tuple of (short opt, long opt), e.g: ('-f', '--format') + :param mvarfmt: metavar format string + :param optsep: separator + """ + opts = [] + + if option._short_opts: + opts.append(option._short_opts[0]) + if option._long_opts: + opts.append(option._long_opts[0]) + if len(opts) > 1: + opts.insert(1, optsep) + + if option.takes_value(): + assert option.dest is not None + metavar = option.metavar or option.dest.lower() + opts.append(mvarfmt.format(metavar.lower())) + + return "".join(opts) + + def format_heading(self, heading: str) -> str: + if heading == "Options": + return "" + return heading + ":\n" + + def format_usage(self, usage: str) -> str: + """ + Ensure there is only one newline between usage and the first heading + if there is no description. + """ + msg = "\nUsage: {}\n".format(self.indent_lines(textwrap.dedent(usage), " ")) + return msg + + def format_description(self, description: Optional[str]) -> str: + # leave full control over description to us + if description: + if hasattr(self.parser, "main"): + label = "Commands" + else: + label = "Description" + # some doc strings have initial newlines, some don't + description = description.lstrip("\n") + # some doc strings have final newlines and spaces, some don't + description = description.rstrip() + # dedent, then reindent + description = self.indent_lines(textwrap.dedent(description), " ") + description = f"{label}:\n{description}\n" + return description + else: + return "" + + def format_epilog(self, epilog: Optional[str]) -> str: + # leave full control over epilog to us + if epilog: + return epilog + else: + return "" + + def indent_lines(self, text: str, indent: str) -> str: + new_lines = [indent + line for line in text.split("\n")] + return "\n".join(new_lines) + + +class UpdatingDefaultsHelpFormatter(PrettyHelpFormatter): + """Custom help formatter for use in ConfigOptionParser. + + This is updates the defaults before expanding them, allowing + them to show up correctly in the help listing. + + Also redact auth from url type options + """ + + def expand_default(self, option: optparse.Option) -> str: + default_values = None + if self.parser is not None: + assert isinstance(self.parser, ConfigOptionParser) + self.parser._update_defaults(self.parser.defaults) + assert option.dest is not None + default_values = self.parser.defaults.get(option.dest) + help_text = super().expand_default(option) + + if default_values and option.metavar == "URL": + if isinstance(default_values, str): + default_values = [default_values] + + # If its not a list, we should abort and just return the help text + if not isinstance(default_values, list): + default_values = [] + + for val in default_values: + help_text = help_text.replace(val, redact_auth_from_url(val)) + + return help_text + + +class CustomOptionParser(optparse.OptionParser): + def insert_option_group( + self, idx: int, *args: Any, **kwargs: Any + ) -> optparse.OptionGroup: + """Insert an OptionGroup at a given position.""" + group = self.add_option_group(*args, **kwargs) + + self.option_groups.pop() + self.option_groups.insert(idx, group) + + return group + + @property + def option_list_all(self) -> List[optparse.Option]: + """Get a list of all options, including those in option groups.""" + res = self.option_list[:] + for i in self.option_groups: + res.extend(i.option_list) + + return res + + +class ConfigOptionParser(CustomOptionParser): + """Custom option parser which updates its defaults by checking the + configuration files and environmental variables""" + + def __init__( + self, + *args: Any, + name: str, + isolated: bool = False, + **kwargs: Any, + ) -> None: + self.name = name + self.config = Configuration(isolated) + + assert self.name + super().__init__(*args, **kwargs) + + def check_default(self, option: optparse.Option, key: str, val: Any) -> Any: + try: + return option.check_value(key, val) + except optparse.OptionValueError as exc: + print(f"An error occurred during configuration: {exc}") + sys.exit(3) + + def _get_ordered_configuration_items( + self, + ) -> Generator[Tuple[str, Any], None, None]: + # Configuration gives keys in an unordered manner. Order them. + override_order = ["global", self.name, ":env:"] + + # Pool the options into different groups + section_items: Dict[str, List[Tuple[str, Any]]] = { + name: [] for name in override_order + } + for section_key, val in self.config.items(): + # ignore empty values + if not val: + logger.debug( + "Ignoring configuration key '%s' as it's value is empty.", + section_key, + ) + continue + + section, key = section_key.split(".", 1) + if section in override_order: + section_items[section].append((key, val)) + + # Yield each group in their override order + for section in override_order: + for key, val in section_items[section]: + yield key, val + + def _update_defaults(self, defaults: Dict[str, Any]) -> Dict[str, Any]: + """Updates the given defaults with values from the config files and + the environ. Does a little special handling for certain types of + options (lists).""" + + # Accumulate complex default state. + self.values = optparse.Values(self.defaults) + late_eval = set() + # Then set the options with those values + for key, val in self._get_ordered_configuration_items(): + # '--' because configuration supports only long names + option = self.get_option("--" + key) + + # Ignore options not present in this parser. E.g. non-globals put + # in [global] by users that want them to apply to all applicable + # commands. + if option is None: + continue + + assert option.dest is not None + + if option.action in ("store_true", "store_false"): + try: + val = strtobool(val) + except ValueError: + self.error( + f"{val} is not a valid value for {key} option, " + "please specify a boolean value like yes/no, " + "true/false or 1/0 instead." + ) + elif option.action == "count": + with suppress(ValueError): + val = strtobool(val) + with suppress(ValueError): + val = int(val) + if not isinstance(val, int) or val < 0: + self.error( + f"{val} is not a valid value for {key} option, " + "please instead specify either a non-negative integer " + "or a boolean value like yes/no or false/true " + "which is equivalent to 1/0." + ) + elif option.action == "append": + val = val.split() + val = [self.check_default(option, key, v) for v in val] + elif option.action == "callback": + assert option.callback is not None + late_eval.add(option.dest) + opt_str = option.get_opt_string() + val = option.convert_value(opt_str, val) + # From take_action + args = option.callback_args or () + kwargs = option.callback_kwargs or {} + option.callback(option, opt_str, val, self, *args, **kwargs) + else: + val = self.check_default(option, key, val) + + defaults[option.dest] = val + + for key in late_eval: + defaults[key] = getattr(self.values, key) + self.values = None + return defaults + + def get_default_values(self) -> optparse.Values: + """Overriding to make updating the defaults after instantiation of + the option parser possible, _update_defaults() does the dirty work.""" + if not self.process_default_values: + # Old, pre-Optik 1.5 behaviour. + return optparse.Values(self.defaults) + + # Load the configuration, or error out in case of an error + try: + self.config.load() + except ConfigurationError as err: + self.exit(UNKNOWN_ERROR, str(err)) + + defaults = self._update_defaults(self.defaults.copy()) # ours + for option in self._get_all_options(): + assert option.dest is not None + default = defaults.get(option.dest) + if isinstance(default, str): + opt_str = option.get_opt_string() + defaults[option.dest] = option.check_value(opt_str, default) + return optparse.Values(defaults) + + def error(self, msg: str) -> NoReturn: + self.print_usage(sys.stderr) + self.exit(UNKNOWN_ERROR, f"{msg}\n") diff --git a/backend/.venv/Lib/site-packages/pip/_internal/cli/progress_bars.py b/backend/.venv/Lib/site-packages/pip/_internal/cli/progress_bars.py new file mode 100644 index 0000000..1236180 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/cli/progress_bars.py @@ -0,0 +1,94 @@ +import functools +import sys +from typing import Callable, Generator, Iterable, Iterator, Optional, Tuple + +from pip._vendor.rich.progress import ( + BarColumn, + DownloadColumn, + FileSizeColumn, + Progress, + ProgressColumn, + SpinnerColumn, + TextColumn, + TimeElapsedColumn, + TimeRemainingColumn, + TransferSpeedColumn, +) + +from pip._internal.cli.spinners import RateLimiter +from pip._internal.utils.logging import get_indentation + +DownloadProgressRenderer = Callable[[Iterable[bytes]], Iterator[bytes]] + + +def _rich_progress_bar( + iterable: Iterable[bytes], + *, + bar_type: str, + size: Optional[int], +) -> Generator[bytes, None, None]: + assert bar_type == "on", "This should only be used in the default mode." + + if not size: + total = float("inf") + columns: Tuple[ProgressColumn, ...] = ( + TextColumn("[progress.description]{task.description}"), + SpinnerColumn("line", speed=1.5), + FileSizeColumn(), + TransferSpeedColumn(), + TimeElapsedColumn(), + ) + else: + total = size + columns = ( + TextColumn("[progress.description]{task.description}"), + BarColumn(), + DownloadColumn(), + TransferSpeedColumn(), + TextColumn("eta"), + TimeRemainingColumn(), + ) + + progress = Progress(*columns, refresh_per_second=5) + task_id = progress.add_task(" " * (get_indentation() + 2), total=total) + with progress: + for chunk in iterable: + yield chunk + progress.update(task_id, advance=len(chunk)) + + +def _raw_progress_bar( + iterable: Iterable[bytes], + *, + size: Optional[int], +) -> Generator[bytes, None, None]: + def write_progress(current: int, total: int) -> None: + sys.stdout.write("Progress %d of %d\n" % (current, total)) + sys.stdout.flush() + + current = 0 + total = size or 0 + rate_limiter = RateLimiter(0.25) + + write_progress(current, total) + for chunk in iterable: + current += len(chunk) + if rate_limiter.ready() or current == total: + write_progress(current, total) + rate_limiter.reset() + yield chunk + + +def get_download_progress_renderer( + *, bar_type: str, size: Optional[int] = None +) -> DownloadProgressRenderer: + """Get an object that can be used to render the download progress. + + Returns a callable, that takes an iterable to "wrap". + """ + if bar_type == "on": + return functools.partial(_rich_progress_bar, bar_type=bar_type, size=size) + elif bar_type == "raw": + return functools.partial(_raw_progress_bar, size=size) + else: + return iter # no-op, when passed an iterator diff --git a/backend/.venv/Lib/site-packages/pip/_internal/cli/req_command.py b/backend/.venv/Lib/site-packages/pip/_internal/cli/req_command.py new file mode 100644 index 0000000..92900f9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/cli/req_command.py @@ -0,0 +1,329 @@ +"""Contains the RequirementCommand base class. + +This class is in a separate module so the commands that do not always +need PackageFinder capability don't unnecessarily import the +PackageFinder machinery and all its vendored dependencies, etc. +""" + +import logging +from functools import partial +from optparse import Values +from typing import Any, List, Optional, Tuple + +from pip._internal.cache import WheelCache +from pip._internal.cli import cmdoptions +from pip._internal.cli.index_command import IndexGroupCommand +from pip._internal.cli.index_command import SessionCommandMixin as SessionCommandMixin +from pip._internal.exceptions import CommandError, PreviousBuildDirError +from pip._internal.index.collector import LinkCollector +from pip._internal.index.package_finder import PackageFinder +from pip._internal.models.selection_prefs import SelectionPreferences +from pip._internal.models.target_python import TargetPython +from pip._internal.network.session import PipSession +from pip._internal.operations.build.build_tracker import BuildTracker +from pip._internal.operations.prepare import RequirementPreparer +from pip._internal.req.constructors import ( + install_req_from_editable, + install_req_from_line, + install_req_from_parsed_requirement, + install_req_from_req_string, +) +from pip._internal.req.req_file import parse_requirements +from pip._internal.req.req_install import InstallRequirement +from pip._internal.resolution.base import BaseResolver +from pip._internal.utils.temp_dir import ( + TempDirectory, + TempDirectoryTypeRegistry, + tempdir_kinds, +) + +logger = logging.getLogger(__name__) + + +KEEPABLE_TEMPDIR_TYPES = [ + tempdir_kinds.BUILD_ENV, + tempdir_kinds.EPHEM_WHEEL_CACHE, + tempdir_kinds.REQ_BUILD, +] + + +def with_cleanup(func: Any) -> Any: + """Decorator for common logic related to managing temporary + directories. + """ + + def configure_tempdir_registry(registry: TempDirectoryTypeRegistry) -> None: + for t in KEEPABLE_TEMPDIR_TYPES: + registry.set_delete(t, False) + + def wrapper( + self: RequirementCommand, options: Values, args: List[Any] + ) -> Optional[int]: + assert self.tempdir_registry is not None + if options.no_clean: + configure_tempdir_registry(self.tempdir_registry) + + try: + return func(self, options, args) + except PreviousBuildDirError: + # This kind of conflict can occur when the user passes an explicit + # build directory with a pre-existing folder. In that case we do + # not want to accidentally remove it. + configure_tempdir_registry(self.tempdir_registry) + raise + + return wrapper + + +class RequirementCommand(IndexGroupCommand): + def __init__(self, *args: Any, **kw: Any) -> None: + super().__init__(*args, **kw) + + self.cmd_opts.add_option(cmdoptions.no_clean()) + + @staticmethod + def determine_resolver_variant(options: Values) -> str: + """Determines which resolver should be used, based on the given options.""" + if "legacy-resolver" in options.deprecated_features_enabled: + return "legacy" + + return "resolvelib" + + @classmethod + def make_requirement_preparer( + cls, + temp_build_dir: TempDirectory, + options: Values, + build_tracker: BuildTracker, + session: PipSession, + finder: PackageFinder, + use_user_site: bool, + download_dir: Optional[str] = None, + verbosity: int = 0, + ) -> RequirementPreparer: + """ + Create a RequirementPreparer instance for the given parameters. + """ + temp_build_dir_path = temp_build_dir.path + assert temp_build_dir_path is not None + legacy_resolver = False + + resolver_variant = cls.determine_resolver_variant(options) + if resolver_variant == "resolvelib": + lazy_wheel = "fast-deps" in options.features_enabled + if lazy_wheel: + logger.warning( + "pip is using lazily downloaded wheels using HTTP " + "range requests to obtain dependency information. " + "This experimental feature is enabled through " + "--use-feature=fast-deps and it is not ready for " + "production." + ) + else: + legacy_resolver = True + lazy_wheel = False + if "fast-deps" in options.features_enabled: + logger.warning( + "fast-deps has no effect when used with the legacy resolver." + ) + + return RequirementPreparer( + build_dir=temp_build_dir_path, + src_dir=options.src_dir, + download_dir=download_dir, + build_isolation=options.build_isolation, + check_build_deps=options.check_build_deps, + build_tracker=build_tracker, + session=session, + progress_bar=options.progress_bar, + finder=finder, + require_hashes=options.require_hashes, + use_user_site=use_user_site, + lazy_wheel=lazy_wheel, + verbosity=verbosity, + legacy_resolver=legacy_resolver, + ) + + @classmethod + def make_resolver( + cls, + preparer: RequirementPreparer, + finder: PackageFinder, + options: Values, + wheel_cache: Optional[WheelCache] = None, + use_user_site: bool = False, + ignore_installed: bool = True, + ignore_requires_python: bool = False, + force_reinstall: bool = False, + upgrade_strategy: str = "to-satisfy-only", + use_pep517: Optional[bool] = None, + py_version_info: Optional[Tuple[int, ...]] = None, + ) -> BaseResolver: + """ + Create a Resolver instance for the given parameters. + """ + make_install_req = partial( + install_req_from_req_string, + isolated=options.isolated_mode, + use_pep517=use_pep517, + ) + resolver_variant = cls.determine_resolver_variant(options) + # The long import name and duplicated invocation is needed to convince + # Mypy into correctly typechecking. Otherwise it would complain the + # "Resolver" class being redefined. + if resolver_variant == "resolvelib": + import pip._internal.resolution.resolvelib.resolver + + return pip._internal.resolution.resolvelib.resolver.Resolver( + preparer=preparer, + finder=finder, + wheel_cache=wheel_cache, + make_install_req=make_install_req, + use_user_site=use_user_site, + ignore_dependencies=options.ignore_dependencies, + ignore_installed=ignore_installed, + ignore_requires_python=ignore_requires_python, + force_reinstall=force_reinstall, + upgrade_strategy=upgrade_strategy, + py_version_info=py_version_info, + ) + import pip._internal.resolution.legacy.resolver + + return pip._internal.resolution.legacy.resolver.Resolver( + preparer=preparer, + finder=finder, + wheel_cache=wheel_cache, + make_install_req=make_install_req, + use_user_site=use_user_site, + ignore_dependencies=options.ignore_dependencies, + ignore_installed=ignore_installed, + ignore_requires_python=ignore_requires_python, + force_reinstall=force_reinstall, + upgrade_strategy=upgrade_strategy, + py_version_info=py_version_info, + ) + + def get_requirements( + self, + args: List[str], + options: Values, + finder: PackageFinder, + session: PipSession, + ) -> List[InstallRequirement]: + """ + Parse command-line arguments into the corresponding requirements. + """ + requirements: List[InstallRequirement] = [] + for filename in options.constraints: + for parsed_req in parse_requirements( + filename, + constraint=True, + finder=finder, + options=options, + session=session, + ): + req_to_add = install_req_from_parsed_requirement( + parsed_req, + isolated=options.isolated_mode, + user_supplied=False, + ) + requirements.append(req_to_add) + + for req in args: + req_to_add = install_req_from_line( + req, + comes_from=None, + isolated=options.isolated_mode, + use_pep517=options.use_pep517, + user_supplied=True, + config_settings=getattr(options, "config_settings", None), + ) + requirements.append(req_to_add) + + for req in options.editables: + req_to_add = install_req_from_editable( + req, + user_supplied=True, + isolated=options.isolated_mode, + use_pep517=options.use_pep517, + config_settings=getattr(options, "config_settings", None), + ) + requirements.append(req_to_add) + + # NOTE: options.require_hashes may be set if --require-hashes is True + for filename in options.requirements: + for parsed_req in parse_requirements( + filename, finder=finder, options=options, session=session + ): + req_to_add = install_req_from_parsed_requirement( + parsed_req, + isolated=options.isolated_mode, + use_pep517=options.use_pep517, + user_supplied=True, + config_settings=( + parsed_req.options.get("config_settings") + if parsed_req.options + else None + ), + ) + requirements.append(req_to_add) + + # If any requirement has hash options, enable hash checking. + if any(req.has_hash_options for req in requirements): + options.require_hashes = True + + if not (args or options.editables or options.requirements): + opts = {"name": self.name} + if options.find_links: + raise CommandError( + "You must give at least one requirement to {name} " + '(maybe you meant "pip {name} {links}"?)'.format( + **dict(opts, links=" ".join(options.find_links)) + ) + ) + else: + raise CommandError( + "You must give at least one requirement to {name} " + '(see "pip help {name}")'.format(**opts) + ) + + return requirements + + @staticmethod + def trace_basic_info(finder: PackageFinder) -> None: + """ + Trace basic information about the provided objects. + """ + # Display where finder is looking for packages + search_scope = finder.search_scope + locations = search_scope.get_formatted_locations() + if locations: + logger.info(locations) + + def _build_package_finder( + self, + options: Values, + session: PipSession, + target_python: Optional[TargetPython] = None, + ignore_requires_python: Optional[bool] = None, + ) -> PackageFinder: + """ + Create a package finder appropriate to this requirement command. + + :param ignore_requires_python: Whether to ignore incompatible + "Requires-Python" values in links. Defaults to False. + """ + link_collector = LinkCollector.create(session, options=options) + selection_prefs = SelectionPreferences( + allow_yanked=True, + format_control=options.format_control, + allow_all_prereleases=options.pre, + prefer_binary=options.prefer_binary, + ignore_requires_python=ignore_requires_python, + ) + + return PackageFinder.create( + link_collector=link_collector, + selection_prefs=selection_prefs, + target_python=target_python, + ) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/cli/spinners.py b/backend/.venv/Lib/site-packages/pip/_internal/cli/spinners.py new file mode 100644 index 0000000..cf2b976 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/cli/spinners.py @@ -0,0 +1,159 @@ +import contextlib +import itertools +import logging +import sys +import time +from typing import IO, Generator, Optional + +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.logging import get_indentation + +logger = logging.getLogger(__name__) + + +class SpinnerInterface: + def spin(self) -> None: + raise NotImplementedError() + + def finish(self, final_status: str) -> None: + raise NotImplementedError() + + +class InteractiveSpinner(SpinnerInterface): + def __init__( + self, + message: str, + file: Optional[IO[str]] = None, + spin_chars: str = "-\\|/", + # Empirically, 8 updates/second looks nice + min_update_interval_seconds: float = 0.125, + ): + self._message = message + if file is None: + file = sys.stdout + self._file = file + self._rate_limiter = RateLimiter(min_update_interval_seconds) + self._finished = False + + self._spin_cycle = itertools.cycle(spin_chars) + + self._file.write(" " * get_indentation() + self._message + " ... ") + self._width = 0 + + def _write(self, status: str) -> None: + assert not self._finished + # Erase what we wrote before by backspacing to the beginning, writing + # spaces to overwrite the old text, and then backspacing again + backup = "\b" * self._width + self._file.write(backup + " " * self._width + backup) + # Now we have a blank slate to add our status + self._file.write(status) + self._width = len(status) + self._file.flush() + self._rate_limiter.reset() + + def spin(self) -> None: + if self._finished: + return + if not self._rate_limiter.ready(): + return + self._write(next(self._spin_cycle)) + + def finish(self, final_status: str) -> None: + if self._finished: + return + self._write(final_status) + self._file.write("\n") + self._file.flush() + self._finished = True + + +# Used for dumb terminals, non-interactive installs (no tty), etc. +# We still print updates occasionally (once every 60 seconds by default) to +# act as a keep-alive for systems like Travis-CI that take lack-of-output as +# an indication that a task has frozen. +class NonInteractiveSpinner(SpinnerInterface): + def __init__(self, message: str, min_update_interval_seconds: float = 60.0) -> None: + self._message = message + self._finished = False + self._rate_limiter = RateLimiter(min_update_interval_seconds) + self._update("started") + + def _update(self, status: str) -> None: + assert not self._finished + self._rate_limiter.reset() + logger.info("%s: %s", self._message, status) + + def spin(self) -> None: + if self._finished: + return + if not self._rate_limiter.ready(): + return + self._update("still running...") + + def finish(self, final_status: str) -> None: + if self._finished: + return + self._update(f"finished with status '{final_status}'") + self._finished = True + + +class RateLimiter: + def __init__(self, min_update_interval_seconds: float) -> None: + self._min_update_interval_seconds = min_update_interval_seconds + self._last_update: float = 0 + + def ready(self) -> bool: + now = time.time() + delta = now - self._last_update + return delta >= self._min_update_interval_seconds + + def reset(self) -> None: + self._last_update = time.time() + + +@contextlib.contextmanager +def open_spinner(message: str) -> Generator[SpinnerInterface, None, None]: + # Interactive spinner goes directly to sys.stdout rather than being routed + # through the logging system, but it acts like it has level INFO, + # i.e. it's only displayed if we're at level INFO or better. + # Non-interactive spinner goes through the logging system, so it is always + # in sync with logging configuration. + if sys.stdout.isatty() and logger.getEffectiveLevel() <= logging.INFO: + spinner: SpinnerInterface = InteractiveSpinner(message) + else: + spinner = NonInteractiveSpinner(message) + try: + with hidden_cursor(sys.stdout): + yield spinner + except KeyboardInterrupt: + spinner.finish("canceled") + raise + except Exception: + spinner.finish("error") + raise + else: + spinner.finish("done") + + +HIDE_CURSOR = "\x1b[?25l" +SHOW_CURSOR = "\x1b[?25h" + + +@contextlib.contextmanager +def hidden_cursor(file: IO[str]) -> Generator[None, None, None]: + # The Windows terminal does not support the hide/show cursor ANSI codes, + # even via colorama. So don't even try. + if WINDOWS: + yield + # We don't want to clutter the output with control characters if we're + # writing to a file, or if the user is running with --quiet. + # See https://github.com/pypa/pip/issues/3418 + elif not file.isatty() or logger.getEffectiveLevel() > logging.INFO: + yield + else: + file.write(HIDE_CURSOR) + try: + yield + finally: + file.write(SHOW_CURSOR) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/cli/status_codes.py b/backend/.venv/Lib/site-packages/pip/_internal/cli/status_codes.py new file mode 100644 index 0000000..5e29502 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/cli/status_codes.py @@ -0,0 +1,6 @@ +SUCCESS = 0 +ERROR = 1 +UNKNOWN_ERROR = 2 +VIRTUALENV_NOT_FOUND = 3 +PREVIOUS_BUILD_DIR_ERROR = 4 +NO_MATCHES_FOUND = 23 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/__init__.py b/backend/.venv/Lib/site-packages/pip/_internal/commands/__init__.py new file mode 100644 index 0000000..858a410 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/commands/__init__.py @@ -0,0 +1,132 @@ +""" +Package containing all pip commands +""" + +import importlib +from collections import namedtuple +from typing import Any, Dict, Optional + +from pip._internal.cli.base_command import Command + +CommandInfo = namedtuple("CommandInfo", "module_path, class_name, summary") + +# This dictionary does a bunch of heavy lifting for help output: +# - Enables avoiding additional (costly) imports for presenting `--help`. +# - The ordering matters for help display. +# +# Even though the module path starts with the same "pip._internal.commands" +# prefix, the full path makes testing easier (specifically when modifying +# `commands_dict` in test setup / teardown). +commands_dict: Dict[str, CommandInfo] = { + "install": CommandInfo( + "pip._internal.commands.install", + "InstallCommand", + "Install packages.", + ), + "download": CommandInfo( + "pip._internal.commands.download", + "DownloadCommand", + "Download packages.", + ), + "uninstall": CommandInfo( + "pip._internal.commands.uninstall", + "UninstallCommand", + "Uninstall packages.", + ), + "freeze": CommandInfo( + "pip._internal.commands.freeze", + "FreezeCommand", + "Output installed packages in requirements format.", + ), + "inspect": CommandInfo( + "pip._internal.commands.inspect", + "InspectCommand", + "Inspect the python environment.", + ), + "list": CommandInfo( + "pip._internal.commands.list", + "ListCommand", + "List installed packages.", + ), + "show": CommandInfo( + "pip._internal.commands.show", + "ShowCommand", + "Show information about installed packages.", + ), + "check": CommandInfo( + "pip._internal.commands.check", + "CheckCommand", + "Verify installed packages have compatible dependencies.", + ), + "config": CommandInfo( + "pip._internal.commands.configuration", + "ConfigurationCommand", + "Manage local and global configuration.", + ), + "search": CommandInfo( + "pip._internal.commands.search", + "SearchCommand", + "Search PyPI for packages.", + ), + "cache": CommandInfo( + "pip._internal.commands.cache", + "CacheCommand", + "Inspect and manage pip's wheel cache.", + ), + "index": CommandInfo( + "pip._internal.commands.index", + "IndexCommand", + "Inspect information available from package indexes.", + ), + "wheel": CommandInfo( + "pip._internal.commands.wheel", + "WheelCommand", + "Build wheels from your requirements.", + ), + "hash": CommandInfo( + "pip._internal.commands.hash", + "HashCommand", + "Compute hashes of package archives.", + ), + "completion": CommandInfo( + "pip._internal.commands.completion", + "CompletionCommand", + "A helper command used for command completion.", + ), + "debug": CommandInfo( + "pip._internal.commands.debug", + "DebugCommand", + "Show information useful for debugging.", + ), + "help": CommandInfo( + "pip._internal.commands.help", + "HelpCommand", + "Show help for commands.", + ), +} + + +def create_command(name: str, **kwargs: Any) -> Command: + """ + Create an instance of the Command class with the given name. + """ + module_path, class_name, summary = commands_dict[name] + module = importlib.import_module(module_path) + command_class = getattr(module, class_name) + command = command_class(name=name, summary=summary, **kwargs) + + return command + + +def get_similar_commands(name: str) -> Optional[str]: + """Command name auto-correct.""" + from difflib import get_close_matches + + name = name.lower() + + close_commands = get_close_matches(name, commands_dict.keys()) + + if close_commands: + return close_commands[0] + else: + return None diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..14658c3a2100387d9e31488561d41fb2488d1a98 GIT binary patch literal 4004 zcmaJ^%X8bt8DD@T2#GH}ZP~JH*p_5dwkX@N<5qrEmZDgGNKVu^t*i_O;x0*8Aiyj@ z$z-S*9(t%IGi^LQSce|enH-XF4?gyP=*1cxf@0FCJ)InS<5W5I)NdDr45el1za|o$2%ZOzZ)jsFg#O7Y{u6B#_GA&E=jaoJ(GtP}7Ik4sfNw|_OQEHZ zz_73$E=86iC22`2MVF!+i|BHxW2r+xA|fFy;phv{Vb4;hhA@bdPTYYzaqLCN!~Y=Q zI7bsWiBkczi=*AR2lochK92U|L-=q29pLB@d=w7`&|@4O!pHH60IG2GBtC^t2hd@T zj^I&zCV-yhXc~{eUs%B_LK~Z&G zDQjhbN+s36R_DLioX)2Ox6@Ed1lyIePSPPaG-XuX@QjwTU3sBwYo?*Npv=Q?S+|*3V)R*h=fq-5|1tQ~l$3pWi@AfU+ zu1|bpU$S=}31~`rN=S{=hS~^vw40daX1>(Lg^FFS*hM*dn}rr7>0kC2x$7dWyPYzB4QtHSj*W6R=xMhaLthqAX|C8dfjrtxEOIkn{fJjp9#$XD zu@u?Q9~LMTg3&%ujDCytQQFZmzgmrYY?KRZIwCe#^;!k zul$~`d|;B-R83b|*z?pZ`L4q>K|>b)2=BFRKb&>rpEB3{eui&XG#z{H!kS^SRkK15 zEG5X#qG}b}<|iZF*d2KLs;8j<%alO6SVdwfW`5sUHfP!z^R_bwMmk}sP&?T+VSE#} zn`wIHemCP&N|ESgLjBEJsaUWjuxSNtwtMqb^%_BVFj=V-+J=X-ZhVFr`8|yO&q9M9 z@)e!;!5b9d%wPcmKiUTfNC*(Teci)cmo*A{3qeV=9JjKVoh)H?NVwAKx=IU{D^X%s zsF4%ciPU-|_{QM3_Y_{wk==q3sv~yZEyImuL)-{$gzeVd1feJ4eWU$CU3}3}-H6!! zeF@bg^^kwp*^oq3m#|nz^)MFxDAt9qh2IGq(Ry?dr9-vZP6eK6N>rG3)$sNXBS+ZW zvkkO0a_{U@)-}7x;R57>p|DYAxIkK@=fNpA+Bz4%Md>g-$B+)KR5q!tYb$QTD`vez z)r}U2t=cwC%e*ZeXXdfMi3_Q=f8x>$jFnnV{cvZwfgAOsFM|;q4}1QDrze-!O}c8q z2}_oZC$=@N=5l7muwm}Ub0#IrD{%J0KDeBL(X1`s*H)G-%_igik-QA)J+XhLPx!q| zWC7FcY&KJ_y2%`mUA9HiYv4i&e%4)hHPDYTI(y~iFL%yN?u3UM_r5y1_38JCL*FHa zcM`+fk9QLn8?)c{4Q|bD-`(w-Xgv5^a`07hYP;{7^_}F@Uq<28`0#bCr!l_=YUn@) zMF3#AvBz@fxpyx{C1FDlAcvkX_9xGaR(%8R!*!vKY?g!kdD7vR-hO@S{X7!uB8}8V zEU^4sMAc9_Ts!Kg2g?LSt=J}uD}~cHL)l#$E>_(z%P>u*MY3?N!@g?Grz36@Yxz9n z1icAXZbUcN3H9bld*(XWxzA+8MvKJ3h7Bf4edNCfe_$hPKq5l=4be zUZ;8~yO^fC+-Nq7&0IE1FG1an$;v@K|xy2aW!KF1<+(Yz@6Sdv`Z^uMunZJQC8P6HaV?;mBtl zdBBke_oCr0sTpEKGmavuXE8@kJMs}nJ_b~`)J$;d5Q=m?8+7C`M?UJvLqPRN&BL5h zP$aRr>d0pt`LH8j11cpoPjYGuMUrp(N_%~sokNnId z^9N-oJlTRrmJgCQJo0motQ{mX9{Ghw!aqpCL5>3ngZx0`-p&Kr{p_40!yg3pDv-TW zbHO8j1!Q2HY$!0!Uwh=rLD`d@Y>tzS#Bc4drnd%P^$qW&M)uGnK@gi%>=1gldYcG7 h--P(*Wpt0#ngcPRZ_8>T_-sFY8T!-4kF3a3?!SJ2&anUh literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/cache.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/cache.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1571c3560ba49c3a00cbdcde023f4d69e9022992 GIT binary patch literal 9703 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/check.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/check.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d8c34dcdc60e7007456ebdd25f0e6fe0f670a556 GIT binary patch literal 2594 zcma(TOK%%Rc-H&!J5G~2uO?k+)7GVNT0oTY5-9X>NQ2Y>hb7T!vpaD%*@rtjPL#-z zdg#Fi4yiaK$8rPZ0-X2{T!>PsW^n})aNw584M?2$X4mVas0T*Y%=dlsz4m*Jf5_$1 z2-fY--nCjugnna4yu=RB{tkd`WFnKZk;=}5%{d7*!7-S(c}Gx%5Eg9FkyI&!MO$`~ zYSKxmsSua!w3AUYAuQWjC#U9|yqb4<)Si%*v)>s%@OCqrgRTp)d_+coS1BuraAg;SpL97lJ}QX&wq z-?{VAoj{)bWNPaA>?~XkR4~;{yr|b~s$qB4BA)ADmzMaT*I2^FidNN)6}^HrAJdpr zbNyPi>Jf^~;3b1#o#Nwc+9L5B&2oLJ+cq}AN{(6S$^ap|Ml2BWYP4FTM)V=kE_IOh zs{m|6OjOQ9YQp4H-b|>1$*ZC%V96A*jFUsaV@f!+D4FtoK~1kGOQ|3`#r*Dk^v2as zF|iicm99HV=YxD@Nngc^;W<^ES_?K-OkBmTiCx3Oe);2#Vp<8;c$Ih+a&*RbG#Ari$}ZStE4H;M*ToOf{3Y-vS?B9vK$r6o&+&aT zRTraM;O+zNH0_P=O|G7-r|M}l!P2oSM05^)eo{c6mjzUpKxXoPSdh9FiVz`)%w}dY zyO}#?2|NT#xq7Ca-R%?#*ck*nSHO-8cFurQ{+NVN&o7^dJv};s`hu^FTMBfJgFexh z>XI+i1wT=jiA4Kj`B`+#f*8k=Llpdu)+{PXGaDDjeFc65->q2$Gx(CSwqzMgisdV= zM~{lKOju$zCL)0)y(`3eF_c@VQDxn$MMWF3l{d~u>>Xv@{!%z4Sjkm&P~cWH=(GhtkR8is zXpk{HchR;C8Y0K1P8K+qu|Xq4EbKwL+rH~T65#ME$S|nmU%*2q0y*yg9*~MUyu1IS zPrWs_=8+X2nDCstO#KPnFd$0Ig$ctWcy0maA&iN+@+yqWxoK-*&W8|9#9HU7R&^5M z1yOT#dlJSAo4x*II84jcb#S8QZWNBss4`H7!5M!D=EObJ8o#kWerqrJawD@f-#UHy zo00v~@9rf}HRP?4R<M9c>lP?-xps3pe%(H}(s+T7}UsdfFnN%eQ%PAl=Bc^Jw&J zW4c*<>EWfl;^gDv)xF}?#?9u~_(S{A*lSzqR^e2$|NUma((E5;_K)q{eQ^6QCH9_p z%A?b-ABZ5`?nk2+UZA3U?fXlQ$~X547q^l-uRQcaO;fR^fo4A_K7E*zLtT@%IHv4E zyNCwQG;X%CgU!OVW?|rQLD?%P0BrX>=sA>yT>gLuj;C3a?R&8D<@~oRt-is=^zYfh zABWz2l)cvK8*a?BAwuxNWrCy@rdHE}w5BdIkV}R>g&^ zX`LQ~QgBxTvF5{zM%e5nY+MCA)O5f@(#SZVUn6pkU7ckctCDbosfYZ_u-!*L2_O7A zJock7aFF0~L-(#9NF{M(=Zymd$5;Jd8D9^D;5Ys=Mv0U$J*B}ww!KP)m2(na5mxq* z8-YaEt3Zz28G{-scWbC@*j9N#_p#O~Cc++u-~~+Z;L@58Y$o=Px-Td`ug<|#H+8B< z{rw*`UKJB~4xzWpVa0|+AsPp4Mg-@c*9Bw12F}hKYS|WD*Qj3U42HoMF++13(WFSh zzk+E92PWh^(=D;s01}3L5-3M$2$JtanSPJF4HxV^^>4v;z;hh;Gs-_fBTvx4AL!Lz z(6uM%t-lijmw1X`J4_?)1MUgB@@s0iG4MDwyq6l@d2>H?_MY@iy3CDiT|Go_gqHpV D;sCFb literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/completion.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/completion.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3352d4e1a6ec4da138dcda9dbae6f20b4f588eca GIT binary patch literal 5195 zcmbVQO>7&-6<(6dA5o-4{rLZiGU9QY6As~00nHIJ*2(VfdkY53N$_CkfN7fEU1OljRO>DdMJ8PEBDZz`rdMP zNlJ9uWI^n{nR)M*$^GW0#y>WeVYHV`+&1{+sq@AYp#*L|0r?Y(nYil@KYtFtj zU#<3$xh7$6HuvjrkD_#TpiY0j%;dF6>GJC{HzX7oADbD=4wHdla^~WYLRW_LvZfJ% z)U~fxeFfarQ6d^dp#{0DSwy@__N<(&p^0l!^4}Xx)QF)m)bPL^Udb*RcY27SJQ>X34|(ciw_l2lN^E(ir#M$yl{Bu27H zA&|7&4Y@$lu9}*vW4sBZufD*2B2EU7bPLZG!HS5bTe7N~L{y0=?!mSMQp+7D2?cR@ z4@^B38t2^?Eo8WPNfuM}MPimT)gp7mnHK%fIM?j(d>tGs3QmBJXDA{TWYU*zVLqXc zi20^W`ytdu9{_?eot~klB~GFNuDSsuiI1eY(p zFAB5GQHYG`Q*N9H9_&6%rfAVvalO{8|NqD8=>I=i_bJ;X(cpU28jBb@p;ZvKip0Hv zh#39kDwfX$h*bhRJG~9%4wKT77og#0L6Z_F)dC&j4a<-pbxkr2io2x1+x&uTF4-a2 z4Qw83pB*n5whTMQI>uN%JZ z*(Wn&M;NurOrOX@9rvFYP~q~42DWr6d@!5zrxx8vU2=|SjYzIVC({Wf#Gf7bEbCq5~5g-a*!&qc9iOW z;Usl#hL!-`WBH;Y870fK<8bOj3N|V`Qj(cTncV|>IAxaGEiEzw_8>U*n^Y^97_sC( zh0&2YIJDg~OLCsh>C2WW%K5xe)-m(NJeYJ2>jCVxbD0&Yugs0B3v;GwQ4s`g%8S&T zgVV{7q{8Wq>2Pjx)5Ju=%ahWo-CkGEtehD2$AH50%QOs6f@0?H;B|-FjwS9V?bVBgZd9QCUi(&Ta3ePODDdbTzs$au{bTI>F06#Jqczu2!c}| za2E1APpcB~*d42eEbm&$t%n}F<>yuIKA#URa{1sqpjLS$u+CRN;+^1++IX%SuJY@F zWv_&~NcdR~t#EA3!Weg+W#=;MwQAo6y^_r%*lLZd1ih49?%Xe9b$NZ>s^0fk;;pC} zv3fi%tJkAip{+++>+nAB>EK}oIP0K?G|gFuJ$m`5N7cW}C+f6EDdAT0E0N`|cpUZb zdf1zF@3&ctd@ulBtMa!vAzBe9;V^8Oc<0$yxQv3+y{JMql3IleilWV7UgJel2-=a_ zZJeQbD~HFXrfy7)kT;DoDV9x(lw{K+Yt?v#C$OstDZAUf*j~FaAx)1?U7MVlw)vZM z)dV1eSyXX=>=<6pZZWxJM--}1-LgaQ|9~BVy%BB=45Qc%mr!xL^UCGvG4H+%una@a z4w(+5rBKG~@GS;K#O9X`RTrWREzeHk3vCD!Q@&x4`2D<;-jxU?0q-< zljBb=-c3F|d}X`6`+oLb_Tkly_P%EaPCSs_k)Eacwo<1yQm5X%^^5Ays!tX+Q|Gr* zmo`$De!KMX^3&9%&D3{yL&1X`cdtH=aLMi;4{dd)H@eeLA|Eb(RQyfxX?J?Fd;AZH z>(6?Q-kta?(Ru&1d#`OJj&CH6Z>PS#l{&MLI`ib*uP=OX;lt|Y+3TCBiRYnUvIDSs zkKLX4_dgGDM@9oCCjHM7qp$EnkaYk(A+*~uNy1x%B-wFEDjG^zLpmWzZ&ntm%297<9 L{)>Z;GueLud4d#s literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3f4befcfeff66edc32901525c049a42772a6fd43 GIT binary patch literal 13165 zcmc&aTW}lKb-UPIya+%b3BD};lbQp zh!%$Is2YDzsWT?qBxEM`1fG6`9=lWet7@n1NVYS{O#4BEvO%wzi86I(nm@`^#)8-owO{(D&nqDSKK}7 zrtj96C%$8JN8CH=jaQCV#;ZoFXuT~~9rum;XxSdCiPw(S(y}8~7q1_!k2j1qu#AO~ znaTa;f(yCa^bV`PjW%1DlZ@nim60lB=R2HHyYn&|aQzNnh6Ai-Jr|CpWF^39Tz}%S z#t%gmRkJ@grACv9a0~!!1Ic(ioR9(*O&EOPh38(-Y$Im}1_nn)0=(uPNG8Uk6Dbl# zc#S_DO-NeZgsg@l#SNkHXiQc#;UY9EFsA+a=+qz~Ndjdj)X51o6iZIP6n5-8MUoSm zYnnt=Ih0JPQz>`G_|Qc_18xXx20O}0mQh~fMg^%+vcAfXS|yuolkBox zb~HdIiI<(@R>=V^6|}`EyP(c3d$1K+DxhV@_CAsTEiP#BmThrEOJ&&>542R3ZP@`W z)n!|}(BhLSWsk(eyu4He?=|o>)sWYg?csx#x}tBaksVU4?1b;CAGb?&(Aog~>mhHX z{dw5|<2Jy1(`6yhr1?s=(Aezo7Ep^*gy-3CB0M3Bv1BA16M+oGiCFSH6ifCu=%lbC zsq+z?Sd>1!rdNysJ@tu5Rib)97Q+!WdPy$rEp{h~I8Ksr3W1~|DpPVKIv$m!03Enj zl%*&PGYBaKDw$oRU7`tC9)(L1qZ80lpLkN%yIev#7sHB@j6}n#EQ!-m^#Uw}5_d33 z3Et?ZV80QgUn#^9I*b9AN>IqNn9*f@g*hbod}^WyG53FwLeWi!R76Q0k0xNzDPR_Y zbH#N8mu#MRQNFB*%7tVqCW+@|QA(0$zSPB zk(hWvRi~7`J$sB^!6cd3(=JZaHJeC~>6&mkw4aFm#$l##3<;0!n9?JjPpRVe>7?Xz zB9;tGK{XneL3W6HA8*$`uyg`33@xxgm{Af<*kmGhna)E;HHT`?Pic_(sc|upOvqw# zTN^PqvIk@69q!hxdsPEq#(WP1HA%#r3A(2pq5NW6&Yp%6vdMgFi(WaWJSCXo|=*q zqMD?AalQI9=P%PSfU?4=m>Q%nXTqHzQ)v;I-;a`5eCaSw*sIgb(U&Pp{|S(ndV7&$ zVapEddGAzMy#RgjO{d%kj}L5XqP&m*`n+apz$|JHXbIv~qjW&%~iX}d{SnpGz( zO;CW$dqFH_#YXsvPf~hLOv0KMJ9=RTnIp1KE`hmhLqBW7WetqVUlinCcz(nH?i3LQv!s zf3qoZsjSfD0xp0c+TpA1k+>8B##c0FSfVBTdMl_DScFy`1i*iC53tobSjSWT5 zkKx)uU_>s0<)Ms$LfI3FCRCY#LAu8j|4=BhJcCo0wTi+Dm9#ie+&o}t`67ruSf27P zkX&Kb?XK6|*W5X~n6-=RuG;m=hV|;kbzl7^&sHAVbTf{&yNtu(+^l6B?ro4Q>(#C6 zzJ~S6qni~J&I)keZE(Kz%4QSp;3LAF*bY~5ts-ad%G$e@+2#HJaOCYHAK4FW!TK4^ zrsH4H_%NAJBE`}LO=T*N{sT62@d5G#IM3iR9L{{8whZq=t<{7m|VVjD^@{ERqEc?-}kAOZKZS6K-;cSt{fp8~Mq~!n;{gtIg63_l_Zn^Lbu& zs6G>FgfVBG zK{U&Se6piZHcRgq1(tDuZ#Tou@Dw*Jtk*6vjf^=u%cz}ZpAn{mQR~gOPKG=&YkfE# zXRMQrCVU~+_rb&)%#g=d#PT9|wzJm1w2m10G&{|_!oA2$v;UuS2OPrztHz^uq46l` zH4e-MjRR9a6R2X>1gfm5Bulpr%V1D}f1t~6vD>c%P)AJ31nkOqFm34(13U==O2{5e z9>=5?67*0L&^bgc3iME;N-~B9wdO!WGlb&ucSw1GYOMm-qeCj1CkbX32(FN!sHkg; z7PsbsRfe#ngKAE?U|OS9(IIrT|87i>1vR(1=n&Y3vgR%ko`6R95aIy9fQ|UEQveg}uGueu)ftnCLXaE@ z1{^e2R#1hbWd#p`;0dE~B$Y_lmzBEE@)rQ2oB%9cVQ%~CbH2{3uM-4p&exUob*)#| zEgo4o0$HwlSGIcBdQHP(XdwhyuBInj({smd^Ev12cYKW3H?J=BFHC1HWb1+(uBz9E zt_`hw_pW<=i;e}y8@n>~YmK|typP=#IJf7no$)oy4c)G+nGY}2%~?0?R!75neRHn9 zCtKgM?ybw5Tir9f>L1?Zn1ovqou61~e=TAXwIEqmjp z6{LF3-k7yF=IpImd+RNG+oqL=AzjUL&&;38x|)~1m64YBE(-LesEm6{|jJ^PQo7W8HnjlzX8Rw2OuXC^S z5pIHsSY8I|9Rqnk%gypLJh9Ah3zpX^cxG0hHG(ocV^P@4jGEUi68kEn<~52beT%-J z%vz8Ijx#2#DKCll;k`!w1U8|)pv44pRLOF&8yHTQ5hM=h1*jVH`z79ly2?f@EbQbg zKg&%s0io0#K?S}K{C(hPu_GeSPYnv?#BU1VA2H9rqV z`QLNXY=9kx_@N~U76`g|V473E6ojQE__*e!rl=v&(34bfLQ`%y4o}Dl`IRYhG<~qF z^w=iZf`@4+N;w+LcYFheQ@SAeZ{`nIm`#SO@%*;?*;QZXU5=@&UbHRP7Cj4|)z&>Z z@8h3zKl?`o(Q-BL7)uU7L01q%R6#&YBBDYJ0NrjHR00(NQXJzaVrnXx5W5QwKYmrg z@h{OPfePY=kv0D8$lwbEtp&|`a_G5Z{X?Xg){mSzGe}yo$U!uPAbo3GOioa-9k3S3 zVB}McgSd_+Pz9v9a9xJQttiN4AcEncQkXmq@9EA*!Q=MNs;o4bG2{p^+i zb$1!A3PpGQ&c*aXdez(ZSzWVH+Hia4o7dbenYLfKJHVdKunSMEy4pYU)NWc>_kk^r z+u?-WcR2sJwHGF&$hleP8K||Emvl%s)Fw9UMtIFXV0D2<{w`-m&A}!@=|~^2>5zi9 zJ>|UG?ULd+^Kw-|PN}GI=_B!I?-k~H&4;W7+)R3)ol+?HRczv(;8%|LNkGslLSXKM z5+Sts$x{e)3=&NMqKqp9#oF6K5gDN>CucA@3yFfByu$a`oQfn5H8Hgj=Zw!bMRHl!n5i?hAMlWxbcO0xa(#%<^hJ1_8L|3$``IdfJI0 zsF%<}ds&we--acnEnqbA$5D4P96u)RD z>r$^eq=YZYrH4vo@r`&)ca+6tV1?@|&!1SDR-^RBFY zS4IJW@^CDp-$TX4tJGix;(H`94sdxv4kH*(fk;&pL-Ya2GDhrVUTB+e%zXwSi22DP zF<)UqqL?p;ni(G8Kqf1{^gB$zE6nRdiGi+~fR8U)tk` zQy$%x>=XTD80;#PzM5}}Ks+!6;X)7(#PE`fv|uG@L1G9C>JIA~k)Z8QPGRy5Oitri z_4-))S}3qF-uGB0e@wEl2xqrLNIU2k>$EcjM%rDm=D;QZ+gpSaq#cjdtK$8Pyfd{Wm= z-Qxq<`U5Kyx9X36;b3ap=f^-_H@4mpnAT_6FRZlYo`Mv6Gtkc*d(!s)lftp5D#%5s ziJ%}i9~4WJLH`X3R1BIeMR_@9EI1nFw7AJ4z&s$GsLry?as_>Ewo?|$Gpht~G+;i1 z^?|%0_9$73$h!+j+j1XiKVgtImkyo;wY8n3OAoE#JP^+L@DL%PrmaB0qF)&f2)eQ0 z%Nq*{#)NcwBV&LHoh;F0GX*Z9Qsa@hbaRb|_kzR)(ZZyA%Tm;XXn75~C`kA~S52+C zrrvB*Z?5TBw&~c7gKJHvb4}mOHhuHsrjcu>=Z??&H!7Qc*u3FwUix-MT|RruyYCB* zscM;T20Cay!~Ujn=X~=$r2(#n`;?m%=owqFF?raz+D;xf9Hdd_Tzsb8Iv2AFvOn z{R8wq1)h@TBhMmSG$2WkK^QJUr5M!M_VoS%2)iR3hQl!guZP3+`y6_d1tlF?4Qe== zz#As*&a_2rKLeq6L4ottSh{;qKiq{2MleG}1~UTmZT=DumZ3kKrv{u_Wl_LLpGp_N zlvk*#R+BU&PlGLRMw=f~b4D)6k&7X?=@io{PrwHZC)E>hRw>cDYMLE;QvjFKlxVDj(prlpZ4d7JH+W0A5RFO|G&lTiLa2 zTdRD0&U(AxB<{<4_pNyk%n9oi-nkLH`s*S!Xy& zFygVSWNm=i;3Sb9fdi9t|1)p}054@F#d!E4+@MOq#UH$;V;ohB6F~gj?*J+3-je{5!Z0Y@v4VrDGB9We8?9+~Q0z8P(kHg3?WV<@wzLNdG0gx+ zMqr%;od-RzXhei4MWSy?@u_ifWnz2S0?q6PM1+b0PhS9(f;t9NLWO5e{p&+Z?Dvk| zu6pVQdtKRN*a5a>qh;4mCYQ#R>sPu~8m_m)*276T2hl+Y@l`i1?fcu_Rafin3fDaQ zy(i%SXo+1oI5&K|x^C{Y?pNoPGR%S-PYuc+Kw%M7GI%ji+WwR?DNXTi2-!Rdfk12n zPb=@|mGkZjDgYq!W&{{A#@ept4@3jpaJuho0`HI@HDJiX*c#)0S5SODCWql32$84Y z^bV*3FL%Ko++~{xrgxk&ZaIilqy#~Z9D}ce3l%Vu<`{e>BGa1|;A@nV&;=ssR;wep?(*hbEm>Df&ef51b$sOV1LMOv7Vp4= zx16gP&b!vVLvTI@Cv7NBR-1a(s$e&JHyr?TPeIfBYU57k&E5SruEa6GJ*4}%0R?aj z*mAr0SFZB)a170=c{ih6AQn_~^}`_~R%c)k2LIcU=miEinklH%ybpbq4e-NoznWe- z(yaQ0qjY;Y#c8NSpc%N_1GkNIeSro$wFdFBpw7XTLPVzc6op{OG`*|*Ug!0*aS-jr zoyK4r=#Yx4*NH=It^EcPw*EnUb~cdfd* z9@6v~Dw(I&s-9kTJxw_`U?D!3V>r;P*+cqacSv)F@ccOi2N)sE6$*V9E<~a}g*RI$ zBqbwIsE$q~;8swG$lpyxA;(KWVAU#c6^L}ffCMRrpp1sYewAn(L;}bOeC5w4lQDv< zOpr_ISqQ<|N(H4RUYH}qC zD14Q0!feyU3+)*zR<$on zEBoG#(&F{w*xHV*9hq^g>R35`z52aVw0NTvTRZgDU3x3OGV-2-7OzW2t4DZh8CoH` z&R-w-CuoJ@4QPdIQ{;vHD?E1Cf8B>2_HVhY!jqd`pKy-FDKR(a#4=8b`DTwxsL$}3 zk+)z#D6S09?7E)a7}&zft!4*&TdiH_XP0X?8O&D(?$TV}1;l-zMYG{m2(S_LFwP8A zYIeB(q+duw($K8x|Xxw((MGG^Pa2Z$+;U0#zj+ zphLu?N<>%i7(dYPL}G~E6(M-ONA(1yTJj@&?Z#vm0@@Gje0Y?+1+PHOx*iAh%(9;{ zo=+Lar%dIqnWo<`yRyu#|6-o_4Rh!Vi@;j87)XBaV%XrXvGVJ;9gTB!IY(pG(YW-r YHAm+a>s{+Hp6zFs4*s5@1v=~h0OyA$6951J literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/debug.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/debug.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..80372006952dfbabf31e88204a9653eb75c9599d GIT binary patch literal 10070 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%0D?!2%TDnc)Y%> z=iZIH9l@pL_xBZAi;L<0p!G*>%i>`MwflPSjs9!>E1f+{ojuFqv3p{}vez&c)>z)7{{aHfnsSGt;XuERNGlnj`KO3*Jekl9xTc5N!{=iV!!+bCMKeNcco?Yk zKNdYiumv9Qm(&RbFiEg$WGqdWFQrA4|D%Osd`7F;JW~opv=jsTl07{HHh02PLsALD zLLug%zu`WBUk5Pn1p{^3_N`E)5=xwjEX@IO0wUb-2NjAglOEJSqSD3M4y<9+PJbT3 zKr0LVl?f1ZxpZ3lKGur#r-?^&I)9qpfDRB8L_r@M0;wGLG4Xs%ydM+C$He&wssDsD z{0HeQkj~!_|0ksN6Y|V|k@io>0s)aAT@#h-^KG(PVIPW41f#T-ZZ;dWJ zadHFe>$}`s)lGh#Kygd_dDTxm8(3X$@^b^+&C|D9ZYj6g-+y79;P)?u4OVXKwsMEo tE9$w%xr^%riiKSpSgarMa*gvx*9jDhLmOD!-`T;{&K>+80tGv({{`x5DoX$W literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/download.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/download.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8840fd003614ee9461cee2fccb028eb202d6b8b1 GIT binary patch literal 7505 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..21dd31c1705ef23d7722d04f9853a32103a3c9c5 GIT binary patch literal 4387 zcmbVP-ESMm5x*mk(#v#*vareGXJ{R;s- zc26p%VJxA{DC`TAI8X)x!Uuw$xF_gI6x|AXniaDvVy^Ecn_SC@H2iDLY#@>g(D=_v z#KBtGxsDtveP|E|UdPHc-L5-^Z4sD7F50!4X6bBr{pQ7sm#<%EA{H=0O$4Jjadgut zsr97_p<#@i2DZxHwq75A2h(Hs1a#|y<58invNt_V7ngu~UC0Hl!&272nGV91X3mtoFD5hIM;7WUbW$aYcEi+F(x}%l zB1A1U44C?Y3C@BhOj9xd-Cf}y@xGn-cq=}>QEA1Gej^>l8KCd83;Q^3mjVnRYQ#lx zO>jh*@V4bYab#6kgh={IY{DLE!YZ>)@EQ$*&KKBv8v1k*A(O^*a33~G4F}N}0YB6o z+cv?4TsQEP#9Tz!1`1|c(x|GVW$rjU4)cEalS%0A3T`5O|IFP>FCxdbBPU!r@w9)o zCC}cMp2t&nufF*yVOYf4?gi-91tb(jT_^^0u^7|?MM)19L%LK9>v25-AsW$TBtzgv zQH%wy9zyYjFc0U%N;sFG$@h6|`El306H}ml)NtwzM=>noXr_sDrQ)^dA5PDmc zar87@)B}1@mnvW&J^UoH74aCvw~+y6)?;Aygr0oTx8=L(tt6!Me!e~p>wTPioApiy z8-;2oNV>kW6XRRH#ok7;p3w(DvurimCD0%0gH>ktp5`Pwgx-BS`#%}ll02Tb(qvd4 z0Zm5#ztvq9>g(wD`q`@~*NYw0o>pZCx~J)52S?kMkGrC7;q{Xrt;$nU}Y&4WFf3E zd{%6JunWqKMT02b34_CFDJ7&d2pq^-!*q-~NOFuCB86OtN;)DAC{<=Dibiy_paBn! z)R3bsYnV!l$gIOxnaxN(Z`x(eq#^GSBMxK()xiz)e)Hxp7Cb0eHn7vsOvnuIC7Pow zYDB4+c1bf8$RmLD(~52@mhJeu`Y+8Dh95m>RLDvAF!%ug~CZd39oT7Fp&7+q+iqfHU_E8qFUF$dxvxv&Y zs0@{Z3O*z>rs;eH9>VP4(<4BP%UgaTEP+V%$wn zx&z~GcF4_+wWUD%csngbr(Ow(XskUZM3X)IgKm1n9hh{pqisn{&$LsVIR?x_JG#@k&KCy0zI}XOkL^s&wx(vEO`X}6&-Umy;HD=)1lwuo`=LXR7B+7D@zxi& zzFzt2vu6`Oem3-OJITe$AU3m4tea5W^kKGr`fNMOnL@yn*vG{7KHHi)`)q1%TR!(3 zY!iPF-;s~Ej3@=ti$rx8C1Qc1%VQtnP%42XHEbHTf6(=)GMwsZtCAjQ0`2uz{`Qz8I1J2qaBcyu@H7abVk|cR6+Ln=a|ZqqqlFuF9r!#zkbNv59(oLw7g2dh-NO(c z5-pnVcl8Q zy$2nYOv6Hi6)>y-^=sxJZdlFqevARqE#M-5h7L;qROa{Ro~0)5OKxgtCpGmnH3bOs z@aluBe~5k=-%cEP9?!tt;Awo^CvQY{MozRwPHZP~FXYUQoNLLs&EwnhsTbKXcVu#B zWV$sn?GC@QzV>L%9hz7-ADM1ubbb2Kv^#icXYgce@T8j_bSIANOw6_>X8)U#2V?gy zy~+s5{)bl{T-iw+Y9$VB-1yU_FK&OE$h8OH^{cGVKYYKBAL(4cD_e6(Dyyoc)sU*v zn9A(dFxfbvs-Hl9^xs5ORkzDP9xy5v%cg!PsO)M*Lk$8KDjGNKiVC+8q}2#M4Q9a% z7%;OXxZS}t2$wBCi*IpE}q2Z0wZ2=ye+0F9fQ9k@DdBrH6Y$h=`=tY1G5awkVrW6f3D|IMD zFoPpc!!%s23VYYVLfJIDD17G)dZ7f@2-UwYVg_9F0469BoCX0lC|r2J(aHUi>^iT8 z;KE(-k~|M=I<}vy;TR?y~Dp^+Ou1nXTkkerSeZbZ(hLjz`}r; z{2aP=P!z?#3$gEn@$ZEr{}N7oC!E^*wZo!#Y%{wnz@sgP#s1IFZIIT$;avg7uQE48 ParpBO{v)s_xAFe~VVMcb literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/hash.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/hash.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..43f8dbaad425705df17aefedad79d10c058c458e GIT binary patch literal 2970 zcmai0T}&L;6~6PkGyB6&`B{E!cU+8|jmpwSwOyka$-*RVLa_uil{Z9_Vdk)Dyj zy|X5)LFK^@AT@IO1P^&grAon~QuEN~s(q;{^(Ba;&>JF0YAdyG8$lH*Pd#^L7jTQz z3w!Q4=brm_&Uen8KW8#Y1ntLf-f}-u5&9b!S`Fl=9sLfvP2?a)@K7P{g@O>tVnKvn z^rVVhkOe*_c}hhss1YxFiHcUxB3|+IO0tlwqzb7>R=sp3Q^-`>3T=^`@Y*XKg^o&R zp;JI2!b15Rn{NCm}7Ix3u2brLw?XjsE~KiE1lPQpEO7)dQFxfDy?wP>k%;`)0@0~$!M zA2uwb1Y<_92%Hz#mS5{?z^88+ zFY~G6Mn0dPV=BR6jrh}cGlG$0GC(Ex9sLu?CR#z|Nc}u1bBq6Kj^K!n6v{2NBZn;? zBS$IgE&XZlsO8kD)Z$K8*lC`t)&DxNlZdSZey((D#%W(}KjmATqn&?;9Wk~L&@#&D z({*vgs;5RqEUy>J z5_TzYZA_VJ**pR);owE9=7mfyVXsQ~8FCua?22PTj3`T5PQ-yN;VvT@5T-5$q+-FO za^U(*ty+X)!nz>Xn1p;Hn43is)T%s-DE1a9_nq<0+Y@8+O96R60e5)bFNbu*vhASe zhpt~7vEfql3xG)MJM;O6*nc=bh!?0o;{Na`7;9pa2RR=Swja}`blOZv#%MunsJcsI7s&&bY3{@zI@O%z-i}={m${- z&hdke?oIs{`UfL>9WNY7;$+(OB462(u#Noy#;Prl|!C!QFDY9c|{6OFwCVEN_U!hC7_>QkWtvtnlp=X;&i=Z zn2sgmYH1O*3e(uyCBw2Uf+0q zKRvXY9{Sb9N3Z?zwNKNdhh2T^Q(txu?spIGb`P)XpLh4I-#JY89drzRIJbTCx0T=D z`BQH1`rN-IG1JzNP*4A{hB~tAZNz|ub0TSjZaSA{nrZr01)C;Inr0<%Y98m)ruk0I z@|q(F({utG)Jp7-F1P4I3Yg8>YVr&q--ZPV#|Ysr2d9OEN#I111Mw+}_Khx0c;F(! zBSvokd5pdi6-8^bp-gUV@?hZ7Cvx^kPAg-L3rQurb-jV0+wR`BpY})W#}ojqWaBlX z<+#t{u<(o7%^C$PLOfy-b{oKKqVS|@ufTUe3n$mmsu-RizT89&pWbRKLJO&@QrN7g z2r{9i1zdJ+)fb@nQBaJ-PMCCjPgS&(fE^l2Gr9Un?j%(9jU%#rVef zUTW|YdGKrfe|6tbo}usExP4Lj!$sxxwM4FuTn7zHctNoUb({=yNrS2vKMXwlObwT- zd@KU-B`D(glOmqCJvYB#QEWD=IpJ4i=NQ4aL|CI>29H@>F*sn@!1K%1LKi+bxXZwb z*S_fGVtwaXRa|OEv53o#Uc})P+yW}ni_xk1l|YDc;d^|k$lWh-&fp}fHrmT^f{&9| zK*#fd-Urf<1VQ*5wMGBQFVNr@DEkle(ld1P8Jc*8#=q1D*0cNiz^*>9^}{{=%9?tt g4hh-!uO1`l8dHKQT-cHt2)gaK`&c^WQndAd026b%4gdfE literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/help.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/help.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..34fcf7612528ecc5908e14a02a3741fcfabbb5d3 GIT binary patch literal 1675 zcmZux-A^1<6u-0cxeM%4pim&iDXkVvSQHaArZiSUtVty?Xp^p+jKj?Bc9!|r-aFHU z%@P~K0~!67Qq?3CJgGdbsX&YXMhxxahv z{jsYnhhV(_@wDSg2>r^9bjWRRcoo1pvXL#g$P-F}z;VXScw$M6vFJ*kT#{ofxr(Qj z)ELXI=4DG+0cFs;$W~U7tzvmwO!Ag;%i4JMcW#UeOu1^h5vG8oD-I1ot22S;nZC{8 z{6{l0v-9%+JKNq_LIPqXnG&hAjl(Gb>jDM_|il5Ghqwv1J*4ML2q z;Ouq9R#&B@6xMMWyR~-yM*sYcpswElkA6KMx|I||8~r&w9xv8NP|+{6{TDxEYETQE zz^6a{x1uzarg%#r zZ)Z?bZYtX_hmRH27MsdlWJ}+Q6=6kds^nx-t9B)SpOv=URFk-Lu7JWq8euEd6DdB{ zO)ZU0^=AUCFFmt!P=x^bUza~_>Vp_ay+Lj?Nc_^*|@1`&0% zBwj;xVO*Uf83-L0Syy@jhV57(%UcASAvW4x)>pxyK^@O=O_Dlk<3!{y`a#`Kk53ba3%pV$Jew!#6$5 z*er3W62re&})*=*E zF5bfat@0ITp-i0+Pr!slvw~?E_B;7>zmw@Ylf2quZJCKA@*9O`u0;_XoC3ND;x_s_ zBV}`cAP@(gQg(QMV0h!wo%-740}XZdZA?Gt7~Aa|+d8$=H?=mqfAXcxrOoPnq18Lp z>UnK#X1CDysJnMPcPH06UEGScD)&EV4ZrcQ`_0EaBOB3ojc*!TXYYQx(=*xXocyIn z-#oR`^YWVdNGp7m|2+SbcIJV0=Am}>aiM=L|Ig72sC(#7BxHww?j8DK?mz_eg!2CW zQob~ezMn3A z@qto<;G2;HnlnoHZ6@$=A|}$1FcFTLjDUF$9fCyUG#A-aa6n%Hv5Iyj{Xi1B25-;q z4~?{>fdgq!9@u#O0D;=-+p_Kr#_&Ep;vO=VriiPDmnP{hzC2UH9PUz#RyHAV`qlA5%w)G6hirMNt$jky0v)k}O+hWRX%TL>>%?J5rzy zf4p}PMFwm%9(|xvcODV$yb!BeC~(_wBoVyYKzp+x-`>*G=Gg``agz-w6=%A6T&-)+9Ea3?Yw* zNJK^^QGDBECS{A-7^Lm8J>`fxQf!n>Iit>$E9%nQ9Ws~Vqr6VDvO855t`8f} zUY&NyzEpj*KIM=4^*Sdvqyo`^PV;hOswvu(3Pyve=4i9t=9XJhp=d~_>*Ur{TeMB5 zJ#u@hBif(VSP~a!yjh4$Xc#J+E;WREfr?WJz;eOe(6zeKV^j zGwHYttgfpPRiFZ-JCPDIdXECNh6`y?x_zEza@jMPR4Sep!#0gQd-?J=FKe!eD`(D} zotOZ&jx0^4)tCr!W689l#$`Ed(edngYttu-!+F;(~fSXKvsn2BT>2dIV>MROyQ(X2HmXVMue#i;aN zE=eWD9HrT_RMPl#CN`B!$LYLQmr2X>R;3{ozX=ecLu70Qkx{GDoz1K`vvI0ORBHqv zl&D(63E=5aBzanM8zXQ=3aTIoU&qg!xIUMmHx+P5>3VurRSv}y34lg5nVvb6fO%e@ z0^gR>;`PWaDShku#pKj=1>o$E>A}kNY%<#qkPA2uu->0A09)zTzZJ=X9^1Mr3!w{$ z5GKAvs(J*NkMgfj+#yf7K#@CG;0~@%{`B3)?{07-&pFS1?>%pk6AGO0xHh@ z*Sp3xxU;3&uAg*%*ty;{u)!VK(NXLgDs&C4cMWfFuf5bYT<98J?>fH0o%nfhPcb-9 z2o5~;G#5SH1y6U$WK~R7z(UzJNna; zk57KV9p40fh~_f3P0<`+B}&4Ko7hDVVRVc`zkyr=ZCvlDEt1TlT{UfxkXb7OsbUgs zRfuGxuDngOBf#hFw-|b~YV0nECptuS7HxUQqgvq!q*&4`?}|sL6~vh!)>juDJmeF3 zd)}eXfq{0XNZKmC%n-HW{}W^{Q7hQeL+Fu3_IJ-W&(7|GEr!0<{NM|fc_nPuAR}93 z|Ad_|-*e0yxoy8j=9sW+T;r^;w4j158!=2sDncShA;PQjybw>m{XG64$SGHwrD0r=Gz5i}x;;`~xL_(* zto!@6Si9E;BAQy4E!PSDNWBFSv;_ATak(C=8p8hR2 z@wY7bezV0Bf9O}l#7i;KVG$vZx_Tj}_sQ?0o2u89(xcjoOMJ1qVQ5@r|PavR$z2xq7iS0ylA)2M`L z#BnObvyi}n-C`$LrFug${ls#Gii9wuo6k8+z#${g%*E#8>6?*&ITQLcX(LqV9xM<}!mcXo9l=%{qkn+@ z5mKk2P!Ir3Z4K)U#-?&fS**B`q47d@jXm$mGmi4!hT;y{Y9ejD#nwZG)i3q~!=;YCQd=){`Q2p# zen1a^#F{99Q`XG~H?-P(@)gtU6Oas)^GP(RNi6DXsnXGF1kP> z!qtvP;o*Qp@~&!56%9jw@-9mfjCUzMHE8vSuDs)~$PX(k2&+`dB=d08`k1#e$T4!C zOW0;e!uGD0kVQ_#pr${0&XWGn_CdXaEb@z7o;M=Vq8n}j;Lnl*5vjd04!$h9zw3sw z?uQj!t2so^>?;=c_FMGMqP6dMzRO#)*!c#DT^4iRk#}#;WgfI);J3)lLHr#c3Nr`w zYlMNn53ZQ8(Kk*J#25Bo%jASK#wT!nJPRhL=OG|MK!DhoNdsKanH+{jBQbUu@uSuQ zYmRo9JPg8b^C%Q=!6zTV0qtGbTuAbn-4dX`WF9dvv48^-@V~XsF^?I%YjBwn4-#Bk zQZ(t&d##{`tqR zeWhR?`+h?^^L?cP>y;VG_5GO1Od2f=$@3G2w;g z)0ImFE0sARd}opNgK)T-u**`KVxnlAy8`-&s3!1gJ`<+RxJ=I=H%4Qv5m7ycv1i*z z^vI#v6-lLtLG&0h+F`o187Zf6+d+r04;-I_>#E|5o-<*5(b)HL5}l`L?l49Vmo$PE zJ7}Q=3@MOsRp)1DqpE_~X@(+v>E=oYpmCw^|6!;zFhDsCsUe)4>U>M;pB`UkzIWnh$Rhw%NCI?u8F5zchHfIQVv9@a@l~jls!H zJ2Wl5QHGqX{n5yukGyc$bVGsmj=%#BLSd+V`L(}TTzcc*8{3~YA1E~+f3ojM%UaWE z;AjbeFEs=pp&LH=q}a!qT&L&f0HLh$G(lmBq-@2;(VR}OU_9KUaj{rBo|0lQ%^i!SGGb0f+7pYtmy640k1G}vGYM#J ztUdXIL8NbKY)*kIMj8g86oWU#1dmQaq1oY7O%X9DMlFhI0L7aO%`uh9$a>CWm^fmN zZa9yLo;?_r6v9?4(43VYL2;M7u-RA+cBy^Onxh4CZ|=_7P0q)jC<`5I%kr@@f!Au& zYT|LLPJW_nVoQ09Ap=9DfuR?5Ev)-_Lra;3ciBk-9c33%90>_4oUwp=Z&9U(8;ySSGTaqm^;om+^f0p5CaIJad3P# zZZ~jwG^aYBg=VVjjH$7)V7NHiD{y{`;IfJt8Zk0hJYkt=LJ_632A#*cuZSe%q=6^K z*y{EO+|WQqs$W1;H;(OmX>0_pozTUIWg{i-t`%nRSSLdhl`u)xdTJTLW+hpHdDUjym_TVe zWSXoskZaiEjr>Hh&a Ck~y3J literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c0586953ef29ff7037ea151a5c4f3c9ba30f9683 GIT binary patch literal 3982 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/search.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/search.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ae665ba3241d8cb4a8b59710dbae0c2346d5cdb0 GIT binary patch literal 7520 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 O%LKrc!A)$K68$fC0}Q$V literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/show.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/commands/__pycache__/show.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bc77d3b4263b4ac05421c1ef3374ee3dd8a13265 GIT binary patch literal 10479 zcmbU{ZEPFImAmAUTz-Fx`qoO8B~!NO4>_?dTW)O0AF^cG^+$>**0B_KB~#{yvP;<( zkHV>N4wYNuEGM|LiXN^qio!CSL)_wk2Dm>llA=8{0YsBNGJERPy{16>;|@%u0!iB+ z_ueeOB+I?x2H4p*Z{EC_oq6--y*K-Fv)MpFI{kW2=zIf3{Td6!#1??nYMP?%Qar`e zVQLuPsxTc<4XbE`)nRpn8D=7yVNFCktc~b~brE)$jp&EIBF14Ofi+=M#5`;! zur_RoSck0y)`e{m`>;LY7)*X*iFj%a8<-J?4cO=8`d$#^Ih4TOP>qd$5z5DxL@gg2%_q7V_HalqPx zfoLom3PMdn@JFF3Aa%X5NF)&Dy((FA?A*CC=Vaaai@m+a&YuU2?Px#}`k*H0~F%~VbH(e7$als#(ice0(gZM?oq%8oe-2mK$`5&fvYFNe7 z!)jhN%<$@A4R7GJFdJH4C+K)qU2|W2MIA; zC^{AsBLN&D7Z`;haIvVs#Y8R=69uT1;(>5j;JL{_@Je7@kbDNx_QGW#BID&k5|DA{ zj`wy3W0A>lC=iWvkw7TST^0hoAaV+SA8D3oB`=QKIw{7+xz}T4=A{wtP=Wtp&gb)8 zkhP)^pAw@(!Gd6sX}~RkBDMM!nT#YgLD1{7iGt8oVnMJ}yqaft4X=Gi_pmUjGzA=( zN;(Ce&^?di+0A=27*MKbOlk8nae_WQp9lp4I7N` zewb8AHUxMAq3CHR1EM5|vJ;k55aUPyX#cnvo0;e3R3%u{GX!YgVLLC8*du3YGFJqAnfsEP_x(pL5qw-jm5Q(pB@!ben4H+MEHfac*~dtD9j0v9Ms z5Qka|_cgvHAE+n;3ZGw*QQcKR9F0kWmzA~Q*!VaIi|$%LjKZReX6Q(ENkTvjUiKGP z85VdfCYvWkSZKc}NTAdtu?i@~ZJ6QUyc&^1xD~Ulkja`irUY?X))nX_oOV=1oY;)j zYH=!>uvSV0Aljiu>W6HW`o!v7F*$Az-5gr38_1XjSDe*zgE^aPPV=dwZE-5?=$zB7 zSnG2p=c4Yu`JVaFwIBb@5C7)(YL(5frlnjpbAv0^syU0e1-N-tq6=O_UX#rFiAMMP zWrN=ziSbim0brBg|Hf1xjI#wLo!`&Lf&gfyB+!Delg6XCsYT_O@Z(kxTY#a6VkDvj z$ZAmjvKr<`+zG`86zP|Ispv!^%xv&T`yhLh`b@=W*u050x6dAXR@=DDcvcyMraND4 z)OZ$N&QtJOaxDcP)DZBIw1yakCvpnHQ%X1pOsl_ztbA--qy)9V@bn?T5=d2o)CAH9 z|hLp9XvSveBTWYB*LF@(^eW}J!f{YtzOr;ug39^(R>jr8YDQkqnxbUEZvDy(k z?eIEb(atKzR6j~5gNrAlXiKOC*>EgK&N;b8;6rgV3;eK6CWK(zU#emYD=Nvx0>t}A zr)7QdAQWX=M2H9YKs*48t}r$R!vRSOjfJ2r>!c}Acp&BM9Y;8`i_!l9r5+F3S%#UW1nCu1Nu%8nZH>O{1<#NC+f!R%$oWUJpFh(=>^ z@=cQ8FQSGaq9^W02*q3xH#8nZ%wB>=`UYfwOXUpa8~r)6?Z#lvV!v@Z*VMkG{?1IA z*^#q2=DTi&(u^l(ch3j!)TEi(oYiq-C|3m_sN52=+}KeyFWvE`nYx_GdSf8xaHko! z!n<5!bk6rJIPdhQjExzlQ5hW>SSOASH{-g)9u*{h!Rmj)asADz0g47eju(_JMLmQn zOfxj7&7!y~D3TZJ`>5NhpejTKRU=lQRwY%N9r;Ps+p1f32B>CK->OPd&`KRtjbkg& zew(ZGJE~h&hMHlZwxrtQ#^Ml?RFWwg2gvQVCa5O-K*e8z!+J(Nqe*IRR$Zkf`j#=N z25uJUAFwm!LqnU?id*BQLtz5GU}HklX2QM^OHoN}@#raz0&ID8+))$byXw1N6`vw9i7Uy8blC;dKdE<;VYOI(yOR2pT+V6P2{fsSX zo4~VUL*h;2RB0aUK!b{5L*mW6r9|UMIwUb^@1sT{um;YgbE0blITU#-Z+pjHY(r$! z1+=aSR2myn@yjOg=-QBYN4e)s>zx(#2R1Z@Vv+ZZJL%?KSHPTr9WnxA{&Te8xkhP* ziXSZU<2ynW?}mBBvtdJeo93&a=I{nI6rsigHLpBhbDfsZ

!$m=Uwz$Mu)|d&Tc8 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 can be a glob expression or a package name. + """ + + ignore_require_venv = True + usage = """ + %prog dir + %prog info + %prog list [] [--format=[human, abspath]] + %prog remove + %prog purge + """ + + def add_options(self) -> None: + self.cmd_opts.add_option( + "--format", + action="store", + dest="list_format", + default="human", + choices=("human", "abspath"), + help="Select the output format among: human (default) or abspath", + ) + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options: Values, args: List[str]) -> int: + handlers = { + "dir": self.get_cache_dir, + "info": self.get_cache_info, + "list": self.list_cache_items, + "remove": self.remove_cache_items, + "purge": self.purge_cache, + } + + if not options.cache_dir: + logger.error("pip cache commands can not function since cache is disabled.") + return ERROR + + # Determine action + if not args or args[0] not in handlers: + logger.error( + "Need an action (%s) to perform.", + ", ".join(sorted(handlers)), + ) + return ERROR + + action = args[0] + + # Error handling happens here, not in the action-handlers. + try: + handlers[action](options, args[1:]) + except PipError as e: + logger.error(e.args[0]) + return ERROR + + return SUCCESS + + def get_cache_dir(self, options: Values, args: List[Any]) -> None: + if args: + raise CommandError("Too many arguments") + + logger.info(options.cache_dir) + + def get_cache_info(self, options: Values, args: List[Any]) -> None: + if args: + raise CommandError("Too many arguments") + + num_http_files = len(self._find_http_files(options)) + num_packages = len(self._find_wheels(options, "*")) + + http_cache_location = self._cache_dir(options, "http-v2") + old_http_cache_location = self._cache_dir(options, "http") + wheels_cache_location = self._cache_dir(options, "wheels") + http_cache_size = filesystem.format_size( + filesystem.directory_size(http_cache_location) + + filesystem.directory_size(old_http_cache_location) + ) + wheels_cache_size = filesystem.format_directory_size(wheels_cache_location) + + message = ( + textwrap.dedent( + """ + Package index page cache location (pip v23.3+): {http_cache_location} + Package index page cache location (older pips): {old_http_cache_location} + Package index page cache size: {http_cache_size} + Number of HTTP files: {num_http_files} + Locally built wheels location: {wheels_cache_location} + Locally built wheels size: {wheels_cache_size} + Number of locally built wheels: {package_count} + """ # noqa: E501 + ) + .format( + http_cache_location=http_cache_location, + old_http_cache_location=old_http_cache_location, + http_cache_size=http_cache_size, + num_http_files=num_http_files, + wheels_cache_location=wheels_cache_location, + package_count=num_packages, + wheels_cache_size=wheels_cache_size, + ) + .strip() + ) + + logger.info(message) + + def list_cache_items(self, options: Values, args: List[Any]) -> None: + if len(args) > 1: + raise CommandError("Too many arguments") + + if args: + pattern = args[0] + else: + pattern = "*" + + files = self._find_wheels(options, pattern) + if options.list_format == "human": + self.format_for_human(files) + else: + self.format_for_abspath(files) + + def format_for_human(self, files: List[str]) -> None: + if not files: + logger.info("No locally built wheels cached.") + return + + results = [] + for filename in files: + wheel = os.path.basename(filename) + size = filesystem.format_file_size(filename) + results.append(f" - {wheel} ({size})") + logger.info("Cache contents:\n") + logger.info("\n".join(sorted(results))) + + def format_for_abspath(self, files: List[str]) -> None: + if files: + logger.info("\n".join(sorted(files))) + + def remove_cache_items(self, options: Values, args: List[Any]) -> None: + if len(args) > 1: + raise CommandError("Too many arguments") + + if not args: + raise CommandError("Please provide a pattern") + + files = self._find_wheels(options, args[0]) + + no_matching_msg = "No matching packages" + if args[0] == "*": + # Only fetch http files if no specific pattern given + files += self._find_http_files(options) + else: + # Add the pattern to the log message + no_matching_msg += f' for pattern "{args[0]}"' + + if not files: + logger.warning(no_matching_msg) + + for filename in files: + os.unlink(filename) + logger.verbose("Removed %s", filename) + logger.info("Files removed: %s", len(files)) + + def purge_cache(self, options: Values, args: List[Any]) -> None: + if args: + raise CommandError("Too many arguments") + + return self.remove_cache_items(options, ["*"]) + + def _cache_dir(self, options: Values, subdir: str) -> str: + return os.path.join(options.cache_dir, subdir) + + def _find_http_files(self, options: Values) -> List[str]: + old_http_dir = self._cache_dir(options, "http") + new_http_dir = self._cache_dir(options, "http-v2") + return filesystem.find_files(old_http_dir, "*") + filesystem.find_files( + new_http_dir, "*" + ) + + def _find_wheels(self, options: Values, pattern: str) -> List[str]: + wheel_dir = self._cache_dir(options, "wheels") + + # The wheel filename format, as specified in PEP 427, is: + # {distribution}-{version}(-{build})?-{python}-{abi}-{platform}.whl + # + # Additionally, non-alphanumeric values in the distribution are + # normalized to underscores (_), meaning hyphens can never occur + # before `-{version}`. + # + # Given that information: + # - If the pattern we're given contains a hyphen (-), the user is + # providing at least the version. Thus, we can just append `*.whl` + # to match the rest of it. + # - If the pattern we're given doesn't contain a hyphen (-), the + # user is only providing the name. Thus, we append `-*.whl` to + # match the hyphen before the version, followed by anything else. + # + # PEP 427: https://www.python.org/dev/peps/pep-0427/ + pattern = pattern + ("*.whl" if "-" in pattern else "-*.whl") + + return filesystem.find_files(wheel_dir, pattern) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/check.py b/backend/.venv/Lib/site-packages/pip/_internal/commands/check.py new file mode 100644 index 0000000..f54a16d --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/commands/check.py @@ -0,0 +1,67 @@ +import logging +from optparse import Values +from typing import List + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import ERROR, SUCCESS +from pip._internal.metadata import get_default_environment +from pip._internal.operations.check import ( + check_package_set, + check_unsupported, + create_package_set_from_installed, +) +from pip._internal.utils.compatibility_tags import get_supported +from pip._internal.utils.misc import write_output + +logger = logging.getLogger(__name__) + + +class CheckCommand(Command): + """Verify installed packages have compatible dependencies.""" + + ignore_require_venv = True + usage = """ + %prog [options]""" + + def run(self, options: Values, args: List[str]) -> int: + package_set, parsing_probs = create_package_set_from_installed() + missing, conflicting = check_package_set(package_set) + unsupported = list( + check_unsupported( + get_default_environment().iter_installed_distributions(), + get_supported(), + ) + ) + + for project_name in missing: + version = package_set[project_name].version + for dependency in missing[project_name]: + write_output( + "%s %s requires %s, which is not installed.", + project_name, + version, + dependency[0], + ) + + for project_name in conflicting: + version = package_set[project_name].version + for dep_name, dep_version, req in conflicting[project_name]: + write_output( + "%s %s has requirement %s, but you have %s %s.", + project_name, + version, + req, + dep_name, + dep_version, + ) + for package in unsupported: + write_output( + "%s %s is not supported on this platform", + package.raw_name, + package.version, + ) + if missing or conflicting or parsing_probs or unsupported: + return ERROR + else: + write_output("No broken requirements found.") + return SUCCESS diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/completion.py b/backend/.venv/Lib/site-packages/pip/_internal/commands/completion.py new file mode 100644 index 0000000..9e89e27 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/commands/completion.py @@ -0,0 +1,130 @@ +import sys +import textwrap +from optparse import Values +from typing import List + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.utils.misc import get_prog + +BASE_COMPLETION = """ +# pip {shell} completion start{script}# pip {shell} completion end +""" + +COMPLETION_SCRIPTS = { + "bash": """ + _pip_completion() + {{ + COMPREPLY=( $( COMP_WORDS="${{COMP_WORDS[*]}}" \\ + COMP_CWORD=$COMP_CWORD \\ + PIP_AUTO_COMPLETE=1 $1 2>/dev/null ) ) + }} + complete -o default -F _pip_completion {prog} + """, + "zsh": """ + #compdef -P pip[0-9.]# + __pip() {{ + compadd $( COMP_WORDS="$words[*]" \\ + COMP_CWORD=$((CURRENT-1)) \\ + PIP_AUTO_COMPLETE=1 $words[1] 2>/dev/null ) + }} + if [[ $zsh_eval_context[-1] == loadautofunc ]]; then + # autoload from fpath, call function directly + __pip "$@" + else + # eval/source/. command, register function for later + compdef __pip -P 'pip[0-9.]#' + fi + """, + "fish": """ + function __fish_complete_pip + set -lx COMP_WORDS (commandline -o) "" + set -lx COMP_CWORD ( \\ + math (contains -i -- (commandline -t) $COMP_WORDS)-1 \\ + ) + set -lx PIP_AUTO_COMPLETE 1 + string split \\ -- (eval $COMP_WORDS[1]) + end + complete -fa "(__fish_complete_pip)" -c {prog} + """, + "powershell": """ + if ((Test-Path Function:\\TabExpansion) -and -not ` + (Test-Path Function:\\_pip_completeBackup)) {{ + Rename-Item Function:\\TabExpansion _pip_completeBackup + }} + function TabExpansion($line, $lastWord) {{ + $lastBlock = [regex]::Split($line, '[|;]')[-1].TrimStart() + if ($lastBlock.StartsWith("{prog} ")) {{ + $Env:COMP_WORDS=$lastBlock + $Env:COMP_CWORD=$lastBlock.Split().Length - 1 + $Env:PIP_AUTO_COMPLETE=1 + (& {prog}).Split() + Remove-Item Env:COMP_WORDS + Remove-Item Env:COMP_CWORD + Remove-Item Env:PIP_AUTO_COMPLETE + }} + elseif (Test-Path Function:\\_pip_completeBackup) {{ + # Fall back on existing tab expansion + _pip_completeBackup $line $lastWord + }} + }} + """, +} + + +class CompletionCommand(Command): + """A helper command to be used for command completion.""" + + ignore_require_venv = True + + def add_options(self) -> None: + self.cmd_opts.add_option( + "--bash", + "-b", + action="store_const", + const="bash", + dest="shell", + help="Emit completion code for bash", + ) + self.cmd_opts.add_option( + "--zsh", + "-z", + action="store_const", + const="zsh", + dest="shell", + help="Emit completion code for zsh", + ) + self.cmd_opts.add_option( + "--fish", + "-f", + action="store_const", + const="fish", + dest="shell", + help="Emit completion code for fish", + ) + self.cmd_opts.add_option( + "--powershell", + "-p", + action="store_const", + const="powershell", + dest="shell", + help="Emit completion code for powershell", + ) + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options: Values, args: List[str]) -> int: + """Prints the completion code of the given shell""" + shells = COMPLETION_SCRIPTS.keys() + shell_options = ["--" + shell for shell in sorted(shells)] + if options.shell in shells: + script = textwrap.dedent( + COMPLETION_SCRIPTS.get(options.shell, "").format(prog=get_prog()) + ) + print(BASE_COMPLETION.format(script=script, shell=options.shell)) + return SUCCESS + else: + sys.stderr.write( + "ERROR: You must pass {}\n".format(" or ".join(shell_options)) + ) + return SUCCESS diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/configuration.py b/backend/.venv/Lib/site-packages/pip/_internal/commands/configuration.py new file mode 100644 index 0000000..1a1dc6b --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/commands/configuration.py @@ -0,0 +1,280 @@ +import logging +import os +import subprocess +from optparse import Values +from typing import Any, List, Optional + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import ERROR, SUCCESS +from pip._internal.configuration import ( + Configuration, + Kind, + get_configuration_files, + kinds, +) +from pip._internal.exceptions import PipError +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import get_prog, write_output + +logger = logging.getLogger(__name__) + + +class ConfigurationCommand(Command): + """ + Manage local and global configuration. + + Subcommands: + + - list: List the active configuration (or from the file specified) + - edit: Edit the configuration file in an editor + - get: Get the value associated with command.option + - set: Set the command.option=value + - unset: Unset the value associated with command.option + - debug: List the configuration files and values defined under them + + Configuration keys should be dot separated command and option name, + with the special prefix "global" affecting any command. For example, + "pip config set global.index-url https://example.org/" would configure + the index url for all commands, but "pip config set download.timeout 10" + would configure a 10 second timeout only for "pip download" commands. + + If none of --user, --global and --site are passed, a virtual + environment configuration file is used if one is active and the file + exists. Otherwise, all modifications happen to the user file by + default. + """ + + ignore_require_venv = True + usage = """ + %prog [] list + %prog [] [--editor ] edit + + %prog [] get command.option + %prog [] set command.option value + %prog [] unset command.option + %prog [] debug + """ + + def add_options(self) -> None: + self.cmd_opts.add_option( + "--editor", + dest="editor", + action="store", + default=None, + help=( + "Editor to use to edit the file. Uses VISUAL or EDITOR " + "environment variables if not provided." + ), + ) + + self.cmd_opts.add_option( + "--global", + dest="global_file", + action="store_true", + default=False, + help="Use the system-wide configuration file only", + ) + + self.cmd_opts.add_option( + "--user", + dest="user_file", + action="store_true", + default=False, + help="Use the user configuration file only", + ) + + self.cmd_opts.add_option( + "--site", + dest="site_file", + action="store_true", + default=False, + help="Use the current environment configuration file only", + ) + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options: Values, args: List[str]) -> int: + handlers = { + "list": self.list_values, + "edit": self.open_in_editor, + "get": self.get_name, + "set": self.set_name_value, + "unset": self.unset_name, + "debug": self.list_config_values, + } + + # Determine action + if not args or args[0] not in handlers: + logger.error( + "Need an action (%s) to perform.", + ", ".join(sorted(handlers)), + ) + return ERROR + + action = args[0] + + # Determine which configuration files are to be loaded + # Depends on whether the command is modifying. + try: + load_only = self._determine_file( + options, need_value=(action in ["get", "set", "unset", "edit"]) + ) + except PipError as e: + logger.error(e.args[0]) + return ERROR + + # Load a new configuration + self.configuration = Configuration( + isolated=options.isolated_mode, load_only=load_only + ) + self.configuration.load() + + # Error handling happens here, not in the action-handlers. + try: + handlers[action](options, args[1:]) + except PipError as e: + logger.error(e.args[0]) + return ERROR + + return SUCCESS + + def _determine_file(self, options: Values, need_value: bool) -> Optional[Kind]: + file_options = [ + key + for key, value in ( + (kinds.USER, options.user_file), + (kinds.GLOBAL, options.global_file), + (kinds.SITE, options.site_file), + ) + if value + ] + + if not file_options: + if not need_value: + return None + # Default to user, unless there's a site file. + elif any( + os.path.exists(site_config_file) + for site_config_file in get_configuration_files()[kinds.SITE] + ): + return kinds.SITE + else: + return kinds.USER + elif len(file_options) == 1: + return file_options[0] + + raise PipError( + "Need exactly one file to operate upon " + "(--user, --site, --global) to perform." + ) + + def list_values(self, options: Values, args: List[str]) -> None: + self._get_n_args(args, "list", n=0) + + for key, value in sorted(self.configuration.items()): + write_output("%s=%r", key, value) + + def get_name(self, options: Values, args: List[str]) -> None: + key = self._get_n_args(args, "get [name]", n=1) + value = self.configuration.get_value(key) + + write_output("%s", value) + + def set_name_value(self, options: Values, args: List[str]) -> None: + key, value = self._get_n_args(args, "set [name] [value]", n=2) + self.configuration.set_value(key, value) + + self._save_configuration() + + def unset_name(self, options: Values, args: List[str]) -> None: + key = self._get_n_args(args, "unset [name]", n=1) + self.configuration.unset_value(key) + + self._save_configuration() + + def list_config_values(self, options: Values, args: List[str]) -> None: + """List config key-value pairs across different config files""" + self._get_n_args(args, "debug", n=0) + + self.print_env_var_values() + # Iterate over config files and print if they exist, and the + # key-value pairs present in them if they do + for variant, files in sorted(self.configuration.iter_config_files()): + write_output("%s:", variant) + for fname in files: + with indent_log(): + file_exists = os.path.exists(fname) + write_output("%s, exists: %r", fname, file_exists) + if file_exists: + self.print_config_file_values(variant) + + def print_config_file_values(self, variant: Kind) -> None: + """Get key-value pairs from the file of a variant""" + for name, value in self.configuration.get_values_in_config(variant).items(): + with indent_log(): + write_output("%s: %s", name, value) + + def print_env_var_values(self) -> None: + """Get key-values pairs present as environment variables""" + write_output("%s:", "env_var") + with indent_log(): + for key, value in sorted(self.configuration.get_environ_vars()): + env_var = f"PIP_{key.upper()}" + write_output("%s=%r", env_var, value) + + def open_in_editor(self, options: Values, args: List[str]) -> None: + editor = self._determine_editor(options) + + fname = self.configuration.get_file_to_edit() + if fname is None: + raise PipError("Could not determine appropriate file.") + elif '"' in fname: + # This shouldn't happen, unless we see a username like that. + # If that happens, we'd appreciate a pull request fixing this. + raise PipError( + f'Can not open an editor for a file name containing "\n{fname}' + ) + + try: + subprocess.check_call(f'{editor} "{fname}"', shell=True) + except FileNotFoundError as e: + if not e.filename: + e.filename = editor + raise + except subprocess.CalledProcessError as e: + raise PipError(f"Editor Subprocess exited with exit code {e.returncode}") + + def _get_n_args(self, args: List[str], example: str, n: int) -> Any: + """Helper to make sure the command got the right number of arguments""" + if len(args) != n: + msg = ( + f"Got unexpected number of arguments, expected {n}. " + f'(example: "{get_prog()} config {example}")' + ) + raise PipError(msg) + + if n == 1: + return args[0] + else: + return args + + def _save_configuration(self) -> None: + # We successfully ran a modifying command. Need to save the + # configuration. + try: + self.configuration.save() + except Exception: + logger.exception( + "Unable to save configuration. Please report this as a bug." + ) + raise PipError("Internal Error.") + + def _determine_editor(self, options: Values) -> str: + if options.editor is not None: + return options.editor + elif "VISUAL" in os.environ: + return os.environ["VISUAL"] + elif "EDITOR" in os.environ: + return os.environ["EDITOR"] + else: + raise PipError("Could not determine editor to use.") diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/debug.py b/backend/.venv/Lib/site-packages/pip/_internal/commands/debug.py new file mode 100644 index 0000000..567ca96 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/commands/debug.py @@ -0,0 +1,201 @@ +import locale +import logging +import os +import sys +from optparse import Values +from types import ModuleType +from typing import Any, Dict, List, Optional + +import pip._vendor +from pip._vendor.certifi import where +from pip._vendor.packaging.version import parse as parse_version + +from pip._internal.cli import cmdoptions +from pip._internal.cli.base_command import Command +from pip._internal.cli.cmdoptions import make_target_python +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.configuration import Configuration +from pip._internal.metadata import get_environment +from pip._internal.utils.compat import open_text_resource +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import get_pip_version + +logger = logging.getLogger(__name__) + + +def show_value(name: str, value: Any) -> None: + logger.info("%s: %s", name, value) + + +def show_sys_implementation() -> None: + logger.info("sys.implementation:") + implementation_name = sys.implementation.name + with indent_log(): + show_value("name", implementation_name) + + +def create_vendor_txt_map() -> Dict[str, str]: + with open_text_resource("pip._vendor", "vendor.txt") as f: + # Purge non version specifying lines. + # Also, remove any space prefix or suffixes (including comments). + lines = [ + line.strip().split(" ", 1)[0] for line in f.readlines() if "==" in line + ] + + # Transform into "module" -> version dict. + return dict(line.split("==", 1) for line in lines) + + +def get_module_from_module_name(module_name: str) -> Optional[ModuleType]: + # Module name can be uppercase in vendor.txt for some reason... + module_name = module_name.lower().replace("-", "_") + # PATCH: setuptools is actually only pkg_resources. + if module_name == "setuptools": + module_name = "pkg_resources" + + try: + __import__(f"pip._vendor.{module_name}", globals(), locals(), level=0) + return getattr(pip._vendor, module_name) + except ImportError: + # We allow 'truststore' to fail to import due + # to being unavailable on Python 3.9 and earlier. + if module_name == "truststore" and sys.version_info < (3, 10): + return None + raise + + +def get_vendor_version_from_module(module_name: str) -> Optional[str]: + module = get_module_from_module_name(module_name) + version = getattr(module, "__version__", None) + + if module and not version: + # Try to find version in debundled module info. + assert module.__file__ is not None + env = get_environment([os.path.dirname(module.__file__)]) + dist = env.get_distribution(module_name) + if dist: + version = str(dist.version) + + return version + + +def show_actual_vendor_versions(vendor_txt_versions: Dict[str, str]) -> None: + """Log the actual version and print extra info if there is + a conflict or if the actual version could not be imported. + """ + for module_name, expected_version in vendor_txt_versions.items(): + extra_message = "" + actual_version = get_vendor_version_from_module(module_name) + if not actual_version: + extra_message = ( + " (Unable to locate actual module version, using" + " vendor.txt specified version)" + ) + actual_version = expected_version + elif parse_version(actual_version) != parse_version(expected_version): + extra_message = ( + " (CONFLICT: vendor.txt suggests version should" + f" be {expected_version})" + ) + logger.info("%s==%s%s", module_name, actual_version, extra_message) + + +def show_vendor_versions() -> None: + logger.info("vendored library versions:") + + vendor_txt_versions = create_vendor_txt_map() + with indent_log(): + show_actual_vendor_versions(vendor_txt_versions) + + +def show_tags(options: Values) -> None: + tag_limit = 10 + + target_python = make_target_python(options) + tags = target_python.get_sorted_tags() + + # Display the target options that were explicitly provided. + formatted_target = target_python.format_given() + suffix = "" + if formatted_target: + suffix = f" (target: {formatted_target})" + + msg = f"Compatible tags: {len(tags)}{suffix}" + logger.info(msg) + + if options.verbose < 1 and len(tags) > tag_limit: + tags_limited = True + tags = tags[:tag_limit] + else: + tags_limited = False + + with indent_log(): + for tag in tags: + logger.info(str(tag)) + + if tags_limited: + msg = f"...\n[First {tag_limit} tags shown. Pass --verbose to show all.]" + logger.info(msg) + + +def ca_bundle_info(config: Configuration) -> str: + levels = {key.split(".", 1)[0] for key, _ in config.items()} + if not levels: + return "Not specified" + + levels_that_override_global = ["install", "wheel", "download"] + global_overriding_level = [ + level for level in levels if level in levels_that_override_global + ] + if not global_overriding_level: + return "global" + + if "global" in levels: + levels.remove("global") + return ", ".join(levels) + + +class DebugCommand(Command): + """ + Display debug information. + """ + + usage = """ + %prog """ + ignore_require_venv = True + + def add_options(self) -> None: + cmdoptions.add_target_python_options(self.cmd_opts) + self.parser.insert_option_group(0, self.cmd_opts) + self.parser.config.load() + + def run(self, options: Values, args: List[str]) -> int: + logger.warning( + "This command is only meant for debugging. " + "Do not use this with automation for parsing and getting these " + "details, since the output and options of this command may " + "change without notice." + ) + show_value("pip version", get_pip_version()) + show_value("sys.version", sys.version) + show_value("sys.executable", sys.executable) + show_value("sys.getdefaultencoding", sys.getdefaultencoding()) + show_value("sys.getfilesystemencoding", sys.getfilesystemencoding()) + show_value( + "locale.getpreferredencoding", + locale.getpreferredencoding(), + ) + show_value("sys.platform", sys.platform) + show_sys_implementation() + + show_value("'cert' config value", ca_bundle_info(self.parser.config)) + show_value("REQUESTS_CA_BUNDLE", os.environ.get("REQUESTS_CA_BUNDLE")) + show_value("CURL_CA_BUNDLE", os.environ.get("CURL_CA_BUNDLE")) + show_value("pip._vendor.certifi.where()", where()) + show_value("pip._vendor.DEBUNDLED", pip._vendor.DEBUNDLED) + + show_vendor_versions() + + show_tags(options) + + return SUCCESS diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/download.py b/backend/.venv/Lib/site-packages/pip/_internal/commands/download.py new file mode 100644 index 0000000..917bbb9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/commands/download.py @@ -0,0 +1,146 @@ +import logging +import os +from optparse import Values +from typing import List + +from pip._internal.cli import cmdoptions +from pip._internal.cli.cmdoptions import make_target_python +from pip._internal.cli.req_command import RequirementCommand, with_cleanup +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.operations.build.build_tracker import get_build_tracker +from pip._internal.req.req_install import check_legacy_setup_py_options +from pip._internal.utils.misc import ensure_dir, normalize_path, write_output +from pip._internal.utils.temp_dir import TempDirectory + +logger = logging.getLogger(__name__) + + +class DownloadCommand(RequirementCommand): + """ + Download packages from: + + - PyPI (and other indexes) using requirement specifiers. + - VCS project urls. + - Local project directories. + - Local or remote source archives. + + pip also supports downloading from "requirements files", which provide + an easy way to specify a whole environment to be downloaded. + """ + + usage = """ + %prog [options] [package-index-options] ... + %prog [options] -r [package-index-options] ... + %prog [options] ... + %prog [options] ... + %prog [options] ...""" + + def add_options(self) -> None: + self.cmd_opts.add_option(cmdoptions.constraints()) + self.cmd_opts.add_option(cmdoptions.requirements()) + self.cmd_opts.add_option(cmdoptions.no_deps()) + self.cmd_opts.add_option(cmdoptions.global_options()) + self.cmd_opts.add_option(cmdoptions.no_binary()) + self.cmd_opts.add_option(cmdoptions.only_binary()) + self.cmd_opts.add_option(cmdoptions.prefer_binary()) + self.cmd_opts.add_option(cmdoptions.src()) + self.cmd_opts.add_option(cmdoptions.pre()) + self.cmd_opts.add_option(cmdoptions.require_hashes()) + self.cmd_opts.add_option(cmdoptions.progress_bar()) + self.cmd_opts.add_option(cmdoptions.no_build_isolation()) + self.cmd_opts.add_option(cmdoptions.use_pep517()) + self.cmd_opts.add_option(cmdoptions.no_use_pep517()) + self.cmd_opts.add_option(cmdoptions.check_build_deps()) + self.cmd_opts.add_option(cmdoptions.ignore_requires_python()) + + self.cmd_opts.add_option( + "-d", + "--dest", + "--destination-dir", + "--destination-directory", + dest="download_dir", + metavar="dir", + default=os.curdir, + help="Download packages into

.", + ) + + cmdoptions.add_target_python_options(self.cmd_opts) + + index_opts = cmdoptions.make_option_group( + cmdoptions.index_group, + self.parser, + ) + + self.parser.insert_option_group(0, index_opts) + self.parser.insert_option_group(0, self.cmd_opts) + + @with_cleanup + def run(self, options: Values, args: List[str]) -> int: + options.ignore_installed = True + # editable doesn't really make sense for `pip download`, but the bowels + # of the RequirementSet code require that property. + options.editables = [] + + cmdoptions.check_dist_restriction(options) + + options.download_dir = normalize_path(options.download_dir) + ensure_dir(options.download_dir) + + session = self.get_default_session(options) + + target_python = make_target_python(options) + finder = self._build_package_finder( + options=options, + session=session, + target_python=target_python, + ignore_requires_python=options.ignore_requires_python, + ) + + build_tracker = self.enter_context(get_build_tracker()) + + directory = TempDirectory( + delete=not options.no_clean, + kind="download", + globally_managed=True, + ) + + reqs = self.get_requirements(args, options, finder, session) + check_legacy_setup_py_options(options, reqs) + + preparer = self.make_requirement_preparer( + temp_build_dir=directory, + options=options, + build_tracker=build_tracker, + session=session, + finder=finder, + download_dir=options.download_dir, + use_user_site=False, + verbosity=self.verbosity, + ) + + resolver = self.make_resolver( + preparer=preparer, + finder=finder, + options=options, + ignore_requires_python=options.ignore_requires_python, + use_pep517=options.use_pep517, + py_version_info=options.python_version, + ) + + self.trace_basic_info(finder) + + requirement_set = resolver.resolve(reqs, check_supported_wheels=True) + + downloaded: List[str] = [] + for req in requirement_set.requirements.values(): + if req.satisfied_by is None: + assert req.name is not None + preparer.save_linked_requirement(req) + downloaded.append(req.name) + + preparer.prepare_linked_requirements_more(requirement_set.requirements.values()) + + if downloaded: + write_output("Successfully downloaded %s", " ".join(downloaded)) + + return SUCCESS diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/freeze.py b/backend/.venv/Lib/site-packages/pip/_internal/commands/freeze.py new file mode 100644 index 0000000..885fdfe --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/commands/freeze.py @@ -0,0 +1,109 @@ +import sys +from optparse import Values +from typing import AbstractSet, List + +from pip._internal.cli import cmdoptions +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.operations.freeze import freeze +from pip._internal.utils.compat import stdlib_pkgs + + +def _should_suppress_build_backends() -> bool: + return sys.version_info < (3, 12) + + +def _dev_pkgs() -> AbstractSet[str]: + pkgs = {"pip"} + + if _should_suppress_build_backends(): + pkgs |= {"setuptools", "distribute", "wheel"} + + return pkgs + + +class FreezeCommand(Command): + """ + Output installed packages in requirements format. + + packages are listed in a case-insensitive sorted order. + """ + + ignore_require_venv = True + usage = """ + %prog [options]""" + log_streams = ("ext://sys.stderr", "ext://sys.stderr") + + def add_options(self) -> None: + self.cmd_opts.add_option( + "-r", + "--requirement", + dest="requirements", + action="append", + default=[], + metavar="file", + help=( + "Use the order in the given requirements file and its " + "comments when generating output. This option can be " + "used multiple times." + ), + ) + self.cmd_opts.add_option( + "-l", + "--local", + dest="local", + action="store_true", + default=False, + help=( + "If in a virtualenv that has global access, do not output " + "globally-installed packages." + ), + ) + self.cmd_opts.add_option( + "--user", + dest="user", + action="store_true", + default=False, + help="Only output packages installed in user-site.", + ) + self.cmd_opts.add_option(cmdoptions.list_path()) + self.cmd_opts.add_option( + "--all", + dest="freeze_all", + action="store_true", + help=( + "Do not skip these packages in the output:" + " {}".format(", ".join(_dev_pkgs())) + ), + ) + self.cmd_opts.add_option( + "--exclude-editable", + dest="exclude_editable", + action="store_true", + help="Exclude editable package from output.", + ) + self.cmd_opts.add_option(cmdoptions.list_exclude()) + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options: Values, args: List[str]) -> int: + skip = set(stdlib_pkgs) + if not options.freeze_all: + skip.update(_dev_pkgs()) + + if options.excludes: + skip.update(options.excludes) + + cmdoptions.check_list_path_option(options) + + for line in freeze( + requirement=options.requirements, + local_only=options.local, + user_only=options.user, + paths=options.path, + isolated=options.isolated_mode, + skip=skip, + exclude_editable=options.exclude_editable, + ): + sys.stdout.write(line + "\n") + return SUCCESS diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/hash.py b/backend/.venv/Lib/site-packages/pip/_internal/commands/hash.py new file mode 100644 index 0000000..042dac8 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/commands/hash.py @@ -0,0 +1,59 @@ +import hashlib +import logging +import sys +from optparse import Values +from typing import List + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import ERROR, SUCCESS +from pip._internal.utils.hashes import FAVORITE_HASH, STRONG_HASHES +from pip._internal.utils.misc import read_chunks, write_output + +logger = logging.getLogger(__name__) + + +class HashCommand(Command): + """ + Compute a hash of a local package archive. + + These can be used with --hash in a requirements file to do repeatable + installs. + """ + + usage = "%prog [options] ..." + ignore_require_venv = True + + def add_options(self) -> None: + self.cmd_opts.add_option( + "-a", + "--algorithm", + dest="algorithm", + choices=STRONG_HASHES, + action="store", + default=FAVORITE_HASH, + help="The hash algorithm to use: one of {}".format( + ", ".join(STRONG_HASHES) + ), + ) + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options: Values, args: List[str]) -> int: + if not args: + self.parser.print_usage(sys.stderr) + return ERROR + + algorithm = options.algorithm + for path in args: + write_output( + "%s:\n--hash=%s:%s", path, algorithm, _hash_of_file(path, algorithm) + ) + return SUCCESS + + +def _hash_of_file(path: str, algorithm: str) -> str: + """Return the hash digest of a file.""" + with open(path, "rb") as archive: + hash = hashlib.new(algorithm) + for chunk in read_chunks(archive): + hash.update(chunk) + return hash.hexdigest() diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/help.py b/backend/.venv/Lib/site-packages/pip/_internal/commands/help.py new file mode 100644 index 0000000..6206631 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/commands/help.py @@ -0,0 +1,41 @@ +from optparse import Values +from typing import List + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.exceptions import CommandError + + +class HelpCommand(Command): + """Show help for commands""" + + usage = """ + %prog """ + ignore_require_venv = True + + def run(self, options: Values, args: List[str]) -> int: + from pip._internal.commands import ( + commands_dict, + create_command, + get_similar_commands, + ) + + try: + # 'pip help' with no args is handled by pip.__init__.parseopt() + cmd_name = args[0] # the command we need help for + except IndexError: + return SUCCESS + + if cmd_name not in commands_dict: + guess = get_similar_commands(cmd_name) + + msg = [f'unknown command "{cmd_name}"'] + if guess: + msg.append(f'maybe you meant "{guess}"') + + raise CommandError(" - ".join(msg)) + + command = create_command(cmd_name) + command.parser.print_help() + + return SUCCESS diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/index.py b/backend/.venv/Lib/site-packages/pip/_internal/commands/index.py new file mode 100644 index 0000000..2e2661b --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/commands/index.py @@ -0,0 +1,139 @@ +import logging +from optparse import Values +from typing import Any, Iterable, List, Optional + +from pip._vendor.packaging.version import Version + +from pip._internal.cli import cmdoptions +from pip._internal.cli.req_command import IndexGroupCommand +from pip._internal.cli.status_codes import ERROR, SUCCESS +from pip._internal.commands.search import print_dist_installation_info +from pip._internal.exceptions import CommandError, DistributionNotFound, PipError +from pip._internal.index.collector import LinkCollector +from pip._internal.index.package_finder import PackageFinder +from pip._internal.models.selection_prefs import SelectionPreferences +from pip._internal.models.target_python import TargetPython +from pip._internal.network.session import PipSession +from pip._internal.utils.misc import write_output + +logger = logging.getLogger(__name__) + + +class IndexCommand(IndexGroupCommand): + """ + Inspect information available from package indexes. + """ + + ignore_require_venv = True + usage = """ + %prog versions + """ + + def add_options(self) -> None: + cmdoptions.add_target_python_options(self.cmd_opts) + + self.cmd_opts.add_option(cmdoptions.ignore_requires_python()) + self.cmd_opts.add_option(cmdoptions.pre()) + self.cmd_opts.add_option(cmdoptions.no_binary()) + self.cmd_opts.add_option(cmdoptions.only_binary()) + + index_opts = cmdoptions.make_option_group( + cmdoptions.index_group, + self.parser, + ) + + self.parser.insert_option_group(0, index_opts) + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options: Values, args: List[str]) -> int: + handlers = { + "versions": self.get_available_package_versions, + } + + logger.warning( + "pip index is currently an experimental command. " + "It may be removed/changed in a future release " + "without prior warning." + ) + + # Determine action + if not args or args[0] not in handlers: + logger.error( + "Need an action (%s) to perform.", + ", ".join(sorted(handlers)), + ) + return ERROR + + action = args[0] + + # Error handling happens here, not in the action-handlers. + try: + handlers[action](options, args[1:]) + except PipError as e: + logger.error(e.args[0]) + return ERROR + + return SUCCESS + + def _build_package_finder( + self, + options: Values, + session: PipSession, + target_python: Optional[TargetPython] = None, + ignore_requires_python: Optional[bool] = None, + ) -> PackageFinder: + """ + Create a package finder appropriate to the index command. + """ + link_collector = LinkCollector.create(session, options=options) + + # Pass allow_yanked=False to ignore yanked versions. + selection_prefs = SelectionPreferences( + allow_yanked=False, + allow_all_prereleases=options.pre, + ignore_requires_python=ignore_requires_python, + ) + + return PackageFinder.create( + link_collector=link_collector, + selection_prefs=selection_prefs, + target_python=target_python, + ) + + def get_available_package_versions(self, options: Values, args: List[Any]) -> None: + if len(args) != 1: + raise CommandError("You need to specify exactly one argument") + + target_python = cmdoptions.make_target_python(options) + query = args[0] + + with self._build_session(options) as session: + finder = self._build_package_finder( + options=options, + session=session, + target_python=target_python, + ignore_requires_python=options.ignore_requires_python, + ) + + versions: Iterable[Version] = ( + candidate.version for candidate in finder.find_all_candidates(query) + ) + + if not options.pre: + # Remove prereleases + versions = ( + version for version in versions if not version.is_prerelease + ) + versions = set(versions) + + if not versions: + raise DistributionNotFound( + f"No matching distribution found for {query}" + ) + + formatted_versions = [str(ver) for ver in sorted(versions, reverse=True)] + latest = formatted_versions[0] + + write_output(f"{query} ({latest})") + write_output("Available versions: {}".format(", ".join(formatted_versions))) + print_dist_installation_info(query, latest) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/inspect.py b/backend/.venv/Lib/site-packages/pip/_internal/commands/inspect.py new file mode 100644 index 0000000..e810c13 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/commands/inspect.py @@ -0,0 +1,92 @@ +import logging +from optparse import Values +from typing import Any, Dict, List + +from pip._vendor.packaging.markers import default_environment +from pip._vendor.rich import print_json + +from pip import __version__ +from pip._internal.cli import cmdoptions +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.metadata import BaseDistribution, get_environment +from pip._internal.utils.compat import stdlib_pkgs +from pip._internal.utils.urls import path_to_url + +logger = logging.getLogger(__name__) + + +class InspectCommand(Command): + """ + Inspect the content of a Python environment and produce a report in JSON format. + """ + + ignore_require_venv = True + usage = """ + %prog [options]""" + + def add_options(self) -> None: + self.cmd_opts.add_option( + "--local", + action="store_true", + default=False, + help=( + "If in a virtualenv that has global access, do not list " + "globally-installed packages." + ), + ) + self.cmd_opts.add_option( + "--user", + dest="user", + action="store_true", + default=False, + help="Only output packages installed in user-site.", + ) + self.cmd_opts.add_option(cmdoptions.list_path()) + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options: Values, args: List[str]) -> int: + cmdoptions.check_list_path_option(options) + dists = get_environment(options.path).iter_installed_distributions( + local_only=options.local, + user_only=options.user, + skip=set(stdlib_pkgs), + ) + output = { + "version": "1", + "pip_version": __version__, + "installed": [self._dist_to_dict(dist) for dist in dists], + "environment": default_environment(), + # TODO tags? scheme? + } + print_json(data=output) + return SUCCESS + + def _dist_to_dict(self, dist: BaseDistribution) -> Dict[str, Any]: + res: Dict[str, Any] = { + "metadata": dist.metadata_dict, + "metadata_location": dist.info_location, + } + # direct_url. Note that we don't have download_info (as in the installation + # report) since it is not recorded in installed metadata. + direct_url = dist.direct_url + if direct_url is not None: + res["direct_url"] = direct_url.to_dict() + else: + # Emulate direct_url for legacy editable installs. + editable_project_location = dist.editable_project_location + if editable_project_location is not None: + res["direct_url"] = { + "url": path_to_url(editable_project_location), + "dir_info": { + "editable": True, + }, + } + # installer + installer = dist.installer + if dist.installer: + res["installer"] = installer + # requested + if dist.installed_with_dist_info: + res["requested"] = dist.requested + return res diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/install.py b/backend/.venv/Lib/site-packages/pip/_internal/commands/install.py new file mode 100644 index 0000000..ad45a2f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/commands/install.py @@ -0,0 +1,783 @@ +import errno +import json +import operator +import os +import shutil +import site +from optparse import SUPPRESS_HELP, Values +from typing import List, Optional + +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.rich import print_json + +from pip._internal.cache import WheelCache +from pip._internal.cli import cmdoptions +from pip._internal.cli.cmdoptions import make_target_python +from pip._internal.cli.req_command import ( + RequirementCommand, + with_cleanup, +) +from pip._internal.cli.status_codes import ERROR, SUCCESS +from pip._internal.exceptions import CommandError, InstallationError +from pip._internal.locations import get_scheme +from pip._internal.metadata import get_environment +from pip._internal.models.installation_report import InstallationReport +from pip._internal.operations.build.build_tracker import get_build_tracker +from pip._internal.operations.check import ConflictDetails, check_install_conflicts +from pip._internal.req import install_given_reqs +from pip._internal.req.req_install import ( + InstallRequirement, + check_legacy_setup_py_options, +) +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.filesystem import test_writable_dir +from pip._internal.utils.logging import getLogger +from pip._internal.utils.misc import ( + check_externally_managed, + ensure_dir, + get_pip_version, + protect_pip_from_modification_on_windows, + warn_if_run_as_root, + write_output, +) +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.virtualenv import ( + running_under_virtualenv, + virtualenv_no_global, +) +from pip._internal.wheel_builder import build, should_build_for_install_command + +logger = getLogger(__name__) + + +class InstallCommand(RequirementCommand): + """ + Install packages from: + + - PyPI (and other indexes) using requirement specifiers. + - VCS project urls. + - Local project directories. + - Local or remote source archives. + + pip also supports installing from "requirements files", which provide + an easy way to specify a whole environment to be installed. + """ + + usage = """ + %prog [options] [package-index-options] ... + %prog [options] -r [package-index-options] ... + %prog [options] [-e] ... + %prog [options] [-e] ... + %prog [options] ...""" + + def add_options(self) -> None: + self.cmd_opts.add_option(cmdoptions.requirements()) + self.cmd_opts.add_option(cmdoptions.constraints()) + self.cmd_opts.add_option(cmdoptions.no_deps()) + self.cmd_opts.add_option(cmdoptions.pre()) + + self.cmd_opts.add_option(cmdoptions.editable()) + self.cmd_opts.add_option( + "--dry-run", + action="store_true", + dest="dry_run", + default=False, + help=( + "Don't actually install anything, just print what would be. " + "Can be used in combination with --ignore-installed " + "to 'resolve' the requirements." + ), + ) + self.cmd_opts.add_option( + "-t", + "--target", + dest="target_dir", + metavar="dir", + default=None, + help=( + "Install packages into . " + "By default this will not replace existing files/folders in " + ". Use --upgrade to replace existing packages in " + "with new versions." + ), + ) + cmdoptions.add_target_python_options(self.cmd_opts) + + self.cmd_opts.add_option( + "--user", + dest="use_user_site", + action="store_true", + help=( + "Install to the Python user install directory for your " + "platform. Typically ~/.local/, or %APPDATA%\\Python on " + "Windows. (See the Python documentation for site.USER_BASE " + "for full details.)" + ), + ) + self.cmd_opts.add_option( + "--no-user", + dest="use_user_site", + action="store_false", + help=SUPPRESS_HELP, + ) + self.cmd_opts.add_option( + "--root", + dest="root_path", + metavar="dir", + default=None, + help="Install everything relative to this alternate root directory.", + ) + self.cmd_opts.add_option( + "--prefix", + dest="prefix_path", + metavar="dir", + default=None, + help=( + "Installation prefix where lib, bin and other top-level " + "folders are placed. Note that the resulting installation may " + "contain scripts and other resources which reference the " + "Python interpreter of pip, and not that of ``--prefix``. " + "See also the ``--python`` option if the intention is to " + "install packages into another (possibly pip-free) " + "environment." + ), + ) + + self.cmd_opts.add_option(cmdoptions.src()) + + self.cmd_opts.add_option( + "-U", + "--upgrade", + dest="upgrade", + action="store_true", + help=( + "Upgrade all specified packages to the newest available " + "version. The handling of dependencies depends on the " + "upgrade-strategy used." + ), + ) + + self.cmd_opts.add_option( + "--upgrade-strategy", + dest="upgrade_strategy", + default="only-if-needed", + choices=["only-if-needed", "eager"], + help=( + "Determines how dependency upgrading should be handled " + "[default: %default]. " + '"eager" - dependencies are upgraded regardless of ' + "whether the currently installed version satisfies the " + "requirements of the upgraded package(s). " + '"only-if-needed" - are upgraded only when they do not ' + "satisfy the requirements of the upgraded package(s)." + ), + ) + + self.cmd_opts.add_option( + "--force-reinstall", + dest="force_reinstall", + action="store_true", + help="Reinstall all packages even if they are already up-to-date.", + ) + + self.cmd_opts.add_option( + "-I", + "--ignore-installed", + dest="ignore_installed", + action="store_true", + help=( + "Ignore the installed packages, overwriting them. " + "This can break your system if the existing package " + "is of a different version or was installed " + "with a different package manager!" + ), + ) + + self.cmd_opts.add_option(cmdoptions.ignore_requires_python()) + self.cmd_opts.add_option(cmdoptions.no_build_isolation()) + self.cmd_opts.add_option(cmdoptions.use_pep517()) + self.cmd_opts.add_option(cmdoptions.no_use_pep517()) + self.cmd_opts.add_option(cmdoptions.check_build_deps()) + self.cmd_opts.add_option(cmdoptions.override_externally_managed()) + + self.cmd_opts.add_option(cmdoptions.config_settings()) + self.cmd_opts.add_option(cmdoptions.global_options()) + + self.cmd_opts.add_option( + "--compile", + action="store_true", + dest="compile", + default=True, + help="Compile Python source files to bytecode", + ) + + self.cmd_opts.add_option( + "--no-compile", + action="store_false", + dest="compile", + help="Do not compile Python source files to bytecode", + ) + + self.cmd_opts.add_option( + "--no-warn-script-location", + action="store_false", + dest="warn_script_location", + default=True, + help="Do not warn when installing scripts outside PATH", + ) + self.cmd_opts.add_option( + "--no-warn-conflicts", + action="store_false", + dest="warn_about_conflicts", + default=True, + help="Do not warn about broken dependencies", + ) + self.cmd_opts.add_option(cmdoptions.no_binary()) + self.cmd_opts.add_option(cmdoptions.only_binary()) + self.cmd_opts.add_option(cmdoptions.prefer_binary()) + self.cmd_opts.add_option(cmdoptions.require_hashes()) + self.cmd_opts.add_option(cmdoptions.progress_bar()) + self.cmd_opts.add_option(cmdoptions.root_user_action()) + + index_opts = cmdoptions.make_option_group( + cmdoptions.index_group, + self.parser, + ) + + self.parser.insert_option_group(0, index_opts) + self.parser.insert_option_group(0, self.cmd_opts) + + self.cmd_opts.add_option( + "--report", + dest="json_report_file", + metavar="file", + default=None, + help=( + "Generate a JSON file describing what pip did to install " + "the provided requirements. " + "Can be used in combination with --dry-run and --ignore-installed " + "to 'resolve' the requirements. " + "When - is used as file name it writes to stdout. " + "When writing to stdout, please combine with the --quiet option " + "to avoid mixing pip logging output with JSON output." + ), + ) + + @with_cleanup + def run(self, options: Values, args: List[str]) -> int: + if options.use_user_site and options.target_dir is not None: + raise CommandError("Can not combine '--user' and '--target'") + + # Check whether the environment we're installing into is externally + # managed, as specified in PEP 668. Specifying --root, --target, or + # --prefix disables the check, since there's no reliable way to locate + # the EXTERNALLY-MANAGED file for those cases. An exception is also + # made specifically for "--dry-run --report" for convenience. + installing_into_current_environment = ( + not (options.dry_run and options.json_report_file) + and options.root_path is None + and options.target_dir is None + and options.prefix_path is None + ) + if ( + installing_into_current_environment + and not options.override_externally_managed + ): + check_externally_managed() + + upgrade_strategy = "to-satisfy-only" + if options.upgrade: + upgrade_strategy = options.upgrade_strategy + + cmdoptions.check_dist_restriction(options, check_target=True) + + logger.verbose("Using %s", get_pip_version()) + options.use_user_site = decide_user_install( + options.use_user_site, + prefix_path=options.prefix_path, + target_dir=options.target_dir, + root_path=options.root_path, + isolated_mode=options.isolated_mode, + ) + + target_temp_dir: Optional[TempDirectory] = None + target_temp_dir_path: Optional[str] = None + if options.target_dir: + options.ignore_installed = True + options.target_dir = os.path.abspath(options.target_dir) + if ( + # fmt: off + os.path.exists(options.target_dir) and + not os.path.isdir(options.target_dir) + # fmt: on + ): + raise CommandError( + "Target path exists but is not a directory, will not continue." + ) + + # Create a target directory for using with the target option + target_temp_dir = TempDirectory(kind="target") + target_temp_dir_path = target_temp_dir.path + self.enter_context(target_temp_dir) + + global_options = options.global_options or [] + + session = self.get_default_session(options) + + target_python = make_target_python(options) + finder = self._build_package_finder( + options=options, + session=session, + target_python=target_python, + ignore_requires_python=options.ignore_requires_python, + ) + build_tracker = self.enter_context(get_build_tracker()) + + directory = TempDirectory( + delete=not options.no_clean, + kind="install", + globally_managed=True, + ) + + try: + reqs = self.get_requirements(args, options, finder, session) + check_legacy_setup_py_options(options, reqs) + + wheel_cache = WheelCache(options.cache_dir) + + # Only when installing is it permitted to use PEP 660. + # In other circumstances (pip wheel, pip download) we generate + # regular (i.e. non editable) metadata and wheels. + for req in reqs: + req.permit_editable_wheels = True + + preparer = self.make_requirement_preparer( + temp_build_dir=directory, + options=options, + build_tracker=build_tracker, + session=session, + finder=finder, + use_user_site=options.use_user_site, + verbosity=self.verbosity, + ) + resolver = self.make_resolver( + preparer=preparer, + finder=finder, + options=options, + wheel_cache=wheel_cache, + use_user_site=options.use_user_site, + ignore_installed=options.ignore_installed, + ignore_requires_python=options.ignore_requires_python, + force_reinstall=options.force_reinstall, + upgrade_strategy=upgrade_strategy, + use_pep517=options.use_pep517, + py_version_info=options.python_version, + ) + + self.trace_basic_info(finder) + + requirement_set = resolver.resolve( + reqs, check_supported_wheels=not options.target_dir + ) + + if options.json_report_file: + report = InstallationReport(requirement_set.requirements_to_install) + if options.json_report_file == "-": + print_json(data=report.to_dict()) + else: + with open(options.json_report_file, "w", encoding="utf-8") as f: + json.dump(report.to_dict(), f, indent=2, ensure_ascii=False) + + if options.dry_run: + would_install_items = sorted( + (r.metadata["name"], r.metadata["version"]) + for r in requirement_set.requirements_to_install + ) + if would_install_items: + write_output( + "Would install %s", + " ".join("-".join(item) for item in would_install_items), + ) + return SUCCESS + + try: + pip_req = requirement_set.get_requirement("pip") + except KeyError: + modifying_pip = False + else: + # If we're not replacing an already installed pip, + # we're not modifying it. + modifying_pip = pip_req.satisfied_by is None + if modifying_pip: + # Eagerly import this module to avoid crashes. Otherwise, this + # module would be imported *after* pip was replaced, resulting in + # crashes if the new self_outdated_check module was incompatible + # with the rest of pip that's already imported. + import pip._internal.self_outdated_check # noqa: F401 + protect_pip_from_modification_on_windows(modifying_pip=modifying_pip) + + reqs_to_build = [ + r + for r in requirement_set.requirements.values() + if should_build_for_install_command(r) + ] + + _, build_failures = build( + reqs_to_build, + wheel_cache=wheel_cache, + verify=True, + build_options=[], + global_options=global_options, + ) + + if build_failures: + raise InstallationError( + "ERROR: Failed to build installable wheels for some " + "pyproject.toml based projects ({})".format( + ", ".join(r.name for r in build_failures) # type: ignore + ) + ) + + to_install = resolver.get_installation_order(requirement_set) + + # Check for conflicts in the package set we're installing. + conflicts: Optional[ConflictDetails] = None + should_warn_about_conflicts = ( + not options.ignore_dependencies and options.warn_about_conflicts + ) + if should_warn_about_conflicts: + conflicts = self._determine_conflicts(to_install) + + # Don't warn about script install locations if + # --target or --prefix has been specified + warn_script_location = options.warn_script_location + if options.target_dir or options.prefix_path: + warn_script_location = False + + installed = install_given_reqs( + to_install, + global_options, + root=options.root_path, + home=target_temp_dir_path, + prefix=options.prefix_path, + warn_script_location=warn_script_location, + use_user_site=options.use_user_site, + pycompile=options.compile, + ) + + lib_locations = get_lib_location_guesses( + user=options.use_user_site, + home=target_temp_dir_path, + root=options.root_path, + prefix=options.prefix_path, + isolated=options.isolated_mode, + ) + env = get_environment(lib_locations) + + # Display a summary of installed packages, with extra care to + # display a package name as it was requested by the user. + installed.sort(key=operator.attrgetter("name")) + summary = [] + installed_versions = {} + for distribution in env.iter_all_distributions(): + installed_versions[distribution.canonical_name] = distribution.version + for package in installed: + display_name = package.name + version = installed_versions.get(canonicalize_name(display_name), None) + if version: + text = f"{display_name}-{version}" + else: + text = display_name + summary.append(text) + + if conflicts is not None: + self._warn_about_conflicts( + conflicts, + resolver_variant=self.determine_resolver_variant(options), + ) + + installed_desc = " ".join(summary) + if installed_desc: + write_output( + "Successfully installed %s", + installed_desc, + ) + except OSError as error: + show_traceback = self.verbosity >= 1 + + message = create_os_error_message( + error, + show_traceback, + options.use_user_site, + ) + logger.error(message, exc_info=show_traceback) + + return ERROR + + if options.target_dir: + assert target_temp_dir + self._handle_target_dir( + options.target_dir, target_temp_dir, options.upgrade + ) + if options.root_user_action == "warn": + warn_if_run_as_root() + return SUCCESS + + def _handle_target_dir( + self, target_dir: str, target_temp_dir: TempDirectory, upgrade: bool + ) -> None: + ensure_dir(target_dir) + + # Checking both purelib and platlib directories for installed + # packages to be moved to target directory + lib_dir_list = [] + + # Checking both purelib and platlib directories for installed + # packages to be moved to target directory + scheme = get_scheme("", home=target_temp_dir.path) + purelib_dir = scheme.purelib + platlib_dir = scheme.platlib + data_dir = scheme.data + + if os.path.exists(purelib_dir): + lib_dir_list.append(purelib_dir) + if os.path.exists(platlib_dir) and platlib_dir != purelib_dir: + lib_dir_list.append(platlib_dir) + if os.path.exists(data_dir): + lib_dir_list.append(data_dir) + + for lib_dir in lib_dir_list: + for item in os.listdir(lib_dir): + if lib_dir == data_dir: + ddir = os.path.join(data_dir, item) + if any(s.startswith(ddir) for s in lib_dir_list[:-1]): + continue + target_item_dir = os.path.join(target_dir, item) + if os.path.exists(target_item_dir): + if not upgrade: + logger.warning( + "Target directory %s already exists. Specify " + "--upgrade to force replacement.", + target_item_dir, + ) + continue + if os.path.islink(target_item_dir): + logger.warning( + "Target directory %s already exists and is " + "a link. pip will not automatically replace " + "links, please remove if replacement is " + "desired.", + target_item_dir, + ) + continue + if os.path.isdir(target_item_dir): + shutil.rmtree(target_item_dir) + else: + os.remove(target_item_dir) + + shutil.move(os.path.join(lib_dir, item), target_item_dir) + + def _determine_conflicts( + self, to_install: List[InstallRequirement] + ) -> Optional[ConflictDetails]: + try: + return check_install_conflicts(to_install) + except Exception: + logger.exception( + "Error while checking for conflicts. Please file an issue on " + "pip's issue tracker: https://github.com/pypa/pip/issues/new" + ) + return None + + def _warn_about_conflicts( + self, conflict_details: ConflictDetails, resolver_variant: str + ) -> None: + package_set, (missing, conflicting) = conflict_details + if not missing and not conflicting: + return + + parts: List[str] = [] + if resolver_variant == "legacy": + parts.append( + "pip's legacy dependency resolver does not consider dependency " + "conflicts when selecting packages. This behaviour is the " + "source of the following dependency conflicts." + ) + else: + assert resolver_variant == "resolvelib" + parts.append( + "pip's dependency resolver does not currently take into account " + "all the packages that are installed. This behaviour is the " + "source of the following dependency conflicts." + ) + + # NOTE: There is some duplication here, with commands/check.py + for project_name in missing: + version = package_set[project_name][0] + for dependency in missing[project_name]: + message = ( + f"{project_name} {version} requires {dependency[1]}, " + "which is not installed." + ) + parts.append(message) + + for project_name in conflicting: + version = package_set[project_name][0] + for dep_name, dep_version, req in conflicting[project_name]: + message = ( + "{name} {version} requires {requirement}, but {you} have " + "{dep_name} {dep_version} which is incompatible." + ).format( + name=project_name, + version=version, + requirement=req, + dep_name=dep_name, + dep_version=dep_version, + you=("you" if resolver_variant == "resolvelib" else "you'll"), + ) + parts.append(message) + + logger.critical("\n".join(parts)) + + +def get_lib_location_guesses( + user: bool = False, + home: Optional[str] = None, + root: Optional[str] = None, + isolated: bool = False, + prefix: Optional[str] = None, +) -> List[str]: + scheme = get_scheme( + "", + user=user, + home=home, + root=root, + isolated=isolated, + prefix=prefix, + ) + return [scheme.purelib, scheme.platlib] + + +def site_packages_writable(root: Optional[str], isolated: bool) -> bool: + return all( + test_writable_dir(d) + for d in set(get_lib_location_guesses(root=root, isolated=isolated)) + ) + + +def decide_user_install( + use_user_site: Optional[bool], + prefix_path: Optional[str] = None, + target_dir: Optional[str] = None, + root_path: Optional[str] = None, + isolated_mode: bool = False, +) -> bool: + """Determine whether to do a user install based on the input options. + + If use_user_site is False, no additional checks are done. + If use_user_site is True, it is checked for compatibility with other + options. + If use_user_site is None, the default behaviour depends on the environment, + which is provided by the other arguments. + """ + # In some cases (config from tox), use_user_site can be set to an integer + # rather than a bool, which 'use_user_site is False' wouldn't catch. + if (use_user_site is not None) and (not use_user_site): + logger.debug("Non-user install by explicit request") + return False + + if use_user_site: + if prefix_path: + raise CommandError( + "Can not combine '--user' and '--prefix' as they imply " + "different installation locations" + ) + if virtualenv_no_global(): + raise InstallationError( + "Can not perform a '--user' install. User site-packages " + "are not visible in this virtualenv." + ) + logger.debug("User install by explicit request") + return True + + # If we are here, user installs have not been explicitly requested/avoided + assert use_user_site is None + + # user install incompatible with --prefix/--target + if prefix_path or target_dir: + logger.debug("Non-user install due to --prefix or --target option") + return False + + # If user installs are not enabled, choose a non-user install + if not site.ENABLE_USER_SITE: + logger.debug("Non-user install because user site-packages disabled") + return False + + # If we have permission for a non-user install, do that, + # otherwise do a user install. + if site_packages_writable(root=root_path, isolated=isolated_mode): + logger.debug("Non-user install because site-packages writeable") + return False + + logger.info( + "Defaulting to user installation because normal site-packages " + "is not writeable" + ) + return True + + +def create_os_error_message( + error: OSError, show_traceback: bool, using_user_site: bool +) -> str: + """Format an error message for an OSError + + It may occur anytime during the execution of the install command. + """ + parts = [] + + # Mention the error if we are not going to show a traceback + parts.append("Could not install packages due to an OSError") + if not show_traceback: + parts.append(": ") + parts.append(str(error)) + else: + parts.append(".") + + # Spilt the error indication from a helper message (if any) + parts[-1] += "\n" + + # Suggest useful actions to the user: + # (1) using user site-packages or (2) verifying the permissions + if error.errno == errno.EACCES: + user_option_part = "Consider using the `--user` option" + permissions_part = "Check the permissions" + + if not running_under_virtualenv() and not using_user_site: + parts.extend( + [ + user_option_part, + " or ", + permissions_part.lower(), + ] + ) + else: + parts.append(permissions_part) + parts.append(".\n") + + # Suggest the user to enable Long Paths if path length is + # more than 260 + if ( + WINDOWS + and error.errno == errno.ENOENT + and error.filename + and len(error.filename) > 260 + ): + parts.append( + "HINT: This error might have occurred since " + "this system does not have Windows Long Path " + "support enabled. You can find information on " + "how to enable this at " + "https://pip.pypa.io/warnings/enable-long-paths\n" + ) + + return "".join(parts).strip() + "\n" diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/list.py b/backend/.venv/Lib/site-packages/pip/_internal/commands/list.py new file mode 100644 index 0000000..8494370 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/commands/list.py @@ -0,0 +1,375 @@ +import json +import logging +from optparse import Values +from typing import TYPE_CHECKING, Generator, List, Optional, Sequence, Tuple, cast + +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.packaging.version import Version + +from pip._internal.cli import cmdoptions +from pip._internal.cli.index_command import IndexGroupCommand +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.exceptions import CommandError +from pip._internal.metadata import BaseDistribution, get_environment +from pip._internal.models.selection_prefs import SelectionPreferences +from pip._internal.utils.compat import stdlib_pkgs +from pip._internal.utils.misc import tabulate, write_output + +if TYPE_CHECKING: + from pip._internal.index.package_finder import PackageFinder + from pip._internal.network.session import PipSession + + class _DistWithLatestInfo(BaseDistribution): + """Give the distribution object a couple of extra fields. + + These will be populated during ``get_outdated()``. This is dirty but + makes the rest of the code much cleaner. + """ + + latest_version: Version + latest_filetype: str + + _ProcessedDists = Sequence[_DistWithLatestInfo] + + +logger = logging.getLogger(__name__) + + +class ListCommand(IndexGroupCommand): + """ + List installed packages, including editables. + + Packages are listed in a case-insensitive sorted order. + """ + + ignore_require_venv = True + usage = """ + %prog [options]""" + + def add_options(self) -> None: + self.cmd_opts.add_option( + "-o", + "--outdated", + action="store_true", + default=False, + help="List outdated packages", + ) + self.cmd_opts.add_option( + "-u", + "--uptodate", + action="store_true", + default=False, + help="List uptodate packages", + ) + self.cmd_opts.add_option( + "-e", + "--editable", + action="store_true", + default=False, + help="List editable projects.", + ) + self.cmd_opts.add_option( + "-l", + "--local", + action="store_true", + default=False, + help=( + "If in a virtualenv that has global access, do not list " + "globally-installed packages." + ), + ) + self.cmd_opts.add_option( + "--user", + dest="user", + action="store_true", + default=False, + help="Only output packages installed in user-site.", + ) + self.cmd_opts.add_option(cmdoptions.list_path()) + self.cmd_opts.add_option( + "--pre", + action="store_true", + default=False, + help=( + "Include pre-release and development versions. By default, " + "pip only finds stable versions." + ), + ) + + self.cmd_opts.add_option( + "--format", + action="store", + dest="list_format", + default="columns", + choices=("columns", "freeze", "json"), + help=( + "Select the output format among: columns (default), freeze, or json. " + "The 'freeze' format cannot be used with the --outdated option." + ), + ) + + self.cmd_opts.add_option( + "--not-required", + action="store_true", + dest="not_required", + help="List packages that are not dependencies of installed packages.", + ) + + self.cmd_opts.add_option( + "--exclude-editable", + action="store_false", + dest="include_editable", + help="Exclude editable package from output.", + ) + self.cmd_opts.add_option( + "--include-editable", + action="store_true", + dest="include_editable", + help="Include editable package from output.", + default=True, + ) + self.cmd_opts.add_option(cmdoptions.list_exclude()) + index_opts = cmdoptions.make_option_group(cmdoptions.index_group, self.parser) + + self.parser.insert_option_group(0, index_opts) + self.parser.insert_option_group(0, self.cmd_opts) + + def handle_pip_version_check(self, options: Values) -> None: + if options.outdated or options.uptodate: + super().handle_pip_version_check(options) + + def _build_package_finder( + self, options: Values, session: "PipSession" + ) -> "PackageFinder": + """ + Create a package finder appropriate to this list command. + """ + # Lazy import the heavy index modules as most list invocations won't need 'em. + from pip._internal.index.collector import LinkCollector + from pip._internal.index.package_finder import PackageFinder + + link_collector = LinkCollector.create(session, options=options) + + # Pass allow_yanked=False to ignore yanked versions. + selection_prefs = SelectionPreferences( + allow_yanked=False, + allow_all_prereleases=options.pre, + ) + + return PackageFinder.create( + link_collector=link_collector, + selection_prefs=selection_prefs, + ) + + def run(self, options: Values, args: List[str]) -> int: + if options.outdated and options.uptodate: + raise CommandError("Options --outdated and --uptodate cannot be combined.") + + if options.outdated and options.list_format == "freeze": + raise CommandError( + "List format 'freeze' cannot be used with the --outdated option." + ) + + cmdoptions.check_list_path_option(options) + + skip = set(stdlib_pkgs) + if options.excludes: + skip.update(canonicalize_name(n) for n in options.excludes) + + packages: _ProcessedDists = [ + cast("_DistWithLatestInfo", d) + for d in get_environment(options.path).iter_installed_distributions( + local_only=options.local, + user_only=options.user, + editables_only=options.editable, + include_editables=options.include_editable, + skip=skip, + ) + ] + + # get_not_required must be called firstly in order to find and + # filter out all dependencies correctly. Otherwise a package + # can't be identified as requirement because some parent packages + # could be filtered out before. + if options.not_required: + packages = self.get_not_required(packages, options) + + if options.outdated: + packages = self.get_outdated(packages, options) + elif options.uptodate: + packages = self.get_uptodate(packages, options) + + self.output_package_listing(packages, options) + return SUCCESS + + def get_outdated( + self, packages: "_ProcessedDists", options: Values + ) -> "_ProcessedDists": + return [ + dist + for dist in self.iter_packages_latest_infos(packages, options) + if dist.latest_version > dist.version + ] + + def get_uptodate( + self, packages: "_ProcessedDists", options: Values + ) -> "_ProcessedDists": + return [ + dist + for dist in self.iter_packages_latest_infos(packages, options) + if dist.latest_version == dist.version + ] + + def get_not_required( + self, packages: "_ProcessedDists", options: Values + ) -> "_ProcessedDists": + dep_keys = { + canonicalize_name(dep.name) + for dist in packages + for dep in (dist.iter_dependencies() or ()) + } + + # Create a set to remove duplicate packages, and cast it to a list + # to keep the return type consistent with get_outdated and + # get_uptodate + return list({pkg for pkg in packages if pkg.canonical_name not in dep_keys}) + + def iter_packages_latest_infos( + self, packages: "_ProcessedDists", options: Values + ) -> Generator["_DistWithLatestInfo", None, None]: + with self._build_session(options) as session: + finder = self._build_package_finder(options, session) + + def latest_info( + dist: "_DistWithLatestInfo", + ) -> Optional["_DistWithLatestInfo"]: + all_candidates = finder.find_all_candidates(dist.canonical_name) + if not options.pre: + # Remove prereleases + all_candidates = [ + candidate + for candidate in all_candidates + if not candidate.version.is_prerelease + ] + + evaluator = finder.make_candidate_evaluator( + project_name=dist.canonical_name, + ) + best_candidate = evaluator.sort_best_candidate(all_candidates) + if best_candidate is None: + return None + + remote_version = best_candidate.version + if best_candidate.link.is_wheel: + typ = "wheel" + else: + typ = "sdist" + dist.latest_version = remote_version + dist.latest_filetype = typ + return dist + + for dist in map(latest_info, packages): + if dist is not None: + yield dist + + def output_package_listing( + self, packages: "_ProcessedDists", options: Values + ) -> None: + packages = sorted( + packages, + key=lambda dist: dist.canonical_name, + ) + if options.list_format == "columns" and packages: + data, header = format_for_columns(packages, options) + self.output_package_listing_columns(data, header) + elif options.list_format == "freeze": + for dist in packages: + if options.verbose >= 1: + write_output( + "%s==%s (%s)", dist.raw_name, dist.version, dist.location + ) + else: + write_output("%s==%s", dist.raw_name, dist.version) + elif options.list_format == "json": + write_output(format_for_json(packages, options)) + + def output_package_listing_columns( + self, data: List[List[str]], header: List[str] + ) -> None: + # insert the header first: we need to know the size of column names + if len(data) > 0: + data.insert(0, header) + + pkg_strings, sizes = tabulate(data) + + # Create and add a separator. + if len(data) > 0: + pkg_strings.insert(1, " ".join("-" * x for x in sizes)) + + for val in pkg_strings: + write_output(val) + + +def format_for_columns( + pkgs: "_ProcessedDists", options: Values +) -> Tuple[List[List[str]], List[str]]: + """ + Convert the package data into something usable + by output_package_listing_columns. + """ + header = ["Package", "Version"] + + running_outdated = options.outdated + if running_outdated: + header.extend(["Latest", "Type"]) + + has_editables = any(x.editable for x in pkgs) + if has_editables: + header.append("Editable project location") + + if options.verbose >= 1: + header.append("Location") + if options.verbose >= 1: + header.append("Installer") + + data = [] + for proj in pkgs: + # if we're working on the 'outdated' list, separate out the + # latest_version and type + row = [proj.raw_name, proj.raw_version] + + if running_outdated: + row.append(str(proj.latest_version)) + row.append(proj.latest_filetype) + + if has_editables: + row.append(proj.editable_project_location or "") + + if options.verbose >= 1: + row.append(proj.location or "") + if options.verbose >= 1: + row.append(proj.installer) + + data.append(row) + + return data, header + + +def format_for_json(packages: "_ProcessedDists", options: Values) -> str: + data = [] + for dist in packages: + info = { + "name": dist.raw_name, + "version": str(dist.version), + } + if options.verbose >= 1: + info["location"] = dist.location or "" + info["installer"] = dist.installer + if options.outdated: + info["latest_version"] = str(dist.latest_version) + info["latest_filetype"] = dist.latest_filetype + editable_project_location = dist.editable_project_location + if editable_project_location: + info["editable_project_location"] = editable_project_location + data.append(info) + return json.dumps(data) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/search.py b/backend/.venv/Lib/site-packages/pip/_internal/commands/search.py new file mode 100644 index 0000000..74b8d65 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/commands/search.py @@ -0,0 +1,172 @@ +import logging +import shutil +import sys +import textwrap +import xmlrpc.client +from collections import OrderedDict +from optparse import Values +from typing import TYPE_CHECKING, Dict, List, Optional, TypedDict + +from pip._vendor.packaging.version import parse as parse_version + +from pip._internal.cli.base_command import Command +from pip._internal.cli.req_command import SessionCommandMixin +from pip._internal.cli.status_codes import NO_MATCHES_FOUND, SUCCESS +from pip._internal.exceptions import CommandError +from pip._internal.metadata import get_default_environment +from pip._internal.models.index import PyPI +from pip._internal.network.xmlrpc import PipXmlrpcTransport +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import write_output + +if TYPE_CHECKING: + + class TransformedHit(TypedDict): + name: str + summary: str + versions: List[str] + + +logger = logging.getLogger(__name__) + + +class SearchCommand(Command, SessionCommandMixin): + """Search for PyPI packages whose name or summary contains .""" + + usage = """ + %prog [options] """ + ignore_require_venv = True + + def add_options(self) -> None: + self.cmd_opts.add_option( + "-i", + "--index", + dest="index", + metavar="URL", + default=PyPI.pypi_url, + help="Base URL of Python Package Index (default %default)", + ) + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options: Values, args: List[str]) -> int: + if not args: + raise CommandError("Missing required argument (search query).") + query = args + pypi_hits = self.search(query, options) + hits = transform_hits(pypi_hits) + + terminal_width = None + if sys.stdout.isatty(): + terminal_width = shutil.get_terminal_size()[0] + + print_results(hits, terminal_width=terminal_width) + if pypi_hits: + return SUCCESS + return NO_MATCHES_FOUND + + def search(self, query: List[str], options: Values) -> List[Dict[str, str]]: + index_url = options.index + + session = self.get_default_session(options) + + transport = PipXmlrpcTransport(index_url, session) + pypi = xmlrpc.client.ServerProxy(index_url, transport) + try: + hits = pypi.search({"name": query, "summary": query}, "or") + except xmlrpc.client.Fault as fault: + message = ( + f"XMLRPC request failed [code: {fault.faultCode}]\n{fault.faultString}" + ) + raise CommandError(message) + assert isinstance(hits, list) + return hits + + +def transform_hits(hits: List[Dict[str, str]]) -> List["TransformedHit"]: + """ + The list from pypi is really a list of versions. We want a list of + packages with the list of versions stored inline. This converts the + list from pypi into one we can use. + """ + packages: Dict[str, TransformedHit] = OrderedDict() + for hit in hits: + name = hit["name"] + summary = hit["summary"] + version = hit["version"] + + if name not in packages.keys(): + packages[name] = { + "name": name, + "summary": summary, + "versions": [version], + } + else: + packages[name]["versions"].append(version) + + # if this is the highest version, replace summary and score + if version == highest_version(packages[name]["versions"]): + packages[name]["summary"] = summary + + return list(packages.values()) + + +def print_dist_installation_info(name: str, latest: str) -> None: + env = get_default_environment() + dist = env.get_distribution(name) + if dist is not None: + with indent_log(): + if dist.version == latest: + write_output("INSTALLED: %s (latest)", dist.version) + else: + write_output("INSTALLED: %s", dist.version) + if parse_version(latest).pre: + write_output( + "LATEST: %s (pre-release; install" + " with `pip install --pre`)", + latest, + ) + else: + write_output("LATEST: %s", latest) + + +def print_results( + hits: List["TransformedHit"], + name_column_width: Optional[int] = None, + terminal_width: Optional[int] = None, +) -> None: + if not hits: + return + if name_column_width is None: + name_column_width = ( + max( + [ + len(hit["name"]) + len(highest_version(hit.get("versions", ["-"]))) + for hit in hits + ] + ) + + 4 + ) + + for hit in hits: + name = hit["name"] + summary = hit["summary"] or "" + latest = highest_version(hit.get("versions", ["-"])) + if terminal_width is not None: + target_width = terminal_width - name_column_width - 5 + if target_width > 10: + # wrap and indent summary to fit terminal + summary_lines = textwrap.wrap(summary, target_width) + summary = ("\n" + " " * (name_column_width + 3)).join(summary_lines) + + name_latest = f"{name} ({latest})" + line = f"{name_latest:{name_column_width}} - {summary}" + try: + write_output(line) + print_dist_installation_info(name, latest) + except UnicodeEncodeError: + pass + + +def highest_version(versions: List[str]) -> str: + return max(versions, key=parse_version) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/show.py b/backend/.venv/Lib/site-packages/pip/_internal/commands/show.py new file mode 100644 index 0000000..c54d548 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/commands/show.py @@ -0,0 +1,217 @@ +import logging +from optparse import Values +from typing import Generator, Iterable, Iterator, List, NamedTuple, Optional + +from pip._vendor.packaging.requirements import InvalidRequirement +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import ERROR, SUCCESS +from pip._internal.metadata import BaseDistribution, get_default_environment +from pip._internal.utils.misc import write_output + +logger = logging.getLogger(__name__) + + +class ShowCommand(Command): + """ + Show information about one or more installed packages. + + The output is in RFC-compliant mail header format. + """ + + usage = """ + %prog [options] ...""" + ignore_require_venv = True + + def add_options(self) -> None: + self.cmd_opts.add_option( + "-f", + "--files", + dest="files", + action="store_true", + default=False, + help="Show the full list of installed files for each package.", + ) + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options: Values, args: List[str]) -> int: + if not args: + logger.warning("ERROR: Please provide a package name or names.") + return ERROR + query = args + + results = search_packages_info(query) + if not print_results( + results, list_files=options.files, verbose=options.verbose + ): + return ERROR + return SUCCESS + + +class _PackageInfo(NamedTuple): + name: str + version: str + location: str + editable_project_location: Optional[str] + requires: List[str] + required_by: List[str] + installer: str + metadata_version: str + classifiers: List[str] + summary: str + homepage: str + project_urls: List[str] + author: str + author_email: str + license: str + entry_points: List[str] + files: Optional[List[str]] + + +def search_packages_info(query: List[str]) -> Generator[_PackageInfo, None, None]: + """ + Gather details from installed distributions. Print distribution name, + version, location, and installed files. Installed files requires a + pip generated 'installed-files.txt' in the distributions '.egg-info' + directory. + """ + env = get_default_environment() + + installed = {dist.canonical_name: dist for dist in env.iter_all_distributions()} + query_names = [canonicalize_name(name) for name in query] + missing = sorted( + [name for name, pkg in zip(query, query_names) if pkg not in installed] + ) + if missing: + logger.warning("Package(s) not found: %s", ", ".join(missing)) + + def _get_requiring_packages(current_dist: BaseDistribution) -> Iterator[str]: + return ( + dist.metadata["Name"] or "UNKNOWN" + for dist in installed.values() + if current_dist.canonical_name + in {canonicalize_name(d.name) for d in dist.iter_dependencies()} + ) + + for query_name in query_names: + try: + dist = installed[query_name] + except KeyError: + continue + + try: + requires = sorted( + # Avoid duplicates in requirements (e.g. due to environment markers). + {req.name for req in dist.iter_dependencies()}, + key=str.lower, + ) + except InvalidRequirement: + requires = sorted(dist.iter_raw_dependencies(), key=str.lower) + + try: + required_by = sorted(_get_requiring_packages(dist), key=str.lower) + except InvalidRequirement: + required_by = ["#N/A"] + + try: + entry_points_text = dist.read_text("entry_points.txt") + entry_points = entry_points_text.splitlines(keepends=False) + except FileNotFoundError: + entry_points = [] + + files_iter = dist.iter_declared_entries() + if files_iter is None: + files: Optional[List[str]] = None + else: + files = sorted(files_iter) + + metadata = dist.metadata + + project_urls = metadata.get_all("Project-URL", []) + homepage = metadata.get("Home-page", "") + if not homepage: + # It's common that there is a "homepage" Project-URL, but Home-page + # remains unset (especially as PEP 621 doesn't surface the field). + # + # This logic was taken from PyPI's codebase. + for url in project_urls: + url_label, url = url.split(",", maxsplit=1) + normalized_label = ( + url_label.casefold().replace("-", "").replace("_", "").strip() + ) + if normalized_label == "homepage": + homepage = url.strip() + break + + yield _PackageInfo( + name=dist.raw_name, + version=dist.raw_version, + location=dist.location or "", + editable_project_location=dist.editable_project_location, + requires=requires, + required_by=required_by, + installer=dist.installer, + metadata_version=dist.metadata_version or "", + classifiers=metadata.get_all("Classifier", []), + summary=metadata.get("Summary", ""), + homepage=homepage, + project_urls=project_urls, + author=metadata.get("Author", ""), + author_email=metadata.get("Author-email", ""), + license=metadata.get("License", ""), + entry_points=entry_points, + files=files, + ) + + +def print_results( + distributions: Iterable[_PackageInfo], + list_files: bool, + verbose: bool, +) -> bool: + """ + Print the information from installed distributions found. + """ + results_printed = False + for i, dist in enumerate(distributions): + results_printed = True + if i > 0: + write_output("---") + + write_output("Name: %s", dist.name) + write_output("Version: %s", dist.version) + write_output("Summary: %s", dist.summary) + write_output("Home-page: %s", dist.homepage) + write_output("Author: %s", dist.author) + write_output("Author-email: %s", dist.author_email) + write_output("License: %s", dist.license) + write_output("Location: %s", dist.location) + if dist.editable_project_location is not None: + write_output( + "Editable project location: %s", dist.editable_project_location + ) + write_output("Requires: %s", ", ".join(dist.requires)) + write_output("Required-by: %s", ", ".join(dist.required_by)) + + if verbose: + write_output("Metadata-Version: %s", dist.metadata_version) + write_output("Installer: %s", dist.installer) + write_output("Classifiers:") + for classifier in dist.classifiers: + write_output(" %s", classifier) + write_output("Entry-points:") + for entry in dist.entry_points: + write_output(" %s", entry.strip()) + write_output("Project-URLs:") + for project_url in dist.project_urls: + write_output(" %s", project_url) + if list_files: + write_output("Files:") + if dist.files is None: + write_output("Cannot locate RECORD or installed-files.txt") + else: + for line in dist.files: + write_output(" %s", line.strip()) + return results_printed diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/uninstall.py b/backend/.venv/Lib/site-packages/pip/_internal/commands/uninstall.py new file mode 100644 index 0000000..bc0edea --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/commands/uninstall.py @@ -0,0 +1,114 @@ +import logging +from optparse import Values +from typing import List + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.cli import cmdoptions +from pip._internal.cli.base_command import Command +from pip._internal.cli.index_command import SessionCommandMixin +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.exceptions import InstallationError +from pip._internal.req import parse_requirements +from pip._internal.req.constructors import ( + install_req_from_line, + install_req_from_parsed_requirement, +) +from pip._internal.utils.misc import ( + check_externally_managed, + protect_pip_from_modification_on_windows, + warn_if_run_as_root, +) + +logger = logging.getLogger(__name__) + + +class UninstallCommand(Command, SessionCommandMixin): + """ + Uninstall packages. + + pip is able to uninstall most installed packages. Known exceptions are: + + - Pure distutils packages installed with ``python setup.py install``, which + leave behind no metadata to determine what files were installed. + - Script wrappers installed by ``python setup.py develop``. + """ + + usage = """ + %prog [options] ... + %prog [options] -r ...""" + + def add_options(self) -> None: + self.cmd_opts.add_option( + "-r", + "--requirement", + dest="requirements", + action="append", + default=[], + metavar="file", + help=( + "Uninstall all the packages listed in the given requirements " + "file. This option can be used multiple times." + ), + ) + self.cmd_opts.add_option( + "-y", + "--yes", + dest="yes", + action="store_true", + help="Don't ask for confirmation of uninstall deletions.", + ) + self.cmd_opts.add_option(cmdoptions.root_user_action()) + self.cmd_opts.add_option(cmdoptions.override_externally_managed()) + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options: Values, args: List[str]) -> int: + session = self.get_default_session(options) + + reqs_to_uninstall = {} + for name in args: + req = install_req_from_line( + name, + isolated=options.isolated_mode, + ) + if req.name: + reqs_to_uninstall[canonicalize_name(req.name)] = req + else: + logger.warning( + "Invalid requirement: %r ignored -" + " the uninstall command expects named" + " requirements.", + name, + ) + for filename in options.requirements: + for parsed_req in parse_requirements( + filename, options=options, session=session + ): + req = install_req_from_parsed_requirement( + parsed_req, isolated=options.isolated_mode + ) + if req.name: + reqs_to_uninstall[canonicalize_name(req.name)] = req + if not reqs_to_uninstall: + raise InstallationError( + f"You must give at least one requirement to {self.name} (see " + f'"pip help {self.name}")' + ) + + if not options.override_externally_managed: + check_externally_managed() + + protect_pip_from_modification_on_windows( + modifying_pip="pip" in reqs_to_uninstall + ) + + for req in reqs_to_uninstall.values(): + uninstall_pathset = req.uninstall( + auto_confirm=options.yes, + verbose=self.verbosity > 0, + ) + if uninstall_pathset: + uninstall_pathset.commit() + if options.root_user_action == "warn": + warn_if_run_as_root() + return SUCCESS diff --git a/backend/.venv/Lib/site-packages/pip/_internal/commands/wheel.py b/backend/.venv/Lib/site-packages/pip/_internal/commands/wheel.py new file mode 100644 index 0000000..278719f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/commands/wheel.py @@ -0,0 +1,182 @@ +import logging +import os +import shutil +from optparse import Values +from typing import List + +from pip._internal.cache import WheelCache +from pip._internal.cli import cmdoptions +from pip._internal.cli.req_command import RequirementCommand, with_cleanup +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.exceptions import CommandError +from pip._internal.operations.build.build_tracker import get_build_tracker +from pip._internal.req.req_install import ( + InstallRequirement, + check_legacy_setup_py_options, +) +from pip._internal.utils.misc import ensure_dir, normalize_path +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.wheel_builder import build, should_build_for_wheel_command + +logger = logging.getLogger(__name__) + + +class WheelCommand(RequirementCommand): + """ + Build Wheel archives for your requirements and dependencies. + + Wheel is a built-package format, and offers the advantage of not + recompiling your software during every install. For more details, see the + wheel docs: https://wheel.readthedocs.io/en/latest/ + + 'pip wheel' uses the build system interface as described here: + https://pip.pypa.io/en/stable/reference/build-system/ + + """ + + usage = """ + %prog [options] ... + %prog [options] -r ... + %prog [options] [-e] ... + %prog [options] [-e] ... + %prog [options] ...""" + + def add_options(self) -> None: + self.cmd_opts.add_option( + "-w", + "--wheel-dir", + dest="wheel_dir", + metavar="dir", + default=os.curdir, + help=( + "Build wheels into , where the default is the " + "current working directory." + ), + ) + self.cmd_opts.add_option(cmdoptions.no_binary()) + self.cmd_opts.add_option(cmdoptions.only_binary()) + self.cmd_opts.add_option(cmdoptions.prefer_binary()) + self.cmd_opts.add_option(cmdoptions.no_build_isolation()) + self.cmd_opts.add_option(cmdoptions.use_pep517()) + self.cmd_opts.add_option(cmdoptions.no_use_pep517()) + self.cmd_opts.add_option(cmdoptions.check_build_deps()) + self.cmd_opts.add_option(cmdoptions.constraints()) + self.cmd_opts.add_option(cmdoptions.editable()) + self.cmd_opts.add_option(cmdoptions.requirements()) + self.cmd_opts.add_option(cmdoptions.src()) + self.cmd_opts.add_option(cmdoptions.ignore_requires_python()) + self.cmd_opts.add_option(cmdoptions.no_deps()) + self.cmd_opts.add_option(cmdoptions.progress_bar()) + + self.cmd_opts.add_option( + "--no-verify", + dest="no_verify", + action="store_true", + default=False, + help="Don't verify if built wheel is valid.", + ) + + self.cmd_opts.add_option(cmdoptions.config_settings()) + self.cmd_opts.add_option(cmdoptions.build_options()) + self.cmd_opts.add_option(cmdoptions.global_options()) + + self.cmd_opts.add_option( + "--pre", + action="store_true", + default=False, + help=( + "Include pre-release and development versions. By default, " + "pip only finds stable versions." + ), + ) + + self.cmd_opts.add_option(cmdoptions.require_hashes()) + + index_opts = cmdoptions.make_option_group( + cmdoptions.index_group, + self.parser, + ) + + self.parser.insert_option_group(0, index_opts) + self.parser.insert_option_group(0, self.cmd_opts) + + @with_cleanup + def run(self, options: Values, args: List[str]) -> int: + session = self.get_default_session(options) + + finder = self._build_package_finder(options, session) + + options.wheel_dir = normalize_path(options.wheel_dir) + ensure_dir(options.wheel_dir) + + build_tracker = self.enter_context(get_build_tracker()) + + directory = TempDirectory( + delete=not options.no_clean, + kind="wheel", + globally_managed=True, + ) + + reqs = self.get_requirements(args, options, finder, session) + check_legacy_setup_py_options(options, reqs) + + wheel_cache = WheelCache(options.cache_dir) + + preparer = self.make_requirement_preparer( + temp_build_dir=directory, + options=options, + build_tracker=build_tracker, + session=session, + finder=finder, + download_dir=options.wheel_dir, + use_user_site=False, + verbosity=self.verbosity, + ) + + resolver = self.make_resolver( + preparer=preparer, + finder=finder, + options=options, + wheel_cache=wheel_cache, + ignore_requires_python=options.ignore_requires_python, + use_pep517=options.use_pep517, + ) + + self.trace_basic_info(finder) + + requirement_set = resolver.resolve(reqs, check_supported_wheels=True) + + reqs_to_build: List[InstallRequirement] = [] + for req in requirement_set.requirements.values(): + if req.is_wheel: + preparer.save_linked_requirement(req) + elif should_build_for_wheel_command(req): + reqs_to_build.append(req) + + preparer.prepare_linked_requirements_more(requirement_set.requirements.values()) + + # build wheels + build_successes, build_failures = build( + reqs_to_build, + wheel_cache=wheel_cache, + verify=(not options.no_verify), + build_options=options.build_options or [], + global_options=options.global_options or [], + ) + for req in build_successes: + assert req.link and req.link.is_wheel + assert req.local_file_path + # copy from cache to target directory + try: + shutil.copy(req.local_file_path, options.wheel_dir) + except OSError as e: + logger.warning( + "Building wheel for %s failed: %s", + req.name, + e, + ) + build_failures.append(req) + if len(build_failures) != 0: + raise CommandError("Failed to build one or more wheels") + + return SUCCESS diff --git a/backend/.venv/Lib/site-packages/pip/_internal/configuration.py b/backend/.venv/Lib/site-packages/pip/_internal/configuration.py new file mode 100644 index 0000000..c25273d --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/configuration.py @@ -0,0 +1,383 @@ +"""Configuration management setup + +Some terminology: +- name + As written in config files. +- value + Value associated with a name +- key + Name combined with it's section (section.name) +- variant + A single word describing where the configuration key-value pair came from +""" + +import configparser +import locale +import os +import sys +from typing import Any, Dict, Iterable, List, NewType, Optional, Tuple + +from pip._internal.exceptions import ( + ConfigurationError, + ConfigurationFileCouldNotBeLoaded, +) +from pip._internal.utils import appdirs +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.logging import getLogger +from pip._internal.utils.misc import ensure_dir, enum + +RawConfigParser = configparser.RawConfigParser # Shorthand +Kind = NewType("Kind", str) + +CONFIG_BASENAME = "pip.ini" if WINDOWS else "pip.conf" +ENV_NAMES_IGNORED = "version", "help" + +# The kinds of configurations there are. +kinds = enum( + USER="user", # User Specific + GLOBAL="global", # System Wide + SITE="site", # [Virtual] Environment Specific + ENV="env", # from PIP_CONFIG_FILE + ENV_VAR="env-var", # from Environment Variables +) +OVERRIDE_ORDER = kinds.GLOBAL, kinds.USER, kinds.SITE, kinds.ENV, kinds.ENV_VAR +VALID_LOAD_ONLY = kinds.USER, kinds.GLOBAL, kinds.SITE + +logger = getLogger(__name__) + + +# NOTE: Maybe use the optionx attribute to normalize keynames. +def _normalize_name(name: str) -> str: + """Make a name consistent regardless of source (environment or file)""" + name = name.lower().replace("_", "-") + if name.startswith("--"): + name = name[2:] # only prefer long opts + return name + + +def _disassemble_key(name: str) -> List[str]: + if "." not in name: + error_message = ( + "Key does not contain dot separated section and key. " + f"Perhaps you wanted to use 'global.{name}' instead?" + ) + raise ConfigurationError(error_message) + return name.split(".", 1) + + +def get_configuration_files() -> Dict[Kind, List[str]]: + global_config_files = [ + os.path.join(path, CONFIG_BASENAME) for path in appdirs.site_config_dirs("pip") + ] + + site_config_file = os.path.join(sys.prefix, CONFIG_BASENAME) + legacy_config_file = os.path.join( + os.path.expanduser("~"), + "pip" if WINDOWS else ".pip", + CONFIG_BASENAME, + ) + new_config_file = os.path.join(appdirs.user_config_dir("pip"), CONFIG_BASENAME) + return { + kinds.GLOBAL: global_config_files, + kinds.SITE: [site_config_file], + kinds.USER: [legacy_config_file, new_config_file], + } + + +class Configuration: + """Handles management of configuration. + + Provides an interface to accessing and managing configuration files. + + This class converts provides an API that takes "section.key-name" style + keys and stores the value associated with it as "key-name" under the + section "section". + + This allows for a clean interface wherein the both the section and the + key-name are preserved in an easy to manage form in the configuration files + and the data stored is also nice. + """ + + def __init__(self, isolated: bool, load_only: Optional[Kind] = None) -> None: + super().__init__() + + if load_only is not None and load_only not in VALID_LOAD_ONLY: + raise ConfigurationError( + "Got invalid value for load_only - should be one of {}".format( + ", ".join(map(repr, VALID_LOAD_ONLY)) + ) + ) + self.isolated = isolated + self.load_only = load_only + + # Because we keep track of where we got the data from + self._parsers: Dict[Kind, List[Tuple[str, RawConfigParser]]] = { + variant: [] for variant in OVERRIDE_ORDER + } + self._config: Dict[Kind, Dict[str, Any]] = { + variant: {} for variant in OVERRIDE_ORDER + } + self._modified_parsers: List[Tuple[str, RawConfigParser]] = [] + + def load(self) -> None: + """Loads configuration from configuration files and environment""" + self._load_config_files() + if not self.isolated: + self._load_environment_vars() + + def get_file_to_edit(self) -> Optional[str]: + """Returns the file with highest priority in configuration""" + assert self.load_only is not None, "Need to be specified a file to be editing" + + try: + return self._get_parser_to_modify()[0] + except IndexError: + return None + + def items(self) -> Iterable[Tuple[str, Any]]: + """Returns key-value pairs like dict.items() representing the loaded + configuration + """ + return self._dictionary.items() + + def get_value(self, key: str) -> Any: + """Get a value from the configuration.""" + orig_key = key + key = _normalize_name(key) + try: + return self._dictionary[key] + except KeyError: + # disassembling triggers a more useful error message than simply + # "No such key" in the case that the key isn't in the form command.option + _disassemble_key(key) + raise ConfigurationError(f"No such key - {orig_key}") + + def set_value(self, key: str, value: Any) -> None: + """Modify a value in the configuration.""" + key = _normalize_name(key) + self._ensure_have_load_only() + + assert self.load_only + fname, parser = self._get_parser_to_modify() + + if parser is not None: + section, name = _disassemble_key(key) + + # Modify the parser and the configuration + if not parser.has_section(section): + parser.add_section(section) + parser.set(section, name, value) + + self._config[self.load_only][key] = value + self._mark_as_modified(fname, parser) + + def unset_value(self, key: str) -> None: + """Unset a value in the configuration.""" + orig_key = key + key = _normalize_name(key) + self._ensure_have_load_only() + + assert self.load_only + if key not in self._config[self.load_only]: + raise ConfigurationError(f"No such key - {orig_key}") + + fname, parser = self._get_parser_to_modify() + + if parser is not None: + section, name = _disassemble_key(key) + if not ( + parser.has_section(section) and parser.remove_option(section, name) + ): + # The option was not removed. + raise ConfigurationError( + "Fatal Internal error [id=1]. Please report as a bug." + ) + + # The section may be empty after the option was removed. + if not parser.items(section): + parser.remove_section(section) + self._mark_as_modified(fname, parser) + + del self._config[self.load_only][key] + + def save(self) -> None: + """Save the current in-memory state.""" + self._ensure_have_load_only() + + for fname, parser in self._modified_parsers: + logger.info("Writing to %s", fname) + + # Ensure directory exists. + ensure_dir(os.path.dirname(fname)) + + # Ensure directory's permission(need to be writeable) + try: + with open(fname, "w") as f: + parser.write(f) + except OSError as error: + raise ConfigurationError( + f"An error occurred while writing to the configuration file " + f"{fname}: {error}" + ) + + # + # Private routines + # + + def _ensure_have_load_only(self) -> None: + if self.load_only is None: + raise ConfigurationError("Needed a specific file to be modifying.") + logger.debug("Will be working with %s variant only", self.load_only) + + @property + def _dictionary(self) -> Dict[str, Any]: + """A dictionary representing the loaded configuration.""" + # NOTE: Dictionaries are not populated if not loaded. So, conditionals + # are not needed here. + retval = {} + + for variant in OVERRIDE_ORDER: + retval.update(self._config[variant]) + + return retval + + def _load_config_files(self) -> None: + """Loads configuration from configuration files""" + config_files = dict(self.iter_config_files()) + if config_files[kinds.ENV][0:1] == [os.devnull]: + logger.debug( + "Skipping loading configuration files due to " + "environment's PIP_CONFIG_FILE being os.devnull" + ) + return + + for variant, files in config_files.items(): + for fname in files: + # If there's specific variant set in `load_only`, load only + # that variant, not the others. + if self.load_only is not None and variant != self.load_only: + logger.debug("Skipping file '%s' (variant: %s)", fname, variant) + continue + + parser = self._load_file(variant, fname) + + # Keeping track of the parsers used + self._parsers[variant].append((fname, parser)) + + def _load_file(self, variant: Kind, fname: str) -> RawConfigParser: + logger.verbose("For variant '%s', will try loading '%s'", variant, fname) + parser = self._construct_parser(fname) + + for section in parser.sections(): + items = parser.items(section) + self._config[variant].update(self._normalized_keys(section, items)) + + return parser + + def _construct_parser(self, fname: str) -> RawConfigParser: + parser = configparser.RawConfigParser() + # If there is no such file, don't bother reading it but create the + # parser anyway, to hold the data. + # Doing this is useful when modifying and saving files, where we don't + # need to construct a parser. + if os.path.exists(fname): + locale_encoding = locale.getpreferredencoding(False) + try: + parser.read(fname, encoding=locale_encoding) + except UnicodeDecodeError: + # See https://github.com/pypa/pip/issues/4963 + raise ConfigurationFileCouldNotBeLoaded( + reason=f"contains invalid {locale_encoding} characters", + fname=fname, + ) + except configparser.Error as error: + # See https://github.com/pypa/pip/issues/4893 + raise ConfigurationFileCouldNotBeLoaded(error=error) + return parser + + def _load_environment_vars(self) -> None: + """Loads configuration from environment variables""" + self._config[kinds.ENV_VAR].update( + self._normalized_keys(":env:", self.get_environ_vars()) + ) + + def _normalized_keys( + self, section: str, items: Iterable[Tuple[str, Any]] + ) -> Dict[str, Any]: + """Normalizes items to construct a dictionary with normalized keys. + + This routine is where the names become keys and are made the same + regardless of source - configuration files or environment. + """ + normalized = {} + for name, val in items: + key = section + "." + _normalize_name(name) + normalized[key] = val + return normalized + + def get_environ_vars(self) -> Iterable[Tuple[str, str]]: + """Returns a generator with all environmental vars with prefix PIP_""" + for key, val in os.environ.items(): + if key.startswith("PIP_"): + name = key[4:].lower() + if name not in ENV_NAMES_IGNORED: + yield name, val + + # XXX: This is patched in the tests. + def iter_config_files(self) -> Iterable[Tuple[Kind, List[str]]]: + """Yields variant and configuration files associated with it. + + This should be treated like items of a dictionary. The order + here doesn't affect what gets overridden. That is controlled + by OVERRIDE_ORDER. However this does control the order they are + displayed to the user. It's probably most ergononmic to display + things in the same order as OVERRIDE_ORDER + """ + # SMELL: Move the conditions out of this function + + env_config_file = os.environ.get("PIP_CONFIG_FILE", None) + config_files = get_configuration_files() + + yield kinds.GLOBAL, config_files[kinds.GLOBAL] + + # per-user config is not loaded when env_config_file exists + should_load_user_config = not self.isolated and not ( + env_config_file and os.path.exists(env_config_file) + ) + if should_load_user_config: + # The legacy config file is overridden by the new config file + yield kinds.USER, config_files[kinds.USER] + + # virtualenv config + yield kinds.SITE, config_files[kinds.SITE] + + if env_config_file is not None: + yield kinds.ENV, [env_config_file] + else: + yield kinds.ENV, [] + + def get_values_in_config(self, variant: Kind) -> Dict[str, Any]: + """Get values present in a config file""" + return self._config[variant] + + def _get_parser_to_modify(self) -> Tuple[str, RawConfigParser]: + # Determine which parser to modify + assert self.load_only + parsers = self._parsers[self.load_only] + if not parsers: + # This should not happen if everything works correctly. + raise ConfigurationError( + "Fatal Internal error [id=2]. Please report as a bug." + ) + + # Use the highest priority parser. + return parsers[-1] + + # XXX: This is patched in the tests. + def _mark_as_modified(self, fname: str, parser: RawConfigParser) -> None: + file_parser_tuple = (fname, parser) + if file_parser_tuple not in self._modified_parsers: + self._modified_parsers.append(file_parser_tuple) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self._dictionary!r})" diff --git a/backend/.venv/Lib/site-packages/pip/_internal/distributions/__init__.py b/backend/.venv/Lib/site-packages/pip/_internal/distributions/__init__.py new file mode 100644 index 0000000..9a89a83 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/distributions/__init__.py @@ -0,0 +1,21 @@ +from pip._internal.distributions.base import AbstractDistribution +from pip._internal.distributions.sdist import SourceDistribution +from pip._internal.distributions.wheel import WheelDistribution +from pip._internal.req.req_install import InstallRequirement + + +def make_distribution_for_install_requirement( + install_req: InstallRequirement, +) -> AbstractDistribution: + """Returns a Distribution for the given InstallRequirement""" + # Editable requirements will always be source distributions. They use the + # legacy logic until we create a modern standard for them. + if install_req.editable: + return SourceDistribution(install_req) + + # If it's a wheel, it's a WheelDistribution + if install_req.is_wheel: + return WheelDistribution(install_req) + + # Otherwise, a SourceDistribution + return SourceDistribution(install_req) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1740633cdd8984bf64581d9c0d6ca49c90cfe37e GIT binary patch literal 943 zcmaJ;&1(}u6rXAKt0rk^?L~sJMG&?nn`1%iN3j<{J+ud5U0C*GnohGH>CB|1(t`*8 zhkEQ){8PLHb5Irof+uf*^yJAmYgS{FKA3&K_vXE~zu&wM_4+jg_Uz?->QoT=CWF$H zDVXd4I7bnRaEub{U@Y-MypU9!N`Wh}lBkYaU?tWP-O&N7M2|Fr_mxP0qd3N?VJ&`_ zBQ2b-ZU>_hTc#6_hfbXB;_@DsMgDHw)+1w zEc|M7x8TK1-<*|X?q|#t2gK~qW0IQxsp9-3GT4BbB8~9*dG|Bl_KG;lc;qy-IKzeBj& zqrJ9AQ$bkj$L(llQ@riL1r?rW_fB&w@w>#Ez4t&16cqcByC@gL>cFiac@MyAG_E1z z`X{~lQEz@}tX*sj8}`7k$J$KRyl4&^t%1?H)KKl#+wQQsK2X*t(2ky4i@6CT?cXHr zSrXh1d`_5LWxjS*885nu7rnCX&r|0&|DFdDZ8)W5rolf8t?v+9lDH;G7+Xme^<(mY stwJc*#P7goT)`NR(Dn#D8li_Hv^Cb2@W$um+v5uOuj-9U6?`%0C$WbHV*mgE literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/distributions/__pycache__/base.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/distributions/__pycache__/base.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1bc2c1d5cb88301b07c5a9b5d464e1d65846beb1 GIT binary patch literal 2895 zcmb7G&2Jk;6rWvt?X?p-?gwp?ehqC<u)v$2( zz0)U*$v00-zBM&{GSuJk1KV>=r>umfpb{Cv|EyusZ7 zxP{ZEwP?=qH*A-2VXd1bB-h!jeF4M=5Gf~Bg^{Ytlxm8pJk3%pT~A*jb%kk{2df&- zEEIb$h-sGMI?oNmrmjMq>02FQ?Z`NSkrV{!Th6|ppEB_<1NXfu{s^6OPn^EGN3g$Mhk&Q84tK<*e-1P zucxlr;E`Q0JqA94vSqpl0&00ea4T?HvD>kx>$&4ie@>VT#Uw9xoCd2HpdVLU(j_~X zr;-Ovzb}?UUEfScdWnOH`G@_qMW1qXsn-mW>|r`g#_SlH$t7JE#?T>*RzieuktsbF z(Wz8S6hJeP=3+(B)S5o5+BT(cL8d^1CyD7 zxt=1sj`6#kv#2H>UGl^tgcG@0YuXO*0ZEHotS73ch;!WKBKD-|+UJ{Hd)SQVfk$nK z2jJ9tq|6%`sYL#UDL`A85l}4QPFsN6?t{Yte``lz`B1q|g6`2(^%A)T<0@%6gZ!BCE=DITdQM>2ne4hGDyQU>E|2AMn$XJN0N2<_sfh5yOyZjM9~V_~g+U%#DO< z@)>s_kmIIhc}1^Z`8k)#NRz2BA&u(RX~Uk9@af+m-Y+eGLwXrQq6m zFac4@aQr~Rx@SqE-dD=X@;4JSsoA_4(72k=X`S)`AfbRZV0C>CV097AeK1L&1-&~} zr_-Lx51|kO3bZk3XkJO(4$`o}03#dX4MtM}UphNm@dfuy!HwR;8404t%Coc3jgA91 zM`Ol<;m=uRRSCCDd%;x0ccPB~XD5X4#Hu1nkPV5spkgzuVJQm3=%C%O+43_Rmf>Ns zeRxj+mKAb;kPPkns<{8QzF%ws&i^fgz-t7SR&0l**Sq049(054OTltwLpL8Qe-LjT zfMtdJT70_4+b~m)K8qp?hv85hr!76l#Bmmuta)xN8ZjFNm9)|zmpuOgWb4tD(^2-t zPS6&+aM=xu#QOj?oqFtkV!fB2-!SSY>QvB3r&7iKN|iU^Jirf+VT5_ZXn3sYAU$Xp z=bNU}ImsFZ^DGz{@Gpr(y&9&>niZDJ&Ii{Q9?X`YB`}sS1sx@JAXQ8R0I%~N6Zo%6 zjNnPS=6R0Ti)5iQbu8{UhEZ0;Cg4UOI2J)v;D3~8!SczEV0mzv{GpaKy*;XG+i&lx zvsr+;ii5G7)enEhFdv literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..380688f88733a6218c552542ce2a8358bcab053d GIT binary patch literal 1702 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 Pt(5vZkNiboO%n1ii!xkQ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/distributions/base.py b/backend/.venv/Lib/site-packages/pip/_internal/distributions/base.py new file mode 100644 index 0000000..6e4d0c9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/distributions/base.py @@ -0,0 +1,53 @@ +import abc +from typing import TYPE_CHECKING, Optional + +from pip._internal.metadata.base import BaseDistribution +from pip._internal.req import InstallRequirement + +if TYPE_CHECKING: + from pip._internal.index.package_finder import PackageFinder + + +class AbstractDistribution(metaclass=abc.ABCMeta): + """A base class for handling installable artifacts. + + The requirements for anything installable are as follows: + + - we must be able to determine the requirement name + (or we can't correctly handle the non-upgrade case). + + - for packages with setup requirements, we must also be able + to determine their requirements without installing additional + packages (for the same reason as run-time dependencies) + + - we must be able to create a Distribution object exposing the + above metadata. + + - if we need to do work in the build tracker, we must be able to generate a unique + string to identify the requirement in the build tracker. + """ + + def __init__(self, req: InstallRequirement) -> None: + super().__init__() + self.req = req + + @abc.abstractproperty + def build_tracker_id(self) -> Optional[str]: + """A string that uniquely identifies this requirement to the build tracker. + + If None, then this dist has no work to do in the build tracker, and + ``.prepare_distribution_metadata()`` will not be called.""" + raise NotImplementedError() + + @abc.abstractmethod + def get_metadata_distribution(self) -> BaseDistribution: + raise NotImplementedError() + + @abc.abstractmethod + def prepare_distribution_metadata( + self, + finder: "PackageFinder", + build_isolation: bool, + check_build_deps: bool, + ) -> None: + raise NotImplementedError() diff --git a/backend/.venv/Lib/site-packages/pip/_internal/distributions/installed.py b/backend/.venv/Lib/site-packages/pip/_internal/distributions/installed.py new file mode 100644 index 0000000..ab8d53b --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/distributions/installed.py @@ -0,0 +1,29 @@ +from typing import Optional + +from pip._internal.distributions.base import AbstractDistribution +from pip._internal.index.package_finder import PackageFinder +from pip._internal.metadata import BaseDistribution + + +class InstalledDistribution(AbstractDistribution): + """Represents an installed package. + + This does not need any preparation as the required information has already + been computed. + """ + + @property + def build_tracker_id(self) -> Optional[str]: + return None + + def get_metadata_distribution(self) -> BaseDistribution: + assert self.req.satisfied_by is not None, "not actually installed" + return self.req.satisfied_by + + def prepare_distribution_metadata( + self, + finder: PackageFinder, + build_isolation: bool, + check_build_deps: bool, + ) -> None: + pass diff --git a/backend/.venv/Lib/site-packages/pip/_internal/distributions/sdist.py b/backend/.venv/Lib/site-packages/pip/_internal/distributions/sdist.py new file mode 100644 index 0000000..28ea5ce --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/distributions/sdist.py @@ -0,0 +1,158 @@ +import logging +from typing import TYPE_CHECKING, Iterable, Optional, Set, Tuple + +from pip._internal.build_env import BuildEnvironment +from pip._internal.distributions.base import AbstractDistribution +from pip._internal.exceptions import InstallationError +from pip._internal.metadata import BaseDistribution +from pip._internal.utils.subprocess import runner_with_spinner_message + +if TYPE_CHECKING: + from pip._internal.index.package_finder import PackageFinder + +logger = logging.getLogger(__name__) + + +class SourceDistribution(AbstractDistribution): + """Represents a source distribution. + + The preparation step for these needs metadata for the packages to be + generated, either using PEP 517 or using the legacy `setup.py egg_info`. + """ + + @property + def build_tracker_id(self) -> Optional[str]: + """Identify this requirement uniquely by its link.""" + assert self.req.link + return self.req.link.url_without_fragment + + def get_metadata_distribution(self) -> BaseDistribution: + return self.req.get_dist() + + def prepare_distribution_metadata( + self, + finder: "PackageFinder", + build_isolation: bool, + check_build_deps: bool, + ) -> None: + # Load pyproject.toml, to determine whether PEP 517 is to be used + self.req.load_pyproject_toml() + + # Set up the build isolation, if this requirement should be isolated + should_isolate = self.req.use_pep517 and build_isolation + if should_isolate: + # Setup an isolated environment and install the build backend static + # requirements in it. + self._prepare_build_backend(finder) + # Check that if the requirement is editable, it either supports PEP 660 or + # has a setup.py or a setup.cfg. This cannot be done earlier because we need + # to setup the build backend to verify it supports build_editable, nor can + # it be done later, because we want to avoid installing build requirements + # needlessly. Doing it here also works around setuptools generating + # UNKNOWN.egg-info when running get_requires_for_build_wheel on a directory + # without setup.py nor setup.cfg. + self.req.isolated_editable_sanity_check() + # Install the dynamic build requirements. + self._install_build_reqs(finder) + # Check if the current environment provides build dependencies + should_check_deps = self.req.use_pep517 and check_build_deps + if should_check_deps: + pyproject_requires = self.req.pyproject_requires + assert pyproject_requires is not None + conflicting, missing = self.req.build_env.check_requirements( + pyproject_requires + ) + if conflicting: + self._raise_conflicts("the backend dependencies", conflicting) + if missing: + self._raise_missing_reqs(missing) + self.req.prepare_metadata() + + def _prepare_build_backend(self, finder: "PackageFinder") -> None: + # Isolate in a BuildEnvironment and install the build-time + # requirements. + pyproject_requires = self.req.pyproject_requires + assert pyproject_requires is not None + + self.req.build_env = BuildEnvironment() + self.req.build_env.install_requirements( + finder, pyproject_requires, "overlay", kind="build dependencies" + ) + conflicting, missing = self.req.build_env.check_requirements( + self.req.requirements_to_check + ) + if conflicting: + self._raise_conflicts("PEP 517/518 supported requirements", conflicting) + if missing: + logger.warning( + "Missing build requirements in pyproject.toml for %s.", + self.req, + ) + logger.warning( + "The project does not specify a build backend, and " + "pip cannot fall back to setuptools without %s.", + " and ".join(map(repr, sorted(missing))), + ) + + def _get_build_requires_wheel(self) -> Iterable[str]: + with self.req.build_env: + runner = runner_with_spinner_message("Getting requirements to build wheel") + backend = self.req.pep517_backend + assert backend is not None + with backend.subprocess_runner(runner): + return backend.get_requires_for_build_wheel() + + def _get_build_requires_editable(self) -> Iterable[str]: + with self.req.build_env: + runner = runner_with_spinner_message( + "Getting requirements to build editable" + ) + backend = self.req.pep517_backend + assert backend is not None + with backend.subprocess_runner(runner): + return backend.get_requires_for_build_editable() + + def _install_build_reqs(self, finder: "PackageFinder") -> None: + # Install any extra build dependencies that the backend requests. + # This must be done in a second pass, as the pyproject.toml + # dependencies must be installed before we can call the backend. + if ( + self.req.editable + and self.req.permit_editable_wheels + and self.req.supports_pyproject_editable + ): + build_reqs = self._get_build_requires_editable() + else: + build_reqs = self._get_build_requires_wheel() + conflicting, missing = self.req.build_env.check_requirements(build_reqs) + if conflicting: + self._raise_conflicts("the backend dependencies", conflicting) + self.req.build_env.install_requirements( + finder, missing, "normal", kind="backend dependencies" + ) + + def _raise_conflicts( + self, conflicting_with: str, conflicting_reqs: Set[Tuple[str, str]] + ) -> None: + format_string = ( + "Some build dependencies for {requirement} " + "conflict with {conflicting_with}: {description}." + ) + error_message = format_string.format( + requirement=self.req, + conflicting_with=conflicting_with, + description=", ".join( + f"{installed} is incompatible with {wanted}" + for installed, wanted in sorted(conflicting_reqs) + ), + ) + raise InstallationError(error_message) + + def _raise_missing_reqs(self, missing: Set[str]) -> None: + format_string = ( + "Some build dependencies for {requirement} are missing: {missing}." + ) + error_message = format_string.format( + requirement=self.req, missing=", ".join(map(repr, sorted(missing))) + ) + raise InstallationError(error_message) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/distributions/wheel.py b/backend/.venv/Lib/site-packages/pip/_internal/distributions/wheel.py new file mode 100644 index 0000000..bfadd39 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/distributions/wheel.py @@ -0,0 +1,42 @@ +from typing import TYPE_CHECKING, Optional + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.distributions.base import AbstractDistribution +from pip._internal.metadata import ( + BaseDistribution, + FilesystemWheel, + get_wheel_distribution, +) + +if TYPE_CHECKING: + from pip._internal.index.package_finder import PackageFinder + + +class WheelDistribution(AbstractDistribution): + """Represents a wheel distribution. + + This does not need any preparation as wheels can be directly unpacked. + """ + + @property + def build_tracker_id(self) -> Optional[str]: + return None + + def get_metadata_distribution(self) -> BaseDistribution: + """Loads the metadata from the wheel file into memory and returns a + Distribution that uses it, not relying on the wheel file or + requirement. + """ + assert self.req.local_file_path, "Set as part of preparation during download" + assert self.req.name, "Wheels are never unnamed" + wheel = FilesystemWheel(self.req.local_file_path) + return get_wheel_distribution(wheel, canonicalize_name(self.req.name)) + + def prepare_distribution_metadata( + self, + finder: "PackageFinder", + build_isolation: bool, + check_build_deps: bool, + ) -> None: + pass diff --git a/backend/.venv/Lib/site-packages/pip/_internal/exceptions.py b/backend/.venv/Lib/site-packages/pip/_internal/exceptions.py new file mode 100644 index 0000000..45a876a --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/exceptions.py @@ -0,0 +1,809 @@ +"""Exceptions used throughout package. + +This module MUST NOT try to import from anything within `pip._internal` to +operate. This is expected to be importable from any/all files within the +subpackage and, thus, should not depend on them. +""" + +import configparser +import contextlib +import locale +import logging +import pathlib +import re +import sys +from itertools import chain, groupby, repeat +from typing import TYPE_CHECKING, Dict, Iterator, List, Literal, Optional, Union + +from pip._vendor.packaging.requirements import InvalidRequirement +from pip._vendor.packaging.version import InvalidVersion +from pip._vendor.rich.console import Console, ConsoleOptions, RenderResult +from pip._vendor.rich.markup import escape +from pip._vendor.rich.text import Text + +if TYPE_CHECKING: + from hashlib import _Hash + + from pip._vendor.requests.models import Request, Response + + from pip._internal.metadata import BaseDistribution + from pip._internal.req.req_install import InstallRequirement + +logger = logging.getLogger(__name__) + + +# +# Scaffolding +# +def _is_kebab_case(s: str) -> bool: + return re.match(r"^[a-z]+(-[a-z]+)*$", s) is not None + + +def _prefix_with_indent( + s: Union[Text, str], + console: Console, + *, + prefix: str, + indent: str, +) -> Text: + if isinstance(s, Text): + text = s + else: + text = console.render_str(s) + + return console.render_str(prefix, overflow="ignore") + console.render_str( + f"\n{indent}", overflow="ignore" + ).join(text.split(allow_blank=True)) + + +class PipError(Exception): + """The base pip error.""" + + +class DiagnosticPipError(PipError): + """An error, that presents diagnostic information to the user. + + This contains a bunch of logic, to enable pretty presentation of our error + messages. Each error gets a unique reference. Each error can also include + additional context, a hint and/or a note -- which are presented with the + main error message in a consistent style. + + This is adapted from the error output styling in `sphinx-theme-builder`. + """ + + reference: str + + def __init__( + self, + *, + kind: 'Literal["error", "warning"]' = "error", + reference: Optional[str] = None, + message: Union[str, Text], + context: Optional[Union[str, Text]], + hint_stmt: Optional[Union[str, Text]], + note_stmt: Optional[Union[str, Text]] = None, + link: Optional[str] = None, + ) -> None: + # Ensure a proper reference is provided. + if reference is None: + assert hasattr(self, "reference"), "error reference not provided!" + reference = self.reference + assert _is_kebab_case(reference), "error reference must be kebab-case!" + + self.kind = kind + self.reference = reference + + self.message = message + self.context = context + + self.note_stmt = note_stmt + self.hint_stmt = hint_stmt + + self.link = link + + super().__init__(f"<{self.__class__.__name__}: {self.reference}>") + + def __repr__(self) -> str: + return ( + f"<{self.__class__.__name__}(" + f"reference={self.reference!r}, " + f"message={self.message!r}, " + f"context={self.context!r}, " + f"note_stmt={self.note_stmt!r}, " + f"hint_stmt={self.hint_stmt!r}" + ")>" + ) + + def __rich_console__( + self, + console: Console, + options: ConsoleOptions, + ) -> RenderResult: + colour = "red" if self.kind == "error" else "yellow" + + yield f"[{colour} bold]{self.kind}[/]: [bold]{self.reference}[/]" + yield "" + + if not options.ascii_only: + # Present the main message, with relevant context indented. + if self.context is not None: + yield _prefix_with_indent( + self.message, + console, + prefix=f"[{colour}]×[/] ", + indent=f"[{colour}]│[/] ", + ) + yield _prefix_with_indent( + self.context, + console, + prefix=f"[{colour}]╰─>[/] ", + indent=f"[{colour}] [/] ", + ) + else: + yield _prefix_with_indent( + self.message, + console, + prefix="[red]×[/] ", + indent=" ", + ) + else: + yield self.message + if self.context is not None: + yield "" + yield self.context + + if self.note_stmt is not None or self.hint_stmt is not None: + yield "" + + if self.note_stmt is not None: + yield _prefix_with_indent( + self.note_stmt, + console, + prefix="[magenta bold]note[/]: ", + indent=" ", + ) + if self.hint_stmt is not None: + yield _prefix_with_indent( + self.hint_stmt, + console, + prefix="[cyan bold]hint[/]: ", + indent=" ", + ) + + if self.link is not None: + yield "" + yield f"Link: {self.link}" + + +# +# Actual Errors +# +class ConfigurationError(PipError): + """General exception in configuration""" + + +class InstallationError(PipError): + """General exception during installation""" + + +class MissingPyProjectBuildRequires(DiagnosticPipError): + """Raised when pyproject.toml has `build-system`, but no `build-system.requires`.""" + + reference = "missing-pyproject-build-system-requires" + + def __init__(self, *, package: str) -> None: + super().__init__( + message=f"Can not process {escape(package)}", + context=Text( + "This package has an invalid pyproject.toml file.\n" + "The [build-system] table is missing the mandatory `requires` key." + ), + note_stmt="This is an issue with the package mentioned above, not pip.", + hint_stmt=Text("See PEP 518 for the detailed specification."), + ) + + +class InvalidPyProjectBuildRequires(DiagnosticPipError): + """Raised when pyproject.toml an invalid `build-system.requires`.""" + + reference = "invalid-pyproject-build-system-requires" + + def __init__(self, *, package: str, reason: str) -> None: + super().__init__( + message=f"Can not process {escape(package)}", + context=Text( + "This package has an invalid `build-system.requires` key in " + f"pyproject.toml.\n{reason}" + ), + note_stmt="This is an issue with the package mentioned above, not pip.", + hint_stmt=Text("See PEP 518 for the detailed specification."), + ) + + +class NoneMetadataError(PipError): + """Raised when accessing a Distribution's "METADATA" or "PKG-INFO". + + This signifies an inconsistency, when the Distribution claims to have + the metadata file (if not, raise ``FileNotFoundError`` instead), but is + not actually able to produce its content. This may be due to permission + errors. + """ + + def __init__( + self, + dist: "BaseDistribution", + metadata_name: str, + ) -> None: + """ + :param dist: A Distribution object. + :param metadata_name: The name of the metadata being accessed + (can be "METADATA" or "PKG-INFO"). + """ + self.dist = dist + self.metadata_name = metadata_name + + def __str__(self) -> str: + # Use `dist` in the error message because its stringification + # includes more information, like the version and location. + return f"None {self.metadata_name} metadata found for distribution: {self.dist}" + + +class UserInstallationInvalid(InstallationError): + """A --user install is requested on an environment without user site.""" + + def __str__(self) -> str: + return "User base directory is not specified" + + +class InvalidSchemeCombination(InstallationError): + def __str__(self) -> str: + before = ", ".join(str(a) for a in self.args[:-1]) + return f"Cannot set {before} and {self.args[-1]} together" + + +class DistributionNotFound(InstallationError): + """Raised when a distribution cannot be found to satisfy a requirement""" + + +class RequirementsFileParseError(InstallationError): + """Raised when a general error occurs parsing a requirements file line.""" + + +class BestVersionAlreadyInstalled(PipError): + """Raised when the most up-to-date version of a package is already + installed.""" + + +class BadCommand(PipError): + """Raised when virtualenv or a command is not found""" + + +class CommandError(PipError): + """Raised when there is an error in command-line arguments""" + + +class PreviousBuildDirError(PipError): + """Raised when there's a previous conflicting build directory""" + + +class NetworkConnectionError(PipError): + """HTTP connection error""" + + def __init__( + self, + error_msg: str, + response: Optional["Response"] = None, + request: Optional["Request"] = None, + ) -> None: + """ + Initialize NetworkConnectionError with `request` and `response` + objects. + """ + self.response = response + self.request = request + self.error_msg = error_msg + if ( + self.response is not None + and not self.request + and hasattr(response, "request") + ): + self.request = self.response.request + super().__init__(error_msg, response, request) + + def __str__(self) -> str: + return str(self.error_msg) + + +class InvalidWheelFilename(InstallationError): + """Invalid wheel filename.""" + + +class UnsupportedWheel(InstallationError): + """Unsupported wheel.""" + + +class InvalidWheel(InstallationError): + """Invalid (e.g. corrupt) wheel.""" + + def __init__(self, location: str, name: str): + self.location = location + self.name = name + + def __str__(self) -> str: + return f"Wheel '{self.name}' located at {self.location} is invalid." + + +class MetadataInconsistent(InstallationError): + """Built metadata contains inconsistent information. + + This is raised when the metadata contains values (e.g. name and version) + that do not match the information previously obtained from sdist filename, + user-supplied ``#egg=`` value, or an install requirement name. + """ + + def __init__( + self, ireq: "InstallRequirement", field: str, f_val: str, m_val: str + ) -> None: + self.ireq = ireq + self.field = field + self.f_val = f_val + self.m_val = m_val + + def __str__(self) -> str: + return ( + f"Requested {self.ireq} has inconsistent {self.field}: " + f"expected {self.f_val!r}, but metadata has {self.m_val!r}" + ) + + +class MetadataInvalid(InstallationError): + """Metadata is invalid.""" + + def __init__(self, ireq: "InstallRequirement", error: str) -> None: + self.ireq = ireq + self.error = error + + def __str__(self) -> str: + return f"Requested {self.ireq} has invalid metadata: {self.error}" + + +class InstallationSubprocessError(DiagnosticPipError, InstallationError): + """A subprocess call failed.""" + + reference = "subprocess-exited-with-error" + + def __init__( + self, + *, + command_description: str, + exit_code: int, + output_lines: Optional[List[str]], + ) -> None: + if output_lines is None: + output_prompt = Text("See above for output.") + else: + output_prompt = ( + Text.from_markup(f"[red][{len(output_lines)} lines of output][/]\n") + + Text("".join(output_lines)) + + Text.from_markup(R"[red]\[end of output][/]") + ) + + super().__init__( + message=( + f"[green]{escape(command_description)}[/] did not run successfully.\n" + f"exit code: {exit_code}" + ), + context=output_prompt, + hint_stmt=None, + note_stmt=( + "This error originates from a subprocess, and is likely not a " + "problem with pip." + ), + ) + + self.command_description = command_description + self.exit_code = exit_code + + def __str__(self) -> str: + return f"{self.command_description} exited with {self.exit_code}" + + +class MetadataGenerationFailed(InstallationSubprocessError, InstallationError): + reference = "metadata-generation-failed" + + def __init__( + self, + *, + package_details: str, + ) -> None: + super(InstallationSubprocessError, self).__init__( + message="Encountered error while generating package metadata.", + context=escape(package_details), + hint_stmt="See above for details.", + note_stmt="This is an issue with the package mentioned above, not pip.", + ) + + def __str__(self) -> str: + return "metadata generation failed" + + +class HashErrors(InstallationError): + """Multiple HashError instances rolled into one for reporting""" + + def __init__(self) -> None: + self.errors: List[HashError] = [] + + def append(self, error: "HashError") -> None: + self.errors.append(error) + + def __str__(self) -> str: + lines = [] + self.errors.sort(key=lambda e: e.order) + for cls, errors_of_cls in groupby(self.errors, lambda e: e.__class__): + lines.append(cls.head) + lines.extend(e.body() for e in errors_of_cls) + if lines: + return "\n".join(lines) + return "" + + def __bool__(self) -> bool: + return bool(self.errors) + + +class HashError(InstallationError): + """ + A failure to verify a package against known-good hashes + + :cvar order: An int sorting hash exception classes by difficulty of + recovery (lower being harder), so the user doesn't bother fretting + about unpinned packages when he has deeper issues, like VCS + dependencies, to deal with. Also keeps error reports in a + deterministic order. + :cvar head: A section heading for display above potentially many + exceptions of this kind + :ivar req: The InstallRequirement that triggered this error. This is + pasted on after the exception is instantiated, because it's not + typically available earlier. + + """ + + req: Optional["InstallRequirement"] = None + head = "" + order: int = -1 + + def body(self) -> str: + """Return a summary of me for display under the heading. + + This default implementation simply prints a description of the + triggering requirement. + + :param req: The InstallRequirement that provoked this error, with + its link already populated by the resolver's _populate_link(). + + """ + return f" {self._requirement_name()}" + + def __str__(self) -> str: + return f"{self.head}\n{self.body()}" + + def _requirement_name(self) -> str: + """Return a description of the requirement that triggered me. + + This default implementation returns long description of the req, with + line numbers + + """ + return str(self.req) if self.req else "unknown package" + + +class VcsHashUnsupported(HashError): + """A hash was provided for a version-control-system-based requirement, but + we don't have a method for hashing those.""" + + order = 0 + head = ( + "Can't verify hashes for these requirements because we don't " + "have a way to hash version control repositories:" + ) + + +class DirectoryUrlHashUnsupported(HashError): + """A hash was provided for a version-control-system-based requirement, but + we don't have a method for hashing those.""" + + order = 1 + head = ( + "Can't verify hashes for these file:// requirements because they " + "point to directories:" + ) + + +class HashMissing(HashError): + """A hash was needed for a requirement but is absent.""" + + order = 2 + head = ( + "Hashes are required in --require-hashes mode, but they are " + "missing from some requirements. Here is a list of those " + "requirements along with the hashes their downloaded archives " + "actually had. Add lines like these to your requirements files to " + "prevent tampering. (If you did not enable --require-hashes " + "manually, note that it turns on automatically when any package " + "has a hash.)" + ) + + def __init__(self, gotten_hash: str) -> None: + """ + :param gotten_hash: The hash of the (possibly malicious) archive we + just downloaded + """ + self.gotten_hash = gotten_hash + + def body(self) -> str: + # Dodge circular import. + from pip._internal.utils.hashes import FAVORITE_HASH + + package = None + if self.req: + # In the case of URL-based requirements, display the original URL + # seen in the requirements file rather than the package name, + # so the output can be directly copied into the requirements file. + package = ( + self.req.original_link + if self.req.is_direct + # In case someone feeds something downright stupid + # to InstallRequirement's constructor. + else getattr(self.req, "req", None) + ) + return " {} --hash={}:{}".format( + package or "unknown package", FAVORITE_HASH, self.gotten_hash + ) + + +class HashUnpinned(HashError): + """A requirement had a hash specified but was not pinned to a specific + version.""" + + order = 3 + head = ( + "In --require-hashes mode, all requirements must have their " + "versions pinned with ==. These do not:" + ) + + +class HashMismatch(HashError): + """ + Distribution file hash values don't match. + + :ivar package_name: The name of the package that triggered the hash + mismatch. Feel free to write to this after the exception is raise to + improve its error message. + + """ + + order = 4 + head = ( + "THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS " + "FILE. If you have updated the package versions, please update " + "the hashes. Otherwise, examine the package contents carefully; " + "someone may have tampered with them." + ) + + def __init__(self, allowed: Dict[str, List[str]], gots: Dict[str, "_Hash"]) -> None: + """ + :param allowed: A dict of algorithm names pointing to lists of allowed + hex digests + :param gots: A dict of algorithm names pointing to hashes we + actually got from the files under suspicion + """ + self.allowed = allowed + self.gots = gots + + def body(self) -> str: + return f" {self._requirement_name()}:\n{self._hash_comparison()}" + + def _hash_comparison(self) -> str: + """ + Return a comparison of actual and expected hash values. + + Example:: + + Expected sha256 abcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcde + or 123451234512345123451234512345123451234512345 + Got bcdefbcdefbcdefbcdefbcdefbcdefbcdefbcdefbcdef + + """ + + def hash_then_or(hash_name: str) -> "chain[str]": + # For now, all the decent hashes have 6-char names, so we can get + # away with hard-coding space literals. + return chain([hash_name], repeat(" or")) + + lines: List[str] = [] + for hash_name, expecteds in self.allowed.items(): + prefix = hash_then_or(hash_name) + lines.extend((f" Expected {next(prefix)} {e}") for e in expecteds) + lines.append( + f" Got {self.gots[hash_name].hexdigest()}\n" + ) + return "\n".join(lines) + + +class UnsupportedPythonVersion(InstallationError): + """Unsupported python version according to Requires-Python package + metadata.""" + + +class ConfigurationFileCouldNotBeLoaded(ConfigurationError): + """When there are errors while loading a configuration file""" + + def __init__( + self, + reason: str = "could not be loaded", + fname: Optional[str] = None, + error: Optional[configparser.Error] = None, + ) -> None: + super().__init__(error) + self.reason = reason + self.fname = fname + self.error = error + + def __str__(self) -> str: + if self.fname is not None: + message_part = f" in {self.fname}." + else: + assert self.error is not None + message_part = f".\n{self.error}\n" + return f"Configuration file {self.reason}{message_part}" + + +_DEFAULT_EXTERNALLY_MANAGED_ERROR = f"""\ +The Python environment under {sys.prefix} is managed externally, and may not be +manipulated by the user. Please use specific tooling from the distributor of +the Python installation to interact with this environment instead. +""" + + +class ExternallyManagedEnvironment(DiagnosticPipError): + """The current environment is externally managed. + + This is raised when the current environment is externally managed, as + defined by `PEP 668`_. The ``EXTERNALLY-MANAGED`` configuration is checked + and displayed when the error is bubbled up to the user. + + :param error: The error message read from ``EXTERNALLY-MANAGED``. + """ + + reference = "externally-managed-environment" + + def __init__(self, error: Optional[str]) -> None: + if error is None: + context = Text(_DEFAULT_EXTERNALLY_MANAGED_ERROR) + else: + context = Text(error) + super().__init__( + message="This environment is externally managed", + context=context, + note_stmt=( + "If you believe this is a mistake, please contact your " + "Python installation or OS distribution provider. " + "You can override this, at the risk of breaking your Python " + "installation or OS, by passing --break-system-packages." + ), + hint_stmt=Text("See PEP 668 for the detailed specification."), + ) + + @staticmethod + def _iter_externally_managed_error_keys() -> Iterator[str]: + # LC_MESSAGES is in POSIX, but not the C standard. The most common + # platform that does not implement this category is Windows, where + # using other categories for console message localization is equally + # unreliable, so we fall back to the locale-less vendor message. This + # can always be re-evaluated when a vendor proposes a new alternative. + try: + category = locale.LC_MESSAGES + except AttributeError: + lang: Optional[str] = None + else: + lang, _ = locale.getlocale(category) + if lang is not None: + yield f"Error-{lang}" + for sep in ("-", "_"): + before, found, _ = lang.partition(sep) + if not found: + continue + yield f"Error-{before}" + yield "Error" + + @classmethod + def from_config( + cls, + config: Union[pathlib.Path, str], + ) -> "ExternallyManagedEnvironment": + parser = configparser.ConfigParser(interpolation=None) + try: + parser.read(config, encoding="utf-8") + section = parser["externally-managed"] + for key in cls._iter_externally_managed_error_keys(): + with contextlib.suppress(KeyError): + return cls(section[key]) + except KeyError: + pass + except (OSError, UnicodeDecodeError, configparser.ParsingError): + from pip._internal.utils._log import VERBOSE + + exc_info = logger.isEnabledFor(VERBOSE) + logger.warning("Failed to read %s", config, exc_info=exc_info) + return cls(None) + + +class UninstallMissingRecord(DiagnosticPipError): + reference = "uninstall-no-record-file" + + def __init__(self, *, distribution: "BaseDistribution") -> None: + installer = distribution.installer + if not installer or installer == "pip": + dep = f"{distribution.raw_name}=={distribution.version}" + hint = Text.assemble( + "You might be able to recover from this via: ", + (f"pip install --force-reinstall --no-deps {dep}", "green"), + ) + else: + hint = Text( + f"The package was installed by {installer}. " + "You should check if it can uninstall the package." + ) + + super().__init__( + message=Text(f"Cannot uninstall {distribution}"), + context=( + "The package's contents are unknown: " + f"no RECORD file was found for {distribution.raw_name}." + ), + hint_stmt=hint, + ) + + +class LegacyDistutilsInstall(DiagnosticPipError): + reference = "uninstall-distutils-installed-package" + + def __init__(self, *, distribution: "BaseDistribution") -> None: + super().__init__( + message=Text(f"Cannot uninstall {distribution}"), + context=( + "It is a distutils installed project and thus we cannot accurately " + "determine which files belong to it which would lead to only a partial " + "uninstall." + ), + hint_stmt=None, + ) + + +class InvalidInstalledPackage(DiagnosticPipError): + reference = "invalid-installed-package" + + def __init__( + self, + *, + dist: "BaseDistribution", + invalid_exc: Union[InvalidRequirement, InvalidVersion], + ) -> None: + installed_location = dist.installed_location + + if isinstance(invalid_exc, InvalidRequirement): + invalid_type = "requirement" + else: + invalid_type = "version" + + super().__init__( + message=Text( + f"Cannot process installed package {dist} " + + (f"in {installed_location!r} " if installed_location else "") + + f"because it has an invalid {invalid_type}:\n{invalid_exc.args[0]}" + ), + context=( + "Starting with pip 24.1, packages with invalid " + f"{invalid_type}s can not be processed." + ), + hint_stmt="To proceed this package must be uninstalled.", + ) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/index/__init__.py b/backend/.venv/Lib/site-packages/pip/_internal/index/__init__.py new file mode 100644 index 0000000..7a17b7b --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/index/__init__.py @@ -0,0 +1,2 @@ +"""Index interaction code +""" diff --git a/backend/.venv/Lib/site-packages/pip/_internal/index/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/index/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e7bd8e11c48d8c65259ad8dba9850a91be5a59cf GIT binary patch literal 234 zcmXw!y^2CH5QP(0ToJ6d6I+Yx?Zw^3N?3gW4TP8sGG2FbN#gH|_zXUaZ(!>Sh;~++ zh@NK789011r)IOkqDIqiY{hv=;Vu3$_j)u3X4r)7c&D=e8j^u+8!3QOI-sStwgwvG z4nKcNX{?s=$nL5AP=lV>SXcN`X%MssK2uuT6$PYurmX`pQ@Q{$qPqrKi(i}xj{&k+ zDAXLhD6!1t6Gm#8V`AqrE-*;hEqCX7|IeD$5`J7Q64TK>{dE1{oZl*(S6wy6f5-4c A9smFU literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/index/__pycache__/collector.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/index/__pycache__/collector.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a50162bd1489bec86a45cde64940e2c3314980d4 GIT binary patch literal 21619 zcmd6Pd2k!onP)f902&7g-nYb-D2W6`LZ@w+mSoGME?c5yOLoSH69_^#MNl}HZcs8g zq(eKJF&QUgDwpV;WX$Z$X5_M_BJXA@%4{m7OeRO|{6m;@h_vO6rY2jnvs<+VnRGeM zZf))Fd)+gQw!#`G3csN`qKYbuJ`yj{tGd)Js&#`b0yhA<-CWOf-d>63wCJL`$e8(Hd$^ zw1wId8$ugc8&`Z|qCM2k@?u;{Yzl2+d3Stsq9fFi*b>^po;~rciEW{6EbonXCb~jh zEbog465XM0mam9!PxOR(SiUmen+S%2Ebou+NbC&lWcjN2uEg%pZkDf(?@8Ohz56R8SCb?d=p;ilO9b&awQLC+}*2ApF z4N4EI>6AC3W`E(GvT4XEx8vP_EGY*{M&5+ChgqMS(Pzi&Hgnt~?A;c;+p4tWXLD5E zrW{54qnJ%6S{_r5$z5^)Z|apUb1mJMh1ZQvxX^LHrb6C+y~lzC>$MlX2CR|tbsu46 zL6q%K{P__db#wB5d8g7P?@~4Zh7TGrly?JqwelVslm6JcMS1UKN9Y7v9AHqpM>&a^ zJ%Y90i}!=97X~AxSq`w-I_3MYipSW<`!MqTN>hI1Q|xUY-acT>HT3wnEpTw+G0&M{ zMM^|sNojOU9ZhM9lp2!K!!b=tq~x)_jYip+6OmE75dH4MvSzSWAtm zQAO(t1U>&s;2I3@x?7H*DdWq8iU9Vp>|SJUN!8$CHuK(OB}l?iq|E6#2~9C|Zb*jizI%WF)SOr_@wB zg~{mRY2|ZcN;0bG4x^Ie$t3DvOi`s0Elsl#pHQ^XR8ms{Hr?}tl2*qLt7=L`>(eJ# z4s{v^mGq^Qip3_ASS&iRN(6!dYIsj85j8q|I+_|)@aQ=e8$GRPnlW6J8i{F2cqpZY zwR9vsM#K7JT9{hIE}|e7S6<`wI#rP)(R4U6mL3idsi{PGOpT+e{bE%6S0cE8U9ahn zB;^>Osc1(~<5c9lqI+l#ry10B-?_0^TsFUfZbt{YQ&rMqYBFk)EPWErfj=U|)o&oV z%B7JS*N90b)-&A)xX;|naZ~&xH$v^!T^5>;xYiZmagw*lL*u{HG0CMZ23=Ibket8B zp~l`xK5FB+)11Ho9qkk6Poz>8B!EqNs{gd4MTeDyqDer`G_dr^Cr$)C9tjsd8rBEI zWVo9~HMyukkA(JvsU&chP+3uxPEAUtfaRzeWF1V{w)YJN9O?#4S$CP^=#F^mlA`J! zd@?nyU5cfLb$eV%25jnPs^>K85x^wrcjx;1o*@*`Mk7(>ndC@X>y1RCsj*}lsM;G% zsme3wBGC&UI^rFE9d`9h=(b(vYa4ZR=2OjT;C1vH=9VStM zyhg|M>M)yh82Au2Mpw6E^gZ~~9zrtBt$DcGhO67ZwtdE#^;W)o|LpxQJ+R{4l<{s_ z*!Gq;a4q`1jvGV&VS6Tc@Ya?$gGaKp&0jp3b8xjAb571zwTeEtC?(eAG&8F`$h-(l zQ8;KNvMd0~=F7$}sd{WWLT9JlmmrxAkucAC2_R?NCGV$*!v!sN2JH`~@VBP@%}?EaS6tP)TG zC`=~_P8JU9o^aUUv&j3x;m?gl;%13mORH>Py~3PUREfvK;n#Q-vV^en|5})CA?2hcPU|0VU3748vL+?VdOu@kI?B=4y*w8_18!q z;Dr*>pRA7r7Q%lV3z@P_+RCvJ*>15Bl^++1nF!{=w86r7lpFDtKGTymhZp#OW8wxQ z`~G1idVz5b6GeN^05hdwB_b;-6LU#zOjTG73n&sHG328rMWoZQ1Vj((3TO^CWWdeh zO2qRu>1-*UoHe-+>jzXJ5iyWdO{UW5@?s<&ldZB|Dl<6L?|j8m)Ll;|FCCS|aU(O6JpvkYF`wVf*c?vpBwXsP62z@@tkFlf5{ zJY?cFKv3IE+8-(@3VdTqRf6wo==XsqI*)?ab76UaP$6UaEa~`ox|3O)K@CnflJ9`oQ#H z)>Xgak}@tSXA|6>HM>)EqN&^e8xIlOvn!qVWjgO$={%U}JhJO0=bGLF5xE#?;au!iMgTAJ0Q}!ug$}#1f1aH2`tDbaT9$OOn z1tPz^1jexDHOa}g>voGkrd(-nzQkpX!E@<~a&N~4kkfmN22Mk^0fmnpJ~SYi_(4Qu z%IY2oii>1?{Ewt416O|^ilPsbrzNNYc@nx9i7_3LsSTyGAx(hw{eMA|j9v|zgjs`+ zD-5U8qq>7q?F{L4&|y=T!cgU6DpW;{XvqmREFL?jJ4Q+A)kQpNpwu)&8}tB%qmmlL zC?Oy+{X%_|UIb_eXHrSWQ&C+QjX(!+Kyy{cb#X|IoKKKk6^J)!B5H!l*kzDfT`{Ry z{7Zcr^}_hmo^W77#omlBPl<7Hit7EC>NJa=uADKBaH!#0-p(*RCSghZc zac#R@+3?cHqS$oDTl4b%+5PkOYiDNmFL`%Q58M{&=FTh&Ex!>O=F)EoZ3dkcBRfrw zA^Qv{4#;lN9hauJ>?)x12+5jtmxYFEMFFiRA@Z;D7TN+qX%u#iy zDYOP@_zShI97w}HQf)mI?&mpK__ulGR(8nFZ`!WAtlp+<=~}BUR1|Zym|=a{w;w-m zvD~~NCmXE33iom=klnJ!nwMn(LRqpwMe|0U#z#67g|P;4mNey=M6%367m3tf>FD7z z2KgG6L<#wt((Vk|h+zC03^mO#8dXJ+fbeOp&rs8M1*PLm11Hs8ibJ*6ByCI^jYVUr zF)cnW#bXx~nulo?^+;L~M;VH#8l+{45iqbET7Eg@ET4o4Y-X-nv!jW@29GMt<^{Nu5?BOT zAJP!mA9NPY=x4}Q|2#}+f6ecwV`&oUMMyfxe7?zO)8ZKDCANL{?y~ zzy;F08N1Y-@znYAup1n*a&GLr+D7&Ish%*BiX{uIn~j8}ZKev0fBzA3r3z4882VJ$ z5Ok0dhRUc$Q15e8_c{`A)5`^TFLWKgKyB7-5%j8Ah+b2%_z(J$%cAb{b>MdCr@&{U!+#wB7&B15KBlj{L) z7Slq|f(&~mEW4Je>$)pCOhP^le}e8%;7W_@E_f|8V5#mpX=dDn1K^F3gxZH?0A&b* zI-gLZxR)YK3qu%dI)-1!)XmixYTuw1glyB?Ke;OB4laBuQ`>XfSN-zI*^?{2O&Q;& zC11x3pKa?{7|gWonc-)G8Q7pTwO6-a**+gzs_B|>{mNT&yS8EO(pUE{`r5NzzahcV zXa2He@+uk21x;CY$#(b|;RI0NQCA%Bo;vUhZ@S_dvdK>5MYwWAy^awjdGE+&MYIXk z#WeeE`B6ByoK3_bI|GQrm$Nf9+anw)voP`Vn#4G#?nV>vfto1Me>e`O7{OR0S0PlV z^U7;B^&V7FlSnig$TUg}gMLG~8RpG;($cjiB-32hU%TSp_NIT^qPT6*zb#wWG$VZ3 z%|NC*7!NE_^vQ+7Na2gf6ze{dd^zpMlGV@hYA@t8S56xmvD`A~(YgRB>l<0Ga4%Q$ zLKg=Yn*l9B_rw4oxVXqoDv-g+z{6M=JY5W4qv)s@Ub-_JRz4RFPqcmn$f)oZHR?qI zH;BJ^e(PV=Ey#b_vgGf1(|_tl-S?Z{X#W0&H#Xeb`t$A|cmF*2<6vgjsYSSM$t6;r zlRSiy67X?lEu}I*uoN(B(RQfZ5pB4zP)I6TD08Bib}D=_R0oUvD7-L=e?sj@t)peu z&JA2We&zVplUGhI`8O|$o7r*#0vk#99Vd@o3F-&j>nuyd#p6t!8-eYh3+Ga)xJnFD zx5F=}K8u|C2qgq2!`pL#a+Lf>{Apw_T;^77Hb-+#I{&Y){kd*(D3bjte!&`rDTq?&(0zJ}LGEUYBIT4DUd*n|Q{6$uKGNstrJ?>YeF65d0UK!~wQ zLYn!Y^Ww(F%|iT?`^*-%vF;YvvFSn_#t|bBaMsJ{QhgqYf%Vgd&F;FSLL*kxiEc8y zfb5u{3}-bMN7%GLg8ShMz>*FI&AM+=CxkA)o#uYyuf6i{+;c09-I>PjrMm6lw~Jzr zfyE^DRHDrCYdnjRuLFt8yLQ!Ttk_moV3{yE&802Q0Vz(qbcKPTBuugY|GhrNAI$C+cSlPMwjwGX&$B7sm8h z`NG}8Dz<5m_e~bcW!w3@(;qvSkc?CIbl$}?QdOvF6# z1rzJe6v#3wnsQ;Rwh#AU%w^IwC8B)ehsy!SO@O1j2#(T+YfZW*U6bNu_v6Q zXH6nOBpIrc>HlC(2Hio{yf!%D7)uZJ?jzSev3uHF*Tr)YY|JAUs5W-~wqZGJqXV`* zc0yP(BJpURn!z|D5(sS;C`^-6N<&=lBOu*qndY`QR{D6;O963m%-;=5DS*i~fZLBPAIIZT+j#Zhm4gdgt_j~2UlW&Vcg+mIN}8F> zRyAd78eV!N=jQ6W!EvxTQ_(s<@anNwjxAMeoj!s}FHg-*z3J~Lw5Vyi8vI&t#)&zu z_@#_rT4=b@aZ6nGAIB`c{+az*UtPAc<|WTvH&?sq1C2P^3j^B*x_I){I|2L&d?vii zUv@LM8bYR^{XPlLLkPOB;xIf9iW52ee$-K1ij&9|&jNd<5(njEXGm1scyh5PQE@`y zazktOjC%rJCW<3p0(W>q8HGB;u$aOWET@pv1^gyVg&Guzr{F+i&R9bJLhM5yK5!(F z_g3^VP07MMa(fzB$6lXj8l9y^FuF6Fg8+<{CFfS|#9XWw_1m|l>cL}n|M$tw7vV{NY3wTu;ZUP^Z4L&A#nuZW$VuqVw z-v#eLfFMFa5lz#S#Uc_(8o?>BafFcj<7(ww3I=(yAQmrdA&>eEbTcu;(2EGc;O(Fb zm_ip6Wz?`tjJ*jGCDO4c4j+MRqK#0}_Gu>sR;($lST~l$>Xahsv>H1%hVNnG9z%r= zj5t_gHxrK0-|8tO>q21==JI8z-Nm-$`cN1dN?Rcm<~%*+ZO?Hi--E;otH2g6Dr!1R z?n_k}(hv@{2g5OkL_yf7{|4`%{IJNTS=*k@LEP0H&2h36aIYK=bdBA$Ot7lY2|; z0tw>H`fIuk@2UQ}tFTEoWuLS^FOnumo214y4p#+voLSFX(L)}5Rt-4X^1JPYcjf%f z78BsnCj&m5Jir^Bj{x9IH4w=+Jd97kV68jJ9!$zm2M`hoR}zE#bqu2Z4H9^==ws1@ zh=jewQ%LsZID)$h=B80XweIc5!#g<&w#zoi^aKz)D`(gBLYw1~4X_JY81 zPSf!8+soWtm~CRt<8buN_vbj=76#sSEwLDQAk(owv++QVL&>eKU+npD@B5Tx z3uCiT{{l0hSkVZny#mGc1Z=_5n7ll-(OU53Y|~X~Xhc5D9A19brDc z<;2#0CfaEqb%?g+*skzatq;3$Qm>?4h_N7FcuGEt{#Bwz@Ew|@`U6V-4vEQkOtf!= z$ClxJ(FPlBhpInBRru05tsNOCy&g{VO;6s2COJ7fIV1c^5EtD$Z)~~ge9MdxVluFV z1rv2MKJ#bD{QjaIfdB+Ec7bn@_POrD+hW=G4#i_mYB#kbQ|K@sLSHDn5?H(rI4&eoaqIn)a|7H2-WT*C>}-z4hqmk_qDE- z?!HWS-;)1<>0`IOjajkE*eT3s<~L@AFUjq8P-<8mM_~=Gp z7J{?zZxTCXOpwf^^Dc;TPKS|tYs|vEXdYyOuDi-Q4?g4)P){Isq>S@G&ezl&AX(=` z1%u(oubcv=*Ij5^90!v}`4J+%b(bs_2k^SN^d_qU!gu-W?!4p0mF~!wxIh$Jtf#{L zdOphKG<;U+ZC1$^PHjfyO<^9yrPp1u7vI|?L!NsY3@S}33cJw$-YM}D+WWxZ#1WEb z>n^;dt(tY$>%eZhXe^nV5}y;t&HE)j9W=@~4kI^UJ5O2Xbm7G*cpaD@8#euoB{KZC6BaFo$+)`_pdp*nvR7%OVypzkNnD2eOs)2xpKBL z>-$vJ*8nR6p+{~H6u7E7RFt;8I{C`vO8eeS``#O;m)h^o2yF;lJv5V^dwias--XcC zxrR4gjo*Cu)uXQ*ef8ukC$De&Zt%6>O84PR_u*UeQum|FZ6`>6P%6n$)G$RB=E!Owl>|Yii$_X1CPx9o2>A%sq z?1#y^*2lqbx%cM4%Kp=t{im1xXBNdXzg@eZ^VPizRo-JR341mbyYBd^-eW7;hhVC; z9h|S_T}~{jVyigBV}2FYnAVD~E#qs;XWp-H0TLV~J!t$t*EVpz&F{jkvi-K$z91|_ zSH$i`u{+no3Y$4!Lz%(`R#?xbW_LWqXRD9m;E-7PwT`*ySGzJ|3p}f=x1sOd`~3&r zcwj|*Fe5&QD0>>P0?k&u9T{&2_53i;YA$y5-Q06?>*BVDR>VV#;vsx1s_SNTTQlBP zs=LSN^a5hpusUB=&W(4!V_YqI~MX*1>b^GKt>z5GR5JY8&0x7fc+ zkqwH2R7d(#5W++f=|gXA^mg2i^FmeT(MLr#&faOdX9!4dINK3d!!~WnM~M*d^_C;- zUDHaGD0hvLM<^j}fl-nACgmu3p2&uX@=rMU)90HOx--qanX2HD5G;9yo7`wljY`&R zDRHZFC@HL&Jlcj+jeOU#1II}zU<=MP95k(BB`!sj;loBLHzdM2=CF44LLSA7pf8_N zLC}I<+f#Hnwo>*gew0=z)vQ#IedxDFuE3GmN*rz#lsb&%$GdvOk5uawv~6NSGo?=a zE%TE-VZ=tpz_*#3);tMEtedJ^8$D*=0eozXx1UGws|*QkoPyDeuvJ(y)Xa*JHH8-2 zGfHA>h8)^#NRn6V$QPW`>=3MRx`pC)$?I;;pm4xdGRjTw9WhVcr?GROIG%@tplSzR zm736`NDvCHN=V3rE_O71L`0jqg1Ri8)bhMBK22{+>^38gt)T>%dB@wI5f+hXUJ7abv;9=1Lji#CkP}YwSX3;bh7%0;8tFisnT|8cvh5C5*7wrOA1m%`0cwPM{k0 z18wDeXzI>MyA~``C(Eho@WYi2@3&v(CWQgc!cR+KEvRFy6|~{JLN%xl_)f(0_i?iCs|oVmcIocI~TH4>QS4vKj^sE_GOrvZ1I z-=aMV(kO9b0ooSM8n{;6c>TBPlRjnczMyUFd=e*5nXc2@n@sgGrX(33IzJ8S4LdeT z7QdfX#}Mvg>PJO~noW8ujE}7e>YS>wUKQrL(fOW|JrY73@*}VAMq-5!d(`BC_?(n=v* zCSUP8L<)`QgYAJXHXZ-L$PI0|x%XOhrFr)cMm}IZ#24xtd63%@s;SFJbkQOPxTNy* z7x3urJfqjEa1>9Cn0^!D{OTQQ{#ibl7wfyO-M6y6 zKZF1E{WG4dw`RrL`lh!vv*n)Kz8dDVsoIvUs=X>+5i&TL(4ws|Z1 zY4OZZPgNVOpqmm5!mJIBNeb^r`h-j(LzVnh*k>cq89=;*T+u!odpXfm3ax?=zex}y zO&UQ%)&}#6e|yHieNo)bWUVe*qNc=MNLbIf{7z&_+=U+zG*&pr1QubNIGCqRc4~p* z>d1#}*m;n1bOMzK&pbMA?6Vd~)36e4OzAe{h8fBGFSPt(>ZxR|*ZetziMDm1AjfRJ z^oIlvvNPcQ!{^$(&~;;zDldAMKS^FVt#=wL=kYh?xCAadSi*cr17YH87@4oz z^8ySeaj5{Cwap6U(4(B5Bg5G@YX`}jPRXKZG8>DEvLAWPq5gM_s8MW#)R!HsiuI~eBes#q zjw?&j^z^i0bNm_w6FW zisb(d#FhwR{pc+&s`JyZEHS;NAhYxDcn!gOIGCwvw5xRX>{(KC4F{Ef9ZpYd_*j(x zd-_`UAo(2xpO4$nwbHf+C#l{eJV)3|Q`<^oSEjLRrSVXv@zAZF<;KTWYf-eyc{X_7 zuj9Pcv)f+k%GGo3mbC_)#9P_0H?v_cTHj-|zWVvEd>#$%p#~dE8?>%9aX#o{8#CUG z-@Nqd)GJfV-d=dVS~^~Bf2AF}x{C(}mzy73bqMv9|J3~0+@Wl3-Q0nN$N&1NZ$GuT z^*;J#m-@NKuRe9I4L)b* ztM}yW_WDXFb=3`bUH1BhnZpqG6}6-a&ey%#{7Un}Jxk4jWncGi{Oz|JTNm4cON~2N zrgy0^2!*Z+jw!p_^TE4~7>LE({r$l$1N(&le(s$^QH$Bq4V@^KotM_XdX&igp!{*@94G{cFaI`RG1yI4r?X3F=U z(ii>-o@fW&fgN~kx3}M^Zp}Gx2Ot_Z=UkK%IZx%Pn{rj0vl_mwj;_1zcE?6m6?asv zY09}MCvt64j>=HW)BLU%xm5&TSLbZ>?qQyDR#Mn@&-}nb?JLL0E7n8h#><>jfJ1E| zP22Sk^Ei#tmf3k^l|AHqJr2*EhUT0DcZ}D*E9asdrq;6NM$Yg7v89pC6+oop6Go)M z2YA#g*qOwjc_dMl2?SrH1iMk3`W4FkZ%TfOgn6g&!v#U+z-CTuy%Kf}y)q3_-JAbq zFGW*HlheJln_)IliJ9vn3{Im9`j)yA$IQSGR1$wG5vM9rLb6u%P~xS8v>+9mkete# zWh}0OjB?$J-$@FFaX3XzsVehp*A>07CZ?%1RJpxeQLu1!y5KF>n^;xr_m_(6kj|?& zmlor9dX%^p1c$j`!~<_CTVCQ0A_Uhrl-4tyQbE%Rz$ig)EnjCW9fO5PF17W&u#zCf z3eyojjU8oPzaXPdB8Hz^YNIZyO9z3&-}(V8;|JUf;*n65X%{*jT0OxILK`GZyx!Pi z@SDCm4^@@+~O34eofKcs|_ z|BooQNC}e;4827xx>#pL9^g&nXf{bK3ndEWp)x{;ti&3#%f>*S^iwz0Fmz z|K7K`%C|Z9+Z1amC$|aktFxTXJuicHXIx7HSuw3r(4t?rDF{De_hG zdvY9Z3;VA1fBV2HW!D-6J}~$68i!l1vX*~{Uuep4biXFAvin*O&%0;F5j)AdbE2Q$ zFdxlvxLtdM-EQt(rKjAM{pcPgxKRmiH}|d5E%zLcajyB<$TyGOI{kx_Y~=SF+*&kyi(O*F&+pA)P3)`jjIhue*oRl4CQxve#4Yvya`aJB@uYfU${yteUO%7T5F zWq0>+Ht*b)Wxnx!TQwh~4uVvQQz^);bv5&KbD=e~smmSYw(q#>a$%L&63W>rbH`Ub z*D*If7sS!!oP*wg&3S9*_RSy9)NadoI&-W(IG)q9>SpB)+}?e6?H=BVz|$PN_v~c% zJC5pA2j1se`T&$OIS#jL6YO?#_||iogHNr}tF;N<#_yP$SmSVe-!shfo_9G)8EX9> Dp<0=J literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b9e8b98022eca5dc91d4930fc91e56c69160cce4 GIT binary patch literal 40650 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 G`2PdX$T#2s literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/index/__pycache__/sources.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/index/__pycache__/sources.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..31d1c918b88378f6806ad0ec1de6f554cf554295 GIT binary patch literal 12526 zcmc&)Yiu0Xb-uGZ`(ExYA4`f9A4BmWtxT@uS7cFgY?+i|DKhO^veRs2uU0!lX{mj% zGegPTPyubY3Dvqag8~)}6foUCv0xW*A3&7=&C3NEphdxrm~bL>SjQt1QltZ&6Y<^E*>;{vW zETmb?yb3Xa-`ip~Ty1H4MvRF9J+r4B8E4Fyam8F2cg&sf#5@^q%$xDWeEhkX_Gg-6 zO_@L}kO{_unNTd0X^u7XXO47BrZv{eWoNoA6OM(s>`J$1I$|A}U9nyK-kt8ubj7*^ zW@8GQ{!F>U)vMC|Hu_8<)}y$U)=rXoA%(frr#O}HMWOs;%EnVAE4AOc-(zE+W3uOE zCVStu@yb|iK=vtvvR~<+66L0s#n=$f6F{C|CC@NV3n8sp8F<@nmE6lyTaemXle&+m zwjniKlN#Zv?MUsYN!>5+Lff5+BzGx$Kuk?~hOMDuXl%TnFfCj$tYw_oA2g z%n6ac|DujeMg+qrD^rQtv@WNTdc zB5gR%&d#Kjh{I?*nZ1%or{ps-GMq@Im24uTR8qfiNm0_3)aGO&o6Dw>$e&l@X2zL> zswr`eO2?-v#m&^KRJxLi?uJihHJ!Rhy%Pz6+946r?QtLHp4fQ&@aXHTzpnd z8$LuNQyTI(QyL{FY3$`7TEga|5N==v(OQn#6uT@aqT(=TPqw`*zHMcUIq}3bWs~ig zOE+W>WD&A=&VdQ^Qa{e*X4Rx(I8{ZTRkKNJ_3;X5?a(UNY)5p1>6K^Y`d<T{}_iiRknmuLh}(1cfCfGSa{ zm#6aKr~^p2X|~3vR}CY9M>N^mAw(~;qNAx~vpEKrE-mX{&;F7@+_W=ifG3vRxLxVn zq*N|1pV}gskAT-?xcLCFk5$@2+vc7&Gv8cCA=GZJX-j1zxf139Vei<=idweQR+q)g z`xraJB96%uq%bsHg%(t)bl#&YFX#s@>6tXtj3<-IDEi!tq8Z+cvx=t0=_Vqm_aJNS z0&9vx=};lA#ngj%%(L`CSYR8zwsl`$!PmFqemA`4J9JAZ_{MHsF8EHaiYLvrg?yFZ zw4}{x2vubz3o*NFQ$*P=i+~~rl#xUB$WC0Hic7Ww+C)o{xoQ-dhd=W|%~hUTx!g6m zd~;&NYqZ5rK<7^I6`51#&gPy`(^`Jd8SI?$LPaumpe!X5$xDhRsfq?z(F~E4FMm~& z$=bI-?}@*wXZcv>g?SdYhR4`NhP#St)E(sqdU*y|8PbuD-Z~F5)ltbi$09boMW^B5 z`rioQvTd)c)I4b|;95A2RX>gGX6_FYKQyByu3>~(MUI=B5o3(l)ZHkj-j7J50ZEdn zO0c(5*_0lS=X)AWRd zRe=0lS&oQ#wSM2^vPp$+o|)XtEH)bU&xM?R3COl>#d;+x&^~LlV5Nl4DT4-8F6mHF zl@eTsot=yX4O>n#T(qpQq}2z}WtCn5U(Z}UsYIa-XJTdsTtKC%GDLy~mEOEcNUoBZ zpgu&=VMGy;?+C*I?xD^ZcBp0}RPG%qYbveLDx}_9xXU+IbywvF8}AwFXEhf!sr?WU zxP+Uv@46BDdTd4fhWAbHPr~;s9^Yu`SytYdetr6OOJs3;BiOxsW-ZuX47II?h6z478s6!h-w7@NbJ@_c>PeI6Ag%w0xo06UVml0_UvB!i#*Q;VN#Fl~C`la}X&6 zBdhKRhXCMCJIYK({OTaC>JUW)BZey;mvc!lH#_KxI!5XIE$tTdoKUK#BwFm;*m_oo>I64a{m12=oAd1QBKDnK1!Tt zRL_k<#eVku`KXtx;j@=gnv~Av!28LpOXgrnWpydXtvQSBgJ6tsATUiwZOkmXUpjxj zZWEn9KPGY3&21fYBbSvFP_L@VBc-yup$c`0@@`OFoI-O5AoE$Hx{jHalXizvMu4*@ z@LX*e67?H#W_|>W8M*J+Ntytb(Pm*O-pxbfmR_WoG<~18G?3( zYs|`;86uu!G;O1s>S-&j>blVQhP04XeFD!-fS!c39ZLCzucw^mf~`=_6qO=&y}+VWei>`_HQNo_R~-(t`^vD0fgWP7xc=IHRWR{HR0)|)Mf?;=WLDp_Oo?NVYfXuU zP-@LYoff!8Mai!IPxfor6RjQVtwV*@q4m}W*IFN394~h4UhlZK&~fkI55BAYUF3Gh z(RKgPg8wKeNZV(M{-YmhMA2V5bj&V%OE@MtzwL&!4Q=VY@mVE({Ap(uvq|Oa0%>E+ zH(K6qc$8=KHQ|PUS!||R+%bb3!2SR=n2w2OAZ?pE>TABQ;UcO!MqZ>+_adsFwXs6$ z*sTZFk33O0^2A!}BuHdS`;zt-kw1NsX6#AffB4>e>Cj;z(pm?@>f@-7?_?8cPtq;H zn-Pr1VMFG0?z7Z@(=Fo_f71zQ&Zj`~P1xp$O1LnSfbIPyX7!IA@4?EGL$$wiWz zb##?HBzc)Pu<0X7;%F{7+RE-4h!)sGDmiVAhfR0Q!{n~%Hr+MdCb(0VlK53ZS#59r zA(E=#UiDun4jKN7DS)`;yCC00*$KPNcLBKf0G1uJu4jTxZ9X&$K04Sm543iq3+FAFm4HtH(L<_!-A{JEpCV|kM45l+CTHO@X=a6fM!9!ilhj(;{hO$gm6Vh|6dNqGNzv}MX z*$e8y0A+m*k*Qp(9|WL0E2IaHt#;YUfBpHj;7HNm!clCr&^r2-{LSf` z)3;j>ue%Tb$bI-DjT{v(J#x$=d|wcbxy0|=oRGJ{Rb@smA?t5HqpCTh4c>zZQndhO zH@zo(sqi_f=Qs4G^SgIUPZgHlq?w^y9F{hGyO!JD=z6{Djo#OL*L?eEW&$m*PG6tC z?cQYp(ZTzKn}LQvL>ksa5!yFu6kiXSJBF9TFu0F@S}ql=>lu7n<~ zB^OCL4L&2xzEgc)S| z$xfJkz=)U&W}!pzC{D}ltMz7k@x*6gg&%SgWHJE*b5497X^uawWOBMv1&;i!depcp zT9_GXZNC3MRc!?L=HuUI6M9bN9J_%FL^H-SutHZ=D(ue-$gl%9PhOzOtFtU&bxmnYF=$YIZ&QH_6z%v5SkXg&j>i?+O!d}5psRlp^Y2AOsXs2y>m=e75pA@Xdy)AaO(AKs6~hb@2GE$CZh7s;&21J zD%fmPPd%~!r0Vw~m8Iw#_-SOolltYH-fgL0T%mqDhf6M!+@y#-B$?!$q_$6?hy_y- z<6!o9W!eRFYHWDOdRf0j48+vv~+u3n%!>Oz2(0`+%F6H{M%ZQFb-% z0L{ivsNK6L%V&|NvdurWvb?L(Gv}^e!%Jv1Kh(J6b;`~_R*iIh)o;*{rxNpjsV^eD zDeM*h${E?N)bPxlYI2RhB_`lAwQ13FzkGf729OJ+y3wA9R`u5V$YnXlios@c2P;Uc zcNNS~8b$w11!yghS`oqO{J$-$6HHczOUWrXT8P!*Vs?dEG~8(z<#cY#+!DkD46pLS z44fhKiO*=^CkMDG2pYkU^r+WA9w$etzQKk%FlU zHNETB`^pdJg-_M$$IidJZT{z7GR{)sc#vl@@1V^$mVcJ~5wxhKy+hhw^6aE8W^tHK z9wT26Zj}`9K$Q~Qoua&8olE0xAmB+FXX`XPw7w=KB@KsXGD;LW0jD$7s~8iwHTQ^A zm~%OSSQpr9;J$@cEia#tnm{9h8HIHo~3D1FQEx97Q%)XatNxv1!;`Pw%Pf-h75_EE$g_2hst z#0$AxTFp`-scH2jMF%OOF9YVzh>=8Wo9_|6dh1Zza33|#YJOII1^KY5nf4H3948Tk zpRvHtSmySgkFWL~FN9C5vKE|~Ssq+& zUuj$JE`){`nttW<3xgjrM5SIqI3+BPml$1FCN}x?SMCvE|A!3G*7L%U(7imi#c
Q!LvwO7UBFW9ddrBUX zuzkWMA4z`J*;8sFDZpCWOF@$0gYqptv^0MG;pKfRV}-8hsxMk_9N22cL%xRp50kjn A*#H0l literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/index/collector.py b/backend/.venv/Lib/site-packages/pip/_internal/index/collector.py new file mode 100644 index 0000000..5f8fdee --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/index/collector.py @@ -0,0 +1,494 @@ +""" +The main purpose of this module is to expose LinkCollector.collect_sources(). +""" + +import collections +import email.message +import functools +import itertools +import json +import logging +import os +import urllib.parse +import urllib.request +from dataclasses import dataclass +from html.parser import HTMLParser +from optparse import Values +from typing import ( + Callable, + Dict, + Iterable, + List, + MutableMapping, + NamedTuple, + Optional, + Protocol, + Sequence, + Tuple, + Union, +) + +from pip._vendor import requests +from pip._vendor.requests import Response +from pip._vendor.requests.exceptions import RetryError, SSLError + +from pip._internal.exceptions import NetworkConnectionError +from pip._internal.models.link import Link +from pip._internal.models.search_scope import SearchScope +from pip._internal.network.session import PipSession +from pip._internal.network.utils import raise_for_status +from pip._internal.utils.filetypes import is_archive_file +from pip._internal.utils.misc import redact_auth_from_url +from pip._internal.vcs import vcs + +from .sources import CandidatesFromPage, LinkSource, build_source + +logger = logging.getLogger(__name__) + +ResponseHeaders = MutableMapping[str, str] + + +def _match_vcs_scheme(url: str) -> Optional[str]: + """Look for VCS schemes in the URL. + + Returns the matched VCS scheme, or None if there's no match. + """ + for scheme in vcs.schemes: + if url.lower().startswith(scheme) and url[len(scheme)] in "+:": + return scheme + return None + + +class _NotAPIContent(Exception): + def __init__(self, content_type: str, request_desc: str) -> None: + super().__init__(content_type, request_desc) + self.content_type = content_type + self.request_desc = request_desc + + +def _ensure_api_header(response: Response) -> None: + """ + Check the Content-Type header to ensure the response contains a Simple + API Response. + + Raises `_NotAPIContent` if the content type is not a valid content-type. + """ + content_type = response.headers.get("Content-Type", "Unknown") + + content_type_l = content_type.lower() + if content_type_l.startswith( + ( + "text/html", + "application/vnd.pypi.simple.v1+html", + "application/vnd.pypi.simple.v1+json", + ) + ): + return + + raise _NotAPIContent(content_type, response.request.method) + + +class _NotHTTP(Exception): + pass + + +def _ensure_api_response(url: str, session: PipSession) -> None: + """ + Send a HEAD request to the URL, and ensure the response contains a simple + API Response. + + Raises `_NotHTTP` if the URL is not available for a HEAD request, or + `_NotAPIContent` if the content type is not a valid content type. + """ + scheme, netloc, path, query, fragment = urllib.parse.urlsplit(url) + if scheme not in {"http", "https"}: + raise _NotHTTP() + + resp = session.head(url, allow_redirects=True) + raise_for_status(resp) + + _ensure_api_header(resp) + + +def _get_simple_response(url: str, session: PipSession) -> Response: + """Access an Simple API response with GET, and return the response. + + This consists of three parts: + + 1. If the URL looks suspiciously like an archive, send a HEAD first to + check the Content-Type is HTML or Simple API, to avoid downloading a + large file. Raise `_NotHTTP` if the content type cannot be determined, or + `_NotAPIContent` if it is not HTML or a Simple API. + 2. Actually perform the request. Raise HTTP exceptions on network failures. + 3. Check the Content-Type header to make sure we got a Simple API response, + and raise `_NotAPIContent` otherwise. + """ + if is_archive_file(Link(url).filename): + _ensure_api_response(url, session=session) + + logger.debug("Getting page %s", redact_auth_from_url(url)) + + resp = session.get( + url, + headers={ + "Accept": ", ".join( + [ + "application/vnd.pypi.simple.v1+json", + "application/vnd.pypi.simple.v1+html; q=0.1", + "text/html; q=0.01", + ] + ), + # We don't want to blindly returned cached data for + # /simple/, because authors generally expecting that + # twine upload && pip install will function, but if + # they've done a pip install in the last ~10 minutes + # it won't. Thus by setting this to zero we will not + # blindly use any cached data, however the benefit of + # using max-age=0 instead of no-cache, is that we will + # still support conditional requests, so we will still + # minimize traffic sent in cases where the page hasn't + # changed at all, we will just always incur the round + # trip for the conditional GET now instead of only + # once per 10 minutes. + # For more information, please see pypa/pip#5670. + "Cache-Control": "max-age=0", + }, + ) + raise_for_status(resp) + + # The check for archives above only works if the url ends with + # something that looks like an archive. However that is not a + # requirement of an url. Unless we issue a HEAD request on every + # url we cannot know ahead of time for sure if something is a + # Simple API response or not. However we can check after we've + # downloaded it. + _ensure_api_header(resp) + + logger.debug( + "Fetched page %s as %s", + redact_auth_from_url(url), + resp.headers.get("Content-Type", "Unknown"), + ) + + return resp + + +def _get_encoding_from_headers(headers: ResponseHeaders) -> Optional[str]: + """Determine if we have any encoding information in our headers.""" + if headers and "Content-Type" in headers: + m = email.message.Message() + m["content-type"] = headers["Content-Type"] + charset = m.get_param("charset") + if charset: + return str(charset) + return None + + +class CacheablePageContent: + def __init__(self, page: "IndexContent") -> None: + assert page.cache_link_parsing + self.page = page + + def __eq__(self, other: object) -> bool: + return isinstance(other, type(self)) and self.page.url == other.page.url + + def __hash__(self) -> int: + return hash(self.page.url) + + +class ParseLinks(Protocol): + def __call__(self, page: "IndexContent") -> Iterable[Link]: ... + + +def with_cached_index_content(fn: ParseLinks) -> ParseLinks: + """ + Given a function that parses an Iterable[Link] from an IndexContent, cache the + function's result (keyed by CacheablePageContent), unless the IndexContent + `page` has `page.cache_link_parsing == False`. + """ + + @functools.lru_cache(maxsize=None) + def wrapper(cacheable_page: CacheablePageContent) -> List[Link]: + return list(fn(cacheable_page.page)) + + @functools.wraps(fn) + def wrapper_wrapper(page: "IndexContent") -> List[Link]: + if page.cache_link_parsing: + return wrapper(CacheablePageContent(page)) + return list(fn(page)) + + return wrapper_wrapper + + +@with_cached_index_content +def parse_links(page: "IndexContent") -> Iterable[Link]: + """ + Parse a Simple API's Index Content, and yield its anchor elements as Link objects. + """ + + content_type_l = page.content_type.lower() + if content_type_l.startswith("application/vnd.pypi.simple.v1+json"): + data = json.loads(page.content) + for file in data.get("files", []): + link = Link.from_json(file, page.url) + if link is None: + continue + yield link + return + + parser = HTMLLinkParser(page.url) + encoding = page.encoding or "utf-8" + parser.feed(page.content.decode(encoding)) + + url = page.url + base_url = parser.base_url or url + for anchor in parser.anchors: + link = Link.from_element(anchor, page_url=url, base_url=base_url) + if link is None: + continue + yield link + + +@dataclass(frozen=True) +class IndexContent: + """Represents one response (or page), along with its URL. + + :param encoding: the encoding to decode the given content. + :param url: the URL from which the HTML was downloaded. + :param cache_link_parsing: whether links parsed from this page's url + should be cached. PyPI index urls should + have this set to False, for example. + """ + + content: bytes + content_type: str + encoding: Optional[str] + url: str + cache_link_parsing: bool = True + + def __str__(self) -> str: + return redact_auth_from_url(self.url) + + +class HTMLLinkParser(HTMLParser): + """ + HTMLParser that keeps the first base HREF and a list of all anchor + elements' attributes. + """ + + def __init__(self, url: str) -> None: + super().__init__(convert_charrefs=True) + + self.url: str = url + self.base_url: Optional[str] = None + self.anchors: List[Dict[str, Optional[str]]] = [] + + def handle_starttag(self, tag: str, attrs: List[Tuple[str, Optional[str]]]) -> None: + if tag == "base" and self.base_url is None: + href = self.get_href(attrs) + if href is not None: + self.base_url = href + elif tag == "a": + self.anchors.append(dict(attrs)) + + def get_href(self, attrs: List[Tuple[str, Optional[str]]]) -> Optional[str]: + for name, value in attrs: + if name == "href": + return value + return None + + +def _handle_get_simple_fail( + link: Link, + reason: Union[str, Exception], + meth: Optional[Callable[..., None]] = None, +) -> None: + if meth is None: + meth = logger.debug + meth("Could not fetch URL %s: %s - skipping", link, reason) + + +def _make_index_content( + response: Response, cache_link_parsing: bool = True +) -> IndexContent: + encoding = _get_encoding_from_headers(response.headers) + return IndexContent( + response.content, + response.headers["Content-Type"], + encoding=encoding, + url=response.url, + cache_link_parsing=cache_link_parsing, + ) + + +def _get_index_content(link: Link, *, session: PipSession) -> Optional["IndexContent"]: + url = link.url.split("#", 1)[0] + + # Check for VCS schemes that do not support lookup as web pages. + vcs_scheme = _match_vcs_scheme(url) + if vcs_scheme: + logger.warning( + "Cannot look at %s URL %s because it does not support lookup as web pages.", + vcs_scheme, + link, + ) + return None + + # Tack index.html onto file:// URLs that point to directories + scheme, _, path, _, _, _ = urllib.parse.urlparse(url) + if scheme == "file" and os.path.isdir(urllib.request.url2pathname(path)): + # add trailing slash if not present so urljoin doesn't trim + # final segment + if not url.endswith("/"): + url += "/" + # TODO: In the future, it would be nice if pip supported PEP 691 + # style responses in the file:// URLs, however there's no + # standard file extension for application/vnd.pypi.simple.v1+json + # so we'll need to come up with something on our own. + url = urllib.parse.urljoin(url, "index.html") + logger.debug(" file: URL is directory, getting %s", url) + + try: + resp = _get_simple_response(url, session=session) + except _NotHTTP: + logger.warning( + "Skipping page %s because it looks like an archive, and cannot " + "be checked by a HTTP HEAD request.", + link, + ) + except _NotAPIContent as exc: + logger.warning( + "Skipping page %s because the %s request got Content-Type: %s. " + "The only supported Content-Types are application/vnd.pypi.simple.v1+json, " + "application/vnd.pypi.simple.v1+html, and text/html", + link, + exc.request_desc, + exc.content_type, + ) + except NetworkConnectionError as exc: + _handle_get_simple_fail(link, exc) + except RetryError as exc: + _handle_get_simple_fail(link, exc) + except SSLError as exc: + reason = "There was a problem confirming the ssl certificate: " + reason += str(exc) + _handle_get_simple_fail(link, reason, meth=logger.info) + except requests.ConnectionError as exc: + _handle_get_simple_fail(link, f"connection error: {exc}") + except requests.Timeout: + _handle_get_simple_fail(link, "timed out") + else: + return _make_index_content(resp, cache_link_parsing=link.cache_link_parsing) + return None + + +class CollectedSources(NamedTuple): + find_links: Sequence[Optional[LinkSource]] + index_urls: Sequence[Optional[LinkSource]] + + +class LinkCollector: + """ + Responsible for collecting Link objects from all configured locations, + making network requests as needed. + + The class's main method is its collect_sources() method. + """ + + def __init__( + self, + session: PipSession, + search_scope: SearchScope, + ) -> None: + self.search_scope = search_scope + self.session = session + + @classmethod + def create( + cls, + session: PipSession, + options: Values, + suppress_no_index: bool = False, + ) -> "LinkCollector": + """ + :param session: The Session to use to make requests. + :param suppress_no_index: Whether to ignore the --no-index option + when constructing the SearchScope object. + """ + index_urls = [options.index_url] + options.extra_index_urls + if options.no_index and not suppress_no_index: + logger.debug( + "Ignoring indexes: %s", + ",".join(redact_auth_from_url(url) for url in index_urls), + ) + index_urls = [] + + # Make sure find_links is a list before passing to create(). + find_links = options.find_links or [] + + search_scope = SearchScope.create( + find_links=find_links, + index_urls=index_urls, + no_index=options.no_index, + ) + link_collector = LinkCollector( + session=session, + search_scope=search_scope, + ) + return link_collector + + @property + def find_links(self) -> List[str]: + return self.search_scope.find_links + + def fetch_response(self, location: Link) -> Optional[IndexContent]: + """ + Fetch an HTML page containing package links. + """ + return _get_index_content(location, session=self.session) + + def collect_sources( + self, + project_name: str, + candidates_from_page: CandidatesFromPage, + ) -> CollectedSources: + # The OrderedDict calls deduplicate sources by URL. + index_url_sources = collections.OrderedDict( + build_source( + loc, + candidates_from_page=candidates_from_page, + page_validator=self.session.is_secure_origin, + expand_dir=False, + cache_link_parsing=False, + project_name=project_name, + ) + for loc in self.search_scope.get_index_urls_locations(project_name) + ).values() + find_links_sources = collections.OrderedDict( + build_source( + loc, + candidates_from_page=candidates_from_page, + page_validator=self.session.is_secure_origin, + expand_dir=True, + cache_link_parsing=True, + project_name=project_name, + ) + for loc in self.find_links + ).values() + + if logger.isEnabledFor(logging.DEBUG): + lines = [ + f"* {s.link}" + for s in itertools.chain(find_links_sources, index_url_sources) + if s is not None and s.link is not None + ] + lines = [ + f"{len(lines)} location(s) to search " + f"for versions of {project_name}:" + ] + lines + logger.debug("\n".join(lines)) + + return CollectedSources( + find_links=list(find_links_sources), + index_urls=list(index_url_sources), + ) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/index/package_finder.py b/backend/.venv/Lib/site-packages/pip/_internal/index/package_finder.py new file mode 100644 index 0000000..0d65ce3 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/index/package_finder.py @@ -0,0 +1,1020 @@ +"""Routines related to PyPI, indexes""" + +import enum +import functools +import itertools +import logging +import re +from dataclasses import dataclass +from typing import TYPE_CHECKING, FrozenSet, Iterable, List, Optional, Set, Tuple, Union + +from pip._vendor.packaging import specifiers +from pip._vendor.packaging.tags import Tag +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.packaging.version import InvalidVersion, _BaseVersion +from pip._vendor.packaging.version import parse as parse_version + +from pip._internal.exceptions import ( + BestVersionAlreadyInstalled, + DistributionNotFound, + InvalidWheelFilename, + UnsupportedWheel, +) +from pip._internal.index.collector import LinkCollector, parse_links +from pip._internal.models.candidate import InstallationCandidate +from pip._internal.models.format_control import FormatControl +from pip._internal.models.link import Link +from pip._internal.models.search_scope import SearchScope +from pip._internal.models.selection_prefs import SelectionPreferences +from pip._internal.models.target_python import TargetPython +from pip._internal.models.wheel import Wheel +from pip._internal.req import InstallRequirement +from pip._internal.utils._log import getLogger +from pip._internal.utils.filetypes import WHEEL_EXTENSION +from pip._internal.utils.hashes import Hashes +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import build_netloc +from pip._internal.utils.packaging import check_requires_python +from pip._internal.utils.unpacking import SUPPORTED_EXTENSIONS + +if TYPE_CHECKING: + from pip._vendor.typing_extensions import TypeGuard + +__all__ = ["FormatControl", "BestCandidateResult", "PackageFinder"] + + +logger = getLogger(__name__) + +BuildTag = Union[Tuple[()], Tuple[int, str]] +CandidateSortingKey = Tuple[int, int, int, _BaseVersion, Optional[int], BuildTag] + + +def _check_link_requires_python( + link: Link, + version_info: Tuple[int, int, int], + ignore_requires_python: bool = False, +) -> bool: + """ + Return whether the given Python version is compatible with a link's + "Requires-Python" value. + + :param version_info: A 3-tuple of ints representing the Python + major-minor-micro version to check. + :param ignore_requires_python: Whether to ignore the "Requires-Python" + value if the given Python version isn't compatible. + """ + try: + is_compatible = check_requires_python( + link.requires_python, + version_info=version_info, + ) + except specifiers.InvalidSpecifier: + logger.debug( + "Ignoring invalid Requires-Python (%r) for link: %s", + link.requires_python, + link, + ) + else: + if not is_compatible: + version = ".".join(map(str, version_info)) + if not ignore_requires_python: + logger.verbose( + "Link requires a different Python (%s not in: %r): %s", + version, + link.requires_python, + link, + ) + return False + + logger.debug( + "Ignoring failed Requires-Python check (%s not in: %r) for link: %s", + version, + link.requires_python, + link, + ) + + return True + + +class LinkType(enum.Enum): + candidate = enum.auto() + different_project = enum.auto() + yanked = enum.auto() + format_unsupported = enum.auto() + format_invalid = enum.auto() + platform_mismatch = enum.auto() + requires_python_mismatch = enum.auto() + + +class LinkEvaluator: + """ + Responsible for evaluating links for a particular project. + """ + + _py_version_re = re.compile(r"-py([123]\.?[0-9]?)$") + + # Don't include an allow_yanked default value to make sure each call + # site considers whether yanked releases are allowed. This also causes + # that decision to be made explicit in the calling code, which helps + # people when reading the code. + def __init__( + self, + project_name: str, + canonical_name: str, + formats: FrozenSet[str], + target_python: TargetPython, + allow_yanked: bool, + ignore_requires_python: Optional[bool] = None, + ) -> None: + """ + :param project_name: The user supplied package name. + :param canonical_name: The canonical package name. + :param formats: The formats allowed for this package. Should be a set + with 'binary' or 'source' or both in it. + :param target_python: The target Python interpreter to use when + evaluating link compatibility. This is used, for example, to + check wheel compatibility, as well as when checking the Python + version, e.g. the Python version embedded in a link filename + (or egg fragment) and against an HTML link's optional PEP 503 + "data-requires-python" attribute. + :param allow_yanked: Whether files marked as yanked (in the sense + of PEP 592) are permitted to be candidates for install. + :param ignore_requires_python: Whether to ignore incompatible + PEP 503 "data-requires-python" values in HTML links. Defaults + to False. + """ + if ignore_requires_python is None: + ignore_requires_python = False + + self._allow_yanked = allow_yanked + self._canonical_name = canonical_name + self._ignore_requires_python = ignore_requires_python + self._formats = formats + self._target_python = target_python + + self.project_name = project_name + + def evaluate_link(self, link: Link) -> Tuple[LinkType, str]: + """ + Determine whether a link is a candidate for installation. + + :return: A tuple (result, detail), where *result* is an enum + representing whether the evaluation found a candidate, or the reason + why one is not found. If a candidate is found, *detail* will be the + candidate's version string; if one is not found, it contains the + reason the link fails to qualify. + """ + version = None + if link.is_yanked and not self._allow_yanked: + reason = link.yanked_reason or "" + return (LinkType.yanked, f"yanked for reason: {reason}") + + if link.egg_fragment: + egg_info = link.egg_fragment + ext = link.ext + else: + egg_info, ext = link.splitext() + if not ext: + return (LinkType.format_unsupported, "not a file") + if ext not in SUPPORTED_EXTENSIONS: + return ( + LinkType.format_unsupported, + f"unsupported archive format: {ext}", + ) + if "binary" not in self._formats and ext == WHEEL_EXTENSION: + reason = f"No binaries permitted for {self.project_name}" + return (LinkType.format_unsupported, reason) + if "macosx10" in link.path and ext == ".zip": + return (LinkType.format_unsupported, "macosx10 one") + if ext == WHEEL_EXTENSION: + try: + wheel = Wheel(link.filename) + except InvalidWheelFilename: + return ( + LinkType.format_invalid, + "invalid wheel filename", + ) + if canonicalize_name(wheel.name) != self._canonical_name: + reason = f"wrong project name (not {self.project_name})" + return (LinkType.different_project, reason) + + supported_tags = self._target_python.get_unsorted_tags() + if not wheel.supported(supported_tags): + # Include the wheel's tags in the reason string to + # simplify troubleshooting compatibility issues. + file_tags = ", ".join(wheel.get_formatted_file_tags()) + reason = ( + f"none of the wheel's tags ({file_tags}) are compatible " + f"(run pip debug --verbose to show compatible tags)" + ) + return (LinkType.platform_mismatch, reason) + + version = wheel.version + + # This should be up by the self.ok_binary check, but see issue 2700. + if "source" not in self._formats and ext != WHEEL_EXTENSION: + reason = f"No sources permitted for {self.project_name}" + return (LinkType.format_unsupported, reason) + + if not version: + version = _extract_version_from_fragment( + egg_info, + self._canonical_name, + ) + if not version: + reason = f"Missing project version for {self.project_name}" + return (LinkType.format_invalid, reason) + + match = self._py_version_re.search(version) + if match: + version = version[: match.start()] + py_version = match.group(1) + if py_version != self._target_python.py_version: + return ( + LinkType.platform_mismatch, + "Python version is incorrect", + ) + + supports_python = _check_link_requires_python( + link, + version_info=self._target_python.py_version_info, + ignore_requires_python=self._ignore_requires_python, + ) + if not supports_python: + reason = f"{version} Requires-Python {link.requires_python}" + return (LinkType.requires_python_mismatch, reason) + + logger.debug("Found link %s, version: %s", link, version) + + return (LinkType.candidate, version) + + +def filter_unallowed_hashes( + candidates: List[InstallationCandidate], + hashes: Optional[Hashes], + project_name: str, +) -> List[InstallationCandidate]: + """ + Filter out candidates whose hashes aren't allowed, and return a new + list of candidates. + + If at least one candidate has an allowed hash, then all candidates with + either an allowed hash or no hash specified are returned. Otherwise, + the given candidates are returned. + + Including the candidates with no hash specified when there is a match + allows a warning to be logged if there is a more preferred candidate + with no hash specified. Returning all candidates in the case of no + matches lets pip report the hash of the candidate that would otherwise + have been installed (e.g. permitting the user to more easily update + their requirements file with the desired hash). + """ + if not hashes: + logger.debug( + "Given no hashes to check %s links for project %r: " + "discarding no candidates", + len(candidates), + project_name, + ) + # Make sure we're not returning back the given value. + return list(candidates) + + matches_or_no_digest = [] + # Collect the non-matches for logging purposes. + non_matches = [] + match_count = 0 + for candidate in candidates: + link = candidate.link + if not link.has_hash: + pass + elif link.is_hash_allowed(hashes=hashes): + match_count += 1 + else: + non_matches.append(candidate) + continue + + matches_or_no_digest.append(candidate) + + if match_count: + filtered = matches_or_no_digest + else: + # Make sure we're not returning back the given value. + filtered = list(candidates) + + if len(filtered) == len(candidates): + discard_message = "discarding no candidates" + else: + discard_message = "discarding {} non-matches:\n {}".format( + len(non_matches), + "\n ".join(str(candidate.link) for candidate in non_matches), + ) + + logger.debug( + "Checked %s links for project %r against %s hashes " + "(%s matches, %s no digest): %s", + len(candidates), + project_name, + hashes.digest_count, + match_count, + len(matches_or_no_digest) - match_count, + discard_message, + ) + + return filtered + + +@dataclass +class CandidatePreferences: + """ + Encapsulates some of the preferences for filtering and sorting + InstallationCandidate objects. + """ + + prefer_binary: bool = False + allow_all_prereleases: bool = False + + +class BestCandidateResult: + """A collection of candidates, returned by `PackageFinder.find_best_candidate`. + + This class is only intended to be instantiated by CandidateEvaluator's + `compute_best_candidate()` method. + """ + + def __init__( + self, + candidates: List[InstallationCandidate], + applicable_candidates: List[InstallationCandidate], + best_candidate: Optional[InstallationCandidate], + ) -> None: + """ + :param candidates: A sequence of all available candidates found. + :param applicable_candidates: The applicable candidates. + :param best_candidate: The most preferred candidate found, or None + if no applicable candidates were found. + """ + assert set(applicable_candidates) <= set(candidates) + + if best_candidate is None: + assert not applicable_candidates + else: + assert best_candidate in applicable_candidates + + self._applicable_candidates = applicable_candidates + self._candidates = candidates + + self.best_candidate = best_candidate + + def iter_all(self) -> Iterable[InstallationCandidate]: + """Iterate through all candidates.""" + return iter(self._candidates) + + def iter_applicable(self) -> Iterable[InstallationCandidate]: + """Iterate through the applicable candidates.""" + return iter(self._applicable_candidates) + + +class CandidateEvaluator: + """ + Responsible for filtering and sorting candidates for installation based + on what tags are valid. + """ + + @classmethod + def create( + cls, + project_name: str, + target_python: Optional[TargetPython] = None, + prefer_binary: bool = False, + allow_all_prereleases: bool = False, + specifier: Optional[specifiers.BaseSpecifier] = None, + hashes: Optional[Hashes] = None, + ) -> "CandidateEvaluator": + """Create a CandidateEvaluator object. + + :param target_python: The target Python interpreter to use when + checking compatibility. If None (the default), a TargetPython + object will be constructed from the running Python. + :param specifier: An optional object implementing `filter` + (e.g. `packaging.specifiers.SpecifierSet`) to filter applicable + versions. + :param hashes: An optional collection of allowed hashes. + """ + if target_python is None: + target_python = TargetPython() + if specifier is None: + specifier = specifiers.SpecifierSet() + + supported_tags = target_python.get_sorted_tags() + + return cls( + project_name=project_name, + supported_tags=supported_tags, + specifier=specifier, + prefer_binary=prefer_binary, + allow_all_prereleases=allow_all_prereleases, + hashes=hashes, + ) + + def __init__( + self, + project_name: str, + supported_tags: List[Tag], + specifier: specifiers.BaseSpecifier, + prefer_binary: bool = False, + allow_all_prereleases: bool = False, + hashes: Optional[Hashes] = None, + ) -> None: + """ + :param supported_tags: The PEP 425 tags supported by the target + Python in order of preference (most preferred first). + """ + self._allow_all_prereleases = allow_all_prereleases + self._hashes = hashes + self._prefer_binary = prefer_binary + self._project_name = project_name + self._specifier = specifier + self._supported_tags = supported_tags + # Since the index of the tag in the _supported_tags list is used + # as a priority, precompute a map from tag to index/priority to be + # used in wheel.find_most_preferred_tag. + self._wheel_tag_preferences = { + tag: idx for idx, tag in enumerate(supported_tags) + } + + def get_applicable_candidates( + self, + candidates: List[InstallationCandidate], + ) -> List[InstallationCandidate]: + """ + Return the applicable candidates from a list of candidates. + """ + # Using None infers from the specifier instead. + allow_prereleases = self._allow_all_prereleases or None + specifier = self._specifier + + # We turn the version object into a str here because otherwise + # when we're debundled but setuptools isn't, Python will see + # packaging.version.Version and + # pkg_resources._vendor.packaging.version.Version as different + # types. This way we'll use a str as a common data interchange + # format. If we stop using the pkg_resources provided specifier + # and start using our own, we can drop the cast to str(). + candidates_and_versions = [(c, str(c.version)) for c in candidates] + versions = set( + specifier.filter( + (v for _, v in candidates_and_versions), + prereleases=allow_prereleases, + ) + ) + + applicable_candidates = [c for c, v in candidates_and_versions if v in versions] + filtered_applicable_candidates = filter_unallowed_hashes( + candidates=applicable_candidates, + hashes=self._hashes, + project_name=self._project_name, + ) + + return sorted(filtered_applicable_candidates, key=self._sort_key) + + def _sort_key(self, candidate: InstallationCandidate) -> CandidateSortingKey: + """ + Function to pass as the `key` argument to a call to sorted() to sort + InstallationCandidates by preference. + + Returns a tuple such that tuples sorting as greater using Python's + default comparison operator are more preferred. + + The preference is as follows: + + First and foremost, candidates with allowed (matching) hashes are + always preferred over candidates without matching hashes. This is + because e.g. if the only candidate with an allowed hash is yanked, + we still want to use that candidate. + + Second, excepting hash considerations, candidates that have been + yanked (in the sense of PEP 592) are always less preferred than + candidates that haven't been yanked. Then: + + If not finding wheels, they are sorted by version only. + If finding wheels, then the sort order is by version, then: + 1. existing installs + 2. wheels ordered via Wheel.support_index_min(self._supported_tags) + 3. source archives + If prefer_binary was set, then all wheels are sorted above sources. + + Note: it was considered to embed this logic into the Link + comparison operators, but then different sdist links + with the same version, would have to be considered equal + """ + valid_tags = self._supported_tags + support_num = len(valid_tags) + build_tag: BuildTag = () + binary_preference = 0 + link = candidate.link + if link.is_wheel: + # can raise InvalidWheelFilename + wheel = Wheel(link.filename) + try: + pri = -( + wheel.find_most_preferred_tag( + valid_tags, self._wheel_tag_preferences + ) + ) + except ValueError: + raise UnsupportedWheel( + f"{wheel.filename} is not a supported wheel for this platform. It " + "can't be sorted." + ) + if self._prefer_binary: + binary_preference = 1 + if wheel.build_tag is not None: + match = re.match(r"^(\d+)(.*)$", wheel.build_tag) + assert match is not None, "guaranteed by filename validation" + build_tag_groups = match.groups() + build_tag = (int(build_tag_groups[0]), build_tag_groups[1]) + else: # sdist + pri = -(support_num) + has_allowed_hash = int(link.is_hash_allowed(self._hashes)) + yank_value = -1 * int(link.is_yanked) # -1 for yanked. + return ( + has_allowed_hash, + yank_value, + binary_preference, + candidate.version, + pri, + build_tag, + ) + + def sort_best_candidate( + self, + candidates: List[InstallationCandidate], + ) -> Optional[InstallationCandidate]: + """ + Return the best candidate per the instance's sort order, or None if + no candidate is acceptable. + """ + if not candidates: + return None + best_candidate = max(candidates, key=self._sort_key) + return best_candidate + + def compute_best_candidate( + self, + candidates: List[InstallationCandidate], + ) -> BestCandidateResult: + """ + Compute and return a `BestCandidateResult` instance. + """ + applicable_candidates = self.get_applicable_candidates(candidates) + + best_candidate = self.sort_best_candidate(applicable_candidates) + + return BestCandidateResult( + candidates, + applicable_candidates=applicable_candidates, + best_candidate=best_candidate, + ) + + +class PackageFinder: + """This finds packages. + + This is meant to match easy_install's technique for looking for + packages, by reading pages and looking for appropriate links. + """ + + def __init__( + self, + link_collector: LinkCollector, + target_python: TargetPython, + allow_yanked: bool, + format_control: Optional[FormatControl] = None, + candidate_prefs: Optional[CandidatePreferences] = None, + ignore_requires_python: Optional[bool] = None, + ) -> None: + """ + This constructor is primarily meant to be used by the create() class + method and from tests. + + :param format_control: A FormatControl object, used to control + the selection of source packages / binary packages when consulting + the index and links. + :param candidate_prefs: Options to use when creating a + CandidateEvaluator object. + """ + if candidate_prefs is None: + candidate_prefs = CandidatePreferences() + + format_control = format_control or FormatControl(set(), set()) + + self._allow_yanked = allow_yanked + self._candidate_prefs = candidate_prefs + self._ignore_requires_python = ignore_requires_python + self._link_collector = link_collector + self._target_python = target_python + + self.format_control = format_control + + # These are boring links that have already been logged somehow. + self._logged_links: Set[Tuple[Link, LinkType, str]] = set() + + # Don't include an allow_yanked default value to make sure each call + # site considers whether yanked releases are allowed. This also causes + # that decision to be made explicit in the calling code, which helps + # people when reading the code. + @classmethod + def create( + cls, + link_collector: LinkCollector, + selection_prefs: SelectionPreferences, + target_python: Optional[TargetPython] = None, + ) -> "PackageFinder": + """Create a PackageFinder. + + :param selection_prefs: The candidate selection preferences, as a + SelectionPreferences object. + :param target_python: The target Python interpreter to use when + checking compatibility. If None (the default), a TargetPython + object will be constructed from the running Python. + """ + if target_python is None: + target_python = TargetPython() + + candidate_prefs = CandidatePreferences( + prefer_binary=selection_prefs.prefer_binary, + allow_all_prereleases=selection_prefs.allow_all_prereleases, + ) + + return cls( + candidate_prefs=candidate_prefs, + link_collector=link_collector, + target_python=target_python, + allow_yanked=selection_prefs.allow_yanked, + format_control=selection_prefs.format_control, + ignore_requires_python=selection_prefs.ignore_requires_python, + ) + + @property + def target_python(self) -> TargetPython: + return self._target_python + + @property + def search_scope(self) -> SearchScope: + return self._link_collector.search_scope + + @search_scope.setter + def search_scope(self, search_scope: SearchScope) -> None: + self._link_collector.search_scope = search_scope + + @property + def find_links(self) -> List[str]: + return self._link_collector.find_links + + @property + def index_urls(self) -> List[str]: + return self.search_scope.index_urls + + @property + def trusted_hosts(self) -> Iterable[str]: + for host_port in self._link_collector.session.pip_trusted_origins: + yield build_netloc(*host_port) + + @property + def allow_all_prereleases(self) -> bool: + return self._candidate_prefs.allow_all_prereleases + + def set_allow_all_prereleases(self) -> None: + self._candidate_prefs.allow_all_prereleases = True + + @property + def prefer_binary(self) -> bool: + return self._candidate_prefs.prefer_binary + + def set_prefer_binary(self) -> None: + self._candidate_prefs.prefer_binary = True + + def requires_python_skipped_reasons(self) -> List[str]: + reasons = { + detail + for _, result, detail in self._logged_links + if result == LinkType.requires_python_mismatch + } + return sorted(reasons) + + def make_link_evaluator(self, project_name: str) -> LinkEvaluator: + canonical_name = canonicalize_name(project_name) + formats = self.format_control.get_allowed_formats(canonical_name) + + return LinkEvaluator( + project_name=project_name, + canonical_name=canonical_name, + formats=formats, + target_python=self._target_python, + allow_yanked=self._allow_yanked, + ignore_requires_python=self._ignore_requires_python, + ) + + def _sort_links(self, links: Iterable[Link]) -> List[Link]: + """ + Returns elements of links in order, non-egg links first, egg links + second, while eliminating duplicates + """ + eggs, no_eggs = [], [] + seen: Set[Link] = set() + for link in links: + if link not in seen: + seen.add(link) + if link.egg_fragment: + eggs.append(link) + else: + no_eggs.append(link) + return no_eggs + eggs + + def _log_skipped_link(self, link: Link, result: LinkType, detail: str) -> None: + entry = (link, result, detail) + if entry not in self._logged_links: + # Put the link at the end so the reason is more visible and because + # the link string is usually very long. + logger.debug("Skipping link: %s: %s", detail, link) + self._logged_links.add(entry) + + def get_install_candidate( + self, link_evaluator: LinkEvaluator, link: Link + ) -> Optional[InstallationCandidate]: + """ + If the link is a candidate for install, convert it to an + InstallationCandidate and return it. Otherwise, return None. + """ + result, detail = link_evaluator.evaluate_link(link) + if result != LinkType.candidate: + self._log_skipped_link(link, result, detail) + return None + + try: + return InstallationCandidate( + name=link_evaluator.project_name, + link=link, + version=detail, + ) + except InvalidVersion: + return None + + def evaluate_links( + self, link_evaluator: LinkEvaluator, links: Iterable[Link] + ) -> List[InstallationCandidate]: + """ + Convert links that are candidates to InstallationCandidate objects. + """ + candidates = [] + for link in self._sort_links(links): + candidate = self.get_install_candidate(link_evaluator, link) + if candidate is not None: + candidates.append(candidate) + + return candidates + + def process_project_url( + self, project_url: Link, link_evaluator: LinkEvaluator + ) -> List[InstallationCandidate]: + logger.debug( + "Fetching project page and analyzing links: %s", + project_url, + ) + index_response = self._link_collector.fetch_response(project_url) + if index_response is None: + return [] + + page_links = list(parse_links(index_response)) + + with indent_log(): + package_links = self.evaluate_links( + link_evaluator, + links=page_links, + ) + + return package_links + + @functools.lru_cache(maxsize=None) + def find_all_candidates(self, project_name: str) -> List[InstallationCandidate]: + """Find all available InstallationCandidate for project_name + + This checks index_urls and find_links. + All versions found are returned as an InstallationCandidate list. + + See LinkEvaluator.evaluate_link() for details on which files + are accepted. + """ + link_evaluator = self.make_link_evaluator(project_name) + + collected_sources = self._link_collector.collect_sources( + project_name=project_name, + candidates_from_page=functools.partial( + self.process_project_url, + link_evaluator=link_evaluator, + ), + ) + + page_candidates_it = itertools.chain.from_iterable( + source.page_candidates() + for sources in collected_sources + for source in sources + if source is not None + ) + page_candidates = list(page_candidates_it) + + file_links_it = itertools.chain.from_iterable( + source.file_links() + for sources in collected_sources + for source in sources + if source is not None + ) + file_candidates = self.evaluate_links( + link_evaluator, + sorted(file_links_it, reverse=True), + ) + + if logger.isEnabledFor(logging.DEBUG) and file_candidates: + paths = [] + for candidate in file_candidates: + assert candidate.link.url # we need to have a URL + try: + paths.append(candidate.link.file_path) + except Exception: + paths.append(candidate.link.url) # it's not a local file + + logger.debug("Local files found: %s", ", ".join(paths)) + + # This is an intentional priority ordering + return file_candidates + page_candidates + + def make_candidate_evaluator( + self, + project_name: str, + specifier: Optional[specifiers.BaseSpecifier] = None, + hashes: Optional[Hashes] = None, + ) -> CandidateEvaluator: + """Create a CandidateEvaluator object to use.""" + candidate_prefs = self._candidate_prefs + return CandidateEvaluator.create( + project_name=project_name, + target_python=self._target_python, + prefer_binary=candidate_prefs.prefer_binary, + allow_all_prereleases=candidate_prefs.allow_all_prereleases, + specifier=specifier, + hashes=hashes, + ) + + @functools.lru_cache(maxsize=None) + def find_best_candidate( + self, + project_name: str, + specifier: Optional[specifiers.BaseSpecifier] = None, + hashes: Optional[Hashes] = None, + ) -> BestCandidateResult: + """Find matches for the given project and specifier. + + :param specifier: An optional object implementing `filter` + (e.g. `packaging.specifiers.SpecifierSet`) to filter applicable + versions. + + :return: A `BestCandidateResult` instance. + """ + candidates = self.find_all_candidates(project_name) + candidate_evaluator = self.make_candidate_evaluator( + project_name=project_name, + specifier=specifier, + hashes=hashes, + ) + return candidate_evaluator.compute_best_candidate(candidates) + + def find_requirement( + self, req: InstallRequirement, upgrade: bool + ) -> Optional[InstallationCandidate]: + """Try to find a Link matching req + + Expects req, an InstallRequirement and upgrade, a boolean + Returns a InstallationCandidate if found, + Raises DistributionNotFound or BestVersionAlreadyInstalled otherwise + """ + hashes = req.hashes(trust_internet=False) + best_candidate_result = self.find_best_candidate( + req.name, + specifier=req.specifier, + hashes=hashes, + ) + best_candidate = best_candidate_result.best_candidate + + installed_version: Optional[_BaseVersion] = None + if req.satisfied_by is not None: + installed_version = req.satisfied_by.version + + def _format_versions(cand_iter: Iterable[InstallationCandidate]) -> str: + # This repeated parse_version and str() conversion is needed to + # handle different vendoring sources from pip and pkg_resources. + # If we stop using the pkg_resources provided specifier and start + # using our own, we can drop the cast to str(). + return ( + ", ".join( + sorted( + {str(c.version) for c in cand_iter}, + key=parse_version, + ) + ) + or "none" + ) + + if installed_version is None and best_candidate is None: + logger.critical( + "Could not find a version that satisfies the requirement %s " + "(from versions: %s)", + req, + _format_versions(best_candidate_result.iter_all()), + ) + + raise DistributionNotFound(f"No matching distribution found for {req}") + + def _should_install_candidate( + candidate: Optional[InstallationCandidate], + ) -> "TypeGuard[InstallationCandidate]": + if installed_version is None: + return True + if best_candidate is None: + return False + return best_candidate.version > installed_version + + if not upgrade and installed_version is not None: + if _should_install_candidate(best_candidate): + logger.debug( + "Existing installed version (%s) satisfies requirement " + "(most up-to-date version is %s)", + installed_version, + best_candidate.version, + ) + else: + logger.debug( + "Existing installed version (%s) is most up-to-date and " + "satisfies requirement", + installed_version, + ) + return None + + if _should_install_candidate(best_candidate): + logger.debug( + "Using version %s (newest of versions: %s)", + best_candidate.version, + _format_versions(best_candidate_result.iter_applicable()), + ) + return best_candidate + + # We have an existing version, and its the best version + logger.debug( + "Installed version (%s) is most up-to-date (past versions: %s)", + installed_version, + _format_versions(best_candidate_result.iter_applicable()), + ) + raise BestVersionAlreadyInstalled + + +def _find_name_version_sep(fragment: str, canonical_name: str) -> int: + """Find the separator's index based on the package's canonical name. + + :param fragment: A + filename "fragment" (stem) or + egg fragment. + :param canonical_name: The package's canonical name. + + This function is needed since the canonicalized name does not necessarily + have the same length as the egg info's name part. An example:: + + >>> fragment = 'foo__bar-1.0' + >>> canonical_name = 'foo-bar' + >>> _find_name_version_sep(fragment, canonical_name) + 8 + """ + # Project name and version must be separated by one single dash. Find all + # occurrences of dashes; if the string in front of it matches the canonical + # name, this is the one separating the name and version parts. + for i, c in enumerate(fragment): + if c != "-": + continue + if canonicalize_name(fragment[:i]) == canonical_name: + return i + raise ValueError(f"{fragment} does not match {canonical_name}") + + +def _extract_version_from_fragment(fragment: str, canonical_name: str) -> Optional[str]: + """Parse the version string from a + filename + "fragment" (stem) or egg fragment. + + :param fragment: The string to parse. E.g. foo-2.1 + :param canonical_name: The canonicalized name of the package this + belongs to. + """ + try: + version_start = _find_name_version_sep(fragment, canonical_name) + 1 + except ValueError: + return None + version = fragment[version_start:] + if not version: + return None + return version diff --git a/backend/.venv/Lib/site-packages/pip/_internal/index/sources.py b/backend/.venv/Lib/site-packages/pip/_internal/index/sources.py new file mode 100644 index 0000000..3dafb30 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/index/sources.py @@ -0,0 +1,284 @@ +import logging +import mimetypes +import os +from collections import defaultdict +from typing import Callable, Dict, Iterable, List, Optional, Tuple + +from pip._vendor.packaging.utils import ( + InvalidSdistFilename, + InvalidWheelFilename, + canonicalize_name, + parse_sdist_filename, + parse_wheel_filename, +) + +from pip._internal.models.candidate import InstallationCandidate +from pip._internal.models.link import Link +from pip._internal.utils.urls import path_to_url, url_to_path +from pip._internal.vcs import is_url + +logger = logging.getLogger(__name__) + +FoundCandidates = Iterable[InstallationCandidate] +FoundLinks = Iterable[Link] +CandidatesFromPage = Callable[[Link], Iterable[InstallationCandidate]] +PageValidator = Callable[[Link], bool] + + +class LinkSource: + @property + def link(self) -> Optional[Link]: + """Returns the underlying link, if there's one.""" + raise NotImplementedError() + + def page_candidates(self) -> FoundCandidates: + """Candidates found by parsing an archive listing HTML file.""" + raise NotImplementedError() + + def file_links(self) -> FoundLinks: + """Links found by specifying archives directly.""" + raise NotImplementedError() + + +def _is_html_file(file_url: str) -> bool: + return mimetypes.guess_type(file_url, strict=False)[0] == "text/html" + + +class _FlatDirectoryToUrls: + """Scans directory and caches results""" + + def __init__(self, path: str) -> None: + self._path = path + self._page_candidates: List[str] = [] + self._project_name_to_urls: Dict[str, List[str]] = defaultdict(list) + self._scanned_directory = False + + def _scan_directory(self) -> None: + """Scans directory once and populates both page_candidates + and project_name_to_urls at the same time + """ + for entry in os.scandir(self._path): + url = path_to_url(entry.path) + if _is_html_file(url): + self._page_candidates.append(url) + continue + + # File must have a valid wheel or sdist name, + # otherwise not worth considering as a package + try: + project_filename = parse_wheel_filename(entry.name)[0] + except InvalidWheelFilename: + try: + project_filename = parse_sdist_filename(entry.name)[0] + except InvalidSdistFilename: + continue + + self._project_name_to_urls[project_filename].append(url) + self._scanned_directory = True + + @property + def page_candidates(self) -> List[str]: + if not self._scanned_directory: + self._scan_directory() + + return self._page_candidates + + @property + def project_name_to_urls(self) -> Dict[str, List[str]]: + if not self._scanned_directory: + self._scan_directory() + + return self._project_name_to_urls + + +class _FlatDirectorySource(LinkSource): + """Link source specified by ``--find-links=``. + + This looks the content of the directory, and returns: + + * ``page_candidates``: Links listed on each HTML file in the directory. + * ``file_candidates``: Archives in the directory. + """ + + _paths_to_urls: Dict[str, _FlatDirectoryToUrls] = {} + + def __init__( + self, + candidates_from_page: CandidatesFromPage, + path: str, + project_name: str, + ) -> None: + self._candidates_from_page = candidates_from_page + self._project_name = canonicalize_name(project_name) + + # Get existing instance of _FlatDirectoryToUrls if it exists + if path in self._paths_to_urls: + self._path_to_urls = self._paths_to_urls[path] + else: + self._path_to_urls = _FlatDirectoryToUrls(path=path) + self._paths_to_urls[path] = self._path_to_urls + + @property + def link(self) -> Optional[Link]: + return None + + def page_candidates(self) -> FoundCandidates: + for url in self._path_to_urls.page_candidates: + yield from self._candidates_from_page(Link(url)) + + def file_links(self) -> FoundLinks: + for url in self._path_to_urls.project_name_to_urls[self._project_name]: + yield Link(url) + + +class _LocalFileSource(LinkSource): + """``--find-links=`` or ``--[extra-]index-url=``. + + If a URL is supplied, it must be a ``file:`` URL. If a path is supplied to + the option, it is converted to a URL first. This returns: + + * ``page_candidates``: Links listed on an HTML file. + * ``file_candidates``: The non-HTML file. + """ + + def __init__( + self, + candidates_from_page: CandidatesFromPage, + link: Link, + ) -> None: + self._candidates_from_page = candidates_from_page + self._link = link + + @property + def link(self) -> Optional[Link]: + return self._link + + def page_candidates(self) -> FoundCandidates: + if not _is_html_file(self._link.url): + return + yield from self._candidates_from_page(self._link) + + def file_links(self) -> FoundLinks: + if _is_html_file(self._link.url): + return + yield self._link + + +class _RemoteFileSource(LinkSource): + """``--find-links=`` or ``--[extra-]index-url=``. + + This returns: + + * ``page_candidates``: Links listed on an HTML file. + * ``file_candidates``: The non-HTML file. + """ + + def __init__( + self, + candidates_from_page: CandidatesFromPage, + page_validator: PageValidator, + link: Link, + ) -> None: + self._candidates_from_page = candidates_from_page + self._page_validator = page_validator + self._link = link + + @property + def link(self) -> Optional[Link]: + return self._link + + def page_candidates(self) -> FoundCandidates: + if not self._page_validator(self._link): + return + yield from self._candidates_from_page(self._link) + + def file_links(self) -> FoundLinks: + yield self._link + + +class _IndexDirectorySource(LinkSource): + """``--[extra-]index-url=``. + + This is treated like a remote URL; ``candidates_from_page`` contains logic + for this by appending ``index.html`` to the link. + """ + + def __init__( + self, + candidates_from_page: CandidatesFromPage, + link: Link, + ) -> None: + self._candidates_from_page = candidates_from_page + self._link = link + + @property + def link(self) -> Optional[Link]: + return self._link + + def page_candidates(self) -> FoundCandidates: + yield from self._candidates_from_page(self._link) + + def file_links(self) -> FoundLinks: + return () + + +def build_source( + location: str, + *, + candidates_from_page: CandidatesFromPage, + page_validator: PageValidator, + expand_dir: bool, + cache_link_parsing: bool, + project_name: str, +) -> Tuple[Optional[str], Optional[LinkSource]]: + path: Optional[str] = None + url: Optional[str] = None + if os.path.exists(location): # Is a local path. + url = path_to_url(location) + path = location + elif location.startswith("file:"): # A file: URL. + url = location + path = url_to_path(location) + elif is_url(location): + url = location + + if url is None: + msg = ( + "Location '%s' is ignored: " + "it is either a non-existing path or lacks a specific scheme." + ) + logger.warning(msg, location) + return (None, None) + + if path is None: + source: LinkSource = _RemoteFileSource( + candidates_from_page=candidates_from_page, + page_validator=page_validator, + link=Link(url, cache_link_parsing=cache_link_parsing), + ) + return (url, source) + + if os.path.isdir(path): + if expand_dir: + source = _FlatDirectorySource( + candidates_from_page=candidates_from_page, + path=path, + project_name=project_name, + ) + else: + source = _IndexDirectorySource( + candidates_from_page=candidates_from_page, + link=Link(url, cache_link_parsing=cache_link_parsing), + ) + return (url, source) + elif os.path.isfile(path): + source = _LocalFileSource( + candidates_from_page=candidates_from_page, + link=Link(url, cache_link_parsing=cache_link_parsing), + ) + return (url, source) + logger.warning( + "Location '%s' is ignored: it is neither a file nor a directory.", + location, + ) + return (url, None) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/locations/__init__.py b/backend/.venv/Lib/site-packages/pip/_internal/locations/__init__.py new file mode 100644 index 0000000..32382be --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/locations/__init__.py @@ -0,0 +1,456 @@ +import functools +import logging +import os +import pathlib +import sys +import sysconfig +from typing import Any, Dict, Generator, Optional, Tuple + +from pip._internal.models.scheme import SCHEME_KEYS, Scheme +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.deprecation import deprecated +from pip._internal.utils.virtualenv import running_under_virtualenv + +from . import _sysconfig +from .base import ( + USER_CACHE_DIR, + get_major_minor_version, + get_src_prefix, + is_osx_framework, + site_packages, + user_site, +) + +__all__ = [ + "USER_CACHE_DIR", + "get_bin_prefix", + "get_bin_user", + "get_major_minor_version", + "get_platlib", + "get_purelib", + "get_scheme", + "get_src_prefix", + "site_packages", + "user_site", +] + + +logger = logging.getLogger(__name__) + + +_PLATLIBDIR: str = getattr(sys, "platlibdir", "lib") + +_USE_SYSCONFIG_DEFAULT = sys.version_info >= (3, 10) + + +def _should_use_sysconfig() -> bool: + """This function determines the value of _USE_SYSCONFIG. + + By default, pip uses sysconfig on Python 3.10+. + But Python distributors can override this decision by setting: + sysconfig._PIP_USE_SYSCONFIG = True / False + Rationale in https://github.com/pypa/pip/issues/10647 + + This is a function for testability, but should be constant during any one + run. + """ + return bool(getattr(sysconfig, "_PIP_USE_SYSCONFIG", _USE_SYSCONFIG_DEFAULT)) + + +_USE_SYSCONFIG = _should_use_sysconfig() + +if not _USE_SYSCONFIG: + # Import distutils lazily to avoid deprecation warnings, + # but import it soon enough that it is in memory and available during + # a pip reinstall. + from . import _distutils + +# Be noisy about incompatibilities if this platforms "should" be using +# sysconfig, but is explicitly opting out and using distutils instead. +if _USE_SYSCONFIG_DEFAULT and not _USE_SYSCONFIG: + _MISMATCH_LEVEL = logging.WARNING +else: + _MISMATCH_LEVEL = logging.DEBUG + + +def _looks_like_bpo_44860() -> bool: + """The resolution to bpo-44860 will change this incorrect platlib. + + See . + """ + from distutils.command.install import INSTALL_SCHEMES + + try: + unix_user_platlib = INSTALL_SCHEMES["unix_user"]["platlib"] + except KeyError: + return False + return unix_user_platlib == "$usersite" + + +def _looks_like_red_hat_patched_platlib_purelib(scheme: Dict[str, str]) -> bool: + platlib = scheme["platlib"] + if "/$platlibdir/" in platlib: + platlib = platlib.replace("/$platlibdir/", f"/{_PLATLIBDIR}/") + if "/lib64/" not in platlib: + return False + unpatched = platlib.replace("/lib64/", "/lib/") + return unpatched.replace("$platbase/", "$base/") == scheme["purelib"] + + +@functools.lru_cache(maxsize=None) +def _looks_like_red_hat_lib() -> bool: + """Red Hat patches platlib in unix_prefix and unix_home, but not purelib. + + This is the only way I can see to tell a Red Hat-patched Python. + """ + from distutils.command.install import INSTALL_SCHEMES + + return all( + k in INSTALL_SCHEMES + and _looks_like_red_hat_patched_platlib_purelib(INSTALL_SCHEMES[k]) + for k in ("unix_prefix", "unix_home") + ) + + +@functools.lru_cache(maxsize=None) +def _looks_like_debian_scheme() -> bool: + """Debian adds two additional schemes.""" + from distutils.command.install import INSTALL_SCHEMES + + return "deb_system" in INSTALL_SCHEMES and "unix_local" in INSTALL_SCHEMES + + +@functools.lru_cache(maxsize=None) +def _looks_like_red_hat_scheme() -> bool: + """Red Hat patches ``sys.prefix`` and ``sys.exec_prefix``. + + Red Hat's ``00251-change-user-install-location.patch`` changes the install + command's ``prefix`` and ``exec_prefix`` to append ``"/local"``. This is + (fortunately?) done quite unconditionally, so we create a default command + object without any configuration to detect this. + """ + from distutils.command.install import install + from distutils.dist import Distribution + + cmd: Any = install(Distribution()) + cmd.finalize_options() + return ( + cmd.exec_prefix == f"{os.path.normpath(sys.exec_prefix)}/local" + and cmd.prefix == f"{os.path.normpath(sys.prefix)}/local" + ) + + +@functools.lru_cache(maxsize=None) +def _looks_like_slackware_scheme() -> bool: + """Slackware patches sysconfig but fails to patch distutils and site. + + Slackware changes sysconfig's user scheme to use ``"lib64"`` for the lib + path, but does not do the same to the site module. + """ + if user_site is None: # User-site not available. + return False + try: + paths = sysconfig.get_paths(scheme="posix_user", expand=False) + except KeyError: # User-site not available. + return False + return "/lib64/" in paths["purelib"] and "/lib64/" not in user_site + + +@functools.lru_cache(maxsize=None) +def _looks_like_msys2_mingw_scheme() -> bool: + """MSYS2 patches distutils and sysconfig to use a UNIX-like scheme. + + However, MSYS2 incorrectly patches sysconfig ``nt`` scheme. The fix is + likely going to be included in their 3.10 release, so we ignore the warning. + See msys2/MINGW-packages#9319. + + MSYS2 MINGW's patch uses lowercase ``"lib"`` instead of the usual uppercase, + and is missing the final ``"site-packages"``. + """ + paths = sysconfig.get_paths("nt", expand=False) + return all( + "Lib" not in p and "lib" in p and not p.endswith("site-packages") + for p in (paths[key] for key in ("platlib", "purelib")) + ) + + +def _fix_abiflags(parts: Tuple[str]) -> Generator[str, None, None]: + ldversion = sysconfig.get_config_var("LDVERSION") + abiflags = getattr(sys, "abiflags", None) + + # LDVERSION does not end with sys.abiflags. Just return the path unchanged. + if not ldversion or not abiflags or not ldversion.endswith(abiflags): + yield from parts + return + + # Strip sys.abiflags from LDVERSION-based path components. + for part in parts: + if part.endswith(ldversion): + part = part[: (0 - len(abiflags))] + yield part + + +@functools.lru_cache(maxsize=None) +def _warn_mismatched(old: pathlib.Path, new: pathlib.Path, *, key: str) -> None: + issue_url = "https://github.com/pypa/pip/issues/10151" + message = ( + "Value for %s does not match. Please report this to <%s>" + "\ndistutils: %s" + "\nsysconfig: %s" + ) + logger.log(_MISMATCH_LEVEL, message, key, issue_url, old, new) + + +def _warn_if_mismatch(old: pathlib.Path, new: pathlib.Path, *, key: str) -> bool: + if old == new: + return False + _warn_mismatched(old, new, key=key) + return True + + +@functools.lru_cache(maxsize=None) +def _log_context( + *, + user: bool = False, + home: Optional[str] = None, + root: Optional[str] = None, + prefix: Optional[str] = None, +) -> None: + parts = [ + "Additional context:", + "user = %r", + "home = %r", + "root = %r", + "prefix = %r", + ] + + logger.log(_MISMATCH_LEVEL, "\n".join(parts), user, home, root, prefix) + + +def get_scheme( + dist_name: str, + user: bool = False, + home: Optional[str] = None, + root: Optional[str] = None, + isolated: bool = False, + prefix: Optional[str] = None, +) -> Scheme: + new = _sysconfig.get_scheme( + dist_name, + user=user, + home=home, + root=root, + isolated=isolated, + prefix=prefix, + ) + if _USE_SYSCONFIG: + return new + + old = _distutils.get_scheme( + dist_name, + user=user, + home=home, + root=root, + isolated=isolated, + prefix=prefix, + ) + + warning_contexts = [] + for k in SCHEME_KEYS: + old_v = pathlib.Path(getattr(old, k)) + new_v = pathlib.Path(getattr(new, k)) + + if old_v == new_v: + continue + + # distutils incorrectly put PyPy packages under ``site-packages/python`` + # in the ``posix_home`` scheme, but PyPy devs said they expect the + # directory name to be ``pypy`` instead. So we treat this as a bug fix + # and not warn about it. See bpo-43307 and python/cpython#24628. + skip_pypy_special_case = ( + sys.implementation.name == "pypy" + and home is not None + and k in ("platlib", "purelib") + and old_v.parent == new_v.parent + and old_v.name.startswith("python") + and new_v.name.startswith("pypy") + ) + if skip_pypy_special_case: + continue + + # sysconfig's ``osx_framework_user`` does not include ``pythonX.Y`` in + # the ``include`` value, but distutils's ``headers`` does. We'll let + # CPython decide whether this is a bug or feature. See bpo-43948. + skip_osx_framework_user_special_case = ( + user + and is_osx_framework() + and k == "headers" + and old_v.parent.parent == new_v.parent + and old_v.parent.name.startswith("python") + ) + if skip_osx_framework_user_special_case: + continue + + # On Red Hat and derived Linux distributions, distutils is patched to + # use "lib64" instead of "lib" for platlib. + if k == "platlib" and _looks_like_red_hat_lib(): + continue + + # On Python 3.9+, sysconfig's posix_user scheme sets platlib against + # sys.platlibdir, but distutils's unix_user incorrectly coninutes + # using the same $usersite for both platlib and purelib. This creates a + # mismatch when sys.platlibdir is not "lib". + skip_bpo_44860 = ( + user + and k == "platlib" + and not WINDOWS + and sys.version_info >= (3, 9) + and _PLATLIBDIR != "lib" + and _looks_like_bpo_44860() + ) + if skip_bpo_44860: + continue + + # Slackware incorrectly patches posix_user to use lib64 instead of lib, + # but not usersite to match the location. + skip_slackware_user_scheme = ( + user + and k in ("platlib", "purelib") + and not WINDOWS + and _looks_like_slackware_scheme() + ) + if skip_slackware_user_scheme: + continue + + # Both Debian and Red Hat patch Python to place the system site under + # /usr/local instead of /usr. Debian also places lib in dist-packages + # instead of site-packages, but the /usr/local check should cover it. + skip_linux_system_special_case = ( + not (user or home or prefix or running_under_virtualenv()) + and old_v.parts[1:3] == ("usr", "local") + and len(new_v.parts) > 1 + and new_v.parts[1] == "usr" + and (len(new_v.parts) < 3 or new_v.parts[2] != "local") + and (_looks_like_red_hat_scheme() or _looks_like_debian_scheme()) + ) + if skip_linux_system_special_case: + continue + + # MSYS2 MINGW's sysconfig patch does not include the "site-packages" + # part of the path. This is incorrect and will be fixed in MSYS. + skip_msys2_mingw_bug = ( + WINDOWS and k in ("platlib", "purelib") and _looks_like_msys2_mingw_scheme() + ) + if skip_msys2_mingw_bug: + continue + + # CPython's POSIX install script invokes pip (via ensurepip) against the + # interpreter located in the source tree, not the install site. This + # triggers special logic in sysconfig that's not present in distutils. + # https://github.com/python/cpython/blob/8c21941ddaf/Lib/sysconfig.py#L178-L194 + skip_cpython_build = ( + sysconfig.is_python_build(check_home=True) + and not WINDOWS + and k in ("headers", "include", "platinclude") + ) + if skip_cpython_build: + continue + + warning_contexts.append((old_v, new_v, f"scheme.{k}")) + + if not warning_contexts: + return old + + # Check if this path mismatch is caused by distutils config files. Those + # files will no longer work once we switch to sysconfig, so this raises a + # deprecation message for them. + default_old = _distutils.distutils_scheme( + dist_name, + user, + home, + root, + isolated, + prefix, + ignore_config_files=True, + ) + if any(default_old[k] != getattr(old, k) for k in SCHEME_KEYS): + deprecated( + reason=( + "Configuring installation scheme with distutils config files " + "is deprecated and will no longer work in the near future. If you " + "are using a Homebrew or Linuxbrew Python, please see discussion " + "at https://github.com/Homebrew/homebrew-core/issues/76621" + ), + replacement=None, + gone_in=None, + ) + return old + + # Post warnings about this mismatch so user can report them back. + for old_v, new_v, key in warning_contexts: + _warn_mismatched(old_v, new_v, key=key) + _log_context(user=user, home=home, root=root, prefix=prefix) + + return old + + +def get_bin_prefix() -> str: + new = _sysconfig.get_bin_prefix() + if _USE_SYSCONFIG: + return new + + old = _distutils.get_bin_prefix() + if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="bin_prefix"): + _log_context() + return old + + +def get_bin_user() -> str: + return _sysconfig.get_scheme("", user=True).scripts + + +def _looks_like_deb_system_dist_packages(value: str) -> bool: + """Check if the value is Debian's APT-controlled dist-packages. + + Debian's ``distutils.sysconfig.get_python_lib()`` implementation returns the + default package path controlled by APT, but does not patch ``sysconfig`` to + do the same. This is similar to the bug worked around in ``get_scheme()``, + but here the default is ``deb_system`` instead of ``unix_local``. Ultimately + we can't do anything about this Debian bug, and this detection allows us to + skip the warning when needed. + """ + if not _looks_like_debian_scheme(): + return False + if value == "/usr/lib/python3/dist-packages": + return True + return False + + +def get_purelib() -> str: + """Return the default pure-Python lib location.""" + new = _sysconfig.get_purelib() + if _USE_SYSCONFIG: + return new + + old = _distutils.get_purelib() + if _looks_like_deb_system_dist_packages(old): + return old + if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="purelib"): + _log_context() + return old + + +def get_platlib() -> str: + """Return the default platform-shared lib location.""" + new = _sysconfig.get_platlib() + if _USE_SYSCONFIG: + return new + + from . import _distutils + + old = _distutils.get_platlib() + if _looks_like_deb_system_dist_packages(old): + return old + if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="platlib"): + _log_context() + return old diff --git a/backend/.venv/Lib/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e4a7f922f287f69b83b8ab376d3e90cdaa543873 GIT binary patch literal 16442 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 XJ-lzSi{#n2RGCNlCzusIu;Bjy#G5cq literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1ecb9aa0ea86347b56d6bf56f4fbf528b72d0d15 GIT binary patch literal 6793 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≧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 bRKKGyb^7@IIo@$TjvmLGh7kXFkc0kz@|$UE literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/locations/_distutils.py b/backend/.venv/Lib/site-packages/pip/_internal/locations/_distutils.py new file mode 100644 index 0000000..3d85625 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/locations/_distutils.py @@ -0,0 +1,172 @@ +"""Locations where we look for configs, install stuff, etc""" + +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False + +# If pip's going to use distutils, it should not be using the copy that setuptools +# might have injected into the environment. This is done by removing the injected +# shim, if it's injected. +# +# See https://github.com/pypa/pip/issues/8761 for the original discussion and +# rationale for why this is done within pip. +try: + __import__("_distutils_hack").remove_shim() +except (ImportError, AttributeError): + pass + +import logging +import os +import sys +from distutils.cmd import Command as DistutilsCommand +from distutils.command.install import SCHEME_KEYS +from distutils.command.install import install as distutils_install_command +from distutils.sysconfig import get_python_lib +from typing import Dict, List, Optional, Union + +from pip._internal.models.scheme import Scheme +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.virtualenv import running_under_virtualenv + +from .base import get_major_minor_version + +logger = logging.getLogger(__name__) + + +def distutils_scheme( + dist_name: str, + user: bool = False, + home: Optional[str] = None, + root: Optional[str] = None, + isolated: bool = False, + prefix: Optional[str] = None, + *, + ignore_config_files: bool = False, +) -> Dict[str, str]: + """ + Return a distutils install scheme + """ + from distutils.dist import Distribution + + dist_args: Dict[str, Union[str, List[str]]] = {"name": dist_name} + if isolated: + dist_args["script_args"] = ["--no-user-cfg"] + + d = Distribution(dist_args) + if not ignore_config_files: + try: + d.parse_config_files() + except UnicodeDecodeError: + paths = d.find_config_files() + logger.warning( + "Ignore distutils configs in %s due to encoding errors.", + ", ".join(os.path.basename(p) for p in paths), + ) + obj: Optional[DistutilsCommand] = None + obj = d.get_command_obj("install", create=True) + assert obj is not None + i: distutils_install_command = obj + # NOTE: setting user or home has the side-effect of creating the home dir + # or user base for installations during finalize_options() + # ideally, we'd prefer a scheme class that has no side-effects. + assert not (user and prefix), f"user={user} prefix={prefix}" + assert not (home and prefix), f"home={home} prefix={prefix}" + i.user = user or i.user + if user or home: + i.prefix = "" + i.prefix = prefix or i.prefix + i.home = home or i.home + i.root = root or i.root + i.finalize_options() + + scheme: Dict[str, str] = {} + for key in SCHEME_KEYS: + scheme[key] = getattr(i, "install_" + key) + + # install_lib specified in setup.cfg should install *everything* + # into there (i.e. it takes precedence over both purelib and + # platlib). Note, i.install_lib is *always* set after + # finalize_options(); we only want to override here if the user + # has explicitly requested it hence going back to the config + if "install_lib" in d.get_option_dict("install"): + scheme.update({"purelib": i.install_lib, "platlib": i.install_lib}) + + if running_under_virtualenv(): + if home: + prefix = home + elif user: + prefix = i.install_userbase + else: + prefix = i.prefix + scheme["headers"] = os.path.join( + prefix, + "include", + "site", + f"python{get_major_minor_version()}", + dist_name, + ) + + if root is not None: + path_no_drive = os.path.splitdrive(os.path.abspath(scheme["headers"]))[1] + scheme["headers"] = os.path.join(root, path_no_drive[1:]) + + return scheme + + +def get_scheme( + dist_name: str, + user: bool = False, + home: Optional[str] = None, + root: Optional[str] = None, + isolated: bool = False, + prefix: Optional[str] = None, +) -> Scheme: + """ + Get the "scheme" corresponding to the input parameters. The distutils + documentation provides the context for the available schemes: + https://docs.python.org/3/install/index.html#alternate-installation + + :param dist_name: the name of the package to retrieve the scheme for, used + in the headers scheme path + :param user: indicates to use the "user" scheme + :param home: indicates to use the "home" scheme and provides the base + directory for the same + :param root: root under which other directories are re-based + :param isolated: equivalent to --no-user-cfg, i.e. do not consider + ~/.pydistutils.cfg (posix) or ~/pydistutils.cfg (non-posix) for + scheme paths + :param prefix: indicates to use the "prefix" scheme and provides the + base directory for the same + """ + scheme = distutils_scheme(dist_name, user, home, root, isolated, prefix) + return Scheme( + platlib=scheme["platlib"], + purelib=scheme["purelib"], + headers=scheme["headers"], + scripts=scheme["scripts"], + data=scheme["data"], + ) + + +def get_bin_prefix() -> str: + # XXX: In old virtualenv versions, sys.prefix can contain '..' components, + # so we need to call normpath to eliminate them. + prefix = os.path.normpath(sys.prefix) + if WINDOWS: + bin_py = os.path.join(prefix, "Scripts") + # buildout uses 'bin' on Windows too? + if not os.path.exists(bin_py): + bin_py = os.path.join(prefix, "bin") + return bin_py + # Forcing to use /usr/local/bin for standard macOS framework installs + # Also log to ~/Library/Logs/ for use with the Console.app log viewer + if sys.platform[:6] == "darwin" and prefix[:16] == "/System/Library/": + return "/usr/local/bin" + return os.path.join(prefix, "bin") + + +def get_purelib() -> str: + return get_python_lib(plat_specific=False) + + +def get_platlib() -> str: + return get_python_lib(plat_specific=True) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/locations/_sysconfig.py b/backend/.venv/Lib/site-packages/pip/_internal/locations/_sysconfig.py new file mode 100644 index 0000000..ca860ea --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/locations/_sysconfig.py @@ -0,0 +1,214 @@ +import logging +import os +import sys +import sysconfig +import typing + +from pip._internal.exceptions import InvalidSchemeCombination, UserInstallationInvalid +from pip._internal.models.scheme import SCHEME_KEYS, Scheme +from pip._internal.utils.virtualenv import running_under_virtualenv + +from .base import change_root, get_major_minor_version, is_osx_framework + +logger = logging.getLogger(__name__) + + +# Notes on _infer_* functions. +# Unfortunately ``get_default_scheme()`` didn't exist before 3.10, so there's no +# way to ask things like "what is the '_prefix' scheme on this platform". These +# functions try to answer that with some heuristics while accounting for ad-hoc +# platforms not covered by CPython's default sysconfig implementation. If the +# ad-hoc implementation does not fully implement sysconfig, we'll fall back to +# a POSIX scheme. + +_AVAILABLE_SCHEMES = set(sysconfig.get_scheme_names()) + +_PREFERRED_SCHEME_API = getattr(sysconfig, "get_preferred_scheme", None) + + +def _should_use_osx_framework_prefix() -> bool: + """Check for Apple's ``osx_framework_library`` scheme. + + Python distributed by Apple's Command Line Tools has this special scheme + that's used when: + + * This is a framework build. + * We are installing into the system prefix. + + This does not account for ``pip install --prefix`` (also means we're not + installing to the system prefix), which should use ``posix_prefix``, but + logic here means ``_infer_prefix()`` outputs ``osx_framework_library``. But + since ``prefix`` is not available for ``sysconfig.get_default_scheme()``, + which is the stdlib replacement for ``_infer_prefix()``, presumably Apple + wouldn't be able to magically switch between ``osx_framework_library`` and + ``posix_prefix``. ``_infer_prefix()`` returning ``osx_framework_library`` + means its behavior is consistent whether we use the stdlib implementation + or our own, and we deal with this special case in ``get_scheme()`` instead. + """ + return ( + "osx_framework_library" in _AVAILABLE_SCHEMES + and not running_under_virtualenv() + and is_osx_framework() + ) + + +def _infer_prefix() -> str: + """Try to find a prefix scheme for the current platform. + + This tries: + + * A special ``osx_framework_library`` for Python distributed by Apple's + Command Line Tools, when not running in a virtual environment. + * Implementation + OS, used by PyPy on Windows (``pypy_nt``). + * Implementation without OS, used by PyPy on POSIX (``pypy``). + * OS + "prefix", used by CPython on POSIX (``posix_prefix``). + * Just the OS name, used by CPython on Windows (``nt``). + + If none of the above works, fall back to ``posix_prefix``. + """ + if _PREFERRED_SCHEME_API: + return _PREFERRED_SCHEME_API("prefix") + if _should_use_osx_framework_prefix(): + return "osx_framework_library" + implementation_suffixed = f"{sys.implementation.name}_{os.name}" + if implementation_suffixed in _AVAILABLE_SCHEMES: + return implementation_suffixed + if sys.implementation.name in _AVAILABLE_SCHEMES: + return sys.implementation.name + suffixed = f"{os.name}_prefix" + if suffixed in _AVAILABLE_SCHEMES: + return suffixed + if os.name in _AVAILABLE_SCHEMES: # On Windows, prefx is just called "nt". + return os.name + return "posix_prefix" + + +def _infer_user() -> str: + """Try to find a user scheme for the current platform.""" + if _PREFERRED_SCHEME_API: + return _PREFERRED_SCHEME_API("user") + if is_osx_framework() and not running_under_virtualenv(): + suffixed = "osx_framework_user" + else: + suffixed = f"{os.name}_user" + if suffixed in _AVAILABLE_SCHEMES: + return suffixed + if "posix_user" not in _AVAILABLE_SCHEMES: # User scheme unavailable. + raise UserInstallationInvalid() + return "posix_user" + + +def _infer_home() -> str: + """Try to find a home for the current platform.""" + if _PREFERRED_SCHEME_API: + return _PREFERRED_SCHEME_API("home") + suffixed = f"{os.name}_home" + if suffixed in _AVAILABLE_SCHEMES: + return suffixed + return "posix_home" + + +# Update these keys if the user sets a custom home. +_HOME_KEYS = [ + "installed_base", + "base", + "installed_platbase", + "platbase", + "prefix", + "exec_prefix", +] +if sysconfig.get_config_var("userbase") is not None: + _HOME_KEYS.append("userbase") + + +def get_scheme( + dist_name: str, + user: bool = False, + home: typing.Optional[str] = None, + root: typing.Optional[str] = None, + isolated: bool = False, + prefix: typing.Optional[str] = None, +) -> Scheme: + """ + Get the "scheme" corresponding to the input parameters. + + :param dist_name: the name of the package to retrieve the scheme for, used + in the headers scheme path + :param user: indicates to use the "user" scheme + :param home: indicates to use the "home" scheme + :param root: root under which other directories are re-based + :param isolated: ignored, but kept for distutils compatibility (where + this controls whether the user-site pydistutils.cfg is honored) + :param prefix: indicates to use the "prefix" scheme and provides the + base directory for the same + """ + if user and prefix: + raise InvalidSchemeCombination("--user", "--prefix") + if home and prefix: + raise InvalidSchemeCombination("--home", "--prefix") + + if home is not None: + scheme_name = _infer_home() + elif user: + scheme_name = _infer_user() + else: + scheme_name = _infer_prefix() + + # Special case: When installing into a custom prefix, use posix_prefix + # instead of osx_framework_library. See _should_use_osx_framework_prefix() + # docstring for details. + if prefix is not None and scheme_name == "osx_framework_library": + scheme_name = "posix_prefix" + + if home is not None: + variables = {k: home for k in _HOME_KEYS} + elif prefix is not None: + variables = {k: prefix for k in _HOME_KEYS} + else: + variables = {} + + paths = sysconfig.get_paths(scheme=scheme_name, vars=variables) + + # Logic here is very arbitrary, we're doing it for compatibility, don't ask. + # 1. Pip historically uses a special header path in virtual environments. + # 2. If the distribution name is not known, distutils uses 'UNKNOWN'. We + # only do the same when not running in a virtual environment because + # pip's historical header path logic (see point 1) did not do this. + if running_under_virtualenv(): + if user: + base = variables.get("userbase", sys.prefix) + else: + base = variables.get("base", sys.prefix) + python_xy = f"python{get_major_minor_version()}" + paths["include"] = os.path.join(base, "include", "site", python_xy) + elif not dist_name: + dist_name = "UNKNOWN" + + scheme = Scheme( + platlib=paths["platlib"], + purelib=paths["purelib"], + headers=os.path.join(paths["include"], dist_name), + scripts=paths["scripts"], + data=paths["data"], + ) + if root is not None: + converted_keys = {} + for key in SCHEME_KEYS: + converted_keys[key] = change_root(root, getattr(scheme, key)) + scheme = Scheme(**converted_keys) + return scheme + + +def get_bin_prefix() -> str: + # Forcing to use /usr/local/bin for standard macOS framework installs. + if sys.platform[:6] == "darwin" and sys.prefix[:16] == "/System/Library/": + return "/usr/local/bin" + return sysconfig.get_paths()["scripts"] + + +def get_purelib() -> str: + return sysconfig.get_paths()["purelib"] + + +def get_platlib() -> str: + return sysconfig.get_paths()["platlib"] diff --git a/backend/.venv/Lib/site-packages/pip/_internal/locations/base.py b/backend/.venv/Lib/site-packages/pip/_internal/locations/base.py new file mode 100644 index 0000000..3f9f896 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/locations/base.py @@ -0,0 +1,81 @@ +import functools +import os +import site +import sys +import sysconfig +import typing + +from pip._internal.exceptions import InstallationError +from pip._internal.utils import appdirs +from pip._internal.utils.virtualenv import running_under_virtualenv + +# Application Directories +USER_CACHE_DIR = appdirs.user_cache_dir("pip") + +# FIXME doesn't account for venv linked to global site-packages +site_packages: str = sysconfig.get_path("purelib") + + +def get_major_minor_version() -> str: + """ + Return the major-minor version of the current Python as a string, e.g. + "3.7" or "3.10". + """ + return "{}.{}".format(*sys.version_info) + + +def change_root(new_root: str, pathname: str) -> str: + """Return 'pathname' with 'new_root' prepended. + + If 'pathname' is relative, this is equivalent to os.path.join(new_root, pathname). + Otherwise, it requires making 'pathname' relative and then joining the + two, which is tricky on DOS/Windows and Mac OS. + + This is borrowed from Python's standard library's distutils module. + """ + if os.name == "posix": + if not os.path.isabs(pathname): + return os.path.join(new_root, pathname) + else: + return os.path.join(new_root, pathname[1:]) + + elif os.name == "nt": + (drive, path) = os.path.splitdrive(pathname) + if path[0] == "\\": + path = path[1:] + return os.path.join(new_root, path) + + else: + raise InstallationError( + f"Unknown platform: {os.name}\n" + "Can not change root path prefix on unknown platform." + ) + + +def get_src_prefix() -> str: + if running_under_virtualenv(): + src_prefix = os.path.join(sys.prefix, "src") + else: + # FIXME: keep src in cwd for now (it is not a temporary folder) + try: + src_prefix = os.path.join(os.getcwd(), "src") + except OSError: + # In case the current working directory has been renamed or deleted + sys.exit("The folder you are executing pip from can no longer be found.") + + # under macOS + virtualenv sys.prefix is not properly resolved + # it is something like /path/to/python/bin/.. + return os.path.abspath(src_prefix) + + +try: + # Use getusersitepackages if this is present, as it ensures that the + # value is initialised properly. + user_site: typing.Optional[str] = site.getusersitepackages() +except AttributeError: + user_site = site.USER_SITE + + +@functools.lru_cache(maxsize=None) +def is_osx_framework() -> bool: + return bool(sysconfig.get_config_var("PYTHONFRAMEWORK")) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/main.py b/backend/.venv/Lib/site-packages/pip/_internal/main.py new file mode 100644 index 0000000..33c6d24 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/main.py @@ -0,0 +1,12 @@ +from typing import List, Optional + + +def main(args: Optional[List[str]] = None) -> int: + """This is preserved for old console scripts that may still be referencing + it. + + For additional details, see https://github.com/pypa/pip/issues/7498. + """ + from pip._internal.utils.entrypoints import _wrapper + + return _wrapper(args) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/metadata/__init__.py b/backend/.venv/Lib/site-packages/pip/_internal/metadata/__init__.py new file mode 100644 index 0000000..aa232b6 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/metadata/__init__.py @@ -0,0 +1,128 @@ +import contextlib +import functools +import os +import sys +from typing import TYPE_CHECKING, List, Optional, Type, cast + +from pip._internal.utils.misc import strtobool + +from .base import BaseDistribution, BaseEnvironment, FilesystemWheel, MemoryWheel, Wheel + +if TYPE_CHECKING: + from typing import Literal, Protocol +else: + Protocol = object + +__all__ = [ + "BaseDistribution", + "BaseEnvironment", + "FilesystemWheel", + "MemoryWheel", + "Wheel", + "get_default_environment", + "get_environment", + "get_wheel_distribution", + "select_backend", +] + + +def _should_use_importlib_metadata() -> bool: + """Whether to use the ``importlib.metadata`` or ``pkg_resources`` backend. + + By default, pip uses ``importlib.metadata`` on Python 3.11+, and + ``pkg_resourcess`` otherwise. This can be overridden by a couple of ways: + + * If environment variable ``_PIP_USE_IMPORTLIB_METADATA`` is set, it + dictates whether ``importlib.metadata`` is used, regardless of Python + version. + * On Python 3.11+, Python distributors can patch ``importlib.metadata`` + to add a global constant ``_PIP_USE_IMPORTLIB_METADATA = False``. This + makes pip use ``pkg_resources`` (unless the user set the aforementioned + environment variable to *True*). + """ + with contextlib.suppress(KeyError, ValueError): + return bool(strtobool(os.environ["_PIP_USE_IMPORTLIB_METADATA"])) + if sys.version_info < (3, 11): + return False + import importlib.metadata + + return bool(getattr(importlib.metadata, "_PIP_USE_IMPORTLIB_METADATA", True)) + + +class Backend(Protocol): + NAME: 'Literal["importlib", "pkg_resources"]' + Distribution: Type[BaseDistribution] + Environment: Type[BaseEnvironment] + + +@functools.lru_cache(maxsize=None) +def select_backend() -> Backend: + if _should_use_importlib_metadata(): + from . import importlib + + return cast(Backend, importlib) + from . import pkg_resources + + return cast(Backend, pkg_resources) + + +def get_default_environment() -> BaseEnvironment: + """Get the default representation for the current environment. + + This returns an Environment instance from the chosen backend. The default + Environment instance should be built from ``sys.path`` and may use caching + to share instance state accorss calls. + """ + return select_backend().Environment.default() + + +def get_environment(paths: Optional[List[str]]) -> BaseEnvironment: + """Get a representation of the environment specified by ``paths``. + + This returns an Environment instance from the chosen backend based on the + given import paths. The backend must build a fresh instance representing + the state of installed distributions when this function is called. + """ + return select_backend().Environment.from_paths(paths) + + +def get_directory_distribution(directory: str) -> BaseDistribution: + """Get the distribution metadata representation in the specified directory. + + This returns a Distribution instance from the chosen backend based on + the given on-disk ``.dist-info`` directory. + """ + return select_backend().Distribution.from_directory(directory) + + +def get_wheel_distribution(wheel: Wheel, canonical_name: str) -> BaseDistribution: + """Get the representation of the specified wheel's distribution metadata. + + This returns a Distribution instance from the chosen backend based on + the given wheel's ``.dist-info`` directory. + + :param canonical_name: Normalized project name of the given wheel. + """ + return select_backend().Distribution.from_wheel(wheel, canonical_name) + + +def get_metadata_distribution( + metadata_contents: bytes, + filename: str, + canonical_name: str, +) -> BaseDistribution: + """Get the dist representation of the specified METADATA file contents. + + This returns a Distribution instance from the chosen backend sourced from the data + in `metadata_contents`. + + :param metadata_contents: Contents of a METADATA file within a dist, or one served + via PEP 658. + :param filename: Filename for the dist this metadata represents. + :param canonical_name: Normalized project name of the given dist. + """ + return select_backend().Distribution.from_metadata_file_contents( + metadata_contents, + filename, + canonical_name, + ) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3f7f81a4500fbfcb5c96749d0a7c2bd14342adf3 GIT binary patch literal 5871 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/metadata/__pycache__/_json.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/metadata/__pycache__/_json.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d9641d2602256b32558230d14eacd89d17b6b08f GIT binary patch literal 2928 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 Mdee_Myx4gCf1UHg>Hq)$ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..05941bfac1383f15eaf9fb1158c6d06031c6a17d GIT binary patch literal 16086 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 a-IDY4J!Y`*_$0TT9l1X8PYgULt^Pk9WbyU@ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/metadata/_json.py b/backend/.venv/Lib/site-packages/pip/_internal/metadata/_json.py new file mode 100644 index 0000000..9097dd5 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/metadata/_json.py @@ -0,0 +1,84 @@ +# Extracted from https://github.com/pfmoore/pkg_metadata + +from email.header import Header, decode_header, make_header +from email.message import Message +from typing import Any, Dict, List, Union, cast + +METADATA_FIELDS = [ + # Name, Multiple-Use + ("Metadata-Version", False), + ("Name", False), + ("Version", False), + ("Dynamic", True), + ("Platform", True), + ("Supported-Platform", True), + ("Summary", False), + ("Description", False), + ("Description-Content-Type", False), + ("Keywords", False), + ("Home-page", False), + ("Download-URL", False), + ("Author", False), + ("Author-email", False), + ("Maintainer", False), + ("Maintainer-email", False), + ("License", False), + ("Classifier", True), + ("Requires-Dist", True), + ("Requires-Python", False), + ("Requires-External", True), + ("Project-URL", True), + ("Provides-Extra", True), + ("Provides-Dist", True), + ("Obsoletes-Dist", True), +] + + +def json_name(field: str) -> str: + return field.lower().replace("-", "_") + + +def msg_to_json(msg: Message) -> Dict[str, Any]: + """Convert a Message object into a JSON-compatible dictionary.""" + + def sanitise_header(h: Union[Header, str]) -> str: + if isinstance(h, Header): + chunks = [] + for bytes, encoding in decode_header(h): + if encoding == "unknown-8bit": + try: + # See if UTF-8 works + bytes.decode("utf-8") + encoding = "utf-8" + except UnicodeDecodeError: + # If not, latin1 at least won't fail + encoding = "latin1" + chunks.append((bytes, encoding)) + return str(make_header(chunks)) + return str(h) + + result = {} + for field, multi in METADATA_FIELDS: + if field not in msg: + continue + key = json_name(field) + if multi: + value: Union[str, List[str]] = [ + sanitise_header(v) for v in msg.get_all(field) # type: ignore + ] + else: + value = sanitise_header(msg.get(field)) # type: ignore + if key == "keywords": + # Accept both comma-separated and space-separated + # forms, for better compatibility with old data. + if "," in value: + value = [v.strip() for v in value.split(",")] + else: + value = value.split() + result[key] = value + + payload = cast(str, msg.get_payload()) + if payload: + result["description"] = payload + + return result diff --git a/backend/.venv/Lib/site-packages/pip/_internal/metadata/base.py b/backend/.venv/Lib/site-packages/pip/_internal/metadata/base.py new file mode 100644 index 0000000..9eabcdb --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/metadata/base.py @@ -0,0 +1,688 @@ +import csv +import email.message +import functools +import json +import logging +import pathlib +import re +import zipfile +from typing import ( + IO, + Any, + Collection, + Container, + Dict, + Iterable, + Iterator, + List, + NamedTuple, + Optional, + Protocol, + Tuple, + Union, +) + +from pip._vendor.packaging.requirements import Requirement +from pip._vendor.packaging.specifiers import InvalidSpecifier, SpecifierSet +from pip._vendor.packaging.utils import NormalizedName, canonicalize_name +from pip._vendor.packaging.version import Version + +from pip._internal.exceptions import NoneMetadataError +from pip._internal.locations import site_packages, user_site +from pip._internal.models.direct_url import ( + DIRECT_URL_METADATA_NAME, + DirectUrl, + DirectUrlValidationError, +) +from pip._internal.utils.compat import stdlib_pkgs # TODO: Move definition here. +from pip._internal.utils.egg_link import egg_link_path_from_sys_path +from pip._internal.utils.misc import is_local, normalize_path +from pip._internal.utils.urls import url_to_path + +from ._json import msg_to_json + +InfoPath = Union[str, pathlib.PurePath] + +logger = logging.getLogger(__name__) + + +class BaseEntryPoint(Protocol): + @property + def name(self) -> str: + raise NotImplementedError() + + @property + def value(self) -> str: + raise NotImplementedError() + + @property + def group(self) -> str: + raise NotImplementedError() + + +def _convert_installed_files_path( + entry: Tuple[str, ...], + info: Tuple[str, ...], +) -> str: + """Convert a legacy installed-files.txt path into modern RECORD path. + + The legacy format stores paths relative to the info directory, while the + modern format stores paths relative to the package root, e.g. the + site-packages directory. + + :param entry: Path parts of the installed-files.txt entry. + :param info: Path parts of the egg-info directory relative to package root. + :returns: The converted entry. + + For best compatibility with symlinks, this does not use ``abspath()`` or + ``Path.resolve()``, but tries to work with path parts: + + 1. While ``entry`` starts with ``..``, remove the equal amounts of parts + from ``info``; if ``info`` is empty, start appending ``..`` instead. + 2. Join the two directly. + """ + while entry and entry[0] == "..": + if not info or info[-1] == "..": + info += ("..",) + else: + info = info[:-1] + entry = entry[1:] + return str(pathlib.Path(*info, *entry)) + + +class RequiresEntry(NamedTuple): + requirement: str + extra: str + marker: str + + +class BaseDistribution(Protocol): + @classmethod + def from_directory(cls, directory: str) -> "BaseDistribution": + """Load the distribution from a metadata directory. + + :param directory: Path to a metadata directory, e.g. ``.dist-info``. + """ + raise NotImplementedError() + + @classmethod + def from_metadata_file_contents( + cls, + metadata_contents: bytes, + filename: str, + project_name: str, + ) -> "BaseDistribution": + """Load the distribution from the contents of a METADATA file. + + This is used to implement PEP 658 by generating a "shallow" dist object that can + be used for resolution without downloading or building the actual dist yet. + + :param metadata_contents: The contents of a METADATA file. + :param filename: File name for the dist with this metadata. + :param project_name: Name of the project this dist represents. + """ + raise NotImplementedError() + + @classmethod + def from_wheel(cls, wheel: "Wheel", name: str) -> "BaseDistribution": + """Load the distribution from a given wheel. + + :param wheel: A concrete wheel definition. + :param name: File name of the wheel. + + :raises InvalidWheel: Whenever loading of the wheel causes a + :py:exc:`zipfile.BadZipFile` exception to be thrown. + :raises UnsupportedWheel: If the wheel is a valid zip, but malformed + internally. + """ + raise NotImplementedError() + + def __repr__(self) -> str: + return f"{self.raw_name} {self.raw_version} ({self.location})" + + def __str__(self) -> str: + return f"{self.raw_name} {self.raw_version}" + + @property + def location(self) -> Optional[str]: + """Where the distribution is loaded from. + + A string value is not necessarily a filesystem path, since distributions + can be loaded from other sources, e.g. arbitrary zip archives. ``None`` + means the distribution is created in-memory. + + Do not canonicalize this value with e.g. ``pathlib.Path.resolve()``. If + this is a symbolic link, we want to preserve the relative path between + it and files in the distribution. + """ + raise NotImplementedError() + + @property + def editable_project_location(self) -> Optional[str]: + """The project location for editable distributions. + + This is the directory where pyproject.toml or setup.py is located. + None if the distribution is not installed in editable mode. + """ + # TODO: this property is relatively costly to compute, memoize it ? + direct_url = self.direct_url + if direct_url: + if direct_url.is_local_editable(): + return url_to_path(direct_url.url) + else: + # Search for an .egg-link file by walking sys.path, as it was + # done before by dist_is_editable(). + egg_link_path = egg_link_path_from_sys_path(self.raw_name) + if egg_link_path: + # TODO: get project location from second line of egg_link file + # (https://github.com/pypa/pip/issues/10243) + return self.location + return None + + @property + def installed_location(self) -> Optional[str]: + """The distribution's "installed" location. + + This should generally be a ``site-packages`` directory. This is + usually ``dist.location``, except for legacy develop-installed packages, + where ``dist.location`` is the source code location, and this is where + the ``.egg-link`` file is. + + The returned location is normalized (in particular, with symlinks removed). + """ + raise NotImplementedError() + + @property + def info_location(self) -> Optional[str]: + """Location of the .[egg|dist]-info directory or file. + + Similarly to ``location``, a string value is not necessarily a + filesystem path. ``None`` means the distribution is created in-memory. + + For a modern .dist-info installation on disk, this should be something + like ``{location}/{raw_name}-{version}.dist-info``. + + Do not canonicalize this value with e.g. ``pathlib.Path.resolve()``. If + this is a symbolic link, we want to preserve the relative path between + it and other files in the distribution. + """ + raise NotImplementedError() + + @property + def installed_by_distutils(self) -> bool: + """Whether this distribution is installed with legacy distutils format. + + A distribution installed with "raw" distutils not patched by setuptools + uses one single file at ``info_location`` to store metadata. We need to + treat this specially on uninstallation. + """ + info_location = self.info_location + if not info_location: + return False + return pathlib.Path(info_location).is_file() + + @property + def installed_as_egg(self) -> bool: + """Whether this distribution is installed as an egg. + + This usually indicates the distribution was installed by (older versions + of) easy_install. + """ + location = self.location + if not location: + return False + return location.endswith(".egg") + + @property + def installed_with_setuptools_egg_info(self) -> bool: + """Whether this distribution is installed with the ``.egg-info`` format. + + This usually indicates the distribution was installed with setuptools + with an old pip version or with ``single-version-externally-managed``. + + Note that this ensure the metadata store is a directory. distutils can + also installs an ``.egg-info``, but as a file, not a directory. This + property is *False* for that case. Also see ``installed_by_distutils``. + """ + info_location = self.info_location + if not info_location: + return False + if not info_location.endswith(".egg-info"): + return False + return pathlib.Path(info_location).is_dir() + + @property + def installed_with_dist_info(self) -> bool: + """Whether this distribution is installed with the "modern format". + + This indicates a "modern" installation, e.g. storing metadata in the + ``.dist-info`` directory. This applies to installations made by + setuptools (but through pip, not directly), or anything using the + standardized build backend interface (PEP 517). + """ + info_location = self.info_location + if not info_location: + return False + if not info_location.endswith(".dist-info"): + return False + return pathlib.Path(info_location).is_dir() + + @property + def canonical_name(self) -> NormalizedName: + raise NotImplementedError() + + @property + def version(self) -> Version: + raise NotImplementedError() + + @property + def raw_version(self) -> str: + raise NotImplementedError() + + @property + def setuptools_filename(self) -> str: + """Convert a project name to its setuptools-compatible filename. + + This is a copy of ``pkg_resources.to_filename()`` for compatibility. + """ + return self.raw_name.replace("-", "_") + + @property + def direct_url(self) -> Optional[DirectUrl]: + """Obtain a DirectUrl from this distribution. + + Returns None if the distribution has no `direct_url.json` metadata, + or if `direct_url.json` is invalid. + """ + try: + content = self.read_text(DIRECT_URL_METADATA_NAME) + except FileNotFoundError: + return None + try: + return DirectUrl.from_json(content) + except ( + UnicodeDecodeError, + json.JSONDecodeError, + DirectUrlValidationError, + ) as e: + logger.warning( + "Error parsing %s for %s: %s", + DIRECT_URL_METADATA_NAME, + self.canonical_name, + e, + ) + return None + + @property + def installer(self) -> str: + try: + installer_text = self.read_text("INSTALLER") + except (OSError, ValueError, NoneMetadataError): + return "" # Fail silently if the installer file cannot be read. + for line in installer_text.splitlines(): + cleaned_line = line.strip() + if cleaned_line: + return cleaned_line + return "" + + @property + def requested(self) -> bool: + return self.is_file("REQUESTED") + + @property + def editable(self) -> bool: + return bool(self.editable_project_location) + + @property + def local(self) -> bool: + """If distribution is installed in the current virtual environment. + + Always True if we're not in a virtualenv. + """ + if self.installed_location is None: + return False + return is_local(self.installed_location) + + @property + def in_usersite(self) -> bool: + if self.installed_location is None or user_site is None: + return False + return self.installed_location.startswith(normalize_path(user_site)) + + @property + def in_site_packages(self) -> bool: + if self.installed_location is None or site_packages is None: + return False + return self.installed_location.startswith(normalize_path(site_packages)) + + def is_file(self, path: InfoPath) -> bool: + """Check whether an entry in the info directory is a file.""" + raise NotImplementedError() + + def iter_distutils_script_names(self) -> Iterator[str]: + """Find distutils 'scripts' entries metadata. + + If 'scripts' is supplied in ``setup.py``, distutils records those in the + installed distribution's ``scripts`` directory, a file for each script. + """ + raise NotImplementedError() + + def read_text(self, path: InfoPath) -> str: + """Read a file in the info directory. + + :raise FileNotFoundError: If ``path`` does not exist in the directory. + :raise NoneMetadataError: If ``path`` exists in the info directory, but + cannot be read. + """ + raise NotImplementedError() + + def iter_entry_points(self) -> Iterable[BaseEntryPoint]: + raise NotImplementedError() + + def _metadata_impl(self) -> email.message.Message: + raise NotImplementedError() + + @functools.cached_property + def metadata(self) -> email.message.Message: + """Metadata of distribution parsed from e.g. METADATA or PKG-INFO. + + This should return an empty message if the metadata file is unavailable. + + :raises NoneMetadataError: If the metadata file is available, but does + not contain valid metadata. + """ + metadata = self._metadata_impl() + self._add_egg_info_requires(metadata) + return metadata + + @property + def metadata_dict(self) -> Dict[str, Any]: + """PEP 566 compliant JSON-serializable representation of METADATA or PKG-INFO. + + This should return an empty dict if the metadata file is unavailable. + + :raises NoneMetadataError: If the metadata file is available, but does + not contain valid metadata. + """ + return msg_to_json(self.metadata) + + @property + def metadata_version(self) -> Optional[str]: + """Value of "Metadata-Version:" in distribution metadata, if available.""" + return self.metadata.get("Metadata-Version") + + @property + def raw_name(self) -> str: + """Value of "Name:" in distribution metadata.""" + # The metadata should NEVER be missing the Name: key, but if it somehow + # does, fall back to the known canonical name. + return self.metadata.get("Name", self.canonical_name) + + @property + def requires_python(self) -> SpecifierSet: + """Value of "Requires-Python:" in distribution metadata. + + If the key does not exist or contains an invalid value, an empty + SpecifierSet should be returned. + """ + value = self.metadata.get("Requires-Python") + if value is None: + return SpecifierSet() + try: + # Convert to str to satisfy the type checker; this can be a Header object. + spec = SpecifierSet(str(value)) + except InvalidSpecifier as e: + message = "Package %r has an invalid Requires-Python: %s" + logger.warning(message, self.raw_name, e) + return SpecifierSet() + return spec + + def iter_dependencies(self, extras: Collection[str] = ()) -> Iterable[Requirement]: + """Dependencies of this distribution. + + For modern .dist-info distributions, this is the collection of + "Requires-Dist:" entries in distribution metadata. + """ + raise NotImplementedError() + + def iter_raw_dependencies(self) -> Iterable[str]: + """Raw Requires-Dist metadata.""" + return self.metadata.get_all("Requires-Dist", []) + + def iter_provided_extras(self) -> Iterable[NormalizedName]: + """Extras provided by this distribution. + + For modern .dist-info distributions, this is the collection of + "Provides-Extra:" entries in distribution metadata. + + The return value of this function is expected to be normalised names, + per PEP 685, with the returned value being handled appropriately by + `iter_dependencies`. + """ + raise NotImplementedError() + + def _iter_declared_entries_from_record(self) -> Optional[Iterator[str]]: + try: + text = self.read_text("RECORD") + except FileNotFoundError: + return None + # This extra Path-str cast normalizes entries. + return (str(pathlib.Path(row[0])) for row in csv.reader(text.splitlines())) + + def _iter_declared_entries_from_legacy(self) -> Optional[Iterator[str]]: + try: + text = self.read_text("installed-files.txt") + except FileNotFoundError: + return None + paths = (p for p in text.splitlines(keepends=False) if p) + root = self.location + info = self.info_location + if root is None or info is None: + return paths + try: + info_rel = pathlib.Path(info).relative_to(root) + except ValueError: # info is not relative to root. + return paths + if not info_rel.parts: # info *is* root. + return paths + return ( + _convert_installed_files_path(pathlib.Path(p).parts, info_rel.parts) + for p in paths + ) + + def iter_declared_entries(self) -> Optional[Iterator[str]]: + """Iterate through file entries declared in this distribution. + + For modern .dist-info distributions, this is the files listed in the + ``RECORD`` metadata file. For legacy setuptools distributions, this + comes from ``installed-files.txt``, with entries normalized to be + compatible with the format used by ``RECORD``. + + :return: An iterator for listed entries, or None if the distribution + contains neither ``RECORD`` nor ``installed-files.txt``. + """ + return ( + self._iter_declared_entries_from_record() + or self._iter_declared_entries_from_legacy() + ) + + def _iter_requires_txt_entries(self) -> Iterator[RequiresEntry]: + """Parse a ``requires.txt`` in an egg-info directory. + + This is an INI-ish format where an egg-info stores dependencies. A + section name describes extra other environment markers, while each entry + is an arbitrary string (not a key-value pair) representing a dependency + as a requirement string (no markers). + + There is a construct in ``importlib.metadata`` called ``Sectioned`` that + does mostly the same, but the format is currently considered private. + """ + try: + content = self.read_text("requires.txt") + except FileNotFoundError: + return + extra = marker = "" # Section-less entries don't have markers. + for line in content.splitlines(): + line = line.strip() + if not line or line.startswith("#"): # Comment; ignored. + continue + if line.startswith("[") and line.endswith("]"): # A section header. + extra, _, marker = line.strip("[]").partition(":") + continue + yield RequiresEntry(requirement=line, extra=extra, marker=marker) + + def _iter_egg_info_extras(self) -> Iterable[str]: + """Get extras from the egg-info directory.""" + known_extras = {""} + for entry in self._iter_requires_txt_entries(): + extra = canonicalize_name(entry.extra) + if extra in known_extras: + continue + known_extras.add(extra) + yield extra + + def _iter_egg_info_dependencies(self) -> Iterable[str]: + """Get distribution dependencies from the egg-info directory. + + To ease parsing, this converts a legacy dependency entry into a PEP 508 + requirement string. Like ``_iter_requires_txt_entries()``, there is code + in ``importlib.metadata`` that does mostly the same, but not do exactly + what we need. + + Namely, ``importlib.metadata`` does not normalize the extra name before + putting it into the requirement string, which causes marker comparison + to fail because the dist-info format do normalize. This is consistent in + all currently available PEP 517 backends, although not standardized. + """ + for entry in self._iter_requires_txt_entries(): + extra = canonicalize_name(entry.extra) + if extra and entry.marker: + marker = f'({entry.marker}) and extra == "{extra}"' + elif extra: + marker = f'extra == "{extra}"' + elif entry.marker: + marker = entry.marker + else: + marker = "" + if marker: + yield f"{entry.requirement} ; {marker}" + else: + yield entry.requirement + + def _add_egg_info_requires(self, metadata: email.message.Message) -> None: + """Add egg-info requires.txt information to the metadata.""" + if not metadata.get_all("Requires-Dist"): + for dep in self._iter_egg_info_dependencies(): + metadata["Requires-Dist"] = dep + if not metadata.get_all("Provides-Extra"): + for extra in self._iter_egg_info_extras(): + metadata["Provides-Extra"] = extra + + +class BaseEnvironment: + """An environment containing distributions to introspect.""" + + @classmethod + def default(cls) -> "BaseEnvironment": + raise NotImplementedError() + + @classmethod + def from_paths(cls, paths: Optional[List[str]]) -> "BaseEnvironment": + raise NotImplementedError() + + def get_distribution(self, name: str) -> Optional["BaseDistribution"]: + """Given a requirement name, return the installed distributions. + + The name may not be normalized. The implementation must canonicalize + it for lookup. + """ + raise NotImplementedError() + + def _iter_distributions(self) -> Iterator["BaseDistribution"]: + """Iterate through installed distributions. + + This function should be implemented by subclass, but never called + directly. Use the public ``iter_distribution()`` instead, which + implements additional logic to make sure the distributions are valid. + """ + raise NotImplementedError() + + def iter_all_distributions(self) -> Iterator[BaseDistribution]: + """Iterate through all installed distributions without any filtering.""" + for dist in self._iter_distributions(): + # Make sure the distribution actually comes from a valid Python + # packaging distribution. Pip's AdjacentTempDirectory leaves folders + # e.g. ``~atplotlib.dist-info`` if cleanup was interrupted. The + # valid project name pattern is taken from PEP 508. + project_name_valid = re.match( + r"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$", + dist.canonical_name, + flags=re.IGNORECASE, + ) + if not project_name_valid: + logger.warning( + "Ignoring invalid distribution %s (%s)", + dist.canonical_name, + dist.location, + ) + continue + yield dist + + def iter_installed_distributions( + self, + local_only: bool = True, + skip: Container[str] = stdlib_pkgs, + include_editables: bool = True, + editables_only: bool = False, + user_only: bool = False, + ) -> Iterator[BaseDistribution]: + """Return a list of installed distributions. + + This is based on ``iter_all_distributions()`` with additional filtering + options. Note that ``iter_installed_distributions()`` without arguments + is *not* equal to ``iter_all_distributions()``, since some of the + configurations exclude packages by default. + + :param local_only: If True (default), only return installations + local to the current virtualenv, if in a virtualenv. + :param skip: An iterable of canonicalized project names to ignore; + defaults to ``stdlib_pkgs``. + :param include_editables: If False, don't report editables. + :param editables_only: If True, only report editables. + :param user_only: If True, only report installations in the user + site directory. + """ + it = self.iter_all_distributions() + if local_only: + it = (d for d in it if d.local) + if not include_editables: + it = (d for d in it if not d.editable) + if editables_only: + it = (d for d in it if d.editable) + if user_only: + it = (d for d in it if d.in_usersite) + return (d for d in it if d.canonical_name not in skip) + + +class Wheel(Protocol): + location: str + + def as_zipfile(self) -> zipfile.ZipFile: + raise NotImplementedError() + + +class FilesystemWheel(Wheel): + def __init__(self, location: str) -> None: + self.location = location + + def as_zipfile(self) -> zipfile.ZipFile: + return zipfile.ZipFile(self.location, allowZip64=True) + + +class MemoryWheel(Wheel): + def __init__(self, location: str, stream: IO[bytes]) -> None: + self.location = location + self.stream = stream + + def as_zipfile(self) -> zipfile.ZipFile: + return zipfile.ZipFile(self.stream, allowZip64=True) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/metadata/importlib/__init__.py b/backend/.venv/Lib/site-packages/pip/_internal/metadata/importlib/__init__.py new file mode 100644 index 0000000..a779138 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/metadata/importlib/__init__.py @@ -0,0 +1,6 @@ +from ._dists import Distribution +from ._envs import Environment + +__all__ = ["NAME", "Distribution", "Environment"] + +NAME = "importlib" diff --git a/backend/.venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cd98eb99f900f355816196595f3ff3915e9892ea GIT binary patch literal 360 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_dists.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_dists.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..def5403d378c757759bdb545e824662e2f7ecc60 GIT binary patch literal 12567 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/metadata/importlib/_compat.py b/backend/.venv/Lib/site-packages/pip/_internal/metadata/importlib/_compat.py new file mode 100644 index 0000000..ec1e815 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/metadata/importlib/_compat.py @@ -0,0 +1,85 @@ +import importlib.metadata +import os +from typing import Any, Optional, Protocol, Tuple, cast + +from pip._vendor.packaging.utils import NormalizedName, canonicalize_name + + +class BadMetadata(ValueError): + def __init__(self, dist: importlib.metadata.Distribution, *, reason: str) -> None: + self.dist = dist + self.reason = reason + + def __str__(self) -> str: + return f"Bad metadata in {self.dist} ({self.reason})" + + +class BasePath(Protocol): + """A protocol that various path objects conform. + + This exists because importlib.metadata uses both ``pathlib.Path`` and + ``zipfile.Path``, and we need a common base for type hints (Union does not + work well since ``zipfile.Path`` is too new for our linter setup). + + This does not mean to be exhaustive, but only contains things that present + in both classes *that we need*. + """ + + @property + def name(self) -> str: + raise NotImplementedError() + + @property + def parent(self) -> "BasePath": + raise NotImplementedError() + + +def get_info_location(d: importlib.metadata.Distribution) -> Optional[BasePath]: + """Find the path to the distribution's metadata directory. + + HACK: This relies on importlib.metadata's private ``_path`` attribute. Not + all distributions exist on disk, so importlib.metadata is correct to not + expose the attribute as public. But pip's code base is old and not as clean, + so we do this to avoid having to rewrite too many things. Hopefully we can + eliminate this some day. + """ + return getattr(d, "_path", None) + + +def parse_name_and_version_from_info_directory( + dist: importlib.metadata.Distribution, +) -> Tuple[Optional[str], Optional[str]]: + """Get a name and version from the metadata directory name. + + This is much faster than reading distribution metadata. + """ + info_location = get_info_location(dist) + if info_location is None: + return None, None + + stem, suffix = os.path.splitext(info_location.name) + if suffix == ".dist-info": + name, sep, version = stem.partition("-") + if sep: + return name, version + + if suffix == ".egg-info": + name = stem.split("-", 1)[0] + return name, None + + return None, None + + +def get_dist_canonical_name(dist: importlib.metadata.Distribution) -> NormalizedName: + """Get the distribution's normalized name. + + The ``name`` attribute is only available in Python 3.10 or later. We are + targeting exactly that, but Mypy does not know this. + """ + if name := parse_name_and_version_from_info_directory(dist)[0]: + return canonicalize_name(name) + + name = cast(Any, dist).name + if not isinstance(name, str): + raise BadMetadata(dist, reason="invalid metadata entry 'name'") + return canonicalize_name(name) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py b/backend/.venv/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py new file mode 100644 index 0000000..36cd326 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py @@ -0,0 +1,221 @@ +import email.message +import importlib.metadata +import pathlib +import zipfile +from typing import ( + Collection, + Dict, + Iterable, + Iterator, + Mapping, + Optional, + Sequence, + cast, +) + +from pip._vendor.packaging.requirements import Requirement +from pip._vendor.packaging.utils import NormalizedName, canonicalize_name +from pip._vendor.packaging.version import Version +from pip._vendor.packaging.version import parse as parse_version + +from pip._internal.exceptions import InvalidWheel, UnsupportedWheel +from pip._internal.metadata.base import ( + BaseDistribution, + BaseEntryPoint, + InfoPath, + Wheel, +) +from pip._internal.utils.misc import normalize_path +from pip._internal.utils.packaging import get_requirement +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.wheel import parse_wheel, read_wheel_metadata_file + +from ._compat import ( + BasePath, + get_dist_canonical_name, + parse_name_and_version_from_info_directory, +) + + +class WheelDistribution(importlib.metadata.Distribution): + """An ``importlib.metadata.Distribution`` read from a wheel. + + Although ``importlib.metadata.PathDistribution`` accepts ``zipfile.Path``, + its implementation is too "lazy" for pip's needs (we can't keep the ZipFile + handle open for the entire lifetime of the distribution object). + + This implementation eagerly reads the entire metadata directory into the + memory instead, and operates from that. + """ + + def __init__( + self, + files: Mapping[pathlib.PurePosixPath, bytes], + info_location: pathlib.PurePosixPath, + ) -> None: + self._files = files + self.info_location = info_location + + @classmethod + def from_zipfile( + cls, + zf: zipfile.ZipFile, + name: str, + location: str, + ) -> "WheelDistribution": + info_dir, _ = parse_wheel(zf, name) + paths = ( + (name, pathlib.PurePosixPath(name.split("/", 1)[-1])) + for name in zf.namelist() + if name.startswith(f"{info_dir}/") + ) + files = { + relpath: read_wheel_metadata_file(zf, fullpath) + for fullpath, relpath in paths + } + info_location = pathlib.PurePosixPath(location, info_dir) + return cls(files, info_location) + + def iterdir(self, path: InfoPath) -> Iterator[pathlib.PurePosixPath]: + # Only allow iterating through the metadata directory. + if pathlib.PurePosixPath(str(path)) in self._files: + return iter(self._files) + raise FileNotFoundError(path) + + def read_text(self, filename: str) -> Optional[str]: + try: + data = self._files[pathlib.PurePosixPath(filename)] + except KeyError: + return None + try: + text = data.decode("utf-8") + except UnicodeDecodeError as e: + wheel = self.info_location.parent + error = f"Error decoding metadata for {wheel}: {e} in {filename} file" + raise UnsupportedWheel(error) + return text + + +class Distribution(BaseDistribution): + def __init__( + self, + dist: importlib.metadata.Distribution, + info_location: Optional[BasePath], + installed_location: Optional[BasePath], + ) -> None: + self._dist = dist + self._info_location = info_location + self._installed_location = installed_location + + @classmethod + def from_directory(cls, directory: str) -> BaseDistribution: + info_location = pathlib.Path(directory) + dist = importlib.metadata.Distribution.at(info_location) + return cls(dist, info_location, info_location.parent) + + @classmethod + def from_metadata_file_contents( + cls, + metadata_contents: bytes, + filename: str, + project_name: str, + ) -> BaseDistribution: + # Generate temp dir to contain the metadata file, and write the file contents. + temp_dir = pathlib.Path( + TempDirectory(kind="metadata", globally_managed=True).path + ) + metadata_path = temp_dir / "METADATA" + metadata_path.write_bytes(metadata_contents) + # Construct dist pointing to the newly created directory. + dist = importlib.metadata.Distribution.at(metadata_path.parent) + return cls(dist, metadata_path.parent, None) + + @classmethod + def from_wheel(cls, wheel: Wheel, name: str) -> BaseDistribution: + try: + with wheel.as_zipfile() as zf: + dist = WheelDistribution.from_zipfile(zf, name, wheel.location) + except zipfile.BadZipFile as e: + raise InvalidWheel(wheel.location, name) from e + return cls(dist, dist.info_location, pathlib.PurePosixPath(wheel.location)) + + @property + def location(self) -> Optional[str]: + if self._info_location is None: + return None + return str(self._info_location.parent) + + @property + def info_location(self) -> Optional[str]: + if self._info_location is None: + return None + return str(self._info_location) + + @property + def installed_location(self) -> Optional[str]: + if self._installed_location is None: + return None + return normalize_path(str(self._installed_location)) + + @property + def canonical_name(self) -> NormalizedName: + return get_dist_canonical_name(self._dist) + + @property + def version(self) -> Version: + if version := parse_name_and_version_from_info_directory(self._dist)[1]: + return parse_version(version) + return parse_version(self._dist.version) + + @property + def raw_version(self) -> str: + return self._dist.version + + def is_file(self, path: InfoPath) -> bool: + return self._dist.read_text(str(path)) is not None + + def iter_distutils_script_names(self) -> Iterator[str]: + # A distutils installation is always "flat" (not in e.g. egg form), so + # if this distribution's info location is NOT a pathlib.Path (but e.g. + # zipfile.Path), it can never contain any distutils scripts. + if not isinstance(self._info_location, pathlib.Path): + return + for child in self._info_location.joinpath("scripts").iterdir(): + yield child.name + + def read_text(self, path: InfoPath) -> str: + content = self._dist.read_text(str(path)) + if content is None: + raise FileNotFoundError(path) + return content + + def iter_entry_points(self) -> Iterable[BaseEntryPoint]: + # importlib.metadata's EntryPoint structure sasitfies BaseEntryPoint. + return self._dist.entry_points + + def _metadata_impl(self) -> email.message.Message: + # From Python 3.10+, importlib.metadata declares PackageMetadata as the + # return type. This protocol is unfortunately a disaster now and misses + # a ton of fields that we need, including get() and get_payload(). We + # rely on the implementation that the object is actually a Message now, + # until upstream can improve the protocol. (python/cpython#94952) + return cast(email.message.Message, self._dist.metadata) + + def iter_provided_extras(self) -> Iterable[NormalizedName]: + return [ + canonicalize_name(extra) + for extra in self.metadata.get_all("Provides-Extra", []) + ] + + def iter_dependencies(self, extras: Collection[str] = ()) -> Iterable[Requirement]: + contexts: Sequence[Dict[str, str]] = [{"extra": e} for e in extras] + for req_string in self.metadata.get_all("Requires-Dist", []): + # strip() because email.message.Message.get_all() may return a leading \n + # in case a long header was wrapped. + req = get_requirement(req_string.strip()) + if not req.marker: + yield req + elif not extras and req.marker.evaluate({"extra": ""}): + yield req + elif any(req.marker.evaluate(context) for context in contexts): + yield req diff --git a/backend/.venv/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py b/backend/.venv/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py new file mode 100644 index 0000000..4d906fd --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py @@ -0,0 +1,189 @@ +import functools +import importlib.metadata +import logging +import os +import pathlib +import sys +import zipfile +import zipimport +from typing import Iterator, List, Optional, Sequence, Set, Tuple + +from pip._vendor.packaging.utils import NormalizedName, canonicalize_name + +from pip._internal.metadata.base import BaseDistribution, BaseEnvironment +from pip._internal.models.wheel import Wheel +from pip._internal.utils.deprecation import deprecated +from pip._internal.utils.filetypes import WHEEL_EXTENSION + +from ._compat import BadMetadata, BasePath, get_dist_canonical_name, get_info_location +from ._dists import Distribution + +logger = logging.getLogger(__name__) + + +def _looks_like_wheel(location: str) -> bool: + if not location.endswith(WHEEL_EXTENSION): + return False + if not os.path.isfile(location): + return False + if not Wheel.wheel_file_re.match(os.path.basename(location)): + return False + return zipfile.is_zipfile(location) + + +class _DistributionFinder: + """Finder to locate distributions. + + The main purpose of this class is to memoize found distributions' names, so + only one distribution is returned for each package name. At lot of pip code + assumes this (because it is setuptools's behavior), and not doing the same + can potentially cause a distribution in lower precedence path to override a + higher precedence one if the caller is not careful. + + Eventually we probably want to make it possible to see lower precedence + installations as well. It's useful feature, after all. + """ + + FoundResult = Tuple[importlib.metadata.Distribution, Optional[BasePath]] + + def __init__(self) -> None: + self._found_names: Set[NormalizedName] = set() + + def _find_impl(self, location: str) -> Iterator[FoundResult]: + """Find distributions in a location.""" + # Skip looking inside a wheel. Since a package inside a wheel is not + # always valid (due to .data directories etc.), its .dist-info entry + # should not be considered an installed distribution. + if _looks_like_wheel(location): + return + # To know exactly where we find a distribution, we have to feed in the + # paths one by one, instead of dumping the list to importlib.metadata. + for dist in importlib.metadata.distributions(path=[location]): + info_location = get_info_location(dist) + try: + name = get_dist_canonical_name(dist) + except BadMetadata as e: + logger.warning("Skipping %s due to %s", info_location, e.reason) + continue + if name in self._found_names: + continue + self._found_names.add(name) + yield dist, info_location + + def find(self, location: str) -> Iterator[BaseDistribution]: + """Find distributions in a location. + + The path can be either a directory, or a ZIP archive. + """ + for dist, info_location in self._find_impl(location): + if info_location is None: + installed_location: Optional[BasePath] = None + else: + installed_location = info_location.parent + yield Distribution(dist, info_location, installed_location) + + def find_linked(self, location: str) -> Iterator[BaseDistribution]: + """Read location in egg-link files and return distributions in there. + + The path should be a directory; otherwise this returns nothing. This + follows how setuptools does this for compatibility. The first non-empty + line in the egg-link is read as a path (resolved against the egg-link's + containing directory if relative). Distributions found at that linked + location are returned. + """ + path = pathlib.Path(location) + if not path.is_dir(): + return + for child in path.iterdir(): + if child.suffix != ".egg-link": + continue + with child.open() as f: + lines = (line.strip() for line in f) + target_rel = next((line for line in lines if line), "") + if not target_rel: + continue + target_location = str(path.joinpath(target_rel)) + for dist, info_location in self._find_impl(target_location): + yield Distribution(dist, info_location, path) + + def _find_eggs_in_dir(self, location: str) -> Iterator[BaseDistribution]: + from pip._vendor.pkg_resources import find_distributions + + from pip._internal.metadata import pkg_resources as legacy + + with os.scandir(location) as it: + for entry in it: + if not entry.name.endswith(".egg"): + continue + for dist in find_distributions(entry.path): + yield legacy.Distribution(dist) + + def _find_eggs_in_zip(self, location: str) -> Iterator[BaseDistribution]: + from pip._vendor.pkg_resources import find_eggs_in_zip + + from pip._internal.metadata import pkg_resources as legacy + + try: + importer = zipimport.zipimporter(location) + except zipimport.ZipImportError: + return + for dist in find_eggs_in_zip(importer, location): + yield legacy.Distribution(dist) + + def find_eggs(self, location: str) -> Iterator[BaseDistribution]: + """Find eggs in a location. + + This actually uses the old *pkg_resources* backend. We likely want to + deprecate this so we can eventually remove the *pkg_resources* + dependency entirely. Before that, this should first emit a deprecation + warning for some versions when using the fallback since importing + *pkg_resources* is slow for those who don't need it. + """ + if os.path.isdir(location): + yield from self._find_eggs_in_dir(location) + if zipfile.is_zipfile(location): + yield from self._find_eggs_in_zip(location) + + +@functools.lru_cache(maxsize=None) # Warn a distribution exactly once. +def _emit_egg_deprecation(location: Optional[str]) -> None: + deprecated( + reason=f"Loading egg at {location} is deprecated.", + replacement="to use pip for package installation", + gone_in="25.1", + issue=12330, + ) + + +class Environment(BaseEnvironment): + def __init__(self, paths: Sequence[str]) -> None: + self._paths = paths + + @classmethod + def default(cls) -> BaseEnvironment: + return cls(sys.path) + + @classmethod + def from_paths(cls, paths: Optional[List[str]]) -> BaseEnvironment: + if paths is None: + return cls(sys.path) + return cls(paths) + + def _iter_distributions(self) -> Iterator[BaseDistribution]: + finder = _DistributionFinder() + for location in self._paths: + yield from finder.find(location) + for dist in finder.find_eggs(location): + _emit_egg_deprecation(dist.location) + yield dist + # This must go last because that's how pkg_resources tie-breaks. + yield from finder.find_linked(location) + + def get_distribution(self, name: str) -> Optional[BaseDistribution]: + canonical_name = canonicalize_name(name) + matches = ( + distribution + for distribution in self.iter_all_distributions() + if distribution.canonical_name == canonical_name + ) + return next(matches, None) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/metadata/pkg_resources.py b/backend/.venv/Lib/site-packages/pip/_internal/metadata/pkg_resources.py new file mode 100644 index 0000000..4ea84f9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/metadata/pkg_resources.py @@ -0,0 +1,301 @@ +import email.message +import email.parser +import logging +import os +import zipfile +from typing import ( + Collection, + Iterable, + Iterator, + List, + Mapping, + NamedTuple, + Optional, +) + +from pip._vendor import pkg_resources +from pip._vendor.packaging.requirements import Requirement +from pip._vendor.packaging.utils import NormalizedName, canonicalize_name +from pip._vendor.packaging.version import Version +from pip._vendor.packaging.version import parse as parse_version + +from pip._internal.exceptions import InvalidWheel, NoneMetadataError, UnsupportedWheel +from pip._internal.utils.egg_link import egg_link_path_from_location +from pip._internal.utils.misc import display_path, normalize_path +from pip._internal.utils.wheel import parse_wheel, read_wheel_metadata_file + +from .base import ( + BaseDistribution, + BaseEntryPoint, + BaseEnvironment, + InfoPath, + Wheel, +) + +__all__ = ["NAME", "Distribution", "Environment"] + +logger = logging.getLogger(__name__) + +NAME = "pkg_resources" + + +class EntryPoint(NamedTuple): + name: str + value: str + group: str + + +class InMemoryMetadata: + """IMetadataProvider that reads metadata files from a dictionary. + + This also maps metadata decoding exceptions to our internal exception type. + """ + + def __init__(self, metadata: Mapping[str, bytes], wheel_name: str) -> None: + self._metadata = metadata + self._wheel_name = wheel_name + + def has_metadata(self, name: str) -> bool: + return name in self._metadata + + def get_metadata(self, name: str) -> str: + try: + return self._metadata[name].decode() + except UnicodeDecodeError as e: + # Augment the default error with the origin of the file. + raise UnsupportedWheel( + f"Error decoding metadata for {self._wheel_name}: {e} in {name} file" + ) + + def get_metadata_lines(self, name: str) -> Iterable[str]: + return pkg_resources.yield_lines(self.get_metadata(name)) + + def metadata_isdir(self, name: str) -> bool: + return False + + def metadata_listdir(self, name: str) -> List[str]: + return [] + + def run_script(self, script_name: str, namespace: str) -> None: + pass + + +class Distribution(BaseDistribution): + def __init__(self, dist: pkg_resources.Distribution) -> None: + self._dist = dist + # This is populated lazily, to avoid loading metadata for all possible + # distributions eagerly. + self.__extra_mapping: Optional[Mapping[NormalizedName, str]] = None + + @property + def _extra_mapping(self) -> Mapping[NormalizedName, str]: + if self.__extra_mapping is None: + self.__extra_mapping = { + canonicalize_name(extra): extra for extra in self._dist.extras + } + + return self.__extra_mapping + + @classmethod + def from_directory(cls, directory: str) -> BaseDistribution: + dist_dir = directory.rstrip(os.sep) + + # Build a PathMetadata object, from path to metadata. :wink: + base_dir, dist_dir_name = os.path.split(dist_dir) + metadata = pkg_resources.PathMetadata(base_dir, dist_dir) + + # Determine the correct Distribution object type. + if dist_dir.endswith(".egg-info"): + dist_cls = pkg_resources.Distribution + dist_name = os.path.splitext(dist_dir_name)[0] + else: + assert dist_dir.endswith(".dist-info") + dist_cls = pkg_resources.DistInfoDistribution + dist_name = os.path.splitext(dist_dir_name)[0].split("-")[0] + + dist = dist_cls(base_dir, project_name=dist_name, metadata=metadata) + return cls(dist) + + @classmethod + def from_metadata_file_contents( + cls, + metadata_contents: bytes, + filename: str, + project_name: str, + ) -> BaseDistribution: + metadata_dict = { + "METADATA": metadata_contents, + } + dist = pkg_resources.DistInfoDistribution( + location=filename, + metadata=InMemoryMetadata(metadata_dict, filename), + project_name=project_name, + ) + return cls(dist) + + @classmethod + def from_wheel(cls, wheel: Wheel, name: str) -> BaseDistribution: + try: + with wheel.as_zipfile() as zf: + info_dir, _ = parse_wheel(zf, name) + metadata_dict = { + path.split("/", 1)[-1]: read_wheel_metadata_file(zf, path) + for path in zf.namelist() + if path.startswith(f"{info_dir}/") + } + except zipfile.BadZipFile as e: + raise InvalidWheel(wheel.location, name) from e + except UnsupportedWheel as e: + raise UnsupportedWheel(f"{name} has an invalid wheel, {e}") + dist = pkg_resources.DistInfoDistribution( + location=wheel.location, + metadata=InMemoryMetadata(metadata_dict, wheel.location), + project_name=name, + ) + return cls(dist) + + @property + def location(self) -> Optional[str]: + return self._dist.location + + @property + def installed_location(self) -> Optional[str]: + egg_link = egg_link_path_from_location(self.raw_name) + if egg_link: + location = egg_link + elif self.location: + location = self.location + else: + return None + return normalize_path(location) + + @property + def info_location(self) -> Optional[str]: + return self._dist.egg_info + + @property + def installed_by_distutils(self) -> bool: + # A distutils-installed distribution is provided by FileMetadata. This + # provider has a "path" attribute not present anywhere else. Not the + # best introspection logic, but pip has been doing this for a long time. + try: + return bool(self._dist._provider.path) + except AttributeError: + return False + + @property + def canonical_name(self) -> NormalizedName: + return canonicalize_name(self._dist.project_name) + + @property + def version(self) -> Version: + return parse_version(self._dist.version) + + @property + def raw_version(self) -> str: + return self._dist.version + + def is_file(self, path: InfoPath) -> bool: + return self._dist.has_metadata(str(path)) + + def iter_distutils_script_names(self) -> Iterator[str]: + yield from self._dist.metadata_listdir("scripts") + + def read_text(self, path: InfoPath) -> str: + name = str(path) + if not self._dist.has_metadata(name): + raise FileNotFoundError(name) + content = self._dist.get_metadata(name) + if content is None: + raise NoneMetadataError(self, name) + return content + + def iter_entry_points(self) -> Iterable[BaseEntryPoint]: + for group, entries in self._dist.get_entry_map().items(): + for name, entry_point in entries.items(): + name, _, value = str(entry_point).partition("=") + yield EntryPoint(name=name.strip(), value=value.strip(), group=group) + + def _metadata_impl(self) -> email.message.Message: + """ + :raises NoneMetadataError: if the distribution reports `has_metadata()` + True but `get_metadata()` returns None. + """ + if isinstance(self._dist, pkg_resources.DistInfoDistribution): + metadata_name = "METADATA" + else: + metadata_name = "PKG-INFO" + try: + metadata = self.read_text(metadata_name) + except FileNotFoundError: + if self.location: + displaying_path = display_path(self.location) + else: + displaying_path = repr(self.location) + logger.warning("No metadata found in %s", displaying_path) + metadata = "" + feed_parser = email.parser.FeedParser() + feed_parser.feed(metadata) + return feed_parser.close() + + def iter_dependencies(self, extras: Collection[str] = ()) -> Iterable[Requirement]: + if extras: + relevant_extras = set(self._extra_mapping) & set( + map(canonicalize_name, extras) + ) + extras = [self._extra_mapping[extra] for extra in relevant_extras] + return self._dist.requires(extras) + + def iter_provided_extras(self) -> Iterable[NormalizedName]: + return self._extra_mapping.keys() + + +class Environment(BaseEnvironment): + def __init__(self, ws: pkg_resources.WorkingSet) -> None: + self._ws = ws + + @classmethod + def default(cls) -> BaseEnvironment: + return cls(pkg_resources.working_set) + + @classmethod + def from_paths(cls, paths: Optional[List[str]]) -> BaseEnvironment: + return cls(pkg_resources.WorkingSet(paths)) + + def _iter_distributions(self) -> Iterator[BaseDistribution]: + for dist in self._ws: + yield Distribution(dist) + + def _search_distribution(self, name: str) -> Optional[BaseDistribution]: + """Find a distribution matching the ``name`` in the environment. + + This searches from *all* distributions available in the environment, to + match the behavior of ``pkg_resources.get_distribution()``. + """ + canonical_name = canonicalize_name(name) + for dist in self.iter_all_distributions(): + if dist.canonical_name == canonical_name: + return dist + return None + + def get_distribution(self, name: str) -> Optional[BaseDistribution]: + # Search the distribution by looking through the working set. + dist = self._search_distribution(name) + if dist: + return dist + + # If distribution could not be found, call working_set.require to + # update the working set, and try to find the distribution again. + # This might happen for e.g. when you install a package twice, once + # using setup.py develop and again using setup.py install. Now when + # running pip uninstall twice, the package gets removed from the + # working set in the first uninstall, so we have to populate the + # working set again so that pip knows about it and the packages gets + # picked up and is successfully uninstalled the second time too. + try: + # We didn't pass in any version specifiers, so this can never + # raise pkg_resources.VersionConflict. + self._ws.require(name) + except pkg_resources.DistributionNotFound: + return None + return self._search_distribution(name) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/models/__init__.py b/backend/.venv/Lib/site-packages/pip/_internal/models/__init__.py new file mode 100644 index 0000000..7855226 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/models/__init__.py @@ -0,0 +1,2 @@ +"""A package that contains models that represent entities. +""" diff --git a/backend/.venv/Lib/site-packages/pip/_internal/models/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/models/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fe7fd458318a2c876b362ed0891fbe4237675698 GIT binary patch literal 268 zcmXv}OHKnZ3{6S}Ri)k`+b(8iix3|nw!i@(Qk2P9#dJub*exm-;S8LG8+6MB5Z$rD zqn0OG_Ir}wvp;9EsS?~hUf`AVuYvqSABNpThIiGe2er}j(c9^@$v!Oo0t`QSHX%j! z7|Fb(4tm;)1#$s`$VLhof$Hh~TyIaD>r!y;L+u9p-}dIrzNWGyu>>2RnJOPbTFFve zR3R0xt%O1BY`uoKwzt??LWb&a1KEtZaTpm&^nJ5GqH&@iJ6Gq;c5*J_s)x&RERn-o RG<^Miq_zGTX+17up?{S#Pxk-- literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/models/__pycache__/candidate.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/models/__pycache__/candidate.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7a06b65f1c6666508a4f2dc2bd7ade1f857ca749 GIT binary patch literal 1606 zcmb7EUuYaf7@yhych_sAy~d`HvMm<7YBpH&Bxw=zAkj9^Gzwi0*3Hgb*vsDTb!HRE zaSwsk_xf~!A{3um(ueqDALEmPFOfzX77JSGgKrm35Pb5R-MtusB7QL6{O0?#sYSPbd_dWa$i6XZxAg7c2N1a5zc9fhh?Bl0v@P#utx zAp?*q5Rs`$z=o*QAR5sd1~Kj^PKjt#ZAhd9xV)xY<@D5S#1k(Jy#zd*@gfp{>$Ed9 zPuq-g8YSHH%yygr3cS!f?+;DRn~j*6!J*yuLpfCDS|(VVZqYDhW&8OGo~upUZ)=hPI^Bh-aVbn#}P!T)V7CBsHQU1?a%|FK{0%70t0 zAxoJ%5|kyUTD;h#ev(#Pm(#>c66U&TH7mGV+PUD=>}0k zS>%P2t(ee|PaagwZm*?=3;G~&-Oky6EWSO|p9Ht~Wnk;*C*$~25yVP=iMPLc1aA)2W#UL7Nwg{F@!c^b#}07875Fg;^G&@Xcg3;HeJ96NT%H z|66J@^=Yu>7lEy#y%VE7>vQYw_|Dl&TT@?8e>J^jZ!6mi-`@P@=Jp5Q-P#$szGGZx zqhM@RMDE24fzBwqE)-`a6!@6y-dgd(LIXaK*avY5oC)KE1C-&~bi{SND2k!C;H`p` zi4-uAO?FDKF<=i-c2yP)D+#G!V(?jDpP^rrE6-ngeSP-la`pD?UbXf_sqK}I-+sTZ z$m-tWa0dDq(6=aGdc?qTNy6M4)_WlZP!yTUGjOw^EH w0@jx?#?R2X7wFAr=$#knwS5gqmAkL(;+OxBM({lDBf$qUl1}eug6zz{00z{9VE_OC literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e2cdef5e28d56b82503a07a737d97d906f5a1e78 GIT binary patch literal 10846 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 PRYD(h{MULDmB9Z8xBb)A literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/models/__pycache__/format_control.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/models/__pycache__/format_control.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2ef04e6327431c0dbbe6ab44a7fb7a0db55775bc GIT binary patch literal 4225 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 I>+R$J2VMWJTL1t6 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/models/__pycache__/index.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/models/__pycache__/index.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3bcad080851814f9965ab7f323376f8399797c4f GIT binary patch literal 1696 zcmZ`(L2nyH6rNr0t~ZV&w=FRuM z*yAKh>b4WZwp(HmgL<8%Sk9wLY+9;zrRdK(dS8`V7vZa1KEgl_-_eDxCJ6Qqf3?>O_N2Cq~WK zK{bV>x3d+4n9@h}nns4UwMu#i-Bl{)d#IEV*=5_gW3SRhpU}I_H*e99QBM7cTej5= zS#iv=ePV?y*l-Eu7PYxcnPoc;<=lz_i~1xCT*xcwBGq7?Fnk($fg>{9T@O8qrOymE zLpPp{)?D!MC}40lCc(Px`b>vAvLO({U^Hqlf5}O8uPv3F%kT705ML{MC<2{~-Bb&G z0qF-_TR|V;qgrXjNsBZRh&UAhFY~Gu-lmjK1*Rws}nTEalJGM|gcNXc*NIxIe z_RoCATD5l;td;kVM@t1Ork*r6Q7N?~j08-fNgzwZLg$T;GGSuu`fh}A452UpYtLN~ zdT29Fg$X7PJvU;qW-%fgfNKH6p&hNUH29b-Fh;(l35`>)HqeV9j2+MB9Ahr&ZdumW zKY0Fn^^<_z;i2u&s$Y-zG*BUE_>t?cPCEgk)fM0skfJ)XLH&*DO?Rcr-H1*@f}|U- zhHhAfsw2vL+bgdJgnGQ}N*2z9n@l3w93SN7Oz(~oAdW#i-9nGdk==CLEZjGXC!_ft z?Q`={eqzu2$~(?qYUeNQ&mZMqInK|u^K%dzJ}JIlBVafHZ*Q^oay62|`T6+b|g;kMP4M|S<_BzE_WH5&IG~m5rk;VAq zhV6ADX$()-0XJ}jdqD&o5h)(AxP5Uwz_x@v4)r{YOA3ptkWcH4q-qH#lR|#{RS-|N z(L?R#<8!yR7CTx-pZjLMgFyY{#Oi1Ax3oG1MZbD)vV%bFPdsmzWY~7&8nZ8@t*$zWd)Vi literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8cc2373fe14f6bb2fe1b2d63911d57e9dfbb1f27 GIT binary patch literal 2279 zcmZ`)O>7fK6rTO@e~e9jAWrJYKnOJ4L#tkz-Z)n3#ZH7wN3Dv~a_G%qq^dpj&8`=MNk`h5_cw3e zoA1rrpQF(*g7NOzqeU@-&>x)fhTJAv?*VZQ=|~q0R2K3=SIU!g2y+GomhDmGeIA*FmDoIDmsVG$T4X8RC|2w_W7J9a>TM!_ElL z4UwJ36^q!cx9G;Ekf*^>t$hcMQ%+0pwYp)th8BfIq&Nyb&7-t12`Tm|TlqXhqd0a6}C#~?elmY0GZhQOMFE`l}Bykmeg+93kg zi>I{hd7UnO>AU(+xJEk^}!7{d0UA0vfeZ*$ex&s^3k|&NJk&(N&nPp!>0&Mr_x5Y*#IK zthRSz?d7$R+MZ(@z{GYnyU@_?MlxGZW*f=F_2l7= zy{n0pL?dxvJ#k>I>gXGZ(RyMOEE37p=t}f@tkFMS?;n4-uQwK6lA8NbSG*BPu1AtL zhQAs8di2kc12^CQ_Ux^*8zV=Sj@RP5>s@>9#k!ZmWIM#Dwc!O4Azq-)lez)~G;_g* z)g6ndw7Ds@r6Q{F_r=zlFZneO79(NxP=QCL_}povxu zPIoEFg{o?}8p3ara99X`yey&_Dy2}`=PjLZUreGlAsjO|U7pb`%EPS(dxwGc2+O#banalqG8dvT(PU|qBC9RI23&dDD?dc@h5z>C?nM_BR-=43)uf&at2kB(Nl7LoZJrb19&C7PdAuzZ}N3A4l-WcbO@%VBnZOq bXrzut9-yNS(BN+<_qRVQgdZW8oc;d+z?~z- literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/models/__pycache__/link.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/models/__pycache__/link.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..19c978014b33ec91b2e8712d1b8c43537857eb06 GIT binary patch literal 26619 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bc396b33ba980cc8baebe7ce8f86117fca14be1c GIT binary patch literal 4989 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 Y#Q($U40D{RAlkqOV%r|MUG((-0jeLR9RL6T literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ca03e0ce44e5f926a075ba26983ae73e9e29d8f4 GIT binary patch literal 1853 zcmZ`)&ube;6rR=Y%91R(O-VxhlZlAf+{Np}27=G^$A`1y!(&c1HHbtC`Kr z%Bq42KKPLTz}L2?hW;tNq|ky`C=HYzdQ;*;p{Kstl`M<8BlgXEGxKKNeBXPcA4{bI zf_DGQE&sO}gnrk?xLG6R^lea15Jl7oP}`^*hSoDdrft?u17*<1h?>WUT0dk`kGj>f zo$R05aEv(jSs3|(lK}M6j*x8dvYC1Cpfh0Qz_Jr7Pt8`57LM(Du4g*M`0_&*Fi*#^D_M(4#yzH< z&;o{bk9#Ckoq$A4;b@;>k8tW!FtHkY;c()HTS8(gx;zks`g||h1YEGsRYZaShH%Rd zn5rZ*&+NDeqoV8f2tQynzLHuXUD#E^5kxT+&%w5Ujq9c0#HI8|x9M{td+}9&j|<6M z$sTun$&?%RqJ6<@G6%Ppc`Y=Ra#o8Xh&U@*)RElFf-!EIArrpS2Ov&R-#*IF%-43` z=p%Q$2K6&w8Dq0=f;D0mp}qx{-XUpy8?14jpq}BFqzg;8CDZ5;d=ctcG#>#Kl|q7! zCSWrplC<%8kT&rb`wX~{DU!HNBtVCW!YPP&-RB8cigCrxcGA0v7T&$Li|@RD+rdOK z95UJVqX@hsft%;pRSA(J(o(L@MKjIDCjJml2V@Vju8LEZCnMc`#xd*#c^Qp!Oh>1i-p=QgeT8+_LB1V~QcX{ez?@2+ z37P;wIs>j)1at#8I}tu4fv?ph)21S)zKXCo1Re~skP?}>Iu zBEK0-bGQ0nl-=dsB)eC2XdM6u*iP?>KVmHcm_Vfpyh8%TCUMkuB)nnB$;K9--TL3k zP`V;CRv7=|Z*MlbLLMmKf;IS~NR^4_i4NDOmp!PsMiW?KoHio8TLUf%#>qXan+#$heX2x}?@L)Lax+)Nn0@Z2?5lCI?QdhXV1mYQzZ)p8> zEi{UW&@YgpAdb}M!gV- zO2UlSfQiZ(6P1*S%5)*8cS%Cme-xAJ#JRgEI3LI*n9$Fkx&mTo8iw&JTKofT{aq*< KTdxp^#O+`8Rt^0C literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/models/__pycache__/target_python.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/models/__pycache__/target_python.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..07dd515f3e919fc1dea0d5c8dbaec95340499578 GIT binary patch literal 4955 zcmcIn-ESP#6~8mH>)oAQdlMXkKhoWsIM`llPl!z@I3YB`X_b~b5x6QWM#Fe#Y)>*f zv)q|YvX-p|l!rwE)sd>&2r8V4hg50R^o{?aFT0q^%ap2-O4ZUQgOOTz>N$7z!|Rwz zedySG=YF0!_nzN5=Xd|m*(nove)Q5)=I;&=@>gs$o>0BA^9oefh)#6DB3XQkmXH^- zVqVHh`A{~L4`;&y_DfbrK9Y^_ddQ0AW7$|<&dR(Uw&M9jHX#s^e4pqYH;5j&BL-i{ zc9w)p^fPQsXF`7HS=06W=!Jr3I<{u{(({Jrhi8ff%g6}6G@~tKM89*v@Km>0C^*bB zbie0{!CaWGn)bY-dX8#4y5qt02W^MtHOpKw)ZJ5Z!Iy(FUT^HY3zaoukgTAStf&iF zX#qC-DF47(nChr=rAIEFc*J%7}`-IrgzMX&A!NAEkzuQ~1nG)PGQ2Fs~T4S}3)htRK?mOxN!+^I)&MVS5^y(T^2C zJ&>PweYv&5PqymZbbegD0@l)1Pg`*P+1GZFTb}kH! z#uJ5#1iziHp;#l!;xbViW6-*O$g6{okV_4qH^;%Mf-d%x7154+kw*8jct;58E21u4 ziZ%LMZ?AzQ;w2ir%YY+2)K3~+YF&HSGm0b*LcfG>>Y`piP&gb0v<&T#+$A0d-5RXXF)n0RYObnyxWQubP(C zCT`xe^*u6knoZ{nI#)C;P|^8fz*?(>k{V!!We9g2 zHqXqtB7$@hrI+qk%XYk$4wjPxrziz(u=_~c-2e{OrcOPCQ4fO`o-w$fOPK*q=)$4E zapNc3w66PVJy^j4bQfQ1#la)_9f39({eed$gwn*bC@wZ2jSbW^;rOieP#Apb8gl( zJ!7ol4YLKaa2#SSBmqdS$McSESnly44?rx(v;t=GqbkfXJyl)m*`0BeM)v?J_8Jt| z$@VB2e!Lv|C^~pA-d~9y{Umi{E2UIZ%58R6sHDcRkE4y`J8+7jC}r zZtnfTji26S9|)D<$<5TM&7RX``QD-4a_G%iEj5b525Nmrq1jdIKL)R4Ev;bh;q4A` z;w093YZKoohyEBnyaP&*Ts<;lonRi|vHzb?0pcR8K#aVEBYU3Lj_TqioVn-Gr5j}b z6;tF+eeRt`E`aC`bN9(1kjcZ#0+byvjyBx$z(@o}nlZmMJTESUAjd@a)h!0PiTCUA zJjuvQQ%wi_9*-J4T=FzMN^Qp;!?;d0FNk0nntn`XVBO52Iz?k3>3GY-WM ziGUfEybQ^AMev#@zbrJ)OuA!Xf(bqkrG-v++7Q4us{z3i?P$c4T*T+L=*Y%%E zt5a*S>d@J*TvYz`o`;0M!4SAD2lEBG|3)8&Y0Zs-7tVsRE5eEh)IoSNwk*5@uv!-1 z5q~MwH{0FZtT^opPyL!?B=#@}@ukZ~$qxgoDH<+f4cwS-nGHkZf7|Q~tZ+x5Xl%Au z{`kbHTaz0Tx5FP4t507nyJchb#OjY%&wrFi{l5Pz7s2(q+$X%1=mRdmLl-*?eZg5Y zDHQ0MhF(8e2SbC=`7$VvBn)(KQ{GSPw#!oAH=1k;#JX=m0mg}vfpj@pizm0@L)G|D zB|ctD9eHo@?Zwa0Y_*|Bwua7rICOSLg4PZZ(_Q5Y+cN3uTR--m^0rb*WNMuQ>uM!2 zR_p9uomqSF=8Kg?y4Lxvb#E&@UQLfz5)<38@Pl$$-cFDM-9Nkb#x;=4&j@7p${_QA z3=oOQ>?ml|W_a{Z9y30K3Zi?zcyawA^doBbJP==m>k`Bn@nH0FU|81n{@ zz#MRwyaQx2=wL{}Oy+vKNDJQoBK54=!l)lY5|D`mNfYxgLvG9v-K|;tGLQ*zBnLSb zqm>`R9q}Llo>z}HNzOs|)sYjErNeCi-ZT0Fh;c0_0K*BAIItBTsKy5>@j*yN>A|hk zlhxFd4L^Q8YP+s122GglNiZCNuy;6O6E={_IU)aD8YD zeKUN7CF|TZE$0D;2Es~REf0C5PUTw1I0`)7t7E{W8r&P&fdW(!|MPfh*WgY7F@(ZJ zm4^~QM~nJFJVI&&6w2_}NvJ{kzyRf9vZ>qfAX=$tyRFYJrS7w0+xV*}0Wkq~l(`+# z)p)uRAO2);Xv5nYK2;q)wK@FM=HMB$2IbZmtR@F5(LrvFOlTUO%mE}vHk^Q}`m(A5 zgDP5BPpImvMa`;@L{wFGa?l-9Ro8MnS5+BWkfC{aE@T*Udc91g?kH%8{~6Q3P-j}M2R zxYs?fKDE*P_W5e}&~_L)0J;4~Hy*w%-G2Ud^w#le-}rU}yQ3ue(5koo%*|4@>&SKt zyJXUL1eSJgqaeVl+_lq*wdaHf!t#1z*}Lef_}`;#~5bIgA9bYR&t>=}@Nz;g$o*p>uA_!E);LdG`9 a*x$$_e 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/models/candidate.py b/backend/.venv/Lib/site-packages/pip/_internal/models/candidate.py new file mode 100644 index 0000000..f27f283 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/models/candidate.py @@ -0,0 +1,25 @@ +from dataclasses import dataclass + +from pip._vendor.packaging.version import Version +from pip._vendor.packaging.version import parse as parse_version + +from pip._internal.models.link import Link + + +@dataclass(frozen=True) +class InstallationCandidate: + """Represents a potential "candidate" for installation.""" + + __slots__ = ["name", "version", "link"] + + name: str + version: Version + link: Link + + def __init__(self, name: str, version: str, link: Link) -> None: + object.__setattr__(self, "name", name) + object.__setattr__(self, "version", parse_version(version)) + object.__setattr__(self, "link", link) + + def __str__(self) -> str: + return f"{self.name!r} candidate (version {self.version} at {self.link})" diff --git a/backend/.venv/Lib/site-packages/pip/_internal/models/direct_url.py b/backend/.venv/Lib/site-packages/pip/_internal/models/direct_url.py new file mode 100644 index 0000000..fc5ec8d --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/models/direct_url.py @@ -0,0 +1,224 @@ +""" PEP 610 """ + +import json +import re +import urllib.parse +from dataclasses import dataclass +from typing import Any, ClassVar, Dict, Iterable, Optional, Type, TypeVar, Union + +__all__ = [ + "DirectUrl", + "DirectUrlValidationError", + "DirInfo", + "ArchiveInfo", + "VcsInfo", +] + +T = TypeVar("T") + +DIRECT_URL_METADATA_NAME = "direct_url.json" +ENV_VAR_RE = re.compile(r"^\$\{[A-Za-z0-9-_]+\}(:\$\{[A-Za-z0-9-_]+\})?$") + + +class DirectUrlValidationError(Exception): + pass + + +def _get( + d: Dict[str, Any], expected_type: Type[T], key: str, default: Optional[T] = None +) -> Optional[T]: + """Get value from dictionary and verify expected type.""" + if key not in d: + return default + value = d[key] + if not isinstance(value, expected_type): + raise DirectUrlValidationError( + f"{value!r} has unexpected type for {key} (expected {expected_type})" + ) + return value + + +def _get_required( + d: Dict[str, Any], expected_type: Type[T], key: str, default: Optional[T] = None +) -> T: + value = _get(d, expected_type, key, default) + if value is None: + raise DirectUrlValidationError(f"{key} must have a value") + return value + + +def _exactly_one_of(infos: Iterable[Optional["InfoType"]]) -> "InfoType": + infos = [info for info in infos if info is not None] + if not infos: + raise DirectUrlValidationError( + "missing one of archive_info, dir_info, vcs_info" + ) + if len(infos) > 1: + raise DirectUrlValidationError( + "more than one of archive_info, dir_info, vcs_info" + ) + assert infos[0] is not None + return infos[0] + + +def _filter_none(**kwargs: Any) -> Dict[str, Any]: + """Make dict excluding None values.""" + return {k: v for k, v in kwargs.items() if v is not None} + + +@dataclass +class VcsInfo: + name: ClassVar = "vcs_info" + + vcs: str + commit_id: str + requested_revision: Optional[str] = None + + @classmethod + def _from_dict(cls, d: Optional[Dict[str, Any]]) -> Optional["VcsInfo"]: + if d is None: + return None + return cls( + vcs=_get_required(d, str, "vcs"), + commit_id=_get_required(d, str, "commit_id"), + requested_revision=_get(d, str, "requested_revision"), + ) + + def _to_dict(self) -> Dict[str, Any]: + return _filter_none( + vcs=self.vcs, + requested_revision=self.requested_revision, + commit_id=self.commit_id, + ) + + +class ArchiveInfo: + name = "archive_info" + + def __init__( + self, + hash: Optional[str] = None, + hashes: Optional[Dict[str, str]] = None, + ) -> None: + # set hashes before hash, since the hash setter will further populate hashes + self.hashes = hashes + self.hash = hash + + @property + def hash(self) -> Optional[str]: + return self._hash + + @hash.setter + def hash(self, value: Optional[str]) -> None: + if value is not None: + # Auto-populate the hashes key to upgrade to the new format automatically. + # We don't back-populate the legacy hash key from hashes. + try: + hash_name, hash_value = value.split("=", 1) + except ValueError: + raise DirectUrlValidationError( + f"invalid archive_info.hash format: {value!r}" + ) + if self.hashes is None: + self.hashes = {hash_name: hash_value} + elif hash_name not in self.hashes: + self.hashes = self.hashes.copy() + self.hashes[hash_name] = hash_value + self._hash = value + + @classmethod + def _from_dict(cls, d: Optional[Dict[str, Any]]) -> Optional["ArchiveInfo"]: + if d is None: + return None + return cls(hash=_get(d, str, "hash"), hashes=_get(d, dict, "hashes")) + + def _to_dict(self) -> Dict[str, Any]: + return _filter_none(hash=self.hash, hashes=self.hashes) + + +@dataclass +class DirInfo: + name: ClassVar = "dir_info" + + editable: bool = False + + @classmethod + def _from_dict(cls, d: Optional[Dict[str, Any]]) -> Optional["DirInfo"]: + if d is None: + return None + return cls(editable=_get_required(d, bool, "editable", default=False)) + + def _to_dict(self) -> Dict[str, Any]: + return _filter_none(editable=self.editable or None) + + +InfoType = Union[ArchiveInfo, DirInfo, VcsInfo] + + +@dataclass +class DirectUrl: + url: str + info: InfoType + subdirectory: Optional[str] = None + + def _remove_auth_from_netloc(self, netloc: str) -> str: + if "@" not in netloc: + return netloc + user_pass, netloc_no_user_pass = netloc.split("@", 1) + if ( + isinstance(self.info, VcsInfo) + and self.info.vcs == "git" + and user_pass == "git" + ): + return netloc + if ENV_VAR_RE.match(user_pass): + return netloc + return netloc_no_user_pass + + @property + def redacted_url(self) -> str: + """url with user:password part removed unless it is formed with + environment variables as specified in PEP 610, or it is ``git`` + in the case of a git URL. + """ + purl = urllib.parse.urlsplit(self.url) + netloc = self._remove_auth_from_netloc(purl.netloc) + surl = urllib.parse.urlunsplit( + (purl.scheme, netloc, purl.path, purl.query, purl.fragment) + ) + return surl + + def validate(self) -> None: + self.from_dict(self.to_dict()) + + @classmethod + def from_dict(cls, d: Dict[str, Any]) -> "DirectUrl": + return DirectUrl( + url=_get_required(d, str, "url"), + subdirectory=_get(d, str, "subdirectory"), + info=_exactly_one_of( + [ + ArchiveInfo._from_dict(_get(d, dict, "archive_info")), + DirInfo._from_dict(_get(d, dict, "dir_info")), + VcsInfo._from_dict(_get(d, dict, "vcs_info")), + ] + ), + ) + + def to_dict(self) -> Dict[str, Any]: + res = _filter_none( + url=self.redacted_url, + subdirectory=self.subdirectory, + ) + res[self.info.name] = self.info._to_dict() + return res + + @classmethod + def from_json(cls, s: str) -> "DirectUrl": + return cls.from_dict(json.loads(s)) + + def to_json(self) -> str: + return json.dumps(self.to_dict(), sort_keys=True) + + def is_local_editable(self) -> bool: + return isinstance(self.info, DirInfo) and self.info.editable diff --git a/backend/.venv/Lib/site-packages/pip/_internal/models/format_control.py b/backend/.venv/Lib/site-packages/pip/_internal/models/format_control.py new file mode 100644 index 0000000..ccd1127 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/models/format_control.py @@ -0,0 +1,78 @@ +from typing import FrozenSet, Optional, Set + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.exceptions import CommandError + + +class FormatControl: + """Helper for managing formats from which a package can be installed.""" + + __slots__ = ["no_binary", "only_binary"] + + def __init__( + self, + no_binary: Optional[Set[str]] = None, + only_binary: Optional[Set[str]] = None, + ) -> None: + if no_binary is None: + no_binary = set() + if only_binary is None: + only_binary = set() + + self.no_binary = no_binary + self.only_binary = only_binary + + def __eq__(self, other: object) -> bool: + if not isinstance(other, self.__class__): + return NotImplemented + + if self.__slots__ != other.__slots__: + return False + + return all(getattr(self, k) == getattr(other, k) for k in self.__slots__) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self.no_binary}, {self.only_binary})" + + @staticmethod + def handle_mutual_excludes(value: str, target: Set[str], other: Set[str]) -> None: + if value.startswith("-"): + raise CommandError( + "--no-binary / --only-binary option requires 1 argument." + ) + new = value.split(",") + while ":all:" in new: + other.clear() + target.clear() + target.add(":all:") + del new[: new.index(":all:") + 1] + # Without a none, we want to discard everything as :all: covers it + if ":none:" not in new: + return + for name in new: + if name == ":none:": + target.clear() + continue + name = canonicalize_name(name) + other.discard(name) + target.add(name) + + def get_allowed_formats(self, canonical_name: str) -> FrozenSet[str]: + result = {"binary", "source"} + if canonical_name in self.only_binary: + result.discard("source") + elif canonical_name in self.no_binary: + result.discard("binary") + elif ":all:" in self.only_binary: + result.discard("source") + elif ":all:" in self.no_binary: + result.discard("binary") + return frozenset(result) + + def disallow_binaries(self) -> None: + self.handle_mutual_excludes( + ":all:", + self.no_binary, + self.only_binary, + ) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/models/index.py b/backend/.venv/Lib/site-packages/pip/_internal/models/index.py new file mode 100644 index 0000000..b94c325 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/models/index.py @@ -0,0 +1,28 @@ +import urllib.parse + + +class PackageIndex: + """Represents a Package Index and provides easier access to endpoints""" + + __slots__ = ["url", "netloc", "simple_url", "pypi_url", "file_storage_domain"] + + def __init__(self, url: str, file_storage_domain: str) -> None: + super().__init__() + self.url = url + self.netloc = urllib.parse.urlsplit(url).netloc + self.simple_url = self._url_for_path("simple") + self.pypi_url = self._url_for_path("pypi") + + # This is part of a temporary hack used to block installs of PyPI + # packages which depend on external urls only necessary until PyPI can + # block such packages themselves + self.file_storage_domain = file_storage_domain + + def _url_for_path(self, path: str) -> str: + return urllib.parse.urljoin(self.url, path) + + +PyPI = PackageIndex("https://pypi.org/", file_storage_domain="files.pythonhosted.org") +TestPyPI = PackageIndex( + "https://test.pypi.org/", file_storage_domain="test-files.pythonhosted.org" +) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/models/installation_report.py b/backend/.venv/Lib/site-packages/pip/_internal/models/installation_report.py new file mode 100644 index 0000000..b9c6330 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/models/installation_report.py @@ -0,0 +1,56 @@ +from typing import Any, Dict, Sequence + +from pip._vendor.packaging.markers import default_environment + +from pip import __version__ +from pip._internal.req.req_install import InstallRequirement + + +class InstallationReport: + def __init__(self, install_requirements: Sequence[InstallRequirement]): + self._install_requirements = install_requirements + + @classmethod + def _install_req_to_dict(cls, ireq: InstallRequirement) -> Dict[str, Any]: + assert ireq.download_info, f"No download_info for {ireq}" + res = { + # PEP 610 json for the download URL. download_info.archive_info.hashes may + # be absent when the requirement was installed from the wheel cache + # and the cache entry was populated by an older pip version that did not + # record origin.json. + "download_info": ireq.download_info.to_dict(), + # is_direct is true if the requirement was a direct URL reference (which + # includes editable requirements), and false if the requirement was + # downloaded from a PEP 503 index or --find-links. + "is_direct": ireq.is_direct, + # is_yanked is true if the requirement was yanked from the index, but + # was still selected by pip to conform to PEP 592. + "is_yanked": ireq.link.is_yanked if ireq.link else False, + # requested is true if the requirement was specified by the user (aka + # top level requirement), and false if it was installed as a dependency of a + # requirement. https://peps.python.org/pep-0376/#requested + "requested": ireq.user_supplied, + # PEP 566 json encoding for metadata + # https://www.python.org/dev/peps/pep-0566/#json-compatible-metadata + "metadata": ireq.get_dist().metadata_dict, + } + if ireq.user_supplied and ireq.extras: + # For top level requirements, the list of requested extras, if any. + res["requested_extras"] = sorted(ireq.extras) + return res + + def to_dict(self) -> Dict[str, Any]: + return { + "version": "1", + "pip_version": __version__, + "install": [ + self._install_req_to_dict(ireq) for ireq in self._install_requirements + ], + # https://peps.python.org/pep-0508/#environment-markers + # TODO: currently, the resolver uses the default environment to evaluate + # environment markers, so that is what we report here. In the future, it + # should also take into account options such as --python-version or + # --platform, perhaps under the form of an environment_override field? + # https://github.com/pypa/pip/issues/11198 + "environment": default_environment(), + } diff --git a/backend/.venv/Lib/site-packages/pip/_internal/models/link.py b/backend/.venv/Lib/site-packages/pip/_internal/models/link.py new file mode 100644 index 0000000..2f41f2f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/models/link.py @@ -0,0 +1,590 @@ +import functools +import itertools +import logging +import os +import posixpath +import re +import urllib.parse +from dataclasses import dataclass +from typing import ( + TYPE_CHECKING, + Any, + Dict, + List, + Mapping, + NamedTuple, + Optional, + Tuple, + Union, +) + +from pip._internal.utils.deprecation import deprecated +from pip._internal.utils.filetypes import WHEEL_EXTENSION +from pip._internal.utils.hashes import Hashes +from pip._internal.utils.misc import ( + pairwise, + redact_auth_from_url, + split_auth_from_netloc, + splitext, +) +from pip._internal.utils.urls import path_to_url, url_to_path + +if TYPE_CHECKING: + from pip._internal.index.collector import IndexContent + +logger = logging.getLogger(__name__) + + +# Order matters, earlier hashes have a precedence over later hashes for what +# we will pick to use. +_SUPPORTED_HASHES = ("sha512", "sha384", "sha256", "sha224", "sha1", "md5") + + +@dataclass(frozen=True) +class LinkHash: + """Links to content may have embedded hash values. This class parses those. + + `name` must be any member of `_SUPPORTED_HASHES`. + + This class can be converted to and from `ArchiveInfo`. While ArchiveInfo intends to + be JSON-serializable to conform to PEP 610, this class contains the logic for + parsing a hash name and value for correctness, and then checking whether that hash + conforms to a schema with `.is_hash_allowed()`.""" + + name: str + value: str + + _hash_url_fragment_re = re.compile( + # NB: we do not validate that the second group (.*) is a valid hex + # digest. Instead, we simply keep that string in this class, and then check it + # against Hashes when hash-checking is needed. This is easier to debug than + # proactively discarding an invalid hex digest, as we handle incorrect hashes + # and malformed hashes in the same place. + r"[#&]({choices})=([^&]*)".format( + choices="|".join(re.escape(hash_name) for hash_name in _SUPPORTED_HASHES) + ), + ) + + def __post_init__(self) -> None: + assert self.name in _SUPPORTED_HASHES + + @classmethod + @functools.lru_cache(maxsize=None) + def find_hash_url_fragment(cls, url: str) -> Optional["LinkHash"]: + """Search a string for a checksum algorithm name and encoded output value.""" + match = cls._hash_url_fragment_re.search(url) + if match is None: + return None + name, value = match.groups() + return cls(name=name, value=value) + + def as_dict(self) -> Dict[str, str]: + return {self.name: self.value} + + def as_hashes(self) -> Hashes: + """Return a Hashes instance which checks only for the current hash.""" + return Hashes({self.name: [self.value]}) + + def is_hash_allowed(self, hashes: Optional[Hashes]) -> bool: + """ + Return True if the current hash is allowed by `hashes`. + """ + if hashes is None: + return False + return hashes.is_hash_allowed(self.name, hex_digest=self.value) + + +@dataclass(frozen=True) +class MetadataFile: + """Information about a core metadata file associated with a distribution.""" + + hashes: Optional[Dict[str, str]] + + def __post_init__(self) -> None: + if self.hashes is not None: + assert all(name in _SUPPORTED_HASHES for name in self.hashes) + + +def supported_hashes(hashes: Optional[Dict[str, str]]) -> Optional[Dict[str, str]]: + # Remove any unsupported hash types from the mapping. If this leaves no + # supported hashes, return None + if hashes is None: + return None + hashes = {n: v for n, v in hashes.items() if n in _SUPPORTED_HASHES} + if not hashes: + return None + return hashes + + +def _clean_url_path_part(part: str) -> str: + """ + Clean a "part" of a URL path (i.e. after splitting on "@" characters). + """ + # We unquote prior to quoting to make sure nothing is double quoted. + return urllib.parse.quote(urllib.parse.unquote(part)) + + +def _clean_file_url_path(part: str) -> str: + """ + Clean the first part of a URL path that corresponds to a local + filesystem path (i.e. the first part after splitting on "@" characters). + """ + # We unquote prior to quoting to make sure nothing is double quoted. + # Also, on Windows the path part might contain a drive letter which + # should not be quoted. On Linux where drive letters do not + # exist, the colon should be quoted. We rely on urllib.request + # to do the right thing here. + return urllib.request.pathname2url(urllib.request.url2pathname(part)) + + +# percent-encoded: / +_reserved_chars_re = re.compile("(@|%2F)", re.IGNORECASE) + + +def _clean_url_path(path: str, is_local_path: bool) -> str: + """ + Clean the path portion of a URL. + """ + if is_local_path: + clean_func = _clean_file_url_path + else: + clean_func = _clean_url_path_part + + # Split on the reserved characters prior to cleaning so that + # revision strings in VCS URLs are properly preserved. + parts = _reserved_chars_re.split(path) + + cleaned_parts = [] + for to_clean, reserved in pairwise(itertools.chain(parts, [""])): + cleaned_parts.append(clean_func(to_clean)) + # Normalize %xx escapes (e.g. %2f -> %2F) + cleaned_parts.append(reserved.upper()) + + return "".join(cleaned_parts) + + +def _ensure_quoted_url(url: str) -> str: + """ + Make sure a link is fully quoted. + For example, if ' ' occurs in the URL, it will be replaced with "%20", + and without double-quoting other characters. + """ + # Split the URL into parts according to the general structure + # `scheme://netloc/path;parameters?query#fragment`. + result = urllib.parse.urlparse(url) + # If the netloc is empty, then the URL refers to a local filesystem path. + is_local_path = not result.netloc + path = _clean_url_path(result.path, is_local_path=is_local_path) + return urllib.parse.urlunparse(result._replace(path=path)) + + +@functools.total_ordering +class Link: + """Represents a parsed link from a Package Index's simple URL""" + + __slots__ = [ + "_parsed_url", + "_url", + "_hashes", + "comes_from", + "requires_python", + "yanked_reason", + "metadata_file_data", + "cache_link_parsing", + "egg_fragment", + ] + + def __init__( + self, + url: str, + comes_from: Optional[Union[str, "IndexContent"]] = None, + requires_python: Optional[str] = None, + yanked_reason: Optional[str] = None, + metadata_file_data: Optional[MetadataFile] = None, + cache_link_parsing: bool = True, + hashes: Optional[Mapping[str, str]] = None, + ) -> None: + """ + :param url: url of the resource pointed to (href of the link) + :param comes_from: instance of IndexContent where the link was found, + or string. + :param requires_python: String containing the `Requires-Python` + metadata field, specified in PEP 345. This may be specified by + a data-requires-python attribute in the HTML link tag, as + described in PEP 503. + :param yanked_reason: the reason the file has been yanked, if the + file has been yanked, or None if the file hasn't been yanked. + This is the value of the "data-yanked" attribute, if present, in + a simple repository HTML link. If the file has been yanked but + no reason was provided, this should be the empty string. See + PEP 592 for more information and the specification. + :param metadata_file_data: the metadata attached to the file, or None if + no such metadata is provided. This argument, if not None, indicates + that a separate metadata file exists, and also optionally supplies + hashes for that file. + :param cache_link_parsing: A flag that is used elsewhere to determine + whether resources retrieved from this link should be cached. PyPI + URLs should generally have this set to False, for example. + :param hashes: A mapping of hash names to digests to allow us to + determine the validity of a download. + """ + + # The comes_from, requires_python, and metadata_file_data arguments are + # only used by classmethods of this class, and are not used in client + # code directly. + + # url can be a UNC windows share + if url.startswith("\\\\"): + url = path_to_url(url) + + self._parsed_url = urllib.parse.urlsplit(url) + # Store the url as a private attribute to prevent accidentally + # trying to set a new value. + self._url = url + + link_hash = LinkHash.find_hash_url_fragment(url) + hashes_from_link = {} if link_hash is None else link_hash.as_dict() + if hashes is None: + self._hashes = hashes_from_link + else: + self._hashes = {**hashes, **hashes_from_link} + + self.comes_from = comes_from + self.requires_python = requires_python if requires_python else None + self.yanked_reason = yanked_reason + self.metadata_file_data = metadata_file_data + + self.cache_link_parsing = cache_link_parsing + self.egg_fragment = self._egg_fragment() + + @classmethod + def from_json( + cls, + file_data: Dict[str, Any], + page_url: str, + ) -> Optional["Link"]: + """ + Convert an pypi json document from a simple repository page into a Link. + """ + file_url = file_data.get("url") + if file_url is None: + return None + + url = _ensure_quoted_url(urllib.parse.urljoin(page_url, file_url)) + pyrequire = file_data.get("requires-python") + yanked_reason = file_data.get("yanked") + hashes = file_data.get("hashes", {}) + + # PEP 714: Indexes must use the name core-metadata, but + # clients should support the old name as a fallback for compatibility. + metadata_info = file_data.get("core-metadata") + if metadata_info is None: + metadata_info = file_data.get("dist-info-metadata") + + # The metadata info value may be a boolean, or a dict of hashes. + if isinstance(metadata_info, dict): + # The file exists, and hashes have been supplied + metadata_file_data = MetadataFile(supported_hashes(metadata_info)) + elif metadata_info: + # The file exists, but there are no hashes + metadata_file_data = MetadataFile(None) + else: + # False or not present: the file does not exist + metadata_file_data = None + + # The Link.yanked_reason expects an empty string instead of a boolean. + if yanked_reason and not isinstance(yanked_reason, str): + yanked_reason = "" + # The Link.yanked_reason expects None instead of False. + elif not yanked_reason: + yanked_reason = None + + return cls( + url, + comes_from=page_url, + requires_python=pyrequire, + yanked_reason=yanked_reason, + hashes=hashes, + metadata_file_data=metadata_file_data, + ) + + @classmethod + def from_element( + cls, + anchor_attribs: Dict[str, Optional[str]], + page_url: str, + base_url: str, + ) -> Optional["Link"]: + """ + Convert an anchor element's attributes in a simple repository page to a Link. + """ + href = anchor_attribs.get("href") + if not href: + return None + + url = _ensure_quoted_url(urllib.parse.urljoin(base_url, href)) + pyrequire = anchor_attribs.get("data-requires-python") + yanked_reason = anchor_attribs.get("data-yanked") + + # PEP 714: Indexes must use the name data-core-metadata, but + # clients should support the old name as a fallback for compatibility. + metadata_info = anchor_attribs.get("data-core-metadata") + if metadata_info is None: + metadata_info = anchor_attribs.get("data-dist-info-metadata") + # The metadata info value may be the string "true", or a string of + # the form "hashname=hashval" + if metadata_info == "true": + # The file exists, but there are no hashes + metadata_file_data = MetadataFile(None) + elif metadata_info is None: + # The file does not exist + metadata_file_data = None + else: + # The file exists, and hashes have been supplied + hashname, sep, hashval = metadata_info.partition("=") + if sep == "=": + metadata_file_data = MetadataFile(supported_hashes({hashname: hashval})) + else: + # Error - data is wrong. Treat as no hashes supplied. + logger.debug( + "Index returned invalid data-dist-info-metadata value: %s", + metadata_info, + ) + metadata_file_data = MetadataFile(None) + + return cls( + url, + comes_from=page_url, + requires_python=pyrequire, + yanked_reason=yanked_reason, + metadata_file_data=metadata_file_data, + ) + + def __str__(self) -> str: + if self.requires_python: + rp = f" (requires-python:{self.requires_python})" + else: + rp = "" + if self.comes_from: + return f"{redact_auth_from_url(self._url)} (from {self.comes_from}){rp}" + else: + return redact_auth_from_url(str(self._url)) + + def __repr__(self) -> str: + return f"" + + def __hash__(self) -> int: + return hash(self.url) + + def __eq__(self, other: Any) -> bool: + if not isinstance(other, Link): + return NotImplemented + return self.url == other.url + + def __lt__(self, other: Any) -> bool: + if not isinstance(other, Link): + return NotImplemented + return self.url < other.url + + @property + def url(self) -> str: + return self._url + + @property + def filename(self) -> str: + path = self.path.rstrip("/") + name = posixpath.basename(path) + if not name: + # Make sure we don't leak auth information if the netloc + # includes a username and password. + netloc, user_pass = split_auth_from_netloc(self.netloc) + return netloc + + name = urllib.parse.unquote(name) + assert name, f"URL {self._url!r} produced no filename" + return name + + @property + def file_path(self) -> str: + return url_to_path(self.url) + + @property + def scheme(self) -> str: + return self._parsed_url.scheme + + @property + def netloc(self) -> str: + """ + This can contain auth information. + """ + return self._parsed_url.netloc + + @property + def path(self) -> str: + return urllib.parse.unquote(self._parsed_url.path) + + def splitext(self) -> Tuple[str, str]: + return splitext(posixpath.basename(self.path.rstrip("/"))) + + @property + def ext(self) -> str: + return self.splitext()[1] + + @property + def url_without_fragment(self) -> str: + scheme, netloc, path, query, fragment = self._parsed_url + return urllib.parse.urlunsplit((scheme, netloc, path, query, "")) + + _egg_fragment_re = re.compile(r"[#&]egg=([^&]*)") + + # Per PEP 508. + _project_name_re = re.compile( + r"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$", re.IGNORECASE + ) + + def _egg_fragment(self) -> Optional[str]: + match = self._egg_fragment_re.search(self._url) + if not match: + return None + + # An egg fragment looks like a PEP 508 project name, along with + # an optional extras specifier. Anything else is invalid. + project_name = match.group(1) + if not self._project_name_re.match(project_name): + deprecated( + reason=f"{self} contains an egg fragment with a non-PEP 508 name", + replacement="to use the req @ url syntax, and remove the egg fragment", + gone_in="25.0", + issue=11617, + ) + + return project_name + + _subdirectory_fragment_re = re.compile(r"[#&]subdirectory=([^&]*)") + + @property + def subdirectory_fragment(self) -> Optional[str]: + match = self._subdirectory_fragment_re.search(self._url) + if not match: + return None + return match.group(1) + + def metadata_link(self) -> Optional["Link"]: + """Return a link to the associated core metadata file (if any).""" + if self.metadata_file_data is None: + return None + metadata_url = f"{self.url_without_fragment}.metadata" + if self.metadata_file_data.hashes is None: + return Link(metadata_url) + return Link(metadata_url, hashes=self.metadata_file_data.hashes) + + def as_hashes(self) -> Hashes: + return Hashes({k: [v] for k, v in self._hashes.items()}) + + @property + def hash(self) -> Optional[str]: + return next(iter(self._hashes.values()), None) + + @property + def hash_name(self) -> Optional[str]: + return next(iter(self._hashes), None) + + @property + def show_url(self) -> str: + return posixpath.basename(self._url.split("#", 1)[0].split("?", 1)[0]) + + @property + def is_file(self) -> bool: + return self.scheme == "file" + + def is_existing_dir(self) -> bool: + return self.is_file and os.path.isdir(self.file_path) + + @property + def is_wheel(self) -> bool: + return self.ext == WHEEL_EXTENSION + + @property + def is_vcs(self) -> bool: + from pip._internal.vcs import vcs + + return self.scheme in vcs.all_schemes + + @property + def is_yanked(self) -> bool: + return self.yanked_reason is not None + + @property + def has_hash(self) -> bool: + return bool(self._hashes) + + def is_hash_allowed(self, hashes: Optional[Hashes]) -> bool: + """ + Return True if the link has a hash and it is allowed by `hashes`. + """ + if hashes is None: + return False + return any(hashes.is_hash_allowed(k, v) for k, v in self._hashes.items()) + + +class _CleanResult(NamedTuple): + """Convert link for equivalency check. + + This is used in the resolver to check whether two URL-specified requirements + likely point to the same distribution and can be considered equivalent. This + equivalency logic avoids comparing URLs literally, which can be too strict + (e.g. "a=1&b=2" vs "b=2&a=1") and produce conflicts unexpecting to users. + + Currently this does three things: + + 1. Drop the basic auth part. This is technically wrong since a server can + serve different content based on auth, but if it does that, it is even + impossible to guarantee two URLs without auth are equivalent, since + the user can input different auth information when prompted. So the + practical solution is to assume the auth doesn't affect the response. + 2. Parse the query to avoid the ordering issue. Note that ordering under the + same key in the query are NOT cleaned; i.e. "a=1&a=2" and "a=2&a=1" are + still considered different. + 3. Explicitly drop most of the fragment part, except ``subdirectory=`` and + hash values, since it should have no impact the downloaded content. Note + that this drops the "egg=" part historically used to denote the requested + project (and extras), which is wrong in the strictest sense, but too many + people are supplying it inconsistently to cause superfluous resolution + conflicts, so we choose to also ignore them. + """ + + parsed: urllib.parse.SplitResult + query: Dict[str, List[str]] + subdirectory: str + hashes: Dict[str, str] + + +def _clean_link(link: Link) -> _CleanResult: + parsed = link._parsed_url + netloc = parsed.netloc.rsplit("@", 1)[-1] + # According to RFC 8089, an empty host in file: means localhost. + if parsed.scheme == "file" and not netloc: + netloc = "localhost" + fragment = urllib.parse.parse_qs(parsed.fragment) + if "egg" in fragment: + logger.debug("Ignoring egg= fragment in %s", link) + try: + # If there are multiple subdirectory values, use the first one. + # This matches the behavior of Link.subdirectory_fragment. + subdirectory = fragment["subdirectory"][0] + except (IndexError, KeyError): + subdirectory = "" + # If there are multiple hash values under the same algorithm, use the + # first one. This matches the behavior of Link.hash_value. + hashes = {k: fragment[k][0] for k in _SUPPORTED_HASHES if k in fragment} + return _CleanResult( + parsed=parsed._replace(netloc=netloc, query="", fragment=""), + query=urllib.parse.parse_qs(parsed.query), + subdirectory=subdirectory, + hashes=hashes, + ) + + +@functools.lru_cache(maxsize=None) +def links_equivalent(link1: Link, link2: Link) -> bool: + return _clean_link(link1) == _clean_link(link2) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/models/scheme.py b/backend/.venv/Lib/site-packages/pip/_internal/models/scheme.py new file mode 100644 index 0000000..06a9a55 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/models/scheme.py @@ -0,0 +1,25 @@ +""" +For types associated with installation schemes. + +For a general overview of available schemes and their context, see +https://docs.python.org/3/install/index.html#alternate-installation. +""" + +from dataclasses import dataclass + +SCHEME_KEYS = ["platlib", "purelib", "headers", "scripts", "data"] + + +@dataclass(frozen=True) +class Scheme: + """A Scheme holds paths which are used as the base directories for + artifacts associated with a Python package. + """ + + __slots__ = SCHEME_KEYS + + platlib: str + purelib: str + headers: str + scripts: str + data: str diff --git a/backend/.venv/Lib/site-packages/pip/_internal/models/search_scope.py b/backend/.venv/Lib/site-packages/pip/_internal/models/search_scope.py new file mode 100644 index 0000000..ee7bc86 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/models/search_scope.py @@ -0,0 +1,127 @@ +import itertools +import logging +import os +import posixpath +import urllib.parse +from dataclasses import dataclass +from typing import List + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.models.index import PyPI +from pip._internal.utils.compat import has_tls +from pip._internal.utils.misc import normalize_path, redact_auth_from_url + +logger = logging.getLogger(__name__) + + +@dataclass(frozen=True) +class SearchScope: + """ + Encapsulates the locations that pip is configured to search. + """ + + __slots__ = ["find_links", "index_urls", "no_index"] + + find_links: List[str] + index_urls: List[str] + no_index: bool + + @classmethod + def create( + cls, + find_links: List[str], + index_urls: List[str], + no_index: bool, + ) -> "SearchScope": + """ + Create a SearchScope object after normalizing the `find_links`. + """ + # Build find_links. If an argument starts with ~, it may be + # a local file relative to a home directory. So try normalizing + # it and if it exists, use the normalized version. + # This is deliberately conservative - it might be fine just to + # blindly normalize anything starting with a ~... + built_find_links: List[str] = [] + for link in find_links: + if link.startswith("~"): + new_link = normalize_path(link) + if os.path.exists(new_link): + link = new_link + built_find_links.append(link) + + # If we don't have TLS enabled, then WARN if anyplace we're looking + # relies on TLS. + if not has_tls(): + for link in itertools.chain(index_urls, built_find_links): + parsed = urllib.parse.urlparse(link) + if parsed.scheme == "https": + logger.warning( + "pip is configured with locations that require " + "TLS/SSL, however the ssl module in Python is not " + "available." + ) + break + + return cls( + find_links=built_find_links, + index_urls=index_urls, + no_index=no_index, + ) + + def get_formatted_locations(self) -> str: + lines = [] + redacted_index_urls = [] + if self.index_urls and self.index_urls != [PyPI.simple_url]: + for url in self.index_urls: + redacted_index_url = redact_auth_from_url(url) + + # Parse the URL + purl = urllib.parse.urlsplit(redacted_index_url) + + # URL is generally invalid if scheme and netloc is missing + # there are issues with Python and URL parsing, so this test + # is a bit crude. See bpo-20271, bpo-23505. Python doesn't + # always parse invalid URLs correctly - it should raise + # exceptions for malformed URLs + if not purl.scheme and not purl.netloc: + logger.warning( + 'The index url "%s" seems invalid, please provide a scheme.', + redacted_index_url, + ) + + redacted_index_urls.append(redacted_index_url) + + lines.append( + "Looking in indexes: {}".format(", ".join(redacted_index_urls)) + ) + + if self.find_links: + lines.append( + "Looking in links: {}".format( + ", ".join(redact_auth_from_url(url) for url in self.find_links) + ) + ) + return "\n".join(lines) + + def get_index_urls_locations(self, project_name: str) -> List[str]: + """Returns the locations found via self.index_urls + + Checks the url_name on the main (first in the list) index and + use this url_name to produce all locations + """ + + def mkurl_pypi_url(url: str) -> str: + loc = posixpath.join( + url, urllib.parse.quote(canonicalize_name(project_name)) + ) + # For maximum compatibility with easy_install, ensure the path + # ends in a trailing slash. Although this isn't in the spec + # (and PyPI can handle it without the slash) some other index + # implementations might break if they relied on easy_install's + # behavior. + if not loc.endswith("/"): + loc = loc + "/" + return loc + + return [mkurl_pypi_url(url) for url in self.index_urls] diff --git a/backend/.venv/Lib/site-packages/pip/_internal/models/selection_prefs.py b/backend/.venv/Lib/site-packages/pip/_internal/models/selection_prefs.py new file mode 100644 index 0000000..e9b50aa --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/models/selection_prefs.py @@ -0,0 +1,53 @@ +from typing import Optional + +from pip._internal.models.format_control import FormatControl + + +# TODO: This needs Python 3.10's improved slots support for dataclasses +# to be converted into a dataclass. +class SelectionPreferences: + """ + Encapsulates the candidate selection preferences for downloading + and installing files. + """ + + __slots__ = [ + "allow_yanked", + "allow_all_prereleases", + "format_control", + "prefer_binary", + "ignore_requires_python", + ] + + # Don't include an allow_yanked default value to make sure each call + # site considers whether yanked releases are allowed. This also causes + # that decision to be made explicit in the calling code, which helps + # people when reading the code. + def __init__( + self, + allow_yanked: bool, + allow_all_prereleases: bool = False, + format_control: Optional[FormatControl] = None, + prefer_binary: bool = False, + ignore_requires_python: Optional[bool] = None, + ) -> None: + """Create a SelectionPreferences object. + + :param allow_yanked: Whether files marked as yanked (in the sense + of PEP 592) are permitted to be candidates for install. + :param format_control: A FormatControl object or None. Used to control + the selection of source packages / binary packages when consulting + the index and links. + :param prefer_binary: Whether to prefer an old, but valid, binary + dist over a new source dist. + :param ignore_requires_python: Whether to ignore incompatible + "Requires-Python" values in links. Defaults to False. + """ + if ignore_requires_python is None: + ignore_requires_python = False + + self.allow_yanked = allow_yanked + self.allow_all_prereleases = allow_all_prereleases + self.format_control = format_control + self.prefer_binary = prefer_binary + self.ignore_requires_python = ignore_requires_python diff --git a/backend/.venv/Lib/site-packages/pip/_internal/models/target_python.py b/backend/.venv/Lib/site-packages/pip/_internal/models/target_python.py new file mode 100644 index 0000000..88925a9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/models/target_python.py @@ -0,0 +1,121 @@ +import sys +from typing import List, Optional, Set, Tuple + +from pip._vendor.packaging.tags import Tag + +from pip._internal.utils.compatibility_tags import get_supported, version_info_to_nodot +from pip._internal.utils.misc import normalize_version_info + + +class TargetPython: + """ + Encapsulates the properties of a Python interpreter one is targeting + for a package install, download, etc. + """ + + __slots__ = [ + "_given_py_version_info", + "abis", + "implementation", + "platforms", + "py_version", + "py_version_info", + "_valid_tags", + "_valid_tags_set", + ] + + def __init__( + self, + platforms: Optional[List[str]] = None, + py_version_info: Optional[Tuple[int, ...]] = None, + abis: Optional[List[str]] = None, + implementation: Optional[str] = None, + ) -> None: + """ + :param platforms: A list of strings or None. If None, searches for + packages that are supported by the current system. Otherwise, will + find packages that can be built on the platforms passed in. These + packages will only be downloaded for distribution: they will + not be built locally. + :param py_version_info: An optional tuple of ints representing the + Python version information to use (e.g. `sys.version_info[:3]`). + This can have length 1, 2, or 3 when provided. + :param abis: A list of strings or None. This is passed to + compatibility_tags.py's get_supported() function as is. + :param implementation: A string or None. This is passed to + compatibility_tags.py's get_supported() function as is. + """ + # Store the given py_version_info for when we call get_supported(). + self._given_py_version_info = py_version_info + + if py_version_info is None: + py_version_info = sys.version_info[:3] + else: + py_version_info = normalize_version_info(py_version_info) + + py_version = ".".join(map(str, py_version_info[:2])) + + self.abis = abis + self.implementation = implementation + self.platforms = platforms + self.py_version = py_version + self.py_version_info = py_version_info + + # This is used to cache the return value of get_(un)sorted_tags. + self._valid_tags: Optional[List[Tag]] = None + self._valid_tags_set: Optional[Set[Tag]] = None + + def format_given(self) -> str: + """ + Format the given, non-None attributes for display. + """ + display_version = None + if self._given_py_version_info is not None: + display_version = ".".join( + str(part) for part in self._given_py_version_info + ) + + key_values = [ + ("platforms", self.platforms), + ("version_info", display_version), + ("abis", self.abis), + ("implementation", self.implementation), + ] + return " ".join( + f"{key}={value!r}" for key, value in key_values if value is not None + ) + + def get_sorted_tags(self) -> List[Tag]: + """ + Return the supported PEP 425 tags to check wheel candidates against. + + The tags are returned in order of preference (most preferred first). + """ + if self._valid_tags is None: + # Pass versions=None if no py_version_info was given since + # versions=None uses special default logic. + py_version_info = self._given_py_version_info + if py_version_info is None: + version = None + else: + version = version_info_to_nodot(py_version_info) + + tags = get_supported( + version=version, + platforms=self.platforms, + abis=self.abis, + impl=self.implementation, + ) + self._valid_tags = tags + + return self._valid_tags + + def get_unsorted_tags(self) -> Set[Tag]: + """Exactly the same as get_sorted_tags, but returns a set. + + This is important for performance. + """ + if self._valid_tags_set is None: + self._valid_tags_set = set(self.get_sorted_tags()) + + return self._valid_tags_set diff --git a/backend/.venv/Lib/site-packages/pip/_internal/models/wheel.py b/backend/.venv/Lib/site-packages/pip/_internal/models/wheel.py new file mode 100644 index 0000000..ea85600 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/models/wheel.py @@ -0,0 +1,118 @@ +"""Represents a wheel file and provides access to the various parts of the +name that have meaning. +""" + +import re +from typing import Dict, Iterable, List + +from pip._vendor.packaging.tags import Tag +from pip._vendor.packaging.utils import ( + InvalidWheelFilename as PackagingInvalidWheelName, +) +from pip._vendor.packaging.utils import parse_wheel_filename + +from pip._internal.exceptions import InvalidWheelFilename +from pip._internal.utils.deprecation import deprecated + + +class Wheel: + """A wheel file""" + + wheel_file_re = re.compile( + r"""^(?P(?P[^\s-]+?)-(?P[^\s-]*?)) + ((-(?P\d[^-]*?))?-(?P[^\s-]+?)-(?P[^\s-]+?)-(?P[^\s-]+?) + \.whl|\.dist-info)$""", + re.VERBOSE, + ) + + def __init__(self, filename: str) -> None: + """ + :raises InvalidWheelFilename: when the filename is invalid for a wheel + """ + wheel_info = self.wheel_file_re.match(filename) + if not wheel_info: + raise InvalidWheelFilename(f"{filename} is not a valid wheel filename.") + self.filename = filename + self.name = wheel_info.group("name").replace("_", "-") + _version = wheel_info.group("ver") + if "_" in _version: + try: + parse_wheel_filename(filename) + except PackagingInvalidWheelName as e: + deprecated( + reason=( + f"Wheel filename {filename!r} is not correctly normalised. " + "Future versions of pip will raise the following error:\n" + f"{e.args[0]}\n\n" + ), + replacement=( + "to rename the wheel to use a correctly normalised " + "name (this may require updating the version in " + "the project metadata)" + ), + gone_in="25.1", + issue=12938, + ) + + _version = _version.replace("_", "-") + + self.version = _version + self.build_tag = wheel_info.group("build") + self.pyversions = wheel_info.group("pyver").split(".") + self.abis = wheel_info.group("abi").split(".") + self.plats = wheel_info.group("plat").split(".") + + # All the tag combinations from this file + self.file_tags = { + Tag(x, y, z) for x in self.pyversions for y in self.abis for z in self.plats + } + + def get_formatted_file_tags(self) -> List[str]: + """Return the wheel's tags as a sorted list of strings.""" + return sorted(str(tag) for tag in self.file_tags) + + def support_index_min(self, tags: List[Tag]) -> int: + """Return the lowest index that one of the wheel's file_tag combinations + achieves in the given list of supported tags. + + For example, if there are 8 supported tags and one of the file tags + is first in the list, then return 0. + + :param tags: the PEP 425 tags to check the wheel against, in order + with most preferred first. + + :raises ValueError: If none of the wheel's file tags match one of + the supported tags. + """ + try: + return next(i for i, t in enumerate(tags) if t in self.file_tags) + except StopIteration: + raise ValueError() + + def find_most_preferred_tag( + self, tags: List[Tag], tag_to_priority: Dict[Tag, int] + ) -> int: + """Return the priority of the most preferred tag that one of the wheel's file + tag combinations achieves in the given list of supported tags using the given + tag_to_priority mapping, where lower priorities are more-preferred. + + This is used in place of support_index_min in some cases in order to avoid + an expensive linear scan of a large list of tags. + + :param tags: the PEP 425 tags to check the wheel against. + :param tag_to_priority: a mapping from tag to priority of that tag, where + lower is more preferred. + + :raises ValueError: If none of the wheel's file tags match one of + the supported tags. + """ + return min( + tag_to_priority[tag] for tag in self.file_tags if tag in tag_to_priority + ) + + def supported(self, tags: Iterable[Tag]) -> bool: + """Return whether the wheel is compatible with one of the given tags. + + :param tags: the PEP 425 tags to check the wheel against. + """ + return not self.file_tags.isdisjoint(tags) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/network/__init__.py b/backend/.venv/Lib/site-packages/pip/_internal/network/__init__.py new file mode 100644 index 0000000..b51bde9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/network/__init__.py @@ -0,0 +1,2 @@ +"""Contains purely network-related utilities. +""" diff --git a/backend/.venv/Lib/site-packages/pip/_internal/network/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/network/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9b4bcf29d7a3061b6f2a82bb8afeb8ec342a9081 GIT binary patch literal 256 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 YZfs^B)@KaQTMUQi_x+Zmm_hFU11vJZ4*&oF literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/network/__pycache__/cache.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/network/__pycache__/cache.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a4f1dd3638339c95ae7c92a32e2e4cbbc4e6deb3 GIT binary patch literal 6453 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 dnO*znR|H-bM2RmW>V>I2sXrW{sl>U(0l*@ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/network/__pycache__/download.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/network/__pycache__/download.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..85adb61a0ed72658597c22120e248f49550f4b78 GIT binary patch literal 8481 zcmb_hZEPFInV#h?$t5X%iIk{s(;xbvEYV*|?b>c)Te71#itUS)>xFen(A9RgSa4kx9(L)5zfm66<4y+7xlY0@77?hhF{5VKJb7v~zBo{HUl8^AL6e0pE%@H${eA1G#Myx3@BBpE+8;4_rq&?+`I9T1BtV%f}PFA-h zT`70O&Fa>qC*_TJSzSz4r+g6~tJ{+PR86FY)$PgJR3H*ybw{!;RUfHOHAEUxjgdyy zR+Vf@HAk9LEs>Vgp2!}Kn25}eo-sC5DdoNIz@9Kg_DN3JA-QBx-d_*TLxSXfU5FfD ztsdDYdF57kYn9vBTT!Zpx9yUTwYEZUKRkCxHSkqKgL$HbOIB3-Pl8QNOPZQYZm(4MJKUuGhm%*3SNP$DTS z!HI-A5*(wMVJa(1Fp-uL@tB&SO4$B;oa<7E*Tm;knZ~XsWlg+1rY17!SW+_&j*lhf z5T}VR%F0+Ktzf-nSXQG_Y5u4&X_U%oNv1M|9<`Tbbs|G=^k&j&IgWFkr!<3age#L* zp2Kn=k-hXeJen$KoS6x&2CF>?*7g#=x4a{pZj2oqzGF=Ap5KB1eZZG^(gE zbzIThuoJeTXnbTmeM5oX4tSl4sZk{{C2M{vOR=~bjg6}#`X|O|QWKT2WI~m1shWV} zH4By1ahi^oq|DCM3^@<~nX-gRZgqjNjW{Nj)cq_pGd2kbwrNA$ts%tuVcw^ znH{AjJ}*z|HQV6inBExTs1LrO;BteH(u|rWvw9XdDG)q_W^l zAf&}@Vl#v@&1bpYL|75nXjx#!w1nK~AcQ($WLbojchf?;3f?eyth8cnT2P%vOI9ea zz?|i&H*5YG0G{eDzvqqj&~ExCVcM*E%kRpnMFVQJ(K=dV)GDRKXUzr>a3o#(gx^+pukexudfBtQWG#)tXA_Q9 zn~fQ><(*GkvlhjawO%Fap7L8$mVZ|?_B$<_NLI{RjdQ$8Lbgj&reKH0g{IsuDWLR0 z1~O8xRhe=b_=wG|%7wuMAtDKxG!c|4s)9vn0_t(d!!%j5fbu6Zaf)20`4Ce9hcXnb z1duQlOQZo=Mluso#27zhQ3Tw~xC+P<8%}{uQxqrlVCKL%EXmC9uuL@}ksiuuUa+F` zLqmv_H{}8OrkvEQ*a23j3C~@+aG9c}P%C618#8i>heTU&swy?3#*$GTG&CNUU}v*S zY&lN0FvDmxiw>8XXyCPidkPwfHsX|CfOUB+MsasKkI4HsS2cT#hyIsSpGdd=0IceT&*5529+@q)K==HhRy zzGB_J`Rwx1w{NU=722N3wVrv8%hjBlwLi4_=Lhdw8`eeF9mkv_=Wkt}`dB>r(0Dws zJbGU|^3dvBv+l`T_Y|yq-+uNN13w@5$a=U~*F5K3x7E(8_iat=;S*i4a&+*U9_VRuEx>{6*MoXj>y4% z#)tO>ZzA>wkt>6-AP_4fioOJ3E?_pWWl(2{Fq;I((3DX$VJxPOph_!j^}r83umqhS zbV1iErO!o6+!HmvNWTkRpTq7*ZXj@xRJraPpF6(hXv{krm--8i)|}8vkHK5bXN;CA z3(`E2JQN#Gf(;m_x0O4~VExZ9!M8a*1CpjqS&{`$^EAwpHI1T;>`0Qy00n@5p88eP zc$QSOMV7K<0N&d77N?jvlI1`?{M1j_(O!vB<=YCUD;P^lY!=<^U@|V95_8m0$AXC= z)((6MhZjsJK{++1PU?bvTva;hZp0`i&X7ej%K$+D87Xj_0FpH83#Ez;*%|COmSW=6 zctxclfu4jd(^HUXTuN670Ul8MN?HL!z}wnIs1y*MT!DY(1;`i-*j#sV9M){_c0LuGYQtO2Kz(RxCPvA354{ zf%crx&NL~$RYj1AnSm{VN3#fG7=?zN3B~_S4Nl^=3YS)?Wo60oSyP!wOce!z){^rl zna~cVg{+`_r=m8a=%nmO|A+PPl3;w*_zr%7nzN>?Fa_QN>`qVyVCSwKAAv{s&MvJt zj)QEEsmL@ejg~zIqlJ*svH?`ucAw2yRb}_v)@B03Fi&Nkl~vH}U_z2($%-B`tU?qU z22x80`v(WF1Pv##D>xKOf;%@HL?1M$X6&ea*cpAi${b(|>5Phz%T1VF(v4usfSc|u zaPxbV6a5}!8VT8%R#S9jG#+e#sV&8m&}^whN=D;>5Mp>7>?8`&fSksFgLdN--@yzH z5q7qPX%RS?-Do`YR}j5$#U+Dj+{FzxP>&8k-zfYm{|*_r!Xokb?@Z54&-6cNXnCva z&91eE&U`~>?%^kY@pG4Ffz4dtb)Q%`v829r>&;sq z`P$cAo;$;H!)vaVysJfTEx0;Xym{Bb?L)ylXD;gqZ&mc5Y@30WG5qgfXMfH>N700L zB)kVO6kp<*VWAoC#*wB<1SJXYn%^nSHqCD_(lT}fR`Z~emP;D9pI(5EQpA(NkV#hs z3&5WoOMzff(wdnCgR~#}fvpjW<^=Hg0@l&L((G!CB7}lZrH5AAak5&Ee6UB^Pr3@@ z&=pXSk7h{GTeDcVP`B8!(6Y=g|5d@;zQX0v2`W0O@0^-DH9z(4@q0b9rwWcUGkxm< zdOt!#(czwXUdKb2q@0ZCWAkZfS|l=waB$fI)F<b5v)CM(6+RXl*kS216Twf9p+~fB7iBJiyB^rZlY{y!XDBGB+LkzNOS}0A zD7#C92Ip0d&>+$&M_Rx?aIT}}=n8gON@az&s_2@tl(k5_vAUMi-@cqK!hg)QCnQUnD0GG@4IjJx!E657rl;}qQYINY^4^ouRripKo8>_ zh9}9~bIr`c!b&4!NE8kjr;&8$5R4R-oBR_a)f-=jA|#D8c-)t|(5U(Mq2h2wZ9v@EUw-5r}1AA0vK_pJC=)U`ur^M}qByys>u z>rU@{$5P*Y=icROpVsf0Hy1rkYo2|1&%WiSKK6vZ;7LR9E1tOaZCFTM(_(fZyB28A z2ijL$_e_PrsoAQcJFwK0bGPQi)~_G!A)dA`iP=_N^!XQ0E}YEyLb<9CUv;h>?av?W|M0*g-sE(_)XwTZY&c-tT9*l+IHm{`xCiF_*PuwfK^+w zjv>>K=^wa74$yp6Ad}pmFpoKF-i3QLipVS>&?O{)|{p*4H#fgOpgy-e{m61Z=_-y~fnzm(iWpK4;?b!MJvGawR z3$qv2y*2YA%ffwc>q^t7&HLxi7yZFCe_P()wmkl^zZ=lL5G|V2NMj~47N&B6 z?wqF^@^w$`qI8<_4h8spc{;C1KoAb8* zQ8@z#@S3I1#m&{8J8pXGtQ)Go4%hdY%hljaXjnz8;25ADA( znfn~J-&n0shd}jJn1)i!6wG!o0FQ0kX@FvMv4sh4;v;51g?|MB?i(>do%u+yrg=$P z_~8bR^+QKl`M~C#Z(S0W6q=~w#o zyLLddXQy9UXL%K+pTffI2L=5?zj^x%Mvqb;#N_(tW*Ju#u-kG3%I^Ai?uhjXrxHqB z{}F-xoSyxUi=nmv}v9%8~=44*Q8uKQYB5hYL zO+2l8Do@i{=!b!xQUy8uLdS7mm^e<@v=FZ5Q{wuRcs?bz&q-IFbp4JT{vEma89DVC zIrtgr{ER&H8R_|)yqG61eon6B$(0AThS|WHts!q~SUOR#9hk9fSOm_$+_6ERSh;nN zzdOB&)eToW*HpAuZ}3n)u)8+QP=eL_YB#J{6N$w&EB`pUX~U;MPT<;Bc$}ndmB$I% zHe6L)$Lg^S0>y{>S&@73rA>U?XsL!zj%*MpRwY*4Q#SEwqf_8K%XXZ{vwDCP_fFt+ Zp08X@T-z4}vag=r%N_ZWK*mhse*pm6iH`sP literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f6c0dd490d86bed7cd6765b1ff43f0b2546c24ca GIT binary patch literal 11609 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

vZp$m#b;G|N6bxm#RCn)tz(F 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 bX7P2wozKk5cO#1)X-PP|C4dbHK;VA?3t=FL literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cf2b5f280ee9770246a5e6d378f24332f418b7e1 GIT binary patch literal 2951 zcmZuzU2Gf25#Hnd^WT(3{aCUYTT;v>qTRv`4A*U%D6Zw!QH)qXldI74>24(*eY|7# zj{3u?FaiUmfdq*I6jGn+0tJ%5eduE!+w?InB5Xv&#X(#YdFUHmIjE7oboP!%rm7d< z?9A@WaBpV5+5I$=Ng^1p{^EybMMUTyREP)PW%fSV$MXX7R#85rXl50sN8S=c9s-=~5$O~4cmQ}J0!Xn9no@jBkoRX{Mm3+7_S%+!` zrNE#B!c284K1_echwn0xqzop|MP$e~k&(oF_4&R|%vCEf*PrjQ5w8qyB+9AH6YDjL z)OE{TtjrV5cIyuDN@lHY;TpC*%`+W4`A=#wS55?(`8TgzP-kW@%>3-q+{J*OZ-8Ez z35s*rTXV?u8OOG@QuqPpO_;etZ-Ykjh7osOPJ{WPe3T$750A#%&#Fk7(rH$k}w#Bm64G*5|}es z%o`jQ4Bilyq$XN|Xy42zVz@6EGDM9tQbyXyP#r88*%9!zlr(ZTc|~rbbw){EMdd?5 z0Y2i5FigD=ZN7emIIE_COIqpLQ$l#{KnzQ(rbbo!;kcG8!EhF<5U@(f2eN4!cwKD} zD-hi%XhFIG0W&lYdu9y>0>NH`*mFAft!U7M(%=3EKz_q)Bd@o4i}%sHP{=+T7Y&2F zo^4g=DfXDE++%x;&&1YSoX=H5$n-Wt#z$(;m!AL$z!Z%QRA%PNQoy^7Iwpans-|sv zsu~FJnNW2BUx%FIKmsx11Xo{y;tNEz%SdWB7-b>gTx>0o4EQElN^(GgR1`Nb_gtta zRkt+PRaKWBi3YiJ;~Q<}+ybpox31}U!LEAlw5ID$!}d&jd0KY}URc!h>)19HDy!ID zUASy6F1V(Lr@`R5wv63{x>-L3hxahCHS3feRs5+a_m%nv8GwJ=Jo5jgQi(r#6cpTZ zK%U${j|C)WZ;35wcxUXsH1(i3wr$0a@LW~x1Od~c}S8Y(xrchc?Q zV@>Ye%syD7fLj5?5Q(zlie?)Y1U60ZTMg`b>Y`(85SpSuT*YM3adA08Xi_VB+|fWl zG&W(;`~|uRluWm$K&dcZf-2B)x68SSpQ5)JA60v$6YW##Gk(H=?r5MTVT<>AWl*K( zJ20xL0}CMfe6P3!Kqhopli3pCzhaDk%cM%vePH;4&-$Xl{*k-eJ>8b%9g3BFDfZ4F zpM%2el{fsuV64@jeW_aPOEDMwxQb37Z#Z6^K;*?O*_W#{u?I#JF>fqht{#iI{%r71 zx2=}?Ix*)9ao=Xp+Ysw5`B(B9vxe5$H_;kX7Unk7(0n~;+0(R@Zb}|r_h@m>m)U@W z{-HssV9mh94Fo72tkpJ;&d$$YDPh{FOOtMCZN;>3X&HMI60iV`FKN1_4V~K7alnEV zq2EppQ$k}GBmuMyJA^Hvy))qIv@$99$#E)Y!#$N?xL0gIIZL!PLd!6adTWB^EHBg6 zpcB(GbdF{78wCXDA81)7AlqXW4w;a$mZx%K-%4-e%&?@fM^!wM|URvz~0YI>`D{6xrz3n!R@izV>{lRpMPZh>6JfE z?B-u=@(;3y-?MI6d)diWcJdCsmwmp;b`k}-&>ot+v$B4)j-FmH^KMl^e)3?)m`ID{uNe~{3TqfH| zqDg9*kC3y# z2O=#?Kmy#r;YC%6%A6K|km+`Pcs2pz0wEFu!P}^V1)+U43_&mqmqw*`X;h#xah*Po z+z15Y|GVA2Q!3r-E{f`rr|UF4({dxE(MB6~c)0uE1lV1{Msx$nfac2~y2$sb5`7K^ zLif~i?=cgG|6>%zAcTr^K1%zK$Sj!9Y`L!k>97pLJW4POw=W3tw@Q59QJ3(4IWnl1F#W-jgS82# Optional[AuthInfo]: ... + + @abstractmethod + def save_auth_info(self, url: str, username: str, password: str) -> None: ... + + +class KeyRingNullProvider(KeyRingBaseProvider): + """Keyring null provider""" + + has_keyring = False + + def get_auth_info(self, url: str, username: Optional[str]) -> Optional[AuthInfo]: + return None + + def save_auth_info(self, url: str, username: str, password: str) -> None: + return None + + +class KeyRingPythonProvider(KeyRingBaseProvider): + """Keyring interface which uses locally imported `keyring`""" + + has_keyring = True + + def __init__(self) -> None: + import keyring + + self.keyring = keyring + + def get_auth_info(self, url: str, username: Optional[str]) -> Optional[AuthInfo]: + # Support keyring's get_credential interface which supports getting + # credentials without a username. This is only available for + # keyring>=15.2.0. + if hasattr(self.keyring, "get_credential"): + logger.debug("Getting credentials from keyring for %s", url) + cred = self.keyring.get_credential(url, username) + if cred is not None: + return cred.username, cred.password + return None + + if username is not None: + logger.debug("Getting password from keyring for %s", url) + password = self.keyring.get_password(url, username) + if password: + return username, password + return None + + def save_auth_info(self, url: str, username: str, password: str) -> None: + self.keyring.set_password(url, username, password) + + +class KeyRingCliProvider(KeyRingBaseProvider): + """Provider which uses `keyring` cli + + Instead of calling the keyring package installed alongside pip + we call keyring on the command line which will enable pip to + use which ever installation of keyring is available first in + PATH. + """ + + has_keyring = True + + def __init__(self, cmd: str) -> None: + self.keyring = cmd + + def get_auth_info(self, url: str, username: Optional[str]) -> Optional[AuthInfo]: + # This is the default implementation of keyring.get_credential + # https://github.com/jaraco/keyring/blob/97689324abcf01bd1793d49063e7ca01e03d7d07/keyring/backend.py#L134-L139 + if username is not None: + password = self._get_password(url, username) + if password is not None: + return username, password + return None + + def save_auth_info(self, url: str, username: str, password: str) -> None: + return self._set_password(url, username, password) + + def _get_password(self, service_name: str, username: str) -> Optional[str]: + """Mirror the implementation of keyring.get_password using cli""" + if self.keyring is None: + return None + + cmd = [self.keyring, "get", service_name, username] + env = os.environ.copy() + env["PYTHONIOENCODING"] = "utf-8" + res = subprocess.run( + cmd, + stdin=subprocess.DEVNULL, + stdout=subprocess.PIPE, + env=env, + ) + if res.returncode: + return None + return res.stdout.decode("utf-8").strip(os.linesep) + + def _set_password(self, service_name: str, username: str, password: str) -> None: + """Mirror the implementation of keyring.set_password using cli""" + if self.keyring is None: + return None + env = os.environ.copy() + env["PYTHONIOENCODING"] = "utf-8" + subprocess.run( + [self.keyring, "set", service_name, username], + input=f"{password}{os.linesep}".encode(), + env=env, + check=True, + ) + return None + + +@lru_cache(maxsize=None) +def get_keyring_provider(provider: str) -> KeyRingBaseProvider: + logger.verbose("Keyring provider requested: %s", provider) + + # keyring has previously failed and been disabled + if KEYRING_DISABLED: + provider = "disabled" + if provider in ["import", "auto"]: + try: + impl = KeyRingPythonProvider() + logger.verbose("Keyring provider set: import") + return impl + except ImportError: + pass + except Exception as exc: + # In the event of an unexpected exception + # we should warn the user + msg = "Installed copy of keyring fails with exception %s" + if provider == "auto": + msg = msg + ", trying to find a keyring executable as a fallback" + logger.warning(msg, exc, exc_info=logger.isEnabledFor(logging.DEBUG)) + if provider in ["subprocess", "auto"]: + cli = shutil.which("keyring") + if cli and cli.startswith(sysconfig.get_path("scripts")): + # all code within this function is stolen from shutil.which implementation + @typing.no_type_check + def PATH_as_shutil_which_determines_it() -> str: + path = os.environ.get("PATH", None) + if path is None: + try: + path = os.confstr("CS_PATH") + except (AttributeError, ValueError): + # os.confstr() or CS_PATH is not available + path = os.defpath + # bpo-35755: Don't use os.defpath if the PATH environment variable is + # set to an empty string + + return path + + scripts = Path(sysconfig.get_path("scripts")) + + paths = [] + for path in PATH_as_shutil_which_determines_it().split(os.pathsep): + p = Path(path) + try: + if not p.samefile(scripts): + paths.append(path) + except FileNotFoundError: + pass + + path = os.pathsep.join(paths) + + cli = shutil.which("keyring", path=path) + + if cli: + logger.verbose("Keyring provider set: subprocess with executable %s", cli) + return KeyRingCliProvider(cli) + + logger.verbose("Keyring provider set: disabled") + return KeyRingNullProvider() + + +class MultiDomainBasicAuth(AuthBase): + def __init__( + self, + prompting: bool = True, + index_urls: Optional[List[str]] = None, + keyring_provider: str = "auto", + ) -> None: + self.prompting = prompting + self.index_urls = index_urls + self.keyring_provider = keyring_provider # type: ignore[assignment] + self.passwords: Dict[str, AuthInfo] = {} + # When the user is prompted to enter credentials and keyring is + # available, we will offer to save them. If the user accepts, + # this value is set to the credentials they entered. After the + # request authenticates, the caller should call + # ``save_credentials`` to save these. + self._credentials_to_save: Optional[Credentials] = None + + @property + def keyring_provider(self) -> KeyRingBaseProvider: + return get_keyring_provider(self._keyring_provider) + + @keyring_provider.setter + def keyring_provider(self, provider: str) -> None: + # The free function get_keyring_provider has been decorated with + # functools.cache. If an exception occurs in get_keyring_auth that + # cache will be cleared and keyring disabled, take that into account + # if you want to remove this indirection. + self._keyring_provider = provider + + @property + def use_keyring(self) -> bool: + # We won't use keyring when --no-input is passed unless + # a specific provider is requested because it might require + # user interaction + return self.prompting or self._keyring_provider not in ["auto", "disabled"] + + def _get_keyring_auth( + self, + url: Optional[str], + username: Optional[str], + ) -> Optional[AuthInfo]: + """Return the tuple auth for a given url from keyring.""" + # Do nothing if no url was provided + if not url: + return None + + try: + return self.keyring_provider.get_auth_info(url, username) + except Exception as exc: + # Log the full exception (with stacktrace) at debug, so it'll only + # show up when running in verbose mode. + logger.debug("Keyring is skipped due to an exception", exc_info=True) + # Always log a shortened version of the exception. + logger.warning( + "Keyring is skipped due to an exception: %s", + str(exc), + ) + global KEYRING_DISABLED + KEYRING_DISABLED = True + get_keyring_provider.cache_clear() + return None + + def _get_index_url(self, url: str) -> Optional[str]: + """Return the original index URL matching the requested URL. + + Cached or dynamically generated credentials may work against + the original index URL rather than just the netloc. + + The provided url should have had its username and password + removed already. If the original index url had credentials then + they will be included in the return value. + + Returns None if no matching index was found, or if --no-index + was specified by the user. + """ + if not url or not self.index_urls: + return None + + url = remove_auth_from_url(url).rstrip("/") + "/" + parsed_url = urllib.parse.urlsplit(url) + + candidates = [] + + for index in self.index_urls: + index = index.rstrip("/") + "/" + parsed_index = urllib.parse.urlsplit(remove_auth_from_url(index)) + if parsed_url == parsed_index: + return index + + if parsed_url.netloc != parsed_index.netloc: + continue + + candidate = urllib.parse.urlsplit(index) + candidates.append(candidate) + + if not candidates: + return None + + candidates.sort( + reverse=True, + key=lambda candidate: commonprefix( + [ + parsed_url.path, + candidate.path, + ] + ).rfind("/"), + ) + + return urllib.parse.urlunsplit(candidates[0]) + + def _get_new_credentials( + self, + original_url: str, + *, + allow_netrc: bool = True, + allow_keyring: bool = False, + ) -> AuthInfo: + """Find and return credentials for the specified URL.""" + # Split the credentials and netloc from the url. + url, netloc, url_user_password = split_auth_netloc_from_url( + original_url, + ) + + # Start with the credentials embedded in the url + username, password = url_user_password + if username is not None and password is not None: + logger.debug("Found credentials in url for %s", netloc) + return url_user_password + + # Find a matching index url for this request + index_url = self._get_index_url(url) + if index_url: + # Split the credentials from the url. + index_info = split_auth_netloc_from_url(index_url) + if index_info: + index_url, _, index_url_user_password = index_info + logger.debug("Found index url %s", index_url) + + # If an index URL was found, try its embedded credentials + if index_url and index_url_user_password[0] is not None: + username, password = index_url_user_password + if username is not None and password is not None: + logger.debug("Found credentials in index url for %s", netloc) + return index_url_user_password + + # Get creds from netrc if we still don't have them + if allow_netrc: + netrc_auth = get_netrc_auth(original_url) + if netrc_auth: + logger.debug("Found credentials in netrc for %s", netloc) + return netrc_auth + + # If we don't have a password and keyring is available, use it. + if allow_keyring: + # The index url is more specific than the netloc, so try it first + # fmt: off + kr_auth = ( + self._get_keyring_auth(index_url, username) or + self._get_keyring_auth(netloc, username) + ) + # fmt: on + if kr_auth: + logger.debug("Found credentials in keyring for %s", netloc) + return kr_auth + + return username, password + + def _get_url_and_credentials( + self, original_url: str + ) -> Tuple[str, Optional[str], Optional[str]]: + """Return the credentials to use for the provided URL. + + If allowed, netrc and keyring may be used to obtain the + correct credentials. + + Returns (url_without_credentials, username, password). Note + that even if the original URL contains credentials, this + function may return a different username and password. + """ + url, netloc, _ = split_auth_netloc_from_url(original_url) + + # Try to get credentials from original url + username, password = self._get_new_credentials(original_url) + + # If credentials not found, use any stored credentials for this netloc. + # Do this if either the username or the password is missing. + # This accounts for the situation in which the user has specified + # the username in the index url, but the password comes from keyring. + if (username is None or password is None) and netloc in self.passwords: + un, pw = self.passwords[netloc] + # It is possible that the cached credentials are for a different username, + # in which case the cache should be ignored. + if username is None or username == un: + username, password = un, pw + + if username is not None or password is not None: + # Convert the username and password if they're None, so that + # this netloc will show up as "cached" in the conditional above. + # Further, HTTPBasicAuth doesn't accept None, so it makes sense to + # cache the value that is going to be used. + username = username or "" + password = password or "" + + # Store any acquired credentials. + self.passwords[netloc] = (username, password) + + assert ( + # Credentials were found + (username is not None and password is not None) + # Credentials were not found + or (username is None and password is None) + ), f"Could not load credentials from url: {original_url}" + + return url, username, password + + def __call__(self, req: Request) -> Request: + # Get credentials for this request + url, username, password = self._get_url_and_credentials(req.url) + + # Set the url of the request to the url without any credentials + req.url = url + + if username is not None and password is not None: + # Send the basic auth with this request + req = HTTPBasicAuth(username, password)(req) + + # Attach a hook to handle 401 responses + req.register_hook("response", self.handle_401) + + return req + + # Factored out to allow for easy patching in tests + def _prompt_for_password( + self, netloc: str + ) -> Tuple[Optional[str], Optional[str], bool]: + username = ask_input(f"User for {netloc}: ") if self.prompting else None + if not username: + return None, None, False + if self.use_keyring: + auth = self._get_keyring_auth(netloc, username) + if auth and auth[0] is not None and auth[1] is not None: + return auth[0], auth[1], False + password = ask_password("Password: ") + return username, password, True + + # Factored out to allow for easy patching in tests + def _should_save_password_to_keyring(self) -> bool: + if ( + not self.prompting + or not self.use_keyring + or not self.keyring_provider.has_keyring + ): + return False + return ask("Save credentials to keyring [y/N]: ", ["y", "n"]) == "y" + + def handle_401(self, resp: Response, **kwargs: Any) -> Response: + # We only care about 401 responses, anything else we want to just + # pass through the actual response + if resp.status_code != 401: + return resp + + username, password = None, None + + # Query the keyring for credentials: + if self.use_keyring: + username, password = self._get_new_credentials( + resp.url, + allow_netrc=False, + allow_keyring=True, + ) + + # We are not able to prompt the user so simply return the response + if not self.prompting and not username and not password: + return resp + + parsed = urllib.parse.urlparse(resp.url) + + # Prompt the user for a new username and password + save = False + if not username and not password: + username, password, save = self._prompt_for_password(parsed.netloc) + + # Store the new username and password to use for future requests + self._credentials_to_save = None + if username is not None and password is not None: + self.passwords[parsed.netloc] = (username, password) + + # Prompt to save the password to keyring + if save and self._should_save_password_to_keyring(): + self._credentials_to_save = Credentials( + url=parsed.netloc, + username=username, + password=password, + ) + + # Consume content and release the original connection to allow our new + # request to reuse the same one. + # The result of the assignment isn't used, it's just needed to consume + # the content. + _ = resp.content + resp.raw.release_conn() + + # Add our new username and password to the request + req = HTTPBasicAuth(username or "", password or "")(resp.request) + req.register_hook("response", self.warn_on_401) + + # On successful request, save the credentials that were used to + # keyring. (Note that if the user responded "no" above, this member + # is not set and nothing will be saved.) + if self._credentials_to_save: + req.register_hook("response", self.save_credentials) + + # Send our new request + new_resp = resp.connection.send(req, **kwargs) + new_resp.history.append(resp) + + return new_resp + + def warn_on_401(self, resp: Response, **kwargs: Any) -> None: + """Response callback to warn about incorrect credentials.""" + if resp.status_code == 401: + logger.warning( + "401 Error, Credentials not correct for %s", + resp.request.url, + ) + + def save_credentials(self, resp: Response, **kwargs: Any) -> None: + """Response callback to save credentials on success.""" + assert ( + self.keyring_provider.has_keyring + ), "should never reach here without keyring" + + creds = self._credentials_to_save + self._credentials_to_save = None + if creds and resp.status_code < 400: + try: + logger.info("Saving credentials to keyring") + self.keyring_provider.save_auth_info( + creds.url, creds.username, creds.password + ) + except Exception: + logger.exception("Failed to save credentials") diff --git a/backend/.venv/Lib/site-packages/pip/_internal/network/cache.py b/backend/.venv/Lib/site-packages/pip/_internal/network/cache.py new file mode 100644 index 0000000..4d0fb54 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/network/cache.py @@ -0,0 +1,106 @@ +"""HTTP cache implementation. +""" + +import os +from contextlib import contextmanager +from datetime import datetime +from typing import BinaryIO, Generator, Optional, Union + +from pip._vendor.cachecontrol.cache import SeparateBodyBaseCache +from pip._vendor.cachecontrol.caches import SeparateBodyFileCache +from pip._vendor.requests.models import Response + +from pip._internal.utils.filesystem import adjacent_tmp_file, replace +from pip._internal.utils.misc import ensure_dir + + +def is_from_cache(response: Response) -> bool: + return getattr(response, "from_cache", False) + + +@contextmanager +def suppressed_cache_errors() -> Generator[None, None, None]: + """If we can't access the cache then we can just skip caching and process + requests as if caching wasn't enabled. + """ + try: + yield + except OSError: + pass + + +class SafeFileCache(SeparateBodyBaseCache): + """ + A file based cache which is safe to use even when the target directory may + not be accessible or writable. + + There is a race condition when two processes try to write and/or read the + same entry at the same time, since each entry consists of two separate + files (https://github.com/psf/cachecontrol/issues/324). We therefore have + additional logic that makes sure that both files to be present before + returning an entry; this fixes the read side of the race condition. + + For the write side, we assume that the server will only ever return the + same data for the same URL, which ought to be the case for files pip is + downloading. PyPI does not have a mechanism to swap out a wheel for + another wheel, for example. If this assumption is not true, the + CacheControl issue will need to be fixed. + """ + + def __init__(self, directory: str) -> None: + assert directory is not None, "Cache directory must not be None." + super().__init__() + self.directory = directory + + def _get_cache_path(self, name: str) -> str: + # From cachecontrol.caches.file_cache.FileCache._fn, brought into our + # class for backwards-compatibility and to avoid using a non-public + # method. + hashed = SeparateBodyFileCache.encode(name) + parts = list(hashed[:5]) + [hashed] + return os.path.join(self.directory, *parts) + + def get(self, key: str) -> Optional[bytes]: + # The cache entry is only valid if both metadata and body exist. + metadata_path = self._get_cache_path(key) + body_path = metadata_path + ".body" + if not (os.path.exists(metadata_path) and os.path.exists(body_path)): + return None + with suppressed_cache_errors(): + with open(metadata_path, "rb") as f: + return f.read() + + def _write(self, path: str, data: bytes) -> None: + with suppressed_cache_errors(): + ensure_dir(os.path.dirname(path)) + + with adjacent_tmp_file(path) as f: + f.write(data) + + replace(f.name, path) + + def set( + self, key: str, value: bytes, expires: Union[int, datetime, None] = None + ) -> None: + path = self._get_cache_path(key) + self._write(path, value) + + def delete(self, key: str) -> None: + path = self._get_cache_path(key) + with suppressed_cache_errors(): + os.remove(path) + with suppressed_cache_errors(): + os.remove(path + ".body") + + def get_body(self, key: str) -> Optional[BinaryIO]: + # The cache entry is only valid if both metadata and body exist. + metadata_path = self._get_cache_path(key) + body_path = metadata_path + ".body" + if not (os.path.exists(metadata_path) and os.path.exists(body_path)): + return None + with suppressed_cache_errors(): + return open(body_path, "rb") + + def set_body(self, key: str, body: bytes) -> None: + path = self._get_cache_path(key) + ".body" + self._write(path, body) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/network/download.py b/backend/.venv/Lib/site-packages/pip/_internal/network/download.py new file mode 100644 index 0000000..5c3bce3 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/network/download.py @@ -0,0 +1,187 @@ +"""Download files with progress indicators. +""" + +import email.message +import logging +import mimetypes +import os +from typing import Iterable, Optional, Tuple + +from pip._vendor.requests.models import Response + +from pip._internal.cli.progress_bars import get_download_progress_renderer +from pip._internal.exceptions import NetworkConnectionError +from pip._internal.models.index import PyPI +from pip._internal.models.link import Link +from pip._internal.network.cache import is_from_cache +from pip._internal.network.session import PipSession +from pip._internal.network.utils import HEADERS, raise_for_status, response_chunks +from pip._internal.utils.misc import format_size, redact_auth_from_url, splitext + +logger = logging.getLogger(__name__) + + +def _get_http_response_size(resp: Response) -> Optional[int]: + try: + return int(resp.headers["content-length"]) + except (ValueError, KeyError, TypeError): + return None + + +def _prepare_download( + resp: Response, + link: Link, + progress_bar: str, +) -> Iterable[bytes]: + total_length = _get_http_response_size(resp) + + if link.netloc == PyPI.file_storage_domain: + url = link.show_url + else: + url = link.url_without_fragment + + logged_url = redact_auth_from_url(url) + + if total_length: + logged_url = f"{logged_url} ({format_size(total_length)})" + + if is_from_cache(resp): + logger.info("Using cached %s", logged_url) + else: + logger.info("Downloading %s", logged_url) + + if logger.getEffectiveLevel() > logging.INFO: + show_progress = False + elif is_from_cache(resp): + show_progress = False + elif not total_length: + show_progress = True + elif total_length > (512 * 1024): + show_progress = True + else: + show_progress = False + + chunks = response_chunks(resp) + + if not show_progress: + return chunks + + renderer = get_download_progress_renderer(bar_type=progress_bar, size=total_length) + return renderer(chunks) + + +def sanitize_content_filename(filename: str) -> str: + """ + Sanitize the "filename" value from a Content-Disposition header. + """ + return os.path.basename(filename) + + +def parse_content_disposition(content_disposition: str, default_filename: str) -> str: + """ + Parse the "filename" value from a Content-Disposition header, and + return the default filename if the result is empty. + """ + m = email.message.Message() + m["content-type"] = content_disposition + filename = m.get_param("filename") + if filename: + # We need to sanitize the filename to prevent directory traversal + # in case the filename contains ".." path parts. + filename = sanitize_content_filename(str(filename)) + return filename or default_filename + + +def _get_http_response_filename(resp: Response, link: Link) -> str: + """Get an ideal filename from the given HTTP response, falling back to + the link filename if not provided. + """ + filename = link.filename # fallback + # Have a look at the Content-Disposition header for a better guess + content_disposition = resp.headers.get("content-disposition") + if content_disposition: + filename = parse_content_disposition(content_disposition, filename) + ext: Optional[str] = splitext(filename)[1] + if not ext: + ext = mimetypes.guess_extension(resp.headers.get("content-type", "")) + if ext: + filename += ext + if not ext and link.url != resp.url: + ext = os.path.splitext(resp.url)[1] + if ext: + filename += ext + return filename + + +def _http_get_download(session: PipSession, link: Link) -> Response: + target_url = link.url.split("#", 1)[0] + resp = session.get(target_url, headers=HEADERS, stream=True) + raise_for_status(resp) + return resp + + +class Downloader: + def __init__( + self, + session: PipSession, + progress_bar: str, + ) -> None: + self._session = session + self._progress_bar = progress_bar + + def __call__(self, link: Link, location: str) -> Tuple[str, str]: + """Download the file given by link into location.""" + try: + resp = _http_get_download(self._session, link) + except NetworkConnectionError as e: + assert e.response is not None + logger.critical( + "HTTP error %s while getting %s", e.response.status_code, link + ) + raise + + filename = _get_http_response_filename(resp, link) + filepath = os.path.join(location, filename) + + chunks = _prepare_download(resp, link, self._progress_bar) + with open(filepath, "wb") as content_file: + for chunk in chunks: + content_file.write(chunk) + content_type = resp.headers.get("Content-Type", "") + return filepath, content_type + + +class BatchDownloader: + def __init__( + self, + session: PipSession, + progress_bar: str, + ) -> None: + self._session = session + self._progress_bar = progress_bar + + def __call__( + self, links: Iterable[Link], location: str + ) -> Iterable[Tuple[Link, Tuple[str, str]]]: + """Download the files given by links into location.""" + for link in links: + try: + resp = _http_get_download(self._session, link) + except NetworkConnectionError as e: + assert e.response is not None + logger.critical( + "HTTP error %s while getting %s", + e.response.status_code, + link, + ) + raise + + filename = _get_http_response_filename(resp, link) + filepath = os.path.join(location, filename) + + chunks = _prepare_download(resp, link, self._progress_bar) + with open(filepath, "wb") as content_file: + for chunk in chunks: + content_file.write(chunk) + content_type = resp.headers.get("Content-Type", "") + yield link, (filepath, content_type) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py b/backend/.venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py new file mode 100644 index 0000000..03f883c --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py @@ -0,0 +1,210 @@ +"""Lazy ZIP over HTTP""" + +__all__ = ["HTTPRangeRequestUnsupported", "dist_from_wheel_url"] + +from bisect import bisect_left, bisect_right +from contextlib import contextmanager +from tempfile import NamedTemporaryFile +from typing import Any, Dict, Generator, List, Optional, Tuple +from zipfile import BadZipFile, ZipFile + +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.requests.models import CONTENT_CHUNK_SIZE, Response + +from pip._internal.metadata import BaseDistribution, MemoryWheel, get_wheel_distribution +from pip._internal.network.session import PipSession +from pip._internal.network.utils import HEADERS, raise_for_status, response_chunks + + +class HTTPRangeRequestUnsupported(Exception): + pass + + +def dist_from_wheel_url(name: str, url: str, session: PipSession) -> BaseDistribution: + """Return a distribution object from the given wheel URL. + + This uses HTTP range requests to only fetch the portion of the wheel + containing metadata, just enough for the object to be constructed. + If such requests are not supported, HTTPRangeRequestUnsupported + is raised. + """ + with LazyZipOverHTTP(url, session) as zf: + # For read-only ZIP files, ZipFile only needs methods read, + # seek, seekable and tell, not the whole IO protocol. + wheel = MemoryWheel(zf.name, zf) # type: ignore + # After context manager exit, wheel.name + # is an invalid file by intention. + return get_wheel_distribution(wheel, canonicalize_name(name)) + + +class LazyZipOverHTTP: + """File-like object mapped to a ZIP file over HTTP. + + This uses HTTP range requests to lazily fetch the file's content, + which is supposed to be fed to ZipFile. If such requests are not + supported by the server, raise HTTPRangeRequestUnsupported + during initialization. + """ + + def __init__( + self, url: str, session: PipSession, chunk_size: int = CONTENT_CHUNK_SIZE + ) -> None: + head = session.head(url, headers=HEADERS) + raise_for_status(head) + assert head.status_code == 200 + self._session, self._url, self._chunk_size = session, url, chunk_size + self._length = int(head.headers["Content-Length"]) + self._file = NamedTemporaryFile() + self.truncate(self._length) + self._left: List[int] = [] + self._right: List[int] = [] + if "bytes" not in head.headers.get("Accept-Ranges", "none"): + raise HTTPRangeRequestUnsupported("range request is not supported") + self._check_zip() + + @property + def mode(self) -> str: + """Opening mode, which is always rb.""" + return "rb" + + @property + def name(self) -> str: + """Path to the underlying file.""" + return self._file.name + + def seekable(self) -> bool: + """Return whether random access is supported, which is True.""" + return True + + def close(self) -> None: + """Close the file.""" + self._file.close() + + @property + def closed(self) -> bool: + """Whether the file is closed.""" + return self._file.closed + + def read(self, size: int = -1) -> bytes: + """Read up to size bytes from the object and return them. + + As a convenience, if size is unspecified or -1, + all bytes until EOF are returned. Fewer than + size bytes may be returned if EOF is reached. + """ + download_size = max(size, self._chunk_size) + start, length = self.tell(), self._length + stop = length if size < 0 else min(start + download_size, length) + start = max(0, stop - download_size) + self._download(start, stop - 1) + return self._file.read(size) + + def readable(self) -> bool: + """Return whether the file is readable, which is True.""" + return True + + def seek(self, offset: int, whence: int = 0) -> int: + """Change stream position and return the new absolute position. + + Seek to offset relative position indicated by whence: + * 0: Start of stream (the default). pos should be >= 0; + * 1: Current position - pos may be negative; + * 2: End of stream - pos usually negative. + """ + return self._file.seek(offset, whence) + + def tell(self) -> int: + """Return the current position.""" + return self._file.tell() + + def truncate(self, size: Optional[int] = None) -> int: + """Resize the stream to the given size in bytes. + + If size is unspecified resize to the current position. + The current stream position isn't changed. + + Return the new file size. + """ + return self._file.truncate(size) + + def writable(self) -> bool: + """Return False.""" + return False + + def __enter__(self) -> "LazyZipOverHTTP": + self._file.__enter__() + return self + + def __exit__(self, *exc: Any) -> None: + self._file.__exit__(*exc) + + @contextmanager + def _stay(self) -> Generator[None, None, None]: + """Return a context manager keeping the position. + + At the end of the block, seek back to original position. + """ + pos = self.tell() + try: + yield + finally: + self.seek(pos) + + def _check_zip(self) -> None: + """Check and download until the file is a valid ZIP.""" + end = self._length - 1 + for start in reversed(range(0, end, self._chunk_size)): + self._download(start, end) + with self._stay(): + try: + # For read-only ZIP files, ZipFile only needs + # methods read, seek, seekable and tell. + ZipFile(self) + except BadZipFile: + pass + else: + break + + def _stream_response( + self, start: int, end: int, base_headers: Dict[str, str] = HEADERS + ) -> Response: + """Return HTTP response to a range request from start to end.""" + headers = base_headers.copy() + headers["Range"] = f"bytes={start}-{end}" + # TODO: Get range requests to be correctly cached + headers["Cache-Control"] = "no-cache" + return self._session.get(self._url, headers=headers, stream=True) + + def _merge( + self, start: int, end: int, left: int, right: int + ) -> Generator[Tuple[int, int], None, None]: + """Return a generator of intervals to be fetched. + + Args: + start (int): Start of needed interval + end (int): End of needed interval + left (int): Index of first overlapping downloaded data + right (int): Index after last overlapping downloaded data + """ + lslice, rslice = self._left[left:right], self._right[left:right] + i = start = min([start] + lslice[:1]) + end = max([end] + rslice[-1:]) + for j, k in zip(lslice, rslice): + if j > i: + yield i, j - 1 + i = k + 1 + if i <= end: + yield i, end + self._left[left:right], self._right[left:right] = [start], [end] + + def _download(self, start: int, end: int) -> None: + """Download bytes from start to end inclusively.""" + with self._stay(): + left = bisect_left(self._right, start) + right = bisect_right(self._left, end) + for start, end in self._merge(start, end, left, right): + response = self._stream_response(start, end) + response.raise_for_status() + self.seek(start) + for chunk in response_chunks(response, self._chunk_size): + self._file.write(chunk) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/network/session.py b/backend/.venv/Lib/site-packages/pip/_internal/network/session.py new file mode 100644 index 0000000..1765b4f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/network/session.py @@ -0,0 +1,522 @@ +"""PipSession and supporting code, containing all pip-specific +network request configuration and behavior. +""" + +import email.utils +import functools +import io +import ipaddress +import json +import logging +import mimetypes +import os +import platform +import shutil +import subprocess +import sys +import urllib.parse +import warnings +from typing import ( + TYPE_CHECKING, + Any, + Dict, + Generator, + List, + Mapping, + Optional, + Sequence, + Tuple, + Union, +) + +from pip._vendor import requests, urllib3 +from pip._vendor.cachecontrol import CacheControlAdapter as _BaseCacheControlAdapter +from pip._vendor.requests.adapters import DEFAULT_POOLBLOCK, BaseAdapter +from pip._vendor.requests.adapters import HTTPAdapter as _BaseHTTPAdapter +from pip._vendor.requests.models import PreparedRequest, Response +from pip._vendor.requests.structures import CaseInsensitiveDict +from pip._vendor.urllib3.connectionpool import ConnectionPool +from pip._vendor.urllib3.exceptions import InsecureRequestWarning + +from pip import __version__ +from pip._internal.metadata import get_default_environment +from pip._internal.models.link import Link +from pip._internal.network.auth import MultiDomainBasicAuth +from pip._internal.network.cache import SafeFileCache + +# Import ssl from compat so the initial import occurs in only one place. +from pip._internal.utils.compat import has_tls +from pip._internal.utils.glibc import libc_ver +from pip._internal.utils.misc import build_url_from_netloc, parse_netloc +from pip._internal.utils.urls import url_to_path + +if TYPE_CHECKING: + from ssl import SSLContext + + from pip._vendor.urllib3.poolmanager import PoolManager + + +logger = logging.getLogger(__name__) + +SecureOrigin = Tuple[str, str, Optional[Union[int, str]]] + + +# Ignore warning raised when using --trusted-host. +warnings.filterwarnings("ignore", category=InsecureRequestWarning) + + +SECURE_ORIGINS: List[SecureOrigin] = [ + # protocol, hostname, port + # Taken from Chrome's list of secure origins (See: http://bit.ly/1qrySKC) + ("https", "*", "*"), + ("*", "localhost", "*"), + ("*", "127.0.0.0/8", "*"), + ("*", "::1/128", "*"), + ("file", "*", None), + # ssh is always secure. + ("ssh", "*", "*"), +] + + +# These are environment variables present when running under various +# CI systems. For each variable, some CI systems that use the variable +# are indicated. The collection was chosen so that for each of a number +# of popular systems, at least one of the environment variables is used. +# This list is used to provide some indication of and lower bound for +# CI traffic to PyPI. Thus, it is okay if the list is not comprehensive. +# For more background, see: https://github.com/pypa/pip/issues/5499 +CI_ENVIRONMENT_VARIABLES = ( + # Azure Pipelines + "BUILD_BUILDID", + # Jenkins + "BUILD_ID", + # AppVeyor, CircleCI, Codeship, Gitlab CI, Shippable, Travis CI + "CI", + # Explicit environment variable. + "PIP_IS_CI", +) + + +def looks_like_ci() -> bool: + """ + Return whether it looks like pip is running under CI. + """ + # We don't use the method of checking for a tty (e.g. using isatty()) + # because some CI systems mimic a tty (e.g. Travis CI). Thus that + # method doesn't provide definitive information in either direction. + return any(name in os.environ for name in CI_ENVIRONMENT_VARIABLES) + + +@functools.lru_cache(maxsize=1) +def user_agent() -> str: + """ + Return a string representing the user agent. + """ + data: Dict[str, Any] = { + "installer": {"name": "pip", "version": __version__}, + "python": platform.python_version(), + "implementation": { + "name": platform.python_implementation(), + }, + } + + if data["implementation"]["name"] == "CPython": + data["implementation"]["version"] = platform.python_version() + elif data["implementation"]["name"] == "PyPy": + pypy_version_info = sys.pypy_version_info # type: ignore + if pypy_version_info.releaselevel == "final": + pypy_version_info = pypy_version_info[:3] + data["implementation"]["version"] = ".".join( + [str(x) for x in pypy_version_info] + ) + elif data["implementation"]["name"] == "Jython": + # Complete Guess + data["implementation"]["version"] = platform.python_version() + elif data["implementation"]["name"] == "IronPython": + # Complete Guess + data["implementation"]["version"] = platform.python_version() + + if sys.platform.startswith("linux"): + from pip._vendor import distro + + linux_distribution = distro.name(), distro.version(), distro.codename() + distro_infos: Dict[str, Any] = dict( + filter( + lambda x: x[1], + zip(["name", "version", "id"], linux_distribution), + ) + ) + libc = dict( + filter( + lambda x: x[1], + zip(["lib", "version"], libc_ver()), + ) + ) + if libc: + distro_infos["libc"] = libc + if distro_infos: + data["distro"] = distro_infos + + if sys.platform.startswith("darwin") and platform.mac_ver()[0]: + data["distro"] = {"name": "macOS", "version": platform.mac_ver()[0]} + + if platform.system(): + data.setdefault("system", {})["name"] = platform.system() + + if platform.release(): + data.setdefault("system", {})["release"] = platform.release() + + if platform.machine(): + data["cpu"] = platform.machine() + + if has_tls(): + import _ssl as ssl + + data["openssl_version"] = ssl.OPENSSL_VERSION + + setuptools_dist = get_default_environment().get_distribution("setuptools") + if setuptools_dist is not None: + data["setuptools_version"] = str(setuptools_dist.version) + + if shutil.which("rustc") is not None: + # If for any reason `rustc --version` fails, silently ignore it + try: + rustc_output = subprocess.check_output( + ["rustc", "--version"], stderr=subprocess.STDOUT, timeout=0.5 + ) + except Exception: + pass + else: + if rustc_output.startswith(b"rustc "): + # The format of `rustc --version` is: + # `b'rustc 1.52.1 (9bc8c42bb 2021-05-09)\n'` + # We extract just the middle (1.52.1) part + data["rustc_version"] = rustc_output.split(b" ")[1].decode() + + # Use None rather than False so as not to give the impression that + # pip knows it is not being run under CI. Rather, it is a null or + # inconclusive result. Also, we include some value rather than no + # value to make it easier to know that the check has been run. + data["ci"] = True if looks_like_ci() else None + + user_data = os.environ.get("PIP_USER_AGENT_USER_DATA") + if user_data is not None: + data["user_data"] = user_data + + return "{data[installer][name]}/{data[installer][version]} {json}".format( + data=data, + json=json.dumps(data, separators=(",", ":"), sort_keys=True), + ) + + +class LocalFSAdapter(BaseAdapter): + def send( + self, + request: PreparedRequest, + stream: bool = False, + timeout: Optional[Union[float, Tuple[float, float]]] = None, + verify: Union[bool, str] = True, + cert: Optional[Union[str, Tuple[str, str]]] = None, + proxies: Optional[Mapping[str, str]] = None, + ) -> Response: + pathname = url_to_path(request.url) + + resp = Response() + resp.status_code = 200 + resp.url = request.url + + try: + stats = os.stat(pathname) + except OSError as exc: + # format the exception raised as a io.BytesIO object, + # to return a better error message: + resp.status_code = 404 + resp.reason = type(exc).__name__ + resp.raw = io.BytesIO(f"{resp.reason}: {exc}".encode()) + else: + modified = email.utils.formatdate(stats.st_mtime, usegmt=True) + content_type = mimetypes.guess_type(pathname)[0] or "text/plain" + resp.headers = CaseInsensitiveDict( + { + "Content-Type": content_type, + "Content-Length": stats.st_size, + "Last-Modified": modified, + } + ) + + resp.raw = open(pathname, "rb") + resp.close = resp.raw.close + + return resp + + def close(self) -> None: + pass + + +class _SSLContextAdapterMixin: + """Mixin to add the ``ssl_context`` constructor argument to HTTP adapters. + + The additional argument is forwarded directly to the pool manager. This allows us + to dynamically decide what SSL store to use at runtime, which is used to implement + the optional ``truststore`` backend. + """ + + def __init__( + self, + *, + ssl_context: Optional["SSLContext"] = None, + **kwargs: Any, + ) -> None: + self._ssl_context = ssl_context + super().__init__(**kwargs) + + def init_poolmanager( + self, + connections: int, + maxsize: int, + block: bool = DEFAULT_POOLBLOCK, + **pool_kwargs: Any, + ) -> "PoolManager": + if self._ssl_context is not None: + pool_kwargs.setdefault("ssl_context", self._ssl_context) + return super().init_poolmanager( # type: ignore[misc] + connections=connections, + maxsize=maxsize, + block=block, + **pool_kwargs, + ) + + +class HTTPAdapter(_SSLContextAdapterMixin, _BaseHTTPAdapter): + pass + + +class CacheControlAdapter(_SSLContextAdapterMixin, _BaseCacheControlAdapter): + pass + + +class InsecureHTTPAdapter(HTTPAdapter): + def cert_verify( + self, + conn: ConnectionPool, + url: str, + verify: Union[bool, str], + cert: Optional[Union[str, Tuple[str, str]]], + ) -> None: + super().cert_verify(conn=conn, url=url, verify=False, cert=cert) + + +class InsecureCacheControlAdapter(CacheControlAdapter): + def cert_verify( + self, + conn: ConnectionPool, + url: str, + verify: Union[bool, str], + cert: Optional[Union[str, Tuple[str, str]]], + ) -> None: + super().cert_verify(conn=conn, url=url, verify=False, cert=cert) + + +class PipSession(requests.Session): + timeout: Optional[int] = None + + def __init__( + self, + *args: Any, + retries: int = 0, + cache: Optional[str] = None, + trusted_hosts: Sequence[str] = (), + index_urls: Optional[List[str]] = None, + ssl_context: Optional["SSLContext"] = None, + **kwargs: Any, + ) -> None: + """ + :param trusted_hosts: Domains not to emit warnings for when not using + HTTPS. + """ + super().__init__(*args, **kwargs) + + # Namespace the attribute with "pip_" just in case to prevent + # possible conflicts with the base class. + self.pip_trusted_origins: List[Tuple[str, Optional[int]]] = [] + + # Attach our User Agent to the request + self.headers["User-Agent"] = user_agent() + + # Attach our Authentication handler to the session + self.auth = MultiDomainBasicAuth(index_urls=index_urls) + + # Create our urllib3.Retry instance which will allow us to customize + # how we handle retries. + retries = urllib3.Retry( + # Set the total number of retries that a particular request can + # have. + total=retries, + # A 503 error from PyPI typically means that the Fastly -> Origin + # connection got interrupted in some way. A 503 error in general + # is typically considered a transient error so we'll go ahead and + # retry it. + # A 500 may indicate transient error in Amazon S3 + # A 502 may be a transient error from a CDN like CloudFlare or CloudFront + # A 520 or 527 - may indicate transient error in CloudFlare + status_forcelist=[500, 502, 503, 520, 527], + # Add a small amount of back off between failed requests in + # order to prevent hammering the service. + backoff_factor=0.25, + ) # type: ignore + + # Our Insecure HTTPAdapter disables HTTPS validation. It does not + # support caching so we'll use it for all http:// URLs. + # If caching is disabled, we will also use it for + # https:// hosts that we've marked as ignoring + # TLS errors for (trusted-hosts). + insecure_adapter = InsecureHTTPAdapter(max_retries=retries) + + # We want to _only_ cache responses on securely fetched origins or when + # the host is specified as trusted. We do this because + # we can't validate the response of an insecurely/untrusted fetched + # origin, and we don't want someone to be able to poison the cache and + # require manual eviction from the cache to fix it. + if cache: + secure_adapter = CacheControlAdapter( + cache=SafeFileCache(cache), + max_retries=retries, + ssl_context=ssl_context, + ) + self._trusted_host_adapter = InsecureCacheControlAdapter( + cache=SafeFileCache(cache), + max_retries=retries, + ) + else: + secure_adapter = HTTPAdapter(max_retries=retries, ssl_context=ssl_context) + self._trusted_host_adapter = insecure_adapter + + self.mount("https://", secure_adapter) + self.mount("http://", insecure_adapter) + + # Enable file:// urls + self.mount("file://", LocalFSAdapter()) + + for host in trusted_hosts: + self.add_trusted_host(host, suppress_logging=True) + + def update_index_urls(self, new_index_urls: List[str]) -> None: + """ + :param new_index_urls: New index urls to update the authentication + handler with. + """ + self.auth.index_urls = new_index_urls + + def add_trusted_host( + self, host: str, source: Optional[str] = None, suppress_logging: bool = False + ) -> None: + """ + :param host: It is okay to provide a host that has previously been + added. + :param source: An optional source string, for logging where the host + string came from. + """ + if not suppress_logging: + msg = f"adding trusted host: {host!r}" + if source is not None: + msg += f" (from {source})" + logger.info(msg) + + parsed_host, parsed_port = parse_netloc(host) + if parsed_host is None: + raise ValueError(f"Trusted host URL must include a host part: {host!r}") + if (parsed_host, parsed_port) not in self.pip_trusted_origins: + self.pip_trusted_origins.append((parsed_host, parsed_port)) + + self.mount( + build_url_from_netloc(host, scheme="http") + "/", self._trusted_host_adapter + ) + self.mount(build_url_from_netloc(host) + "/", self._trusted_host_adapter) + if not parsed_port: + self.mount( + build_url_from_netloc(host, scheme="http") + ":", + self._trusted_host_adapter, + ) + # Mount wildcard ports for the same host. + self.mount(build_url_from_netloc(host) + ":", self._trusted_host_adapter) + + def iter_secure_origins(self) -> Generator[SecureOrigin, None, None]: + yield from SECURE_ORIGINS + for host, port in self.pip_trusted_origins: + yield ("*", host, "*" if port is None else port) + + def is_secure_origin(self, location: Link) -> bool: + # Determine if this url used a secure transport mechanism + parsed = urllib.parse.urlparse(str(location)) + origin_protocol, origin_host, origin_port = ( + parsed.scheme, + parsed.hostname, + parsed.port, + ) + + # The protocol to use to see if the protocol matches. + # Don't count the repository type as part of the protocol: in + # cases such as "git+ssh", only use "ssh". (I.e., Only verify against + # the last scheme.) + origin_protocol = origin_protocol.rsplit("+", 1)[-1] + + # Determine if our origin is a secure origin by looking through our + # hardcoded list of secure origins, as well as any additional ones + # configured on this PackageFinder instance. + for secure_origin in self.iter_secure_origins(): + secure_protocol, secure_host, secure_port = secure_origin + if origin_protocol != secure_protocol and secure_protocol != "*": + continue + + try: + addr = ipaddress.ip_address(origin_host or "") + network = ipaddress.ip_network(secure_host) + except ValueError: + # We don't have both a valid address or a valid network, so + # we'll check this origin against hostnames. + if ( + origin_host + and origin_host.lower() != secure_host.lower() + and secure_host != "*" + ): + continue + else: + # We have a valid address and network, so see if the address + # is contained within the network. + if addr not in network: + continue + + # Check to see if the port matches. + if ( + origin_port != secure_port + and secure_port != "*" + and secure_port is not None + ): + continue + + # If we've gotten here, then this origin matches the current + # secure origin and we should return True + return True + + # If we've gotten to this point, then the origin isn't secure and we + # will not accept it as a valid location to search. We will however + # log a warning that we are ignoring it. + logger.warning( + "The repository located at %s is not a trusted or secure host and " + "is being ignored. If this repository is available via HTTPS we " + "recommend you use HTTPS instead, otherwise you may silence " + "this warning and allow it anyway with '--trusted-host %s'.", + origin_host, + origin_host, + ) + + return False + + def request(self, method: str, url: str, *args: Any, **kwargs: Any) -> Response: + # Allow setting a default timeout on a session + kwargs.setdefault("timeout", self.timeout) + # Allow setting a default proxies on a session + kwargs.setdefault("proxies", self.proxies) + + # Dispatch the actual request + return super().request(method, url, *args, **kwargs) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/network/utils.py b/backend/.venv/Lib/site-packages/pip/_internal/network/utils.py new file mode 100644 index 0000000..bba4c26 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/network/utils.py @@ -0,0 +1,98 @@ +from typing import Dict, Generator + +from pip._vendor.requests.models import Response + +from pip._internal.exceptions import NetworkConnectionError + +# The following comments and HTTP headers were originally added by +# Donald Stufft in git commit 22c562429a61bb77172039e480873fb239dd8c03. +# +# We use Accept-Encoding: identity here because requests defaults to +# accepting compressed responses. This breaks in a variety of ways +# depending on how the server is configured. +# - Some servers will notice that the file isn't a compressible file +# and will leave the file alone and with an empty Content-Encoding +# - Some servers will notice that the file is already compressed and +# will leave the file alone, adding a Content-Encoding: gzip header +# - Some servers won't notice anything at all and will take a file +# that's already been compressed and compress it again, and set +# the Content-Encoding: gzip header +# By setting this to request only the identity encoding we're hoping +# to eliminate the third case. Hopefully there does not exist a server +# which when given a file will notice it is already compressed and that +# you're not asking for a compressed file and will then decompress it +# before sending because if that's the case I don't think it'll ever be +# possible to make this work. +HEADERS: Dict[str, str] = {"Accept-Encoding": "identity"} + +DOWNLOAD_CHUNK_SIZE = 256 * 1024 + + +def raise_for_status(resp: Response) -> None: + http_error_msg = "" + if isinstance(resp.reason, bytes): + # We attempt to decode utf-8 first because some servers + # choose to localize their reason strings. If the string + # isn't utf-8, we fall back to iso-8859-1 for all other + # encodings. + try: + reason = resp.reason.decode("utf-8") + except UnicodeDecodeError: + reason = resp.reason.decode("iso-8859-1") + else: + reason = resp.reason + + if 400 <= resp.status_code < 500: + http_error_msg = ( + f"{resp.status_code} Client Error: {reason} for url: {resp.url}" + ) + + elif 500 <= resp.status_code < 600: + http_error_msg = ( + f"{resp.status_code} Server Error: {reason} for url: {resp.url}" + ) + + if http_error_msg: + raise NetworkConnectionError(http_error_msg, response=resp) + + +def response_chunks( + response: Response, chunk_size: int = DOWNLOAD_CHUNK_SIZE +) -> Generator[bytes, None, None]: + """Given a requests Response, provide the data chunks.""" + try: + # Special case for urllib3. + for chunk in response.raw.stream( + chunk_size, + # We use decode_content=False here because we don't + # want urllib3 to mess with the raw bytes we get + # from the server. If we decompress inside of + # urllib3 then we cannot verify the checksum + # because the checksum will be of the compressed + # file. This breakage will only occur if the + # server adds a Content-Encoding header, which + # depends on how the server was configured: + # - Some servers will notice that the file isn't a + # compressible file and will leave the file alone + # and with an empty Content-Encoding + # - Some servers will notice that the file is + # already compressed and will leave the file + # alone and will add a Content-Encoding: gzip + # header + # - Some servers won't notice anything at all and + # will take a file that's already been compressed + # and compress it again and set the + # Content-Encoding: gzip header + # + # By setting this not to decode automatically we + # hope to eliminate problems with the second case. + decode_content=False, + ): + yield chunk + except AttributeError: + # Standard file-like object. + while True: + chunk = response.raw.read(chunk_size) + if not chunk: + break + yield chunk diff --git a/backend/.venv/Lib/site-packages/pip/_internal/network/xmlrpc.py b/backend/.venv/Lib/site-packages/pip/_internal/network/xmlrpc.py new file mode 100644 index 0000000..22ec8d2 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/network/xmlrpc.py @@ -0,0 +1,62 @@ +"""xmlrpclib.Transport implementation +""" + +import logging +import urllib.parse +import xmlrpc.client +from typing import TYPE_CHECKING, Tuple + +from pip._internal.exceptions import NetworkConnectionError +from pip._internal.network.session import PipSession +from pip._internal.network.utils import raise_for_status + +if TYPE_CHECKING: + from xmlrpc.client import _HostType, _Marshallable + + from _typeshed import SizedBuffer + +logger = logging.getLogger(__name__) + + +class PipXmlrpcTransport(xmlrpc.client.Transport): + """Provide a `xmlrpclib.Transport` implementation via a `PipSession` + object. + """ + + def __init__( + self, index_url: str, session: PipSession, use_datetime: bool = False + ) -> None: + super().__init__(use_datetime) + index_parts = urllib.parse.urlparse(index_url) + self._scheme = index_parts.scheme + self._session = session + + def request( + self, + host: "_HostType", + handler: str, + request_body: "SizedBuffer", + verbose: bool = False, + ) -> Tuple["_Marshallable", ...]: + assert isinstance(host, str) + parts = (self._scheme, host, handler, None, None, None) + url = urllib.parse.urlunparse(parts) + try: + headers = {"Content-Type": "text/xml"} + response = self._session.post( + url, + data=request_body, + headers=headers, + stream=True, + ) + raise_for_status(response) + self.verbose = verbose + return self.parse_response(response.raw) + except NetworkConnectionError as exc: + assert exc.response + logger.critical( + "HTTP error %s while getting %s", + exc.response.status_code, + url, + ) + raise diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/__init__.py b/backend/.venv/Lib/site-packages/pip/_internal/operations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5990a12faf1a12709c1302df48cae198fdf1b3b5 GIT binary patch literal 199 zcmZ8aK?=e!5KOFs2z`i$ws%o4Ueym62x+>O*t!WxTIoxCgKzN%UVVY|=E>yh!0gTr zGwd@>7bM_t+NikSar|SP2Io!&vZTicv6FC(G4nm|R_vy2@#i z1y%~#09GvT0eiMrC3DI{77C51!7-yu!4-P2DB40Bu)-^iuHeB{p7Y!culf3_tFDEu RorSkF&_(e{D5W+D>Ib1cHx&Q? literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/__pycache__/check.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/operations/__pycache__/check.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..429fb44cd6e665f309c46eb7b3c55861d250dcf8 GIT binary patch literal 7106 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9eb1cb806ad97d05622fe61777ad20b657d8893d GIT binary patch literal 25774 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 Vng^kK`;IzIkC}ePu^Ssv{})Tvuo(aV literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/build/__init__.py b/backend/.venv/Lib/site-packages/pip/_internal/operations/build/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..91ca957ee94d7aa11e1b0b039acba14c6dde1276 GIT binary patch literal 205 zcmZ8aK?=e!5KOFs2z`i$Hg{1kUeym62x+>=+L(kSt@I_n!MFGWuf9Nf^JIE;V0LGB zX4z++FG#}Sw862z$MTP1nl^XRlO;Vqh@Yfs7&BkJTk)IqO>j~HHLSKTFSPVi?6Iqm=qAsUIDjIa&Y! literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/build_tracker.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/build_tracker.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8018ce6a7d6b6fc14ed9b6acb934c707892c0ea3 GIT binary patch literal 7669 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 Q70*xP?2Zik^fhqyFBiuGdjJ3c literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b828ffa3c4405ed67ec8570110888e547e7fcfe7 GIT binary patch literal 1893 zcmZ`)-ES0C6u);qcegujX|Ys_b|Toi#%?hnB&47&B8Ys2Vj}A%li8WucG~&My|Z1~ zY?T-vATc36>4Oiv83KQR#wYqj;!6pbl8Gin!-H?t*3{G&&z+rFK7zOD+sH+;NmKVS#$+YtcsZHBvgB4rL{{9qSEv?}wd!_x#cC1OIU?J6BH9I_*gK5Xorvj?8pg}F7+YXDUQ*Ur9D;NIYV9%6rJWy#ku3a&$IpW(V zf?)2b>AHl1r8lu0^XDBJ_#W}2k`NDl;IjxEl0zmN^^gV@VeA;C0gVSUAjdm6-ZveW z*br=pHhchQG@WS1V4;%;9&9zI37EAD#0%eZD6yh|F2wmd2W1d{K33~(Xt8R;H6545 z3MEm4`j(jHn@=kIb9sFV^V~=9Z4X|7TjEWjEiH*HaW-9N9(-PsTIel=Q3N$@4_msK z##oYDc$UY1X0+tYgYV2E@X9~q0%GfN93_uzh5uz}psvrzQFj*Mc_?SMW!A@YOZu!6 zZxZcBQNmAd--Br1k{W55Z%eqmJ0 zfkpm|9e*k?xK<|o-7yZ7=aY}E#?eEyWd8LySz@$qC&B z_&9ahcksE4HoDP{Ju9U{cP`u?IDh%hQ_C!zb@d+#CM*tKz1Ny2m$rP@#WgCn|Pd zJ9zcrwTY_}-xROA_qz72Nc;ZTP|^1BzYvDazYLVWZ{8m`e&?f=-t+&iiCnj}sX~Mm zt-O^)x$@!`dmFHR`%-08`~g>n$^FukeA%mX23c>yZ##|1Z literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fc202e70fccd7cd4aa8dc7c292e9b14bb4d41382 GIT binary patch literal 3013 zcmaJ@U2Ggz6~1?Nc6Vlfyzbf6aVXLg??j6MU&oWBYf|cpn+4gbZv57A|4G7D@ut z5i3#=OCshv(TY}LrI_E2TJefhk}7gZt|UqcUly~Hl~gI^x8qj2k||~Uwq#{1U8OFJ z1Vr%SNU(sL3$QMBl!cd)N7=OXrw`wfq$0t8C@NH%E*Dfe?=&C zub!SEu4ZVirj&_IsOFlEtyoUk)RhH?Di$eg`ijDw8r6wnn9QZ-e2p8iV&W4%^K1co zT~jsFGS1moOzPMbV!I$qIaOk-tZLfewh-}hFWb!3EX$wa9HkER_U{&5s?AraqZ7v3 z%7I{EFNN!RQ8O)KfbRnpZHcIixV5V5I2Kb$xvZM@f}?7*%)lV4!%Qj*U4kh6DydY@ znw03SLsvZ62%9kqj;O774$?o)7?ctCZ+C5 z2+`f+#LtZjhM`3t)?wFgET;GNd9RM@f)U*Zts9*kUxHm>_^;t*REVt>Uo>q)(QKs% zhd;^>UxD)uPgOB(<@K=ldT~__?N*gpXV<9E2mn_DmoV@Xe%z}kW*kZs_cF}k*yR6@ zpnQ>qxF(RD_$Y?mAPqievX+g z8HE8$TA8r9s#zTaSh|GTnl%P|Xw!?0&2zepRXWU5+axPiSGL)((UA5PEP+M*BBaKf4R{$^S5Nr z{mgJBEOEOJ_Be~7jJYl z7`dS*LogyY#Q?C2oWxIkYtda4!u4o9ax)ruT8q`uNd*2lD*Vrg1=Kr<*5Wd9L!#7U zK#zDmep9+3wrw$zk&)oPV19_;Pxak=$1$o$1J9SxVdQ24`4L3B*CaO=^y}hHIk2ot zZwW?XO?p#W1`56rc?~V&!)P2aybQ#A4OWiP)yZeepFMNiwvb%4J3*Ex0VtIk1Dq@V zjRG=9=QTzQ#UKkB#80r&ftDt#Ko&>2vv2*UNFn62fj&3Rik|RaDm5zjTTl1sw?hgNP>YRTo5F&h`wxiDcz~ST!v~8 zrhD-q#X;8TtQHhL#Agc$F9x}^OsE$%$b79#Ie92Y0p*aV96OZ9bjqyTl`*|_Mivzqk1cfK^L`RSEW|Z(`%D5MP6aGj0xhB_1=|m0oNl$?M2>jXap;$*d zeJGmz(e(GGo6?!4)Z3J@J8>}@+ex9GL)Y!w?!ElaPeNa;)Xe%ElbXP`MS(mZs!Idu46ax~ZdIEpf-A4kA^ zXAq?ZH@>))Jk}78{d-47J!6j$=EM4mx0dhqz4XU#HM%bTw-w>CCy#S5u92R6^7*k( z*bA_QKcuEcB6pH_sxNvcoqgeyc;|q`C8y-6e0&q9r!w))Oq93t5wO|pi%t#8oBQKn zvpEu-IvFnvcyU!V99>l*all;xENB)yd;Ng7Vi>-QVVI*l@OXoJwYp^%J3wImt$G7{ z4agfhsrv6GKN)>?-`x8<&!*^1P?2^cde(1Ri)k0zGjaURFL{eu=h0h1!^s&Qu(uW|6PcNs#e8&EA6o z?hE5j1&qb*7{b}VBKaTaD-Y0@9}6NDK1ERcGlB4V`~XcpKwte>9(=q1BYE(yJh*Xc zOFpt5YsFG{d_!*`sIKeVylNf%0zTf%4!0suf1K}YMWJrRP_CyH=Pe0k^DUXT5-5{v RC3!1_V)9NJT66*y^*=Q#B+~!@ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2a40f631d18de5ee7af1b462fb1a6d6f320bd3c3 GIT binary patch literal 1679 zcmZux-ESL35Z}EIf7?ycq{T^9t|TdSNgS#wBt&T?Qd&V((kk#0`*zJ3u7c9f=XR&hX<5I@8On|idzYF>K(E%v3DfoG}W^#4+D<-Q^30Z4(Nb0a|e!LiMV}mvrV?flwxl8AakN zj!`Clc%ik=?J*?foe=^~hJSAkj&K{*r8Vg? z`T|E0@0gT?{y)Q%>he9QwTKZ{+iFv;qi>O^d?&X{a#N|}Qn;-@pmn8fF^(_-o9KbA z&DG_)^u5}Sb5k|3_}VhWO|>omuPvp+ZS4WA%b#`peTW9p8N_f^!e}0H!07AD4S60_ z@gU*>ki@)zLv#^QeZasO2dWUi~I$tL8dHd*5LkdOAlwsX%Ya z#Nk?nSx!;oOGLYN@tQV%W zU8=2iYp1*#q*DSgWw~3nGZ{=HaQ4+>mki4$W-H@=?;2*Am>;s;Vv$f^HOWGyNCimz zZdO^?Kbzh{wI2^otOp_e=*1fa65I)2C6v0S@{w>%vsN>e6NA83mGeN}P=vg@Rjgpc2K=f=fw${{rQ+E5upJ zU$GYQ%;IDeHY~$6V|mZ=#&pZ!gu-DT@hfnCe;}n-Z~cs{(>X0Ir%U;v<3xF<2QC=$)*hSNpi5M0);N5k2S-Bi=f1zW>j!76iTfZ OKEM7f4iY^95&i*YV6rU$ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e062c76d5a92743e1ebb8c921ce18993662c41c8 GIT binary patch literal 2018 zcmZuyO>7%Q6rTOH*Iv6#>a@*oS54C5k~&2#X-HEf99r?yKMI$c6l>$1IP0u;&CEKk zBL_-_P$Pk=o>~bZ^@_@YBL{?NIC4qVqK0jeDggp+RuieHTzIqVO-krkJ2UUi`SYlbqNo6@F z`?P39%F$euLp;K$)E*k$SaIwo7f`vlAz{^!v1CMGjl!p30jr&GJRLJ)AB(v}olD36 zV&bRLoEJS^aZSh8tu*g#&sI&#$m)ezY#XmR&g_J4S(tcnwm)f7YT89m=_Xa%#w1@e z-I+YCm_AX)lF+7=Iw@U1S7)0*R z5ts$|R=5phUCAf;>)0kR=9_^+hU(}JWx9oaABfbXrL*0btV>IhFa)`sxmy2ZCq zKXQE(vGV~$(hKranI|^1!kr;EP(!}ix)TnagNPR759G~p)gem8uW>bWK{$tMTt9jN zQLe@_9S(kmJh4`OkbrX^xGx*KO(ooX+C+ ztAKQ z8m$(X*mTvh>b|C%(N2RkQZp$Y(gJuR2}2jFJ` zVZ(IwDGO`U4$6#f zwfaFb985K)G^5W2=O8`Y z?kgYkrI++w=EHypYX?ulggC@gj$J5VzvDgLp`OSt)e}pOX{RHE^#zHtiRDKa5TQ%` zX7^(Lwdeir<}hWVtT-^9kcqL$nnPx3MK9n-dx<@_6MJsV{glWwc{S0q(mQak_u%c`gDa`dmAx-DCDeCl6$yRq zS7VPQlpJ2$jnw3o!;6Qnj4zH~m#)v>iSJt$_x-)L1EqF7LXkwzgRR@IsaMq|&vlGG zOzm7rb*w2;Tl=btcJ@5(1{2GP%s)*PB%eG^w8*s{q;@<){8OQid?VhC9{qXCwx$H^ zC-f~y_LGt95%evW9TvXZ_R1K4t33+ztuZA#BrOR$vU{baE)fow`WSy{uf+I60^ z*)ggXewhpa$^Q4~d6=34$8q;j@;*|2LEV3#H-AURA1Ym!cidCDZYy2aNAD;D7ooDd ux#w46iKYPS!$f~mf)&c$+0%@$T@y;7L;f$lTKf`8Iq zkR~O8)r+QF2uudJ>^GHyI;nD5GPOc*GFS*rh6Ln87|r!ICTW#8@Wb5KG#286#-<%_vgCH{_gj5-{5xqyo{9o1byt8_H# zy(1jeC#)i_oH$(jVVPomWaKU;(-ug!rPEn!;iF3IkfD~83ERCZvzak*+j7{xIWvQ^ zcK$9N$9J*m2I`A)r5iWLe)+De;G#hn^7d@fPgLkj80cCzZD5*p{WiX5Q$IB5kY1PG z8J$|N$UH4&vUsXEXVZ~PHfxoOHf(kzYY{v(oypF_z*DKaxOjJJJU=}}^EMuV4)d8D zrcFh2W!~ zK(>tbHPmrpqq-A6zdY`Q^^LbSBAe4&!86M@{uS(Tl+adea9bH%@z-J~6kC38KZ>;2 zbM@G^dTdAS`+e>Yg~x@zspq)im2Kq;7>2lEO+~Sz&!dCe(ZLOSH+s?u^{yM+q2ntP z%(lI6V`8iC+*a)TwsL;OzZZ-yzxNW>gIuYYDPZa98d9sQN)7)O(4uIw8|SHoN5jw2 zGE$#Wsv^Lq{772*zs+lNUT4$JvD-V8<{I37puQ?pfo&P*Huic4C6&sxUvS3J?OCjs zGWIM(29vq_02;Z%PTwLKvZ!<4(%~Wi4;EQWReHy{ht(UbnR-VC-AY`~5}dKIp%*QE zCU0Vz(k8xU{8hQqY$|}S!z7ua4!Gr3DeV^6@{8Apva^;&0Ta+dsGS_u39uR>?7EVQ zD^rWW_}q(01nS(tLWUH<-W6d8*Jn}J&$i|I=d64Yu-(mivr`}}Mje2wSfDw|7?9yp z*GU3I_XvPL?O`a*w_c}wHYDk1#_-X{kO6esQ8>PK;dk#Z-~4+p=EQ!ud46+f>+G$q z$h#||qXc)O{ToxyuI)s}ww19J@r4q(A6bp8(Ou<;6ODfv&{i(|wz78pH^1783~hF7 zDm5gW8Fq$GZ=QJ8UK54zg_?-eP)&jCdxrWl7`}gL_0s*Tt5?^Rje$+!@z73ic*{Rb zx?q)Vn8&bmX)(=DMWa@kWHCopBxhRF88dD1Fi737x8a5=F()vx%@_frF`nee`}i>O zfbFaPs`ONNQb*E~Z1^||M2Jv<1K0~Ruyg?}Dc_Gf14eB4u7Ff@0C_UR7GG6)DmUj- z?KW5)Pjl@Jsa3WxyrkLes(GqvRlsUhuBuP9Cv}cl3RZ(zpP{l}YxX;+54AAZkH}d8 zRh2pBn}?Fo+@XLD?C)C;YAC=UbsiGX2k7vei|PWpCw_nygg$fzQDMQytOWQis$P9E zSovg(u|LOBxyWJ#psyY>^fCt$L-%pdr;pcRTYs^nG>y5w#|X4Z2X!i#(P=r$9yT*& z)AX3YPU*K{II@tZ_@wT=T__L0DLztCBq!iF$Pi?16yhL6Hy)&z!&TyZsSMlR44gB9 z`Ve7U_)Y1GI9av}n)58=+yWA9#_$v~f10m|Za3K>ZcxN|+FfRNlIk z0d_IGoxeHx0G&um-^mckAYsl=m|u8YBN=$QoFgnmxa!S&SRCzrtTNAS^I$bh-JQTtg(NjO~tPG_If{r0{pwad#tt3^;}5~xVt zoZpI%E|0%Z6Km$K+PAU5$SbrO+De>$Hn6K)uK6{!`$eMPiS;^fk2)Pko$epN7@d)o zTl<};E&fn@psioni5**!UL;OC?Ojfy*J(>QJ$=rRWBWn5Q(MtsvRLn{Q%LLIR{Q?D z-+^L1-yl)#c0%#{6RQ*Jmv%#aFGB72$5+RfioiFds^0v)#0zFG&EzJ8VP zwAYlK{o}5&i{hW7*Dw1%QwBl&?DFZcbJFKS0?41A6_|WZWb#F6>?eU_2Z=!^H(=2e zr+1xcvb_iwkRy!d2;(xh7v5c|=DRDEHS?*uhf(etZvUGGWjk-u)WLrp7(lrzxkta% zwD}(d_bl%+Dd$-lz^~*bI|FT?@+k}|Y-nm8} zBx@qbdmUXh3Cfy`Wc6i$NkiSjNhcUx6IZX)M3DC)Z8Zr>FbPI#0VXLZ-o=MdnWmvc zcP+@I5RxM+*|d-2Yi1SJg8)=>*ENkNI8_4tFI)>Nj!Q?+|t Zd~l@}WE#9PqqQ)TBK0BnqoDDV_#Z Generator[None, None, None]: + target = os.environ + + # Save values from the target and change them. + non_existent_marker = object() + saved_values: Dict[str, Union[object, str]] = {} + for name, new_value in changes.items(): + try: + saved_values[name] = target[name] + except KeyError: + saved_values[name] = non_existent_marker + target[name] = new_value + + try: + yield + finally: + # Restore original values in the target. + for name, original_value in saved_values.items(): + if original_value is non_existent_marker: + del target[name] + else: + assert isinstance(original_value, str) # for mypy + target[name] = original_value + + +@contextlib.contextmanager +def get_build_tracker() -> Generator["BuildTracker", None, None]: + root = os.environ.get("PIP_BUILD_TRACKER") + with contextlib.ExitStack() as ctx: + if root is None: + root = ctx.enter_context(TempDirectory(kind="build-tracker")).path + ctx.enter_context(update_env_context_manager(PIP_BUILD_TRACKER=root)) + logger.debug("Initialized build tracking at %s", root) + + with BuildTracker(root) as tracker: + yield tracker + + +class TrackerId(str): + """Uniquely identifying string provided to the build tracker.""" + + +class BuildTracker: + """Ensure that an sdist cannot request itself as a setup requirement. + + When an sdist is prepared, it identifies its setup requirements in the + context of ``BuildTracker.track()``. If a requirement shows up recursively, this + raises an exception. + + This stops fork bombs embedded in malicious packages.""" + + def __init__(self, root: str) -> None: + self._root = root + self._entries: Dict[TrackerId, InstallRequirement] = {} + logger.debug("Created build tracker: %s", self._root) + + def __enter__(self) -> "BuildTracker": + logger.debug("Entered build tracker: %s", self._root) + return self + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + self.cleanup() + + def _entry_path(self, key: TrackerId) -> str: + hashed = hashlib.sha224(key.encode()).hexdigest() + return os.path.join(self._root, hashed) + + def add(self, req: InstallRequirement, key: TrackerId) -> None: + """Add an InstallRequirement to build tracking.""" + + # Get the file to write information about this requirement. + entry_path = self._entry_path(key) + + # Try reading from the file. If it exists and can be read from, a build + # is already in progress, so a LookupError is raised. + try: + with open(entry_path) as fp: + contents = fp.read() + except FileNotFoundError: + pass + else: + message = f"{req.link} is already being built: {contents}" + raise LookupError(message) + + # If we're here, req should really not be building already. + assert key not in self._entries + + # Start tracking this requirement. + with open(entry_path, "w", encoding="utf-8") as fp: + fp.write(str(req)) + self._entries[key] = req + + logger.debug("Added %s to build tracker %r", req, self._root) + + def remove(self, req: InstallRequirement, key: TrackerId) -> None: + """Remove an InstallRequirement from build tracking.""" + + # Delete the created file and the corresponding entry. + os.unlink(self._entry_path(key)) + del self._entries[key] + + logger.debug("Removed %s from build tracker %r", req, self._root) + + def cleanup(self) -> None: + for key, req in list(self._entries.items()): + self.remove(req, key) + + logger.debug("Removed build tracker: %r", self._root) + + @contextlib.contextmanager + def track(self, req: InstallRequirement, key: str) -> Generator[None, None, None]: + """Ensure that `key` cannot install itself as a setup requirement. + + :raises LookupError: If `key` was already provided in a parent invocation of + the context introduced by this method.""" + tracker_id = TrackerId(key) + self.add(req, tracker_id) + yield + self.remove(req, tracker_id) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/build/metadata.py b/backend/.venv/Lib/site-packages/pip/_internal/operations/build/metadata.py new file mode 100644 index 0000000..c66ac35 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/operations/build/metadata.py @@ -0,0 +1,39 @@ +"""Metadata generation logic for source distributions. +""" + +import os + +from pip._vendor.pyproject_hooks import BuildBackendHookCaller + +from pip._internal.build_env import BuildEnvironment +from pip._internal.exceptions import ( + InstallationSubprocessError, + MetadataGenerationFailed, +) +from pip._internal.utils.subprocess import runner_with_spinner_message +from pip._internal.utils.temp_dir import TempDirectory + + +def generate_metadata( + build_env: BuildEnvironment, backend: BuildBackendHookCaller, details: str +) -> str: + """Generate metadata using mechanisms described in PEP 517. + + Returns the generated metadata directory. + """ + metadata_tmpdir = TempDirectory(kind="modern-metadata", globally_managed=True) + + metadata_dir = metadata_tmpdir.path + + with build_env: + # Note that BuildBackendHookCaller implements a fallback for + # prepare_metadata_for_build_wheel, so we don't have to + # consider the possibility that this hook doesn't exist. + runner = runner_with_spinner_message("Preparing metadata (pyproject.toml)") + with backend.subprocess_runner(runner): + try: + distinfo_dir = backend.prepare_metadata_for_build_wheel(metadata_dir) + except InstallationSubprocessError as error: + raise MetadataGenerationFailed(package_details=details) from error + + return os.path.join(metadata_dir, distinfo_dir) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py b/backend/.venv/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py new file mode 100644 index 0000000..27c69f0 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py @@ -0,0 +1,41 @@ +"""Metadata generation logic for source distributions. +""" + +import os + +from pip._vendor.pyproject_hooks import BuildBackendHookCaller + +from pip._internal.build_env import BuildEnvironment +from pip._internal.exceptions import ( + InstallationSubprocessError, + MetadataGenerationFailed, +) +from pip._internal.utils.subprocess import runner_with_spinner_message +from pip._internal.utils.temp_dir import TempDirectory + + +def generate_editable_metadata( + build_env: BuildEnvironment, backend: BuildBackendHookCaller, details: str +) -> str: + """Generate metadata using mechanisms described in PEP 660. + + Returns the generated metadata directory. + """ + metadata_tmpdir = TempDirectory(kind="modern-metadata", globally_managed=True) + + metadata_dir = metadata_tmpdir.path + + with build_env: + # Note that BuildBackendHookCaller implements a fallback for + # prepare_metadata_for_build_wheel/editable, so we don't have to + # consider the possibility that this hook doesn't exist. + runner = runner_with_spinner_message( + "Preparing editable metadata (pyproject.toml)" + ) + with backend.subprocess_runner(runner): + try: + distinfo_dir = backend.prepare_metadata_for_build_editable(metadata_dir) + except InstallationSubprocessError as error: + raise MetadataGenerationFailed(package_details=details) from error + + return os.path.join(metadata_dir, distinfo_dir) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/build/metadata_legacy.py b/backend/.venv/Lib/site-packages/pip/_internal/operations/build/metadata_legacy.py new file mode 100644 index 0000000..c01dd1c --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/operations/build/metadata_legacy.py @@ -0,0 +1,74 @@ +"""Metadata generation logic for legacy source distributions. +""" + +import logging +import os + +from pip._internal.build_env import BuildEnvironment +from pip._internal.cli.spinners import open_spinner +from pip._internal.exceptions import ( + InstallationError, + InstallationSubprocessError, + MetadataGenerationFailed, +) +from pip._internal.utils.setuptools_build import make_setuptools_egg_info_args +from pip._internal.utils.subprocess import call_subprocess +from pip._internal.utils.temp_dir import TempDirectory + +logger = logging.getLogger(__name__) + + +def _find_egg_info(directory: str) -> str: + """Find an .egg-info subdirectory in `directory`.""" + filenames = [f for f in os.listdir(directory) if f.endswith(".egg-info")] + + if not filenames: + raise InstallationError(f"No .egg-info directory found in {directory}") + + if len(filenames) > 1: + raise InstallationError( + f"More than one .egg-info directory found in {directory}" + ) + + return os.path.join(directory, filenames[0]) + + +def generate_metadata( + build_env: BuildEnvironment, + setup_py_path: str, + source_dir: str, + isolated: bool, + details: str, +) -> str: + """Generate metadata using setup.py-based defacto mechanisms. + + Returns the generated metadata directory. + """ + logger.debug( + "Running setup.py (path:%s) egg_info for package %s", + setup_py_path, + details, + ) + + egg_info_dir = TempDirectory(kind="pip-egg-info", globally_managed=True).path + + args = make_setuptools_egg_info_args( + setup_py_path, + egg_info_dir=egg_info_dir, + no_user_config=isolated, + ) + + with build_env: + with open_spinner("Preparing metadata (setup.py)") as spinner: + try: + call_subprocess( + args, + cwd=source_dir, + command_desc="python setup.py egg_info", + spinner=spinner, + ) + except InstallationSubprocessError as error: + raise MetadataGenerationFailed(package_details=details) from error + + # Return the .egg-info directory. + return _find_egg_info(egg_info_dir) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/build/wheel.py b/backend/.venv/Lib/site-packages/pip/_internal/operations/build/wheel.py new file mode 100644 index 0000000..064811a --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/operations/build/wheel.py @@ -0,0 +1,37 @@ +import logging +import os +from typing import Optional + +from pip._vendor.pyproject_hooks import BuildBackendHookCaller + +from pip._internal.utils.subprocess import runner_with_spinner_message + +logger = logging.getLogger(__name__) + + +def build_wheel_pep517( + name: str, + backend: BuildBackendHookCaller, + metadata_directory: str, + tempd: str, +) -> Optional[str]: + """Build one InstallRequirement using the PEP 517 build process. + + Returns path to wheel if successfully built. Otherwise, returns None. + """ + assert metadata_directory is not None + try: + logger.debug("Destination directory: %s", tempd) + + runner = runner_with_spinner_message( + f"Building wheel for {name} (pyproject.toml)" + ) + with backend.subprocess_runner(runner): + wheel_name = backend.build_wheel( + tempd, + metadata_directory=metadata_directory, + ) + except Exception: + logger.error("Failed building wheel for %s", name) + return None + return os.path.join(tempd, wheel_name) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py b/backend/.venv/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py new file mode 100644 index 0000000..719d69d --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py @@ -0,0 +1,46 @@ +import logging +import os +from typing import Optional + +from pip._vendor.pyproject_hooks import BuildBackendHookCaller, HookMissing + +from pip._internal.utils.subprocess import runner_with_spinner_message + +logger = logging.getLogger(__name__) + + +def build_wheel_editable( + name: str, + backend: BuildBackendHookCaller, + metadata_directory: str, + tempd: str, +) -> Optional[str]: + """Build one InstallRequirement using the PEP 660 build process. + + Returns path to wheel if successfully built. Otherwise, returns None. + """ + assert metadata_directory is not None + try: + logger.debug("Destination directory: %s", tempd) + + runner = runner_with_spinner_message( + f"Building editable for {name} (pyproject.toml)" + ) + with backend.subprocess_runner(runner): + try: + wheel_name = backend.build_editable( + tempd, + metadata_directory=metadata_directory, + ) + except HookMissing as e: + logger.error( + "Cannot build editable %s because the build " + "backend does not have the %s hook", + name, + e, + ) + return None + except Exception: + logger.error("Failed building editable for %s", name) + return None + return os.path.join(tempd, wheel_name) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/build/wheel_legacy.py b/backend/.venv/Lib/site-packages/pip/_internal/operations/build/wheel_legacy.py new file mode 100644 index 0000000..3ee2a70 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/operations/build/wheel_legacy.py @@ -0,0 +1,102 @@ +import logging +import os.path +from typing import List, Optional + +from pip._internal.cli.spinners import open_spinner +from pip._internal.utils.setuptools_build import make_setuptools_bdist_wheel_args +from pip._internal.utils.subprocess import call_subprocess, format_command_args + +logger = logging.getLogger(__name__) + + +def format_command_result( + command_args: List[str], + command_output: str, +) -> str: + """Format command information for logging.""" + command_desc = format_command_args(command_args) + text = f"Command arguments: {command_desc}\n" + + if not command_output: + text += "Command output: None" + elif logger.getEffectiveLevel() > logging.DEBUG: + text += "Command output: [use --verbose to show]" + else: + if not command_output.endswith("\n"): + command_output += "\n" + text += f"Command output:\n{command_output}" + + return text + + +def get_legacy_build_wheel_path( + names: List[str], + temp_dir: str, + name: str, + command_args: List[str], + command_output: str, +) -> Optional[str]: + """Return the path to the wheel in the temporary build directory.""" + # Sort for determinism. + names = sorted(names) + if not names: + msg = f"Legacy build of wheel for {name!r} created no files.\n" + msg += format_command_result(command_args, command_output) + logger.warning(msg) + return None + + if len(names) > 1: + msg = ( + f"Legacy build of wheel for {name!r} created more than one file.\n" + f"Filenames (choosing first): {names}\n" + ) + msg += format_command_result(command_args, command_output) + logger.warning(msg) + + return os.path.join(temp_dir, names[0]) + + +def build_wheel_legacy( + name: str, + setup_py_path: str, + source_dir: str, + global_options: List[str], + build_options: List[str], + tempd: str, +) -> Optional[str]: + """Build one unpacked package using the "legacy" build process. + + Returns path to wheel if successfully built. Otherwise, returns None. + """ + wheel_args = make_setuptools_bdist_wheel_args( + setup_py_path, + global_options=global_options, + build_options=build_options, + destination_dir=tempd, + ) + + spin_message = f"Building wheel for {name} (setup.py)" + with open_spinner(spin_message) as spinner: + logger.debug("Destination directory: %s", tempd) + + try: + output = call_subprocess( + wheel_args, + command_desc="python setup.py bdist_wheel", + cwd=source_dir, + spinner=spinner, + ) + except Exception: + spinner.finish("error") + logger.error("Failed building wheel for %s", name) + return None + + names = os.listdir(tempd) + wheel_path = get_legacy_build_wheel_path( + names=names, + temp_dir=tempd, + name=name, + command_args=wheel_args, + command_output=output, + ) + return wheel_path diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/check.py b/backend/.venv/Lib/site-packages/pip/_internal/operations/check.py new file mode 100644 index 0000000..4b6fbc4 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/operations/check.py @@ -0,0 +1,181 @@ +"""Validation of dependencies of packages +""" + +import logging +from contextlib import suppress +from email.parser import Parser +from functools import reduce +from typing import ( + Callable, + Dict, + FrozenSet, + Generator, + Iterable, + List, + NamedTuple, + Optional, + Set, + Tuple, +) + +from pip._vendor.packaging.requirements import Requirement +from pip._vendor.packaging.tags import Tag, parse_tag +from pip._vendor.packaging.utils import NormalizedName, canonicalize_name +from pip._vendor.packaging.version import Version + +from pip._internal.distributions import make_distribution_for_install_requirement +from pip._internal.metadata import get_default_environment +from pip._internal.metadata.base import BaseDistribution +from pip._internal.req.req_install import InstallRequirement + +logger = logging.getLogger(__name__) + + +class PackageDetails(NamedTuple): + version: Version + dependencies: List[Requirement] + + +# Shorthands +PackageSet = Dict[NormalizedName, PackageDetails] +Missing = Tuple[NormalizedName, Requirement] +Conflicting = Tuple[NormalizedName, Version, Requirement] + +MissingDict = Dict[NormalizedName, List[Missing]] +ConflictingDict = Dict[NormalizedName, List[Conflicting]] +CheckResult = Tuple[MissingDict, ConflictingDict] +ConflictDetails = Tuple[PackageSet, CheckResult] + + +def create_package_set_from_installed() -> Tuple[PackageSet, bool]: + """Converts a list of distributions into a PackageSet.""" + package_set = {} + problems = False + env = get_default_environment() + for dist in env.iter_installed_distributions(local_only=False, skip=()): + name = dist.canonical_name + try: + dependencies = list(dist.iter_dependencies()) + package_set[name] = PackageDetails(dist.version, dependencies) + except (OSError, ValueError) as e: + # Don't crash on unreadable or broken metadata. + logger.warning("Error parsing dependencies of %s: %s", name, e) + problems = True + return package_set, problems + + +def check_package_set( + package_set: PackageSet, should_ignore: Optional[Callable[[str], bool]] = None +) -> CheckResult: + """Check if a package set is consistent + + If should_ignore is passed, it should be a callable that takes a + package name and returns a boolean. + """ + + missing = {} + conflicting = {} + + for package_name, package_detail in package_set.items(): + # Info about dependencies of package_name + missing_deps: Set[Missing] = set() + conflicting_deps: Set[Conflicting] = set() + + if should_ignore and should_ignore(package_name): + continue + + for req in package_detail.dependencies: + name = canonicalize_name(req.name) + + # Check if it's missing + if name not in package_set: + missed = True + if req.marker is not None: + missed = req.marker.evaluate({"extra": ""}) + if missed: + missing_deps.add((name, req)) + continue + + # Check if there's a conflict + version = package_set[name].version + if not req.specifier.contains(version, prereleases=True): + conflicting_deps.add((name, version, req)) + + if missing_deps: + missing[package_name] = sorted(missing_deps, key=str) + if conflicting_deps: + conflicting[package_name] = sorted(conflicting_deps, key=str) + + return missing, conflicting + + +def check_install_conflicts(to_install: List[InstallRequirement]) -> ConflictDetails: + """For checking if the dependency graph would be consistent after \ + installing given requirements + """ + # Start from the current state + package_set, _ = create_package_set_from_installed() + # Install packages + would_be_installed = _simulate_installation_of(to_install, package_set) + + # Only warn about directly-dependent packages; create a whitelist of them + whitelist = _create_whitelist(would_be_installed, package_set) + + return ( + package_set, + check_package_set( + package_set, should_ignore=lambda name: name not in whitelist + ), + ) + + +def check_unsupported( + packages: Iterable[BaseDistribution], + supported_tags: Iterable[Tag], +) -> Generator[BaseDistribution, None, None]: + for p in packages: + with suppress(FileNotFoundError): + wheel_file = p.read_text("WHEEL") + wheel_tags: FrozenSet[Tag] = reduce( + frozenset.union, + map(parse_tag, Parser().parsestr(wheel_file).get_all("Tag", [])), + frozenset(), + ) + if wheel_tags.isdisjoint(supported_tags): + yield p + + +def _simulate_installation_of( + to_install: List[InstallRequirement], package_set: PackageSet +) -> Set[NormalizedName]: + """Computes the version of packages after installing to_install.""" + # Keep track of packages that were installed + installed = set() + + # Modify it as installing requirement_set would (assuming no errors) + for inst_req in to_install: + abstract_dist = make_distribution_for_install_requirement(inst_req) + dist = abstract_dist.get_metadata_distribution() + name = dist.canonical_name + package_set[name] = PackageDetails(dist.version, list(dist.iter_dependencies())) + + installed.add(name) + + return installed + + +def _create_whitelist( + would_be_installed: Set[NormalizedName], package_set: PackageSet +) -> Set[NormalizedName]: + packages_affected = set(would_be_installed) + + for package_name in package_set: + if package_name in packages_affected: + continue + + for req in package_set[package_name].dependencies: + if canonicalize_name(req.name) in packages_affected: + packages_affected.add(package_name) + break + + return packages_affected diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/freeze.py b/backend/.venv/Lib/site-packages/pip/_internal/operations/freeze.py new file mode 100644 index 0000000..bb1039f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/operations/freeze.py @@ -0,0 +1,258 @@ +import collections +import logging +import os +from typing import Container, Dict, Generator, Iterable, List, NamedTuple, Optional, Set + +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.packaging.version import InvalidVersion + +from pip._internal.exceptions import BadCommand, InstallationError +from pip._internal.metadata import BaseDistribution, get_environment +from pip._internal.req.constructors import ( + install_req_from_editable, + install_req_from_line, +) +from pip._internal.req.req_file import COMMENT_RE +from pip._internal.utils.direct_url_helpers import direct_url_as_pep440_direct_reference + +logger = logging.getLogger(__name__) + + +class _EditableInfo(NamedTuple): + requirement: str + comments: List[str] + + +def freeze( + requirement: Optional[List[str]] = None, + local_only: bool = False, + user_only: bool = False, + paths: Optional[List[str]] = None, + isolated: bool = False, + exclude_editable: bool = False, + skip: Container[str] = (), +) -> Generator[str, None, None]: + installations: Dict[str, FrozenRequirement] = {} + + dists = get_environment(paths).iter_installed_distributions( + local_only=local_only, + skip=(), + user_only=user_only, + ) + for dist in dists: + req = FrozenRequirement.from_dist(dist) + if exclude_editable and req.editable: + continue + installations[req.canonical_name] = req + + if requirement: + # the options that don't get turned into an InstallRequirement + # should only be emitted once, even if the same option is in multiple + # requirements files, so we need to keep track of what has been emitted + # so that we don't emit it again if it's seen again + emitted_options: Set[str] = set() + # keep track of which files a requirement is in so that we can + # give an accurate warning if a requirement appears multiple times. + req_files: Dict[str, List[str]] = collections.defaultdict(list) + for req_file_path in requirement: + with open(req_file_path) as req_file: + for line in req_file: + if ( + not line.strip() + or line.strip().startswith("#") + or line.startswith( + ( + "-r", + "--requirement", + "-f", + "--find-links", + "-i", + "--index-url", + "--pre", + "--trusted-host", + "--process-dependency-links", + "--extra-index-url", + "--use-feature", + ) + ) + ): + line = line.rstrip() + if line not in emitted_options: + emitted_options.add(line) + yield line + continue + + if line.startswith("-e") or line.startswith("--editable"): + if line.startswith("-e"): + line = line[2:].strip() + else: + line = line[len("--editable") :].strip().lstrip("=") + line_req = install_req_from_editable( + line, + isolated=isolated, + ) + else: + line_req = install_req_from_line( + COMMENT_RE.sub("", line).strip(), + isolated=isolated, + ) + + if not line_req.name: + logger.info( + "Skipping line in requirement file [%s] because " + "it's not clear what it would install: %s", + req_file_path, + line.strip(), + ) + logger.info( + " (add #egg=PackageName to the URL to avoid" + " this warning)" + ) + else: + line_req_canonical_name = canonicalize_name(line_req.name) + if line_req_canonical_name not in installations: + # either it's not installed, or it is installed + # but has been processed already + if not req_files[line_req.name]: + logger.warning( + "Requirement file [%s] contains %s, but " + "package %r is not installed", + req_file_path, + COMMENT_RE.sub("", line).strip(), + line_req.name, + ) + else: + req_files[line_req.name].append(req_file_path) + else: + yield str(installations[line_req_canonical_name]).rstrip() + del installations[line_req_canonical_name] + req_files[line_req.name].append(req_file_path) + + # Warn about requirements that were included multiple times (in a + # single requirements file or in different requirements files). + for name, files in req_files.items(): + if len(files) > 1: + logger.warning( + "Requirement %s included multiple times [%s]", + name, + ", ".join(sorted(set(files))), + ) + + yield ("## The following requirements were added by pip freeze:") + for installation in sorted(installations.values(), key=lambda x: x.name.lower()): + if installation.canonical_name not in skip: + yield str(installation).rstrip() + + +def _format_as_name_version(dist: BaseDistribution) -> str: + try: + dist_version = dist.version + except InvalidVersion: + # legacy version + return f"{dist.raw_name}==={dist.raw_version}" + else: + return f"{dist.raw_name}=={dist_version}" + + +def _get_editable_info(dist: BaseDistribution) -> _EditableInfo: + """ + Compute and return values (req, comments) for use in + FrozenRequirement.from_dist(). + """ + editable_project_location = dist.editable_project_location + assert editable_project_location + location = os.path.normcase(os.path.abspath(editable_project_location)) + + from pip._internal.vcs import RemoteNotFoundError, RemoteNotValidError, vcs + + vcs_backend = vcs.get_backend_for_dir(location) + + if vcs_backend is None: + display = _format_as_name_version(dist) + logger.debug( + 'No VCS found for editable requirement "%s" in: %r', + display, + location, + ) + return _EditableInfo( + requirement=location, + comments=[f"# Editable install with no version control ({display})"], + ) + + vcs_name = type(vcs_backend).__name__ + + try: + req = vcs_backend.get_src_requirement(location, dist.raw_name) + except RemoteNotFoundError: + display = _format_as_name_version(dist) + return _EditableInfo( + requirement=location, + comments=[f"# Editable {vcs_name} install with no remote ({display})"], + ) + except RemoteNotValidError as ex: + display = _format_as_name_version(dist) + return _EditableInfo( + requirement=location, + comments=[ + f"# Editable {vcs_name} install ({display}) with either a deleted " + f"local remote or invalid URI:", + f"# '{ex.url}'", + ], + ) + except BadCommand: + logger.warning( + "cannot determine version of editable source in %s " + "(%s command not found in path)", + location, + vcs_backend.name, + ) + return _EditableInfo(requirement=location, comments=[]) + except InstallationError as exc: + logger.warning("Error when trying to get requirement for VCS system %s", exc) + else: + return _EditableInfo(requirement=req, comments=[]) + + logger.warning("Could not determine repository location of %s", location) + + return _EditableInfo( + requirement=location, + comments=["## !! Could not determine repository location"], + ) + + +class FrozenRequirement: + def __init__( + self, + name: str, + req: str, + editable: bool, + comments: Iterable[str] = (), + ) -> None: + self.name = name + self.canonical_name = canonicalize_name(name) + self.req = req + self.editable = editable + self.comments = comments + + @classmethod + def from_dist(cls, dist: BaseDistribution) -> "FrozenRequirement": + editable = dist.editable + if editable: + req, comments = _get_editable_info(dist) + else: + comments = [] + direct_url = dist.direct_url + if direct_url: + # if PEP 610 metadata is present, use it + req = direct_url_as_pep440_direct_reference(direct_url, dist.raw_name) + else: + # name==version requirement + req = _format_as_name_version(dist) + + return cls(dist.raw_name, req, editable, comments=comments) + + def __str__(self) -> str: + req = self.req + if self.editable: + req = f"-e {req}" + return "\n".join(list(self.comments) + [str(req)]) + "\n" diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/install/__init__.py b/backend/.venv/Lib/site-packages/pip/_internal/operations/install/__init__.py new file mode 100644 index 0000000..24d6a5d --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/operations/install/__init__.py @@ -0,0 +1,2 @@ +"""For modules related to installing packages. +""" diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0cee1b47fb152c626a162c49be73c1d820a0c0ed GIT binary patch literal 268 zcmXv}K~4iP3`|M|Ri*wR*GlZ}fg1uYNSuHN&`435SXF4Sqa-aVAK?wWg&*|F2P%5w zgja3n;u+Zm_Dl{iwokHqNzzP{{>?lFDH4v8W7@{-W4b_-7ZMLJEL)yE1&gc8L SO8@olOiKAXkaC!ZEdK$qKu}r$ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c878e7b59988b4c8b1e9731e0535ba78abdafe10 GIT binary patch literal 1800 zcmZuxO>7%Q6rT0|c-Q|)oR}t|-I7*dL>v_gsw#dIeh#Qjk?1L|rRjQi;%vL#S!Q;V zIxCI|)R6*1Y}RoAJCiZ@xD_ z6pJ|ovU24OU)2%%O&a@B9fO_k0o+9%Y9deZGJ(=m;Hw6iuG&<)T2oV`UkmiE(KJ%5 z2idOKG*fH@RyWtor8pbpyM<;!K^a7pYqR@-4!@+dt&FT@*)xeoD#yU|ETWE4?f~V< zgjXOHuLz?AxJ(SM0(ip9tW~|qPqpS`FH@h|dg~(TIBw4-o*z5yfY^S>VMn{wkK~&49uZIJYulNT zQ$aB>X(WBUkNQSm>1X=t{miy8@_uZ^+5HvUWAG|cP(LemETgB=w>-6P-q*Ir5rIRx z{2fL*YWMU7bOv!{GozqY*h@j5Pu@^h(WY|L-_u9_y0LZT{ShN<$Cd?hI+7!YeCbjT zsIfwMY{QKu@{Tzm0*g6cjMo`WI_o(bB&PP^H8)b%)`<_3F!aODXy!lEveziHPxHFY zQn!f&woKF70-m&;wp^SE%l$cd4!m1IX7Q zOlW=xfn>RvtUi<1TF<31kHla_IbV{hELBCS2~a|lOyx2odCHOOCGVVXZBllfL(NDl zycY9C$8~8E#&Ft2mon07OS*+#tFZz6YhCo)ElJtMagli|@}ni}hcRK$RZBD?ENx1@ zG;YzQ{hq}^+QU#iQ5nzS{W&%VdC7#i2kIu;J&yGJXBR%X@UU{`o3lS_=YG#WKQN~U zwbO&zi9vaKP@EXdEbJDu1>@$syOSta{bF7eXMQcr4Jy^av#$-Ri+^XeV(A|hm1>}J zGq>g+7iVs*?v0H-{u~7QR$V@+epg`@nE zk(IXrbrD9~i{Q&7qnQRu)SwEDgDNx*`jyEh5_A8bO=3Ubjqzsbg^E*8TX9H3oNkyB zKpcPS(u0R5<%Y02B)&M}j)}2+T`*=fnTyI};8Ppku(al1qaE-fCZBO(z7B1Y1msOt z2UEV`{3}pHRZ*0`GK!+@7)U8UMyLNkXCI-LAEA{;==>9F_Ezl|YxYNL_TIUltW!6Q zpVSs^Do)?Ie0yb>m6nO}Q+Hmuy*RX_l|$8MhIxq!C|?>DB`Tq6 lZCIA5g343F35h0A#U4&cR7Li}a9W}nWaM^hfY=L==fAZC?Y;m2 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..62ed224be6a9e73d54ebe347afadf46a6aedd12b GIT binary patch literal 34105 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 RRjD3@sCM@=5n_iR|1TdDQ!fAj literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py b/backend/.venv/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py new file mode 100644 index 0000000..9aaa699 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py @@ -0,0 +1,47 @@ +"""Legacy editable installation process, i.e. `setup.py develop`. +""" + +import logging +from typing import Optional, Sequence + +from pip._internal.build_env import BuildEnvironment +from pip._internal.utils.logging import indent_log +from pip._internal.utils.setuptools_build import make_setuptools_develop_args +from pip._internal.utils.subprocess import call_subprocess + +logger = logging.getLogger(__name__) + + +def install_editable( + *, + global_options: Sequence[str], + prefix: Optional[str], + home: Optional[str], + use_user_site: bool, + name: str, + setup_py_path: str, + isolated: bool, + build_env: BuildEnvironment, + unpacked_source_directory: str, +) -> None: + """Install a package in editable mode. Most arguments are pass-through + to setuptools. + """ + logger.info("Running setup.py develop for %s", name) + + args = make_setuptools_develop_args( + setup_py_path, + global_options=global_options, + no_user_config=isolated, + prefix=prefix, + home=home, + use_user_site=use_user_site, + ) + + with indent_log(): + with build_env: + call_subprocess( + args, + command_desc="python setup.py develop", + cwd=unpacked_source_directory, + ) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/install/wheel.py b/backend/.venv/Lib/site-packages/pip/_internal/operations/install/wheel.py new file mode 100644 index 0000000..aef42aa --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/operations/install/wheel.py @@ -0,0 +1,741 @@ +"""Support for installing and building the "wheel" binary package format. +""" + +import collections +import compileall +import contextlib +import csv +import importlib +import logging +import os.path +import re +import shutil +import sys +import warnings +from base64 import urlsafe_b64encode +from email.message import Message +from itertools import chain, filterfalse, starmap +from typing import ( + IO, + TYPE_CHECKING, + Any, + BinaryIO, + Callable, + Dict, + Generator, + Iterable, + Iterator, + List, + NewType, + Optional, + Protocol, + Sequence, + Set, + Tuple, + Union, + cast, +) +from zipfile import ZipFile, ZipInfo + +from pip._vendor.distlib.scripts import ScriptMaker +from pip._vendor.distlib.util import get_export_entry +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.exceptions import InstallationError +from pip._internal.locations import get_major_minor_version +from pip._internal.metadata import ( + BaseDistribution, + FilesystemWheel, + get_wheel_distribution, +) +from pip._internal.models.direct_url import DIRECT_URL_METADATA_NAME, DirectUrl +from pip._internal.models.scheme import SCHEME_KEYS, Scheme +from pip._internal.utils.filesystem import adjacent_tmp_file, replace +from pip._internal.utils.misc import StreamWrapper, ensure_dir, hash_file, partition +from pip._internal.utils.unpacking import ( + current_umask, + is_within_directory, + set_extracted_file_to_default_mode_plus_executable, + zip_item_is_executable, +) +from pip._internal.utils.wheel import parse_wheel + +if TYPE_CHECKING: + + class File(Protocol): + src_record_path: "RecordPath" + dest_path: str + changed: bool + + def save(self) -> None: + pass + + +logger = logging.getLogger(__name__) + +RecordPath = NewType("RecordPath", str) +InstalledCSVRow = Tuple[RecordPath, str, Union[int, str]] + + +def rehash(path: str, blocksize: int = 1 << 20) -> Tuple[str, str]: + """Return (encoded_digest, length) for path using hashlib.sha256()""" + h, length = hash_file(path, blocksize) + digest = "sha256=" + urlsafe_b64encode(h.digest()).decode("latin1").rstrip("=") + return (digest, str(length)) + + +def csv_io_kwargs(mode: str) -> Dict[str, Any]: + """Return keyword arguments to properly open a CSV file + in the given mode. + """ + return {"mode": mode, "newline": "", "encoding": "utf-8"} + + +def fix_script(path: str) -> bool: + """Replace #!python with #!/path/to/python + Return True if file was changed. + """ + # XXX RECORD hashes will need to be updated + assert os.path.isfile(path) + + with open(path, "rb") as script: + firstline = script.readline() + if not firstline.startswith(b"#!python"): + return False + exename = sys.executable.encode(sys.getfilesystemencoding()) + firstline = b"#!" + exename + os.linesep.encode("ascii") + rest = script.read() + with open(path, "wb") as script: + script.write(firstline) + script.write(rest) + return True + + +def wheel_root_is_purelib(metadata: Message) -> bool: + return metadata.get("Root-Is-Purelib", "").lower() == "true" + + +def get_entrypoints(dist: BaseDistribution) -> Tuple[Dict[str, str], Dict[str, str]]: + console_scripts = {} + gui_scripts = {} + for entry_point in dist.iter_entry_points(): + if entry_point.group == "console_scripts": + console_scripts[entry_point.name] = entry_point.value + elif entry_point.group == "gui_scripts": + gui_scripts[entry_point.name] = entry_point.value + return console_scripts, gui_scripts + + +def message_about_scripts_not_on_PATH(scripts: Sequence[str]) -> Optional[str]: + """Determine if any scripts are not on PATH and format a warning. + Returns a warning message if one or more scripts are not on PATH, + otherwise None. + """ + if not scripts: + return None + + # Group scripts by the path they were installed in + grouped_by_dir: Dict[str, Set[str]] = collections.defaultdict(set) + for destfile in scripts: + parent_dir = os.path.dirname(destfile) + script_name = os.path.basename(destfile) + grouped_by_dir[parent_dir].add(script_name) + + # We don't want to warn for directories that are on PATH. + not_warn_dirs = [ + os.path.normcase(os.path.normpath(i)).rstrip(os.sep) + for i in os.environ.get("PATH", "").split(os.pathsep) + ] + # If an executable sits with sys.executable, we don't warn for it. + # This covers the case of venv invocations without activating the venv. + not_warn_dirs.append( + os.path.normcase(os.path.normpath(os.path.dirname(sys.executable))) + ) + warn_for: Dict[str, Set[str]] = { + parent_dir: scripts + for parent_dir, scripts in grouped_by_dir.items() + if os.path.normcase(os.path.normpath(parent_dir)) not in not_warn_dirs + } + if not warn_for: + return None + + # Format a message + msg_lines = [] + for parent_dir, dir_scripts in warn_for.items(): + sorted_scripts: List[str] = sorted(dir_scripts) + if len(sorted_scripts) == 1: + start_text = f"script {sorted_scripts[0]} is" + else: + start_text = "scripts {} are".format( + ", ".join(sorted_scripts[:-1]) + " and " + sorted_scripts[-1] + ) + + msg_lines.append( + f"The {start_text} installed in '{parent_dir}' which is not on PATH." + ) + + last_line_fmt = ( + "Consider adding {} to PATH or, if you prefer " + "to suppress this warning, use --no-warn-script-location." + ) + if len(msg_lines) == 1: + msg_lines.append(last_line_fmt.format("this directory")) + else: + msg_lines.append(last_line_fmt.format("these directories")) + + # Add a note if any directory starts with ~ + warn_for_tilde = any( + i[0] == "~" for i in os.environ.get("PATH", "").split(os.pathsep) if i + ) + if warn_for_tilde: + tilde_warning_msg = ( + "NOTE: The current PATH contains path(s) starting with `~`, " + "which may not be expanded by all applications." + ) + msg_lines.append(tilde_warning_msg) + + # Returns the formatted multiline message + return "\n".join(msg_lines) + + +def _normalized_outrows( + outrows: Iterable[InstalledCSVRow], +) -> List[Tuple[str, str, str]]: + """Normalize the given rows of a RECORD file. + + Items in each row are converted into str. Rows are then sorted to make + the value more predictable for tests. + + Each row is a 3-tuple (path, hash, size) and corresponds to a record of + a RECORD file (see PEP 376 and PEP 427 for details). For the rows + passed to this function, the size can be an integer as an int or string, + or the empty string. + """ + # Normally, there should only be one row per path, in which case the + # second and third elements don't come into play when sorting. + # However, in cases in the wild where a path might happen to occur twice, + # we don't want the sort operation to trigger an error (but still want + # determinism). Since the third element can be an int or string, we + # coerce each element to a string to avoid a TypeError in this case. + # For additional background, see-- + # https://github.com/pypa/pip/issues/5868 + return sorted( + (record_path, hash_, str(size)) for record_path, hash_, size in outrows + ) + + +def _record_to_fs_path(record_path: RecordPath, lib_dir: str) -> str: + return os.path.join(lib_dir, record_path) + + +def _fs_to_record_path(path: str, lib_dir: str) -> RecordPath: + # On Windows, do not handle relative paths if they belong to different + # logical disks + if os.path.splitdrive(path)[0].lower() == os.path.splitdrive(lib_dir)[0].lower(): + path = os.path.relpath(path, lib_dir) + + path = path.replace(os.path.sep, "/") + return cast("RecordPath", path) + + +def get_csv_rows_for_installed( + old_csv_rows: List[List[str]], + installed: Dict[RecordPath, RecordPath], + changed: Set[RecordPath], + generated: List[str], + lib_dir: str, +) -> List[InstalledCSVRow]: + """ + :param installed: A map from archive RECORD path to installation RECORD + path. + """ + installed_rows: List[InstalledCSVRow] = [] + for row in old_csv_rows: + if len(row) > 3: + logger.warning("RECORD line has more than three elements: %s", row) + old_record_path = cast("RecordPath", row[0]) + new_record_path = installed.pop(old_record_path, old_record_path) + if new_record_path in changed: + digest, length = rehash(_record_to_fs_path(new_record_path, lib_dir)) + else: + digest = row[1] if len(row) > 1 else "" + length = row[2] if len(row) > 2 else "" + installed_rows.append((new_record_path, digest, length)) + for f in generated: + path = _fs_to_record_path(f, lib_dir) + digest, length = rehash(f) + installed_rows.append((path, digest, length)) + return installed_rows + [ + (installed_record_path, "", "") for installed_record_path in installed.values() + ] + + +def get_console_script_specs(console: Dict[str, str]) -> List[str]: + """ + Given the mapping from entrypoint name to callable, return the relevant + console script specs. + """ + # Don't mutate caller's version + console = console.copy() + + scripts_to_generate = [] + + # Special case pip and setuptools to generate versioned wrappers + # + # The issue is that some projects (specifically, pip and setuptools) use + # code in setup.py to create "versioned" entry points - pip2.7 on Python + # 2.7, pip3.3 on Python 3.3, etc. But these entry points are baked into + # the wheel metadata at build time, and so if the wheel is installed with + # a *different* version of Python the entry points will be wrong. The + # correct fix for this is to enhance the metadata to be able to describe + # such versioned entry points. + # Currently, projects using versioned entry points will either have + # incorrect versioned entry points, or they will not be able to distribute + # "universal" wheels (i.e., they will need a wheel per Python version). + # + # Because setuptools and pip are bundled with _ensurepip and virtualenv, + # we need to use universal wheels. As a workaround, we + # override the versioned entry points in the wheel and generate the + # correct ones. + # + # To add the level of hack in this section of code, in order to support + # ensurepip this code will look for an ``ENSUREPIP_OPTIONS`` environment + # variable which will control which version scripts get installed. + # + # ENSUREPIP_OPTIONS=altinstall + # - Only pipX.Y and easy_install-X.Y will be generated and installed + # ENSUREPIP_OPTIONS=install + # - pipX.Y, pipX, easy_install-X.Y will be generated and installed. Note + # that this option is technically if ENSUREPIP_OPTIONS is set and is + # not altinstall + # DEFAULT + # - The default behavior is to install pip, pipX, pipX.Y, easy_install + # and easy_install-X.Y. + pip_script = console.pop("pip", None) + if pip_script: + if "ENSUREPIP_OPTIONS" not in os.environ: + scripts_to_generate.append("pip = " + pip_script) + + if os.environ.get("ENSUREPIP_OPTIONS", "") != "altinstall": + scripts_to_generate.append(f"pip{sys.version_info[0]} = {pip_script}") + + scripts_to_generate.append(f"pip{get_major_minor_version()} = {pip_script}") + # Delete any other versioned pip entry points + pip_ep = [k for k in console if re.match(r"pip(\d+(\.\d+)?)?$", k)] + for k in pip_ep: + del console[k] + easy_install_script = console.pop("easy_install", None) + if easy_install_script: + if "ENSUREPIP_OPTIONS" not in os.environ: + scripts_to_generate.append("easy_install = " + easy_install_script) + + scripts_to_generate.append( + f"easy_install-{get_major_minor_version()} = {easy_install_script}" + ) + # Delete any other versioned easy_install entry points + easy_install_ep = [ + k for k in console if re.match(r"easy_install(-\d+\.\d+)?$", k) + ] + for k in easy_install_ep: + del console[k] + + # Generate the console entry points specified in the wheel + scripts_to_generate.extend(starmap("{} = {}".format, console.items())) + + return scripts_to_generate + + +class ZipBackedFile: + def __init__( + self, src_record_path: RecordPath, dest_path: str, zip_file: ZipFile + ) -> None: + self.src_record_path = src_record_path + self.dest_path = dest_path + self._zip_file = zip_file + self.changed = False + + def _getinfo(self) -> ZipInfo: + return self._zip_file.getinfo(self.src_record_path) + + def save(self) -> None: + # When we open the output file below, any existing file is truncated + # before we start writing the new contents. This is fine in most + # cases, but can cause a segfault if pip has loaded a shared + # object (e.g. from pyopenssl through its vendored urllib3) + # Since the shared object is mmap'd an attempt to call a + # symbol in it will then cause a segfault. Unlinking the file + # allows writing of new contents while allowing the process to + # continue to use the old copy. + if os.path.exists(self.dest_path): + os.unlink(self.dest_path) + + zipinfo = self._getinfo() + + # optimization: the file is created by open(), + # skip the decompression when there is 0 bytes to decompress. + with open(self.dest_path, "wb") as dest: + if zipinfo.file_size > 0: + with self._zip_file.open(zipinfo) as f: + blocksize = min(zipinfo.file_size, 1024 * 1024) + shutil.copyfileobj(f, dest, blocksize) + + if zip_item_is_executable(zipinfo): + set_extracted_file_to_default_mode_plus_executable(self.dest_path) + + +class ScriptFile: + def __init__(self, file: "File") -> None: + self._file = file + self.src_record_path = self._file.src_record_path + self.dest_path = self._file.dest_path + self.changed = False + + def save(self) -> None: + self._file.save() + self.changed = fix_script(self.dest_path) + + +class MissingCallableSuffix(InstallationError): + def __init__(self, entry_point: str) -> None: + super().__init__( + f"Invalid script entry point: {entry_point} - A callable " + "suffix is required. Cf https://packaging.python.org/" + "specifications/entry-points/#use-for-scripts for more " + "information." + ) + + +def _raise_for_invalid_entrypoint(specification: str) -> None: + entry = get_export_entry(specification) + if entry is not None and entry.suffix is None: + raise MissingCallableSuffix(str(entry)) + + +class PipScriptMaker(ScriptMaker): + def make( + self, specification: str, options: Optional[Dict[str, Any]] = None + ) -> List[str]: + _raise_for_invalid_entrypoint(specification) + return super().make(specification, options) + + +def _install_wheel( # noqa: C901, PLR0915 function is too long + name: str, + wheel_zip: ZipFile, + wheel_path: str, + scheme: Scheme, + pycompile: bool = True, + warn_script_location: bool = True, + direct_url: Optional[DirectUrl] = None, + requested: bool = False, +) -> None: + """Install a wheel. + + :param name: Name of the project to install + :param wheel_zip: open ZipFile for wheel being installed + :param scheme: Distutils scheme dictating the install directories + :param req_description: String used in place of the requirement, for + logging + :param pycompile: Whether to byte-compile installed Python files + :param warn_script_location: Whether to check that scripts are installed + into a directory on PATH + :raises UnsupportedWheel: + * when the directory holds an unpacked wheel with incompatible + Wheel-Version + * when the .dist-info dir does not match the wheel + """ + info_dir, metadata = parse_wheel(wheel_zip, name) + + if wheel_root_is_purelib(metadata): + lib_dir = scheme.purelib + else: + lib_dir = scheme.platlib + + # Record details of the files moved + # installed = files copied from the wheel to the destination + # changed = files changed while installing (scripts #! line typically) + # generated = files newly generated during the install (script wrappers) + installed: Dict[RecordPath, RecordPath] = {} + changed: Set[RecordPath] = set() + generated: List[str] = [] + + def record_installed( + srcfile: RecordPath, destfile: str, modified: bool = False + ) -> None: + """Map archive RECORD paths to installation RECORD paths.""" + newpath = _fs_to_record_path(destfile, lib_dir) + installed[srcfile] = newpath + if modified: + changed.add(newpath) + + def is_dir_path(path: RecordPath) -> bool: + return path.endswith("/") + + def assert_no_path_traversal(dest_dir_path: str, target_path: str) -> None: + if not is_within_directory(dest_dir_path, target_path): + message = ( + "The wheel {!r} has a file {!r} trying to install" + " outside the target directory {!r}" + ) + raise InstallationError( + message.format(wheel_path, target_path, dest_dir_path) + ) + + def root_scheme_file_maker( + zip_file: ZipFile, dest: str + ) -> Callable[[RecordPath], "File"]: + def make_root_scheme_file(record_path: RecordPath) -> "File": + normed_path = os.path.normpath(record_path) + dest_path = os.path.join(dest, normed_path) + assert_no_path_traversal(dest, dest_path) + return ZipBackedFile(record_path, dest_path, zip_file) + + return make_root_scheme_file + + def data_scheme_file_maker( + zip_file: ZipFile, scheme: Scheme + ) -> Callable[[RecordPath], "File"]: + scheme_paths = {key: getattr(scheme, key) for key in SCHEME_KEYS} + + def make_data_scheme_file(record_path: RecordPath) -> "File": + normed_path = os.path.normpath(record_path) + try: + _, scheme_key, dest_subpath = normed_path.split(os.path.sep, 2) + except ValueError: + message = ( + f"Unexpected file in {wheel_path}: {record_path!r}. .data directory" + " contents should be named like: '/'." + ) + raise InstallationError(message) + + try: + scheme_path = scheme_paths[scheme_key] + except KeyError: + valid_scheme_keys = ", ".join(sorted(scheme_paths)) + message = ( + f"Unknown scheme key used in {wheel_path}: {scheme_key} " + f"(for file {record_path!r}). .data directory contents " + f"should be in subdirectories named with a valid scheme " + f"key ({valid_scheme_keys})" + ) + raise InstallationError(message) + + dest_path = os.path.join(scheme_path, dest_subpath) + assert_no_path_traversal(scheme_path, dest_path) + return ZipBackedFile(record_path, dest_path, zip_file) + + return make_data_scheme_file + + def is_data_scheme_path(path: RecordPath) -> bool: + return path.split("/", 1)[0].endswith(".data") + + paths = cast(List[RecordPath], wheel_zip.namelist()) + file_paths = filterfalse(is_dir_path, paths) + root_scheme_paths, data_scheme_paths = partition(is_data_scheme_path, file_paths) + + make_root_scheme_file = root_scheme_file_maker(wheel_zip, lib_dir) + files: Iterator[File] = map(make_root_scheme_file, root_scheme_paths) + + def is_script_scheme_path(path: RecordPath) -> bool: + parts = path.split("/", 2) + return len(parts) > 2 and parts[0].endswith(".data") and parts[1] == "scripts" + + other_scheme_paths, script_scheme_paths = partition( + is_script_scheme_path, data_scheme_paths + ) + + make_data_scheme_file = data_scheme_file_maker(wheel_zip, scheme) + other_scheme_files = map(make_data_scheme_file, other_scheme_paths) + files = chain(files, other_scheme_files) + + # Get the defined entry points + distribution = get_wheel_distribution( + FilesystemWheel(wheel_path), + canonicalize_name(name), + ) + console, gui = get_entrypoints(distribution) + + def is_entrypoint_wrapper(file: "File") -> bool: + # EP, EP.exe and EP-script.py are scripts generated for + # entry point EP by setuptools + path = file.dest_path + name = os.path.basename(path) + if name.lower().endswith(".exe"): + matchname = name[:-4] + elif name.lower().endswith("-script.py"): + matchname = name[:-10] + elif name.lower().endswith(".pya"): + matchname = name[:-4] + else: + matchname = name + # Ignore setuptools-generated scripts + return matchname in console or matchname in gui + + script_scheme_files: Iterator[File] = map( + make_data_scheme_file, script_scheme_paths + ) + script_scheme_files = filterfalse(is_entrypoint_wrapper, script_scheme_files) + script_scheme_files = map(ScriptFile, script_scheme_files) + files = chain(files, script_scheme_files) + + existing_parents = set() + for file in files: + # directory creation is lazy and after file filtering + # to ensure we don't install empty dirs; empty dirs can't be + # uninstalled. + parent_dir = os.path.dirname(file.dest_path) + if parent_dir not in existing_parents: + ensure_dir(parent_dir) + existing_parents.add(parent_dir) + file.save() + record_installed(file.src_record_path, file.dest_path, file.changed) + + def pyc_source_file_paths() -> Generator[str, None, None]: + # We de-duplicate installation paths, since there can be overlap (e.g. + # file in .data maps to same location as file in wheel root). + # Sorting installation paths makes it easier to reproduce and debug + # issues related to permissions on existing files. + for installed_path in sorted(set(installed.values())): + full_installed_path = os.path.join(lib_dir, installed_path) + if not os.path.isfile(full_installed_path): + continue + if not full_installed_path.endswith(".py"): + continue + yield full_installed_path + + def pyc_output_path(path: str) -> str: + """Return the path the pyc file would have been written to.""" + return importlib.util.cache_from_source(path) + + # Compile all of the pyc files for the installed files + if pycompile: + with contextlib.redirect_stdout( + StreamWrapper.from_stream(sys.stdout) + ) as stdout: + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + for path in pyc_source_file_paths(): + success = compileall.compile_file(path, force=True, quiet=True) + if success: + pyc_path = pyc_output_path(path) + assert os.path.exists(pyc_path) + pyc_record_path = cast( + "RecordPath", pyc_path.replace(os.path.sep, "/") + ) + record_installed(pyc_record_path, pyc_path) + logger.debug(stdout.getvalue()) + + maker = PipScriptMaker(None, scheme.scripts) + + # Ensure old scripts are overwritten. + # See https://github.com/pypa/pip/issues/1800 + maker.clobber = True + + # Ensure we don't generate any variants for scripts because this is almost + # never what somebody wants. + # See https://bitbucket.org/pypa/distlib/issue/35/ + maker.variants = {""} + + # This is required because otherwise distlib creates scripts that are not + # executable. + # See https://bitbucket.org/pypa/distlib/issue/32/ + maker.set_mode = True + + # Generate the console and GUI entry points specified in the wheel + scripts_to_generate = get_console_script_specs(console) + + gui_scripts_to_generate = list(starmap("{} = {}".format, gui.items())) + + generated_console_scripts = maker.make_multiple(scripts_to_generate) + generated.extend(generated_console_scripts) + + generated.extend(maker.make_multiple(gui_scripts_to_generate, {"gui": True})) + + if warn_script_location: + msg = message_about_scripts_not_on_PATH(generated_console_scripts) + if msg is not None: + logger.warning(msg) + + generated_file_mode = 0o666 & ~current_umask() + + @contextlib.contextmanager + def _generate_file(path: str, **kwargs: Any) -> Generator[BinaryIO, None, None]: + with adjacent_tmp_file(path, **kwargs) as f: + yield f + os.chmod(f.name, generated_file_mode) + replace(f.name, path) + + dest_info_dir = os.path.join(lib_dir, info_dir) + + # Record pip as the installer + installer_path = os.path.join(dest_info_dir, "INSTALLER") + with _generate_file(installer_path) as installer_file: + installer_file.write(b"pip\n") + generated.append(installer_path) + + # Record the PEP 610 direct URL reference + if direct_url is not None: + direct_url_path = os.path.join(dest_info_dir, DIRECT_URL_METADATA_NAME) + with _generate_file(direct_url_path) as direct_url_file: + direct_url_file.write(direct_url.to_json().encode("utf-8")) + generated.append(direct_url_path) + + # Record the REQUESTED file + if requested: + requested_path = os.path.join(dest_info_dir, "REQUESTED") + with open(requested_path, "wb"): + pass + generated.append(requested_path) + + record_text = distribution.read_text("RECORD") + record_rows = list(csv.reader(record_text.splitlines())) + + rows = get_csv_rows_for_installed( + record_rows, + installed=installed, + changed=changed, + generated=generated, + lib_dir=lib_dir, + ) + + # Record details of all files installed + record_path = os.path.join(dest_info_dir, "RECORD") + + with _generate_file(record_path, **csv_io_kwargs("w")) as record_file: + # Explicitly cast to typing.IO[str] as a workaround for the mypy error: + # "writer" has incompatible type "BinaryIO"; expected "_Writer" + writer = csv.writer(cast("IO[str]", record_file)) + writer.writerows(_normalized_outrows(rows)) + + +@contextlib.contextmanager +def req_error_context(req_description: str) -> Generator[None, None, None]: + try: + yield + except InstallationError as e: + message = f"For req: {req_description}. {e.args[0]}" + raise InstallationError(message) from e + + +def install_wheel( + name: str, + wheel_path: str, + scheme: Scheme, + req_description: str, + pycompile: bool = True, + warn_script_location: bool = True, + direct_url: Optional[DirectUrl] = None, + requested: bool = False, +) -> None: + with ZipFile(wheel_path, allowZip64=True) as z: + with req_error_context(req_description): + _install_wheel( + name=name, + wheel_zip=z, + wheel_path=wheel_path, + scheme=scheme, + pycompile=pycompile, + warn_script_location=warn_script_location, + direct_url=direct_url, + requested=requested, + ) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/operations/prepare.py b/backend/.venv/Lib/site-packages/pip/_internal/operations/prepare.py new file mode 100644 index 0000000..e6aa344 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/operations/prepare.py @@ -0,0 +1,732 @@ +"""Prepares a distribution for installation +""" + +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False + +import mimetypes +import os +import shutil +from dataclasses import dataclass +from pathlib import Path +from typing import Dict, Iterable, List, Optional + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.distributions import make_distribution_for_install_requirement +from pip._internal.distributions.installed import InstalledDistribution +from pip._internal.exceptions import ( + DirectoryUrlHashUnsupported, + HashMismatch, + HashUnpinned, + InstallationError, + MetadataInconsistent, + NetworkConnectionError, + VcsHashUnsupported, +) +from pip._internal.index.package_finder import PackageFinder +from pip._internal.metadata import BaseDistribution, get_metadata_distribution +from pip._internal.models.direct_url import ArchiveInfo +from pip._internal.models.link import Link +from pip._internal.models.wheel import Wheel +from pip._internal.network.download import BatchDownloader, Downloader +from pip._internal.network.lazy_wheel import ( + HTTPRangeRequestUnsupported, + dist_from_wheel_url, +) +from pip._internal.network.session import PipSession +from pip._internal.operations.build.build_tracker import BuildTracker +from pip._internal.req.req_install import InstallRequirement +from pip._internal.utils._log import getLogger +from pip._internal.utils.direct_url_helpers import ( + direct_url_for_editable, + direct_url_from_link, +) +from pip._internal.utils.hashes import Hashes, MissingHashes +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import ( + display_path, + hash_file, + hide_url, + redact_auth_from_requirement, +) +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.unpacking import unpack_file +from pip._internal.vcs import vcs + +logger = getLogger(__name__) + + +def _get_prepared_distribution( + req: InstallRequirement, + build_tracker: BuildTracker, + finder: PackageFinder, + build_isolation: bool, + check_build_deps: bool, +) -> BaseDistribution: + """Prepare a distribution for installation.""" + abstract_dist = make_distribution_for_install_requirement(req) + tracker_id = abstract_dist.build_tracker_id + if tracker_id is not None: + with build_tracker.track(req, tracker_id): + abstract_dist.prepare_distribution_metadata( + finder, build_isolation, check_build_deps + ) + return abstract_dist.get_metadata_distribution() + + +def unpack_vcs_link(link: Link, location: str, verbosity: int) -> None: + vcs_backend = vcs.get_backend_for_scheme(link.scheme) + assert vcs_backend is not None + vcs_backend.unpack(location, url=hide_url(link.url), verbosity=verbosity) + + +@dataclass +class File: + path: str + content_type: Optional[str] = None + + def __post_init__(self) -> None: + if self.content_type is None: + self.content_type = mimetypes.guess_type(self.path)[0] + + +def get_http_url( + link: Link, + download: Downloader, + download_dir: Optional[str] = None, + hashes: Optional[Hashes] = None, +) -> File: + temp_dir = TempDirectory(kind="unpack", globally_managed=True) + # If a download dir is specified, is the file already downloaded there? + already_downloaded_path = None + if download_dir: + already_downloaded_path = _check_download_dir(link, download_dir, hashes) + + if already_downloaded_path: + from_path = already_downloaded_path + content_type = None + else: + # let's download to a tmp dir + from_path, content_type = download(link, temp_dir.path) + if hashes: + hashes.check_against_path(from_path) + + return File(from_path, content_type) + + +def get_file_url( + link: Link, download_dir: Optional[str] = None, hashes: Optional[Hashes] = None +) -> File: + """Get file and optionally check its hash.""" + # If a download dir is specified, is the file already there and valid? + already_downloaded_path = None + if download_dir: + already_downloaded_path = _check_download_dir(link, download_dir, hashes) + + if already_downloaded_path: + from_path = already_downloaded_path + else: + from_path = link.file_path + + # If --require-hashes is off, `hashes` is either empty, the + # link's embedded hash, or MissingHashes; it is required to + # match. If --require-hashes is on, we are satisfied by any + # hash in `hashes` matching: a URL-based or an option-based + # one; no internet-sourced hash will be in `hashes`. + if hashes: + hashes.check_against_path(from_path) + return File(from_path, None) + + +def unpack_url( + link: Link, + location: str, + download: Downloader, + verbosity: int, + download_dir: Optional[str] = None, + hashes: Optional[Hashes] = None, +) -> Optional[File]: + """Unpack link into location, downloading if required. + + :param hashes: A Hashes object, one of whose embedded hashes must match, + or HashMismatch will be raised. If the Hashes is empty, no matches are + required, and unhashable types of requirements (like VCS ones, which + would ordinarily raise HashUnsupported) are allowed. + """ + # non-editable vcs urls + if link.is_vcs: + unpack_vcs_link(link, location, verbosity=verbosity) + return None + + assert not link.is_existing_dir() + + # file urls + if link.is_file: + file = get_file_url(link, download_dir, hashes=hashes) + + # http urls + else: + file = get_http_url( + link, + download, + download_dir, + hashes=hashes, + ) + + # unpack the archive to the build dir location. even when only downloading + # archives, they have to be unpacked to parse dependencies, except wheels + if not link.is_wheel: + unpack_file(file.path, location, file.content_type) + + return file + + +def _check_download_dir( + link: Link, + download_dir: str, + hashes: Optional[Hashes], + warn_on_hash_mismatch: bool = True, +) -> Optional[str]: + """Check download_dir for previously downloaded file with correct hash + If a correct file is found return its path else None + """ + download_path = os.path.join(download_dir, link.filename) + + if not os.path.exists(download_path): + return None + + # If already downloaded, does its hash match? + logger.info("File was already downloaded %s", download_path) + if hashes: + try: + hashes.check_against_path(download_path) + except HashMismatch: + if warn_on_hash_mismatch: + logger.warning( + "Previously-downloaded file %s has bad hash. Re-downloading.", + download_path, + ) + os.unlink(download_path) + return None + return download_path + + +class RequirementPreparer: + """Prepares a Requirement""" + + def __init__( + self, + build_dir: str, + download_dir: Optional[str], + src_dir: str, + build_isolation: bool, + check_build_deps: bool, + build_tracker: BuildTracker, + session: PipSession, + progress_bar: str, + finder: PackageFinder, + require_hashes: bool, + use_user_site: bool, + lazy_wheel: bool, + verbosity: int, + legacy_resolver: bool, + ) -> None: + super().__init__() + + self.src_dir = src_dir + self.build_dir = build_dir + self.build_tracker = build_tracker + self._session = session + self._download = Downloader(session, progress_bar) + self._batch_download = BatchDownloader(session, progress_bar) + self.finder = finder + + # Where still-packed archives should be written to. If None, they are + # not saved, and are deleted immediately after unpacking. + self.download_dir = download_dir + + # Is build isolation allowed? + self.build_isolation = build_isolation + + # Should check build dependencies? + self.check_build_deps = check_build_deps + + # Should hash-checking be required? + self.require_hashes = require_hashes + + # Should install in user site-packages? + self.use_user_site = use_user_site + + # Should wheels be downloaded lazily? + self.use_lazy_wheel = lazy_wheel + + # How verbose should underlying tooling be? + self.verbosity = verbosity + + # Are we using the legacy resolver? + self.legacy_resolver = legacy_resolver + + # Memoized downloaded files, as mapping of url: path. + self._downloaded: Dict[str, str] = {} + + # Previous "header" printed for a link-based InstallRequirement + self._previous_requirement_header = ("", "") + + def _log_preparing_link(self, req: InstallRequirement) -> None: + """Provide context for the requirement being prepared.""" + if req.link.is_file and not req.is_wheel_from_cache: + message = "Processing %s" + information = str(display_path(req.link.file_path)) + else: + message = "Collecting %s" + information = redact_auth_from_requirement(req.req) if req.req else str(req) + + # If we used req.req, inject requirement source if available (this + # would already be included if we used req directly) + if req.req and req.comes_from: + if isinstance(req.comes_from, str): + comes_from: Optional[str] = req.comes_from + else: + comes_from = req.comes_from.from_path() + if comes_from: + information += f" (from {comes_from})" + + if (message, information) != self._previous_requirement_header: + self._previous_requirement_header = (message, information) + logger.info(message, information) + + if req.is_wheel_from_cache: + with indent_log(): + logger.info("Using cached %s", req.link.filename) + + def _ensure_link_req_src_dir( + self, req: InstallRequirement, parallel_builds: bool + ) -> None: + """Ensure source_dir of a linked InstallRequirement.""" + # Since source_dir is only set for editable requirements. + if req.link.is_wheel: + # We don't need to unpack wheels, so no need for a source + # directory. + return + assert req.source_dir is None + if req.link.is_existing_dir(): + # build local directories in-tree + req.source_dir = req.link.file_path + return + + # We always delete unpacked sdists after pip runs. + req.ensure_has_source_dir( + self.build_dir, + autodelete=True, + parallel_builds=parallel_builds, + ) + req.ensure_pristine_source_checkout() + + def _get_linked_req_hashes(self, req: InstallRequirement) -> Hashes: + # By the time this is called, the requirement's link should have + # been checked so we can tell what kind of requirements req is + # and raise some more informative errors than otherwise. + # (For example, we can raise VcsHashUnsupported for a VCS URL + # rather than HashMissing.) + if not self.require_hashes: + return req.hashes(trust_internet=True) + + # We could check these first 2 conditions inside unpack_url + # and save repetition of conditions, but then we would + # report less-useful error messages for unhashable + # requirements, complaining that there's no hash provided. + if req.link.is_vcs: + raise VcsHashUnsupported() + if req.link.is_existing_dir(): + raise DirectoryUrlHashUnsupported() + + # Unpinned packages are asking for trouble when a new version + # is uploaded. This isn't a security check, but it saves users + # a surprising hash mismatch in the future. + # file:/// URLs aren't pinnable, so don't complain about them + # not being pinned. + if not req.is_direct and not req.is_pinned: + raise HashUnpinned() + + # If known-good hashes are missing for this requirement, + # shim it with a facade object that will provoke hash + # computation and then raise a HashMissing exception + # showing the user what the hash should be. + return req.hashes(trust_internet=False) or MissingHashes() + + def _fetch_metadata_only( + self, + req: InstallRequirement, + ) -> Optional[BaseDistribution]: + if self.legacy_resolver: + logger.debug( + "Metadata-only fetching is not used in the legacy resolver", + ) + return None + if self.require_hashes: + logger.debug( + "Metadata-only fetching is not used as hash checking is required", + ) + return None + # Try PEP 658 metadata first, then fall back to lazy wheel if unavailable. + return self._fetch_metadata_using_link_data_attr( + req + ) or self._fetch_metadata_using_lazy_wheel(req.link) + + def _fetch_metadata_using_link_data_attr( + self, + req: InstallRequirement, + ) -> Optional[BaseDistribution]: + """Fetch metadata from the data-dist-info-metadata attribute, if possible.""" + # (1) Get the link to the metadata file, if provided by the backend. + metadata_link = req.link.metadata_link() + if metadata_link is None: + return None + assert req.req is not None + logger.verbose( + "Obtaining dependency information for %s from %s", + req.req, + metadata_link, + ) + # (2) Download the contents of the METADATA file, separate from the dist itself. + metadata_file = get_http_url( + metadata_link, + self._download, + hashes=metadata_link.as_hashes(), + ) + with open(metadata_file.path, "rb") as f: + metadata_contents = f.read() + # (3) Generate a dist just from those file contents. + metadata_dist = get_metadata_distribution( + metadata_contents, + req.link.filename, + req.req.name, + ) + # (4) Ensure the Name: field from the METADATA file matches the name from the + # install requirement. + # + # NB: raw_name will fall back to the name from the install requirement if + # the Name: field is not present, but it's noted in the raw_name docstring + # that that should NEVER happen anyway. + if canonicalize_name(metadata_dist.raw_name) != canonicalize_name(req.req.name): + raise MetadataInconsistent( + req, "Name", req.req.name, metadata_dist.raw_name + ) + return metadata_dist + + def _fetch_metadata_using_lazy_wheel( + self, + link: Link, + ) -> Optional[BaseDistribution]: + """Fetch metadata using lazy wheel, if possible.""" + # --use-feature=fast-deps must be provided. + if not self.use_lazy_wheel: + return None + if link.is_file or not link.is_wheel: + logger.debug( + "Lazy wheel is not used as %r does not point to a remote wheel", + link, + ) + return None + + wheel = Wheel(link.filename) + name = canonicalize_name(wheel.name) + logger.info( + "Obtaining dependency information from %s %s", + name, + wheel.version, + ) + url = link.url.split("#", 1)[0] + try: + return dist_from_wheel_url(name, url, self._session) + except HTTPRangeRequestUnsupported: + logger.debug("%s does not support range requests", url) + return None + + def _complete_partial_requirements( + self, + partially_downloaded_reqs: Iterable[InstallRequirement], + parallel_builds: bool = False, + ) -> None: + """Download any requirements which were only fetched by metadata.""" + # Download to a temporary directory. These will be copied over as + # needed for downstream 'download', 'wheel', and 'install' commands. + temp_dir = TempDirectory(kind="unpack", globally_managed=True).path + + # Map each link to the requirement that owns it. This allows us to set + # `req.local_file_path` on the appropriate requirement after passing + # all the links at once into BatchDownloader. + links_to_fully_download: Dict[Link, InstallRequirement] = {} + for req in partially_downloaded_reqs: + assert req.link + links_to_fully_download[req.link] = req + + batch_download = self._batch_download( + links_to_fully_download.keys(), + temp_dir, + ) + for link, (filepath, _) in batch_download: + logger.debug("Downloading link %s to %s", link, filepath) + req = links_to_fully_download[link] + # Record the downloaded file path so wheel reqs can extract a Distribution + # in .get_dist(). + req.local_file_path = filepath + # Record that the file is downloaded so we don't do it again in + # _prepare_linked_requirement(). + self._downloaded[req.link.url] = filepath + + # If this is an sdist, we need to unpack it after downloading, but the + # .source_dir won't be set up until we are in _prepare_linked_requirement(). + # Add the downloaded archive to the install requirement to unpack after + # preparing the source dir. + if not req.is_wheel: + req.needs_unpacked_archive(Path(filepath)) + + # This step is necessary to ensure all lazy wheels are processed + # successfully by the 'download', 'wheel', and 'install' commands. + for req in partially_downloaded_reqs: + self._prepare_linked_requirement(req, parallel_builds) + + def prepare_linked_requirement( + self, req: InstallRequirement, parallel_builds: bool = False + ) -> BaseDistribution: + """Prepare a requirement to be obtained from req.link.""" + assert req.link + self._log_preparing_link(req) + with indent_log(): + # Check if the relevant file is already available + # in the download directory + file_path = None + if self.download_dir is not None and req.link.is_wheel: + hashes = self._get_linked_req_hashes(req) + file_path = _check_download_dir( + req.link, + self.download_dir, + hashes, + # When a locally built wheel has been found in cache, we don't warn + # about re-downloading when the already downloaded wheel hash does + # not match. This is because the hash must be checked against the + # original link, not the cached link. It that case the already + # downloaded file will be removed and re-fetched from cache (which + # implies a hash check against the cache entry's origin.json). + warn_on_hash_mismatch=not req.is_wheel_from_cache, + ) + + if file_path is not None: + # The file is already available, so mark it as downloaded + self._downloaded[req.link.url] = file_path + else: + # The file is not available, attempt to fetch only metadata + metadata_dist = self._fetch_metadata_only(req) + if metadata_dist is not None: + req.needs_more_preparation = True + return metadata_dist + + # None of the optimizations worked, fully prepare the requirement + return self._prepare_linked_requirement(req, parallel_builds) + + def prepare_linked_requirements_more( + self, reqs: Iterable[InstallRequirement], parallel_builds: bool = False + ) -> None: + """Prepare linked requirements more, if needed.""" + reqs = [req for req in reqs if req.needs_more_preparation] + for req in reqs: + # Determine if any of these requirements were already downloaded. + if self.download_dir is not None and req.link.is_wheel: + hashes = self._get_linked_req_hashes(req) + file_path = _check_download_dir(req.link, self.download_dir, hashes) + if file_path is not None: + self._downloaded[req.link.url] = file_path + req.needs_more_preparation = False + + # Prepare requirements we found were already downloaded for some + # reason. The other downloads will be completed separately. + partially_downloaded_reqs: List[InstallRequirement] = [] + for req in reqs: + if req.needs_more_preparation: + partially_downloaded_reqs.append(req) + else: + self._prepare_linked_requirement(req, parallel_builds) + + # TODO: separate this part out from RequirementPreparer when the v1 + # resolver can be removed! + self._complete_partial_requirements( + partially_downloaded_reqs, + parallel_builds=parallel_builds, + ) + + def _prepare_linked_requirement( + self, req: InstallRequirement, parallel_builds: bool + ) -> BaseDistribution: + assert req.link + link = req.link + + hashes = self._get_linked_req_hashes(req) + + if hashes and req.is_wheel_from_cache: + assert req.download_info is not None + assert link.is_wheel + assert link.is_file + # We need to verify hashes, and we have found the requirement in the cache + # of locally built wheels. + if ( + isinstance(req.download_info.info, ArchiveInfo) + and req.download_info.info.hashes + and hashes.has_one_of(req.download_info.info.hashes) + ): + # At this point we know the requirement was built from a hashable source + # artifact, and we verified that the cache entry's hash of the original + # artifact matches one of the hashes we expect. We don't verify hashes + # against the cached wheel, because the wheel is not the original. + hashes = None + else: + logger.warning( + "The hashes of the source archive found in cache entry " + "don't match, ignoring cached built wheel " + "and re-downloading source." + ) + req.link = req.cached_wheel_source_link + link = req.link + + self._ensure_link_req_src_dir(req, parallel_builds) + + if link.is_existing_dir(): + local_file = None + elif link.url not in self._downloaded: + try: + local_file = unpack_url( + link, + req.source_dir, + self._download, + self.verbosity, + self.download_dir, + hashes, + ) + except NetworkConnectionError as exc: + raise InstallationError( + f"Could not install requirement {req} because of HTTP " + f"error {exc} for URL {link}" + ) + else: + file_path = self._downloaded[link.url] + if hashes: + hashes.check_against_path(file_path) + local_file = File(file_path, content_type=None) + + # If download_info is set, we got it from the wheel cache. + if req.download_info is None: + # Editables don't go through this function (see + # prepare_editable_requirement). + assert not req.editable + req.download_info = direct_url_from_link(link, req.source_dir) + # Make sure we have a hash in download_info. If we got it as part of the + # URL, it will have been verified and we can rely on it. Otherwise we + # compute it from the downloaded file. + # FIXME: https://github.com/pypa/pip/issues/11943 + if ( + isinstance(req.download_info.info, ArchiveInfo) + and not req.download_info.info.hashes + and local_file + ): + hash = hash_file(local_file.path)[0].hexdigest() + # We populate info.hash for backward compatibility. + # This will automatically populate info.hashes. + req.download_info.info.hash = f"sha256={hash}" + + # For use in later processing, + # preserve the file path on the requirement. + if local_file: + req.local_file_path = local_file.path + + dist = _get_prepared_distribution( + req, + self.build_tracker, + self.finder, + self.build_isolation, + self.check_build_deps, + ) + return dist + + def save_linked_requirement(self, req: InstallRequirement) -> None: + assert self.download_dir is not None + assert req.link is not None + link = req.link + if link.is_vcs or (link.is_existing_dir() and req.editable): + # Make a .zip of the source_dir we already created. + req.archive(self.download_dir) + return + + if link.is_existing_dir(): + logger.debug( + "Not copying link to destination directory " + "since it is a directory: %s", + link, + ) + return + if req.local_file_path is None: + # No distribution was downloaded for this requirement. + return + + download_location = os.path.join(self.download_dir, link.filename) + if not os.path.exists(download_location): + shutil.copy(req.local_file_path, download_location) + download_path = display_path(download_location) + logger.info("Saved %s", download_path) + + def prepare_editable_requirement( + self, + req: InstallRequirement, + ) -> BaseDistribution: + """Prepare an editable requirement.""" + assert req.editable, "cannot prepare a non-editable req as editable" + + logger.info("Obtaining %s", req) + + with indent_log(): + if self.require_hashes: + raise InstallationError( + f"The editable requirement {req} cannot be installed when " + "requiring hashes, because there is no single file to " + "hash." + ) + req.ensure_has_source_dir(self.src_dir) + req.update_editable() + assert req.source_dir + req.download_info = direct_url_for_editable(req.unpacked_source_directory) + + dist = _get_prepared_distribution( + req, + self.build_tracker, + self.finder, + self.build_isolation, + self.check_build_deps, + ) + + req.check_if_exists(self.use_user_site) + + return dist + + def prepare_installed_requirement( + self, + req: InstallRequirement, + skip_reason: str, + ) -> BaseDistribution: + """Prepare an already-installed requirement.""" + assert req.satisfied_by, "req should have been satisfied but isn't" + assert skip_reason is not None, ( + "did not get skip reason skipped but req.satisfied_by " + f"is set to {req.satisfied_by}" + ) + logger.info( + "Requirement %s: %s (%s)", skip_reason, req, req.satisfied_by.version + ) + with indent_log(): + if self.require_hashes: + logger.debug( + "Since it is already installed, we are trusting this " + "package without checking its hash. To ensure a " + "completely repeatable environment, install into an " + "empty virtualenv." + ) + return InstalledDistribution(req).get_metadata_distribution() diff --git a/backend/.venv/Lib/site-packages/pip/_internal/pyproject.py b/backend/.venv/Lib/site-packages/pip/_internal/pyproject.py new file mode 100644 index 0000000..2a9cad4 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/pyproject.py @@ -0,0 +1,185 @@ +import importlib.util +import os +import sys +from collections import namedtuple +from typing import Any, List, Optional + +if sys.version_info >= (3, 11): + import tomllib +else: + from pip._vendor import tomli as tomllib + +from pip._vendor.packaging.requirements import InvalidRequirement + +from pip._internal.exceptions import ( + InstallationError, + InvalidPyProjectBuildRequires, + MissingPyProjectBuildRequires, +) +from pip._internal.utils.packaging import get_requirement + + +def _is_list_of_str(obj: Any) -> bool: + return isinstance(obj, list) and all(isinstance(item, str) for item in obj) + + +def make_pyproject_path(unpacked_source_directory: str) -> str: + return os.path.join(unpacked_source_directory, "pyproject.toml") + + +BuildSystemDetails = namedtuple( + "BuildSystemDetails", ["requires", "backend", "check", "backend_path"] +) + + +def load_pyproject_toml( + use_pep517: Optional[bool], pyproject_toml: str, setup_py: str, req_name: str +) -> Optional[BuildSystemDetails]: + """Load the pyproject.toml file. + + Parameters: + use_pep517 - Has the user requested PEP 517 processing? None + means the user hasn't explicitly specified. + pyproject_toml - Location of the project's pyproject.toml file + setup_py - Location of the project's setup.py file + req_name - The name of the requirement we're processing (for + error reporting) + + Returns: + None if we should use the legacy code path, otherwise a tuple + ( + requirements from pyproject.toml, + name of PEP 517 backend, + requirements we should check are installed after setting + up the build environment + directory paths to import the backend from (backend-path), + relative to the project root. + ) + """ + has_pyproject = os.path.isfile(pyproject_toml) + has_setup = os.path.isfile(setup_py) + + if not has_pyproject and not has_setup: + raise InstallationError( + f"{req_name} does not appear to be a Python project: " + f"neither 'setup.py' nor 'pyproject.toml' found." + ) + + if has_pyproject: + with open(pyproject_toml, encoding="utf-8") as f: + pp_toml = tomllib.loads(f.read()) + build_system = pp_toml.get("build-system") + else: + build_system = None + + # The following cases must use PEP 517 + # We check for use_pep517 being non-None and falsey because that means + # the user explicitly requested --no-use-pep517. The value 0 as + # opposed to False can occur when the value is provided via an + # environment variable or config file option (due to the quirk of + # strtobool() returning an integer in pip's configuration code). + if has_pyproject and not has_setup: + if use_pep517 is not None and not use_pep517: + raise InstallationError( + "Disabling PEP 517 processing is invalid: " + "project does not have a setup.py" + ) + use_pep517 = True + elif build_system and "build-backend" in build_system: + if use_pep517 is not None and not use_pep517: + raise InstallationError( + "Disabling PEP 517 processing is invalid: " + "project specifies a build backend of {} " + "in pyproject.toml".format(build_system["build-backend"]) + ) + use_pep517 = True + + # If we haven't worked out whether to use PEP 517 yet, + # and the user hasn't explicitly stated a preference, + # we do so if the project has a pyproject.toml file + # or if we cannot import setuptools or wheels. + + # We fallback to PEP 517 when without setuptools or without the wheel package, + # so setuptools can be installed as a default build backend. + # For more info see: + # https://discuss.python.org/t/pip-without-setuptools-could-the-experience-be-improved/11810/9 + # https://github.com/pypa/pip/issues/8559 + elif use_pep517 is None: + use_pep517 = ( + has_pyproject + or not importlib.util.find_spec("setuptools") + or not importlib.util.find_spec("wheel") + ) + + # At this point, we know whether we're going to use PEP 517. + assert use_pep517 is not None + + # If we're using the legacy code path, there is nothing further + # for us to do here. + if not use_pep517: + return None + + if build_system is None: + # Either the user has a pyproject.toml with no build-system + # section, or the user has no pyproject.toml, but has opted in + # explicitly via --use-pep517. + # In the absence of any explicit backend specification, we + # assume the setuptools backend that most closely emulates the + # traditional direct setup.py execution, and require wheel and + # a version of setuptools that supports that backend. + + build_system = { + "requires": ["setuptools>=40.8.0"], + "build-backend": "setuptools.build_meta:__legacy__", + } + + # If we're using PEP 517, we have build system information (either + # from pyproject.toml, or defaulted by the code above). + # Note that at this point, we do not know if the user has actually + # specified a backend, though. + assert build_system is not None + + # Ensure that the build-system section in pyproject.toml conforms + # to PEP 518. + + # Specifying the build-system table but not the requires key is invalid + if "requires" not in build_system: + raise MissingPyProjectBuildRequires(package=req_name) + + # Error out if requires is not a list of strings + requires = build_system["requires"] + if not _is_list_of_str(requires): + raise InvalidPyProjectBuildRequires( + package=req_name, + reason="It is not a list of strings.", + ) + + # Each requirement must be valid as per PEP 508 + for requirement in requires: + try: + get_requirement(requirement) + except InvalidRequirement as error: + raise InvalidPyProjectBuildRequires( + package=req_name, + reason=f"It contains an invalid requirement: {requirement!r}", + ) from error + + backend = build_system.get("build-backend") + backend_path = build_system.get("backend-path", []) + check: List[str] = [] + if backend is None: + # If the user didn't specify a backend, we assume they want to use + # the setuptools backend. But we can't be sure they have included + # a version of setuptools which supplies the backend. So we + # make a note to check that this requirement is present once + # we have set up the environment. + # This is quite a lot of work to check for a very specific case. But + # the problem is, that case is potentially quite common - projects that + # adopted PEP 518 early for the ability to specify requirements to + # execute setup.py, but never considered needing to mention the build + # tools themselves. The original PEP 518 code had a similar check (but + # implemented in a different way). + backend = "setuptools.build_meta:__legacy__" + check = ["setuptools>=40.8.0"] + + return BuildSystemDetails(requires, backend, check, backend_path) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/req/__init__.py b/backend/.venv/Lib/site-packages/pip/_internal/req/__init__.py new file mode 100644 index 0000000..422d851 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/req/__init__.py @@ -0,0 +1,90 @@ +import collections +import logging +from dataclasses import dataclass +from typing import Generator, List, Optional, Sequence, Tuple + +from pip._internal.utils.logging import indent_log + +from .req_file import parse_requirements +from .req_install import InstallRequirement +from .req_set import RequirementSet + +__all__ = [ + "RequirementSet", + "InstallRequirement", + "parse_requirements", + "install_given_reqs", +] + +logger = logging.getLogger(__name__) + + +@dataclass(frozen=True) +class InstallationResult: + name: str + + +def _validate_requirements( + requirements: List[InstallRequirement], +) -> Generator[Tuple[str, InstallRequirement], None, None]: + for req in requirements: + assert req.name, f"invalid to-be-installed requirement: {req}" + yield req.name, req + + +def install_given_reqs( + requirements: List[InstallRequirement], + global_options: Sequence[str], + root: Optional[str], + home: Optional[str], + prefix: Optional[str], + warn_script_location: bool, + use_user_site: bool, + pycompile: bool, +) -> List[InstallationResult]: + """ + Install everything in the given list. + + (to be called after having downloaded and unpacked the packages) + """ + to_install = collections.OrderedDict(_validate_requirements(requirements)) + + if to_install: + logger.info( + "Installing collected packages: %s", + ", ".join(to_install.keys()), + ) + + installed = [] + + with indent_log(): + for req_name, requirement in to_install.items(): + if requirement.should_reinstall: + logger.info("Attempting uninstall: %s", req_name) + with indent_log(): + uninstalled_pathset = requirement.uninstall(auto_confirm=True) + else: + uninstalled_pathset = None + + try: + requirement.install( + global_options, + root=root, + home=home, + prefix=prefix, + warn_script_location=warn_script_location, + use_user_site=use_user_site, + pycompile=pycompile, + ) + except Exception: + # if install did not succeed, rollback previous uninstall + if uninstalled_pathset and not requirement.install_succeeded: + uninstalled_pathset.rollback() + raise + else: + if uninstalled_pathset and requirement.install_succeeded: + uninstalled_pathset.commit() + + installed.append(InstallationResult(req_name)) + + return installed diff --git a/backend/.venv/Lib/site-packages/pip/_internal/req/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/req/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f019b447ba479a1b47f772f9c6bf15f0fb99beec GIT binary patch literal 3447 zcmahMTWk~A_0Gfgj34nMwiEJL3?U>=NCLZJSy(8G%Dccygnq1>)o9|mPR5L9ym!Xr zQAdpsl|t2u@X-dT>POojDyX!d{iOSls`kew&{(sevT9fA{+SIDE&b`aV~>+{yX|r2 z-gE9f_ndR@J&&6|g+hJ=aPfP`)b|1VD7C`^u{SdLdBH~38VHr^-}aF@ds!@efg*}~#2EP;0@N%*?p z3xlSlBQK_OgS?&vCcWcJYRRQEV~dJx$yrS{&9uiB&tM%B*)oXDUr5u6H5emRe}pJYtqqkx@pOpc6nl2kC1l1A~MBz;hlwdM?G zTEq@ZlC0~7VGAD`^eOsL9UubIg6+Cyk(Bb*{o60EmfZx%NhhvP0QJ< zSXZXTVMo`dE~wK}rfT6aSa4OI!RAy^ElxvkbqPzNg6LMkSJ(znj|2m z51JpMXa3NQbA;ZnGh+u~QS0z+FTqxc=-H-|0vAF&d;{=p=AiiwV&K5a=p=f77@;Mm z%;aIT9Zdgu2)HuybMy<=b>i#az*}Z=?9Z4rhCx3b;n4#6EjP!c*-MLqs(ww@R3&8@ zW7Bx7dAV3gZ8P{tD$S4>Xiu}G7do4xw@#xcl_EWKASpRQWb5l*Ms~s^U11)E=I`hq z%V^V!B7G}dEgZWw|D*YeaJtg_&V$Yep308X>%!@k`C3Qx*6hvMJKRcPUFd!80q%dA z^lYwA902c}(Tr(XlME*SOq(Z$0lqS86tL|r5}Z@#?f9Hbbji#TwMe5N>-d8mDnSIm zM|1Du)8&6wJs>%%oQ#p?JbW>m64lW+vH5p7u)I;Mq%?*V;hu(JdL?Fa4*=^;AStH4VOeK?6SLj2f>9v5_Qfta5=!aeu>Z& z>}<)u6etJs^orYn9Q{9g;L83jOTNL1Kt9nX7D$D^?{W9C6jZ$Qw{ez zO9x=DO^75J@>!_x*RP z%?Macqo@tGtiF!skSq7=`ltGe{fy6iCPHKvNS`6Vnd7OB777a#GD&PCl}|P#R}26jN2t88)9cRNdyU;suk? zAhkV^9}1=&F=vgEra*yfnq!MC%WR)J7HuMuS;}THh9j}PkXQ<;Ws9fgv)IW~wm@L( zw8+?Axmbis;}nH-$jPQ8MNR*od$Rp-0Io{0iGV5r@~~4K?ZCElZFjZ|#fnsvtyvRW zCQT{S1zO-_Zqh-O(}o_Uc^=$*8NGN7#rij*!`0~UqxA6y!S(dT_2{ML^Pl^oPlS$J zft!I^aH1BB+&Xvj+-iQ!xNWQ_ht`9`FFc&+ulrH7bNSrg#Ll1e)dnXv1`k#T5B_=Z zP&K$~IlDk)@>RvQ7T8RwQ`Do}sEz-LY8K_1EYVqB*9sTsLcULWathRfi_S#TA zjG}v9AR!ui{u+u8-FQ1bK6y?4LAF>&GH#05v({%U;xqxkE! zNTM#n^sARc+m^pFkHMM#K6QdS)y;i0(0MZD`{>O8;2*QyC-?Cm_q+}GCn?X#bl{Ug zAI0~jPbGYxCMf@>-JVmsed%731{t=Gx-0~T9cVoau}Ns9vc1+q5oQRjk%U$xLW>Te z8IjP^X7|GDWxVxz882C?W{x-IH9X#Nqa4)2#tV=7lIv~G!_W575pW{sEol4Tp`~f? z2oqRK=b@`a zmc7rthz+dndBk+RWErNTj-c7(5ZhgMNWsJO)nds?SGpP-sdGR*^K`6~RwpYx`zncj z)$rI|>%%LR@ZqZG$fgIT>yblDV%rL!p2hp_Oy0g&_W%wq8R%Sn3`7)v~x!P2Gc%6)c^nh literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/req/__pycache__/constructors.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/req/__pycache__/constructors.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fb111b435c019f9ee631df4c9b2bb16fabb3ebdf GIT binary patch literal 21257 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/req/__pycache__/req_file.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/req/__pycache__/req_file.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..28b6945b9cabaae9aa753571a370ccf523f521df GIT binary patch literal 22125 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 b$NwH!Wu1vxzWjY@!?}aP-|uXAP7wYt3{L!d literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/req/__pycache__/req_install.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/req/__pycache__/req_install.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ef536ec985aaa788d32552b02e084665b61f43ee GIT binary patch literal 38477 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 M34-SdLCV+s513WWzW@LL literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..18b340af3173b555a92e15871640a622bd24a165 GIT binary patch literal 32096 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 Tuple[str, Optional[str]]: + m = re.match(r"^(.+)(\[[^\]]+\])$", path) + extras = None + if m: + path_no_extras = m.group(1) + extras = m.group(2) + else: + path_no_extras = path + + return path_no_extras, extras + + +def convert_extras(extras: Optional[str]) -> Set[str]: + if not extras: + return set() + return get_requirement("placeholder" + extras.lower()).extras + + +def _set_requirement_extras(req: Requirement, new_extras: Set[str]) -> Requirement: + """ + Returns a new requirement based on the given one, with the supplied extras. If the + given requirement already has extras those are replaced (or dropped if no new extras + are given). + """ + match: Optional[re.Match[str]] = re.fullmatch( + # see https://peps.python.org/pep-0508/#complete-grammar + r"([\w\t .-]+)(\[[^\]]*\])?(.*)", + str(req), + flags=re.ASCII, + ) + # ireq.req is a valid requirement so the regex should always match + assert ( + match is not None + ), f"regex match on requirement {req} failed, this should never happen" + pre: Optional[str] = match.group(1) + post: Optional[str] = match.group(3) + assert ( + pre is not None and post is not None + ), f"regex group selection for requirement {req} failed, this should never happen" + extras: str = "[{}]".format(",".join(sorted(new_extras)) if new_extras else "") + return get_requirement(f"{pre}{extras}{post}") + + +def parse_editable(editable_req: str) -> Tuple[Optional[str], str, Set[str]]: + """Parses an editable requirement into: + - a requirement name + - an URL + - extras + - editable options + Accepted requirements: + svn+http://blahblah@rev#egg=Foobar[baz]&subdirectory=version_subdir + .[some_extra] + """ + + url = editable_req + + # If a file path is specified with extras, strip off the extras. + url_no_extras, extras = _strip_extras(url) + + if os.path.isdir(url_no_extras): + # Treating it as code that has already been checked out + url_no_extras = path_to_url(url_no_extras) + + if url_no_extras.lower().startswith("file:"): + package_name = Link(url_no_extras).egg_fragment + if extras: + return ( + package_name, + url_no_extras, + get_requirement("placeholder" + extras.lower()).extras, + ) + else: + return package_name, url_no_extras, set() + + for version_control in vcs: + if url.lower().startswith(f"{version_control}:"): + url = f"{version_control}+{url}" + break + + link = Link(url) + + if not link.is_vcs: + backends = ", ".join(vcs.all_schemes) + raise InstallationError( + f"{editable_req} is not a valid editable requirement. " + f"It should either be a path to a local project or a VCS URL " + f"(beginning with {backends})." + ) + + package_name = link.egg_fragment + if not package_name: + raise InstallationError( + f"Could not detect requirement name for '{editable_req}', " + "please specify one with #egg=your_package_name" + ) + return package_name, url, set() + + +def check_first_requirement_in_file(filename: str) -> None: + """Check if file is parsable as a requirements file. + + This is heavily based on ``pkg_resources.parse_requirements``, but + simplified to just check the first meaningful line. + + :raises InvalidRequirement: If the first meaningful line cannot be parsed + as an requirement. + """ + with open(filename, encoding="utf-8", errors="ignore") as f: + # Create a steppable iterator, so we can handle \-continuations. + lines = ( + line + for line in (line.strip() for line in f) + if line and not line.startswith("#") # Skip blank lines/comments. + ) + + for line in lines: + # Drop comments -- a hash without a space may be in a URL. + if " #" in line: + line = line[: line.find(" #")] + # If there is a line continuation, drop it, and append the next line. + if line.endswith("\\"): + line = line[:-2].strip() + next(lines, "") + get_requirement(line) + return + + +def deduce_helpful_msg(req: str) -> str: + """Returns helpful msg in case requirements file does not exist, + or cannot be parsed. + + :params req: Requirements file path + """ + if not os.path.exists(req): + return f" File '{req}' does not exist." + msg = " The path does exist. " + # Try to parse and check if it is a requirements file. + try: + check_first_requirement_in_file(req) + except InvalidRequirement: + logger.debug("Cannot parse '%s' as requirements file", req) + else: + msg += ( + f"The argument you provided " + f"({req}) appears to be a" + f" requirements file. If that is the" + f" case, use the '-r' flag to install" + f" the packages specified within it." + ) + return msg + + +@dataclass(frozen=True) +class RequirementParts: + requirement: Optional[Requirement] + link: Optional[Link] + markers: Optional[Marker] + extras: Set[str] + + +def parse_req_from_editable(editable_req: str) -> RequirementParts: + name, url, extras_override = parse_editable(editable_req) + + if name is not None: + try: + req: Optional[Requirement] = get_requirement(name) + except InvalidRequirement as exc: + raise InstallationError(f"Invalid requirement: {name!r}: {exc}") + else: + req = None + + link = Link(url) + + return RequirementParts(req, link, None, extras_override) + + +# ---- The actual constructors follow ---- + + +def install_req_from_editable( + editable_req: str, + comes_from: Optional[Union[InstallRequirement, str]] = None, + *, + use_pep517: Optional[bool] = None, + isolated: bool = False, + global_options: Optional[List[str]] = None, + hash_options: Optional[Dict[str, List[str]]] = None, + constraint: bool = False, + user_supplied: bool = False, + permit_editable_wheels: bool = False, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, +) -> InstallRequirement: + parts = parse_req_from_editable(editable_req) + + return InstallRequirement( + parts.requirement, + comes_from=comes_from, + user_supplied=user_supplied, + editable=True, + permit_editable_wheels=permit_editable_wheels, + link=parts.link, + constraint=constraint, + use_pep517=use_pep517, + isolated=isolated, + global_options=global_options, + hash_options=hash_options, + config_settings=config_settings, + extras=parts.extras, + ) + + +def _looks_like_path(name: str) -> bool: + """Checks whether the string "looks like" a path on the filesystem. + + This does not check whether the target actually exists, only judge from the + appearance. + + Returns true if any of the following conditions is true: + * a path separator is found (either os.path.sep or os.path.altsep); + * a dot is found (which represents the current directory). + """ + if os.path.sep in name: + return True + if os.path.altsep is not None and os.path.altsep in name: + return True + if name.startswith("."): + return True + return False + + +def _get_url_from_path(path: str, name: str) -> Optional[str]: + """ + First, it checks whether a provided path is an installable directory. If it + is, returns the path. + + If false, check if the path is an archive file (such as a .whl). + The function checks if the path is a file. If false, if the path has + an @, it will treat it as a PEP 440 URL requirement and return the path. + """ + if _looks_like_path(name) and os.path.isdir(path): + if is_installable_dir(path): + return path_to_url(path) + # TODO: The is_installable_dir test here might not be necessary + # now that it is done in load_pyproject_toml too. + raise InstallationError( + f"Directory {name!r} is not installable. Neither 'setup.py' " + "nor 'pyproject.toml' found." + ) + if not is_archive_file(path): + return None + if os.path.isfile(path): + return path_to_url(path) + urlreq_parts = name.split("@", 1) + if len(urlreq_parts) >= 2 and not _looks_like_path(urlreq_parts[0]): + # If the path contains '@' and the part before it does not look + # like a path, try to treat it as a PEP 440 URL req instead. + return None + logger.warning( + "Requirement %r looks like a filename, but the file does not exist", + name, + ) + return path_to_url(path) + + +def parse_req_from_line(name: str, line_source: Optional[str]) -> RequirementParts: + if is_url(name): + marker_sep = "; " + else: + marker_sep = ";" + if marker_sep in name: + name, markers_as_string = name.split(marker_sep, 1) + markers_as_string = markers_as_string.strip() + if not markers_as_string: + markers = None + else: + markers = Marker(markers_as_string) + else: + markers = None + name = name.strip() + req_as_string = None + path = os.path.normpath(os.path.abspath(name)) + link = None + extras_as_string = None + + if is_url(name): + link = Link(name) + else: + p, extras_as_string = _strip_extras(path) + url = _get_url_from_path(p, name) + if url is not None: + link = Link(url) + + # it's a local file, dir, or url + if link: + # Handle relative file URLs + if link.scheme == "file" and re.search(r"\.\./", link.url): + link = Link(path_to_url(os.path.normpath(os.path.abspath(link.path)))) + # wheel file + if link.is_wheel: + wheel = Wheel(link.filename) # can raise InvalidWheelFilename + req_as_string = f"{wheel.name}=={wheel.version}" + else: + # set the req to the egg fragment. when it's not there, this + # will become an 'unnamed' requirement + req_as_string = link.egg_fragment + + # a requirement specifier + else: + req_as_string = name + + extras = convert_extras(extras_as_string) + + def with_source(text: str) -> str: + if not line_source: + return text + return f"{text} (from {line_source})" + + def _parse_req_string(req_as_string: str) -> Requirement: + try: + return get_requirement(req_as_string) + except InvalidRequirement as exc: + if os.path.sep in req_as_string: + add_msg = "It looks like a path." + add_msg += deduce_helpful_msg(req_as_string) + elif "=" in req_as_string and not any( + op in req_as_string for op in operators + ): + add_msg = "= is not a valid operator. Did you mean == ?" + else: + add_msg = "" + msg = with_source(f"Invalid requirement: {req_as_string!r}: {exc}") + if add_msg: + msg += f"\nHint: {add_msg}" + raise InstallationError(msg) + + if req_as_string is not None: + req: Optional[Requirement] = _parse_req_string(req_as_string) + else: + req = None + + return RequirementParts(req, link, markers, extras) + + +def install_req_from_line( + name: str, + comes_from: Optional[Union[str, InstallRequirement]] = None, + *, + use_pep517: Optional[bool] = None, + isolated: bool = False, + global_options: Optional[List[str]] = None, + hash_options: Optional[Dict[str, List[str]]] = None, + constraint: bool = False, + line_source: Optional[str] = None, + user_supplied: bool = False, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, +) -> InstallRequirement: + """Creates an InstallRequirement from a name, which might be a + requirement, directory containing 'setup.py', filename, or URL. + + :param line_source: An optional string describing where the line is from, + for logging purposes in case of an error. + """ + parts = parse_req_from_line(name, line_source) + + return InstallRequirement( + parts.requirement, + comes_from, + link=parts.link, + markers=parts.markers, + use_pep517=use_pep517, + isolated=isolated, + global_options=global_options, + hash_options=hash_options, + config_settings=config_settings, + constraint=constraint, + extras=parts.extras, + user_supplied=user_supplied, + ) + + +def install_req_from_req_string( + req_string: str, + comes_from: Optional[InstallRequirement] = None, + isolated: bool = False, + use_pep517: Optional[bool] = None, + user_supplied: bool = False, +) -> InstallRequirement: + try: + req = get_requirement(req_string) + except InvalidRequirement as exc: + raise InstallationError(f"Invalid requirement: {req_string!r}: {exc}") + + domains_not_allowed = [ + PyPI.file_storage_domain, + TestPyPI.file_storage_domain, + ] + if ( + req.url + and comes_from + and comes_from.link + and comes_from.link.netloc in domains_not_allowed + ): + # Explicitly disallow pypi packages that depend on external urls + raise InstallationError( + "Packages installed from PyPI cannot depend on packages " + "which are not also hosted on PyPI.\n" + f"{comes_from.name} depends on {req} " + ) + + return InstallRequirement( + req, + comes_from, + isolated=isolated, + use_pep517=use_pep517, + user_supplied=user_supplied, + ) + + +def install_req_from_parsed_requirement( + parsed_req: ParsedRequirement, + isolated: bool = False, + use_pep517: Optional[bool] = None, + user_supplied: bool = False, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, +) -> InstallRequirement: + if parsed_req.is_editable: + req = install_req_from_editable( + parsed_req.requirement, + comes_from=parsed_req.comes_from, + use_pep517=use_pep517, + constraint=parsed_req.constraint, + isolated=isolated, + user_supplied=user_supplied, + config_settings=config_settings, + ) + + else: + req = install_req_from_line( + parsed_req.requirement, + comes_from=parsed_req.comes_from, + use_pep517=use_pep517, + isolated=isolated, + global_options=( + parsed_req.options.get("global_options", []) + if parsed_req.options + else [] + ), + hash_options=( + parsed_req.options.get("hashes", {}) if parsed_req.options else {} + ), + constraint=parsed_req.constraint, + line_source=parsed_req.line_source, + user_supplied=user_supplied, + config_settings=config_settings, + ) + return req + + +def install_req_from_link_and_ireq( + link: Link, ireq: InstallRequirement +) -> InstallRequirement: + return InstallRequirement( + req=ireq.req, + comes_from=ireq.comes_from, + editable=ireq.editable, + link=link, + markers=ireq.markers, + use_pep517=ireq.use_pep517, + isolated=ireq.isolated, + global_options=ireq.global_options, + hash_options=ireq.hash_options, + config_settings=ireq.config_settings, + user_supplied=ireq.user_supplied, + ) + + +def install_req_drop_extras(ireq: InstallRequirement) -> InstallRequirement: + """ + Creates a new InstallationRequirement using the given template but without + any extras. Sets the original requirement as the new one's parent + (comes_from). + """ + return InstallRequirement( + req=( + _set_requirement_extras(ireq.req, set()) if ireq.req is not None else None + ), + comes_from=ireq, + editable=ireq.editable, + link=ireq.link, + markers=ireq.markers, + use_pep517=ireq.use_pep517, + isolated=ireq.isolated, + global_options=ireq.global_options, + hash_options=ireq.hash_options, + constraint=ireq.constraint, + extras=[], + config_settings=ireq.config_settings, + user_supplied=ireq.user_supplied, + permit_editable_wheels=ireq.permit_editable_wheels, + ) + + +def install_req_extend_extras( + ireq: InstallRequirement, + extras: Collection[str], +) -> InstallRequirement: + """ + Returns a copy of an installation requirement with some additional extras. + Makes a shallow copy of the ireq object. + """ + result = copy.copy(ireq) + result.extras = {*ireq.extras, *extras} + result.req = ( + _set_requirement_extras(ireq.req, result.extras) + if ireq.req is not None + else None + ) + return result diff --git a/backend/.venv/Lib/site-packages/pip/_internal/req/req_file.py b/backend/.venv/Lib/site-packages/pip/_internal/req/req_file.py new file mode 100644 index 0000000..eb2a1f6 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/req/req_file.py @@ -0,0 +1,574 @@ +""" +Requirements file parsing +""" + +import logging +import optparse +import os +import re +import shlex +import urllib.parse +from optparse import Values +from typing import ( + TYPE_CHECKING, + Any, + Callable, + Dict, + Generator, + Iterable, + List, + NoReturn, + Optional, + Tuple, +) + +from pip._internal.cli import cmdoptions +from pip._internal.exceptions import InstallationError, RequirementsFileParseError +from pip._internal.models.search_scope import SearchScope +from pip._internal.utils.encoding import auto_decode + +if TYPE_CHECKING: + from pip._internal.index.package_finder import PackageFinder + from pip._internal.network.session import PipSession + +__all__ = ["parse_requirements"] + +ReqFileLines = Iterable[Tuple[int, str]] + +LineParser = Callable[[str], Tuple[str, Values]] + +SCHEME_RE = re.compile(r"^(http|https|file):", re.I) +COMMENT_RE = re.compile(r"(^|\s+)#.*$") + +# Matches environment variable-style values in '${MY_VARIABLE_1}' with the +# variable name consisting of only uppercase letters, digits or the '_' +# (underscore). This follows the POSIX standard defined in IEEE Std 1003.1, +# 2013 Edition. +ENV_VAR_RE = re.compile(r"(?P\$\{(?P[A-Z0-9_]+)\})") + +SUPPORTED_OPTIONS: List[Callable[..., optparse.Option]] = [ + cmdoptions.index_url, + cmdoptions.extra_index_url, + cmdoptions.no_index, + cmdoptions.constraints, + cmdoptions.requirements, + cmdoptions.editable, + cmdoptions.find_links, + cmdoptions.no_binary, + cmdoptions.only_binary, + cmdoptions.prefer_binary, + cmdoptions.require_hashes, + cmdoptions.pre, + cmdoptions.trusted_host, + cmdoptions.use_new_feature, +] + +# options to be passed to requirements +SUPPORTED_OPTIONS_REQ: List[Callable[..., optparse.Option]] = [ + cmdoptions.global_options, + cmdoptions.hash, + cmdoptions.config_settings, +] + +SUPPORTED_OPTIONS_EDITABLE_REQ: List[Callable[..., optparse.Option]] = [ + cmdoptions.config_settings, +] + + +# the 'dest' string values +SUPPORTED_OPTIONS_REQ_DEST = [str(o().dest) for o in SUPPORTED_OPTIONS_REQ] +SUPPORTED_OPTIONS_EDITABLE_REQ_DEST = [ + str(o().dest) for o in SUPPORTED_OPTIONS_EDITABLE_REQ +] + +logger = logging.getLogger(__name__) + + +class ParsedRequirement: + def __init__( + self, + requirement: str, + is_editable: bool, + comes_from: str, + constraint: bool, + options: Optional[Dict[str, Any]] = None, + line_source: Optional[str] = None, + ) -> None: + self.requirement = requirement + self.is_editable = is_editable + self.comes_from = comes_from + self.options = options + self.constraint = constraint + self.line_source = line_source + + +class ParsedLine: + def __init__( + self, + filename: str, + lineno: int, + args: str, + opts: Values, + constraint: bool, + ) -> None: + self.filename = filename + self.lineno = lineno + self.opts = opts + self.constraint = constraint + + if args: + self.is_requirement = True + self.is_editable = False + self.requirement = args + elif opts.editables: + self.is_requirement = True + self.is_editable = True + # We don't support multiple -e on one line + self.requirement = opts.editables[0] + else: + self.is_requirement = False + + +def parse_requirements( + filename: str, + session: "PipSession", + finder: Optional["PackageFinder"] = None, + options: Optional[optparse.Values] = None, + constraint: bool = False, +) -> Generator[ParsedRequirement, None, None]: + """Parse a requirements file and yield ParsedRequirement instances. + + :param filename: Path or url of requirements file. + :param session: PipSession instance. + :param finder: Instance of pip.index.PackageFinder. + :param options: cli options. + :param constraint: If true, parsing a constraint file rather than + requirements file. + """ + line_parser = get_line_parser(finder) + parser = RequirementsFileParser(session, line_parser) + + for parsed_line in parser.parse(filename, constraint): + parsed_req = handle_line( + parsed_line, options=options, finder=finder, session=session + ) + if parsed_req is not None: + yield parsed_req + + +def preprocess(content: str) -> ReqFileLines: + """Split, filter, and join lines, and return a line iterator + + :param content: the content of the requirements file + """ + lines_enum: ReqFileLines = enumerate(content.splitlines(), start=1) + lines_enum = join_lines(lines_enum) + lines_enum = ignore_comments(lines_enum) + lines_enum = expand_env_variables(lines_enum) + return lines_enum + + +def handle_requirement_line( + line: ParsedLine, + options: Optional[optparse.Values] = None, +) -> ParsedRequirement: + # preserve for the nested code path + line_comes_from = "{} {} (line {})".format( + "-c" if line.constraint else "-r", + line.filename, + line.lineno, + ) + + assert line.is_requirement + + # get the options that apply to requirements + if line.is_editable: + supported_dest = SUPPORTED_OPTIONS_EDITABLE_REQ_DEST + else: + supported_dest = SUPPORTED_OPTIONS_REQ_DEST + req_options = {} + for dest in supported_dest: + if dest in line.opts.__dict__ and line.opts.__dict__[dest]: + req_options[dest] = line.opts.__dict__[dest] + + line_source = f"line {line.lineno} of {line.filename}" + return ParsedRequirement( + requirement=line.requirement, + is_editable=line.is_editable, + comes_from=line_comes_from, + constraint=line.constraint, + options=req_options, + line_source=line_source, + ) + + +def handle_option_line( + opts: Values, + filename: str, + lineno: int, + finder: Optional["PackageFinder"] = None, + options: Optional[optparse.Values] = None, + session: Optional["PipSession"] = None, +) -> None: + if opts.hashes: + logger.warning( + "%s line %s has --hash but no requirement, and will be ignored.", + filename, + lineno, + ) + + if options: + # percolate options upward + if opts.require_hashes: + options.require_hashes = opts.require_hashes + if opts.features_enabled: + options.features_enabled.extend( + f for f in opts.features_enabled if f not in options.features_enabled + ) + + # set finder options + if finder: + find_links = finder.find_links + index_urls = finder.index_urls + no_index = finder.search_scope.no_index + if opts.no_index is True: + no_index = True + index_urls = [] + if opts.index_url and not no_index: + index_urls = [opts.index_url] + if opts.extra_index_urls and not no_index: + index_urls.extend(opts.extra_index_urls) + if opts.find_links: + # FIXME: it would be nice to keep track of the source + # of the find_links: support a find-links local path + # relative to a requirements file. + value = opts.find_links[0] + req_dir = os.path.dirname(os.path.abspath(filename)) + relative_to_reqs_file = os.path.join(req_dir, value) + if os.path.exists(relative_to_reqs_file): + value = relative_to_reqs_file + find_links.append(value) + + if session: + # We need to update the auth urls in session + session.update_index_urls(index_urls) + + search_scope = SearchScope( + find_links=find_links, + index_urls=index_urls, + no_index=no_index, + ) + finder.search_scope = search_scope + + if opts.pre: + finder.set_allow_all_prereleases() + + if opts.prefer_binary: + finder.set_prefer_binary() + + if session: + for host in opts.trusted_hosts or []: + source = f"line {lineno} of {filename}" + session.add_trusted_host(host, source=source) + + +def handle_line( + line: ParsedLine, + options: Optional[optparse.Values] = None, + finder: Optional["PackageFinder"] = None, + session: Optional["PipSession"] = None, +) -> Optional[ParsedRequirement]: + """Handle a single parsed requirements line; This can result in + creating/yielding requirements, or updating the finder. + + :param line: The parsed line to be processed. + :param options: CLI options. + :param finder: The finder - updated by non-requirement lines. + :param session: The session - updated by non-requirement lines. + + Returns a ParsedRequirement object if the line is a requirement line, + otherwise returns None. + + For lines that contain requirements, the only options that have an effect + are from SUPPORTED_OPTIONS_REQ, and they are scoped to the + requirement. Other options from SUPPORTED_OPTIONS may be present, but are + ignored. + + For lines that do not contain requirements, the only options that have an + effect are from SUPPORTED_OPTIONS. Options from SUPPORTED_OPTIONS_REQ may + be present, but are ignored. These lines may contain multiple options + (although our docs imply only one is supported), and all our parsed and + affect the finder. + """ + + if line.is_requirement: + parsed_req = handle_requirement_line(line, options) + return parsed_req + else: + handle_option_line( + line.opts, + line.filename, + line.lineno, + finder, + options, + session, + ) + return None + + +class RequirementsFileParser: + def __init__( + self, + session: "PipSession", + line_parser: LineParser, + ) -> None: + self._session = session + self._line_parser = line_parser + + def parse( + self, filename: str, constraint: bool + ) -> Generator[ParsedLine, None, None]: + """Parse a given file, yielding parsed lines.""" + yield from self._parse_and_recurse( + filename, constraint, [{os.path.abspath(filename): None}] + ) + + def _parse_and_recurse( + self, + filename: str, + constraint: bool, + parsed_files_stack: List[Dict[str, Optional[str]]], + ) -> Generator[ParsedLine, None, None]: + for line in self._parse_file(filename, constraint): + if not line.is_requirement and ( + line.opts.requirements or line.opts.constraints + ): + # parse a nested requirements file + if line.opts.requirements: + req_path = line.opts.requirements[0] + nested_constraint = False + else: + req_path = line.opts.constraints[0] + nested_constraint = True + + # original file is over http + if SCHEME_RE.search(filename): + # do a url join so relative paths work + req_path = urllib.parse.urljoin(filename, req_path) + # original file and nested file are paths + elif not SCHEME_RE.search(req_path): + # do a join so relative paths work + # and then abspath so that we can identify recursive references + req_path = os.path.abspath( + os.path.join( + os.path.dirname(filename), + req_path, + ) + ) + parsed_files = parsed_files_stack[0] + if req_path in parsed_files: + initial_file = parsed_files[req_path] + tail = ( + f" and again in {initial_file}" + if initial_file is not None + else "" + ) + raise RequirementsFileParseError( + f"{req_path} recursively references itself in {filename}{tail}" + ) + # Keeping a track where was each file first included in + new_parsed_files = parsed_files.copy() + new_parsed_files[req_path] = filename + yield from self._parse_and_recurse( + req_path, nested_constraint, [new_parsed_files, *parsed_files_stack] + ) + else: + yield line + + def _parse_file( + self, filename: str, constraint: bool + ) -> Generator[ParsedLine, None, None]: + _, content = get_file_content(filename, self._session) + + lines_enum = preprocess(content) + + for line_number, line in lines_enum: + try: + args_str, opts = self._line_parser(line) + except OptionParsingError as e: + # add offending line + msg = f"Invalid requirement: {line}\n{e.msg}" + raise RequirementsFileParseError(msg) + + yield ParsedLine( + filename, + line_number, + args_str, + opts, + constraint, + ) + + +def get_line_parser(finder: Optional["PackageFinder"]) -> LineParser: + def parse_line(line: str) -> Tuple[str, Values]: + # Build new parser for each line since it accumulates appendable + # options. + parser = build_parser() + defaults = parser.get_default_values() + defaults.index_url = None + if finder: + defaults.format_control = finder.format_control + + args_str, options_str = break_args_options(line) + + try: + options = shlex.split(options_str) + except ValueError as e: + raise OptionParsingError(f"Could not split options: {options_str}") from e + + opts, _ = parser.parse_args(options, defaults) + + return args_str, opts + + return parse_line + + +def break_args_options(line: str) -> Tuple[str, str]: + """Break up the line into an args and options string. We only want to shlex + (and then optparse) the options, not the args. args can contain markers + which are corrupted by shlex. + """ + tokens = line.split(" ") + args = [] + options = tokens[:] + for token in tokens: + if token.startswith("-") or token.startswith("--"): + break + else: + args.append(token) + options.pop(0) + return " ".join(args), " ".join(options) + + +class OptionParsingError(Exception): + def __init__(self, msg: str) -> None: + self.msg = msg + + +def build_parser() -> optparse.OptionParser: + """ + Return a parser for parsing requirement lines + """ + parser = optparse.OptionParser(add_help_option=False) + + option_factories = SUPPORTED_OPTIONS + SUPPORTED_OPTIONS_REQ + for option_factory in option_factories: + option = option_factory() + parser.add_option(option) + + # By default optparse sys.exits on parsing errors. We want to wrap + # that in our own exception. + def parser_exit(self: Any, msg: str) -> "NoReturn": + raise OptionParsingError(msg) + + # NOTE: mypy disallows assigning to a method + # https://github.com/python/mypy/issues/2427 + parser.exit = parser_exit # type: ignore + + return parser + + +def join_lines(lines_enum: ReqFileLines) -> ReqFileLines: + """Joins a line ending in '\' with the previous line (except when following + comments). The joined line takes on the index of the first line. + """ + primary_line_number = None + new_line: List[str] = [] + for line_number, line in lines_enum: + if not line.endswith("\\") or COMMENT_RE.match(line): + if COMMENT_RE.match(line): + # this ensures comments are always matched later + line = " " + line + if new_line: + new_line.append(line) + assert primary_line_number is not None + yield primary_line_number, "".join(new_line) + new_line = [] + else: + yield line_number, line + else: + if not new_line: + primary_line_number = line_number + new_line.append(line.strip("\\")) + + # last line contains \ + if new_line: + assert primary_line_number is not None + yield primary_line_number, "".join(new_line) + + # TODO: handle space after '\'. + + +def ignore_comments(lines_enum: ReqFileLines) -> ReqFileLines: + """ + Strips comments and filter empty lines. + """ + for line_number, line in lines_enum: + line = COMMENT_RE.sub("", line) + line = line.strip() + if line: + yield line_number, line + + +def expand_env_variables(lines_enum: ReqFileLines) -> ReqFileLines: + """Replace all environment variables that can be retrieved via `os.getenv`. + + The only allowed format for environment variables defined in the + requirement file is `${MY_VARIABLE_1}` to ensure two things: + + 1. Strings that contain a `$` aren't accidentally (partially) expanded. + 2. Ensure consistency across platforms for requirement files. + + These points are the result of a discussion on the `github pull + request #3514 `_. + + Valid characters in variable names follow the `POSIX standard + `_ and are limited + to uppercase letter, digits and the `_` (underscore). + """ + for line_number, line in lines_enum: + for env_var, var_name in ENV_VAR_RE.findall(line): + value = os.getenv(var_name) + if not value: + continue + + line = line.replace(env_var, value) + + yield line_number, line + + +def get_file_content(url: str, session: "PipSession") -> Tuple[str, str]: + """Gets the content of a file; it may be a filename, file: URL, or + http: URL. Returns (location, content). Content is unicode. + Respects # -*- coding: declarations on the retrieved files. + + :param url: File path or url. + :param session: PipSession instance. + """ + scheme = urllib.parse.urlsplit(url).scheme + # Pip has special support for file:// URLs (LocalFSAdapter). + if scheme in ["http", "https", "file"]: + # Delay importing heavy network modules until absolutely necessary. + from pip._internal.network.utils import raise_for_status + + resp = session.get(url) + raise_for_status(resp) + return resp.url, resp.text + + # Assume this is a bare path. + try: + with open(url, "rb") as f: + content = auto_decode(f.read()) + except OSError as exc: + raise InstallationError(f"Could not open requirements file: {exc}") + return url, content diff --git a/backend/.venv/Lib/site-packages/pip/_internal/req/req_install.py b/backend/.venv/Lib/site-packages/pip/_internal/req/req_install.py new file mode 100644 index 0000000..834bc51 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/req/req_install.py @@ -0,0 +1,934 @@ +import functools +import logging +import os +import shutil +import sys +import uuid +import zipfile +from optparse import Values +from pathlib import Path +from typing import Any, Collection, Dict, Iterable, List, Optional, Sequence, Union + +from pip._vendor.packaging.markers import Marker +from pip._vendor.packaging.requirements import Requirement +from pip._vendor.packaging.specifiers import SpecifierSet +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.packaging.version import Version +from pip._vendor.packaging.version import parse as parse_version +from pip._vendor.pyproject_hooks import BuildBackendHookCaller + +from pip._internal.build_env import BuildEnvironment, NoOpBuildEnvironment +from pip._internal.exceptions import InstallationError, PreviousBuildDirError +from pip._internal.locations import get_scheme +from pip._internal.metadata import ( + BaseDistribution, + get_default_environment, + get_directory_distribution, + get_wheel_distribution, +) +from pip._internal.metadata.base import FilesystemWheel +from pip._internal.models.direct_url import DirectUrl +from pip._internal.models.link import Link +from pip._internal.operations.build.metadata import generate_metadata +from pip._internal.operations.build.metadata_editable import generate_editable_metadata +from pip._internal.operations.build.metadata_legacy import ( + generate_metadata as generate_metadata_legacy, +) +from pip._internal.operations.install.editable_legacy import ( + install_editable as install_editable_legacy, +) +from pip._internal.operations.install.wheel import install_wheel +from pip._internal.pyproject import load_pyproject_toml, make_pyproject_path +from pip._internal.req.req_uninstall import UninstallPathSet +from pip._internal.utils.deprecation import deprecated +from pip._internal.utils.hashes import Hashes +from pip._internal.utils.misc import ( + ConfiguredBuildBackendHookCaller, + ask_path_exists, + backup_dir, + display_path, + hide_url, + is_installable_dir, + redact_auth_from_requirement, + redact_auth_from_url, +) +from pip._internal.utils.packaging import get_requirement +from pip._internal.utils.subprocess import runner_with_spinner_message +from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds +from pip._internal.utils.unpacking import unpack_file +from pip._internal.utils.virtualenv import running_under_virtualenv +from pip._internal.vcs import vcs + +logger = logging.getLogger(__name__) + + +class InstallRequirement: + """ + Represents something that may be installed later on, may have information + about where to fetch the relevant requirement and also contains logic for + installing the said requirement. + """ + + def __init__( + self, + req: Optional[Requirement], + comes_from: Optional[Union[str, "InstallRequirement"]], + editable: bool = False, + link: Optional[Link] = None, + markers: Optional[Marker] = None, + use_pep517: Optional[bool] = None, + isolated: bool = False, + *, + global_options: Optional[List[str]] = None, + hash_options: Optional[Dict[str, List[str]]] = None, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, + constraint: bool = False, + extras: Collection[str] = (), + user_supplied: bool = False, + permit_editable_wheels: bool = False, + ) -> None: + assert req is None or isinstance(req, Requirement), req + self.req = req + self.comes_from = comes_from + self.constraint = constraint + self.editable = editable + self.permit_editable_wheels = permit_editable_wheels + + # source_dir is the local directory where the linked requirement is + # located, or unpacked. In case unpacking is needed, creating and + # populating source_dir is done by the RequirementPreparer. Note this + # is not necessarily the directory where pyproject.toml or setup.py is + # located - that one is obtained via unpacked_source_directory. + self.source_dir: Optional[str] = None + if self.editable: + assert link + if link.is_file: + self.source_dir = os.path.normpath(os.path.abspath(link.file_path)) + + # original_link is the direct URL that was provided by the user for the + # requirement, either directly or via a constraints file. + if link is None and req and req.url: + # PEP 508 URL requirement + link = Link(req.url) + self.link = self.original_link = link + + # When this InstallRequirement is a wheel obtained from the cache of locally + # built wheels, this is the source link corresponding to the cache entry, which + # was used to download and build the cached wheel. + self.cached_wheel_source_link: Optional[Link] = None + + # Information about the location of the artifact that was downloaded . This + # property is guaranteed to be set in resolver results. + self.download_info: Optional[DirectUrl] = None + + # Path to any downloaded or already-existing package. + self.local_file_path: Optional[str] = None + if self.link and self.link.is_file: + self.local_file_path = self.link.file_path + + if extras: + self.extras = extras + elif req: + self.extras = req.extras + else: + self.extras = set() + if markers is None and req: + markers = req.marker + self.markers = markers + + # This holds the Distribution object if this requirement is already installed. + self.satisfied_by: Optional[BaseDistribution] = None + # Whether the installation process should try to uninstall an existing + # distribution before installing this requirement. + self.should_reinstall = False + # Temporary build location + self._temp_build_dir: Optional[TempDirectory] = None + # Set to True after successful installation + self.install_succeeded: Optional[bool] = None + # Supplied options + self.global_options = global_options if global_options else [] + self.hash_options = hash_options if hash_options else {} + self.config_settings = config_settings + # Set to True after successful preparation of this requirement + self.prepared = False + # User supplied requirement are explicitly requested for installation + # by the user via CLI arguments or requirements files, as opposed to, + # e.g. dependencies, extras or constraints. + self.user_supplied = user_supplied + + self.isolated = isolated + self.build_env: BuildEnvironment = NoOpBuildEnvironment() + + # For PEP 517, the directory where we request the project metadata + # gets stored. We need this to pass to build_wheel, so the backend + # can ensure that the wheel matches the metadata (see the PEP for + # details). + self.metadata_directory: Optional[str] = None + + # The static build requirements (from pyproject.toml) + self.pyproject_requires: Optional[List[str]] = None + + # Build requirements that we will check are available + self.requirements_to_check: List[str] = [] + + # The PEP 517 backend we should use to build the project + self.pep517_backend: Optional[BuildBackendHookCaller] = None + + # Are we using PEP 517 for this requirement? + # After pyproject.toml has been loaded, the only valid values are True + # and False. Before loading, None is valid (meaning "use the default"). + # Setting an explicit value before loading pyproject.toml is supported, + # but after loading this flag should be treated as read only. + self.use_pep517 = use_pep517 + + # If config settings are provided, enforce PEP 517. + if self.config_settings: + if self.use_pep517 is False: + logger.warning( + "--no-use-pep517 ignored for %s " + "because --config-settings are specified.", + self, + ) + self.use_pep517 = True + + # This requirement needs more preparation before it can be built + self.needs_more_preparation = False + + # This requirement needs to be unpacked before it can be installed. + self._archive_source: Optional[Path] = None + + def __str__(self) -> str: + if self.req: + s = redact_auth_from_requirement(self.req) + if self.link: + s += f" from {redact_auth_from_url(self.link.url)}" + elif self.link: + s = redact_auth_from_url(self.link.url) + else: + s = "" + if self.satisfied_by is not None: + if self.satisfied_by.location is not None: + location = display_path(self.satisfied_by.location) + else: + location = "" + s += f" in {location}" + if self.comes_from: + if isinstance(self.comes_from, str): + comes_from: Optional[str] = self.comes_from + else: + comes_from = self.comes_from.from_path() + if comes_from: + s += f" (from {comes_from})" + return s + + def __repr__(self) -> str: + return ( + f"<{self.__class__.__name__} object: " + f"{str(self)} editable={self.editable!r}>" + ) + + def format_debug(self) -> str: + """An un-tested helper for getting state, for debugging.""" + attributes = vars(self) + names = sorted(attributes) + + state = (f"{attr}={attributes[attr]!r}" for attr in sorted(names)) + return "<{name} object: {{{state}}}>".format( + name=self.__class__.__name__, + state=", ".join(state), + ) + + # Things that are valid for all kinds of requirements? + @property + def name(self) -> Optional[str]: + if self.req is None: + return None + return self.req.name + + @functools.cached_property + def supports_pyproject_editable(self) -> bool: + if not self.use_pep517: + return False + assert self.pep517_backend + with self.build_env: + runner = runner_with_spinner_message( + "Checking if build backend supports build_editable" + ) + with self.pep517_backend.subprocess_runner(runner): + return "build_editable" in self.pep517_backend._supported_features() + + @property + def specifier(self) -> SpecifierSet: + assert self.req is not None + return self.req.specifier + + @property + def is_direct(self) -> bool: + """Whether this requirement was specified as a direct URL.""" + return self.original_link is not None + + @property + def is_pinned(self) -> bool: + """Return whether I am pinned to an exact version. + + For example, some-package==1.2 is pinned; some-package>1.2 is not. + """ + assert self.req is not None + specifiers = self.req.specifier + return len(specifiers) == 1 and next(iter(specifiers)).operator in {"==", "==="} + + def match_markers(self, extras_requested: Optional[Iterable[str]] = None) -> bool: + if not extras_requested: + # Provide an extra to safely evaluate the markers + # without matching any extra + extras_requested = ("",) + if self.markers is not None: + return any( + self.markers.evaluate({"extra": extra}) for extra in extras_requested + ) + else: + return True + + @property + def has_hash_options(self) -> bool: + """Return whether any known-good hashes are specified as options. + + These activate --require-hashes mode; hashes specified as part of a + URL do not. + + """ + return bool(self.hash_options) + + def hashes(self, trust_internet: bool = True) -> Hashes: + """Return a hash-comparer that considers my option- and URL-based + hashes to be known-good. + + Hashes in URLs--ones embedded in the requirements file, not ones + downloaded from an index server--are almost peers with ones from + flags. They satisfy --require-hashes (whether it was implicitly or + explicitly activated) but do not activate it. md5 and sha224 are not + allowed in flags, which should nudge people toward good algos. We + always OR all hashes together, even ones from URLs. + + :param trust_internet: Whether to trust URL-based (#md5=...) hashes + downloaded from the internet, as by populate_link() + + """ + good_hashes = self.hash_options.copy() + if trust_internet: + link = self.link + elif self.is_direct and self.user_supplied: + link = self.original_link + else: + link = None + if link and link.hash: + assert link.hash_name is not None + good_hashes.setdefault(link.hash_name, []).append(link.hash) + return Hashes(good_hashes) + + def from_path(self) -> Optional[str]: + """Format a nice indicator to show where this "comes from" """ + if self.req is None: + return None + s = str(self.req) + if self.comes_from: + comes_from: Optional[str] + if isinstance(self.comes_from, str): + comes_from = self.comes_from + else: + comes_from = self.comes_from.from_path() + if comes_from: + s += "->" + comes_from + return s + + def ensure_build_location( + self, build_dir: str, autodelete: bool, parallel_builds: bool + ) -> str: + assert build_dir is not None + if self._temp_build_dir is not None: + assert self._temp_build_dir.path + return self._temp_build_dir.path + if self.req is None: + # Some systems have /tmp as a symlink which confuses custom + # builds (such as numpy). Thus, we ensure that the real path + # is returned. + self._temp_build_dir = TempDirectory( + kind=tempdir_kinds.REQ_BUILD, globally_managed=True + ) + + return self._temp_build_dir.path + + # This is the only remaining place where we manually determine the path + # for the temporary directory. It is only needed for editables where + # it is the value of the --src option. + + # When parallel builds are enabled, add a UUID to the build directory + # name so multiple builds do not interfere with each other. + dir_name: str = canonicalize_name(self.req.name) + if parallel_builds: + dir_name = f"{dir_name}_{uuid.uuid4().hex}" + + # FIXME: Is there a better place to create the build_dir? (hg and bzr + # need this) + if not os.path.exists(build_dir): + logger.debug("Creating directory %s", build_dir) + os.makedirs(build_dir) + actual_build_dir = os.path.join(build_dir, dir_name) + # `None` indicates that we respect the globally-configured deletion + # settings, which is what we actually want when auto-deleting. + delete_arg = None if autodelete else False + return TempDirectory( + path=actual_build_dir, + delete=delete_arg, + kind=tempdir_kinds.REQ_BUILD, + globally_managed=True, + ).path + + def _set_requirement(self) -> None: + """Set requirement after generating metadata.""" + assert self.req is None + assert self.metadata is not None + assert self.source_dir is not None + + # Construct a Requirement object from the generated metadata + if isinstance(parse_version(self.metadata["Version"]), Version): + op = "==" + else: + op = "===" + + self.req = get_requirement( + "".join( + [ + self.metadata["Name"], + op, + self.metadata["Version"], + ] + ) + ) + + def warn_on_mismatching_name(self) -> None: + assert self.req is not None + metadata_name = canonicalize_name(self.metadata["Name"]) + if canonicalize_name(self.req.name) == metadata_name: + # Everything is fine. + return + + # If we're here, there's a mismatch. Log a warning about it. + logger.warning( + "Generating metadata for package %s " + "produced metadata for project name %s. Fix your " + "#egg=%s fragments.", + self.name, + metadata_name, + self.name, + ) + self.req = get_requirement(metadata_name) + + def check_if_exists(self, use_user_site: bool) -> None: + """Find an installed distribution that satisfies or conflicts + with this requirement, and set self.satisfied_by or + self.should_reinstall appropriately. + """ + if self.req is None: + return + existing_dist = get_default_environment().get_distribution(self.req.name) + if not existing_dist: + return + + version_compatible = self.req.specifier.contains( + existing_dist.version, + prereleases=True, + ) + if not version_compatible: + self.satisfied_by = None + if use_user_site: + if existing_dist.in_usersite: + self.should_reinstall = True + elif running_under_virtualenv() and existing_dist.in_site_packages: + raise InstallationError( + f"Will not install to the user site because it will " + f"lack sys.path precedence to {existing_dist.raw_name} " + f"in {existing_dist.location}" + ) + else: + self.should_reinstall = True + else: + if self.editable: + self.should_reinstall = True + # when installing editables, nothing pre-existing should ever + # satisfy + self.satisfied_by = None + else: + self.satisfied_by = existing_dist + + # Things valid for wheels + @property + def is_wheel(self) -> bool: + if not self.link: + return False + return self.link.is_wheel + + @property + def is_wheel_from_cache(self) -> bool: + # When True, it means that this InstallRequirement is a local wheel file in the + # cache of locally built wheels. + return self.cached_wheel_source_link is not None + + # Things valid for sdists + @property + def unpacked_source_directory(self) -> str: + assert self.source_dir, f"No source dir for {self}" + return os.path.join( + self.source_dir, self.link and self.link.subdirectory_fragment or "" + ) + + @property + def setup_py_path(self) -> str: + assert self.source_dir, f"No source dir for {self}" + setup_py = os.path.join(self.unpacked_source_directory, "setup.py") + + return setup_py + + @property + def setup_cfg_path(self) -> str: + assert self.source_dir, f"No source dir for {self}" + setup_cfg = os.path.join(self.unpacked_source_directory, "setup.cfg") + + return setup_cfg + + @property + def pyproject_toml_path(self) -> str: + assert self.source_dir, f"No source dir for {self}" + return make_pyproject_path(self.unpacked_source_directory) + + def load_pyproject_toml(self) -> None: + """Load the pyproject.toml file. + + After calling this routine, all of the attributes related to PEP 517 + processing for this requirement have been set. In particular, the + use_pep517 attribute can be used to determine whether we should + follow the PEP 517 or legacy (setup.py) code path. + """ + pyproject_toml_data = load_pyproject_toml( + self.use_pep517, self.pyproject_toml_path, self.setup_py_path, str(self) + ) + + if pyproject_toml_data is None: + assert not self.config_settings + self.use_pep517 = False + return + + self.use_pep517 = True + requires, backend, check, backend_path = pyproject_toml_data + self.requirements_to_check = check + self.pyproject_requires = requires + self.pep517_backend = ConfiguredBuildBackendHookCaller( + self, + self.unpacked_source_directory, + backend, + backend_path=backend_path, + ) + + def isolated_editable_sanity_check(self) -> None: + """Check that an editable requirement if valid for use with PEP 517/518. + + This verifies that an editable that has a pyproject.toml either supports PEP 660 + or as a setup.py or a setup.cfg + """ + if ( + self.editable + and self.use_pep517 + and not self.supports_pyproject_editable + and not os.path.isfile(self.setup_py_path) + and not os.path.isfile(self.setup_cfg_path) + ): + raise InstallationError( + f"Project {self} has a 'pyproject.toml' and its build " + f"backend is missing the 'build_editable' hook. Since it does not " + f"have a 'setup.py' nor a 'setup.cfg', " + f"it cannot be installed in editable mode. " + f"Consider using a build backend that supports PEP 660." + ) + + def prepare_metadata(self) -> None: + """Ensure that project metadata is available. + + Under PEP 517 and PEP 660, call the backend hook to prepare the metadata. + Under legacy processing, call setup.py egg-info. + """ + assert self.source_dir, f"No source dir for {self}" + details = self.name or f"from {self.link}" + + if self.use_pep517: + assert self.pep517_backend is not None + if ( + self.editable + and self.permit_editable_wheels + and self.supports_pyproject_editable + ): + self.metadata_directory = generate_editable_metadata( + build_env=self.build_env, + backend=self.pep517_backend, + details=details, + ) + else: + self.metadata_directory = generate_metadata( + build_env=self.build_env, + backend=self.pep517_backend, + details=details, + ) + else: + self.metadata_directory = generate_metadata_legacy( + build_env=self.build_env, + setup_py_path=self.setup_py_path, + source_dir=self.unpacked_source_directory, + isolated=self.isolated, + details=details, + ) + + # Act on the newly generated metadata, based on the name and version. + if not self.name: + self._set_requirement() + else: + self.warn_on_mismatching_name() + + self.assert_source_matches_version() + + @property + def metadata(self) -> Any: + if not hasattr(self, "_metadata"): + self._metadata = self.get_dist().metadata + + return self._metadata + + def get_dist(self) -> BaseDistribution: + if self.metadata_directory: + return get_directory_distribution(self.metadata_directory) + elif self.local_file_path and self.is_wheel: + assert self.req is not None + return get_wheel_distribution( + FilesystemWheel(self.local_file_path), + canonicalize_name(self.req.name), + ) + raise AssertionError( + f"InstallRequirement {self} has no metadata directory and no wheel: " + f"can't make a distribution." + ) + + def assert_source_matches_version(self) -> None: + assert self.source_dir, f"No source dir for {self}" + version = self.metadata["version"] + if self.req and self.req.specifier and version not in self.req.specifier: + logger.warning( + "Requested %s, but installing version %s", + self, + version, + ) + else: + logger.debug( + "Source in %s has version %s, which satisfies requirement %s", + display_path(self.source_dir), + version, + self, + ) + + # For both source distributions and editables + def ensure_has_source_dir( + self, + parent_dir: str, + autodelete: bool = False, + parallel_builds: bool = False, + ) -> None: + """Ensure that a source_dir is set. + + This will create a temporary build dir if the name of the requirement + isn't known yet. + + :param parent_dir: The ideal pip parent_dir for the source_dir. + Generally src_dir for editables and build_dir for sdists. + :return: self.source_dir + """ + if self.source_dir is None: + self.source_dir = self.ensure_build_location( + parent_dir, + autodelete=autodelete, + parallel_builds=parallel_builds, + ) + + def needs_unpacked_archive(self, archive_source: Path) -> None: + assert self._archive_source is None + self._archive_source = archive_source + + def ensure_pristine_source_checkout(self) -> None: + """Ensure the source directory has not yet been built in.""" + assert self.source_dir is not None + if self._archive_source is not None: + unpack_file(str(self._archive_source), self.source_dir) + elif is_installable_dir(self.source_dir): + # If a checkout exists, it's unwise to keep going. + # version inconsistencies are logged later, but do not fail + # the installation. + raise PreviousBuildDirError( + f"pip can't proceed with requirements '{self}' due to a " + f"pre-existing build directory ({self.source_dir}). This is likely " + "due to a previous installation that failed . pip is " + "being responsible and not assuming it can delete this. " + "Please delete it and try again." + ) + + # For editable installations + def update_editable(self) -> None: + if not self.link: + logger.debug( + "Cannot update repository at %s; repository location is unknown", + self.source_dir, + ) + return + assert self.editable + assert self.source_dir + if self.link.scheme == "file": + # Static paths don't get updated + return + vcs_backend = vcs.get_backend_for_scheme(self.link.scheme) + # Editable requirements are validated in Requirement constructors. + # So here, if it's neither a path nor a valid VCS URL, it's a bug. + assert vcs_backend, f"Unsupported VCS URL {self.link.url}" + hidden_url = hide_url(self.link.url) + vcs_backend.obtain(self.source_dir, url=hidden_url, verbosity=0) + + # Top-level Actions + def uninstall( + self, auto_confirm: bool = False, verbose: bool = False + ) -> Optional[UninstallPathSet]: + """ + Uninstall the distribution currently satisfying this requirement. + + Prompts before removing or modifying files unless + ``auto_confirm`` is True. + + Refuses to delete or modify files outside of ``sys.prefix`` - + thus uninstallation within a virtual environment can only + modify that virtual environment, even if the virtualenv is + linked to global site-packages. + + """ + assert self.req + dist = get_default_environment().get_distribution(self.req.name) + if not dist: + logger.warning("Skipping %s as it is not installed.", self.name) + return None + logger.info("Found existing installation: %s", dist) + + uninstalled_pathset = UninstallPathSet.from_dist(dist) + uninstalled_pathset.remove(auto_confirm, verbose) + return uninstalled_pathset + + def _get_archive_name(self, path: str, parentdir: str, rootdir: str) -> str: + def _clean_zip_name(name: str, prefix: str) -> str: + assert name.startswith( + prefix + os.path.sep + ), f"name {name!r} doesn't start with prefix {prefix!r}" + name = name[len(prefix) + 1 :] + name = name.replace(os.path.sep, "/") + return name + + assert self.req is not None + path = os.path.join(parentdir, path) + name = _clean_zip_name(path, rootdir) + return self.req.name + "/" + name + + def archive(self, build_dir: Optional[str]) -> None: + """Saves archive to provided build_dir. + + Used for saving downloaded VCS requirements as part of `pip download`. + """ + assert self.source_dir + if build_dir is None: + return + + create_archive = True + archive_name = "{}-{}.zip".format(self.name, self.metadata["version"]) + archive_path = os.path.join(build_dir, archive_name) + + if os.path.exists(archive_path): + response = ask_path_exists( + f"The file {display_path(archive_path)} exists. (i)gnore, (w)ipe, " + "(b)ackup, (a)bort ", + ("i", "w", "b", "a"), + ) + if response == "i": + create_archive = False + elif response == "w": + logger.warning("Deleting %s", display_path(archive_path)) + os.remove(archive_path) + elif response == "b": + dest_file = backup_dir(archive_path) + logger.warning( + "Backing up %s to %s", + display_path(archive_path), + display_path(dest_file), + ) + shutil.move(archive_path, dest_file) + elif response == "a": + sys.exit(-1) + + if not create_archive: + return + + zip_output = zipfile.ZipFile( + archive_path, + "w", + zipfile.ZIP_DEFLATED, + allowZip64=True, + ) + with zip_output: + dir = os.path.normcase(os.path.abspath(self.unpacked_source_directory)) + for dirpath, dirnames, filenames in os.walk(dir): + for dirname in dirnames: + dir_arcname = self._get_archive_name( + dirname, + parentdir=dirpath, + rootdir=dir, + ) + zipdir = zipfile.ZipInfo(dir_arcname + "/") + zipdir.external_attr = 0x1ED << 16 # 0o755 + zip_output.writestr(zipdir, "") + for filename in filenames: + file_arcname = self._get_archive_name( + filename, + parentdir=dirpath, + rootdir=dir, + ) + filename = os.path.join(dirpath, filename) + zip_output.write(filename, file_arcname) + + logger.info("Saved %s", display_path(archive_path)) + + def install( + self, + global_options: Optional[Sequence[str]] = None, + root: Optional[str] = None, + home: Optional[str] = None, + prefix: Optional[str] = None, + warn_script_location: bool = True, + use_user_site: bool = False, + pycompile: bool = True, + ) -> None: + assert self.req is not None + scheme = get_scheme( + self.req.name, + user=use_user_site, + home=home, + root=root, + isolated=self.isolated, + prefix=prefix, + ) + + if self.editable and not self.is_wheel: + deprecated( + reason=( + f"Legacy editable install of {self} (setup.py develop) " + "is deprecated." + ), + replacement=( + "to add a pyproject.toml or enable --use-pep517, " + "and use setuptools >= 64. " + "If the resulting installation is not behaving as expected, " + "try using --config-settings editable_mode=compat. " + "Please consult the setuptools documentation for more information" + ), + gone_in="25.0", + issue=11457, + ) + if self.config_settings: + logger.warning( + "--config-settings ignored for legacy editable install of %s. " + "Consider upgrading to a version of setuptools " + "that supports PEP 660 (>= 64).", + self, + ) + install_editable_legacy( + global_options=global_options if global_options is not None else [], + prefix=prefix, + home=home, + use_user_site=use_user_site, + name=self.req.name, + setup_py_path=self.setup_py_path, + isolated=self.isolated, + build_env=self.build_env, + unpacked_source_directory=self.unpacked_source_directory, + ) + self.install_succeeded = True + return + + assert self.is_wheel + assert self.local_file_path + + install_wheel( + self.req.name, + self.local_file_path, + scheme=scheme, + req_description=str(self.req), + pycompile=pycompile, + warn_script_location=warn_script_location, + direct_url=self.download_info if self.is_direct else None, + requested=self.user_supplied, + ) + self.install_succeeded = True + + +def check_invalid_constraint_type(req: InstallRequirement) -> str: + # Check for unsupported forms + problem = "" + if not req.name: + problem = "Unnamed requirements are not allowed as constraints" + elif req.editable: + problem = "Editable requirements are not allowed as constraints" + elif req.extras: + problem = "Constraints cannot have extras" + + if problem: + deprecated( + reason=( + "Constraints are only allowed to take the form of a package " + "name and a version specifier. Other forms were originally " + "permitted as an accident of the implementation, but were " + "undocumented. The new implementation of the resolver no " + "longer supports these forms." + ), + replacement="replacing the constraint with a requirement", + # No plan yet for when the new resolver becomes default + gone_in=None, + issue=8210, + ) + + return problem + + +def _has_option(options: Values, reqs: List[InstallRequirement], option: str) -> bool: + if getattr(options, option, None): + return True + for req in reqs: + if getattr(req, option, None): + return True + return False + + +def check_legacy_setup_py_options( + options: Values, + reqs: List[InstallRequirement], +) -> None: + has_build_options = _has_option(options, reqs, "build_options") + has_global_options = _has_option(options, reqs, "global_options") + if has_build_options or has_global_options: + deprecated( + reason="--build-option and --global-option are deprecated.", + issue=11859, + replacement="to use --config-settings", + gone_in="25.0", + ) + logger.warning( + "Implying --no-binary=:all: due to the presence of " + "--build-option / --global-option. " + ) + options.format_control.disallow_binaries() diff --git a/backend/.venv/Lib/site-packages/pip/_internal/req/req_set.py b/backend/.venv/Lib/site-packages/pip/_internal/req/req_set.py new file mode 100644 index 0000000..ec7a6e0 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/req/req_set.py @@ -0,0 +1,82 @@ +import logging +from collections import OrderedDict +from typing import Dict, List + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.req.req_install import InstallRequirement + +logger = logging.getLogger(__name__) + + +class RequirementSet: + def __init__(self, check_supported_wheels: bool = True) -> None: + """Create a RequirementSet.""" + + self.requirements: Dict[str, InstallRequirement] = OrderedDict() + self.check_supported_wheels = check_supported_wheels + + self.unnamed_requirements: List[InstallRequirement] = [] + + def __str__(self) -> str: + requirements = sorted( + (req for req in self.requirements.values() if not req.comes_from), + key=lambda req: canonicalize_name(req.name or ""), + ) + return " ".join(str(req.req) for req in requirements) + + def __repr__(self) -> str: + requirements = sorted( + self.requirements.values(), + key=lambda req: canonicalize_name(req.name or ""), + ) + + format_string = "<{classname} object; {count} requirement(s): {reqs}>" + return format_string.format( + classname=self.__class__.__name__, + count=len(requirements), + reqs=", ".join(str(req.req) for req in requirements), + ) + + def add_unnamed_requirement(self, install_req: InstallRequirement) -> None: + assert not install_req.name + self.unnamed_requirements.append(install_req) + + def add_named_requirement(self, install_req: InstallRequirement) -> None: + assert install_req.name + + project_name = canonicalize_name(install_req.name) + self.requirements[project_name] = install_req + + def has_requirement(self, name: str) -> bool: + project_name = canonicalize_name(name) + + return ( + project_name in self.requirements + and not self.requirements[project_name].constraint + ) + + def get_requirement(self, name: str) -> InstallRequirement: + project_name = canonicalize_name(name) + + if project_name in self.requirements: + return self.requirements[project_name] + + raise KeyError(f"No project with the name {name!r}") + + @property + def all_requirements(self) -> List[InstallRequirement]: + return self.unnamed_requirements + list(self.requirements.values()) + + @property + def requirements_to_install(self) -> List[InstallRequirement]: + """Return the list of requirements that need to be installed. + + TODO remove this property together with the legacy resolver, since the new + resolver only returns requirements that need to be installed. + """ + return [ + install_req + for install_req in self.all_requirements + if not install_req.constraint and not install_req.satisfied_by + ] diff --git a/backend/.venv/Lib/site-packages/pip/_internal/req/req_uninstall.py b/backend/.venv/Lib/site-packages/pip/_internal/req/req_uninstall.py new file mode 100644 index 0000000..26df208 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/req/req_uninstall.py @@ -0,0 +1,633 @@ +import functools +import os +import sys +import sysconfig +from importlib.util import cache_from_source +from typing import Any, Callable, Dict, Generator, Iterable, List, Optional, Set, Tuple + +from pip._internal.exceptions import LegacyDistutilsInstall, UninstallMissingRecord +from pip._internal.locations import get_bin_prefix, get_bin_user +from pip._internal.metadata import BaseDistribution +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.egg_link import egg_link_path_from_location +from pip._internal.utils.logging import getLogger, indent_log +from pip._internal.utils.misc import ask, normalize_path, renames, rmtree +from pip._internal.utils.temp_dir import AdjacentTempDirectory, TempDirectory +from pip._internal.utils.virtualenv import running_under_virtualenv + +logger = getLogger(__name__) + + +def _script_names( + bin_dir: str, script_name: str, is_gui: bool +) -> Generator[str, None, None]: + """Create the fully qualified name of the files created by + {console,gui}_scripts for the given ``dist``. + Returns the list of file names + """ + exe_name = os.path.join(bin_dir, script_name) + yield exe_name + if not WINDOWS: + return + yield f"{exe_name}.exe" + yield f"{exe_name}.exe.manifest" + if is_gui: + yield f"{exe_name}-script.pyw" + else: + yield f"{exe_name}-script.py" + + +def _unique( + fn: Callable[..., Generator[Any, None, None]] +) -> Callable[..., Generator[Any, None, None]]: + @functools.wraps(fn) + def unique(*args: Any, **kw: Any) -> Generator[Any, None, None]: + seen: Set[Any] = set() + for item in fn(*args, **kw): + if item not in seen: + seen.add(item) + yield item + + return unique + + +@_unique +def uninstallation_paths(dist: BaseDistribution) -> Generator[str, None, None]: + """ + Yield all the uninstallation paths for dist based on RECORD-without-.py[co] + + Yield paths to all the files in RECORD. For each .py file in RECORD, add + the .pyc and .pyo in the same directory. + + UninstallPathSet.add() takes care of the __pycache__ .py[co]. + + If RECORD is not found, raises an error, + with possible information from the INSTALLER file. + + https://packaging.python.org/specifications/recording-installed-packages/ + """ + location = dist.location + assert location is not None, "not installed" + + entries = dist.iter_declared_entries() + if entries is None: + raise UninstallMissingRecord(distribution=dist) + + for entry in entries: + path = os.path.join(location, entry) + yield path + if path.endswith(".py"): + dn, fn = os.path.split(path) + base = fn[:-3] + path = os.path.join(dn, base + ".pyc") + yield path + path = os.path.join(dn, base + ".pyo") + yield path + + +def compact(paths: Iterable[str]) -> Set[str]: + """Compact a path set to contain the minimal number of paths + necessary to contain all paths in the set. If /a/path/ and + /a/path/to/a/file.txt are both in the set, leave only the + shorter path.""" + + sep = os.path.sep + short_paths: Set[str] = set() + for path in sorted(paths, key=len): + should_skip = any( + path.startswith(shortpath.rstrip("*")) + and path[len(shortpath.rstrip("*").rstrip(sep))] == sep + for shortpath in short_paths + ) + if not should_skip: + short_paths.add(path) + return short_paths + + +def compress_for_rename(paths: Iterable[str]) -> Set[str]: + """Returns a set containing the paths that need to be renamed. + + This set may include directories when the original sequence of paths + included every file on disk. + """ + case_map = {os.path.normcase(p): p for p in paths} + remaining = set(case_map) + unchecked = sorted({os.path.split(p)[0] for p in case_map.values()}, key=len) + wildcards: Set[str] = set() + + def norm_join(*a: str) -> str: + return os.path.normcase(os.path.join(*a)) + + for root in unchecked: + if any(os.path.normcase(root).startswith(w) for w in wildcards): + # This directory has already been handled. + continue + + all_files: Set[str] = set() + all_subdirs: Set[str] = set() + for dirname, subdirs, files in os.walk(root): + all_subdirs.update(norm_join(root, dirname, d) for d in subdirs) + all_files.update(norm_join(root, dirname, f) for f in files) + # If all the files we found are in our remaining set of files to + # remove, then remove them from the latter set and add a wildcard + # for the directory. + if not (all_files - remaining): + remaining.difference_update(all_files) + wildcards.add(root + os.sep) + + return set(map(case_map.__getitem__, remaining)) | wildcards + + +def compress_for_output_listing(paths: Iterable[str]) -> Tuple[Set[str], Set[str]]: + """Returns a tuple of 2 sets of which paths to display to user + + The first set contains paths that would be deleted. Files of a package + are not added and the top-level directory of the package has a '*' added + at the end - to signify that all it's contents are removed. + + The second set contains files that would have been skipped in the above + folders. + """ + + will_remove = set(paths) + will_skip = set() + + # Determine folders and files + folders = set() + files = set() + for path in will_remove: + if path.endswith(".pyc"): + continue + if path.endswith("__init__.py") or ".dist-info" in path: + folders.add(os.path.dirname(path)) + files.add(path) + + _normcased_files = set(map(os.path.normcase, files)) + + folders = compact(folders) + + # This walks the tree using os.walk to not miss extra folders + # that might get added. + for folder in folders: + for dirpath, _, dirfiles in os.walk(folder): + for fname in dirfiles: + if fname.endswith(".pyc"): + continue + + file_ = os.path.join(dirpath, fname) + if ( + os.path.isfile(file_) + and os.path.normcase(file_) not in _normcased_files + ): + # We are skipping this file. Add it to the set. + will_skip.add(file_) + + will_remove = files | {os.path.join(folder, "*") for folder in folders} + + return will_remove, will_skip + + +class StashedUninstallPathSet: + """A set of file rename operations to stash files while + tentatively uninstalling them.""" + + def __init__(self) -> None: + # Mapping from source file root to [Adjacent]TempDirectory + # for files under that directory. + self._save_dirs: Dict[str, TempDirectory] = {} + # (old path, new path) tuples for each move that may need + # to be undone. + self._moves: List[Tuple[str, str]] = [] + + def _get_directory_stash(self, path: str) -> str: + """Stashes a directory. + + Directories are stashed adjacent to their original location if + possible, or else moved/copied into the user's temp dir.""" + + try: + save_dir: TempDirectory = AdjacentTempDirectory(path) + except OSError: + save_dir = TempDirectory(kind="uninstall") + self._save_dirs[os.path.normcase(path)] = save_dir + + return save_dir.path + + def _get_file_stash(self, path: str) -> str: + """Stashes a file. + + If no root has been provided, one will be created for the directory + in the user's temp directory.""" + path = os.path.normcase(path) + head, old_head = os.path.dirname(path), None + save_dir = None + + while head != old_head: + try: + save_dir = self._save_dirs[head] + break + except KeyError: + pass + head, old_head = os.path.dirname(head), head + else: + # Did not find any suitable root + head = os.path.dirname(path) + save_dir = TempDirectory(kind="uninstall") + self._save_dirs[head] = save_dir + + relpath = os.path.relpath(path, head) + if relpath and relpath != os.path.curdir: + return os.path.join(save_dir.path, relpath) + return save_dir.path + + def stash(self, path: str) -> str: + """Stashes the directory or file and returns its new location. + Handle symlinks as files to avoid modifying the symlink targets. + """ + path_is_dir = os.path.isdir(path) and not os.path.islink(path) + if path_is_dir: + new_path = self._get_directory_stash(path) + else: + new_path = self._get_file_stash(path) + + self._moves.append((path, new_path)) + if path_is_dir and os.path.isdir(new_path): + # If we're moving a directory, we need to + # remove the destination first or else it will be + # moved to inside the existing directory. + # We just created new_path ourselves, so it will + # be removable. + os.rmdir(new_path) + renames(path, new_path) + return new_path + + def commit(self) -> None: + """Commits the uninstall by removing stashed files.""" + for save_dir in self._save_dirs.values(): + save_dir.cleanup() + self._moves = [] + self._save_dirs = {} + + def rollback(self) -> None: + """Undoes the uninstall by moving stashed files back.""" + for p in self._moves: + logger.info("Moving to %s\n from %s", *p) + + for new_path, path in self._moves: + try: + logger.debug("Replacing %s from %s", new_path, path) + if os.path.isfile(new_path) or os.path.islink(new_path): + os.unlink(new_path) + elif os.path.isdir(new_path): + rmtree(new_path) + renames(path, new_path) + except OSError as ex: + logger.error("Failed to restore %s", new_path) + logger.debug("Exception: %s", ex) + + self.commit() + + @property + def can_rollback(self) -> bool: + return bool(self._moves) + + +class UninstallPathSet: + """A set of file paths to be removed in the uninstallation of a + requirement.""" + + def __init__(self, dist: BaseDistribution) -> None: + self._paths: Set[str] = set() + self._refuse: Set[str] = set() + self._pth: Dict[str, UninstallPthEntries] = {} + self._dist = dist + self._moved_paths = StashedUninstallPathSet() + # Create local cache of normalize_path results. Creating an UninstallPathSet + # can result in hundreds/thousands of redundant calls to normalize_path with + # the same args, which hurts performance. + self._normalize_path_cached = functools.lru_cache(normalize_path) + + def _permitted(self, path: str) -> bool: + """ + Return True if the given path is one we are permitted to + remove/modify, False otherwise. + + """ + # aka is_local, but caching normalized sys.prefix + if not running_under_virtualenv(): + return True + return path.startswith(self._normalize_path_cached(sys.prefix)) + + def add(self, path: str) -> None: + head, tail = os.path.split(path) + + # we normalize the head to resolve parent directory symlinks, but not + # the tail, since we only want to uninstall symlinks, not their targets + path = os.path.join(self._normalize_path_cached(head), os.path.normcase(tail)) + + if not os.path.exists(path): + return + if self._permitted(path): + self._paths.add(path) + else: + self._refuse.add(path) + + # __pycache__ files can show up after 'installed-files.txt' is created, + # due to imports + if os.path.splitext(path)[1] == ".py": + self.add(cache_from_source(path)) + + def add_pth(self, pth_file: str, entry: str) -> None: + pth_file = self._normalize_path_cached(pth_file) + if self._permitted(pth_file): + if pth_file not in self._pth: + self._pth[pth_file] = UninstallPthEntries(pth_file) + self._pth[pth_file].add(entry) + else: + self._refuse.add(pth_file) + + def remove(self, auto_confirm: bool = False, verbose: bool = False) -> None: + """Remove paths in ``self._paths`` with confirmation (unless + ``auto_confirm`` is True).""" + + if not self._paths: + logger.info( + "Can't uninstall '%s'. No files were found to uninstall.", + self._dist.raw_name, + ) + return + + dist_name_version = f"{self._dist.raw_name}-{self._dist.raw_version}" + logger.info("Uninstalling %s:", dist_name_version) + + with indent_log(): + if auto_confirm or self._allowed_to_proceed(verbose): + moved = self._moved_paths + + for_rename = compress_for_rename(self._paths) + + for path in sorted(compact(for_rename)): + moved.stash(path) + logger.verbose("Removing file or directory %s", path) + + for pth in self._pth.values(): + pth.remove() + + logger.info("Successfully uninstalled %s", dist_name_version) + + def _allowed_to_proceed(self, verbose: bool) -> bool: + """Display which files would be deleted and prompt for confirmation""" + + def _display(msg: str, paths: Iterable[str]) -> None: + if not paths: + return + + logger.info(msg) + with indent_log(): + for path in sorted(compact(paths)): + logger.info(path) + + if not verbose: + will_remove, will_skip = compress_for_output_listing(self._paths) + else: + # In verbose mode, display all the files that are going to be + # deleted. + will_remove = set(self._paths) + will_skip = set() + + _display("Would remove:", will_remove) + _display("Would not remove (might be manually added):", will_skip) + _display("Would not remove (outside of prefix):", self._refuse) + if verbose: + _display("Will actually move:", compress_for_rename(self._paths)) + + return ask("Proceed (Y/n)? ", ("y", "n", "")) != "n" + + def rollback(self) -> None: + """Rollback the changes previously made by remove().""" + if not self._moved_paths.can_rollback: + logger.error( + "Can't roll back %s; was not uninstalled", + self._dist.raw_name, + ) + return + logger.info("Rolling back uninstall of %s", self._dist.raw_name) + self._moved_paths.rollback() + for pth in self._pth.values(): + pth.rollback() + + def commit(self) -> None: + """Remove temporary save dir: rollback will no longer be possible.""" + self._moved_paths.commit() + + @classmethod + def from_dist(cls, dist: BaseDistribution) -> "UninstallPathSet": + dist_location = dist.location + info_location = dist.info_location + if dist_location is None: + logger.info( + "Not uninstalling %s since it is not installed", + dist.canonical_name, + ) + return cls(dist) + + normalized_dist_location = normalize_path(dist_location) + if not dist.local: + logger.info( + "Not uninstalling %s at %s, outside environment %s", + dist.canonical_name, + normalized_dist_location, + sys.prefix, + ) + return cls(dist) + + if normalized_dist_location in { + p + for p in {sysconfig.get_path("stdlib"), sysconfig.get_path("platstdlib")} + if p + }: + logger.info( + "Not uninstalling %s at %s, as it is in the standard library.", + dist.canonical_name, + normalized_dist_location, + ) + return cls(dist) + + paths_to_remove = cls(dist) + develop_egg_link = egg_link_path_from_location(dist.raw_name) + + # Distribution is installed with metadata in a "flat" .egg-info + # directory. This means it is not a modern .dist-info installation, an + # egg, or legacy editable. + setuptools_flat_installation = ( + dist.installed_with_setuptools_egg_info + and info_location is not None + and os.path.exists(info_location) + # If dist is editable and the location points to a ``.egg-info``, + # we are in fact in the legacy editable case. + and not info_location.endswith(f"{dist.setuptools_filename}.egg-info") + ) + + # Uninstall cases order do matter as in the case of 2 installs of the + # same package, pip needs to uninstall the currently detected version + if setuptools_flat_installation: + if info_location is not None: + paths_to_remove.add(info_location) + installed_files = dist.iter_declared_entries() + if installed_files is not None: + for installed_file in installed_files: + paths_to_remove.add(os.path.join(dist_location, installed_file)) + # FIXME: need a test for this elif block + # occurs with --single-version-externally-managed/--record outside + # of pip + elif dist.is_file("top_level.txt"): + try: + namespace_packages = dist.read_text("namespace_packages.txt") + except FileNotFoundError: + namespaces = [] + else: + namespaces = namespace_packages.splitlines(keepends=False) + for top_level_pkg in [ + p + for p in dist.read_text("top_level.txt").splitlines() + if p and p not in namespaces + ]: + path = os.path.join(dist_location, top_level_pkg) + paths_to_remove.add(path) + paths_to_remove.add(f"{path}.py") + paths_to_remove.add(f"{path}.pyc") + paths_to_remove.add(f"{path}.pyo") + + elif dist.installed_by_distutils: + raise LegacyDistutilsInstall(distribution=dist) + + elif dist.installed_as_egg: + # package installed by easy_install + # We cannot match on dist.egg_name because it can slightly vary + # i.e. setuptools-0.6c11-py2.6.egg vs setuptools-0.6rc11-py2.6.egg + paths_to_remove.add(dist_location) + easy_install_egg = os.path.split(dist_location)[1] + easy_install_pth = os.path.join( + os.path.dirname(dist_location), + "easy-install.pth", + ) + paths_to_remove.add_pth(easy_install_pth, "./" + easy_install_egg) + + elif dist.installed_with_dist_info: + for path in uninstallation_paths(dist): + paths_to_remove.add(path) + + elif develop_egg_link: + # PEP 660 modern editable is handled in the ``.dist-info`` case + # above, so this only covers the setuptools-style editable. + with open(develop_egg_link) as fh: + link_pointer = os.path.normcase(fh.readline().strip()) + normalized_link_pointer = paths_to_remove._normalize_path_cached( + link_pointer + ) + assert os.path.samefile( + normalized_link_pointer, normalized_dist_location + ), ( + f"Egg-link {develop_egg_link} (to {link_pointer}) does not match " + f"installed location of {dist.raw_name} (at {dist_location})" + ) + paths_to_remove.add(develop_egg_link) + easy_install_pth = os.path.join( + os.path.dirname(develop_egg_link), "easy-install.pth" + ) + paths_to_remove.add_pth(easy_install_pth, dist_location) + + else: + logger.debug( + "Not sure how to uninstall: %s - Check: %s", + dist, + dist_location, + ) + + if dist.in_usersite: + bin_dir = get_bin_user() + else: + bin_dir = get_bin_prefix() + + # find distutils scripts= scripts + try: + for script in dist.iter_distutils_script_names(): + paths_to_remove.add(os.path.join(bin_dir, script)) + if WINDOWS: + paths_to_remove.add(os.path.join(bin_dir, f"{script}.bat")) + except (FileNotFoundError, NotADirectoryError): + pass + + # find console_scripts and gui_scripts + def iter_scripts_to_remove( + dist: BaseDistribution, + bin_dir: str, + ) -> Generator[str, None, None]: + for entry_point in dist.iter_entry_points(): + if entry_point.group == "console_scripts": + yield from _script_names(bin_dir, entry_point.name, False) + elif entry_point.group == "gui_scripts": + yield from _script_names(bin_dir, entry_point.name, True) + + for s in iter_scripts_to_remove(dist, bin_dir): + paths_to_remove.add(s) + + return paths_to_remove + + +class UninstallPthEntries: + def __init__(self, pth_file: str) -> None: + self.file = pth_file + self.entries: Set[str] = set() + self._saved_lines: Optional[List[bytes]] = None + + def add(self, entry: str) -> None: + entry = os.path.normcase(entry) + # On Windows, os.path.normcase converts the entry to use + # backslashes. This is correct for entries that describe absolute + # paths outside of site-packages, but all the others use forward + # slashes. + # os.path.splitdrive is used instead of os.path.isabs because isabs + # treats non-absolute paths with drive letter markings like c:foo\bar + # as absolute paths. It also does not recognize UNC paths if they don't + # have more than "\\sever\share". Valid examples: "\\server\share\" or + # "\\server\share\folder". + if WINDOWS and not os.path.splitdrive(entry)[0]: + entry = entry.replace("\\", "/") + self.entries.add(entry) + + def remove(self) -> None: + logger.verbose("Removing pth entries from %s:", self.file) + + # If the file doesn't exist, log a warning and return + if not os.path.isfile(self.file): + logger.warning("Cannot remove entries from nonexistent file %s", self.file) + return + with open(self.file, "rb") as fh: + # windows uses '\r\n' with py3k, but uses '\n' with py2.x + lines = fh.readlines() + self._saved_lines = lines + if any(b"\r\n" in line for line in lines): + endline = "\r\n" + else: + endline = "\n" + # handle missing trailing newline + if lines and not lines[-1].endswith(endline.encode("utf-8")): + lines[-1] = lines[-1] + endline.encode("utf-8") + for entry in self.entries: + try: + logger.verbose("Removing entry: %s", entry) + lines.remove((entry + endline).encode("utf-8")) + except ValueError: + pass + with open(self.file, "wb") as fh: + fh.writelines(lines) + + def rollback(self) -> bool: + if self._saved_lines is None: + logger.error("Cannot roll back changes to %s, none were made", self.file) + return False + logger.debug("Rolling %s back to previous state", self.file) + with open(self.file, "wb") as fh: + fh.writelines(self._saved_lines) + return True diff --git a/backend/.venv/Lib/site-packages/pip/_internal/resolution/__init__.py b/backend/.venv/Lib/site-packages/pip/_internal/resolution/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a22f67327f1e11795b1bf85d9e3eaf65f7201250 GIT binary patch literal 199 zcmZ8aK?=e!5KOFs2z`i$ws%o4Ueym62x+>OwKWMzTIoxCgKzN%UVVY|=E>yh!0gTr zGwd@>7bM_t+F;!8IQ}tCgL5YXS<>T!*h#p?nE9S}D|XYiaYjgB>f&7{q|}}AsOn5= z3#=5f0adZQ2i3DZmdv4tEEF11gJT9w!BKgzO0Rs|0(dd_n*yyokxuDTYs Rb{5{!Ko`X)p_JMrs2`+}Hzfc7 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/resolution/__pycache__/base.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/resolution/__pycache__/base.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dd099ce3382c2969f910f63665e9e7eae79586d9 GIT binary patch literal 1187 zcma)5O=}cE5bd6?on4cNCMHIRtj4HINTT2=i6V-Ks8RGbE)26Xl{jX;w!3#Foiare>X_@=?wM{*8^ zH3a=8f*lsIh$k%N9#0L=NKMb=#2JZ|+MZovGjY<2SK$mexL|@kjVCt@u-6SjUe#bX zS!8Xq$bN-?qv6%IoJQp{!G@{b>p_wPtpv1nCzeXP_X-u~S&%fiK6)#Y3YQ;1yAumY zAydeX{pLOd6;hys;S5246~PVz=JAMmM#NE?MS>!f7Mb9zJ1ENXDv=Ei`oq+EP!3k0IRjWv3`|p&;^~J_bmnb_A%7$U^f#4bGG^ z`Ta>WJ4|t$%JFJAzu>!kZI|ouwOrjwi=@mFq8mcw0?T7bNY({)OdLWZDOSB+|Ixa> z+ey9@q>vKsJlG zSn}gcfxv1n2}-m>rC(}c-iyVSu9RFCo=yB-iNzs1f=c?MXr8lg4m*7M&Dd^#3kX%0(5r}8Ae`x&o zrZVCLg*}F5tx?sk?`J^@zOQS(pXN~~Aw1&y?M{#kRs=l?K^IF~tvpXeh5T_c$Ir-#Z~EfCN#5;y<@}*K)wj{#uMs&lHzY@UWA(l2 zsc*DYDlJ2jO8)Jb7xy{gzsd$5CxT}MjT@ka$(cPBIX!cFc`Fl3M$L2q=)pzXDhncyzw)^sY jZ+vdAcD84o>orz-*2)*tIBE3QiSM;4Kl7ELDP#Wx53MvY literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/resolution/base.py b/backend/.venv/Lib/site-packages/pip/_internal/resolution/base.py new file mode 100644 index 0000000..42dade1 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/resolution/base.py @@ -0,0 +1,20 @@ +from typing import Callable, List, Optional + +from pip._internal.req.req_install import InstallRequirement +from pip._internal.req.req_set import RequirementSet + +InstallRequirementProvider = Callable[ + [str, Optional[InstallRequirement]], InstallRequirement +] + + +class BaseResolver: + def resolve( + self, root_reqs: List[InstallRequirement], check_supported_wheels: bool + ) -> RequirementSet: + raise NotImplementedError() + + def get_installation_order( + self, req_set: RequirementSet + ) -> List[InstallRequirement]: + raise NotImplementedError() diff --git a/backend/.venv/Lib/site-packages/pip/_internal/resolution/legacy/__init__.py b/backend/.venv/Lib/site-packages/pip/_internal/resolution/legacy/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..08c1efa092d774ecd0f71181cb4ec18e525119c7 GIT binary patch literal 206 zcmZ8aK?=e!5KOFs2z`i$Hg{1kUeym62x+>M*fa@ATIoxCgKzN%UVVY|=E>yh!0gWM z%(BlsU!jQ8WhYaAr}B?!9yfP1qBTB0kekJ6N||qW*wCACt+!kN)z{z)E`;fIkh&>^ zaX>3BTF^Bu2hamO%8Gg!poj-8Z@^P4En!jzaGERPz#G*EX*5yLa4`}VO&J&~?f6=5 WJ5%=x_HGfs<4B*xC&L)KEUF)3_Bqf1 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2a758ac0df54d859cf1447505c08cb627ac405d1 GIT binary patch literal 22581 zcmb7sd2k%pnP1O^xiJF_jsXTo10aqe4w3-Dn-uTEq$oh z<@dclW&pM9O_O;2`kmjqzWdFugFzpM=gDUer<{MrasQh>jK`}-Hhy8_xI3J{jd6la zu%~TfHukoU+3|Ly9U14C(?)sDv@26JR>k73v^(P&^JKhZ-i&X|m+_DJGl8){CO8&k z`BmxaOlT~`;_h@fQ!`e>;+}MECNdUbac{aVQ$JRpX&7tBG>$c9qGQoa(^ylcd8|1T z8;h|rzI02bb*z=e{pq$$`&c`R2hx0|W2}S4gXzvp*H{;eSEsjSy2rX%Je2Oq^p5pr z`o{X$cQ_r-Y#-as;x+01%)r<{W^infeb=UkGCRh0uy`cBGqY=K7mL@WhchE%BP?E@ z-klj88)fl^^q$P#vArzbnBJG!Kepe-**VcRl`|%|{1y+sjX9=g?2zaY{o>&!#6_Rj zOYaFgg=0s&oX{>r#de`d42nife9j){lXK|iq&Oo^3*z+n9RG|cXVbH}RCe0uyK+tBg>sf;X7QFiDUfX|0CK9`*tOp7T{5@!9G090HM- zXT)(nNj1?5+T&-W?36g38$i9uq$H$8S?047{CIYHBApt~;X~r5v$-MG5*o|qu8Gpk zlq~W|zEjA~UQLUYU3T)~t#NUN#zYWHNt6^=-K#@9ssf4|q9mmRfHHe^aMOs(a1XID zZ7PrwWn(a%6Ddi~VFG5Sg#rF%YFh5(`)&d(k$M2Y0>*{TuS#N4$X(-E@wo5rX(2Ag zZK_`oCz7-2oPhD+(=~oAnVODQss58%`bng#o^v@-N@8@X^Fm6-_fu?8$+YUYEap_# zmD!oJh}u4y(bPmrlw@l9neyyY=9jODV){gK{F)edtFhyvocj_AVseh93Anj)({c{0 zAqr~UN%SJ6uCncLF`GM0qf@C?O$yJSmHnFdz*hpT3T_iwy&j zNX76jN#aaWLS4IBtAkUKtF~gyfQ5er9W~Fpu zLds?mX>CM48a7}_XD3mrVH&3jV9tvP^i0bGxF@p6sna8q_FviW&i&tG()tU(#L z1;>Kz9sApQ`9;@)OR~*@4ouZ=u1#OLMkB3^02gdVU9)}nf?ev$RU2ie2*GW61Q%ee z-I9pU1^0sEZKsxQ7?_G1rvy zjF{lC9>GGDf#Gf3S3!dpt6r+Y3b1z>g19&NODv#|knssR7Cf*O;ZcUKCQ~=WX^ zyuPIfeHl9(2=-w|EB2Nux=o#nM6tgp|E!0eWdgilTUv00k#%~ed4F>FS5Wd8H;9|L9jPc&rd9ppHZNZi&AJikt+=)6g9#J0oVssvO|EWz{w`fBYQb2%6=IWC~b+YdLK) zLD@i;HT;aWsWOpZVg$OSd5_WSe49ad(KYtQ!~`hdbWYz%2l#o9Q7c}pI#D)* zNBKGMP&;q}K-H&{=^bVMYDXH3&-k2{g3gC#=G0h1!~1mLwjy-t007&IKe>e9Wvk2)J4i*EkVpI2Hm!rwI6#TG`^VAnT)$7$YZ(Lix z_D%UONA3ky8wXdbhh9GOTX*XtPxTvtR&BOWHu6)5oZH* z)$RA3|7!ex#}6k~s|WL*!9Sp^Yv>P;tGPf!!QZ3!dp_cv02lyNFIN`>2OnPf>GMB% z{#Pd+JM3QH<0|z1hmsd1K9z?s=&#ow_i=ZF$9Hn?`Mk#m9q&czkM}v=>vK_jXXM0? zDdu>a6D<^-qREjUG&;1a8Z zD$y-^7@zGHy@E&d310m9@aM;00DnQzFI1ycKnw~Yjaz5s!-8WXy2MS`gql}^W7R^f z7!t!QCxTjGv1X!5sC&gZR_o=^V~-WHwCtO33Nf@?uYCg!Cu9TXScA~Y^7ZzS+J@9dy_Q>yQZGntM`}|=T^`@f zdZ`%lJMi7Y;MLmGVZwMik<%)4VI*M#Qk36@)V3w=mTj#4G8gYvJqDLG|7|@cgCwQK zuNi0u2uB2Z0(!qH0`KTd>W*0)cs)*ex;(;;C~@9|Uclm_VisA9Ic20PJDX$7_;rK6 z=y-_9C`5&l({o188jd|e+>z=M!J$f@R+IEHn3@@a)W_loZ4SF}OK#a!w7+%xz*Mhon9XXS|a4pz+b)#%Y{`Z`tl} zWv*;Fu)ux8#c^*Vn;sjt-~;zz@+D(Zzin`p{ssR6moQscu;HuBZ`tu>wh5k-OO!cKK$bAMs|7E<%I$;eOPFH@ zcgQ7zX5SusnOx=qILbuG%yZ%^Y<%Uq%otH6_84%Z9FZ&b%yDu1#lNR1jn}Cz$N(Tw zo&**>l}jYlNJ5u+jYXmbcF1$GMwO@!H4N^4)3QlNkt`jf;5Y?mDL6yHDGE+g!06dY z#MGL^)?FqMG^#UAvO+WgS~5I%P3Ev9+@k)H*f1wKE0)1LYhw?@c7e z(@9xQBxIUhb{6&EWobXve-gobjd9|Kj5(nVC%=W@lb5;2Eu6P{*{yh@Yo6v}sQupV zLf1hB|3e4!o`d<&!F7Lg-rxDCt)tL3q_hp)mmb*iZNtk?{jP2IgT!jvsimjZ`5jBn zHBak$lwWeb9xOJr;N>sIdMGuz&hKQo#r7e3w-mef(3>wB={<+&yQ|o`o!-sGj$QO_ z``yv=|MleR(WjT3?|Zs804xS9WwVSZ%W8v0rA>h^!4AE=Nz|fkOzW^gA{LIBzU3jV z*x#`k8)*@O)Jg97evVsoE;y|OFv*|8k<^|AQ|Q3aHEe{Tf(-25(-0Oo*ZjxJc zl?6BBXhZBM9~Xy}aI)Ys+5vnx0E-}w3$7{iu#`InBo=~8B_zgZ0a1^WTd0!k3spcK zj>{ZGBvYV+IMli5UT`kBD-L$mlqo(|^yn_P2;s-R=zhul`ep51A^bR!e}zfc_aDei zGFK)Ko9K)H4TdJS&;~w6T&)aoe^3NxJB~^u2tY2%K#Ish@k12H;O_XoGDS~-od0TKe3 zzdFai@B*02A(Q6GLwb8Jyr2st1jJL*<05$TOXrxZ08*4ojhA7aqhT@K4WGOL*?=@p z1AHpS-^|XY1yJEK3|U!Dk=6|aI0J;D%>$!<8eoiQgRLeF9f}oUdT5FUA8>3*M@)tiq8O2n^i);Fazq^JB#l$C#i04TAUi^cOtzqHo; z<)zTyL|T?k6hpOdy!6^jkHUlZ$JfHc;L!_#J|)n1zx`p?`+*}RH&@qMs^v!aE`=U7 z@c$yc2-fb^5?N^%iKYZdhk@HI@N_JkEH zz8`+7^rgw;kVf7sIhaxKjyt-Ww@| zdzEnSA4)Fdekw-+{m;5OjtA`T1-!@iy56gg9v^nSH|#=ON+MJBS298&Vw0@p9uP-a};~{0y6}AoUJ#=#+_1k)uCl{3!3pnaZrG%69aUf(w zaI+N?Q&zQ10^3a3FH<>_`6$KRKu1`d`fZPa^m^7JWwm?J;>3r8VzMFV1fF~@jbgy9{AioMdx+PBY77bUvqzf z6PyN2tfa-<%MF0FeM@zGE|`6Q>e(k@ilP+&HL^{0Se3R~R|87W7l&Ys9?m^h^ZdlD_%@(4i)Rn~A2j>bdlgk8W^6Fgq0mdaG>WF`j3_Eqk-?e$+8s`7Ys zvIkX<34$T?6CEIHW75zy68$CCLnk5?434h--9k_ffP)fwQV(hjoTeqv4V2(rzzu3* zJ>nId7Ex@l7otEMm|h~G&%ltEB4zgMG<70W!dYhAs5za+6Y#`3 z$^;TsfeBHB4w=}jvT+kU2tPZcDc;MBl8@Rk9x^4#+6ZQ#_XLAFn`GB3|+2>&g*wha#A@-(W z>ZY=!BM18kv$e)OLyP`w1+PO*dV(SD^qt|cJ?B=y}j-+b~j7I~i8mtYPELP*m087v9&?g6&@539ELeAfxK z{b>Sq#Tq#P=muMIHIVq;`4hbdj8m@(8YE4iW0$5#?WDO{mR4zf&?rHbN{y>A>`}6=Gj9z&(Kr-pOvs9I0&9}cm$kwUFB9c8 za2c>8(-l37w0YhXi#|uf`zcDvAqTU53~-P{LVZf8FCX8(7CP`KQ2WOD<@3exStg?J zN|L9B3;g~Se*dGorn~)x z=Iu)J_CoWB(mb+Sw|nW-qeyolGNMFARwJWJCySxBLTGd)H2P5dY4#`CUkPhRE(SYFY~6_)0i_Kan3iS%Ph2|GIzQh70dv z;3NQ}p|r1r+F^Am1V)s=$b<81fuqH`_S=W=ZOcb`@`0X`)8*yYNrKy-a)lzf#wq5BGoMqLfkhQKXS7?56h#;`^d`@e1QE<=*`eae)fr>pf2SX!rPVb_WRd=lzl5( z7&@cifA~x(#Cf-USjz=^AJujhYX|N>d;iH2XFJedZ12B2egDjZ^M&0fmE9-vBWK=y z5w@V3FW6u>id4gJ6s(5y8E#=SuuBQ-deFZXII_-Wpg$iO%m)Tb9=2*7EB=oAErs~e zmH5$Or2h6oKGKD8ulMXK^z2c3_CQ+g^%VorLZDR%w5|l6zSm#q99BAq3!QtF&b<#0 z6%Jld4qhl6d|JW(&Zn^)hkSWY*N0UG*rN}w7xtW1_MFa-p1}&9we{0F_HQ_x1SxH$ zYObqqDX`{g$7Iq@+P31~R*VlWU04hBJZkI0Ui{|B?S(?)cBOIqYNY?2@dy2d;gibn z$JyN{ZPF)Np5f9nC*4Dxm*(2h+D^IJ70eCegT3;9rg-qZid;}>mQ zI11yMmoLWJ|LFy?z44#Qgk65&h@Efbe%Y^B7hjp zP2s)u5p2Zt!lMKFcguW-o)3MwWxk8@bqj&bN~w9vCI`SG+N^8~uoG2Xl%4=kr=`OP zuSiD_#vPg#TtZwT9Qc-9!&(W%Wg3=_NuY5DayBd@y7GO#rHolVn>!4VSAGgjyv!B- zp@N@R{Cs}f=!$=|7>O2xHHBcO670M;xe^>KMjF>6jfF^`66wni99oGS$_EbRBZrES zhC*bU64|yA*>m6Vqw2S+^MO6mm(Zs5^uLT8Oux-)`d-#dE0*p!63NJ@yY;b}NXaeO z7iXR=tgdP4vMM9jpcT{lRW2de^%L!wb7DLe${x853KvW7D=VL`1)Jb{r^+xOV6^`T z*dZpGiYk}_9OTzD=gtv>#U3N=^yWY1U>%LxI$uv5vc4ZkTTe=Q@IXu!fV8IVY6xh|@M@kOu%YG#hVC3Df+RCJLpTEu zs`-nM^D9XKC<%YrB*ZonqF|9AaRj1@+1RlONIzg{(_l5pD+&N@85skddDb!}yz(fL z$cLkAHl_)2nkUniR?x0?#`Vz%@I*03&WpM6A^zC(oY@i+Q8gzoZRSX3WS(IF4~{T` zVPhYkg|J7m`ZY=^w@5;z*_r_}NtT=BsfvlXXo{jF2izEk6fUJnqGSdaKApM_Q5-CP zlEe{MBFTf8Ew$D!n>w>Y2|{uT0_`AGkx8tb;~_J{k7r^IB_Z@7-S9n_nbp@y8v~hd z2F#WK@H7u8i53sSEt3|h0wfM9$l$}mOIhN}$@oEgK!Z-7=^bWU=8Qum!GxDL!2wfX z<#S;6F~vz4z0pM6yavbtE<{9qV-JuVL@Ql^q#4zm?=l20W4^Ja%_-8MnXmawp)2q} zbsO2WM)vH?ARHjz<}1d7%m}T9G&^W&BEduhS+g7e1BP^k_<5q^ zo`!;_NAWOY2r=(76)oEZM!m`eL~5j{i-6Av~aj2k!sbyI1nz zfwk}#N_Ct!SnzZzp3Zwm);z;#>yyXzT-^?`xD5Qy#{NfpuivUJpm8V7+E& zdC$>$e3*N0*n7g`c<-z+tn4Rn)F`|E zIu;xtTyP4u(jhauwiQ7eguUBmf?-C$8rtdd#G(t_i-T+o3$E{S-*duZZMt+=TA@wL z1;~vPOr-PTeBjVD>9Cj{;>i5TE5I~B7D9@)Fc4*0JDzl=3b`+cW;FYrDIdkFK$w$ynFBm*hitFY4wwEJ1+?K+FE~!E88xWAvGM6NGc|*>6J_G= zGBYc^PL-;!!UhH}A{|<-C3tjGJvchblQLQVbtzi2E;b~#9xCQ^KHpwus4NRC&

H z!T#1Z6l%9CwcGEHtk&*Wau=IgzaRTftk5*7G>twOf4FzG>BLg?Z$qs(1(1B$7FR-@ zOHT03Zyb5;NU^@DP~WT6_pa3Mzkg)ubjfF{=_+>Z%6AS!3LF_I4h-Ml2YX@7Xvxb3 z!;iyUF!IL5<%@Sm)&lJ~R!jcR^32305rehyb?nX0<(V6>cd68tr@Xr>d0&)uZYhY* zuTdKoOqnG+rZIk>ZG?N7Y+d#WTbE^D)~uWrXAgGF-1p_~%CG2Ft`%r0|8?JFy|F%7WNHI8%-t?;_@^_GxLlbz}T2A#e|(DGhSOvW6F~0o5?xc zq?%2ob9_2W-0<9hrgJVkoa^0Tdf8CSwn!aIPBMnm4Rb$XAdrvdEuel02wi6+XNd)s zvNz!wp9Y}RrrA&?B{RjaC=cca7c?lEW(;sTWj_7L|L zNMAZ`HV17fd{A)jL72siWN|+X=A%p&1A^s%-CWD1GU&^!aB+T@HByJsNxY@8m*8VH zUJ>xnZh@wRk)43!NIL*BJzF--p*0@X zc(`xl)M>7XM-gLkH0?`${WbM9YdV49N^?@0%JUSEW}RuB)gbO8Or~InVN^=>!EaK= zbfJP8)xgqwmSM(#-z!0+R%w;gps~0B5cInPtzz8FbB9zMs=uOlndky2rA8&I6Ej(G z>)-%1>eyJOj+-+6IZ?%G1mGK+xj^WRearju{#dawR%jen8iyZ@tTyglI`R5h#wW%U ze=P6sx|jRci$7Q_^qyGhJy8tQuETNX*7B`)Y})9FXWr{JoFd# zomKXoT??Ee&meSgccc&-Q1CxA@E}&$b!KJPnc|M&AKiNE)@{dHc%T?+hE7BYb>u^X z#cewZ+x95i_S|;7AMSYU;kx%1>l*Kzee>*tXA7g}mC^I?yzj21dL5wf(XK*cuhIzR z$v4iHnz%sMXX!Ih(mzR`rP%)uZ}~Q+ogVnv*sLh>*9;9Ac?E5G$`l`T(6YAF@;R_r zs#nT6mr=r0x0K;PUN6hDfDw63tVat9ZsqHsDVj(okRs^Kq~7J;%JYJD;USvi zjl8KYBUXMxIxw#iYUSh3`S~mGx+muSoaT7{Oa;{>!lu-c+SkT8-riO)>teuK)j8s$uGU{k>#QkiC>3?Wsh za4Yxz~=e5hZfuq5SUo)ySoM;1Vz& z$>lM{6T5qYyv0M2Hx`!{3!%MAXzxSEY6wo_kln*|h0wN@(6(YAR0xpC=AN^_4=eoe zT42QNVjZQz-AcGSA3vak4}8QqYRHUGi1aED?j86tEeapG@P)pCkoUd0@6Ho%K5=hC zi42ge)chfo-K|g~=w`Q(weSwof7dPfAA7l)M$#@6>z)BF$DJ>j95D&V(y+Ay^KCpN ziPQJSI>J}ES8cD_U-jPMmMx_LIe>Hvd?wi^ftv-}vOS?=YK~jxtn>uSrtjXOqv9g1 z1Eno=0!X#c2;iczJ^~xO*~5 z%e*E&HRPsIDC03o3yiASVU}%H9_ZFJ3>++XBHsd&Y9=v^(!8K-EDPojvnf=)<0+37 z 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 None: + """ + Check whether the given Python version is compatible with a distribution's + "Requires-Python" value. + + :param version_info: A 3-tuple of ints representing the Python + major-minor-micro version to check. + :param ignore_requires_python: Whether to ignore the "Requires-Python" + value if the given Python version isn't compatible. + + :raises UnsupportedPythonVersion: When the given Python version isn't + compatible. + """ + # This idiosyncratically converts the SpecifierSet to str and let + # check_requires_python then parse it again into SpecifierSet. But this + # is the legacy resolver so I'm just not going to bother refactoring. + try: + requires_python = str(dist.requires_python) + except FileNotFoundError as e: + raise NoneMetadataError(dist, str(e)) + try: + is_compatible = check_requires_python( + requires_python, + version_info=version_info, + ) + except specifiers.InvalidSpecifier as exc: + logger.warning( + "Package %r has an invalid Requires-Python: %s", dist.raw_name, exc + ) + return + + if is_compatible: + return + + version = ".".join(map(str, version_info)) + if ignore_requires_python: + logger.debug( + "Ignoring failed Requires-Python check for package %r: %s not in %r", + dist.raw_name, + version, + requires_python, + ) + return + + raise UnsupportedPythonVersion( + f"Package {dist.raw_name!r} requires a different Python: " + f"{version} not in {requires_python!r}" + ) + + +class Resolver(BaseResolver): + """Resolves which packages need to be installed/uninstalled to perform \ + the requested operation without breaking the requirements of any package. + """ + + _allowed_strategies = {"eager", "only-if-needed", "to-satisfy-only"} + + def __init__( + self, + preparer: RequirementPreparer, + finder: PackageFinder, + wheel_cache: Optional[WheelCache], + make_install_req: InstallRequirementProvider, + use_user_site: bool, + ignore_dependencies: bool, + ignore_installed: bool, + ignore_requires_python: bool, + force_reinstall: bool, + upgrade_strategy: str, + py_version_info: Optional[Tuple[int, ...]] = None, + ) -> None: + super().__init__() + assert upgrade_strategy in self._allowed_strategies + + if py_version_info is None: + py_version_info = sys.version_info[:3] + else: + py_version_info = normalize_version_info(py_version_info) + + self._py_version_info = py_version_info + + self.preparer = preparer + self.finder = finder + self.wheel_cache = wheel_cache + + self.upgrade_strategy = upgrade_strategy + self.force_reinstall = force_reinstall + self.ignore_dependencies = ignore_dependencies + self.ignore_installed = ignore_installed + self.ignore_requires_python = ignore_requires_python + self.use_user_site = use_user_site + self._make_install_req = make_install_req + + self._discovered_dependencies: DiscoveredDependencies = defaultdict(list) + + def resolve( + self, root_reqs: List[InstallRequirement], check_supported_wheels: bool + ) -> RequirementSet: + """Resolve what operations need to be done + + As a side-effect of this method, the packages (and their dependencies) + are downloaded, unpacked and prepared for installation. This + preparation is done by ``pip.operations.prepare``. + + Once PyPI has static dependency metadata available, it would be + possible to move the preparation to become a step separated from + dependency resolution. + """ + requirement_set = RequirementSet(check_supported_wheels=check_supported_wheels) + for req in root_reqs: + if req.constraint: + check_invalid_constraint_type(req) + self._add_requirement_to_set(requirement_set, req) + + # Actually prepare the files, and collect any exceptions. Most hash + # exceptions cannot be checked ahead of time, because + # _populate_link() needs to be called before we can make decisions + # based on link type. + discovered_reqs: List[InstallRequirement] = [] + hash_errors = HashErrors() + for req in chain(requirement_set.all_requirements, discovered_reqs): + try: + discovered_reqs.extend(self._resolve_one(requirement_set, req)) + except HashError as exc: + exc.req = req + hash_errors.append(exc) + + if hash_errors: + raise hash_errors + + return requirement_set + + def _add_requirement_to_set( + self, + requirement_set: RequirementSet, + install_req: InstallRequirement, + parent_req_name: Optional[str] = None, + extras_requested: Optional[Iterable[str]] = None, + ) -> Tuple[List[InstallRequirement], Optional[InstallRequirement]]: + """Add install_req as a requirement to install. + + :param parent_req_name: The name of the requirement that needed this + added. The name is used because when multiple unnamed requirements + resolve to the same name, we could otherwise end up with dependency + links that point outside the Requirements set. parent_req must + already be added. Note that None implies that this is a user + supplied requirement, vs an inferred one. + :param extras_requested: an iterable of extras used to evaluate the + environment markers. + :return: Additional requirements to scan. That is either [] if + the requirement is not applicable, or [install_req] if the + requirement is applicable and has just been added. + """ + # If the markers do not match, ignore this requirement. + if not install_req.match_markers(extras_requested): + logger.info( + "Ignoring %s: markers '%s' don't match your environment", + install_req.name, + install_req.markers, + ) + return [], None + + # If the wheel is not supported, raise an error. + # Should check this after filtering out based on environment markers to + # allow specifying different wheels based on the environment/OS, in a + # single requirements file. + if install_req.link and install_req.link.is_wheel: + wheel = Wheel(install_req.link.filename) + tags = compatibility_tags.get_supported() + if requirement_set.check_supported_wheels and not wheel.supported(tags): + raise InstallationError( + f"{wheel.filename} is not a supported wheel on this platform." + ) + + # This next bit is really a sanity check. + assert ( + not install_req.user_supplied or parent_req_name is None + ), "a user supplied req shouldn't have a parent" + + # Unnamed requirements are scanned again and the requirement won't be + # added as a dependency until after scanning. + if not install_req.name: + requirement_set.add_unnamed_requirement(install_req) + return [install_req], None + + try: + existing_req: Optional[InstallRequirement] = ( + requirement_set.get_requirement(install_req.name) + ) + except KeyError: + existing_req = None + + has_conflicting_requirement = ( + parent_req_name is None + and existing_req + and not existing_req.constraint + and existing_req.extras == install_req.extras + and existing_req.req + and install_req.req + and existing_req.req.specifier != install_req.req.specifier + ) + if has_conflicting_requirement: + raise InstallationError( + f"Double requirement given: {install_req} " + f"(already in {existing_req}, name={install_req.name!r})" + ) + + # When no existing requirement exists, add the requirement as a + # dependency and it will be scanned again after. + if not existing_req: + requirement_set.add_named_requirement(install_req) + # We'd want to rescan this requirement later + return [install_req], install_req + + # Assume there's no need to scan, and that we've already + # encountered this for scanning. + if install_req.constraint or not existing_req.constraint: + return [], existing_req + + does_not_satisfy_constraint = install_req.link and not ( + existing_req.link and install_req.link.path == existing_req.link.path + ) + if does_not_satisfy_constraint: + raise InstallationError( + f"Could not satisfy constraints for '{install_req.name}': " + "installation from path or url cannot be " + "constrained to a version" + ) + # If we're now installing a constraint, mark the existing + # object for real installation. + existing_req.constraint = False + # If we're now installing a user supplied requirement, + # mark the existing object as such. + if install_req.user_supplied: + existing_req.user_supplied = True + existing_req.extras = tuple( + sorted(set(existing_req.extras) | set(install_req.extras)) + ) + logger.debug( + "Setting %s extras to: %s", + existing_req, + existing_req.extras, + ) + # Return the existing requirement for addition to the parent and + # scanning again. + return [existing_req], existing_req + + def _is_upgrade_allowed(self, req: InstallRequirement) -> bool: + if self.upgrade_strategy == "to-satisfy-only": + return False + elif self.upgrade_strategy == "eager": + return True + else: + assert self.upgrade_strategy == "only-if-needed" + return req.user_supplied or req.constraint + + def _set_req_to_reinstall(self, req: InstallRequirement) -> None: + """ + Set a requirement to be installed. + """ + # Don't uninstall the conflict if doing a user install and the + # conflict is not a user install. + assert req.satisfied_by is not None + if not self.use_user_site or req.satisfied_by.in_usersite: + req.should_reinstall = True + req.satisfied_by = None + + def _check_skip_installed( + self, req_to_install: InstallRequirement + ) -> Optional[str]: + """Check if req_to_install should be skipped. + + This will check if the req is installed, and whether we should upgrade + or reinstall it, taking into account all the relevant user options. + + After calling this req_to_install will only have satisfied_by set to + None if the req_to_install is to be upgraded/reinstalled etc. Any + other value will be a dist recording the current thing installed that + satisfies the requirement. + + Note that for vcs urls and the like we can't assess skipping in this + routine - we simply identify that we need to pull the thing down, + then later on it is pulled down and introspected to assess upgrade/ + reinstalls etc. + + :return: A text reason for why it was skipped, or None. + """ + if self.ignore_installed: + return None + + req_to_install.check_if_exists(self.use_user_site) + if not req_to_install.satisfied_by: + return None + + if self.force_reinstall: + self._set_req_to_reinstall(req_to_install) + return None + + if not self._is_upgrade_allowed(req_to_install): + if self.upgrade_strategy == "only-if-needed": + return "already satisfied, skipping upgrade" + return "already satisfied" + + # Check for the possibility of an upgrade. For link-based + # requirements we have to pull the tree down and inspect to assess + # the version #, so it's handled way down. + if not req_to_install.link: + try: + self.finder.find_requirement(req_to_install, upgrade=True) + except BestVersionAlreadyInstalled: + # Then the best version is installed. + return "already up-to-date" + except DistributionNotFound: + # No distribution found, so we squash the error. It will + # be raised later when we re-try later to do the install. + # Why don't we just raise here? + pass + + self._set_req_to_reinstall(req_to_install) + return None + + def _find_requirement_link(self, req: InstallRequirement) -> Optional[Link]: + upgrade = self._is_upgrade_allowed(req) + best_candidate = self.finder.find_requirement(req, upgrade) + if not best_candidate: + return None + + # Log a warning per PEP 592 if necessary before returning. + link = best_candidate.link + if link.is_yanked: + reason = link.yanked_reason or "" + msg = ( + # Mark this as a unicode string to prevent + # "UnicodeEncodeError: 'ascii' codec can't encode character" + # in Python 2 when the reason contains non-ascii characters. + "The candidate selected for download or install is a " + f"yanked version: {best_candidate}\n" + f"Reason for being yanked: {reason}" + ) + logger.warning(msg) + + return link + + def _populate_link(self, req: InstallRequirement) -> None: + """Ensure that if a link can be found for this, that it is found. + + Note that req.link may still be None - if the requirement is already + installed and not needed to be upgraded based on the return value of + _is_upgrade_allowed(). + + If preparer.require_hashes is True, don't use the wheel cache, because + cached wheels, always built locally, have different hashes than the + files downloaded from the index server and thus throw false hash + mismatches. Furthermore, cached wheels at present have undeterministic + contents due to file modification times. + """ + if req.link is None: + req.link = self._find_requirement_link(req) + + if self.wheel_cache is None or self.preparer.require_hashes: + return + + assert req.link is not None, "_find_requirement_link unexpectedly returned None" + cache_entry = self.wheel_cache.get_cache_entry( + link=req.link, + package_name=req.name, + supported_tags=get_supported(), + ) + if cache_entry is not None: + logger.debug("Using cached wheel link: %s", cache_entry.link) + if req.link is req.original_link and cache_entry.persistent: + req.cached_wheel_source_link = req.link + if cache_entry.origin is not None: + req.download_info = cache_entry.origin + else: + # Legacy cache entry that does not have origin.json. + # download_info may miss the archive_info.hashes field. + req.download_info = direct_url_from_link( + req.link, link_is_in_wheel_cache=cache_entry.persistent + ) + req.link = cache_entry.link + + def _get_dist_for(self, req: InstallRequirement) -> BaseDistribution: + """Takes a InstallRequirement and returns a single AbstractDist \ + representing a prepared variant of the same. + """ + if req.editable: + return self.preparer.prepare_editable_requirement(req) + + # satisfied_by is only evaluated by calling _check_skip_installed, + # so it must be None here. + assert req.satisfied_by is None + skip_reason = self._check_skip_installed(req) + + if req.satisfied_by: + return self.preparer.prepare_installed_requirement(req, skip_reason) + + # We eagerly populate the link, since that's our "legacy" behavior. + self._populate_link(req) + dist = self.preparer.prepare_linked_requirement(req) + + # NOTE + # The following portion is for determining if a certain package is + # going to be re-installed/upgraded or not and reporting to the user. + # This should probably get cleaned up in a future refactor. + + # req.req is only avail after unpack for URL + # pkgs repeat check_if_exists to uninstall-on-upgrade + # (#14) + if not self.ignore_installed: + req.check_if_exists(self.use_user_site) + + if req.satisfied_by: + should_modify = ( + self.upgrade_strategy != "to-satisfy-only" + or self.force_reinstall + or self.ignore_installed + or req.link.scheme == "file" + ) + if should_modify: + self._set_req_to_reinstall(req) + else: + logger.info( + "Requirement already satisfied (use --upgrade to upgrade): %s", + req, + ) + return dist + + def _resolve_one( + self, + requirement_set: RequirementSet, + req_to_install: InstallRequirement, + ) -> List[InstallRequirement]: + """Prepare a single requirements file. + + :return: A list of additional InstallRequirements to also install. + """ + # Tell user what we are doing for this requirement: + # obtain (editable), skipping, processing (local url), collecting + # (remote url or package name) + if req_to_install.constraint or req_to_install.prepared: + return [] + + req_to_install.prepared = True + + # Parse and return dependencies + dist = self._get_dist_for(req_to_install) + # This will raise UnsupportedPythonVersion if the given Python + # version isn't compatible with the distribution's Requires-Python. + _check_dist_requires_python( + dist, + version_info=self._py_version_info, + ignore_requires_python=self.ignore_requires_python, + ) + + more_reqs: List[InstallRequirement] = [] + + def add_req(subreq: Requirement, extras_requested: Iterable[str]) -> None: + # This idiosyncratically converts the Requirement to str and let + # make_install_req then parse it again into Requirement. But this is + # the legacy resolver so I'm just not going to bother refactoring. + sub_install_req = self._make_install_req(str(subreq), req_to_install) + parent_req_name = req_to_install.name + to_scan_again, add_to_parent = self._add_requirement_to_set( + requirement_set, + sub_install_req, + parent_req_name=parent_req_name, + extras_requested=extras_requested, + ) + if parent_req_name and add_to_parent: + self._discovered_dependencies[parent_req_name].append(add_to_parent) + more_reqs.extend(to_scan_again) + + with indent_log(): + # We add req_to_install before its dependencies, so that we + # can refer to it when adding dependencies. + assert req_to_install.name is not None + if not requirement_set.has_requirement(req_to_install.name): + # 'unnamed' requirements will get added here + # 'unnamed' requirements can only come from being directly + # provided by the user. + assert req_to_install.user_supplied + self._add_requirement_to_set( + requirement_set, req_to_install, parent_req_name=None + ) + + if not self.ignore_dependencies: + if req_to_install.extras: + logger.debug( + "Installing extra requirements: %r", + ",".join(req_to_install.extras), + ) + missing_requested = sorted( + set(req_to_install.extras) - set(dist.iter_provided_extras()) + ) + for missing in missing_requested: + logger.warning( + "%s %s does not provide the extra '%s'", + dist.raw_name, + dist.version, + missing, + ) + + available_requested = sorted( + set(dist.iter_provided_extras()) & set(req_to_install.extras) + ) + for subreq in dist.iter_dependencies(available_requested): + add_req(subreq, extras_requested=available_requested) + + return more_reqs + + def get_installation_order( + self, req_set: RequirementSet + ) -> List[InstallRequirement]: + """Create the installation order. + + The installation order is topological - requirements are installed + before the requiring thing. We break cycles at an arbitrary point, + and make no other guarantees. + """ + # The current implementation, which we may change at any point + # installs the user specified things in the order given, except when + # dependencies must come earlier to achieve topological order. + order = [] + ordered_reqs: Set[InstallRequirement] = set() + + def schedule(req: InstallRequirement) -> None: + if req.satisfied_by or req in ordered_reqs: + return + if req.constraint: + return + ordered_reqs.add(req) + for dep in self._discovered_dependencies[req.name]: + schedule(dep) + order.append(req) + + for install_req in req_set.requirements.values(): + schedule(install_req) + return order diff --git a/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__init__.py b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4c84ad16b4cfe41656335fc17438331442aa3e52 GIT binary patch literal 210 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8fa69452d0ffb62e51f72a8f0156552fdb02733e GIT binary patch literal 29410 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 RYwhN1=fgkcaAVl&{{jPr5KaI9 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..54f1d41ff799e4722fcbc81588974b59e90dcd46 GIT binary patch literal 32521 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

YFwHs-fe1HM7=Vc>OR#daAB({nplmlhtq@ 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3de692244b349584085091af129e4a6a95c2e694 GIT binary patch literal 6795 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 Dk+%L* literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3fba40a9b530e4f40c9993f2d99b3ebc926ff870 GIT binary patch literal 10525 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4306e6944aac223ec13204f70cceae1b3a9e30d8 GIT binary patch literal 5042 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py new file mode 100644 index 0000000..0f31dc9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py @@ -0,0 +1,139 @@ +from dataclasses import dataclass +from typing import FrozenSet, Iterable, Optional, Tuple + +from pip._vendor.packaging.specifiers import SpecifierSet +from pip._vendor.packaging.utils import NormalizedName +from pip._vendor.packaging.version import Version + +from pip._internal.models.link import Link, links_equivalent +from pip._internal.req.req_install import InstallRequirement +from pip._internal.utils.hashes import Hashes + +CandidateLookup = Tuple[Optional["Candidate"], Optional[InstallRequirement]] + + +def format_name(project: NormalizedName, extras: FrozenSet[NormalizedName]) -> str: + if not extras: + return project + extras_expr = ",".join(sorted(extras)) + return f"{project}[{extras_expr}]" + + +@dataclass(frozen=True) +class Constraint: + specifier: SpecifierSet + hashes: Hashes + links: FrozenSet[Link] + + @classmethod + def empty(cls) -> "Constraint": + return Constraint(SpecifierSet(), Hashes(), frozenset()) + + @classmethod + def from_ireq(cls, ireq: InstallRequirement) -> "Constraint": + links = frozenset([ireq.link]) if ireq.link else frozenset() + return Constraint(ireq.specifier, ireq.hashes(trust_internet=False), links) + + def __bool__(self) -> bool: + return bool(self.specifier) or bool(self.hashes) or bool(self.links) + + def __and__(self, other: InstallRequirement) -> "Constraint": + if not isinstance(other, InstallRequirement): + return NotImplemented + specifier = self.specifier & other.specifier + hashes = self.hashes & other.hashes(trust_internet=False) + links = self.links + if other.link: + links = links.union([other.link]) + return Constraint(specifier, hashes, links) + + def is_satisfied_by(self, candidate: "Candidate") -> bool: + # Reject if there are any mismatched URL constraints on this package. + if self.links and not all(_match_link(link, candidate) for link in self.links): + return False + # We can safely always allow prereleases here since PackageFinder + # already implements the prerelease logic, and would have filtered out + # prerelease candidates if the user does not expect them. + return self.specifier.contains(candidate.version, prereleases=True) + + +class Requirement: + @property + def project_name(self) -> NormalizedName: + """The "project name" of a requirement. + + This is different from ``name`` if this requirement contains extras, + in which case ``name`` would contain the ``[...]`` part, while this + refers to the name of the project. + """ + raise NotImplementedError("Subclass should override") + + @property + def name(self) -> str: + """The name identifying this requirement in the resolver. + + This is different from ``project_name`` if this requirement contains + extras, where ``project_name`` would not contain the ``[...]`` part. + """ + raise NotImplementedError("Subclass should override") + + def is_satisfied_by(self, candidate: "Candidate") -> bool: + return False + + def get_candidate_lookup(self) -> CandidateLookup: + raise NotImplementedError("Subclass should override") + + def format_for_error(self) -> str: + raise NotImplementedError("Subclass should override") + + +def _match_link(link: Link, candidate: "Candidate") -> bool: + if candidate.source_link: + return links_equivalent(link, candidate.source_link) + return False + + +class Candidate: + @property + def project_name(self) -> NormalizedName: + """The "project name" of the candidate. + + This is different from ``name`` if this candidate contains extras, + in which case ``name`` would contain the ``[...]`` part, while this + refers to the name of the project. + """ + raise NotImplementedError("Override in subclass") + + @property + def name(self) -> str: + """The name identifying this candidate in the resolver. + + This is different from ``project_name`` if this candidate contains + extras, where ``project_name`` would not contain the ``[...]`` part. + """ + raise NotImplementedError("Override in subclass") + + @property + def version(self) -> Version: + raise NotImplementedError("Override in subclass") + + @property + def is_installed(self) -> bool: + raise NotImplementedError("Override in subclass") + + @property + def is_editable(self) -> bool: + raise NotImplementedError("Override in subclass") + + @property + def source_link(self) -> Optional[Link]: + raise NotImplementedError("Override in subclass") + + def iter_dependencies(self, with_requires: bool) -> Iterable[Optional[Requirement]]: + raise NotImplementedError("Override in subclass") + + def get_install_requirement(self) -> Optional[InstallRequirement]: + raise NotImplementedError("Override in subclass") + + def format_for_error(self) -> str: + raise NotImplementedError("Subclass should override") diff --git a/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py new file mode 100644 index 0000000..6617644 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py @@ -0,0 +1,574 @@ +import logging +import sys +from typing import TYPE_CHECKING, Any, FrozenSet, Iterable, Optional, Tuple, Union, cast + +from pip._vendor.packaging.requirements import InvalidRequirement +from pip._vendor.packaging.utils import NormalizedName, canonicalize_name +from pip._vendor.packaging.version import Version + +from pip._internal.exceptions import ( + HashError, + InstallationSubprocessError, + InvalidInstalledPackage, + MetadataInconsistent, + MetadataInvalid, +) +from pip._internal.metadata import BaseDistribution +from pip._internal.models.link import Link, links_equivalent +from pip._internal.models.wheel import Wheel +from pip._internal.req.constructors import ( + install_req_from_editable, + install_req_from_line, +) +from pip._internal.req.req_install import InstallRequirement +from pip._internal.utils.direct_url_helpers import direct_url_from_link +from pip._internal.utils.misc import normalize_version_info + +from .base import Candidate, Requirement, format_name + +if TYPE_CHECKING: + from .factory import Factory + +logger = logging.getLogger(__name__) + +BaseCandidate = Union[ + "AlreadyInstalledCandidate", + "EditableCandidate", + "LinkCandidate", +] + +# Avoid conflicting with the PyPI package "Python". +REQUIRES_PYTHON_IDENTIFIER = cast(NormalizedName, "") + + +def as_base_candidate(candidate: Candidate) -> Optional[BaseCandidate]: + """The runtime version of BaseCandidate.""" + base_candidate_classes = ( + AlreadyInstalledCandidate, + EditableCandidate, + LinkCandidate, + ) + if isinstance(candidate, base_candidate_classes): + return candidate + return None + + +def make_install_req_from_link( + link: Link, template: InstallRequirement +) -> InstallRequirement: + assert not template.editable, "template is editable" + if template.req: + line = str(template.req) + else: + line = link.url + ireq = install_req_from_line( + line, + user_supplied=template.user_supplied, + comes_from=template.comes_from, + use_pep517=template.use_pep517, + isolated=template.isolated, + constraint=template.constraint, + global_options=template.global_options, + hash_options=template.hash_options, + config_settings=template.config_settings, + ) + ireq.original_link = template.original_link + ireq.link = link + ireq.extras = template.extras + return ireq + + +def make_install_req_from_editable( + link: Link, template: InstallRequirement +) -> InstallRequirement: + assert template.editable, "template not editable" + ireq = install_req_from_editable( + link.url, + user_supplied=template.user_supplied, + comes_from=template.comes_from, + use_pep517=template.use_pep517, + isolated=template.isolated, + constraint=template.constraint, + permit_editable_wheels=template.permit_editable_wheels, + global_options=template.global_options, + hash_options=template.hash_options, + config_settings=template.config_settings, + ) + ireq.extras = template.extras + return ireq + + +def _make_install_req_from_dist( + dist: BaseDistribution, template: InstallRequirement +) -> InstallRequirement: + if template.req: + line = str(template.req) + elif template.link: + line = f"{dist.canonical_name} @ {template.link.url}" + else: + line = f"{dist.canonical_name}=={dist.version}" + ireq = install_req_from_line( + line, + user_supplied=template.user_supplied, + comes_from=template.comes_from, + use_pep517=template.use_pep517, + isolated=template.isolated, + constraint=template.constraint, + global_options=template.global_options, + hash_options=template.hash_options, + config_settings=template.config_settings, + ) + ireq.satisfied_by = dist + return ireq + + +class _InstallRequirementBackedCandidate(Candidate): + """A candidate backed by an ``InstallRequirement``. + + This represents a package request with the target not being already + in the environment, and needs to be fetched and installed. The backing + ``InstallRequirement`` is responsible for most of the leg work; this + class exposes appropriate information to the resolver. + + :param link: The link passed to the ``InstallRequirement``. The backing + ``InstallRequirement`` will use this link to fetch the distribution. + :param source_link: The link this candidate "originates" from. This is + different from ``link`` when the link is found in the wheel cache. + ``link`` would point to the wheel cache, while this points to the + found remote link (e.g. from pypi.org). + """ + + dist: BaseDistribution + is_installed = False + + def __init__( + self, + link: Link, + source_link: Link, + ireq: InstallRequirement, + factory: "Factory", + name: Optional[NormalizedName] = None, + version: Optional[Version] = None, + ) -> None: + self._link = link + self._source_link = source_link + self._factory = factory + self._ireq = ireq + self._name = name + self._version = version + self.dist = self._prepare() + self._hash: Optional[int] = None + + def __str__(self) -> str: + return f"{self.name} {self.version}" + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({str(self._link)!r})" + + def __hash__(self) -> int: + if self._hash is not None: + return self._hash + + self._hash = hash((self.__class__, self._link)) + return self._hash + + def __eq__(self, other: Any) -> bool: + if isinstance(other, self.__class__): + return links_equivalent(self._link, other._link) + return False + + @property + def source_link(self) -> Optional[Link]: + return self._source_link + + @property + def project_name(self) -> NormalizedName: + """The normalised name of the project the candidate refers to""" + if self._name is None: + self._name = self.dist.canonical_name + return self._name + + @property + def name(self) -> str: + return self.project_name + + @property + def version(self) -> Version: + if self._version is None: + self._version = self.dist.version + return self._version + + def format_for_error(self) -> str: + return ( + f"{self.name} {self.version} " + f"(from {self._link.file_path if self._link.is_file else self._link})" + ) + + def _prepare_distribution(self) -> BaseDistribution: + raise NotImplementedError("Override in subclass") + + def _check_metadata_consistency(self, dist: BaseDistribution) -> None: + """Check for consistency of project name and version of dist.""" + if self._name is not None and self._name != dist.canonical_name: + raise MetadataInconsistent( + self._ireq, + "name", + self._name, + dist.canonical_name, + ) + if self._version is not None and self._version != dist.version: + raise MetadataInconsistent( + self._ireq, + "version", + str(self._version), + str(dist.version), + ) + # check dependencies are valid + # TODO performance: this means we iterate the dependencies at least twice, + # we may want to cache parsed Requires-Dist + try: + list(dist.iter_dependencies(list(dist.iter_provided_extras()))) + except InvalidRequirement as e: + raise MetadataInvalid(self._ireq, str(e)) + + def _prepare(self) -> BaseDistribution: + try: + dist = self._prepare_distribution() + except HashError as e: + # Provide HashError the underlying ireq that caused it. This + # provides context for the resulting error message to show the + # offending line to the user. + e.req = self._ireq + raise + except InstallationSubprocessError as exc: + # The output has been presented already, so don't duplicate it. + exc.context = "See above for output." + raise + + self._check_metadata_consistency(dist) + return dist + + def iter_dependencies(self, with_requires: bool) -> Iterable[Optional[Requirement]]: + requires = self.dist.iter_dependencies() if with_requires else () + for r in requires: + yield from self._factory.make_requirements_from_spec(str(r), self._ireq) + yield self._factory.make_requires_python_requirement(self.dist.requires_python) + + def get_install_requirement(self) -> Optional[InstallRequirement]: + return self._ireq + + +class LinkCandidate(_InstallRequirementBackedCandidate): + is_editable = False + + def __init__( + self, + link: Link, + template: InstallRequirement, + factory: "Factory", + name: Optional[NormalizedName] = None, + version: Optional[Version] = None, + ) -> None: + source_link = link + cache_entry = factory.get_wheel_cache_entry(source_link, name) + if cache_entry is not None: + logger.debug("Using cached wheel link: %s", cache_entry.link) + link = cache_entry.link + ireq = make_install_req_from_link(link, template) + assert ireq.link == link + if ireq.link.is_wheel and not ireq.link.is_file: + wheel = Wheel(ireq.link.filename) + wheel_name = canonicalize_name(wheel.name) + assert name == wheel_name, f"{name!r} != {wheel_name!r} for wheel" + # Version may not be present for PEP 508 direct URLs + if version is not None: + wheel_version = Version(wheel.version) + assert ( + version == wheel_version + ), f"{version!r} != {wheel_version!r} for wheel {name}" + + if cache_entry is not None: + assert ireq.link.is_wheel + assert ireq.link.is_file + if cache_entry.persistent and template.link is template.original_link: + ireq.cached_wheel_source_link = source_link + if cache_entry.origin is not None: + ireq.download_info = cache_entry.origin + else: + # Legacy cache entry that does not have origin.json. + # download_info may miss the archive_info.hashes field. + ireq.download_info = direct_url_from_link( + source_link, link_is_in_wheel_cache=cache_entry.persistent + ) + + super().__init__( + link=link, + source_link=source_link, + ireq=ireq, + factory=factory, + name=name, + version=version, + ) + + def _prepare_distribution(self) -> BaseDistribution: + preparer = self._factory.preparer + return preparer.prepare_linked_requirement(self._ireq, parallel_builds=True) + + +class EditableCandidate(_InstallRequirementBackedCandidate): + is_editable = True + + def __init__( + self, + link: Link, + template: InstallRequirement, + factory: "Factory", + name: Optional[NormalizedName] = None, + version: Optional[Version] = None, + ) -> None: + super().__init__( + link=link, + source_link=link, + ireq=make_install_req_from_editable(link, template), + factory=factory, + name=name, + version=version, + ) + + def _prepare_distribution(self) -> BaseDistribution: + return self._factory.preparer.prepare_editable_requirement(self._ireq) + + +class AlreadyInstalledCandidate(Candidate): + is_installed = True + source_link = None + + def __init__( + self, + dist: BaseDistribution, + template: InstallRequirement, + factory: "Factory", + ) -> None: + self.dist = dist + self._ireq = _make_install_req_from_dist(dist, template) + self._factory = factory + self._version = None + + # This is just logging some messages, so we can do it eagerly. + # The returned dist would be exactly the same as self.dist because we + # set satisfied_by in _make_install_req_from_dist. + # TODO: Supply reason based on force_reinstall and upgrade_strategy. + skip_reason = "already satisfied" + factory.preparer.prepare_installed_requirement(self._ireq, skip_reason) + + def __str__(self) -> str: + return str(self.dist) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self.dist!r})" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, AlreadyInstalledCandidate): + return NotImplemented + return self.name == other.name and self.version == other.version + + def __hash__(self) -> int: + return hash((self.name, self.version)) + + @property + def project_name(self) -> NormalizedName: + return self.dist.canonical_name + + @property + def name(self) -> str: + return self.project_name + + @property + def version(self) -> Version: + if self._version is None: + self._version = self.dist.version + return self._version + + @property + def is_editable(self) -> bool: + return self.dist.editable + + def format_for_error(self) -> str: + return f"{self.name} {self.version} (Installed)" + + def iter_dependencies(self, with_requires: bool) -> Iterable[Optional[Requirement]]: + if not with_requires: + return + + try: + for r in self.dist.iter_dependencies(): + yield from self._factory.make_requirements_from_spec(str(r), self._ireq) + except InvalidRequirement as exc: + raise InvalidInstalledPackage(dist=self.dist, invalid_exc=exc) from None + + def get_install_requirement(self) -> Optional[InstallRequirement]: + return None + + +class ExtrasCandidate(Candidate): + """A candidate that has 'extras', indicating additional dependencies. + + Requirements can be for a project with dependencies, something like + foo[extra]. The extras don't affect the project/version being installed + directly, but indicate that we need additional dependencies. We model that + by having an artificial ExtrasCandidate that wraps the "base" candidate. + + The ExtrasCandidate differs from the base in the following ways: + + 1. It has a unique name, of the form foo[extra]. This causes the resolver + to treat it as a separate node in the dependency graph. + 2. When we're getting the candidate's dependencies, + a) We specify that we want the extra dependencies as well. + b) We add a dependency on the base candidate. + See below for why this is needed. + 3. We return None for the underlying InstallRequirement, as the base + candidate will provide it, and we don't want to end up with duplicates. + + The dependency on the base candidate is needed so that the resolver can't + decide that it should recommend foo[extra1] version 1.0 and foo[extra2] + version 2.0. Having those candidates depend on foo=1.0 and foo=2.0 + respectively forces the resolver to recognise that this is a conflict. + """ + + def __init__( + self, + base: BaseCandidate, + extras: FrozenSet[str], + *, + comes_from: Optional[InstallRequirement] = None, + ) -> None: + """ + :param comes_from: the InstallRequirement that led to this candidate if it + differs from the base's InstallRequirement. This will often be the + case in the sense that this candidate's requirement has the extras + while the base's does not. Unlike the InstallRequirement backed + candidates, this requirement is used solely for reporting purposes, + it does not do any leg work. + """ + self.base = base + self.extras = frozenset(canonicalize_name(e) for e in extras) + self._comes_from = comes_from if comes_from is not None else self.base._ireq + + def __str__(self) -> str: + name, rest = str(self.base).split(" ", 1) + return "{}[{}] {}".format(name, ",".join(self.extras), rest) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}(base={self.base!r}, extras={self.extras!r})" + + def __hash__(self) -> int: + return hash((self.base, self.extras)) + + def __eq__(self, other: Any) -> bool: + if isinstance(other, self.__class__): + return self.base == other.base and self.extras == other.extras + return False + + @property + def project_name(self) -> NormalizedName: + return self.base.project_name + + @property + def name(self) -> str: + """The normalised name of the project the candidate refers to""" + return format_name(self.base.project_name, self.extras) + + @property + def version(self) -> Version: + return self.base.version + + def format_for_error(self) -> str: + return "{} [{}]".format( + self.base.format_for_error(), ", ".join(sorted(self.extras)) + ) + + @property + def is_installed(self) -> bool: + return self.base.is_installed + + @property + def is_editable(self) -> bool: + return self.base.is_editable + + @property + def source_link(self) -> Optional[Link]: + return self.base.source_link + + def iter_dependencies(self, with_requires: bool) -> Iterable[Optional[Requirement]]: + factory = self.base._factory + + # Add a dependency on the exact base + # (See note 2b in the class docstring) + yield factory.make_requirement_from_candidate(self.base) + if not with_requires: + return + + # The user may have specified extras that the candidate doesn't + # support. We ignore any unsupported extras here. + valid_extras = self.extras.intersection(self.base.dist.iter_provided_extras()) + invalid_extras = self.extras.difference(self.base.dist.iter_provided_extras()) + for extra in sorted(invalid_extras): + logger.warning( + "%s %s does not provide the extra '%s'", + self.base.name, + self.version, + extra, + ) + + for r in self.base.dist.iter_dependencies(valid_extras): + yield from factory.make_requirements_from_spec( + str(r), + self._comes_from, + valid_extras, + ) + + def get_install_requirement(self) -> Optional[InstallRequirement]: + # We don't return anything here, because we always + # depend on the base candidate, and we'll get the + # install requirement from that. + return None + + +class RequiresPythonCandidate(Candidate): + is_installed = False + source_link = None + + def __init__(self, py_version_info: Optional[Tuple[int, ...]]) -> None: + if py_version_info is not None: + version_info = normalize_version_info(py_version_info) + else: + version_info = sys.version_info[:3] + self._version = Version(".".join(str(c) for c in version_info)) + + # We don't need to implement __eq__() and __ne__() since there is always + # only one RequiresPythonCandidate in a resolution, i.e. the host Python. + # The built-in object.__eq__() and object.__ne__() do exactly what we want. + + def __str__(self) -> str: + return f"Python {self._version}" + + @property + def project_name(self) -> NormalizedName: + return REQUIRES_PYTHON_IDENTIFIER + + @property + def name(self) -> str: + return REQUIRES_PYTHON_IDENTIFIER + + @property + def version(self) -> Version: + return self._version + + def format_for_error(self) -> str: + return f"Python {self.version}" + + def iter_dependencies(self, with_requires: bool) -> Iterable[Optional[Requirement]]: + return () + + def get_install_requirement(self) -> Optional[InstallRequirement]: + return None diff --git a/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py new file mode 100644 index 0000000..dc6e2e1 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py @@ -0,0 +1,823 @@ +import contextlib +import functools +import logging +from typing import ( + TYPE_CHECKING, + Callable, + Dict, + FrozenSet, + Iterable, + Iterator, + List, + Mapping, + NamedTuple, + Optional, + Protocol, + Sequence, + Set, + Tuple, + TypeVar, + cast, +) + +from pip._vendor.packaging.requirements import InvalidRequirement +from pip._vendor.packaging.specifiers import SpecifierSet +from pip._vendor.packaging.utils import NormalizedName, canonicalize_name +from pip._vendor.packaging.version import InvalidVersion, Version +from pip._vendor.resolvelib import ResolutionImpossible + +from pip._internal.cache import CacheEntry, WheelCache +from pip._internal.exceptions import ( + DistributionNotFound, + InstallationError, + InvalidInstalledPackage, + MetadataInconsistent, + MetadataInvalid, + UnsupportedPythonVersion, + UnsupportedWheel, +) +from pip._internal.index.package_finder import PackageFinder +from pip._internal.metadata import BaseDistribution, get_default_environment +from pip._internal.models.link import Link +from pip._internal.models.wheel import Wheel +from pip._internal.operations.prepare import RequirementPreparer +from pip._internal.req.constructors import ( + install_req_drop_extras, + install_req_from_link_and_ireq, +) +from pip._internal.req.req_install import ( + InstallRequirement, + check_invalid_constraint_type, +) +from pip._internal.resolution.base import InstallRequirementProvider +from pip._internal.utils.compatibility_tags import get_supported +from pip._internal.utils.hashes import Hashes +from pip._internal.utils.packaging import get_requirement +from pip._internal.utils.virtualenv import running_under_virtualenv + +from .base import Candidate, Constraint, Requirement +from .candidates import ( + AlreadyInstalledCandidate, + BaseCandidate, + EditableCandidate, + ExtrasCandidate, + LinkCandidate, + RequiresPythonCandidate, + as_base_candidate, +) +from .found_candidates import FoundCandidates, IndexCandidateInfo +from .requirements import ( + ExplicitRequirement, + RequiresPythonRequirement, + SpecifierRequirement, + SpecifierWithoutExtrasRequirement, + UnsatisfiableRequirement, +) + +if TYPE_CHECKING: + + class ConflictCause(Protocol): + requirement: RequiresPythonRequirement + parent: Candidate + + +logger = logging.getLogger(__name__) + +C = TypeVar("C") +Cache = Dict[Link, C] + + +class CollectedRootRequirements(NamedTuple): + requirements: List[Requirement] + constraints: Dict[str, Constraint] + user_requested: Dict[str, int] + + +class Factory: + def __init__( + self, + finder: PackageFinder, + preparer: RequirementPreparer, + make_install_req: InstallRequirementProvider, + wheel_cache: Optional[WheelCache], + use_user_site: bool, + force_reinstall: bool, + ignore_installed: bool, + ignore_requires_python: bool, + py_version_info: Optional[Tuple[int, ...]] = None, + ) -> None: + self._finder = finder + self.preparer = preparer + self._wheel_cache = wheel_cache + self._python_candidate = RequiresPythonCandidate(py_version_info) + self._make_install_req_from_spec = make_install_req + self._use_user_site = use_user_site + self._force_reinstall = force_reinstall + self._ignore_requires_python = ignore_requires_python + + self._build_failures: Cache[InstallationError] = {} + self._link_candidate_cache: Cache[LinkCandidate] = {} + self._editable_candidate_cache: Cache[EditableCandidate] = {} + self._installed_candidate_cache: Dict[str, AlreadyInstalledCandidate] = {} + self._extras_candidate_cache: Dict[ + Tuple[int, FrozenSet[NormalizedName]], ExtrasCandidate + ] = {} + self._supported_tags_cache = get_supported() + + if not ignore_installed: + env = get_default_environment() + self._installed_dists = { + dist.canonical_name: dist + for dist in env.iter_installed_distributions(local_only=False) + } + else: + self._installed_dists = {} + + @property + def force_reinstall(self) -> bool: + return self._force_reinstall + + def _fail_if_link_is_unsupported_wheel(self, link: Link) -> None: + if not link.is_wheel: + return + wheel = Wheel(link.filename) + if wheel.supported(self._finder.target_python.get_unsorted_tags()): + return + msg = f"{link.filename} is not a supported wheel on this platform." + raise UnsupportedWheel(msg) + + def _make_extras_candidate( + self, + base: BaseCandidate, + extras: FrozenSet[str], + *, + comes_from: Optional[InstallRequirement] = None, + ) -> ExtrasCandidate: + cache_key = (id(base), frozenset(canonicalize_name(e) for e in extras)) + try: + candidate = self._extras_candidate_cache[cache_key] + except KeyError: + candidate = ExtrasCandidate(base, extras, comes_from=comes_from) + self._extras_candidate_cache[cache_key] = candidate + return candidate + + def _make_candidate_from_dist( + self, + dist: BaseDistribution, + extras: FrozenSet[str], + template: InstallRequirement, + ) -> Candidate: + try: + base = self._installed_candidate_cache[dist.canonical_name] + except KeyError: + base = AlreadyInstalledCandidate(dist, template, factory=self) + self._installed_candidate_cache[dist.canonical_name] = base + if not extras: + return base + return self._make_extras_candidate(base, extras, comes_from=template) + + def _make_candidate_from_link( + self, + link: Link, + extras: FrozenSet[str], + template: InstallRequirement, + name: Optional[NormalizedName], + version: Optional[Version], + ) -> Optional[Candidate]: + base: Optional[BaseCandidate] = self._make_base_candidate_from_link( + link, template, name, version + ) + if not extras or base is None: + return base + return self._make_extras_candidate(base, extras, comes_from=template) + + def _make_base_candidate_from_link( + self, + link: Link, + template: InstallRequirement, + name: Optional[NormalizedName], + version: Optional[Version], + ) -> Optional[BaseCandidate]: + # TODO: Check already installed candidate, and use it if the link and + # editable flag match. + + if link in self._build_failures: + # We already tried this candidate before, and it does not build. + # Don't bother trying again. + return None + + if template.editable: + if link not in self._editable_candidate_cache: + try: + self._editable_candidate_cache[link] = EditableCandidate( + link, + template, + factory=self, + name=name, + version=version, + ) + except (MetadataInconsistent, MetadataInvalid) as e: + logger.info( + "Discarding [blue underline]%s[/]: [yellow]%s[reset]", + link, + e, + extra={"markup": True}, + ) + self._build_failures[link] = e + return None + + return self._editable_candidate_cache[link] + else: + if link not in self._link_candidate_cache: + try: + self._link_candidate_cache[link] = LinkCandidate( + link, + template, + factory=self, + name=name, + version=version, + ) + except MetadataInconsistent as e: + logger.info( + "Discarding [blue underline]%s[/]: [yellow]%s[reset]", + link, + e, + extra={"markup": True}, + ) + self._build_failures[link] = e + return None + return self._link_candidate_cache[link] + + def _iter_found_candidates( + self, + ireqs: Sequence[InstallRequirement], + specifier: SpecifierSet, + hashes: Hashes, + prefers_installed: bool, + incompatible_ids: Set[int], + ) -> Iterable[Candidate]: + if not ireqs: + return () + + # The InstallRequirement implementation requires us to give it a + # "template". Here we just choose the first requirement to represent + # all of them. + # Hopefully the Project model can correct this mismatch in the future. + template = ireqs[0] + assert template.req, "Candidates found on index must be PEP 508" + name = canonicalize_name(template.req.name) + + extras: FrozenSet[str] = frozenset() + for ireq in ireqs: + assert ireq.req, "Candidates found on index must be PEP 508" + specifier &= ireq.req.specifier + hashes &= ireq.hashes(trust_internet=False) + extras |= frozenset(ireq.extras) + + def _get_installed_candidate() -> Optional[Candidate]: + """Get the candidate for the currently-installed version.""" + # If --force-reinstall is set, we want the version from the index + # instead, so we "pretend" there is nothing installed. + if self._force_reinstall: + return None + try: + installed_dist = self._installed_dists[name] + except KeyError: + return None + + try: + # Don't use the installed distribution if its version + # does not fit the current dependency graph. + if not specifier.contains(installed_dist.version, prereleases=True): + return None + except InvalidVersion as e: + raise InvalidInstalledPackage(dist=installed_dist, invalid_exc=e) + + candidate = self._make_candidate_from_dist( + dist=installed_dist, + extras=extras, + template=template, + ) + # The candidate is a known incompatibility. Don't use it. + if id(candidate) in incompatible_ids: + return None + return candidate + + def iter_index_candidate_infos() -> Iterator[IndexCandidateInfo]: + result = self._finder.find_best_candidate( + project_name=name, + specifier=specifier, + hashes=hashes, + ) + icans = list(result.iter_applicable()) + + # PEP 592: Yanked releases are ignored unless the specifier + # explicitly pins a version (via '==' or '===') that can be + # solely satisfied by a yanked release. + all_yanked = all(ican.link.is_yanked for ican in icans) + + def is_pinned(specifier: SpecifierSet) -> bool: + for sp in specifier: + if sp.operator == "===": + return True + if sp.operator != "==": + continue + if sp.version.endswith(".*"): + continue + return True + return False + + pinned = is_pinned(specifier) + + # PackageFinder returns earlier versions first, so we reverse. + for ican in reversed(icans): + if not (all_yanked and pinned) and ican.link.is_yanked: + continue + func = functools.partial( + self._make_candidate_from_link, + link=ican.link, + extras=extras, + template=template, + name=name, + version=ican.version, + ) + yield ican.version, func + + return FoundCandidates( + iter_index_candidate_infos, + _get_installed_candidate(), + prefers_installed, + incompatible_ids, + ) + + def _iter_explicit_candidates_from_base( + self, + base_requirements: Iterable[Requirement], + extras: FrozenSet[str], + ) -> Iterator[Candidate]: + """Produce explicit candidates from the base given an extra-ed package. + + :param base_requirements: Requirements known to the resolver. The + requirements are guaranteed to not have extras. + :param extras: The extras to inject into the explicit requirements' + candidates. + """ + for req in base_requirements: + lookup_cand, _ = req.get_candidate_lookup() + if lookup_cand is None: # Not explicit. + continue + # We've stripped extras from the identifier, and should always + # get a BaseCandidate here, unless there's a bug elsewhere. + base_cand = as_base_candidate(lookup_cand) + assert base_cand is not None, "no extras here" + yield self._make_extras_candidate(base_cand, extras) + + def _iter_candidates_from_constraints( + self, + identifier: str, + constraint: Constraint, + template: InstallRequirement, + ) -> Iterator[Candidate]: + """Produce explicit candidates from constraints. + + This creates "fake" InstallRequirement objects that are basically clones + of what "should" be the template, but with original_link set to link. + """ + for link in constraint.links: + self._fail_if_link_is_unsupported_wheel(link) + candidate = self._make_base_candidate_from_link( + link, + template=install_req_from_link_and_ireq(link, template), + name=canonicalize_name(identifier), + version=None, + ) + if candidate: + yield candidate + + def find_candidates( + self, + identifier: str, + requirements: Mapping[str, Iterable[Requirement]], + incompatibilities: Mapping[str, Iterator[Candidate]], + constraint: Constraint, + prefers_installed: bool, + is_satisfied_by: Callable[[Requirement, Candidate], bool], + ) -> Iterable[Candidate]: + # Collect basic lookup information from the requirements. + explicit_candidates: Set[Candidate] = set() + ireqs: List[InstallRequirement] = [] + for req in requirements[identifier]: + cand, ireq = req.get_candidate_lookup() + if cand is not None: + explicit_candidates.add(cand) + if ireq is not None: + ireqs.append(ireq) + + # If the current identifier contains extras, add requires and explicit + # candidates from entries from extra-less identifier. + with contextlib.suppress(InvalidRequirement): + parsed_requirement = get_requirement(identifier) + if parsed_requirement.name != identifier: + explicit_candidates.update( + self._iter_explicit_candidates_from_base( + requirements.get(parsed_requirement.name, ()), + frozenset(parsed_requirement.extras), + ), + ) + for req in requirements.get(parsed_requirement.name, []): + _, ireq = req.get_candidate_lookup() + if ireq is not None: + ireqs.append(ireq) + + # Add explicit candidates from constraints. We only do this if there are + # known ireqs, which represent requirements not already explicit. If + # there are no ireqs, we're constraining already-explicit requirements, + # which is handled later when we return the explicit candidates. + if ireqs: + try: + explicit_candidates.update( + self._iter_candidates_from_constraints( + identifier, + constraint, + template=ireqs[0], + ), + ) + except UnsupportedWheel: + # If we're constrained to install a wheel incompatible with the + # target architecture, no candidates will ever be valid. + return () + + # Since we cache all the candidates, incompatibility identification + # can be made quicker by comparing only the id() values. + incompat_ids = {id(c) for c in incompatibilities.get(identifier, ())} + + # If none of the requirements want an explicit candidate, we can ask + # the finder for candidates. + if not explicit_candidates: + return self._iter_found_candidates( + ireqs, + constraint.specifier, + constraint.hashes, + prefers_installed, + incompat_ids, + ) + + return ( + c + for c in explicit_candidates + if id(c) not in incompat_ids + and constraint.is_satisfied_by(c) + and all(is_satisfied_by(req, c) for req in requirements[identifier]) + ) + + def _make_requirements_from_install_req( + self, ireq: InstallRequirement, requested_extras: Iterable[str] + ) -> Iterator[Requirement]: + """ + Returns requirement objects associated with the given InstallRequirement. In + most cases this will be a single object but the following special cases exist: + - the InstallRequirement has markers that do not apply -> result is empty + - the InstallRequirement has both a constraint (or link) and extras + -> result is split in two requirement objects: one with the constraint + (or link) and one with the extra. This allows centralized constraint + handling for the base, resulting in fewer candidate rejections. + """ + if not ireq.match_markers(requested_extras): + logger.info( + "Ignoring %s: markers '%s' don't match your environment", + ireq.name, + ireq.markers, + ) + elif not ireq.link: + if ireq.extras and ireq.req is not None and ireq.req.specifier: + yield SpecifierWithoutExtrasRequirement(ireq) + yield SpecifierRequirement(ireq) + else: + self._fail_if_link_is_unsupported_wheel(ireq.link) + # Always make the link candidate for the base requirement to make it + # available to `find_candidates` for explicit candidate lookup for any + # set of extras. + # The extras are required separately via a second requirement. + cand = self._make_base_candidate_from_link( + ireq.link, + template=install_req_drop_extras(ireq) if ireq.extras else ireq, + name=canonicalize_name(ireq.name) if ireq.name else None, + version=None, + ) + if cand is None: + # There's no way we can satisfy a URL requirement if the underlying + # candidate fails to build. An unnamed URL must be user-supplied, so + # we fail eagerly. If the URL is named, an unsatisfiable requirement + # can make the resolver do the right thing, either backtrack (and + # maybe find some other requirement that's buildable) or raise a + # ResolutionImpossible eventually. + if not ireq.name: + raise self._build_failures[ireq.link] + yield UnsatisfiableRequirement(canonicalize_name(ireq.name)) + else: + # require the base from the link + yield self.make_requirement_from_candidate(cand) + if ireq.extras: + # require the extras on top of the base candidate + yield self.make_requirement_from_candidate( + self._make_extras_candidate(cand, frozenset(ireq.extras)) + ) + + def collect_root_requirements( + self, root_ireqs: List[InstallRequirement] + ) -> CollectedRootRequirements: + collected = CollectedRootRequirements([], {}, {}) + for i, ireq in enumerate(root_ireqs): + if ireq.constraint: + # Ensure we only accept valid constraints + problem = check_invalid_constraint_type(ireq) + if problem: + raise InstallationError(problem) + if not ireq.match_markers(): + continue + assert ireq.name, "Constraint must be named" + name = canonicalize_name(ireq.name) + if name in collected.constraints: + collected.constraints[name] &= ireq + else: + collected.constraints[name] = Constraint.from_ireq(ireq) + else: + reqs = list( + self._make_requirements_from_install_req( + ireq, + requested_extras=(), + ) + ) + if not reqs: + continue + template = reqs[0] + if ireq.user_supplied and template.name not in collected.user_requested: + collected.user_requested[template.name] = i + collected.requirements.extend(reqs) + # Put requirements with extras at the end of the root requires. This does not + # affect resolvelib's picking preference but it does affect its initial criteria + # population: by putting extras at the end we enable the candidate finder to + # present resolvelib with a smaller set of candidates to resolvelib, already + # taking into account any non-transient constraints on the associated base. This + # means resolvelib will have fewer candidates to visit and reject. + # Python's list sort is stable, meaning relative order is kept for objects with + # the same key. + collected.requirements.sort(key=lambda r: r.name != r.project_name) + return collected + + def make_requirement_from_candidate( + self, candidate: Candidate + ) -> ExplicitRequirement: + return ExplicitRequirement(candidate) + + def make_requirements_from_spec( + self, + specifier: str, + comes_from: Optional[InstallRequirement], + requested_extras: Iterable[str] = (), + ) -> Iterator[Requirement]: + """ + Returns requirement objects associated with the given specifier. In most cases + this will be a single object but the following special cases exist: + - the specifier has markers that do not apply -> result is empty + - the specifier has both a constraint and extras -> result is split + in two requirement objects: one with the constraint and one with the + extra. This allows centralized constraint handling for the base, + resulting in fewer candidate rejections. + """ + ireq = self._make_install_req_from_spec(specifier, comes_from) + return self._make_requirements_from_install_req(ireq, requested_extras) + + def make_requires_python_requirement( + self, + specifier: SpecifierSet, + ) -> Optional[Requirement]: + if self._ignore_requires_python: + return None + # Don't bother creating a dependency for an empty Requires-Python. + if not str(specifier): + return None + return RequiresPythonRequirement(specifier, self._python_candidate) + + def get_wheel_cache_entry( + self, link: Link, name: Optional[str] + ) -> Optional[CacheEntry]: + """Look up the link in the wheel cache. + + If ``preparer.require_hashes`` is True, don't use the wheel cache, + because cached wheels, always built locally, have different hashes + than the files downloaded from the index server and thus throw false + hash mismatches. Furthermore, cached wheels at present have + nondeterministic contents due to file modification times. + """ + if self._wheel_cache is None: + return None + return self._wheel_cache.get_cache_entry( + link=link, + package_name=name, + supported_tags=self._supported_tags_cache, + ) + + def get_dist_to_uninstall(self, candidate: Candidate) -> Optional[BaseDistribution]: + # TODO: Are there more cases this needs to return True? Editable? + dist = self._installed_dists.get(candidate.project_name) + if dist is None: # Not installed, no uninstallation required. + return None + + # We're installing into global site. The current installation must + # be uninstalled, no matter it's in global or user site, because the + # user site installation has precedence over global. + if not self._use_user_site: + return dist + + # We're installing into user site. Remove the user site installation. + if dist.in_usersite: + return dist + + # We're installing into user site, but the installed incompatible + # package is in global site. We can't uninstall that, and would let + # the new user installation to "shadow" it. But shadowing won't work + # in virtual environments, so we error out. + if running_under_virtualenv() and dist.in_site_packages: + message = ( + f"Will not install to the user site because it will lack " + f"sys.path precedence to {dist.raw_name} in {dist.location}" + ) + raise InstallationError(message) + return None + + def _report_requires_python_error( + self, causes: Sequence["ConflictCause"] + ) -> UnsupportedPythonVersion: + assert causes, "Requires-Python error reported with no cause" + + version = self._python_candidate.version + + if len(causes) == 1: + specifier = str(causes[0].requirement.specifier) + message = ( + f"Package {causes[0].parent.name!r} requires a different " + f"Python: {version} not in {specifier!r}" + ) + return UnsupportedPythonVersion(message) + + message = f"Packages require a different Python. {version} not in:" + for cause in causes: + package = cause.parent.format_for_error() + specifier = str(cause.requirement.specifier) + message += f"\n{specifier!r} (required by {package})" + return UnsupportedPythonVersion(message) + + def _report_single_requirement_conflict( + self, req: Requirement, parent: Optional[Candidate] + ) -> DistributionNotFound: + if parent is None: + req_disp = str(req) + else: + req_disp = f"{req} (from {parent.name})" + + cands = self._finder.find_all_candidates(req.project_name) + skipped_by_requires_python = self._finder.requires_python_skipped_reasons() + + versions_set: Set[Version] = set() + yanked_versions_set: Set[Version] = set() + for c in cands: + is_yanked = c.link.is_yanked if c.link else False + if is_yanked: + yanked_versions_set.add(c.version) + else: + versions_set.add(c.version) + + versions = [str(v) for v in sorted(versions_set)] + yanked_versions = [str(v) for v in sorted(yanked_versions_set)] + + if yanked_versions: + # Saying "version X is yanked" isn't entirely accurate. + # https://github.com/pypa/pip/issues/11745#issuecomment-1402805842 + logger.critical( + "Ignored the following yanked versions: %s", + ", ".join(yanked_versions) or "none", + ) + if skipped_by_requires_python: + logger.critical( + "Ignored the following versions that require a different python " + "version: %s", + "; ".join(skipped_by_requires_python) or "none", + ) + logger.critical( + "Could not find a version that satisfies the requirement %s " + "(from versions: %s)", + req_disp, + ", ".join(versions) or "none", + ) + if str(req) == "requirements.txt": + logger.info( + "HINT: You are attempting to install a package literally " + 'named "requirements.txt" (which cannot exist). Consider ' + "using the '-r' flag to install the packages listed in " + "requirements.txt" + ) + + return DistributionNotFound(f"No matching distribution found for {req}") + + def get_installation_error( + self, + e: "ResolutionImpossible[Requirement, Candidate]", + constraints: Dict[str, Constraint], + ) -> InstallationError: + assert e.causes, "Installation error reported with no cause" + + # If one of the things we can't solve is "we need Python X.Y", + # that is what we report. + requires_python_causes = [ + cause + for cause in e.causes + if isinstance(cause.requirement, RequiresPythonRequirement) + and not cause.requirement.is_satisfied_by(self._python_candidate) + ] + if requires_python_causes: + # The comprehension above makes sure all Requirement instances are + # RequiresPythonRequirement, so let's cast for convenience. + return self._report_requires_python_error( + cast("Sequence[ConflictCause]", requires_python_causes), + ) + + # Otherwise, we have a set of causes which can't all be satisfied + # at once. + + # The simplest case is when we have *one* cause that can't be + # satisfied. We just report that case. + if len(e.causes) == 1: + req, parent = e.causes[0] + if req.name not in constraints: + return self._report_single_requirement_conflict(req, parent) + + # OK, we now have a list of requirements that can't all be + # satisfied at once. + + # A couple of formatting helpers + def text_join(parts: List[str]) -> str: + if len(parts) == 1: + return parts[0] + + return ", ".join(parts[:-1]) + " and " + parts[-1] + + def describe_trigger(parent: Candidate) -> str: + ireq = parent.get_install_requirement() + if not ireq or not ireq.comes_from: + return f"{parent.name}=={parent.version}" + if isinstance(ireq.comes_from, InstallRequirement): + return str(ireq.comes_from.name) + return str(ireq.comes_from) + + triggers = set() + for req, parent in e.causes: + if parent is None: + # This is a root requirement, so we can report it directly + trigger = req.format_for_error() + else: + trigger = describe_trigger(parent) + triggers.add(trigger) + + if triggers: + info = text_join(sorted(triggers)) + else: + info = "the requested packages" + + msg = ( + f"Cannot install {info} because these package versions " + "have conflicting dependencies." + ) + logger.critical(msg) + msg = "\nThe conflict is caused by:" + + relevant_constraints = set() + for req, parent in e.causes: + if req.name in constraints: + relevant_constraints.add(req.name) + msg = msg + "\n " + if parent: + msg = msg + f"{parent.name} {parent.version} depends on " + else: + msg = msg + "The user requested " + msg = msg + req.format_for_error() + for key in relevant_constraints: + spec = constraints[key].specifier + msg += f"\n The user requested (constraint) {key}{spec}" + + msg = ( + msg + + "\n\n" + + "To fix this you could try to:\n" + + "1. loosen the range of package versions you've specified\n" + + "2. remove package versions to allow pip to attempt to solve " + + "the dependency conflict\n" + ) + + logger.info(msg) + + return DistributionNotFound( + "ResolutionImpossible: for help visit " + "https://pip.pypa.io/en/latest/topics/dependency-resolution/" + "#dealing-with-dependency-conflicts" + ) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py new file mode 100644 index 0000000..a1d57e0 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py @@ -0,0 +1,174 @@ +"""Utilities to lazily create and visit candidates found. + +Creating and visiting a candidate is a *very* costly operation. It involves +fetching, extracting, potentially building modules from source, and verifying +distribution metadata. It is therefore crucial for performance to keep +everything here lazy all the way down, so we only touch candidates that we +absolutely need, and not "download the world" when we only need one version of +something. +""" + +import functools +import logging +from collections.abc import Sequence +from typing import TYPE_CHECKING, Any, Callable, Iterator, Optional, Set, Tuple + +from pip._vendor.packaging.version import _BaseVersion + +from pip._internal.exceptions import MetadataInvalid + +from .base import Candidate + +logger = logging.getLogger(__name__) + +IndexCandidateInfo = Tuple[_BaseVersion, Callable[[], Optional[Candidate]]] + +if TYPE_CHECKING: + SequenceCandidate = Sequence[Candidate] +else: + # For compatibility: Python before 3.9 does not support using [] on the + # Sequence class. + # + # >>> from collections.abc import Sequence + # >>> Sequence[str] + # Traceback (most recent call last): + # File "", line 1, in + # TypeError: 'ABCMeta' object is not subscriptable + # + # TODO: Remove this block after dropping Python 3.8 support. + SequenceCandidate = Sequence + + +def _iter_built(infos: Iterator[IndexCandidateInfo]) -> Iterator[Candidate]: + """Iterator for ``FoundCandidates``. + + This iterator is used when the package is not already installed. Candidates + from index come later in their normal ordering. + """ + versions_found: Set[_BaseVersion] = set() + for version, func in infos: + if version in versions_found: + continue + try: + candidate = func() + except MetadataInvalid as e: + logger.warning( + "Ignoring version %s of %s since it has invalid metadata:\n" + "%s\n" + "Please use pip<24.1 if you need to use this version.", + version, + e.ireq.name, + e, + ) + # Mark version as found to avoid trying other candidates with the same + # version, since they most likely have invalid metadata as well. + versions_found.add(version) + else: + if candidate is None: + continue + yield candidate + versions_found.add(version) + + +def _iter_built_with_prepended( + installed: Candidate, infos: Iterator[IndexCandidateInfo] +) -> Iterator[Candidate]: + """Iterator for ``FoundCandidates``. + + This iterator is used when the resolver prefers the already-installed + candidate and NOT to upgrade. The installed candidate is therefore + always yielded first, and candidates from index come later in their + normal ordering, except skipped when the version is already installed. + """ + yield installed + versions_found: Set[_BaseVersion] = {installed.version} + for version, func in infos: + if version in versions_found: + continue + candidate = func() + if candidate is None: + continue + yield candidate + versions_found.add(version) + + +def _iter_built_with_inserted( + installed: Candidate, infos: Iterator[IndexCandidateInfo] +) -> Iterator[Candidate]: + """Iterator for ``FoundCandidates``. + + This iterator is used when the resolver prefers to upgrade an + already-installed package. Candidates from index are returned in their + normal ordering, except replaced when the version is already installed. + + The implementation iterates through and yields other candidates, inserting + the installed candidate exactly once before we start yielding older or + equivalent candidates, or after all other candidates if they are all newer. + """ + versions_found: Set[_BaseVersion] = set() + for version, func in infos: + if version in versions_found: + continue + # If the installed candidate is better, yield it first. + if installed.version >= version: + yield installed + versions_found.add(installed.version) + candidate = func() + if candidate is None: + continue + yield candidate + versions_found.add(version) + + # If the installed candidate is older than all other candidates. + if installed.version not in versions_found: + yield installed + + +class FoundCandidates(SequenceCandidate): + """A lazy sequence to provide candidates to the resolver. + + The intended usage is to return this from `find_matches()` so the resolver + can iterate through the sequence multiple times, but only access the index + page when remote packages are actually needed. This improve performances + when suitable candidates are already installed on disk. + """ + + def __init__( + self, + get_infos: Callable[[], Iterator[IndexCandidateInfo]], + installed: Optional[Candidate], + prefers_installed: bool, + incompatible_ids: Set[int], + ): + self._get_infos = get_infos + self._installed = installed + self._prefers_installed = prefers_installed + self._incompatible_ids = incompatible_ids + + def __getitem__(self, index: Any) -> Any: + # Implemented to satisfy the ABC check. This is not needed by the + # resolver, and should not be used by the provider either (for + # performance reasons). + raise NotImplementedError("don't do this") + + def __iter__(self) -> Iterator[Candidate]: + infos = self._get_infos() + if not self._installed: + iterator = _iter_built(infos) + elif self._prefers_installed: + iterator = _iter_built_with_prepended(self._installed, infos) + else: + iterator = _iter_built_with_inserted(self._installed, infos) + return (c for c in iterator if id(c) not in self._incompatible_ids) + + def __len__(self) -> int: + # Implemented to satisfy the ABC check. This is not needed by the + # resolver, and should not be used by the provider either (for + # performance reasons). + raise NotImplementedError("don't do this") + + @functools.lru_cache(maxsize=1) + def __bool__(self) -> bool: + if self._prefers_installed and self._installed: + return True + return any(self) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py new file mode 100644 index 0000000..fb0dd85 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py @@ -0,0 +1,258 @@ +import collections +import math +from functools import lru_cache +from typing import ( + TYPE_CHECKING, + Dict, + Iterable, + Iterator, + Mapping, + Sequence, + TypeVar, + Union, +) + +from pip._vendor.resolvelib.providers import AbstractProvider + +from .base import Candidate, Constraint, Requirement +from .candidates import REQUIRES_PYTHON_IDENTIFIER +from .factory import Factory + +if TYPE_CHECKING: + from pip._vendor.resolvelib.providers import Preference + from pip._vendor.resolvelib.resolvers import RequirementInformation + + PreferenceInformation = RequirementInformation[Requirement, Candidate] + + _ProviderBase = AbstractProvider[Requirement, Candidate, str] +else: + _ProviderBase = AbstractProvider + +# Notes on the relationship between the provider, the factory, and the +# candidate and requirement classes. +# +# The provider is a direct implementation of the resolvelib class. Its role +# is to deliver the API that resolvelib expects. +# +# Rather than work with completely abstract "requirement" and "candidate" +# concepts as resolvelib does, pip has concrete classes implementing these two +# ideas. The API of Requirement and Candidate objects are defined in the base +# classes, but essentially map fairly directly to the equivalent provider +# methods. In particular, `find_matches` and `is_satisfied_by` are +# requirement methods, and `get_dependencies` is a candidate method. +# +# The factory is the interface to pip's internal mechanisms. It is stateless, +# and is created by the resolver and held as a property of the provider. It is +# responsible for creating Requirement and Candidate objects, and provides +# services to those objects (access to pip's finder and preparer). + + +D = TypeVar("D") +V = TypeVar("V") + + +def _get_with_identifier( + mapping: Mapping[str, V], + identifier: str, + default: D, +) -> Union[D, V]: + """Get item from a package name lookup mapping with a resolver identifier. + + This extra logic is needed when the target mapping is keyed by package + name, which cannot be directly looked up with an identifier (which may + contain requested extras). Additional logic is added to also look up a value + by "cleaning up" the extras from the identifier. + """ + if identifier in mapping: + return mapping[identifier] + # HACK: Theoretically we should check whether this identifier is a valid + # "NAME[EXTRAS]" format, and parse out the name part with packaging or + # some regular expression. But since pip's resolver only spits out three + # kinds of identifiers: normalized PEP 503 names, normalized names plus + # extras, and Requires-Python, we can cheat a bit here. + name, open_bracket, _ = identifier.partition("[") + if open_bracket and name in mapping: + return mapping[name] + return default + + +class PipProvider(_ProviderBase): + """Pip's provider implementation for resolvelib. + + :params constraints: A mapping of constraints specified by the user. Keys + are canonicalized project names. + :params ignore_dependencies: Whether the user specified ``--no-deps``. + :params upgrade_strategy: The user-specified upgrade strategy. + :params user_requested: A set of canonicalized package names that the user + supplied for pip to install/upgrade. + """ + + def __init__( + self, + factory: Factory, + constraints: Dict[str, Constraint], + ignore_dependencies: bool, + upgrade_strategy: str, + user_requested: Dict[str, int], + ) -> None: + self._factory = factory + self._constraints = constraints + self._ignore_dependencies = ignore_dependencies + self._upgrade_strategy = upgrade_strategy + self._user_requested = user_requested + self._known_depths: Dict[str, float] = collections.defaultdict(lambda: math.inf) + + def identify(self, requirement_or_candidate: Union[Requirement, Candidate]) -> str: + return requirement_or_candidate.name + + def get_preference( + self, + identifier: str, + resolutions: Mapping[str, Candidate], + candidates: Mapping[str, Iterator[Candidate]], + information: Mapping[str, Iterable["PreferenceInformation"]], + backtrack_causes: Sequence["PreferenceInformation"], + ) -> "Preference": + """Produce a sort key for given requirement based on preference. + + The lower the return value is, the more preferred this group of + arguments is. + + Currently pip considers the following in order: + + * Prefer if any of the known requirements is "direct", e.g. points to an + explicit URL. + * If equal, prefer if any requirement is "pinned", i.e. contains + operator ``===`` or ``==``. + * If equal, calculate an approximate "depth" and resolve requirements + closer to the user-specified requirements first. If the depth cannot + by determined (eg: due to no matching parents), it is considered + infinite. + * Order user-specified requirements by the order they are specified. + * If equal, prefers "non-free" requirements, i.e. contains at least one + operator, such as ``>=`` or ``<``. + * If equal, order alphabetically for consistency (helps debuggability). + """ + try: + next(iter(information[identifier])) + except StopIteration: + # There is no information for this identifier, so there's no known + # candidates. + has_information = False + else: + has_information = True + + if has_information: + lookups = (r.get_candidate_lookup() for r, _ in information[identifier]) + candidate, ireqs = zip(*lookups) + else: + candidate, ireqs = None, () + + operators = [ + specifier.operator + for specifier_set in (ireq.specifier for ireq in ireqs if ireq) + for specifier in specifier_set + ] + + direct = candidate is not None + pinned = any(op[:2] == "==" for op in operators) + unfree = bool(operators) + + try: + requested_order: Union[int, float] = self._user_requested[identifier] + except KeyError: + requested_order = math.inf + if has_information: + parent_depths = ( + self._known_depths[parent.name] if parent is not None else 0.0 + for _, parent in information[identifier] + ) + inferred_depth = min(d for d in parent_depths) + 1.0 + else: + inferred_depth = math.inf + else: + inferred_depth = 1.0 + self._known_depths[identifier] = inferred_depth + + requested_order = self._user_requested.get(identifier, math.inf) + + # Requires-Python has only one candidate and the check is basically + # free, so we always do it first to avoid needless work if it fails. + requires_python = identifier == REQUIRES_PYTHON_IDENTIFIER + + # Prefer the causes of backtracking on the assumption that the problem + # resolving the dependency tree is related to the failures that caused + # the backtracking + backtrack_cause = self.is_backtrack_cause(identifier, backtrack_causes) + + return ( + not requires_python, + not direct, + not pinned, + not backtrack_cause, + inferred_depth, + requested_order, + not unfree, + identifier, + ) + + def find_matches( + self, + identifier: str, + requirements: Mapping[str, Iterator[Requirement]], + incompatibilities: Mapping[str, Iterator[Candidate]], + ) -> Iterable[Candidate]: + def _eligible_for_upgrade(identifier: str) -> bool: + """Are upgrades allowed for this project? + + This checks the upgrade strategy, and whether the project was one + that the user specified in the command line, in order to decide + whether we should upgrade if there's a newer version available. + + (Note that we don't need access to the `--upgrade` flag, because + an upgrade strategy of "to-satisfy-only" means that `--upgrade` + was not specified). + """ + if self._upgrade_strategy == "eager": + return True + elif self._upgrade_strategy == "only-if-needed": + user_order = _get_with_identifier( + self._user_requested, + identifier, + default=None, + ) + return user_order is not None + return False + + constraint = _get_with_identifier( + self._constraints, + identifier, + default=Constraint.empty(), + ) + return self._factory.find_candidates( + identifier=identifier, + requirements=requirements, + constraint=constraint, + prefers_installed=(not _eligible_for_upgrade(identifier)), + incompatibilities=incompatibilities, + is_satisfied_by=self.is_satisfied_by, + ) + + @lru_cache(maxsize=None) + def is_satisfied_by(self, requirement: Requirement, candidate: Candidate) -> bool: + return requirement.is_satisfied_by(candidate) + + def get_dependencies(self, candidate: Candidate) -> Sequence[Requirement]: + with_requires = not self._ignore_dependencies + return [r for r in candidate.iter_dependencies(with_requires) if r is not None] + + @staticmethod + def is_backtrack_cause( + identifier: str, backtrack_causes: Sequence["PreferenceInformation"] + ) -> bool: + for backtrack_cause in backtrack_causes: + if identifier == backtrack_cause.requirement.name: + return True + if backtrack_cause.parent and identifier == backtrack_cause.parent.name: + return True + return False diff --git a/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py new file mode 100644 index 0000000..0594569 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py @@ -0,0 +1,81 @@ +from collections import defaultdict +from logging import getLogger +from typing import Any, DefaultDict + +from pip._vendor.resolvelib.reporters import BaseReporter + +from .base import Candidate, Requirement + +logger = getLogger(__name__) + + +class PipReporter(BaseReporter): + def __init__(self) -> None: + self.reject_count_by_package: DefaultDict[str, int] = defaultdict(int) + + self._messages_at_reject_count = { + 1: ( + "pip is looking at multiple versions of {package_name} to " + "determine which version is compatible with other " + "requirements. This could take a while." + ), + 8: ( + "pip is still looking at multiple versions of {package_name} to " + "determine which version is compatible with other " + "requirements. This could take a while." + ), + 13: ( + "This is taking longer than usual. You might need to provide " + "the dependency resolver with stricter constraints to reduce " + "runtime. See https://pip.pypa.io/warnings/backtracking for " + "guidance. If you want to abort this run, press Ctrl + C." + ), + } + + def rejecting_candidate(self, criterion: Any, candidate: Candidate) -> None: + self.reject_count_by_package[candidate.name] += 1 + + count = self.reject_count_by_package[candidate.name] + if count not in self._messages_at_reject_count: + return + + message = self._messages_at_reject_count[count] + logger.info("INFO: %s", message.format(package_name=candidate.name)) + + msg = "Will try a different candidate, due to conflict:" + for req_info in criterion.information: + req, parent = req_info.requirement, req_info.parent + # Inspired by Factory.get_installation_error + msg += "\n " + if parent: + msg += f"{parent.name} {parent.version} depends on " + else: + msg += "The user requested " + msg += req.format_for_error() + logger.debug(msg) + + +class PipDebuggingReporter(BaseReporter): + """A reporter that does an info log for every event it sees.""" + + def starting(self) -> None: + logger.info("Reporter.starting()") + + def starting_round(self, index: int) -> None: + logger.info("Reporter.starting_round(%r)", index) + + def ending_round(self, index: int, state: Any) -> None: + logger.info("Reporter.ending_round(%r, state)", index) + logger.debug("Reporter.ending_round(%r, %r)", index, state) + + def ending(self, state: Any) -> None: + logger.info("Reporter.ending(%r)", state) + + def adding_requirement(self, requirement: Requirement, parent: Candidate) -> None: + logger.info("Reporter.adding_requirement(%r, %r)", requirement, parent) + + def rejecting_candidate(self, criterion: Any, candidate: Candidate) -> None: + logger.info("Reporter.rejecting_candidate(%r, %r)", criterion, candidate) + + def pinning(self, candidate: Candidate) -> None: + logger.info("Reporter.pinning(%r)", candidate) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py new file mode 100644 index 0000000..b04f41b --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py @@ -0,0 +1,245 @@ +from typing import Any, Optional + +from pip._vendor.packaging.specifiers import SpecifierSet +from pip._vendor.packaging.utils import NormalizedName, canonicalize_name + +from pip._internal.req.constructors import install_req_drop_extras +from pip._internal.req.req_install import InstallRequirement + +from .base import Candidate, CandidateLookup, Requirement, format_name + + +class ExplicitRequirement(Requirement): + def __init__(self, candidate: Candidate) -> None: + self.candidate = candidate + + def __str__(self) -> str: + return str(self.candidate) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self.candidate!r})" + + def __hash__(self) -> int: + return hash(self.candidate) + + def __eq__(self, other: Any) -> bool: + if not isinstance(other, ExplicitRequirement): + return False + return self.candidate == other.candidate + + @property + def project_name(self) -> NormalizedName: + # No need to canonicalize - the candidate did this + return self.candidate.project_name + + @property + def name(self) -> str: + # No need to canonicalize - the candidate did this + return self.candidate.name + + def format_for_error(self) -> str: + return self.candidate.format_for_error() + + def get_candidate_lookup(self) -> CandidateLookup: + return self.candidate, None + + def is_satisfied_by(self, candidate: Candidate) -> bool: + return candidate == self.candidate + + +class SpecifierRequirement(Requirement): + def __init__(self, ireq: InstallRequirement) -> None: + assert ireq.link is None, "This is a link, not a specifier" + self._ireq = ireq + self._equal_cache: Optional[str] = None + self._hash: Optional[int] = None + self._extras = frozenset(canonicalize_name(e) for e in self._ireq.extras) + + @property + def _equal(self) -> str: + if self._equal_cache is not None: + return self._equal_cache + + self._equal_cache = str(self._ireq) + return self._equal_cache + + def __str__(self) -> str: + return str(self._ireq.req) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({str(self._ireq.req)!r})" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, SpecifierRequirement): + return NotImplemented + return self._equal == other._equal + + def __hash__(self) -> int: + if self._hash is not None: + return self._hash + + self._hash = hash(self._equal) + return self._hash + + @property + def project_name(self) -> NormalizedName: + assert self._ireq.req, "Specifier-backed ireq is always PEP 508" + return canonicalize_name(self._ireq.req.name) + + @property + def name(self) -> str: + return format_name(self.project_name, self._extras) + + def format_for_error(self) -> str: + # Convert comma-separated specifiers into "A, B, ..., F and G" + # This makes the specifier a bit more "human readable", without + # risking a change in meaning. (Hopefully! Not all edge cases have + # been checked) + parts = [s.strip() for s in str(self).split(",")] + if len(parts) == 0: + return "" + elif len(parts) == 1: + return parts[0] + + return ", ".join(parts[:-1]) + " and " + parts[-1] + + def get_candidate_lookup(self) -> CandidateLookup: + return None, self._ireq + + def is_satisfied_by(self, candidate: Candidate) -> bool: + assert candidate.name == self.name, ( + f"Internal issue: Candidate is not for this requirement " + f"{candidate.name} vs {self.name}" + ) + # We can safely always allow prereleases here since PackageFinder + # already implements the prerelease logic, and would have filtered out + # prerelease candidates if the user does not expect them. + assert self._ireq.req, "Specifier-backed ireq is always PEP 508" + spec = self._ireq.req.specifier + return spec.contains(candidate.version, prereleases=True) + + +class SpecifierWithoutExtrasRequirement(SpecifierRequirement): + """ + Requirement backed by an install requirement on a base package. + Trims extras from its install requirement if there are any. + """ + + def __init__(self, ireq: InstallRequirement) -> None: + assert ireq.link is None, "This is a link, not a specifier" + self._ireq = install_req_drop_extras(ireq) + self._equal_cache: Optional[str] = None + self._hash: Optional[int] = None + self._extras = frozenset(canonicalize_name(e) for e in self._ireq.extras) + + @property + def _equal(self) -> str: + if self._equal_cache is not None: + return self._equal_cache + + self._equal_cache = str(self._ireq) + return self._equal_cache + + def __eq__(self, other: object) -> bool: + if not isinstance(other, SpecifierWithoutExtrasRequirement): + return NotImplemented + return self._equal == other._equal + + def __hash__(self) -> int: + if self._hash is not None: + return self._hash + + self._hash = hash(self._equal) + return self._hash + + +class RequiresPythonRequirement(Requirement): + """A requirement representing Requires-Python metadata.""" + + def __init__(self, specifier: SpecifierSet, match: Candidate) -> None: + self.specifier = specifier + self._specifier_string = str(specifier) # for faster __eq__ + self._hash: Optional[int] = None + self._candidate = match + + def __str__(self) -> str: + return f"Python {self.specifier}" + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({str(self.specifier)!r})" + + def __hash__(self) -> int: + if self._hash is not None: + return self._hash + + self._hash = hash((self._specifier_string, self._candidate)) + return self._hash + + def __eq__(self, other: Any) -> bool: + if not isinstance(other, RequiresPythonRequirement): + return False + return ( + self._specifier_string == other._specifier_string + and self._candidate == other._candidate + ) + + @property + def project_name(self) -> NormalizedName: + return self._candidate.project_name + + @property + def name(self) -> str: + return self._candidate.name + + def format_for_error(self) -> str: + return str(self) + + def get_candidate_lookup(self) -> CandidateLookup: + if self.specifier.contains(self._candidate.version, prereleases=True): + return self._candidate, None + return None, None + + def is_satisfied_by(self, candidate: Candidate) -> bool: + assert candidate.name == self._candidate.name, "Not Python candidate" + # We can safely always allow prereleases here since PackageFinder + # already implements the prerelease logic, and would have filtered out + # prerelease candidates if the user does not expect them. + return self.specifier.contains(candidate.version, prereleases=True) + + +class UnsatisfiableRequirement(Requirement): + """A requirement that cannot be satisfied.""" + + def __init__(self, name: NormalizedName) -> None: + self._name = name + + def __str__(self) -> str: + return f"{self._name} (unavailable)" + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({str(self._name)!r})" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, UnsatisfiableRequirement): + return NotImplemented + return self._name == other._name + + def __hash__(self) -> int: + return hash(self._name) + + @property + def project_name(self) -> NormalizedName: + return self._name + + @property + def name(self) -> str: + return self._name + + def format_for_error(self) -> str: + return str(self) + + def get_candidate_lookup(self) -> CandidateLookup: + return None, None + + def is_satisfied_by(self, candidate: Candidate) -> bool: + return False diff --git a/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py new file mode 100644 index 0000000..c12beef --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py @@ -0,0 +1,317 @@ +import contextlib +import functools +import logging +import os +from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple, cast + +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.resolvelib import BaseReporter, ResolutionImpossible +from pip._vendor.resolvelib import Resolver as RLResolver +from pip._vendor.resolvelib.structs import DirectedGraph + +from pip._internal.cache import WheelCache +from pip._internal.index.package_finder import PackageFinder +from pip._internal.operations.prepare import RequirementPreparer +from pip._internal.req.constructors import install_req_extend_extras +from pip._internal.req.req_install import InstallRequirement +from pip._internal.req.req_set import RequirementSet +from pip._internal.resolution.base import BaseResolver, InstallRequirementProvider +from pip._internal.resolution.resolvelib.provider import PipProvider +from pip._internal.resolution.resolvelib.reporter import ( + PipDebuggingReporter, + PipReporter, +) +from pip._internal.utils.packaging import get_requirement + +from .base import Candidate, Requirement +from .factory import Factory + +if TYPE_CHECKING: + from pip._vendor.resolvelib.resolvers import Result as RLResult + + Result = RLResult[Requirement, Candidate, str] + + +logger = logging.getLogger(__name__) + + +class Resolver(BaseResolver): + _allowed_strategies = {"eager", "only-if-needed", "to-satisfy-only"} + + def __init__( + self, + preparer: RequirementPreparer, + finder: PackageFinder, + wheel_cache: Optional[WheelCache], + make_install_req: InstallRequirementProvider, + use_user_site: bool, + ignore_dependencies: bool, + ignore_installed: bool, + ignore_requires_python: bool, + force_reinstall: bool, + upgrade_strategy: str, + py_version_info: Optional[Tuple[int, ...]] = None, + ): + super().__init__() + assert upgrade_strategy in self._allowed_strategies + + self.factory = Factory( + finder=finder, + preparer=preparer, + make_install_req=make_install_req, + wheel_cache=wheel_cache, + use_user_site=use_user_site, + force_reinstall=force_reinstall, + ignore_installed=ignore_installed, + ignore_requires_python=ignore_requires_python, + py_version_info=py_version_info, + ) + self.ignore_dependencies = ignore_dependencies + self.upgrade_strategy = upgrade_strategy + self._result: Optional[Result] = None + + def resolve( + self, root_reqs: List[InstallRequirement], check_supported_wheels: bool + ) -> RequirementSet: + collected = self.factory.collect_root_requirements(root_reqs) + provider = PipProvider( + factory=self.factory, + constraints=collected.constraints, + ignore_dependencies=self.ignore_dependencies, + upgrade_strategy=self.upgrade_strategy, + user_requested=collected.user_requested, + ) + if "PIP_RESOLVER_DEBUG" in os.environ: + reporter: BaseReporter = PipDebuggingReporter() + else: + reporter = PipReporter() + resolver: RLResolver[Requirement, Candidate, str] = RLResolver( + provider, + reporter, + ) + + try: + limit_how_complex_resolution_can_be = 200000 + result = self._result = resolver.resolve( + collected.requirements, max_rounds=limit_how_complex_resolution_can_be + ) + + except ResolutionImpossible as e: + error = self.factory.get_installation_error( + cast("ResolutionImpossible[Requirement, Candidate]", e), + collected.constraints, + ) + raise error from e + + req_set = RequirementSet(check_supported_wheels=check_supported_wheels) + # process candidates with extras last to ensure their base equivalent is + # already in the req_set if appropriate. + # Python's sort is stable so using a binary key function keeps relative order + # within both subsets. + for candidate in sorted( + result.mapping.values(), key=lambda c: c.name != c.project_name + ): + ireq = candidate.get_install_requirement() + if ireq is None: + if candidate.name != candidate.project_name: + # extend existing req's extras + with contextlib.suppress(KeyError): + req = req_set.get_requirement(candidate.project_name) + req_set.add_named_requirement( + install_req_extend_extras( + req, get_requirement(candidate.name).extras + ) + ) + continue + + # Check if there is already an installation under the same name, + # and set a flag for later stages to uninstall it, if needed. + installed_dist = self.factory.get_dist_to_uninstall(candidate) + if installed_dist is None: + # There is no existing installation -- nothing to uninstall. + ireq.should_reinstall = False + elif self.factory.force_reinstall: + # The --force-reinstall flag is set -- reinstall. + ireq.should_reinstall = True + elif installed_dist.version != candidate.version: + # The installation is different in version -- reinstall. + ireq.should_reinstall = True + elif candidate.is_editable or installed_dist.editable: + # The incoming distribution is editable, or different in + # editable-ness to installation -- reinstall. + ireq.should_reinstall = True + elif candidate.source_link and candidate.source_link.is_file: + # The incoming distribution is under file:// + if candidate.source_link.is_wheel: + # is a local wheel -- do nothing. + logger.info( + "%s is already installed with the same version as the " + "provided wheel. Use --force-reinstall to force an " + "installation of the wheel.", + ireq.name, + ) + continue + + # is a local sdist or path -- reinstall + ireq.should_reinstall = True + else: + continue + + link = candidate.source_link + if link and link.is_yanked: + # The reason can contain non-ASCII characters, Unicode + # is required for Python 2. + msg = ( + "The candidate selected for download or install is a " + "yanked version: {name!r} candidate (version {version} " + "at {link})\nReason for being yanked: {reason}" + ).format( + name=candidate.name, + version=candidate.version, + link=link, + reason=link.yanked_reason or "", + ) + logger.warning(msg) + + req_set.add_named_requirement(ireq) + + reqs = req_set.all_requirements + self.factory.preparer.prepare_linked_requirements_more(reqs) + for req in reqs: + req.prepared = True + req.needs_more_preparation = False + return req_set + + def get_installation_order( + self, req_set: RequirementSet + ) -> List[InstallRequirement]: + """Get order for installation of requirements in RequirementSet. + + The returned list contains a requirement before another that depends on + it. This helps ensure that the environment is kept consistent as they + get installed one-by-one. + + The current implementation creates a topological ordering of the + dependency graph, giving more weight to packages with less + or no dependencies, while breaking any cycles in the graph at + arbitrary points. We make no guarantees about where the cycle + would be broken, other than it *would* be broken. + """ + assert self._result is not None, "must call resolve() first" + + if not req_set.requirements: + # Nothing is left to install, so we do not need an order. + return [] + + graph = self._result.graph + weights = get_topological_weights(graph, set(req_set.requirements.keys())) + + sorted_items = sorted( + req_set.requirements.items(), + key=functools.partial(_req_set_item_sorter, weights=weights), + reverse=True, + ) + return [ireq for _, ireq in sorted_items] + + +def get_topological_weights( + graph: "DirectedGraph[Optional[str]]", requirement_keys: Set[str] +) -> Dict[Optional[str], int]: + """Assign weights to each node based on how "deep" they are. + + This implementation may change at any point in the future without prior + notice. + + We first simplify the dependency graph by pruning any leaves and giving them + the highest weight: a package without any dependencies should be installed + first. This is done again and again in the same way, giving ever less weight + to the newly found leaves. The loop stops when no leaves are left: all + remaining packages have at least one dependency left in the graph. + + Then we continue with the remaining graph, by taking the length for the + longest path to any node from root, ignoring any paths that contain a single + node twice (i.e. cycles). This is done through a depth-first search through + the graph, while keeping track of the path to the node. + + Cycles in the graph result would result in node being revisited while also + being on its own path. In this case, take no action. This helps ensure we + don't get stuck in a cycle. + + When assigning weight, the longer path (i.e. larger length) is preferred. + + We are only interested in the weights of packages that are in the + requirement_keys. + """ + path: Set[Optional[str]] = set() + weights: Dict[Optional[str], int] = {} + + def visit(node: Optional[str]) -> None: + if node in path: + # We hit a cycle, so we'll break it here. + return + + # Time to visit the children! + path.add(node) + for child in graph.iter_children(node): + visit(child) + path.remove(node) + + if node not in requirement_keys: + return + + last_known_parent_count = weights.get(node, 0) + weights[node] = max(last_known_parent_count, len(path)) + + # Simplify the graph, pruning leaves that have no dependencies. + # This is needed for large graphs (say over 200 packages) because the + # `visit` function is exponentially slower then, taking minutes. + # See https://github.com/pypa/pip/issues/10557 + # We will loop until we explicitly break the loop. + while True: + leaves = set() + for key in graph: + if key is None: + continue + for _child in graph.iter_children(key): + # This means we have at least one child + break + else: + # No child. + leaves.add(key) + if not leaves: + # We are done simplifying. + break + # Calculate the weight for the leaves. + weight = len(graph) - 1 + for leaf in leaves: + if leaf not in requirement_keys: + continue + weights[leaf] = weight + # Remove the leaves from the graph, making it simpler. + for leaf in leaves: + graph.remove(leaf) + + # Visit the remaining graph. + # `None` is guaranteed to be the root node by resolvelib. + visit(None) + + # Sanity check: all requirement keys should be in the weights, + # and no other keys should be in the weights. + difference = set(weights.keys()).difference(requirement_keys) + assert not difference, difference + + return weights + + +def _req_set_item_sorter( + item: Tuple[str, InstallRequirement], + weights: Dict[Optional[str], int], +) -> Tuple[int, str]: + """Key function used to sort install requirements for installation. + + Based on the "weight" mapping calculated in ``get_installation_order()``. + The canonical package name is returned as the second member as a tie- + breaker to ensure the result is predictable, which is useful in tests. + """ + name = canonicalize_name(item[0]) + return weights[name], name diff --git a/backend/.venv/Lib/site-packages/pip/_internal/self_outdated_check.py b/backend/.venv/Lib/site-packages/pip/_internal/self_outdated_check.py new file mode 100644 index 0000000..f9a91af --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/self_outdated_check.py @@ -0,0 +1,244 @@ +import datetime +import functools +import hashlib +import json +import logging +import optparse +import os.path +import sys +from dataclasses import dataclass +from typing import Any, Callable, Dict, Optional + +from pip._vendor.packaging.version import Version +from pip._vendor.packaging.version import parse as parse_version +from pip._vendor.rich.console import Group +from pip._vendor.rich.markup import escape +from pip._vendor.rich.text import Text + +from pip._internal.index.collector import LinkCollector +from pip._internal.index.package_finder import PackageFinder +from pip._internal.metadata import get_default_environment +from pip._internal.models.selection_prefs import SelectionPreferences +from pip._internal.network.session import PipSession +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.entrypoints import ( + get_best_invocation_for_this_pip, + get_best_invocation_for_this_python, +) +from pip._internal.utils.filesystem import adjacent_tmp_file, check_path_owner, replace +from pip._internal.utils.misc import ensure_dir + +_WEEK = datetime.timedelta(days=7) + +logger = logging.getLogger(__name__) + + +def _get_statefile_name(key: str) -> str: + key_bytes = key.encode() + name = hashlib.sha224(key_bytes).hexdigest() + return name + + +def _convert_date(isodate: str) -> datetime.datetime: + """Convert an ISO format string to a date. + + Handles the format 2020-01-22T14:24:01Z (trailing Z) + which is not supported by older versions of fromisoformat. + """ + return datetime.datetime.fromisoformat(isodate.replace("Z", "+00:00")) + + +class SelfCheckState: + def __init__(self, cache_dir: str) -> None: + self._state: Dict[str, Any] = {} + self._statefile_path = None + + # Try to load the existing state + if cache_dir: + self._statefile_path = os.path.join( + cache_dir, "selfcheck", _get_statefile_name(self.key) + ) + try: + with open(self._statefile_path, encoding="utf-8") as statefile: + self._state = json.load(statefile) + except (OSError, ValueError, KeyError): + # Explicitly suppressing exceptions, since we don't want to + # error out if the cache file is invalid. + pass + + @property + def key(self) -> str: + return sys.prefix + + def get(self, current_time: datetime.datetime) -> Optional[str]: + """Check if we have a not-outdated version loaded already.""" + if not self._state: + return None + + if "last_check" not in self._state: + return None + + if "pypi_version" not in self._state: + return None + + # Determine if we need to refresh the state + last_check = _convert_date(self._state["last_check"]) + time_since_last_check = current_time - last_check + if time_since_last_check > _WEEK: + return None + + return self._state["pypi_version"] + + def set(self, pypi_version: str, current_time: datetime.datetime) -> None: + # If we do not have a path to cache in, don't bother saving. + if not self._statefile_path: + return + + # Check to make sure that we own the directory + if not check_path_owner(os.path.dirname(self._statefile_path)): + return + + # Now that we've ensured the directory is owned by this user, we'll go + # ahead and make sure that all our directories are created. + ensure_dir(os.path.dirname(self._statefile_path)) + + state = { + # Include the key so it's easy to tell which pip wrote the + # file. + "key": self.key, + "last_check": current_time.isoformat(), + "pypi_version": pypi_version, + } + + text = json.dumps(state, sort_keys=True, separators=(",", ":")) + + with adjacent_tmp_file(self._statefile_path) as f: + f.write(text.encode()) + + try: + # Since we have a prefix-specific state file, we can just + # overwrite whatever is there, no need to check. + replace(f.name, self._statefile_path) + except OSError: + # Best effort. + pass + + +@dataclass +class UpgradePrompt: + old: str + new: str + + def __rich__(self) -> Group: + if WINDOWS: + pip_cmd = f"{get_best_invocation_for_this_python()} -m pip" + else: + pip_cmd = get_best_invocation_for_this_pip() + + notice = "[bold][[reset][blue]notice[reset][bold]][reset]" + return Group( + Text(), + Text.from_markup( + f"{notice} A new release of pip is available: " + f"[red]{self.old}[reset] -> [green]{self.new}[reset]" + ), + Text.from_markup( + f"{notice} To update, run: " + f"[green]{escape(pip_cmd)} install --upgrade pip" + ), + ) + + +def was_installed_by_pip(pkg: str) -> bool: + """Checks whether pkg was installed by pip + + This is used not to display the upgrade message when pip is in fact + installed by system package manager, such as dnf on Fedora. + """ + dist = get_default_environment().get_distribution(pkg) + return dist is not None and "pip" == dist.installer + + +def _get_current_remote_pip_version( + session: PipSession, options: optparse.Values +) -> Optional[str]: + # Lets use PackageFinder to see what the latest pip version is + link_collector = LinkCollector.create( + session, + options=options, + suppress_no_index=True, + ) + + # Pass allow_yanked=False so we don't suggest upgrading to a + # yanked version. + selection_prefs = SelectionPreferences( + allow_yanked=False, + allow_all_prereleases=False, # Explicitly set to False + ) + + finder = PackageFinder.create( + link_collector=link_collector, + selection_prefs=selection_prefs, + ) + best_candidate = finder.find_best_candidate("pip").best_candidate + if best_candidate is None: + return None + + return str(best_candidate.version) + + +def _self_version_check_logic( + *, + state: SelfCheckState, + current_time: datetime.datetime, + local_version: Version, + get_remote_version: Callable[[], Optional[str]], +) -> Optional[UpgradePrompt]: + remote_version_str = state.get(current_time) + if remote_version_str is None: + remote_version_str = get_remote_version() + if remote_version_str is None: + logger.debug("No remote pip version found") + return None + state.set(remote_version_str, current_time) + + remote_version = parse_version(remote_version_str) + logger.debug("Remote version of pip: %s", remote_version) + logger.debug("Local version of pip: %s", local_version) + + pip_installed_by_pip = was_installed_by_pip("pip") + logger.debug("Was pip installed by pip? %s", pip_installed_by_pip) + if not pip_installed_by_pip: + return None # Only suggest upgrade if pip is installed by pip. + + local_version_is_older = ( + local_version < remote_version + and local_version.base_version != remote_version.base_version + ) + if local_version_is_older: + return UpgradePrompt(old=str(local_version), new=remote_version_str) + + return None + + +def pip_self_version_check(session: PipSession, options: optparse.Values) -> None: + """Check for an update for pip. + + Limit the frequency of checks to once per week. State is stored either in + the active virtualenv or in the user's USER_CACHE_DIR keyed off the prefix + of the pip script path. + """ + installed_dist = get_default_environment().get_distribution("pip") + if not installed_dist: + return + + upgrade_prompt = _self_version_check_logic( + state=SelfCheckState(cache_dir=options.cache_dir), + current_time=datetime.datetime.now(datetime.timezone.utc), + local_version=installed_dist.version, + get_remote_version=functools.partial( + _get_current_remote_pip_version, session, options + ), + ) + if upgrade_prompt is not None: + logger.warning("%s", upgrade_prompt, extra={"rich": True}) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/__init__.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e468d32299de0ee2877c50a9eb8791f1244d2b4b GIT binary patch literal 194 zcmX@j%ge<81isO>nIQTxh(HIQS%4zb87dhx8U0o=6fpsLpFwJVB|2Nhl;;;^7Z)TZ zr^e)El@#kHCMV~Y=9OgTrRyf=7p2A|B_?O5=B32wm8IsD#rR|<#S~|jr0N1SWGAMl z7RMB17U;)k=9Q!t7&-6`mz2TUuKFiEBG{;AAWrm8jAb5EMPcjT~B}BE}RckW^gRbm-;oN?dul zyO>>Crr;z-kVB0Gumcp44?Uzni#BkI_LyrxBVxUej>7I62fDfp6b>wHBMn(ih7^IDKl)l$v$O}^Bl*M!L(H{gE5 z^IYFFc;ND?$s06WwSt=E@XMa%B`TH^n8MNQ%L(3=0Zz4M+8*iYiF;iApQUXuGQ~sOq%qHL--KyrTK8!wU&M z?Yi}kmjekoX`z!D^y@4LFCK^`|;y-|l_8l?(fvTWcz9@I=eQtWVy#7GISgA<56 zt#y}rVL)U8VaarhgGjd<2H8N#LQ%4#kufHSsj1TVA7T zTYfFh4U0rq8v!VNnv^)l$&X1_sJ?02B%zZh{nkku(gJLtzXOrfyIR90=%)qJ>QX~E zP}$CR!v$ngY$lDl zOl~^6kjms<=4Zi|%a?dIGnXkrXerN0VMkOZ4ZayZmo7}tLUQtKCYvcO#?_fjDMvDA z@&%sc^T|RfGrf>a7Wn)^VLo3>LwyQjbD7*s0b0^?>0BuRt(fEKSMkD&v&n3hRH?}Y zSYIIf_;h}Lv5nXVb7Oc{ZDFtAbP0*<@xe&Qr;`YAy8JO5nE6uCr^3 zcuK)@rJqWYGBllTli0(GEEdYOl+l>dQjtg^@M%lpEsRa&6Epv(IsHO;)fHEKPt(n^ zvl95HG+lQa$U0~FlL)~c3$D=<%i;fl6w`eihO$zC&|u28pQ01D{q;BAd*cIrsmRn4{x)G?>sjxEGAbkUixOD zi(^Z!I~M0-RZWat>N4z@{AOk%D?7ybzcQ8`$vO&N60pWcb+=9};R%xZ7XO5u!Z~m4ny6RB?Ty4GyBQm*lZLiQUa*Mh)%VRF*Erqw;{ zS!kSuGD`lj_6{BU77A(0T8NJdiV6@O@=#OdF@WHfxXYp{6Rx$V-zjknEHB~bKaJZB zw)r&Mv;WrA&8a&lH=@sdpxlp++>4An4mf4gD1KXi#qAtZc4QrjS0@8sM<`P4QiieD zmFvn1h3RY8c3%+B53%d`G%>=**ptd+HwU-N<+h$RNc|2Ply{%MuDq|TD++t}T!b}4 zqinn6o@64TutoUN46U+j;YGHp{5HI*#3I^j09K;>ii@*myWZlcg;vzS`3UD=jR!)r zu&|8u(69J5lA$lyvhuEg7r7+4lmgv(X+p1(|KH{HEM41K zD`6rEG-{)?FDF0IaHLClBNLwUJ-KXu(d3%>1cq~1{Ni65_^IhEj!M;SFNwDDqw-3E@ z?ne64{fB-UdARqfTlJguJE=eKJ+T=I4u@{2+Cy%V1^W%x*I|KZIrp8xXcjQG|_@|5zc z=aR=mpF|E|_{rhjbU!|noEZ4z`(YZ#6dF&^I2LW~u2k?PSgEvzZ|%CScwMR`dQJhLf>pAYU)Mz@}QRyip3{|DTZ(J}x4 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/_log.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/_log.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b52698efa07cd3068d679e5a4c402cdf69733e1d GIT binary patch literal 1865 zcmZux&1>976rYi_tF?BW?MGUtZoor(vB2I03Qj0ZA#vQa;A|kFp=`G(vSz%Nt(DxF zSvxj9_>e<;X;UaT2Omu7p=~JS*#DuIxM^?^g&x{VZVqcG^wjsH)#igd(0flaZ$92{ z-tYZ7I_eOR%b%VL|1}Bu8-EHZ4V?ZWI6H)s7U7f|5p7YhW@L2Dmf5vh7A4$jl?-x; z@X{^9%YrV~icOx_yRbh>%jUMI@QSb(Ek1I~YK`zJcfdLuhFjbGX||_y(hWBSi;_+! zj605VQ7neBP%Ox%vT-3<5cx{6#Y8f_B-jm%7P7G>0$=Gzbr=e8ypYPk=}&^QLj(czNXy`~WpYDU+!Q5l!B^tt#R|6phw?_*t)!#Z z^F;E)Hb2Q>VfpVA;|K|W!+bW#7;iWoi8T>94geEWj(i2=$?$5fl*`u7Rv#%>z@U+LkzM-mce^o^l;4< z?HF6ecl76SNVd%H=~wg`acPDZTs5@^7j&)EQX*QEh?E>bg*B-xP?*PmpUuA8UQgtT zTJ;0bj+eEX_Jbhl#TxRT4&dS13x2R7V%~<=kJsAs;X+%5T1>-&6~7}?do^4=<%O{p zGWMfWJsn2s6jnoHbtAP0_-(%S4B|y0y^eR80JTm2sE>W2zrOk9&0Tx%)%*3CJ^fpK z=7+WY`po^xOdmpsYo`^@i~X+fywvf$yo|uFdEVzeKN`%~p2w2_hE1iVL|(|3LH$VN zE9k$3$}SZCDJ-5_12lGvEeQM!>vI=fMK^0O4 z2T$#P2x^Du;oOtQ(*^sh2D#h(pc4*a9UtR z33NJh^Y&HI2^G}j3vfY_76b+mSjKB;V@QZ=OGz)np7nz6h5Zb=R>FpWO}bOrs<0s% zEQ}dYp)sUF!vhx@qnCxqV{p-?Tas^rO^>Of)6HU|&0nPEb3Ttfriq1x@$v+!Vcn*+ zr#r1=Fp1<*Z-Lq-M>SHa9a!W0*7)wZ-!1n~t9oFa*tbsXj_tV*t*LAu*T^ci=~g9@ zFTYJ$Z>&OP*)oR1Sv4^9p1WA(y_}8j%eP?`>qngjb!bvb9~&iV z^^Xx+|BIYFtdQ#HwtZB#>6zP?cADQbj|jMj#|?V+_Us`6bLVm&&5>i%>Fmz`1Jkv{ A%K!iX literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..94d21b3d21ba2450adf36389301a9c9b8681325a GIT binary patch literal 2409 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..54f8bd0a3c90cb82f57d0784bb37d30d45777c94 GIT binary patch literal 6349 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/datetime.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/datetime.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..58ff1f7a6d18065adf9ac5e3ec115d52d9dbca02 GIT binary patch literal 683 zcmZuvzi$&U6t?etNmMSVQW?tBLog7bBrIJJ?b4QsbYTl8ot(2tF1gr|&q)+?l`^n& zf~_4pg1RvBKd^v0AXyAZOl*NLG4XsPLP9+0z3=_-^ZWed_tokK0%<+nOMU=;wZU2{ zD`$BZoHN8w8!^nB6t^*Rxx)yk2U_CpvkEJ}AZ;>pYL(}WM^XjT9v8tV83j`+bQWkC z#62Dl0^Q>QqnZbBMkhnw*!X7092+v@R2gq5h3*-b(U~bJuE$Em?uv&657frX379ja z!TyoHv-bXC-=6+QE?4o1tMR(@zup|>ICm~rvrkCw=45b)&=XX{$2Hef>?7<046&Z^ zv;@vIPuUJdtg+LTU9a)F$%Ko{CITzJ=)r?uQ&5#4$$6%RW! z9&o|J26Rrs$4Mv563y$-FrZzYg|ORZlnBk0plNfglQe6tIW{Co4GFV{9-?Vj#^Alpmm zK{d~mqln2kij@5z#sv?E>B&6!7lwr%e_&{ssgsrK$h` literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5de5f10c95720c0d3f07f76b4b700ffae602eedc GIT binary patch literal 4190 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 XP13`wC$1lB2b_FCPjdb{U+w<|{fSPa literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..47b6811962dfe087aa81c57ad387003ffcc86bf7 GIT binary patch literal 3535 zcma)8U2Gf25#Hk+$>Z@Tk`hIcvi@R;PAS(C9oY$B#ED}&1?(hJQ@d?I3pr4{m2?t$ z$L<~FS|$@A2vGSYk=h5z2ns7efF!UUl&8Gru|QwQNCoMG3v4^L@9R3-Y4J0F($)GHgWEjdjGL9^p zWV2k7%Q}F4-Xq z)|{K=WG~G99wY~3ALe15!M-S*FL&SoXmGQOb5kKWZTyyGOgFIBn)`QYoid=uy{o8;K)tz?F)taKlqVUOvP)^* z6l6=4E}5K~%3{++u#qQf+Cfik3>Q!q{trKc)eTfY3yi(hqE8zvg9?nyEW@nmm_tR@ zpqkbIJ(nPa(sdQ>Rk3w zuhq3veeSTen?Ao|`P{~fy3L>QBVgNUQSyF)UFd4fZSMcK@U-zd3{uaZdXtcC-@b|N zxQ#wxPQ6Xo)@xBR(B5;I1K-=o(;R8}T3|^}!67?k*8;7C6QjV|l2oe^Q^y??cP}Sy zXzCIs#!zagSqMXh2Gg998zT4*dC2iBR*fOuAc{ISw#*J)8#0;mCUb4sr{`ztHK36P zS50QvWX{EXCcl)*D00fcrl9DGsv9XajZIF0iXv`sfY66FSz0!pw3f{(hNQ@ZX1B@B zr}TN#mCEI?DifOArg;1ilUvXfHO>()wL=rp^d584^vsgf9CcUMsl6c>|6ROsW%|BG z7WG^zji=QGL%)zpr?tFlz|`ZUC1 zTvAj66F`vhyrE?D@mBFm^Ei{kL?6pNFk{D-Q@WJHxl5N4Qe%i7 z(toksfAJsUEC2FGH%Fh0KOWzHZO=bZ;wMV}i4$hr!HRp}NB2OL4_5d{nU8D^esiUA z{(2eyqSyEM8_(PUs-kb+dGf*I54M!u{zSPaQRWlWhj57tA3{u!Dd<|Bq%jR!`Z!oN zq4YXPZ6Kq$cf3&TR5zT|79BFP?XXw3S-Vsr{kh4zv^8K^F;X)b9Cr{}Xrvo{;w+*1 zgg%m$hjE6y1iVhq93lhoYxW#_Ye;R$wnIj!4E*c#nOD%hH?%MIYzn*L@V+m!Dew7) zkDRRNsv*|tB2;kFC4HY_=dZne9> zH0?sSI5`T8ZKLQm{Pu2vGlET?UFfv=7A?Rj+sxBOl)$?tF1KVL1seNzsQ*2!9hBrJRn)nPq6 zhYhKLrxL9S9TJ#+8Z~H$?gR8w+fquErBvRSH$!ygzGBR4c|)=>+!U#-?L)mDt^Q%* ze)sXd(9-dPGx(2+PQjf5NWF=8XkU@&H=5*)5A|5?uVn5aH1Se z?1a8Q^WB-<@YPlCGk!&skae6B%KX_?w&WY!3LfxC zJbNIb(7BQrD|N-HkpC@vSqZt_!O- zUo_RXHL@3cxs5do6yuJ`U&T93m+>G6Z%JtNnuE}Z$C{mZEUU>lqmQ*BZ#`^1Qz*V! zpBrYht&;UT6im&?i~Cl4AA^L{E%Y~oFK#z8orNzVtC3rHZ*nu5ma*RZTV(lPPYeEa za5A64Z;&_OEZRME1Ab~O!!Xa$nSZ0ZyXfw7H2NGRo}-s)t`O6+qtpUzF{HQjBCepNJ%Y#e#88pIbaivP!&3A7VR6^y7TzGI)8i8qCYu1j+`K4dG$XT CcLf6g literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..16fe6764e69104fbd22eb6232e104fd73f86285c GIT binary patch literal 3205 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 GPxc?6wd|b$ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a1bbe2030d0a6b3fd7322e2b43c08be17224d50e GIT binary patch literal 3992 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..40666e8efa1af401085ed5ee03f3b6f5698fb191 GIT binary patch literal 7328 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 K{V68KhWP*t8gKEMfEbjpgfer2#Gs^= zm?GLrYN;MP72_h}%Zw)W`1)esF|Dr$Pg5L;NC>I!i)D&R?U*HztQnLpb5{Q&PLt|c zB^M6P+71fpRV3SP*~1khusv55zmo`{z=$u@stzJX(yuypfVP8>Q@7R}g$a{tU|_Wr zP7ow0g=!>S)h6`(N+G|vJb!(0S>eM(OxX@8<3KuL7bHe1_Bvt3h|(+Cp-4gx?P?@x z^EVEm3fm1`jqf{<29Bh{m8C;8g@-cAJSbc(RA-G67d2A|9tnr>#l7< zI+JzE>RGS5=lk#;4E|0XYyu4HOr2G@@cdGoQ7+&bX=YizOY68R+rDhbrsw*$g)p*Y zgPdL2z~-90iR3crzWSXeFU%?|ruRm?<82`v<*qEv%+24*A9|a@;1p%BWDY+0i9nWr zmu4;$w>-SzR}B*t-Sxm9GfdN~xqJxk{szE{O3e;SP0<{214$a0N{ylVC-{lsF7(8pKC}>zG?29 zZLU4b?16I~Mi^!q>BqI^^3F(e<;lZ+AV8)gfzdNBFMk-mc$9vzJv@CBnQjk^?7FRi h$u|#L1Npb<*1*jVAlDIinB5ua0HStBe^M3K{0C^qICB61 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4361e90364fb282d217f160def0ab451f4dbd060 GIT binary patch literal 2418 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 ZT{&W;A2$5B^P^THpBzUoYUD!T-vISjka++A literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/misc.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/misc.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3268a48480d5d83dab79a0f9d105d7e12aba2e5c GIT binary patch literal 33450 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 U2u-Sa*F%mX4`ZfPyvF|he>BgWr~m)} literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fa9cf4a55a5e9c8e27fa19e9f95e9825fee4195f GIT binary patch literal 2582 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 bz_rv;=h7=n-PhZf+w*tL;fE$TtL^^*IHwKV literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..198ac12bc35c8ce6d922399a7c34e856a174df85 GIT binary patch literal 4549 zcmaJ_&2JmW72hS7 z%q}HMr2)AO3OSd`C#yI2R>S!tdMwZji3X^;In+UW>5YL56zHk%%`Csvrfco&%+7mn z=KbD#zghZEnM_iFYySRqYjHqP{*Hs@)faY-?x>3LT%ih8ZDmp26nc+)sb z(gfT(i^{i!B<=Yuwwwy3Ls^<^YS9!}>6A`?rY)zBNw??YGz0UQWAnIbFYH9@gZ8z0 z{arihr30YbD|An^WKg$lU#Ej0)3>c=hyRHlFJz;EcE|GkK)+k|E!Q#aKwo5^R+y7# z=6Xy~k_0aHh~+2qZmDe9Y;s~^LcAO!OY4?L;O|=5DjOd2D`nqxZO_P?w$1nrVi?3E zazOlb(HZghnk#v)1AA7$PqGO9|Hq(>w zYpa&I<@l3A9xdTDdh6c3yZ2_vP16w$Vrf)-))5)vSx`Kk(1&q1H%-eHX=*uSwA(7; zy;iYo3YolVan~s^$DbaZ>XJfeuVaRIK4b)MPi9+UILjVc{^Yw^2}Lf4TDcs#PA+jF z){$cHvN9XmsqZQBhCY$rwHY#Y)F-xpdTY^Jm@ic=m?UtF-wm<;jLfZ_g zh@j-k+qt|;(OzMiGm}nAf0*sDws^;?qu0!e?;6cSqMcZW+|!2l_!6U{`rFyil^^d* zQ*I&B|Q^J(5dg@)sBRP>@Mp;nD7EDANaPd=LmkU)?nI0V-1(i1VK}aVdoX}svsw@ZQV5cg%W$Vbe{S*C(ocV~bocI^ z#oXeLZqEmCAm@_lXJb4Lq34(gT*sydnm~i)JP)%Cy&(U#ZqBaYY3jid%2u3*zGs;E zJRAl-P`iN#?#db*uFRn;)0;qfD|f8570>dSA@S0F*9YJJ{q;W&e!rHUt!uL=IE;e5b$w({3kMf!{TJ){MbJz2?S6Cw z=9M5Lw$!TFKKL*IZ$)r(@G0`Y>+%|CLS2Rxq$pLTs#5if$SbT`xI_g;Db!^#+N{WG zv(7ZAq}amJ%ZLnzh(u})KWuXF?ZIpaHhrlI7`oy%1cv!AHvQ1F!^YwJTM6K7?*_EP zqQvzqh<${b--QNn9a7Sl4)x&|&L6cm(MUSJJJ*OSv7WsL2XilGYU%gt+Izcmi12(} zI|Dt$j1PitzLSMoT=fpj{9jBW)d&SlLcW2K#DSjz#UO^CV$M#?FyJGL<7ayoI1L^W zB;hfF3u!9-J$u|=VL*EN76?9o+q(h{c&dMkr$5^-*3u(&ZKTt?AYSIIU_A=7b+^QV z3>2K?a7^@kGvw%Y%XJQe=Snrkk%%KdR(`2=r$#mMh1yDucr{J|h!BQ2Xe8hbrix4u zAo3^p2FSSeCMIO!G|_q!2k`WTY?wn>(m{fo$S5N_KhgPF*{V z&{#3`e2 zu*3I?=ff`$-it4z&=0gV`28s8iX+8vtUiu0=eW(6ir@^HC;GLLODi_J!DnC!Ysur# zHlnJkex)S8Qu_X;T&XKp8cAhnZ2x=DKX~>*BQhS-kD`}{BL9N_PKfqAx%{ii#=NSi z1C5VWW#;PPIdV8M_D#8FT z4t-D$S4rULA1xn>?M`V@c!b{`9=yyX(ctdfAy)+$l$0~89LqQ n!(M;W@Bogkr9;E;e0}2V!PRF*BL@A@bL{D%!kZo#iJ1Hc%j?x+ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2ddbbd18b0fb18058caacd4be8447be0a319dc23 GIT binary patch literal 8638 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 N#ohf+aGgl-e*nv88omGk literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..988b84c70d4d24e8f7a0a0792d5ccdf55bb0bcb9 GIT binary patch literal 12023 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 T_a2vy3qsZW>CYLJ99RDb7QfDS literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7d4198b4a553182dcff126e65284f051e0fe8416 GIT binary patch literal 13497 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 B%+~+_ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/urls.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/urls.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6979dcc120995463bd64f4b2e3c4fd5e7c229aa5 GIT binary patch literal 2076 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 UyK%9MpeY>+!FS~if`;q!e+=GL8UO$Q literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1698258cdc83156a1af977dd3173a9f68fc14b7b GIT binary patch literal 5902 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/_jaraco_text.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/_jaraco_text.py new file mode 100644 index 0000000..6ccf53b --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/_jaraco_text.py @@ -0,0 +1,109 @@ +"""Functions brought over from jaraco.text. + +These functions are not supposed to be used within `pip._internal`. These are +helper functions brought over from `jaraco.text` to enable vendoring newer +copies of `pkg_resources` without having to vendor `jaraco.text` and its entire +dependency cone; something that our vendoring setup is not currently capable of +handling. + +License reproduced from original source below: + +Copyright Jason R. Coombs + +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. +""" + +import functools +import itertools + + +def _nonblank(str): + return str and not str.startswith("#") + + +@functools.singledispatch +def yield_lines(iterable): + r""" + Yield valid lines of a string or iterable. + + >>> list(yield_lines('')) + [] + >>> list(yield_lines(['foo', 'bar'])) + ['foo', 'bar'] + >>> list(yield_lines('foo\nbar')) + ['foo', 'bar'] + >>> list(yield_lines('\nfoo\n#bar\nbaz #comment')) + ['foo', 'baz #comment'] + >>> list(yield_lines(['foo\nbar', 'baz', 'bing\n\n\n'])) + ['foo', 'bar', 'baz', 'bing'] + """ + return itertools.chain.from_iterable(map(yield_lines, iterable)) + + +@yield_lines.register(str) +def _(text): + return filter(_nonblank, map(str.strip, text.splitlines())) + + +def drop_comment(line): + """ + Drop comments. + + >>> drop_comment('foo # bar') + 'foo' + + A hash without a space may be in a URL. + + >>> drop_comment('http://example.com/foo#bar') + 'http://example.com/foo#bar' + """ + return line.partition(" #")[0] + + +def join_continuation(lines): + r""" + Join lines continued by a trailing backslash. + + >>> list(join_continuation(['foo \\', 'bar', 'baz'])) + ['foobar', 'baz'] + >>> list(join_continuation(['foo \\', 'bar', 'baz'])) + ['foobar', 'baz'] + >>> list(join_continuation(['foo \\', 'bar \\', 'baz'])) + ['foobarbaz'] + + Not sure why, but... + The character preceding the backslash is also elided. + + >>> list(join_continuation(['goo\\', 'dly'])) + ['godly'] + + A terrible idea, but... + If no line is available to continue, suppress the lines. + + >>> list(join_continuation(['foo', 'bar\\', 'baz\\'])) + ['foo'] + """ + lines = iter(lines) + for item in lines: + while item.endswith("\\"): + try: + item = item[:-2].strip() + next(lines) + except StopIteration: + return + yield item diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/_log.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/_log.py new file mode 100644 index 0000000..92c4c6a --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/_log.py @@ -0,0 +1,38 @@ +"""Customize logging + +Defines custom logger class for the `logger.verbose(...)` method. + +init_logging() must be called before any other modules that call logging.getLogger. +""" + +import logging +from typing import Any, cast + +# custom log level for `--verbose` output +# between DEBUG and INFO +VERBOSE = 15 + + +class VerboseLogger(logging.Logger): + """Custom Logger, defining a verbose log-level + + VERBOSE is between INFO and DEBUG. + """ + + def verbose(self, msg: str, *args: Any, **kwargs: Any) -> None: + return self.log(VERBOSE, msg, *args, **kwargs) + + +def getLogger(name: str) -> VerboseLogger: + """logging.getLogger, but ensures our VerboseLogger class is returned""" + return cast(VerboseLogger, logging.getLogger(name)) + + +def init_logging() -> None: + """Register our VerboseLogger and VERBOSE log level. + + Should be called before any calls to getLogger(), + i.e. in pip._internal.__init__ + """ + logging.setLoggerClass(VerboseLogger) + logging.addLevelName(VERBOSE, "VERBOSE") diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/appdirs.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/appdirs.py new file mode 100644 index 0000000..16933bf --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/appdirs.py @@ -0,0 +1,52 @@ +""" +This code wraps the vendored appdirs module to so the return values are +compatible for the current pip code base. + +The intention is to rewrite current usages gradually, keeping the tests pass, +and eventually drop this after all usages are changed. +""" + +import os +import sys +from typing import List + +from pip._vendor import platformdirs as _appdirs + + +def user_cache_dir(appname: str) -> str: + return _appdirs.user_cache_dir(appname, appauthor=False) + + +def _macos_user_config_dir(appname: str, roaming: bool = True) -> str: + # Use ~/Application Support/pip, if the directory exists. + path = _appdirs.user_data_dir(appname, appauthor=False, roaming=roaming) + if os.path.isdir(path): + return path + + # Use a Linux-like ~/.config/pip, by default. + linux_like_path = "~/.config/" + if appname: + linux_like_path = os.path.join(linux_like_path, appname) + + return os.path.expanduser(linux_like_path) + + +def user_config_dir(appname: str, roaming: bool = True) -> str: + if sys.platform == "darwin": + return _macos_user_config_dir(appname, roaming) + + return _appdirs.user_config_dir(appname, appauthor=False, roaming=roaming) + + +# for the discussion regarding site_config_dir locations +# see +def site_config_dirs(appname: str) -> List[str]: + if sys.platform == "darwin": + return [_appdirs.site_data_dir(appname, appauthor=False, multipath=True)] + + dirval = _appdirs.site_config_dir(appname, appauthor=False, multipath=True) + if sys.platform == "win32": + return [dirval] + + # Unix-y system. Look in /etc as well. + return dirval.split(os.pathsep) + ["/etc"] diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/compat.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/compat.py new file mode 100644 index 0000000..d8b54e4 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/compat.py @@ -0,0 +1,79 @@ +"""Stuff that differs in different Python versions and platform +distributions.""" + +import importlib.resources +import logging +import os +import sys +from typing import IO + +__all__ = ["get_path_uid", "stdlib_pkgs", "WINDOWS"] + + +logger = logging.getLogger(__name__) + + +def has_tls() -> bool: + try: + import _ssl # noqa: F401 # ignore unused + + return True + except ImportError: + pass + + from pip._vendor.urllib3.util import IS_PYOPENSSL + + return IS_PYOPENSSL + + +def get_path_uid(path: str) -> int: + """ + Return path's uid. + + Does not follow symlinks: + https://github.com/pypa/pip/pull/935#discussion_r5307003 + + Placed this function in compat due to differences on AIX and + Jython, that should eventually go away. + + :raises OSError: When path is a symlink or can't be read. + """ + if hasattr(os, "O_NOFOLLOW"): + fd = os.open(path, os.O_RDONLY | os.O_NOFOLLOW) + file_uid = os.fstat(fd).st_uid + os.close(fd) + else: # AIX and Jython + # WARNING: time of check vulnerability, but best we can do w/o NOFOLLOW + if not os.path.islink(path): + # older versions of Jython don't have `os.fstat` + file_uid = os.stat(path).st_uid + else: + # raise OSError for parity with os.O_NOFOLLOW above + raise OSError(f"{path} is a symlink; Will not return uid for symlinks") + return file_uid + + +# The importlib.resources.open_text function was deprecated in 3.11 with suggested +# replacement we use below. +if sys.version_info < (3, 11): + open_text_resource = importlib.resources.open_text +else: + + def open_text_resource( + package: str, resource: str, encoding: str = "utf-8", errors: str = "strict" + ) -> IO[str]: + return (importlib.resources.files(package) / resource).open( + "r", encoding=encoding, errors=errors + ) + + +# packages in the stdlib that may have installation metadata, but should not be +# considered 'installed'. this theoretically could be determined based on +# dist.location (py27:`sysconfig.get_paths()['stdlib']`, +# py26:sysconfig.get_config_vars('LIBDEST')), but fear platform variation may +# make this ineffective, so hard-coding +stdlib_pkgs = {"python", "wsgiref", "argparse"} + + +# windows detection, covers cpython and ironpython +WINDOWS = sys.platform.startswith("win") or (sys.platform == "cli" and os.name == "nt") diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/compatibility_tags.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/compatibility_tags.py new file mode 100644 index 0000000..2e7b745 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/compatibility_tags.py @@ -0,0 +1,188 @@ +"""Generate and work with PEP 425 Compatibility Tags. +""" + +import re +from typing import List, Optional, Tuple + +from pip._vendor.packaging.tags import ( + PythonVersion, + Tag, + compatible_tags, + cpython_tags, + generic_tags, + interpreter_name, + interpreter_version, + ios_platforms, + mac_platforms, +) + +_apple_arch_pat = re.compile(r"(.+)_(\d+)_(\d+)_(.+)") + + +def version_info_to_nodot(version_info: Tuple[int, ...]) -> str: + # Only use up to the first two numbers. + return "".join(map(str, version_info[:2])) + + +def _mac_platforms(arch: str) -> List[str]: + match = _apple_arch_pat.match(arch) + if match: + name, major, minor, actual_arch = match.groups() + mac_version = (int(major), int(minor)) + arches = [ + # Since we have always only checked that the platform starts + # with "macosx", for backwards-compatibility we extract the + # actual prefix provided by the user in case they provided + # something like "macosxcustom_". It may be good to remove + # this as undocumented or deprecate it in the future. + "{}_{}".format(name, arch[len("macosx_") :]) + for arch in mac_platforms(mac_version, actual_arch) + ] + else: + # arch pattern didn't match (?!) + arches = [arch] + return arches + + +def _ios_platforms(arch: str) -> List[str]: + match = _apple_arch_pat.match(arch) + if match: + name, major, minor, actual_multiarch = match.groups() + ios_version = (int(major), int(minor)) + arches = [ + # Since we have always only checked that the platform starts + # with "ios", for backwards-compatibility we extract the + # actual prefix provided by the user in case they provided + # something like "ioscustom_". It may be good to remove + # this as undocumented or deprecate it in the future. + "{}_{}".format(name, arch[len("ios_") :]) + for arch in ios_platforms(ios_version, actual_multiarch) + ] + else: + # arch pattern didn't match (?!) + arches = [arch] + return arches + + +def _custom_manylinux_platforms(arch: str) -> List[str]: + arches = [arch] + arch_prefix, arch_sep, arch_suffix = arch.partition("_") + if arch_prefix == "manylinux2014": + # manylinux1/manylinux2010 wheels run on most manylinux2014 systems + # with the exception of wheels depending on ncurses. PEP 599 states + # manylinux1/manylinux2010 wheels should be considered + # manylinux2014 wheels: + # https://www.python.org/dev/peps/pep-0599/#backwards-compatibility-with-manylinux2010-wheels + if arch_suffix in {"i686", "x86_64"}: + arches.append("manylinux2010" + arch_sep + arch_suffix) + arches.append("manylinux1" + arch_sep + arch_suffix) + elif arch_prefix == "manylinux2010": + # manylinux1 wheels run on most manylinux2010 systems with the + # exception of wheels depending on ncurses. PEP 571 states + # manylinux1 wheels should be considered manylinux2010 wheels: + # https://www.python.org/dev/peps/pep-0571/#backwards-compatibility-with-manylinux1-wheels + arches.append("manylinux1" + arch_sep + arch_suffix) + return arches + + +def _get_custom_platforms(arch: str) -> List[str]: + arch_prefix, arch_sep, arch_suffix = arch.partition("_") + if arch.startswith("macosx"): + arches = _mac_platforms(arch) + elif arch.startswith("ios"): + arches = _ios_platforms(arch) + elif arch_prefix in ["manylinux2014", "manylinux2010"]: + arches = _custom_manylinux_platforms(arch) + else: + arches = [arch] + return arches + + +def _expand_allowed_platforms(platforms: Optional[List[str]]) -> Optional[List[str]]: + if not platforms: + return None + + seen = set() + result = [] + + for p in platforms: + if p in seen: + continue + additions = [c for c in _get_custom_platforms(p) if c not in seen] + seen.update(additions) + result.extend(additions) + + return result + + +def _get_python_version(version: str) -> PythonVersion: + if len(version) > 1: + return int(version[0]), int(version[1:]) + else: + return (int(version[0]),) + + +def _get_custom_interpreter( + implementation: Optional[str] = None, version: Optional[str] = None +) -> str: + if implementation is None: + implementation = interpreter_name() + if version is None: + version = interpreter_version() + return f"{implementation}{version}" + + +def get_supported( + version: Optional[str] = None, + platforms: Optional[List[str]] = None, + impl: Optional[str] = None, + abis: Optional[List[str]] = None, +) -> List[Tag]: + """Return a list of supported tags for each version specified in + `versions`. + + :param version: a string version, of the form "33" or "32", + or None. The version will be assumed to support our ABI. + :param platform: specify a list of platforms you want valid + tags for, or None. If None, use the local system platform. + :param impl: specify the exact implementation you want valid + tags for, or None. If None, use the local interpreter impl. + :param abis: specify a list of abis you want valid + tags for, or None. If None, use the local interpreter abi. + """ + supported: List[Tag] = [] + + python_version: Optional[PythonVersion] = None + if version is not None: + python_version = _get_python_version(version) + + interpreter = _get_custom_interpreter(impl, version) + + platforms = _expand_allowed_platforms(platforms) + + is_cpython = (impl or interpreter_name()) == "cp" + if is_cpython: + supported.extend( + cpython_tags( + python_version=python_version, + abis=abis, + platforms=platforms, + ) + ) + else: + supported.extend( + generic_tags( + interpreter=interpreter, + abis=abis, + platforms=platforms, + ) + ) + supported.extend( + compatible_tags( + python_version=python_version, + interpreter=interpreter, + platforms=platforms, + ) + ) + + return supported diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/datetime.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/datetime.py new file mode 100644 index 0000000..8668b3b --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/datetime.py @@ -0,0 +1,11 @@ +"""For when pip wants to check the date or time. +""" + +import datetime + + +def today_is_later_than(year: int, month: int, day: int) -> bool: + today = datetime.date.today() + given = datetime.date(year, month, day) + + return today > given diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/deprecation.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/deprecation.py new file mode 100644 index 0000000..0911147 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/deprecation.py @@ -0,0 +1,124 @@ +""" +A module that implements tooling to enable easy warnings about deprecations. +""" + +import logging +import warnings +from typing import Any, Optional, TextIO, Type, Union + +from pip._vendor.packaging.version import parse + +from pip import __version__ as current_version # NOTE: tests patch this name. + +DEPRECATION_MSG_PREFIX = "DEPRECATION: " + + +class PipDeprecationWarning(Warning): + pass + + +_original_showwarning: Any = None + + +# Warnings <-> Logging Integration +def _showwarning( + message: Union[Warning, str], + category: Type[Warning], + filename: str, + lineno: int, + file: Optional[TextIO] = None, + line: Optional[str] = None, +) -> None: + if file is not None: + if _original_showwarning is not None: + _original_showwarning(message, category, filename, lineno, file, line) + elif issubclass(category, PipDeprecationWarning): + # We use a specially named logger which will handle all of the + # deprecation messages for pip. + logger = logging.getLogger("pip._internal.deprecations") + logger.warning(message) + else: + _original_showwarning(message, category, filename, lineno, file, line) + + +def install_warning_logger() -> None: + # Enable our Deprecation Warnings + warnings.simplefilter("default", PipDeprecationWarning, append=True) + + global _original_showwarning + + if _original_showwarning is None: + _original_showwarning = warnings.showwarning + warnings.showwarning = _showwarning + + +def deprecated( + *, + reason: str, + replacement: Optional[str], + gone_in: Optional[str], + feature_flag: Optional[str] = None, + issue: Optional[int] = None, +) -> None: + """Helper to deprecate existing functionality. + + reason: + Textual reason shown to the user about why this functionality has + been deprecated. Should be a complete sentence. + replacement: + Textual suggestion shown to the user about what alternative + functionality they can use. + gone_in: + The version of pip does this functionality should get removed in. + Raises an error if pip's current version is greater than or equal to + this. + feature_flag: + Command-line flag of the form --use-feature={feature_flag} for testing + upcoming functionality. + issue: + Issue number on the tracker that would serve as a useful place for + users to find related discussion and provide feedback. + """ + + # Determine whether or not the feature is already gone in this version. + is_gone = gone_in is not None and parse(current_version) >= parse(gone_in) + + message_parts = [ + (reason, f"{DEPRECATION_MSG_PREFIX}{{}}"), + ( + gone_in, + ( + "pip {} will enforce this behaviour change." + if not is_gone + else "Since pip {}, this is no longer supported." + ), + ), + ( + replacement, + "A possible replacement is {}.", + ), + ( + feature_flag, + ( + "You can use the flag --use-feature={} to test the upcoming behaviour." + if not is_gone + else None + ), + ), + ( + issue, + "Discussion can be found at https://github.com/pypa/pip/issues/{}", + ), + ] + + message = " ".join( + format_str.format(value) + for value, format_str in message_parts + if format_str is not None and value is not None + ) + + # Raise as an error if this behaviour is deprecated. + if is_gone: + raise PipDeprecationWarning(message) + + warnings.warn(message, category=PipDeprecationWarning, stacklevel=2) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/direct_url_helpers.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/direct_url_helpers.py new file mode 100644 index 0000000..66020d3 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/direct_url_helpers.py @@ -0,0 +1,87 @@ +from typing import Optional + +from pip._internal.models.direct_url import ArchiveInfo, DirectUrl, DirInfo, VcsInfo +from pip._internal.models.link import Link +from pip._internal.utils.urls import path_to_url +from pip._internal.vcs import vcs + + +def direct_url_as_pep440_direct_reference(direct_url: DirectUrl, name: str) -> str: + """Convert a DirectUrl to a pip requirement string.""" + direct_url.validate() # if invalid, this is a pip bug + requirement = name + " @ " + fragments = [] + if isinstance(direct_url.info, VcsInfo): + requirement += ( + f"{direct_url.info.vcs}+{direct_url.url}@{direct_url.info.commit_id}" + ) + elif isinstance(direct_url.info, ArchiveInfo): + requirement += direct_url.url + if direct_url.info.hash: + fragments.append(direct_url.info.hash) + else: + assert isinstance(direct_url.info, DirInfo) + requirement += direct_url.url + if direct_url.subdirectory: + fragments.append("subdirectory=" + direct_url.subdirectory) + if fragments: + requirement += "#" + "&".join(fragments) + return requirement + + +def direct_url_for_editable(source_dir: str) -> DirectUrl: + return DirectUrl( + url=path_to_url(source_dir), + info=DirInfo(editable=True), + ) + + +def direct_url_from_link( + link: Link, source_dir: Optional[str] = None, link_is_in_wheel_cache: bool = False +) -> DirectUrl: + if link.is_vcs: + vcs_backend = vcs.get_backend_for_scheme(link.scheme) + assert vcs_backend + url, requested_revision, _ = vcs_backend.get_url_rev_and_auth( + link.url_without_fragment + ) + # For VCS links, we need to find out and add commit_id. + if link_is_in_wheel_cache: + # If the requested VCS link corresponds to a cached + # wheel, it means the requested revision was an + # immutable commit hash, otherwise it would not have + # been cached. In that case we don't have a source_dir + # with the VCS checkout. + assert requested_revision + commit_id = requested_revision + else: + # If the wheel was not in cache, it means we have + # had to checkout from VCS to build and we have a source_dir + # which we can inspect to find out the commit id. + assert source_dir + commit_id = vcs_backend.get_revision(source_dir) + return DirectUrl( + url=url, + info=VcsInfo( + vcs=vcs_backend.name, + commit_id=commit_id, + requested_revision=requested_revision, + ), + subdirectory=link.subdirectory_fragment, + ) + elif link.is_existing_dir(): + return DirectUrl( + url=link.url_without_fragment, + info=DirInfo(), + subdirectory=link.subdirectory_fragment, + ) + else: + hash = None + hash_name = link.hash_name + if hash_name: + hash = f"{hash_name}={link.hash}" + return DirectUrl( + url=link.url_without_fragment, + info=ArchiveInfo(hash=hash), + subdirectory=link.subdirectory_fragment, + ) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/egg_link.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/egg_link.py new file mode 100644 index 0000000..4a384a6 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/egg_link.py @@ -0,0 +1,80 @@ +import os +import re +import sys +from typing import List, Optional + +from pip._internal.locations import site_packages, user_site +from pip._internal.utils.virtualenv import ( + running_under_virtualenv, + virtualenv_no_global, +) + +__all__ = [ + "egg_link_path_from_sys_path", + "egg_link_path_from_location", +] + + +def _egg_link_names(raw_name: str) -> List[str]: + """ + Convert a Name metadata value to a .egg-link name, by applying + the same substitution as pkg_resources's safe_name function. + Note: we cannot use canonicalize_name because it has a different logic. + + We also look for the raw name (without normalization) as setuptools 69 changed + the way it names .egg-link files (https://github.com/pypa/setuptools/issues/4167). + """ + return [ + re.sub("[^A-Za-z0-9.]+", "-", raw_name) + ".egg-link", + f"{raw_name}.egg-link", + ] + + +def egg_link_path_from_sys_path(raw_name: str) -> Optional[str]: + """ + Look for a .egg-link file for project name, by walking sys.path. + """ + egg_link_names = _egg_link_names(raw_name) + for path_item in sys.path: + for egg_link_name in egg_link_names: + egg_link = os.path.join(path_item, egg_link_name) + if os.path.isfile(egg_link): + return egg_link + return None + + +def egg_link_path_from_location(raw_name: str) -> Optional[str]: + """ + Return the path for the .egg-link file if it exists, otherwise, None. + + There's 3 scenarios: + 1) not in a virtualenv + try to find in site.USER_SITE, then site_packages + 2) in a no-global virtualenv + try to find in site_packages + 3) in a yes-global virtualenv + try to find in site_packages, then site.USER_SITE + (don't look in global location) + + For #1 and #3, there could be odd cases, where there's an egg-link in 2 + locations. + + This method will just return the first one found. + """ + sites: List[str] = [] + if running_under_virtualenv(): + sites.append(site_packages) + if not virtualenv_no_global() and user_site: + sites.append(user_site) + else: + if user_site: + sites.append(user_site) + sites.append(site_packages) + + egg_link_names = _egg_link_names(raw_name) + for site in sites: + for egg_link_name in egg_link_names: + egglink = os.path.join(site, egg_link_name) + if os.path.isfile(egglink): + return egglink + return None diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/encoding.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/encoding.py new file mode 100644 index 0000000..008f06a --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/encoding.py @@ -0,0 +1,36 @@ +import codecs +import locale +import re +import sys +from typing import List, Tuple + +BOMS: List[Tuple[bytes, str]] = [ + (codecs.BOM_UTF8, "utf-8"), + (codecs.BOM_UTF16, "utf-16"), + (codecs.BOM_UTF16_BE, "utf-16-be"), + (codecs.BOM_UTF16_LE, "utf-16-le"), + (codecs.BOM_UTF32, "utf-32"), + (codecs.BOM_UTF32_BE, "utf-32-be"), + (codecs.BOM_UTF32_LE, "utf-32-le"), +] + +ENCODING_RE = re.compile(rb"coding[:=]\s*([-\w.]+)") + + +def auto_decode(data: bytes) -> str: + """Check a bytes string for a BOM to correctly detect the encoding + + Fallback to locale.getpreferredencoding(False) like open() on Python3""" + for bom, encoding in BOMS: + if data.startswith(bom): + return data[len(bom) :].decode(encoding) + # Lets check the first two lines as in PEP263 + for line in data.split(b"\n")[:2]: + if line[0:1] == b"#" and ENCODING_RE.search(line): + result = ENCODING_RE.search(line) + assert result is not None + encoding = result.groups()[0].decode("ascii") + return data.decode(encoding) + return data.decode( + locale.getpreferredencoding(False) or sys.getdefaultencoding(), + ) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/entrypoints.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/entrypoints.py new file mode 100644 index 0000000..1501369 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/entrypoints.py @@ -0,0 +1,84 @@ +import itertools +import os +import shutil +import sys +from typing import List, Optional + +from pip._internal.cli.main import main +from pip._internal.utils.compat import WINDOWS + +_EXECUTABLE_NAMES = [ + "pip", + f"pip{sys.version_info.major}", + f"pip{sys.version_info.major}.{sys.version_info.minor}", +] +if WINDOWS: + _allowed_extensions = {"", ".exe"} + _EXECUTABLE_NAMES = [ + "".join(parts) + for parts in itertools.product(_EXECUTABLE_NAMES, _allowed_extensions) + ] + + +def _wrapper(args: Optional[List[str]] = None) -> int: + """Central wrapper for all old entrypoints. + + Historically pip has had several entrypoints defined. Because of issues + arising from PATH, sys.path, multiple Pythons, their interactions, and most + of them having a pip installed, users suffer every time an entrypoint gets + moved. + + To alleviate this pain, and provide a mechanism for warning users and + directing them to an appropriate place for help, we now define all of + our old entrypoints as wrappers for the current one. + """ + sys.stderr.write( + "WARNING: pip is being invoked by an old script wrapper. This will " + "fail in a future version of pip.\n" + "Please see https://github.com/pypa/pip/issues/5599 for advice on " + "fixing the underlying issue.\n" + "To avoid this problem you can invoke Python with '-m pip' instead of " + "running pip directly.\n" + ) + return main(args) + + +def get_best_invocation_for_this_pip() -> str: + """Try to figure out the best way to invoke pip in the current environment.""" + binary_directory = "Scripts" if WINDOWS else "bin" + binary_prefix = os.path.join(sys.prefix, binary_directory) + + # Try to use pip[X[.Y]] names, if those executables for this environment are + # the first on PATH with that name. + path_parts = os.path.normcase(os.environ.get("PATH", "")).split(os.pathsep) + exe_are_in_PATH = os.path.normcase(binary_prefix) in path_parts + if exe_are_in_PATH: + for exe_name in _EXECUTABLE_NAMES: + found_executable = shutil.which(exe_name) + binary_executable = os.path.join(binary_prefix, exe_name) + if ( + found_executable + and os.path.exists(binary_executable) + and os.path.samefile( + found_executable, + binary_executable, + ) + ): + return exe_name + + # Use the `-m` invocation, if there's no "nice" invocation. + return f"{get_best_invocation_for_this_python()} -m pip" + + +def get_best_invocation_for_this_python() -> str: + """Try to figure out the best way to invoke the current Python.""" + exe = sys.executable + exe_name = os.path.basename(exe) + + # Try to use the basename, if it's the first executable. + found_executable = shutil.which(exe_name) + if found_executable and os.path.samefile(found_executable, exe): + return exe_name + + # Use the full executable name, because we couldn't find something simpler. + return exe diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/filesystem.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/filesystem.py new file mode 100644 index 0000000..22e356c --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/filesystem.py @@ -0,0 +1,149 @@ +import fnmatch +import os +import os.path +import random +import sys +from contextlib import contextmanager +from tempfile import NamedTemporaryFile +from typing import Any, BinaryIO, Generator, List, Union, cast + +from pip._internal.utils.compat import get_path_uid +from pip._internal.utils.misc import format_size +from pip._internal.utils.retry import retry + + +def check_path_owner(path: str) -> bool: + # If we don't have a way to check the effective uid of this process, then + # we'll just assume that we own the directory. + if sys.platform == "win32" or not hasattr(os, "geteuid"): + return True + + assert os.path.isabs(path) + + previous = None + while path != previous: + if os.path.lexists(path): + # Check if path is writable by current user. + if os.geteuid() == 0: + # Special handling for root user in order to handle properly + # cases where users use sudo without -H flag. + try: + path_uid = get_path_uid(path) + except OSError: + return False + return path_uid == 0 + else: + return os.access(path, os.W_OK) + else: + previous, path = path, os.path.dirname(path) + return False # assume we don't own the path + + +@contextmanager +def adjacent_tmp_file(path: str, **kwargs: Any) -> Generator[BinaryIO, None, None]: + """Return a file-like object pointing to a tmp file next to path. + + The file is created securely and is ensured to be written to disk + after the context reaches its end. + + kwargs will be passed to tempfile.NamedTemporaryFile to control + the way the temporary file will be opened. + """ + with NamedTemporaryFile( + delete=False, + dir=os.path.dirname(path), + prefix=os.path.basename(path), + suffix=".tmp", + **kwargs, + ) as f: + result = cast(BinaryIO, f) + try: + yield result + finally: + result.flush() + os.fsync(result.fileno()) + + +replace = retry(stop_after_delay=1, wait=0.25)(os.replace) + + +# test_writable_dir and _test_writable_dir_win are copied from Flit, +# with the author's agreement to also place them under pip's license. +def test_writable_dir(path: str) -> bool: + """Check if a directory is writable. + + Uses os.access() on POSIX, tries creating files on Windows. + """ + # If the directory doesn't exist, find the closest parent that does. + while not os.path.isdir(path): + parent = os.path.dirname(path) + if parent == path: + break # Should never get here, but infinite loops are bad + path = parent + + if os.name == "posix": + return os.access(path, os.W_OK) + + return _test_writable_dir_win(path) + + +def _test_writable_dir_win(path: str) -> bool: + # os.access doesn't work on Windows: http://bugs.python.org/issue2528 + # and we can't use tempfile: http://bugs.python.org/issue22107 + basename = "accesstest_deleteme_fishfingers_custard_" + alphabet = "abcdefghijklmnopqrstuvwxyz0123456789" + for _ in range(10): + name = basename + "".join(random.choice(alphabet) for _ in range(6)) + file = os.path.join(path, name) + try: + fd = os.open(file, os.O_RDWR | os.O_CREAT | os.O_EXCL) + except FileExistsError: + pass + except PermissionError: + # This could be because there's a directory with the same name. + # But it's highly unlikely there's a directory called that, + # so we'll assume it's because the parent dir is not writable. + # This could as well be because the parent dir is not readable, + # due to non-privileged user access. + return False + else: + os.close(fd) + os.unlink(file) + return True + + # This should never be reached + raise OSError("Unexpected condition testing for writable directory") + + +def find_files(path: str, pattern: str) -> List[str]: + """Returns a list of absolute paths of files beneath path, recursively, + with filenames which match the UNIX-style shell glob pattern.""" + result: List[str] = [] + for root, _, files in os.walk(path): + matches = fnmatch.filter(files, pattern) + result.extend(os.path.join(root, f) for f in matches) + return result + + +def file_size(path: str) -> Union[int, float]: + # If it's a symlink, return 0. + if os.path.islink(path): + return 0 + return os.path.getsize(path) + + +def format_file_size(path: str) -> str: + return format_size(file_size(path)) + + +def directory_size(path: str) -> Union[int, float]: + size = 0.0 + for root, _dirs, files in os.walk(path): + for filename in files: + file_path = os.path.join(root, filename) + size += file_size(file_path) + return size + + +def format_directory_size(path: str) -> str: + return format_size(directory_size(path)) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/filetypes.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/filetypes.py new file mode 100644 index 0000000..5948570 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/filetypes.py @@ -0,0 +1,27 @@ +"""Filetype information. +""" + +from typing import Tuple + +from pip._internal.utils.misc import splitext + +WHEEL_EXTENSION = ".whl" +BZ2_EXTENSIONS: Tuple[str, ...] = (".tar.bz2", ".tbz") +XZ_EXTENSIONS: Tuple[str, ...] = ( + ".tar.xz", + ".txz", + ".tlz", + ".tar.lz", + ".tar.lzma", +) +ZIP_EXTENSIONS: Tuple[str, ...] = (".zip", WHEEL_EXTENSION) +TAR_EXTENSIONS: Tuple[str, ...] = (".tar.gz", ".tgz", ".tar") +ARCHIVE_EXTENSIONS = ZIP_EXTENSIONS + BZ2_EXTENSIONS + TAR_EXTENSIONS + XZ_EXTENSIONS + + +def is_archive_file(name: str) -> bool: + """Return True if `name` is a considered as an archive file.""" + ext = splitext(name)[1].lower() + if ext in ARCHIVE_EXTENSIONS: + return True + return False diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/glibc.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/glibc.py new file mode 100644 index 0000000..998868f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/glibc.py @@ -0,0 +1,101 @@ +import os +import sys +from typing import Optional, Tuple + + +def glibc_version_string() -> Optional[str]: + "Returns glibc version string, or None if not using glibc." + return glibc_version_string_confstr() or glibc_version_string_ctypes() + + +def glibc_version_string_confstr() -> Optional[str]: + "Primary implementation of glibc_version_string using os.confstr." + # os.confstr is quite a bit faster than ctypes.DLL. It's also less likely + # to be broken or missing. This strategy is used in the standard library + # platform module: + # https://github.com/python/cpython/blob/fcf1d003bf4f0100c9d0921ff3d70e1127ca1b71/Lib/platform.py#L175-L183 + if sys.platform == "win32": + return None + try: + gnu_libc_version = os.confstr("CS_GNU_LIBC_VERSION") + if gnu_libc_version is None: + return None + # os.confstr("CS_GNU_LIBC_VERSION") returns a string like "glibc 2.17": + _, version = gnu_libc_version.split() + except (AttributeError, OSError, ValueError): + # os.confstr() or CS_GNU_LIBC_VERSION not available (or a bad value)... + return None + return version + + +def glibc_version_string_ctypes() -> Optional[str]: + "Fallback implementation of glibc_version_string using ctypes." + + try: + import ctypes + except ImportError: + return None + + # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen + # manpage says, "If filename is NULL, then the returned handle is for the + # main program". This way we can let the linker do the work to figure out + # which libc our process is actually using. + # + # We must also handle the special case where the executable is not a + # dynamically linked executable. This can occur when using musl libc, + # for example. In this situation, dlopen() will error, leading to an + # OSError. Interestingly, at least in the case of musl, there is no + # errno set on the OSError. The single string argument used to construct + # OSError comes from libc itself and is therefore not portable to + # hard code here. In any case, failure to call dlopen() means we + # can't proceed, so we bail on our attempt. + try: + process_namespace = ctypes.CDLL(None) + except OSError: + return None + + try: + gnu_get_libc_version = process_namespace.gnu_get_libc_version + except AttributeError: + # Symbol doesn't exist -> therefore, we are not linked to + # glibc. + return None + + # Call gnu_get_libc_version, which returns a string like "2.5" + gnu_get_libc_version.restype = ctypes.c_char_p + version_str: str = gnu_get_libc_version() + # py2 / py3 compatibility: + if not isinstance(version_str, str): + version_str = version_str.decode("ascii") + + return version_str + + +# platform.libc_ver regularly returns completely nonsensical glibc +# versions. E.g. on my computer, platform says: +# +# ~$ python2.7 -c 'import platform; print(platform.libc_ver())' +# ('glibc', '2.7') +# ~$ python3.5 -c 'import platform; print(platform.libc_ver())' +# ('glibc', '2.9') +# +# But the truth is: +# +# ~$ ldd --version +# ldd (Debian GLIBC 2.22-11) 2.22 +# +# This is unfortunate, because it means that the linehaul data on libc +# versions that was generated by pip 8.1.2 and earlier is useless and +# misleading. Solution: instead of using platform, use our code that actually +# works. +def libc_ver() -> Tuple[str, str]: + """Try to determine the glibc version + + Returns a tuple of strings (lib, version) which default to empty strings + in case the lookup fails. + """ + glibc_version = glibc_version_string() + if glibc_version is None: + return ("", "") + else: + return ("glibc", glibc_version) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/hashes.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/hashes.py new file mode 100644 index 0000000..535e94f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/hashes.py @@ -0,0 +1,147 @@ +import hashlib +from typing import TYPE_CHECKING, BinaryIO, Dict, Iterable, List, NoReturn, Optional + +from pip._internal.exceptions import HashMismatch, HashMissing, InstallationError +from pip._internal.utils.misc import read_chunks + +if TYPE_CHECKING: + from hashlib import _Hash + + +# The recommended hash algo of the moment. Change this whenever the state of +# the art changes; it won't hurt backward compatibility. +FAVORITE_HASH = "sha256" + + +# Names of hashlib algorithms allowed by the --hash option and ``pip hash`` +# Currently, those are the ones at least as collision-resistant as sha256. +STRONG_HASHES = ["sha256", "sha384", "sha512"] + + +class Hashes: + """A wrapper that builds multiple hashes at once and checks them against + known-good values + + """ + + def __init__(self, hashes: Optional[Dict[str, List[str]]] = None) -> None: + """ + :param hashes: A dict of algorithm names pointing to lists of allowed + hex digests + """ + allowed = {} + if hashes is not None: + for alg, keys in hashes.items(): + # Make sure values are always sorted (to ease equality checks) + allowed[alg] = [k.lower() for k in sorted(keys)] + self._allowed = allowed + + def __and__(self, other: "Hashes") -> "Hashes": + if not isinstance(other, Hashes): + return NotImplemented + + # If either of the Hashes object is entirely empty (i.e. no hash + # specified at all), all hashes from the other object are allowed. + if not other: + return self + if not self: + return other + + # Otherwise only hashes that present in both objects are allowed. + new = {} + for alg, values in other._allowed.items(): + if alg not in self._allowed: + continue + new[alg] = [v for v in values if v in self._allowed[alg]] + return Hashes(new) + + @property + def digest_count(self) -> int: + return sum(len(digests) for digests in self._allowed.values()) + + def is_hash_allowed(self, hash_name: str, hex_digest: str) -> bool: + """Return whether the given hex digest is allowed.""" + return hex_digest in self._allowed.get(hash_name, []) + + def check_against_chunks(self, chunks: Iterable[bytes]) -> None: + """Check good hashes against ones built from iterable of chunks of + data. + + Raise HashMismatch if none match. + + """ + gots = {} + for hash_name in self._allowed.keys(): + try: + gots[hash_name] = hashlib.new(hash_name) + except (ValueError, TypeError): + raise InstallationError(f"Unknown hash name: {hash_name}") + + for chunk in chunks: + for hash in gots.values(): + hash.update(chunk) + + for hash_name, got in gots.items(): + if got.hexdigest() in self._allowed[hash_name]: + return + self._raise(gots) + + def _raise(self, gots: Dict[str, "_Hash"]) -> "NoReturn": + raise HashMismatch(self._allowed, gots) + + def check_against_file(self, file: BinaryIO) -> None: + """Check good hashes against a file-like object + + Raise HashMismatch if none match. + + """ + return self.check_against_chunks(read_chunks(file)) + + def check_against_path(self, path: str) -> None: + with open(path, "rb") as file: + return self.check_against_file(file) + + def has_one_of(self, hashes: Dict[str, str]) -> bool: + """Return whether any of the given hashes are allowed.""" + for hash_name, hex_digest in hashes.items(): + if self.is_hash_allowed(hash_name, hex_digest): + return True + return False + + def __bool__(self) -> bool: + """Return whether I know any known-good hashes.""" + return bool(self._allowed) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, Hashes): + return NotImplemented + return self._allowed == other._allowed + + def __hash__(self) -> int: + return hash( + ",".join( + sorted( + ":".join((alg, digest)) + for alg, digest_list in self._allowed.items() + for digest in digest_list + ) + ) + ) + + +class MissingHashes(Hashes): + """A workalike for Hashes used when we're missing a hash for a requirement + + It computes the actual hash of the requirement and raises a HashMissing + exception showing it to the user. + + """ + + def __init__(self) -> None: + """Don't offer the ``hashes`` kwarg.""" + # Pass our favorite hash in to generate a "gotten hash". With the + # empty list, it will never match, so an error will always raise. + super().__init__(hashes={FAVORITE_HASH: []}) + + def _raise(self, gots: Dict[str, "_Hash"]) -> "NoReturn": + raise HashMissing(gots[FAVORITE_HASH].hexdigest()) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/logging.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/logging.py new file mode 100644 index 0000000..41f6eb5 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/logging.py @@ -0,0 +1,347 @@ +import contextlib +import errno +import logging +import logging.handlers +import os +import sys +import threading +from dataclasses import dataclass +from io import TextIOWrapper +from logging import Filter +from typing import Any, ClassVar, Generator, List, Optional, TextIO, Type + +from pip._vendor.rich.console import ( + Console, + ConsoleOptions, + ConsoleRenderable, + RenderableType, + RenderResult, + RichCast, +) +from pip._vendor.rich.highlighter import NullHighlighter +from pip._vendor.rich.logging import RichHandler +from pip._vendor.rich.segment import Segment +from pip._vendor.rich.style import Style + +from pip._internal.utils._log import VERBOSE, getLogger +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.deprecation import DEPRECATION_MSG_PREFIX +from pip._internal.utils.misc import ensure_dir + +_log_state = threading.local() +subprocess_logger = getLogger("pip.subprocessor") + + +class BrokenStdoutLoggingError(Exception): + """ + Raised if BrokenPipeError occurs for the stdout stream while logging. + """ + + +def _is_broken_pipe_error(exc_class: Type[BaseException], exc: BaseException) -> bool: + if exc_class is BrokenPipeError: + return True + + # On Windows, a broken pipe can show up as EINVAL rather than EPIPE: + # https://bugs.python.org/issue19612 + # https://bugs.python.org/issue30418 + if not WINDOWS: + return False + + return isinstance(exc, OSError) and exc.errno in (errno.EINVAL, errno.EPIPE) + + +@contextlib.contextmanager +def indent_log(num: int = 2) -> Generator[None, None, None]: + """ + A context manager which will cause the log output to be indented for any + log messages emitted inside it. + """ + # For thread-safety + _log_state.indentation = get_indentation() + _log_state.indentation += num + try: + yield + finally: + _log_state.indentation -= num + + +def get_indentation() -> int: + return getattr(_log_state, "indentation", 0) + + +class IndentingFormatter(logging.Formatter): + default_time_format = "%Y-%m-%dT%H:%M:%S" + + def __init__( + self, + *args: Any, + add_timestamp: bool = False, + **kwargs: Any, + ) -> None: + """ + A logging.Formatter that obeys the indent_log() context manager. + + :param add_timestamp: A bool indicating output lines should be prefixed + with their record's timestamp. + """ + self.add_timestamp = add_timestamp + super().__init__(*args, **kwargs) + + def get_message_start(self, formatted: str, levelno: int) -> str: + """ + Return the start of the formatted log message (not counting the + prefix to add to each line). + """ + if levelno < logging.WARNING: + return "" + if formatted.startswith(DEPRECATION_MSG_PREFIX): + # Then the message already has a prefix. We don't want it to + # look like "WARNING: DEPRECATION: ...." + return "" + if levelno < logging.ERROR: + return "WARNING: " + + return "ERROR: " + + def format(self, record: logging.LogRecord) -> str: + """ + Calls the standard formatter, but will indent all of the log message + lines by our current indentation level. + """ + formatted = super().format(record) + message_start = self.get_message_start(formatted, record.levelno) + formatted = message_start + formatted + + prefix = "" + if self.add_timestamp: + prefix = f"{self.formatTime(record)} " + prefix += " " * get_indentation() + formatted = "".join([prefix + line for line in formatted.splitlines(True)]) + return formatted + + +@dataclass +class IndentedRenderable: + renderable: RenderableType + indent: int + + def __rich_console__( + self, console: Console, options: ConsoleOptions + ) -> RenderResult: + segments = console.render(self.renderable, options) + lines = Segment.split_lines(segments) + for line in lines: + yield Segment(" " * self.indent) + yield from line + yield Segment("\n") + + +class RichPipStreamHandler(RichHandler): + KEYWORDS: ClassVar[Optional[List[str]]] = [] + + def __init__(self, stream: Optional[TextIO], no_color: bool) -> None: + super().__init__( + console=Console(file=stream, no_color=no_color, soft_wrap=True), + show_time=False, + show_level=False, + show_path=False, + highlighter=NullHighlighter(), + ) + + # Our custom override on Rich's logger, to make things work as we need them to. + def emit(self, record: logging.LogRecord) -> None: + style: Optional[Style] = None + + # If we are given a diagnostic error to present, present it with indentation. + if getattr(record, "rich", False): + assert isinstance(record.args, tuple) + (rich_renderable,) = record.args + assert isinstance( + rich_renderable, (ConsoleRenderable, RichCast, str) + ), f"{rich_renderable} is not rich-console-renderable" + + renderable: RenderableType = IndentedRenderable( + rich_renderable, indent=get_indentation() + ) + else: + message = self.format(record) + renderable = self.render_message(record, message) + if record.levelno is not None: + if record.levelno >= logging.ERROR: + style = Style(color="red") + elif record.levelno >= logging.WARNING: + style = Style(color="yellow") + + try: + self.console.print(renderable, overflow="ignore", crop=False, style=style) + except Exception: + self.handleError(record) + + def handleError(self, record: logging.LogRecord) -> None: + """Called when logging is unable to log some output.""" + + exc_class, exc = sys.exc_info()[:2] + # If a broken pipe occurred while calling write() or flush() on the + # stdout stream in logging's Handler.emit(), then raise our special + # exception so we can handle it in main() instead of logging the + # broken pipe error and continuing. + if ( + exc_class + and exc + and self.console.file is sys.stdout + and _is_broken_pipe_error(exc_class, exc) + ): + raise BrokenStdoutLoggingError() + + return super().handleError(record) + + +class BetterRotatingFileHandler(logging.handlers.RotatingFileHandler): + def _open(self) -> TextIOWrapper: + ensure_dir(os.path.dirname(self.baseFilename)) + return super()._open() + + +class MaxLevelFilter(Filter): + def __init__(self, level: int) -> None: + self.level = level + + def filter(self, record: logging.LogRecord) -> bool: + return record.levelno < self.level + + +class ExcludeLoggerFilter(Filter): + """ + A logging Filter that excludes records from a logger (or its children). + """ + + def filter(self, record: logging.LogRecord) -> bool: + # The base Filter class allows only records from a logger (or its + # children). + return not super().filter(record) + + +def setup_logging(verbosity: int, no_color: bool, user_log_file: Optional[str]) -> int: + """Configures and sets up all of the logging + + Returns the requested logging level, as its integer value. + """ + + # Determine the level to be logging at. + if verbosity >= 2: + level_number = logging.DEBUG + elif verbosity == 1: + level_number = VERBOSE + elif verbosity == -1: + level_number = logging.WARNING + elif verbosity == -2: + level_number = logging.ERROR + elif verbosity <= -3: + level_number = logging.CRITICAL + else: + level_number = logging.INFO + + level = logging.getLevelName(level_number) + + # The "root" logger should match the "console" level *unless* we also need + # to log to a user log file. + include_user_log = user_log_file is not None + if include_user_log: + additional_log_file = user_log_file + root_level = "DEBUG" + else: + additional_log_file = "/dev/null" + root_level = level + + # Disable any logging besides WARNING unless we have DEBUG level logging + # enabled for vendored libraries. + vendored_log_level = "WARNING" if level in ["INFO", "ERROR"] else "DEBUG" + + # Shorthands for clarity + log_streams = { + "stdout": "ext://sys.stdout", + "stderr": "ext://sys.stderr", + } + handler_classes = { + "stream": "pip._internal.utils.logging.RichPipStreamHandler", + "file": "pip._internal.utils.logging.BetterRotatingFileHandler", + } + handlers = ["console", "console_errors", "console_subprocess"] + ( + ["user_log"] if include_user_log else [] + ) + + logging.config.dictConfig( + { + "version": 1, + "disable_existing_loggers": False, + "filters": { + "exclude_warnings": { + "()": "pip._internal.utils.logging.MaxLevelFilter", + "level": logging.WARNING, + }, + "restrict_to_subprocess": { + "()": "logging.Filter", + "name": subprocess_logger.name, + }, + "exclude_subprocess": { + "()": "pip._internal.utils.logging.ExcludeLoggerFilter", + "name": subprocess_logger.name, + }, + }, + "formatters": { + "indent": { + "()": IndentingFormatter, + "format": "%(message)s", + }, + "indent_with_timestamp": { + "()": IndentingFormatter, + "format": "%(message)s", + "add_timestamp": True, + }, + }, + "handlers": { + "console": { + "level": level, + "class": handler_classes["stream"], + "no_color": no_color, + "stream": log_streams["stdout"], + "filters": ["exclude_subprocess", "exclude_warnings"], + "formatter": "indent", + }, + "console_errors": { + "level": "WARNING", + "class": handler_classes["stream"], + "no_color": no_color, + "stream": log_streams["stderr"], + "filters": ["exclude_subprocess"], + "formatter": "indent", + }, + # A handler responsible for logging to the console messages + # from the "subprocessor" logger. + "console_subprocess": { + "level": level, + "class": handler_classes["stream"], + "stream": log_streams["stderr"], + "no_color": no_color, + "filters": ["restrict_to_subprocess"], + "formatter": "indent", + }, + "user_log": { + "level": "DEBUG", + "class": handler_classes["file"], + "filename": additional_log_file, + "encoding": "utf-8", + "delay": True, + "formatter": "indent_with_timestamp", + }, + }, + "root": { + "level": root_level, + "handlers": handlers, + }, + "loggers": {"pip._vendor": {"level": vendored_log_level}}, + } + ) + + return level_number diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/misc.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/misc.py new file mode 100644 index 0000000..c0a3e4d --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/misc.py @@ -0,0 +1,772 @@ +import errno +import getpass +import hashlib +import logging +import os +import posixpath +import shutil +import stat +import sys +import sysconfig +import urllib.parse +from dataclasses import dataclass +from functools import partial +from io import StringIO +from itertools import filterfalse, tee, zip_longest +from pathlib import Path +from types import FunctionType, TracebackType +from typing import ( + Any, + BinaryIO, + Callable, + Dict, + Generator, + Iterable, + Iterator, + List, + Optional, + TextIO, + Tuple, + Type, + TypeVar, + Union, + cast, +) + +from pip._vendor.packaging.requirements import Requirement +from pip._vendor.pyproject_hooks import BuildBackendHookCaller + +from pip import __version__ +from pip._internal.exceptions import CommandError, ExternallyManagedEnvironment +from pip._internal.locations import get_major_minor_version +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.retry import retry +from pip._internal.utils.virtualenv import running_under_virtualenv + +__all__ = [ + "rmtree", + "display_path", + "backup_dir", + "ask", + "splitext", + "format_size", + "is_installable_dir", + "normalize_path", + "renames", + "get_prog", + "ensure_dir", + "remove_auth_from_url", + "check_externally_managed", + "ConfiguredBuildBackendHookCaller", +] + +logger = logging.getLogger(__name__) + +T = TypeVar("T") +ExcInfo = Tuple[Type[BaseException], BaseException, TracebackType] +VersionInfo = Tuple[int, int, int] +NetlocTuple = Tuple[str, Tuple[Optional[str], Optional[str]]] +OnExc = Callable[[FunctionType, Path, BaseException], Any] +OnErr = Callable[[FunctionType, Path, ExcInfo], Any] + +FILE_CHUNK_SIZE = 1024 * 1024 + + +def get_pip_version() -> str: + pip_pkg_dir = os.path.join(os.path.dirname(__file__), "..", "..") + pip_pkg_dir = os.path.abspath(pip_pkg_dir) + + return f"pip {__version__} from {pip_pkg_dir} (python {get_major_minor_version()})" + + +def normalize_version_info(py_version_info: Tuple[int, ...]) -> Tuple[int, int, int]: + """ + Convert a tuple of ints representing a Python version to one of length + three. + + :param py_version_info: a tuple of ints representing a Python version, + or None to specify no version. The tuple can have any length. + + :return: a tuple of length three if `py_version_info` is non-None. + Otherwise, return `py_version_info` unchanged (i.e. None). + """ + if len(py_version_info) < 3: + py_version_info += (3 - len(py_version_info)) * (0,) + elif len(py_version_info) > 3: + py_version_info = py_version_info[:3] + + return cast("VersionInfo", py_version_info) + + +def ensure_dir(path: str) -> None: + """os.path.makedirs without EEXIST.""" + try: + os.makedirs(path) + except OSError as e: + # Windows can raise spurious ENOTEMPTY errors. See #6426. + if e.errno != errno.EEXIST and e.errno != errno.ENOTEMPTY: + raise + + +def get_prog() -> str: + try: + prog = os.path.basename(sys.argv[0]) + if prog in ("__main__.py", "-c"): + return f"{sys.executable} -m pip" + else: + return prog + except (AttributeError, TypeError, IndexError): + pass + return "pip" + + +# Retry every half second for up to 3 seconds +@retry(stop_after_delay=3, wait=0.5) +def rmtree( + dir: str, ignore_errors: bool = False, onexc: Optional[OnExc] = None +) -> None: + if ignore_errors: + onexc = _onerror_ignore + if onexc is None: + onexc = _onerror_reraise + handler: OnErr = partial(rmtree_errorhandler, onexc=onexc) + if sys.version_info >= (3, 12): + # See https://docs.python.org/3.12/whatsnew/3.12.html#shutil. + shutil.rmtree(dir, onexc=handler) # type: ignore + else: + shutil.rmtree(dir, onerror=handler) # type: ignore + + +def _onerror_ignore(*_args: Any) -> None: + pass + + +def _onerror_reraise(*_args: Any) -> None: + raise # noqa: PLE0704 - Bare exception used to reraise existing exception + + +def rmtree_errorhandler( + func: FunctionType, + path: Path, + exc_info: Union[ExcInfo, BaseException], + *, + onexc: OnExc = _onerror_reraise, +) -> None: + """ + `rmtree` error handler to 'force' a file remove (i.e. like `rm -f`). + + * If a file is readonly then it's write flag is set and operation is + retried. + + * `onerror` is the original callback from `rmtree(... onerror=onerror)` + that is chained at the end if the "rm -f" still fails. + """ + try: + st_mode = os.stat(path).st_mode + except OSError: + # it's equivalent to os.path.exists + return + + if not st_mode & stat.S_IWRITE: + # convert to read/write + try: + os.chmod(path, st_mode | stat.S_IWRITE) + except OSError: + pass + else: + # use the original function to repeat the operation + try: + func(path) + return + except OSError: + pass + + if not isinstance(exc_info, BaseException): + _, exc_info, _ = exc_info + onexc(func, path, exc_info) + + +def display_path(path: str) -> str: + """Gives the display value for a given path, making it relative to cwd + if possible.""" + path = os.path.normcase(os.path.abspath(path)) + if path.startswith(os.getcwd() + os.path.sep): + path = "." + path[len(os.getcwd()) :] + return path + + +def backup_dir(dir: str, ext: str = ".bak") -> str: + """Figure out the name of a directory to back up the given dir to + (adding .bak, .bak2, etc)""" + n = 1 + extension = ext + while os.path.exists(dir + extension): + n += 1 + extension = ext + str(n) + return dir + extension + + +def ask_path_exists(message: str, options: Iterable[str]) -> str: + for action in os.environ.get("PIP_EXISTS_ACTION", "").split(): + if action in options: + return action + return ask(message, options) + + +def _check_no_input(message: str) -> None: + """Raise an error if no input is allowed.""" + if os.environ.get("PIP_NO_INPUT"): + raise Exception( + f"No input was expected ($PIP_NO_INPUT set); question: {message}" + ) + + +def ask(message: str, options: Iterable[str]) -> str: + """Ask the message interactively, with the given possible responses""" + while 1: + _check_no_input(message) + response = input(message) + response = response.strip().lower() + if response not in options: + print( + "Your response ({!r}) was not one of the expected responses: " + "{}".format(response, ", ".join(options)) + ) + else: + return response + + +def ask_input(message: str) -> str: + """Ask for input interactively.""" + _check_no_input(message) + return input(message) + + +def ask_password(message: str) -> str: + """Ask for a password interactively.""" + _check_no_input(message) + return getpass.getpass(message) + + +def strtobool(val: str) -> int: + """Convert a string representation of truth to true (1) or false (0). + + True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values + are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if + 'val' is anything else. + """ + val = val.lower() + if val in ("y", "yes", "t", "true", "on", "1"): + return 1 + elif val in ("n", "no", "f", "false", "off", "0"): + return 0 + else: + raise ValueError(f"invalid truth value {val!r}") + + +def format_size(bytes: float) -> str: + if bytes > 1000 * 1000: + return f"{bytes / 1000.0 / 1000:.1f} MB" + elif bytes > 10 * 1000: + return f"{int(bytes / 1000)} kB" + elif bytes > 1000: + return f"{bytes / 1000.0:.1f} kB" + else: + return f"{int(bytes)} bytes" + + +def tabulate(rows: Iterable[Iterable[Any]]) -> Tuple[List[str], List[int]]: + """Return a list of formatted rows and a list of column sizes. + + For example:: + + >>> tabulate([['foobar', 2000], [0xdeadbeef]]) + (['foobar 2000', '3735928559'], [10, 4]) + """ + rows = [tuple(map(str, row)) for row in rows] + sizes = [max(map(len, col)) for col in zip_longest(*rows, fillvalue="")] + table = [" ".join(map(str.ljust, row, sizes)).rstrip() for row in rows] + return table, sizes + + +def is_installable_dir(path: str) -> bool: + """Is path is a directory containing pyproject.toml or setup.py? + + If pyproject.toml exists, this is a PEP 517 project. Otherwise we look for + a legacy setuptools layout by identifying setup.py. We don't check for the + setup.cfg because using it without setup.py is only available for PEP 517 + projects, which are already covered by the pyproject.toml check. + """ + if not os.path.isdir(path): + return False + if os.path.isfile(os.path.join(path, "pyproject.toml")): + return True + if os.path.isfile(os.path.join(path, "setup.py")): + return True + return False + + +def read_chunks( + file: BinaryIO, size: int = FILE_CHUNK_SIZE +) -> Generator[bytes, None, None]: + """Yield pieces of data from a file-like object until EOF.""" + while True: + chunk = file.read(size) + if not chunk: + break + yield chunk + + +def normalize_path(path: str, resolve_symlinks: bool = True) -> str: + """ + Convert a path to its canonical, case-normalized, absolute version. + + """ + path = os.path.expanduser(path) + if resolve_symlinks: + path = os.path.realpath(path) + else: + path = os.path.abspath(path) + return os.path.normcase(path) + + +def splitext(path: str) -> Tuple[str, str]: + """Like os.path.splitext, but take off .tar too""" + base, ext = posixpath.splitext(path) + if base.lower().endswith(".tar"): + ext = base[-4:] + ext + base = base[:-4] + return base, ext + + +def renames(old: str, new: str) -> None: + """Like os.renames(), but handles renaming across devices.""" + # Implementation borrowed from os.renames(). + head, tail = os.path.split(new) + if head and tail and not os.path.exists(head): + os.makedirs(head) + + shutil.move(old, new) + + head, tail = os.path.split(old) + if head and tail: + try: + os.removedirs(head) + except OSError: + pass + + +def is_local(path: str) -> bool: + """ + Return True if path is within sys.prefix, if we're running in a virtualenv. + + If we're not in a virtualenv, all paths are considered "local." + + Caution: this function assumes the head of path has been normalized + with normalize_path. + """ + if not running_under_virtualenv(): + return True + return path.startswith(normalize_path(sys.prefix)) + + +def write_output(msg: Any, *args: Any) -> None: + logger.info(msg, *args) + + +class StreamWrapper(StringIO): + orig_stream: TextIO + + @classmethod + def from_stream(cls, orig_stream: TextIO) -> "StreamWrapper": + ret = cls() + ret.orig_stream = orig_stream + return ret + + # compileall.compile_dir() needs stdout.encoding to print to stdout + # type ignore is because TextIOBase.encoding is writeable + @property + def encoding(self) -> str: # type: ignore + return self.orig_stream.encoding + + +# Simulates an enum +def enum(*sequential: Any, **named: Any) -> Type[Any]: + enums = dict(zip(sequential, range(len(sequential))), **named) + reverse = {value: key for key, value in enums.items()} + enums["reverse_mapping"] = reverse + return type("Enum", (), enums) + + +def build_netloc(host: str, port: Optional[int]) -> str: + """ + Build a netloc from a host-port pair + """ + if port is None: + return host + if ":" in host: + # Only wrap host with square brackets when it is IPv6 + host = f"[{host}]" + return f"{host}:{port}" + + +def build_url_from_netloc(netloc: str, scheme: str = "https") -> str: + """ + Build a full URL from a netloc. + """ + if netloc.count(":") >= 2 and "@" not in netloc and "[" not in netloc: + # It must be a bare IPv6 address, so wrap it with brackets. + netloc = f"[{netloc}]" + return f"{scheme}://{netloc}" + + +def parse_netloc(netloc: str) -> Tuple[Optional[str], Optional[int]]: + """ + Return the host-port pair from a netloc. + """ + url = build_url_from_netloc(netloc) + parsed = urllib.parse.urlparse(url) + return parsed.hostname, parsed.port + + +def split_auth_from_netloc(netloc: str) -> NetlocTuple: + """ + Parse out and remove the auth information from a netloc. + + Returns: (netloc, (username, password)). + """ + if "@" not in netloc: + return netloc, (None, None) + + # Split from the right because that's how urllib.parse.urlsplit() + # behaves if more than one @ is present (which can be checked using + # the password attribute of urlsplit()'s return value). + auth, netloc = netloc.rsplit("@", 1) + pw: Optional[str] = None + if ":" in auth: + # Split from the left because that's how urllib.parse.urlsplit() + # behaves if more than one : is present (which again can be checked + # using the password attribute of the return value) + user, pw = auth.split(":", 1) + else: + user, pw = auth, None + + user = urllib.parse.unquote(user) + if pw is not None: + pw = urllib.parse.unquote(pw) + + return netloc, (user, pw) + + +def redact_netloc(netloc: str) -> str: + """ + Replace the sensitive data in a netloc with "****", if it exists. + + For example: + - "user:pass@example.com" returns "user:****@example.com" + - "accesstoken@example.com" returns "****@example.com" + """ + netloc, (user, password) = split_auth_from_netloc(netloc) + if user is None: + return netloc + if password is None: + user = "****" + password = "" + else: + user = urllib.parse.quote(user) + password = ":****" + return f"{user}{password}@{netloc}" + + +def _transform_url( + url: str, transform_netloc: Callable[[str], Tuple[Any, ...]] +) -> Tuple[str, NetlocTuple]: + """Transform and replace netloc in a url. + + transform_netloc is a function taking the netloc and returning a + tuple. The first element of this tuple is the new netloc. The + entire tuple is returned. + + Returns a tuple containing the transformed url as item 0 and the + original tuple returned by transform_netloc as item 1. + """ + purl = urllib.parse.urlsplit(url) + netloc_tuple = transform_netloc(purl.netloc) + # stripped url + url_pieces = (purl.scheme, netloc_tuple[0], purl.path, purl.query, purl.fragment) + surl = urllib.parse.urlunsplit(url_pieces) + return surl, cast("NetlocTuple", netloc_tuple) + + +def _get_netloc(netloc: str) -> NetlocTuple: + return split_auth_from_netloc(netloc) + + +def _redact_netloc(netloc: str) -> Tuple[str]: + return (redact_netloc(netloc),) + + +def split_auth_netloc_from_url( + url: str, +) -> Tuple[str, str, Tuple[Optional[str], Optional[str]]]: + """ + Parse a url into separate netloc, auth, and url with no auth. + + Returns: (url_without_auth, netloc, (username, password)) + """ + url_without_auth, (netloc, auth) = _transform_url(url, _get_netloc) + return url_without_auth, netloc, auth + + +def remove_auth_from_url(url: str) -> str: + """Return a copy of url with 'username:password@' removed.""" + # username/pass params are passed to subversion through flags + # and are not recognized in the url. + return _transform_url(url, _get_netloc)[0] + + +def redact_auth_from_url(url: str) -> str: + """Replace the password in a given url with ****.""" + return _transform_url(url, _redact_netloc)[0] + + +def redact_auth_from_requirement(req: Requirement) -> str: + """Replace the password in a given requirement url with ****.""" + if not req.url: + return str(req) + return str(req).replace(req.url, redact_auth_from_url(req.url)) + + +@dataclass(frozen=True) +class HiddenText: + secret: str + redacted: str + + def __repr__(self) -> str: + return f"" + + def __str__(self) -> str: + return self.redacted + + # This is useful for testing. + def __eq__(self, other: Any) -> bool: + if type(self) is not type(other): + return False + + # The string being used for redaction doesn't also have to match, + # just the raw, original string. + return self.secret == other.secret + + +def hide_value(value: str) -> HiddenText: + return HiddenText(value, redacted="****") + + +def hide_url(url: str) -> HiddenText: + redacted = redact_auth_from_url(url) + return HiddenText(url, redacted=redacted) + + +def protect_pip_from_modification_on_windows(modifying_pip: bool) -> None: + """Protection of pip.exe from modification on Windows + + On Windows, any operation modifying pip should be run as: + python -m pip ... + """ + pip_names = [ + "pip", + f"pip{sys.version_info.major}", + f"pip{sys.version_info.major}.{sys.version_info.minor}", + ] + + # See https://github.com/pypa/pip/issues/1299 for more discussion + should_show_use_python_msg = ( + modifying_pip and WINDOWS and os.path.basename(sys.argv[0]) in pip_names + ) + + if should_show_use_python_msg: + new_command = [sys.executable, "-m", "pip"] + sys.argv[1:] + raise CommandError( + "To modify pip, please run the following command:\n{}".format( + " ".join(new_command) + ) + ) + + +def check_externally_managed() -> None: + """Check whether the current environment is externally managed. + + If the ``EXTERNALLY-MANAGED`` config file is found, the current environment + is considered externally managed, and an ExternallyManagedEnvironment is + raised. + """ + if running_under_virtualenv(): + return + marker = os.path.join(sysconfig.get_path("stdlib"), "EXTERNALLY-MANAGED") + if not os.path.isfile(marker): + return + raise ExternallyManagedEnvironment.from_config(marker) + + +def is_console_interactive() -> bool: + """Is this console interactive?""" + return sys.stdin is not None and sys.stdin.isatty() + + +def hash_file(path: str, blocksize: int = 1 << 20) -> Tuple[Any, int]: + """Return (hash, length) for path using hashlib.sha256()""" + + h = hashlib.sha256() + length = 0 + with open(path, "rb") as f: + for block in read_chunks(f, size=blocksize): + length += len(block) + h.update(block) + return h, length + + +def pairwise(iterable: Iterable[Any]) -> Iterator[Tuple[Any, Any]]: + """ + Return paired elements. + + For example: + s -> (s0, s1), (s2, s3), (s4, s5), ... + """ + iterable = iter(iterable) + return zip_longest(iterable, iterable) + + +def partition( + pred: Callable[[T], bool], iterable: Iterable[T] +) -> Tuple[Iterable[T], Iterable[T]]: + """ + Use a predicate to partition entries into false entries and true entries, + like + + partition(is_odd, range(10)) --> 0 2 4 6 8 and 1 3 5 7 9 + """ + t1, t2 = tee(iterable) + return filterfalse(pred, t1), filter(pred, t2) + + +class ConfiguredBuildBackendHookCaller(BuildBackendHookCaller): + def __init__( + self, + config_holder: Any, + source_dir: str, + build_backend: str, + backend_path: Optional[str] = None, + runner: Optional[Callable[..., None]] = None, + python_executable: Optional[str] = None, + ): + super().__init__( + source_dir, build_backend, backend_path, runner, python_executable + ) + self.config_holder = config_holder + + def build_wheel( + self, + wheel_directory: str, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, + metadata_directory: Optional[str] = None, + ) -> str: + cs = self.config_holder.config_settings + return super().build_wheel( + wheel_directory, config_settings=cs, metadata_directory=metadata_directory + ) + + def build_sdist( + self, + sdist_directory: str, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, + ) -> str: + cs = self.config_holder.config_settings + return super().build_sdist(sdist_directory, config_settings=cs) + + def build_editable( + self, + wheel_directory: str, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, + metadata_directory: Optional[str] = None, + ) -> str: + cs = self.config_holder.config_settings + return super().build_editable( + wheel_directory, config_settings=cs, metadata_directory=metadata_directory + ) + + def get_requires_for_build_wheel( + self, config_settings: Optional[Dict[str, Union[str, List[str]]]] = None + ) -> List[str]: + cs = self.config_holder.config_settings + return super().get_requires_for_build_wheel(config_settings=cs) + + def get_requires_for_build_sdist( + self, config_settings: Optional[Dict[str, Union[str, List[str]]]] = None + ) -> List[str]: + cs = self.config_holder.config_settings + return super().get_requires_for_build_sdist(config_settings=cs) + + def get_requires_for_build_editable( + self, config_settings: Optional[Dict[str, Union[str, List[str]]]] = None + ) -> List[str]: + cs = self.config_holder.config_settings + return super().get_requires_for_build_editable(config_settings=cs) + + def prepare_metadata_for_build_wheel( + self, + metadata_directory: str, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, + _allow_fallback: bool = True, + ) -> str: + cs = self.config_holder.config_settings + return super().prepare_metadata_for_build_wheel( + metadata_directory=metadata_directory, + config_settings=cs, + _allow_fallback=_allow_fallback, + ) + + def prepare_metadata_for_build_editable( + self, + metadata_directory: str, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, + _allow_fallback: bool = True, + ) -> str: + cs = self.config_holder.config_settings + return super().prepare_metadata_for_build_editable( + metadata_directory=metadata_directory, + config_settings=cs, + _allow_fallback=_allow_fallback, + ) + + +def warn_if_run_as_root() -> None: + """Output a warning for sudo users on Unix. + + In a virtual environment, sudo pip still writes to virtualenv. + On Windows, users may run pip as Administrator without issues. + This warning only applies to Unix root users outside of virtualenv. + """ + if running_under_virtualenv(): + return + if not hasattr(os, "getuid"): + return + # On Windows, there are no "system managed" Python packages. Installing as + # Administrator via pip is the correct way of updating system environments. + # + # We choose sys.platform over utils.compat.WINDOWS here to enable Mypy platform + # checks: https://mypy.readthedocs.io/en/stable/common_issues.html + if sys.platform == "win32" or sys.platform == "cygwin": + return + + if os.getuid() != 0: + return + + logger.warning( + "Running pip as the 'root' user can result in broken permissions and " + "conflicting behaviour with the system package manager, possibly " + "rendering your system unusable." + "It is recommended to use a virtual environment instead: " + "https://pip.pypa.io/warnings/venv. " + "Use the --root-user-action option if you know what you are doing and " + "want to suppress this warning." + ) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/packaging.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/packaging.py new file mode 100644 index 0000000..4b8fa0f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/packaging.py @@ -0,0 +1,57 @@ +import functools +import logging +import re +from typing import NewType, Optional, Tuple, cast + +from pip._vendor.packaging import specifiers, version +from pip._vendor.packaging.requirements import Requirement + +NormalizedExtra = NewType("NormalizedExtra", str) + +logger = logging.getLogger(__name__) + + +def check_requires_python( + requires_python: Optional[str], version_info: Tuple[int, ...] +) -> bool: + """ + Check if the given Python version matches a "Requires-Python" specifier. + + :param version_info: A 3-tuple of ints representing a Python + major-minor-micro version to check (e.g. `sys.version_info[:3]`). + + :return: `True` if the given Python version satisfies the requirement. + Otherwise, return `False`. + + :raises InvalidSpecifier: If `requires_python` has an invalid format. + """ + if requires_python is None: + # The package provides no information + return True + requires_python_specifier = specifiers.SpecifierSet(requires_python) + + python_version = version.parse(".".join(map(str, version_info))) + return python_version in requires_python_specifier + + +@functools.lru_cache(maxsize=2048) +def get_requirement(req_string: str) -> Requirement: + """Construct a packaging.Requirement object with caching""" + # Parsing requirement strings is expensive, and is also expected to happen + # with a low diversity of different arguments (at least relative the number + # constructed). This method adds a cache to requirement object creation to + # minimize repeated parsing of the same string to construct equivalent + # Requirement objects. + return Requirement(req_string) + + +def safe_extra(extra: str) -> NormalizedExtra: + """Convert an arbitrary string to a standard 'extra' name + + Any runs of non-alphanumeric characters are replaced with a single '_', + and the result is always lowercased. + + This function is duplicated from ``pkg_resources``. Note that this is not + the same to either ``canonicalize_name`` or ``_egg_link_name``. + """ + return cast(NormalizedExtra, re.sub("[^A-Za-z0-9.-]+", "_", extra).lower()) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/retry.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/retry.py new file mode 100644 index 0000000..abfe072 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/retry.py @@ -0,0 +1,42 @@ +import functools +from time import perf_counter, sleep +from typing import Callable, TypeVar + +from pip._vendor.typing_extensions import ParamSpec + +T = TypeVar("T") +P = ParamSpec("P") + + +def retry( + wait: float, stop_after_delay: float +) -> Callable[[Callable[P, T]], Callable[P, T]]: + """Decorator to automatically retry a function on error. + + If the function raises, the function is recalled with the same arguments + until it returns or the time limit is reached. When the time limit is + surpassed, the last exception raised is reraised. + + :param wait: The time to wait after an error before retrying, in seconds. + :param stop_after_delay: The time limit after which retries will cease, + in seconds. + """ + + def wrapper(func: Callable[P, T]) -> Callable[P, T]: + + @functools.wraps(func) + def retry_wrapped(*args: P.args, **kwargs: P.kwargs) -> T: + # The performance counter is monotonic on all platforms we care + # about and has much better resolution than time.monotonic(). + start_time = perf_counter() + while True: + try: + return func(*args, **kwargs) + except Exception: + if perf_counter() - start_time > stop_after_delay: + raise + sleep(wait) + + return retry_wrapped + + return wrapper diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/setuptools_build.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/setuptools_build.py new file mode 100644 index 0000000..96d1b24 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/setuptools_build.py @@ -0,0 +1,146 @@ +import sys +import textwrap +from typing import List, Optional, Sequence + +# Shim to wrap setup.py invocation with setuptools +# Note that __file__ is handled via two {!r} *and* %r, to ensure that paths on +# Windows are correctly handled (it should be "C:\\Users" not "C:\Users"). +_SETUPTOOLS_SHIM = textwrap.dedent( + """ + exec(compile(''' + # This is -- a caller that pip uses to run setup.py + # + # - It imports setuptools before invoking setup.py, to enable projects that directly + # import from `distutils.core` to work with newer packaging standards. + # - It provides a clear error message when setuptools is not installed. + # - It sets `sys.argv[0]` to the underlying `setup.py`, when invoking `setup.py` so + # setuptools doesn't think the script is `-c`. This avoids the following warning: + # manifest_maker: standard file '-c' not found". + # - It generates a shim setup.py, for handling setup.cfg-only projects. + import os, sys, tokenize + + try: + import setuptools + except ImportError as error: + print( + "ERROR: Can not execute `setup.py` since setuptools is not available in " + "the build environment.", + file=sys.stderr, + ) + sys.exit(1) + + __file__ = %r + sys.argv[0] = __file__ + + if os.path.exists(__file__): + filename = __file__ + with tokenize.open(__file__) as f: + setup_py_code = f.read() + else: + filename = "" + setup_py_code = "from setuptools import setup; setup()" + + exec(compile(setup_py_code, filename, "exec")) + ''' % ({!r},), "", "exec")) + """ +).rstrip() + + +def make_setuptools_shim_args( + setup_py_path: str, + global_options: Optional[Sequence[str]] = None, + no_user_config: bool = False, + unbuffered_output: bool = False, +) -> List[str]: + """ + Get setuptools command arguments with shim wrapped setup file invocation. + + :param setup_py_path: The path to setup.py to be wrapped. + :param global_options: Additional global options. + :param no_user_config: If True, disables personal user configuration. + :param unbuffered_output: If True, adds the unbuffered switch to the + argument list. + """ + args = [sys.executable] + if unbuffered_output: + args += ["-u"] + args += ["-c", _SETUPTOOLS_SHIM.format(setup_py_path)] + if global_options: + args += global_options + if no_user_config: + args += ["--no-user-cfg"] + return args + + +def make_setuptools_bdist_wheel_args( + setup_py_path: str, + global_options: Sequence[str], + build_options: Sequence[str], + destination_dir: str, +) -> List[str]: + # NOTE: Eventually, we'd want to also -S to the flags here, when we're + # isolating. Currently, it breaks Python in virtualenvs, because it + # relies on site.py to find parts of the standard library outside the + # virtualenv. + args = make_setuptools_shim_args( + setup_py_path, global_options=global_options, unbuffered_output=True + ) + args += ["bdist_wheel", "-d", destination_dir] + args += build_options + return args + + +def make_setuptools_clean_args( + setup_py_path: str, + global_options: Sequence[str], +) -> List[str]: + args = make_setuptools_shim_args( + setup_py_path, global_options=global_options, unbuffered_output=True + ) + args += ["clean", "--all"] + return args + + +def make_setuptools_develop_args( + setup_py_path: str, + *, + global_options: Sequence[str], + no_user_config: bool, + prefix: Optional[str], + home: Optional[str], + use_user_site: bool, +) -> List[str]: + assert not (use_user_site and prefix) + + args = make_setuptools_shim_args( + setup_py_path, + global_options=global_options, + no_user_config=no_user_config, + ) + + args += ["develop", "--no-deps"] + + if prefix: + args += ["--prefix", prefix] + if home is not None: + args += ["--install-dir", home] + + if use_user_site: + args += ["--user", "--prefix="] + + return args + + +def make_setuptools_egg_info_args( + setup_py_path: str, + egg_info_dir: Optional[str], + no_user_config: bool, +) -> List[str]: + args = make_setuptools_shim_args(setup_py_path, no_user_config=no_user_config) + + args += ["egg_info"] + + if egg_info_dir: + args += ["--egg-base", egg_info_dir] + + return args diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/subprocess.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/subprocess.py new file mode 100644 index 0000000..cb2e23f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/subprocess.py @@ -0,0 +1,245 @@ +import logging +import os +import shlex +import subprocess +from typing import Any, Callable, Iterable, List, Literal, Mapping, Optional, Union + +from pip._vendor.rich.markup import escape + +from pip._internal.cli.spinners import SpinnerInterface, open_spinner +from pip._internal.exceptions import InstallationSubprocessError +from pip._internal.utils.logging import VERBOSE, subprocess_logger +from pip._internal.utils.misc import HiddenText + +CommandArgs = List[Union[str, HiddenText]] + + +def make_command(*args: Union[str, HiddenText, CommandArgs]) -> CommandArgs: + """ + Create a CommandArgs object. + """ + command_args: CommandArgs = [] + for arg in args: + # Check for list instead of CommandArgs since CommandArgs is + # only known during type-checking. + if isinstance(arg, list): + command_args.extend(arg) + else: + # Otherwise, arg is str or HiddenText. + command_args.append(arg) + + return command_args + + +def format_command_args(args: Union[List[str], CommandArgs]) -> str: + """ + Format command arguments for display. + """ + # For HiddenText arguments, display the redacted form by calling str(). + # Also, we don't apply str() to arguments that aren't HiddenText since + # this can trigger a UnicodeDecodeError in Python 2 if the argument + # has type unicode and includes a non-ascii character. (The type + # checker doesn't ensure the annotations are correct in all cases.) + return " ".join( + shlex.quote(str(arg)) if isinstance(arg, HiddenText) else shlex.quote(arg) + for arg in args + ) + + +def reveal_command_args(args: Union[List[str], CommandArgs]) -> List[str]: + """ + Return the arguments in their raw, unredacted form. + """ + return [arg.secret if isinstance(arg, HiddenText) else arg for arg in args] + + +def call_subprocess( + cmd: Union[List[str], CommandArgs], + show_stdout: bool = False, + cwd: Optional[str] = None, + on_returncode: 'Literal["raise", "warn", "ignore"]' = "raise", + extra_ok_returncodes: Optional[Iterable[int]] = None, + extra_environ: Optional[Mapping[str, Any]] = None, + unset_environ: Optional[Iterable[str]] = None, + spinner: Optional[SpinnerInterface] = None, + log_failed_cmd: Optional[bool] = True, + stdout_only: Optional[bool] = False, + *, + command_desc: str, +) -> str: + """ + Args: + show_stdout: if true, use INFO to log the subprocess's stderr and + stdout streams. Otherwise, use DEBUG. Defaults to False. + extra_ok_returncodes: an iterable of integer return codes that are + acceptable, in addition to 0. Defaults to None, which means []. + unset_environ: an iterable of environment variable names to unset + prior to calling subprocess.Popen(). + log_failed_cmd: if false, failed commands are not logged, only raised. + stdout_only: if true, return only stdout, else return both. When true, + logging of both stdout and stderr occurs when the subprocess has + terminated, else logging occurs as subprocess output is produced. + """ + if extra_ok_returncodes is None: + extra_ok_returncodes = [] + if unset_environ is None: + unset_environ = [] + # Most places in pip use show_stdout=False. What this means is-- + # + # - We connect the child's output (combined stderr and stdout) to a + # single pipe, which we read. + # - We log this output to stderr at DEBUG level as it is received. + # - If DEBUG logging isn't enabled (e.g. if --verbose logging wasn't + # requested), then we show a spinner so the user can still see the + # subprocess is in progress. + # - If the subprocess exits with an error, we log the output to stderr + # at ERROR level if it hasn't already been displayed to the console + # (e.g. if --verbose logging wasn't enabled). This way we don't log + # the output to the console twice. + # + # If show_stdout=True, then the above is still done, but with DEBUG + # replaced by INFO. + if show_stdout: + # Then log the subprocess output at INFO level. + log_subprocess: Callable[..., None] = subprocess_logger.info + used_level = logging.INFO + else: + # Then log the subprocess output using VERBOSE. This also ensures + # it will be logged to the log file (aka user_log), if enabled. + log_subprocess = subprocess_logger.verbose + used_level = VERBOSE + + # Whether the subprocess will be visible in the console. + showing_subprocess = subprocess_logger.getEffectiveLevel() <= used_level + + # Only use the spinner if we're not showing the subprocess output + # and we have a spinner. + use_spinner = not showing_subprocess and spinner is not None + + log_subprocess("Running command %s", command_desc) + env = os.environ.copy() + if extra_environ: + env.update(extra_environ) + for name in unset_environ: + env.pop(name, None) + try: + proc = subprocess.Popen( + # Convert HiddenText objects to the underlying str. + reveal_command_args(cmd), + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT if not stdout_only else subprocess.PIPE, + cwd=cwd, + env=env, + errors="backslashreplace", + ) + except Exception as exc: + if log_failed_cmd: + subprocess_logger.critical( + "Error %s while executing command %s", + exc, + command_desc, + ) + raise + all_output = [] + if not stdout_only: + assert proc.stdout + assert proc.stdin + proc.stdin.close() + # In this mode, stdout and stderr are in the same pipe. + while True: + line: str = proc.stdout.readline() + if not line: + break + line = line.rstrip() + all_output.append(line + "\n") + + # Show the line immediately. + log_subprocess(line) + # Update the spinner. + if use_spinner: + assert spinner + spinner.spin() + try: + proc.wait() + finally: + if proc.stdout: + proc.stdout.close() + output = "".join(all_output) + else: + # In this mode, stdout and stderr are in different pipes. + # We must use communicate() which is the only safe way to read both. + out, err = proc.communicate() + # log line by line to preserve pip log indenting + for out_line in out.splitlines(): + log_subprocess(out_line) + all_output.append(out) + for err_line in err.splitlines(): + log_subprocess(err_line) + all_output.append(err) + output = out + + proc_had_error = proc.returncode and proc.returncode not in extra_ok_returncodes + if use_spinner: + assert spinner + if proc_had_error: + spinner.finish("error") + else: + spinner.finish("done") + if proc_had_error: + if on_returncode == "raise": + error = InstallationSubprocessError( + command_description=command_desc, + exit_code=proc.returncode, + output_lines=all_output if not showing_subprocess else None, + ) + if log_failed_cmd: + subprocess_logger.error("%s", error, extra={"rich": True}) + subprocess_logger.verbose( + "[bold magenta]full command[/]: [blue]%s[/]", + escape(format_command_args(cmd)), + extra={"markup": True}, + ) + subprocess_logger.verbose( + "[bold magenta]cwd[/]: %s", + escape(cwd or "[inherit]"), + extra={"markup": True}, + ) + + raise error + elif on_returncode == "warn": + subprocess_logger.warning( + 'Command "%s" had error code %s in %s', + command_desc, + proc.returncode, + cwd, + ) + elif on_returncode == "ignore": + pass + else: + raise ValueError(f"Invalid value: on_returncode={on_returncode!r}") + return output + + +def runner_with_spinner_message(message: str) -> Callable[..., None]: + """Provide a subprocess_runner that shows a spinner message. + + Intended for use with for BuildBackendHookCaller. Thus, the runner has + an API that matches what's expected by BuildBackendHookCaller.subprocess_runner. + """ + + def runner( + cmd: List[str], + cwd: Optional[str] = None, + extra_environ: Optional[Mapping[str, Any]] = None, + ) -> None: + with open_spinner(message) as spinner: + call_subprocess( + cmd, + command_desc=message, + cwd=cwd, + extra_environ=extra_environ, + spinner=spinner, + ) + + return runner diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/temp_dir.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/temp_dir.py new file mode 100644 index 0000000..06668e8 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/temp_dir.py @@ -0,0 +1,296 @@ +import errno +import itertools +import logging +import os.path +import tempfile +import traceback +from contextlib import ExitStack, contextmanager +from pathlib import Path +from typing import ( + Any, + Callable, + Dict, + Generator, + List, + Optional, + TypeVar, + Union, +) + +from pip._internal.utils.misc import enum, rmtree + +logger = logging.getLogger(__name__) + +_T = TypeVar("_T", bound="TempDirectory") + + +# Kinds of temporary directories. Only needed for ones that are +# globally-managed. +tempdir_kinds = enum( + BUILD_ENV="build-env", + EPHEM_WHEEL_CACHE="ephem-wheel-cache", + REQ_BUILD="req-build", +) + + +_tempdir_manager: Optional[ExitStack] = None + + +@contextmanager +def global_tempdir_manager() -> Generator[None, None, None]: + global _tempdir_manager + with ExitStack() as stack: + old_tempdir_manager, _tempdir_manager = _tempdir_manager, stack + try: + yield + finally: + _tempdir_manager = old_tempdir_manager + + +class TempDirectoryTypeRegistry: + """Manages temp directory behavior""" + + def __init__(self) -> None: + self._should_delete: Dict[str, bool] = {} + + def set_delete(self, kind: str, value: bool) -> None: + """Indicate whether a TempDirectory of the given kind should be + auto-deleted. + """ + self._should_delete[kind] = value + + def get_delete(self, kind: str) -> bool: + """Get configured auto-delete flag for a given TempDirectory type, + default True. + """ + return self._should_delete.get(kind, True) + + +_tempdir_registry: Optional[TempDirectoryTypeRegistry] = None + + +@contextmanager +def tempdir_registry() -> Generator[TempDirectoryTypeRegistry, None, None]: + """Provides a scoped global tempdir registry that can be used to dictate + whether directories should be deleted. + """ + global _tempdir_registry + old_tempdir_registry = _tempdir_registry + _tempdir_registry = TempDirectoryTypeRegistry() + try: + yield _tempdir_registry + finally: + _tempdir_registry = old_tempdir_registry + + +class _Default: + pass + + +_default = _Default() + + +class TempDirectory: + """Helper class that owns and cleans up a temporary directory. + + This class can be used as a context manager or as an OO representation of a + temporary directory. + + Attributes: + path + Location to the created temporary directory + delete + Whether the directory should be deleted when exiting + (when used as a contextmanager) + + Methods: + cleanup() + Deletes the temporary directory + + When used as a context manager, if the delete attribute is True, on + exiting the context the temporary directory is deleted. + """ + + def __init__( + self, + path: Optional[str] = None, + delete: Union[bool, None, _Default] = _default, + kind: str = "temp", + globally_managed: bool = False, + ignore_cleanup_errors: bool = True, + ): + super().__init__() + + if delete is _default: + if path is not None: + # If we were given an explicit directory, resolve delete option + # now. + delete = False + else: + # Otherwise, we wait until cleanup and see what + # tempdir_registry says. + delete = None + + # The only time we specify path is in for editables where it + # is the value of the --src option. + if path is None: + path = self._create(kind) + + self._path = path + self._deleted = False + self.delete = delete + self.kind = kind + self.ignore_cleanup_errors = ignore_cleanup_errors + + if globally_managed: + assert _tempdir_manager is not None + _tempdir_manager.enter_context(self) + + @property + def path(self) -> str: + assert not self._deleted, f"Attempted to access deleted path: {self._path}" + return self._path + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} {self.path!r}>" + + def __enter__(self: _T) -> _T: + return self + + def __exit__(self, exc: Any, value: Any, tb: Any) -> None: + if self.delete is not None: + delete = self.delete + elif _tempdir_registry: + delete = _tempdir_registry.get_delete(self.kind) + else: + delete = True + + if delete: + self.cleanup() + + def _create(self, kind: str) -> str: + """Create a temporary directory and store its path in self.path""" + # We realpath here because some systems have their default tmpdir + # symlinked to another directory. This tends to confuse build + # scripts, so we canonicalize the path by traversing potential + # symlinks here. + path = os.path.realpath(tempfile.mkdtemp(prefix=f"pip-{kind}-")) + logger.debug("Created temporary directory: %s", path) + return path + + def cleanup(self) -> None: + """Remove the temporary directory created and reset state""" + self._deleted = True + if not os.path.exists(self._path): + return + + errors: List[BaseException] = [] + + def onerror( + func: Callable[..., Any], + path: Path, + exc_val: BaseException, + ) -> None: + """Log a warning for a `rmtree` error and continue""" + formatted_exc = "\n".join( + traceback.format_exception_only(type(exc_val), exc_val) + ) + formatted_exc = formatted_exc.rstrip() # remove trailing new line + if func in (os.unlink, os.remove, os.rmdir): + logger.debug( + "Failed to remove a temporary file '%s' due to %s.\n", + path, + formatted_exc, + ) + else: + logger.debug("%s failed with %s.", func.__qualname__, formatted_exc) + errors.append(exc_val) + + if self.ignore_cleanup_errors: + try: + # first try with @retry; retrying to handle ephemeral errors + rmtree(self._path, ignore_errors=False) + except OSError: + # last pass ignore/log all errors + rmtree(self._path, onexc=onerror) + if errors: + logger.warning( + "Failed to remove contents in a temporary directory '%s'.\n" + "You can safely remove it manually.", + self._path, + ) + else: + rmtree(self._path) + + +class AdjacentTempDirectory(TempDirectory): + """Helper class that creates a temporary directory adjacent to a real one. + + Attributes: + original + The original directory to create a temp directory for. + path + After calling create() or entering, contains the full + path to the temporary directory. + delete + Whether the directory should be deleted when exiting + (when used as a contextmanager) + + """ + + # The characters that may be used to name the temp directory + # We always prepend a ~ and then rotate through these until + # a usable name is found. + # pkg_resources raises a different error for .dist-info folder + # with leading '-' and invalid metadata + LEADING_CHARS = "-~.=%0123456789" + + def __init__(self, original: str, delete: Optional[bool] = None) -> None: + self.original = original.rstrip("/\\") + super().__init__(delete=delete) + + @classmethod + def _generate_names(cls, name: str) -> Generator[str, None, None]: + """Generates a series of temporary names. + + The algorithm replaces the leading characters in the name + with ones that are valid filesystem characters, but are not + valid package names (for both Python and pip definitions of + package). + """ + for i in range(1, len(name)): + for candidate in itertools.combinations_with_replacement( + cls.LEADING_CHARS, i - 1 + ): + new_name = "~" + "".join(candidate) + name[i:] + if new_name != name: + yield new_name + + # If we make it this far, we will have to make a longer name + for i in range(len(cls.LEADING_CHARS)): + for candidate in itertools.combinations_with_replacement( + cls.LEADING_CHARS, i + ): + new_name = "~" + "".join(candidate) + name + if new_name != name: + yield new_name + + def _create(self, kind: str) -> str: + root, name = os.path.split(self.original) + for candidate in self._generate_names(name): + path = os.path.join(root, candidate) + try: + os.mkdir(path) + except OSError as ex: + # Continue if the name exists already + if ex.errno != errno.EEXIST: + raise + else: + path = os.path.realpath(path) + break + else: + # Final fallback on the default behavior. + path = os.path.realpath(tempfile.mkdtemp(prefix=f"pip-{kind}-")) + + logger.debug("Created temporary directory: %s", path) + return path diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/unpacking.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/unpacking.py new file mode 100644 index 0000000..875e30e --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/unpacking.py @@ -0,0 +1,337 @@ +"""Utilities related archives. +""" + +import logging +import os +import shutil +import stat +import sys +import tarfile +import zipfile +from typing import Iterable, List, Optional +from zipfile import ZipInfo + +from pip._internal.exceptions import InstallationError +from pip._internal.utils.filetypes import ( + BZ2_EXTENSIONS, + TAR_EXTENSIONS, + XZ_EXTENSIONS, + ZIP_EXTENSIONS, +) +from pip._internal.utils.misc import ensure_dir + +logger = logging.getLogger(__name__) + + +SUPPORTED_EXTENSIONS = ZIP_EXTENSIONS + TAR_EXTENSIONS + +try: + import bz2 # noqa + + SUPPORTED_EXTENSIONS += BZ2_EXTENSIONS +except ImportError: + logger.debug("bz2 module is not available") + +try: + # Only for Python 3.3+ + import lzma # noqa + + SUPPORTED_EXTENSIONS += XZ_EXTENSIONS +except ImportError: + logger.debug("lzma module is not available") + + +def current_umask() -> int: + """Get the current umask which involves having to set it temporarily.""" + mask = os.umask(0) + os.umask(mask) + return mask + + +def split_leading_dir(path: str) -> List[str]: + path = path.lstrip("/").lstrip("\\") + if "/" in path and ( + ("\\" in path and path.find("/") < path.find("\\")) or "\\" not in path + ): + return path.split("/", 1) + elif "\\" in path: + return path.split("\\", 1) + else: + return [path, ""] + + +def has_leading_dir(paths: Iterable[str]) -> bool: + """Returns true if all the paths have the same leading path name + (i.e., everything is in one subdirectory in an archive)""" + common_prefix = None + for path in paths: + prefix, rest = split_leading_dir(path) + if not prefix: + return False + elif common_prefix is None: + common_prefix = prefix + elif prefix != common_prefix: + return False + return True + + +def is_within_directory(directory: str, target: str) -> bool: + """ + Return true if the absolute path of target is within the directory + """ + abs_directory = os.path.abspath(directory) + abs_target = os.path.abspath(target) + + prefix = os.path.commonprefix([abs_directory, abs_target]) + return prefix == abs_directory + + +def _get_default_mode_plus_executable() -> int: + return 0o777 & ~current_umask() | 0o111 + + +def set_extracted_file_to_default_mode_plus_executable(path: str) -> None: + """ + Make file present at path have execute for user/group/world + (chmod +x) is no-op on windows per python docs + """ + os.chmod(path, _get_default_mode_plus_executable()) + + +def zip_item_is_executable(info: ZipInfo) -> bool: + mode = info.external_attr >> 16 + # if mode and regular file and any execute permissions for + # user/group/world? + return bool(mode and stat.S_ISREG(mode) and mode & 0o111) + + +def unzip_file(filename: str, location: str, flatten: bool = True) -> None: + """ + Unzip the file (with path `filename`) to the destination `location`. All + files are written based on system defaults and umask (i.e. permissions are + not preserved), except that regular file members with any execute + permissions (user, group, or world) have "chmod +x" applied after being + written. Note that for windows, any execute changes using os.chmod are + no-ops per the python docs. + """ + ensure_dir(location) + zipfp = open(filename, "rb") + try: + zip = zipfile.ZipFile(zipfp, allowZip64=True) + leading = has_leading_dir(zip.namelist()) and flatten + for info in zip.infolist(): + name = info.filename + fn = name + if leading: + fn = split_leading_dir(name)[1] + fn = os.path.join(location, fn) + dir = os.path.dirname(fn) + if not is_within_directory(location, fn): + message = ( + "The zip file ({}) has a file ({}) trying to install " + "outside target directory ({})" + ) + raise InstallationError(message.format(filename, fn, location)) + if fn.endswith("/") or fn.endswith("\\"): + # A directory + ensure_dir(fn) + else: + ensure_dir(dir) + # Don't use read() to avoid allocating an arbitrarily large + # chunk of memory for the file's content + fp = zip.open(name) + try: + with open(fn, "wb") as destfp: + shutil.copyfileobj(fp, destfp) + finally: + fp.close() + if zip_item_is_executable(info): + set_extracted_file_to_default_mode_plus_executable(fn) + finally: + zipfp.close() + + +def untar_file(filename: str, location: str) -> None: + """ + Untar the file (with path `filename`) to the destination `location`. + All files are written based on system defaults and umask (i.e. permissions + are not preserved), except that regular file members with any execute + permissions (user, group, or world) have "chmod +x" applied on top of the + default. Note that for windows, any execute changes using os.chmod are + no-ops per the python docs. + """ + ensure_dir(location) + if filename.lower().endswith(".gz") or filename.lower().endswith(".tgz"): + mode = "r:gz" + elif filename.lower().endswith(BZ2_EXTENSIONS): + mode = "r:bz2" + elif filename.lower().endswith(XZ_EXTENSIONS): + mode = "r:xz" + elif filename.lower().endswith(".tar"): + mode = "r" + else: + logger.warning( + "Cannot determine compression type for file %s", + filename, + ) + mode = "r:*" + + tar = tarfile.open(filename, mode, encoding="utf-8") + try: + leading = has_leading_dir([member.name for member in tar.getmembers()]) + + # PEP 706 added `tarfile.data_filter`, and made some other changes to + # Python's tarfile module (see below). The features were backported to + # security releases. + try: + data_filter = tarfile.data_filter + except AttributeError: + _untar_without_filter(filename, location, tar, leading) + else: + default_mode_plus_executable = _get_default_mode_plus_executable() + + if leading: + # Strip the leading directory from all files in the archive, + # including hardlink targets (which are relative to the + # unpack location). + for member in tar.getmembers(): + name_lead, name_rest = split_leading_dir(member.name) + member.name = name_rest + if member.islnk(): + lnk_lead, lnk_rest = split_leading_dir(member.linkname) + if lnk_lead == name_lead: + member.linkname = lnk_rest + + def pip_filter(member: tarfile.TarInfo, path: str) -> tarfile.TarInfo: + orig_mode = member.mode + try: + try: + member = data_filter(member, location) + except tarfile.LinkOutsideDestinationError: + if sys.version_info[:3] in { + (3, 8, 17), + (3, 9, 17), + (3, 10, 12), + (3, 11, 4), + }: + # The tarfile filter in specific Python versions + # raises LinkOutsideDestinationError on valid input + # (https://github.com/python/cpython/issues/107845) + # Ignore the error there, but do use the + # more lax `tar_filter` + member = tarfile.tar_filter(member, location) + else: + raise + except tarfile.TarError as exc: + message = "Invalid member in the tar file {}: {}" + # Filter error messages mention the member name. + # No need to add it here. + raise InstallationError( + message.format( + filename, + exc, + ) + ) + if member.isfile() and orig_mode & 0o111: + member.mode = default_mode_plus_executable + else: + # See PEP 706 note above. + # The PEP changed this from `int` to `Optional[int]`, + # where None means "use the default". Mypy doesn't + # know this yet. + member.mode = None # type: ignore [assignment] + return member + + tar.extractall(location, filter=pip_filter) + + finally: + tar.close() + + +def _untar_without_filter( + filename: str, + location: str, + tar: tarfile.TarFile, + leading: bool, +) -> None: + """Fallback for Python without tarfile.data_filter""" + for member in tar.getmembers(): + fn = member.name + if leading: + fn = split_leading_dir(fn)[1] + path = os.path.join(location, fn) + if not is_within_directory(location, path): + message = ( + "The tar file ({}) has a file ({}) trying to install " + "outside target directory ({})" + ) + raise InstallationError(message.format(filename, path, location)) + if member.isdir(): + ensure_dir(path) + elif member.issym(): + try: + tar._extract_member(member, path) + except Exception as exc: + # Some corrupt tar files seem to produce this + # (specifically bad symlinks) + logger.warning( + "In the tar file %s the member %s is invalid: %s", + filename, + member.name, + exc, + ) + continue + else: + try: + fp = tar.extractfile(member) + except (KeyError, AttributeError) as exc: + # Some corrupt tar files seem to produce this + # (specifically bad symlinks) + logger.warning( + "In the tar file %s the member %s is invalid: %s", + filename, + member.name, + exc, + ) + continue + ensure_dir(os.path.dirname(path)) + assert fp is not None + with open(path, "wb") as destfp: + shutil.copyfileobj(fp, destfp) + fp.close() + # Update the timestamp (useful for cython compiled files) + tar.utime(member, path) + # member have any execute permissions for user/group/world? + if member.mode & 0o111: + set_extracted_file_to_default_mode_plus_executable(path) + + +def unpack_file( + filename: str, + location: str, + content_type: Optional[str] = None, +) -> None: + filename = os.path.realpath(filename) + if ( + content_type == "application/zip" + or filename.lower().endswith(ZIP_EXTENSIONS) + or zipfile.is_zipfile(filename) + ): + unzip_file(filename, location, flatten=not filename.endswith(".whl")) + elif ( + content_type == "application/x-gzip" + or tarfile.is_tarfile(filename) + or filename.lower().endswith(TAR_EXTENSIONS + BZ2_EXTENSIONS + XZ_EXTENSIONS) + ): + untar_file(filename, location) + else: + # FIXME: handle? + # FIXME: magic signatures? + logger.critical( + "Cannot unpack file %s (downloaded from %s, content-type: %s); " + "cannot detect archive format", + filename, + location, + content_type, + ) + raise InstallationError(f"Cannot determine archive format of {location}") diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/urls.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/urls.py new file mode 100644 index 0000000..9f34f88 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/urls.py @@ -0,0 +1,55 @@ +import os +import string +import urllib.parse +import urllib.request + +from .compat import WINDOWS + + +def path_to_url(path: str) -> str: + """ + Convert a path to a file: URL. The path will be made absolute and have + quoted path parts. + """ + path = os.path.normpath(os.path.abspath(path)) + url = urllib.parse.urljoin("file:", urllib.request.pathname2url(path)) + return url + + +def url_to_path(url: str) -> str: + """ + Convert a file: URL to a path. + """ + assert url.startswith( + "file:" + ), f"You can only turn file: urls into filenames (not {url!r})" + + _, netloc, path, _, _ = urllib.parse.urlsplit(url) + + if not netloc or netloc == "localhost": + # According to RFC 8089, same as empty authority. + netloc = "" + elif WINDOWS: + # If we have a UNC path, prepend UNC share notation. + netloc = "\\\\" + netloc + else: + raise ValueError( + f"non-local file URIs are not supported on this platform: {url!r}" + ) + + path = urllib.request.url2pathname(netloc + path) + + # On Windows, urlsplit parses the path as something like "/C:/Users/foo". + # This creates issues for path-related functions like io.open(), so we try + # to detect and strip the leading slash. + if ( + WINDOWS + and not netloc # Not UNC. + and len(path) >= 3 + and path[0] == "/" # Leading slash to strip. + and path[1] in string.ascii_letters # Drive letter. + and path[2:4] in (":", ":/") # Colon + end of string, or colon + absolute path. + ): + path = path[1:] + + return path diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/virtualenv.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/virtualenv.py new file mode 100644 index 0000000..882e36f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/virtualenv.py @@ -0,0 +1,104 @@ +import logging +import os +import re +import site +import sys +from typing import List, Optional + +logger = logging.getLogger(__name__) +_INCLUDE_SYSTEM_SITE_PACKAGES_REGEX = re.compile( + r"include-system-site-packages\s*=\s*(?Ptrue|false)" +) + + +def _running_under_venv() -> bool: + """Checks if sys.base_prefix and sys.prefix match. + + This handles PEP 405 compliant virtual environments. + """ + return sys.prefix != getattr(sys, "base_prefix", sys.prefix) + + +def _running_under_legacy_virtualenv() -> bool: + """Checks if sys.real_prefix is set. + + This handles virtual environments created with pypa's virtualenv. + """ + # pypa/virtualenv case + return hasattr(sys, "real_prefix") + + +def running_under_virtualenv() -> bool: + """True if we're running inside a virtual environment, False otherwise.""" + return _running_under_venv() or _running_under_legacy_virtualenv() + + +def _get_pyvenv_cfg_lines() -> Optional[List[str]]: + """Reads {sys.prefix}/pyvenv.cfg and returns its contents as list of lines + + Returns None, if it could not read/access the file. + """ + pyvenv_cfg_file = os.path.join(sys.prefix, "pyvenv.cfg") + try: + # Although PEP 405 does not specify, the built-in venv module always + # writes with UTF-8. (pypa/pip#8717) + with open(pyvenv_cfg_file, encoding="utf-8") as f: + return f.read().splitlines() # avoids trailing newlines + except OSError: + return None + + +def _no_global_under_venv() -> bool: + """Check `{sys.prefix}/pyvenv.cfg` for system site-packages inclusion + + PEP 405 specifies that when system site-packages are not supposed to be + visible from a virtual environment, `pyvenv.cfg` must contain the following + line: + + include-system-site-packages = false + + Additionally, log a warning if accessing the file fails. + """ + cfg_lines = _get_pyvenv_cfg_lines() + if cfg_lines is None: + # We're not in a "sane" venv, so assume there is no system + # site-packages access (since that's PEP 405's default state). + logger.warning( + "Could not access 'pyvenv.cfg' despite a virtual environment " + "being active. Assuming global site-packages is not accessible " + "in this environment." + ) + return True + + for line in cfg_lines: + match = _INCLUDE_SYSTEM_SITE_PACKAGES_REGEX.match(line) + if match is not None and match.group("value") == "false": + return True + return False + + +def _no_global_under_legacy_virtualenv() -> bool: + """Check if "no-global-site-packages.txt" exists beside site.py + + This mirrors logic in pypa/virtualenv for determining whether system + site-packages are visible in the virtual environment. + """ + site_mod_dir = os.path.dirname(os.path.abspath(site.__file__)) + no_global_site_packages_file = os.path.join( + site_mod_dir, + "no-global-site-packages.txt", + ) + return os.path.exists(no_global_site_packages_file) + + +def virtualenv_no_global() -> bool: + """Returns a boolean, whether running in venv with no system site-packages.""" + # PEP 405 compliance needs to be checked first since virtualenv >=20 would + # return True for both checks, but is only able to use the PEP 405 config. + if _running_under_venv(): + return _no_global_under_venv() + + if _running_under_legacy_virtualenv(): + return _no_global_under_legacy_virtualenv() + + return False diff --git a/backend/.venv/Lib/site-packages/pip/_internal/utils/wheel.py b/backend/.venv/Lib/site-packages/pip/_internal/utils/wheel.py new file mode 100644 index 0000000..f85aee8 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/utils/wheel.py @@ -0,0 +1,134 @@ +"""Support functions for working with wheel files. +""" + +import logging +from email.message import Message +from email.parser import Parser +from typing import Tuple +from zipfile import BadZipFile, ZipFile + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.exceptions import UnsupportedWheel + +VERSION_COMPATIBLE = (1, 0) + + +logger = logging.getLogger(__name__) + + +def parse_wheel(wheel_zip: ZipFile, name: str) -> Tuple[str, Message]: + """Extract information from the provided wheel, ensuring it meets basic + standards. + + Returns the name of the .dist-info directory and the parsed WHEEL metadata. + """ + try: + info_dir = wheel_dist_info_dir(wheel_zip, name) + metadata = wheel_metadata(wheel_zip, info_dir) + version = wheel_version(metadata) + except UnsupportedWheel as e: + raise UnsupportedWheel(f"{name} has an invalid wheel, {e}") + + check_compatibility(version, name) + + return info_dir, metadata + + +def wheel_dist_info_dir(source: ZipFile, name: str) -> str: + """Returns the name of the contained .dist-info directory. + + Raises AssertionError or UnsupportedWheel if not found, >1 found, or + it doesn't match the provided name. + """ + # Zip file path separators must be / + subdirs = {p.split("/", 1)[0] for p in source.namelist()} + + info_dirs = [s for s in subdirs if s.endswith(".dist-info")] + + if not info_dirs: + raise UnsupportedWheel(".dist-info directory not found") + + if len(info_dirs) > 1: + raise UnsupportedWheel( + "multiple .dist-info directories found: {}".format(", ".join(info_dirs)) + ) + + info_dir = info_dirs[0] + + info_dir_name = canonicalize_name(info_dir) + canonical_name = canonicalize_name(name) + if not info_dir_name.startswith(canonical_name): + raise UnsupportedWheel( + f".dist-info directory {info_dir!r} does not start with {canonical_name!r}" + ) + + return info_dir + + +def read_wheel_metadata_file(source: ZipFile, path: str) -> bytes: + try: + return source.read(path) + # BadZipFile for general corruption, KeyError for missing entry, + # and RuntimeError for password-protected files + except (BadZipFile, KeyError, RuntimeError) as e: + raise UnsupportedWheel(f"could not read {path!r} file: {e!r}") + + +def wheel_metadata(source: ZipFile, dist_info_dir: str) -> Message: + """Return the WHEEL metadata of an extracted wheel, if possible. + Otherwise, raise UnsupportedWheel. + """ + path = f"{dist_info_dir}/WHEEL" + # Zip file path separators must be / + wheel_contents = read_wheel_metadata_file(source, path) + + try: + wheel_text = wheel_contents.decode() + except UnicodeDecodeError as e: + raise UnsupportedWheel(f"error decoding {path!r}: {e!r}") + + # FeedParser (used by Parser) does not raise any exceptions. The returned + # message may have .defects populated, but for backwards-compatibility we + # currently ignore them. + return Parser().parsestr(wheel_text) + + +def wheel_version(wheel_data: Message) -> Tuple[int, ...]: + """Given WHEEL metadata, return the parsed Wheel-Version. + Otherwise, raise UnsupportedWheel. + """ + version_text = wheel_data["Wheel-Version"] + if version_text is None: + raise UnsupportedWheel("WHEEL is missing Wheel-Version") + + version = version_text.strip() + + try: + return tuple(map(int, version.split("."))) + except ValueError: + raise UnsupportedWheel(f"invalid Wheel-Version: {version!r}") + + +def check_compatibility(version: Tuple[int, ...], name: str) -> None: + """Raises errors or warns if called with an incompatible Wheel-Version. + + pip should refuse to install a Wheel-Version that's a major series + ahead of what it's compatible with (e.g 2.0 > 1.1); and warn when + installing a version only minor version ahead (e.g 1.2 > 1.1). + + version: a 2-tuple representing a Wheel-Version (Major, Minor) + name: name of wheel or package to raise exception about + + :raises UnsupportedWheel: when an incompatible Wheel-Version is given + """ + if version[0] > VERSION_COMPATIBLE[0]: + raise UnsupportedWheel( + "{}'s Wheel-Version ({}) is not compatible with this version " + "of pip".format(name, ".".join(map(str, version))) + ) + elif version > VERSION_COMPATIBLE: + logger.warning( + "Installing from a newer Wheel-Version (%s)", + ".".join(map(str, version)), + ) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/vcs/__init__.py b/backend/.venv/Lib/site-packages/pip/_internal/vcs/__init__.py new file mode 100644 index 0000000..b6beddb --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/vcs/__init__.py @@ -0,0 +1,15 @@ +# Expose a limited set of classes and functions so callers outside of +# the vcs package don't need to import deeper than `pip._internal.vcs`. +# (The test directory may still need to import from a vcs sub-package.) +# Import all vcs modules to register each VCS in the VcsSupport object. +import pip._internal.vcs.bazaar +import pip._internal.vcs.git +import pip._internal.vcs.mercurial +import pip._internal.vcs.subversion # noqa: F401 +from pip._internal.vcs.versioncontrol import ( # noqa: F401 + RemoteNotFoundError, + RemoteNotValidError, + is_url, + make_vcs_requirement_url, + vcs, +) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f68268e5a4dfa2b29c84026802fd699d40ac9a8b GIT binary patch literal 533 zcmZXQPfNov7{-&)eL>QfV|jOH+IhE7Y);YT)sJr6aDgIGk`bi7&(;Hp22AelTJ~ZeqMc|8M9%4&6_% y6*fu2@zgaArOt|+AHxQoM{${5#D`BQowo?>%*f7+?9Isjmlsg)lOSLncl-c3tEPGY literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1b0b2406c1dcff2283b3b0c55b8d4515f714bd4d GIT binary patch literal 5054 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 Rgm(hp3sheDltk>W{tI>Iv#9_8 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/vcs/__pycache__/git.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/vcs/__pycache__/git.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7c52da0961ac81e44c917d7130b69d28895e18d2 GIT binary patch literal 19019 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 gJj-)W-teyzgtebI20-zK4@`0W#{d8T literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6c3c68055bfdc03224817f7cda790e39fc69d682 GIT binary patch literal 12526 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 aD6C7*nIRTD&wSJN4O=Go3(8C0<9`4b)4gZ_ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..970de740c769e6e884bc5771824ba7fd03391dde GIT binary patch literal 28999 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 List[str]: + return ["-r", rev] + + def fetch_new( + self, dest: str, url: HiddenText, rev_options: RevOptions, verbosity: int + ) -> None: + rev_display = rev_options.to_display() + logger.info( + "Checking out %s%s to %s", + url, + rev_display, + display_path(dest), + ) + if verbosity <= 0: + flags = ["--quiet"] + elif verbosity == 1: + flags = [] + else: + flags = [f"-{'v'*verbosity}"] + cmd_args = make_command( + "checkout", "--lightweight", *flags, rev_options.to_args(), url, dest + ) + self.run_command(cmd_args) + + def switch(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: + self.run_command(make_command("switch", url), cwd=dest) + + def update(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: + output = self.run_command( + make_command("info"), show_stdout=False, stdout_only=True, cwd=dest + ) + if output.startswith("Standalone "): + # Older versions of pip used to create standalone branches. + # Convert the standalone branch to a checkout by calling "bzr bind". + cmd_args = make_command("bind", "-q", url) + self.run_command(cmd_args, cwd=dest) + + cmd_args = make_command("update", "-q", rev_options.to_args()) + self.run_command(cmd_args, cwd=dest) + + @classmethod + def get_url_rev_and_auth(cls, url: str) -> Tuple[str, Optional[str], AuthInfo]: + # hotfix the URL scheme after removing bzr+ from bzr+ssh:// re-add it + url, rev, user_pass = super().get_url_rev_and_auth(url) + if url.startswith("ssh://"): + url = "bzr+" + url + return url, rev, user_pass + + @classmethod + def get_remote_url(cls, location: str) -> str: + urls = cls.run_command( + ["info"], show_stdout=False, stdout_only=True, cwd=location + ) + for line in urls.splitlines(): + line = line.strip() + for x in ("checkout of branch: ", "parent branch: "): + if line.startswith(x): + repo = line.split(x)[1] + if cls._is_local_repository(repo): + return path_to_url(repo) + return repo + raise RemoteNotFoundError + + @classmethod + def get_revision(cls, location: str) -> str: + revision = cls.run_command( + ["revno"], + show_stdout=False, + stdout_only=True, + cwd=location, + ) + return revision.splitlines()[-1] + + @classmethod + def is_commit_id_equal(cls, dest: str, name: Optional[str]) -> bool: + """Always assume the versions don't match""" + return False + + +vcs.register(Bazaar) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/vcs/git.py b/backend/.venv/Lib/site-packages/pip/_internal/vcs/git.py new file mode 100644 index 0000000..0425deb --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/vcs/git.py @@ -0,0 +1,527 @@ +import logging +import os.path +import pathlib +import re +import urllib.parse +import urllib.request +from dataclasses import replace +from typing import List, Optional, Tuple + +from pip._internal.exceptions import BadCommand, InstallationError +from pip._internal.utils.misc import HiddenText, display_path, hide_url +from pip._internal.utils.subprocess import make_command +from pip._internal.vcs.versioncontrol import ( + AuthInfo, + RemoteNotFoundError, + RemoteNotValidError, + RevOptions, + VersionControl, + find_path_to_project_root_from_repo_root, + vcs, +) + +urlsplit = urllib.parse.urlsplit +urlunsplit = urllib.parse.urlunsplit + + +logger = logging.getLogger(__name__) + + +GIT_VERSION_REGEX = re.compile( + r"^git version " # Prefix. + r"(\d+)" # Major. + r"\.(\d+)" # Dot, minor. + r"(?:\.(\d+))?" # Optional dot, patch. + r".*$" # Suffix, including any pre- and post-release segments we don't care about. +) + +HASH_REGEX = re.compile("^[a-fA-F0-9]{40}$") + +# SCP (Secure copy protocol) shorthand. e.g. 'git@example.com:foo/bar.git' +SCP_REGEX = re.compile( + r"""^ + # Optional user, e.g. 'git@' + (\w+@)? + # Server, e.g. 'github.com'. + ([^/:]+): + # The server-side path. e.g. 'user/project.git'. Must start with an + # alphanumeric character so as not to be confusable with a Windows paths + # like 'C:/foo/bar' or 'C:\foo\bar'. + (\w[^:]*) + $""", + re.VERBOSE, +) + + +def looks_like_hash(sha: str) -> bool: + return bool(HASH_REGEX.match(sha)) + + +class Git(VersionControl): + name = "git" + dirname = ".git" + repo_name = "clone" + schemes = ( + "git+http", + "git+https", + "git+ssh", + "git+git", + "git+file", + ) + # Prevent the user's environment variables from interfering with pip: + # https://github.com/pypa/pip/issues/1130 + unset_environ = ("GIT_DIR", "GIT_WORK_TREE") + default_arg_rev = "HEAD" + + @staticmethod + def get_base_rev_args(rev: str) -> List[str]: + return [rev] + + def is_immutable_rev_checkout(self, url: str, dest: str) -> bool: + _, rev_options = self.get_url_rev_options(hide_url(url)) + if not rev_options.rev: + return False + if not self.is_commit_id_equal(dest, rev_options.rev): + # the current commit is different from rev, + # which means rev was something else than a commit hash + return False + # return False in the rare case rev is both a commit hash + # and a tag or a branch; we don't want to cache in that case + # because that branch/tag could point to something else in the future + is_tag_or_branch = bool(self.get_revision_sha(dest, rev_options.rev)[0]) + return not is_tag_or_branch + + def get_git_version(self) -> Tuple[int, ...]: + version = self.run_command( + ["version"], + command_desc="git version", + show_stdout=False, + stdout_only=True, + ) + match = GIT_VERSION_REGEX.match(version) + if not match: + logger.warning("Can't parse git version: %s", version) + return () + return (int(match.group(1)), int(match.group(2))) + + @classmethod + def get_current_branch(cls, location: str) -> Optional[str]: + """ + Return the current branch, or None if HEAD isn't at a branch + (e.g. detached HEAD). + """ + # git-symbolic-ref exits with empty stdout if "HEAD" is a detached + # HEAD rather than a symbolic ref. In addition, the -q causes the + # command to exit with status code 1 instead of 128 in this case + # and to suppress the message to stderr. + args = ["symbolic-ref", "-q", "HEAD"] + output = cls.run_command( + args, + extra_ok_returncodes=(1,), + show_stdout=False, + stdout_only=True, + cwd=location, + ) + ref = output.strip() + + if ref.startswith("refs/heads/"): + return ref[len("refs/heads/") :] + + return None + + @classmethod + def get_revision_sha(cls, dest: str, rev: str) -> Tuple[Optional[str], bool]: + """ + Return (sha_or_none, is_branch), where sha_or_none is a commit hash + if the revision names a remote branch or tag, otherwise None. + + Args: + dest: the repository directory. + rev: the revision name. + """ + # Pass rev to pre-filter the list. + output = cls.run_command( + ["show-ref", rev], + cwd=dest, + show_stdout=False, + stdout_only=True, + on_returncode="ignore", + ) + refs = {} + # NOTE: We do not use splitlines here since that would split on other + # unicode separators, which can be maliciously used to install a + # different revision. + for line in output.strip().split("\n"): + line = line.rstrip("\r") + if not line: + continue + try: + ref_sha, ref_name = line.split(" ", maxsplit=2) + except ValueError: + # Include the offending line to simplify troubleshooting if + # this error ever occurs. + raise ValueError(f"unexpected show-ref line: {line!r}") + + refs[ref_name] = ref_sha + + branch_ref = f"refs/remotes/origin/{rev}" + tag_ref = f"refs/tags/{rev}" + + sha = refs.get(branch_ref) + if sha is not None: + return (sha, True) + + sha = refs.get(tag_ref) + + return (sha, False) + + @classmethod + def _should_fetch(cls, dest: str, rev: str) -> bool: + """ + Return true if rev is a ref or is a commit that we don't have locally. + + Branches and tags are not considered in this method because they are + assumed to be always available locally (which is a normal outcome of + ``git clone`` and ``git fetch --tags``). + """ + if rev.startswith("refs/"): + # Always fetch remote refs. + return True + + if not looks_like_hash(rev): + # Git fetch would fail with abbreviated commits. + return False + + if cls.has_commit(dest, rev): + # Don't fetch if we have the commit locally. + return False + + return True + + @classmethod + def resolve_revision( + cls, dest: str, url: HiddenText, rev_options: RevOptions + ) -> RevOptions: + """ + Resolve a revision to a new RevOptions object with the SHA1 of the + branch, tag, or ref if found. + + Args: + rev_options: a RevOptions object. + """ + rev = rev_options.arg_rev + # The arg_rev property's implementation for Git ensures that the + # rev return value is always non-None. + assert rev is not None + + sha, is_branch = cls.get_revision_sha(dest, rev) + + if sha is not None: + rev_options = rev_options.make_new(sha) + rev_options = replace(rev_options, branch_name=(rev if is_branch else None)) + + return rev_options + + # Do not show a warning for the common case of something that has + # the form of a Git commit hash. + if not looks_like_hash(rev): + logger.warning( + "Did not find branch or tag '%s', assuming revision or ref.", + rev, + ) + + if not cls._should_fetch(dest, rev): + return rev_options + + # fetch the requested revision + cls.run_command( + make_command("fetch", "-q", url, rev_options.to_args()), + cwd=dest, + ) + # Change the revision to the SHA of the ref we fetched + sha = cls.get_revision(dest, rev="FETCH_HEAD") + rev_options = rev_options.make_new(sha) + + return rev_options + + @classmethod + def is_commit_id_equal(cls, dest: str, name: Optional[str]) -> bool: + """ + Return whether the current commit hash equals the given name. + + Args: + dest: the repository directory. + name: a string name. + """ + if not name: + # Then avoid an unnecessary subprocess call. + return False + + return cls.get_revision(dest) == name + + def fetch_new( + self, dest: str, url: HiddenText, rev_options: RevOptions, verbosity: int + ) -> None: + rev_display = rev_options.to_display() + logger.info("Cloning %s%s to %s", url, rev_display, display_path(dest)) + if verbosity <= 0: + flags: Tuple[str, ...] = ("--quiet",) + elif verbosity == 1: + flags = () + else: + flags = ("--verbose", "--progress") + if self.get_git_version() >= (2, 17): + # Git added support for partial clone in 2.17 + # https://git-scm.com/docs/partial-clone + # Speeds up cloning by functioning without a complete copy of repository + self.run_command( + make_command( + "clone", + "--filter=blob:none", + *flags, + url, + dest, + ) + ) + else: + self.run_command(make_command("clone", *flags, url, dest)) + + if rev_options.rev: + # Then a specific revision was requested. + rev_options = self.resolve_revision(dest, url, rev_options) + branch_name = getattr(rev_options, "branch_name", None) + logger.debug("Rev options %s, branch_name %s", rev_options, branch_name) + if branch_name is None: + # Only do a checkout if the current commit id doesn't match + # the requested revision. + if not self.is_commit_id_equal(dest, rev_options.rev): + cmd_args = make_command( + "checkout", + "-q", + rev_options.to_args(), + ) + self.run_command(cmd_args, cwd=dest) + elif self.get_current_branch(dest) != branch_name: + # Then a specific branch was requested, and that branch + # is not yet checked out. + track_branch = f"origin/{branch_name}" + cmd_args = [ + "checkout", + "-b", + branch_name, + "--track", + track_branch, + ] + self.run_command(cmd_args, cwd=dest) + else: + sha = self.get_revision(dest) + rev_options = rev_options.make_new(sha) + + logger.info("Resolved %s to commit %s", url, rev_options.rev) + + #: repo may contain submodules + self.update_submodules(dest) + + def switch(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: + self.run_command( + make_command("config", "remote.origin.url", url), + cwd=dest, + ) + cmd_args = make_command("checkout", "-q", rev_options.to_args()) + self.run_command(cmd_args, cwd=dest) + + self.update_submodules(dest) + + def update(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: + # First fetch changes from the default remote + if self.get_git_version() >= (1, 9): + # fetch tags in addition to everything else + self.run_command(["fetch", "-q", "--tags"], cwd=dest) + else: + self.run_command(["fetch", "-q"], cwd=dest) + # Then reset to wanted revision (maybe even origin/master) + rev_options = self.resolve_revision(dest, url, rev_options) + cmd_args = make_command("reset", "--hard", "-q", rev_options.to_args()) + self.run_command(cmd_args, cwd=dest) + #: update submodules + self.update_submodules(dest) + + @classmethod + def get_remote_url(cls, location: str) -> str: + """ + Return URL of the first remote encountered. + + Raises RemoteNotFoundError if the repository does not have a remote + url configured. + """ + # We need to pass 1 for extra_ok_returncodes since the command + # exits with return code 1 if there are no matching lines. + stdout = cls.run_command( + ["config", "--get-regexp", r"remote\..*\.url"], + extra_ok_returncodes=(1,), + show_stdout=False, + stdout_only=True, + cwd=location, + ) + remotes = stdout.splitlines() + try: + found_remote = remotes[0] + except IndexError: + raise RemoteNotFoundError + + for remote in remotes: + if remote.startswith("remote.origin.url "): + found_remote = remote + break + url = found_remote.split(" ")[1] + return cls._git_remote_to_pip_url(url.strip()) + + @staticmethod + def _git_remote_to_pip_url(url: str) -> str: + """ + Convert a remote url from what git uses to what pip accepts. + + There are 3 legal forms **url** may take: + + 1. A fully qualified url: ssh://git@example.com/foo/bar.git + 2. A local project.git folder: /path/to/bare/repository.git + 3. SCP shorthand for form 1: git@example.com:foo/bar.git + + Form 1 is output as-is. Form 2 must be converted to URI and form 3 must + be converted to form 1. + + See the corresponding test test_git_remote_url_to_pip() for examples of + sample inputs/outputs. + """ + if re.match(r"\w+://", url): + # This is already valid. Pass it though as-is. + return url + if os.path.exists(url): + # A local bare remote (git clone --mirror). + # Needs a file:// prefix. + return pathlib.PurePath(url).as_uri() + scp_match = SCP_REGEX.match(url) + if scp_match: + # Add an ssh:// prefix and replace the ':' with a '/'. + return scp_match.expand(r"ssh://\1\2/\3") + # Otherwise, bail out. + raise RemoteNotValidError(url) + + @classmethod + def has_commit(cls, location: str, rev: str) -> bool: + """ + Check if rev is a commit that is available in the local repository. + """ + try: + cls.run_command( + ["rev-parse", "-q", "--verify", "sha^" + rev], + cwd=location, + log_failed_cmd=False, + ) + except InstallationError: + return False + else: + return True + + @classmethod + def get_revision(cls, location: str, rev: Optional[str] = None) -> str: + if rev is None: + rev = "HEAD" + current_rev = cls.run_command( + ["rev-parse", rev], + show_stdout=False, + stdout_only=True, + cwd=location, + ) + return current_rev.strip() + + @classmethod + def get_subdirectory(cls, location: str) -> Optional[str]: + """ + Return the path to Python project root, relative to the repo root. + Return None if the project root is in the repo root. + """ + # find the repo root + git_dir = cls.run_command( + ["rev-parse", "--git-dir"], + show_stdout=False, + stdout_only=True, + cwd=location, + ).strip() + if not os.path.isabs(git_dir): + git_dir = os.path.join(location, git_dir) + repo_root = os.path.abspath(os.path.join(git_dir, "..")) + return find_path_to_project_root_from_repo_root(location, repo_root) + + @classmethod + def get_url_rev_and_auth(cls, url: str) -> Tuple[str, Optional[str], AuthInfo]: + """ + Prefixes stub URLs like 'user@hostname:user/repo.git' with 'ssh://'. + That's required because although they use SSH they sometimes don't + work with a ssh:// scheme (e.g. GitHub). But we need a scheme for + parsing. Hence we remove it again afterwards and return it as a stub. + """ + # Works around an apparent Git bug + # (see https://article.gmane.org/gmane.comp.version-control.git/146500) + scheme, netloc, path, query, fragment = urlsplit(url) + if scheme.endswith("file"): + initial_slashes = path[: -len(path.lstrip("/"))] + newpath = initial_slashes + urllib.request.url2pathname(path).replace( + "\\", "/" + ).lstrip("/") + after_plus = scheme.find("+") + 1 + url = scheme[:after_plus] + urlunsplit( + (scheme[after_plus:], netloc, newpath, query, fragment), + ) + + if "://" not in url: + assert "file:" not in url + url = url.replace("git+", "git+ssh://") + url, rev, user_pass = super().get_url_rev_and_auth(url) + url = url.replace("ssh://", "") + else: + url, rev, user_pass = super().get_url_rev_and_auth(url) + + return url, rev, user_pass + + @classmethod + def update_submodules(cls, location: str) -> None: + if not os.path.exists(os.path.join(location, ".gitmodules")): + return + cls.run_command( + ["submodule", "update", "--init", "--recursive", "-q"], + cwd=location, + ) + + @classmethod + def get_repository_root(cls, location: str) -> Optional[str]: + loc = super().get_repository_root(location) + if loc: + return loc + try: + r = cls.run_command( + ["rev-parse", "--show-toplevel"], + cwd=location, + show_stdout=False, + stdout_only=True, + on_returncode="raise", + log_failed_cmd=False, + ) + except BadCommand: + logger.debug( + "could not determine if %s is under git control " + "because git is not available", + location, + ) + return None + except InstallationError: + return None + return os.path.normpath(r.rstrip("\r\n")) + + @staticmethod + def should_add_vcs_url_prefix(repo_url: str) -> bool: + """In either https or ssh form, requirements must be prefixed with git+.""" + return True + + +vcs.register(Git) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/vcs/mercurial.py b/backend/.venv/Lib/site-packages/pip/_internal/vcs/mercurial.py new file mode 100644 index 0000000..c183d41 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/vcs/mercurial.py @@ -0,0 +1,163 @@ +import configparser +import logging +import os +from typing import List, Optional, Tuple + +from pip._internal.exceptions import BadCommand, InstallationError +from pip._internal.utils.misc import HiddenText, display_path +from pip._internal.utils.subprocess import make_command +from pip._internal.utils.urls import path_to_url +from pip._internal.vcs.versioncontrol import ( + RevOptions, + VersionControl, + find_path_to_project_root_from_repo_root, + vcs, +) + +logger = logging.getLogger(__name__) + + +class Mercurial(VersionControl): + name = "hg" + dirname = ".hg" + repo_name = "clone" + schemes = ( + "hg+file", + "hg+http", + "hg+https", + "hg+ssh", + "hg+static-http", + ) + + @staticmethod + def get_base_rev_args(rev: str) -> List[str]: + return [f"--rev={rev}"] + + def fetch_new( + self, dest: str, url: HiddenText, rev_options: RevOptions, verbosity: int + ) -> None: + rev_display = rev_options.to_display() + logger.info( + "Cloning hg %s%s to %s", + url, + rev_display, + display_path(dest), + ) + if verbosity <= 0: + flags: Tuple[str, ...] = ("--quiet",) + elif verbosity == 1: + flags = () + elif verbosity == 2: + flags = ("--verbose",) + else: + flags = ("--verbose", "--debug") + self.run_command(make_command("clone", "--noupdate", *flags, url, dest)) + self.run_command( + make_command("update", *flags, rev_options.to_args()), + cwd=dest, + ) + + def switch(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: + repo_config = os.path.join(dest, self.dirname, "hgrc") + config = configparser.RawConfigParser() + try: + config.read(repo_config) + config.set("paths", "default", url.secret) + with open(repo_config, "w") as config_file: + config.write(config_file) + except (OSError, configparser.NoSectionError) as exc: + logger.warning("Could not switch Mercurial repository to %s: %s", url, exc) + else: + cmd_args = make_command("update", "-q", rev_options.to_args()) + self.run_command(cmd_args, cwd=dest) + + def update(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: + self.run_command(["pull", "-q"], cwd=dest) + cmd_args = make_command("update", "-q", rev_options.to_args()) + self.run_command(cmd_args, cwd=dest) + + @classmethod + def get_remote_url(cls, location: str) -> str: + url = cls.run_command( + ["showconfig", "paths.default"], + show_stdout=False, + stdout_only=True, + cwd=location, + ).strip() + if cls._is_local_repository(url): + url = path_to_url(url) + return url.strip() + + @classmethod + def get_revision(cls, location: str) -> str: + """ + Return the repository-local changeset revision number, as an integer. + """ + current_revision = cls.run_command( + ["parents", "--template={rev}"], + show_stdout=False, + stdout_only=True, + cwd=location, + ).strip() + return current_revision + + @classmethod + def get_requirement_revision(cls, location: str) -> str: + """ + Return the changeset identification hash, as a 40-character + hexadecimal string + """ + current_rev_hash = cls.run_command( + ["parents", "--template={node}"], + show_stdout=False, + stdout_only=True, + cwd=location, + ).strip() + return current_rev_hash + + @classmethod + def is_commit_id_equal(cls, dest: str, name: Optional[str]) -> bool: + """Always assume the versions don't match""" + return False + + @classmethod + def get_subdirectory(cls, location: str) -> Optional[str]: + """ + Return the path to Python project root, relative to the repo root. + Return None if the project root is in the repo root. + """ + # find the repo root + repo_root = cls.run_command( + ["root"], show_stdout=False, stdout_only=True, cwd=location + ).strip() + if not os.path.isabs(repo_root): + repo_root = os.path.abspath(os.path.join(location, repo_root)) + return find_path_to_project_root_from_repo_root(location, repo_root) + + @classmethod + def get_repository_root(cls, location: str) -> Optional[str]: + loc = super().get_repository_root(location) + if loc: + return loc + try: + r = cls.run_command( + ["root"], + cwd=location, + show_stdout=False, + stdout_only=True, + on_returncode="raise", + log_failed_cmd=False, + ) + except BadCommand: + logger.debug( + "could not determine if %s is under hg control " + "because hg is not available", + location, + ) + return None + except InstallationError: + return None + return os.path.normpath(r.rstrip("\r\n")) + + +vcs.register(Mercurial) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/vcs/subversion.py b/backend/.venv/Lib/site-packages/pip/_internal/vcs/subversion.py new file mode 100644 index 0000000..f359266 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/vcs/subversion.py @@ -0,0 +1,324 @@ +import logging +import os +import re +from typing import List, Optional, Tuple + +from pip._internal.utils.misc import ( + HiddenText, + display_path, + is_console_interactive, + is_installable_dir, + split_auth_from_netloc, +) +from pip._internal.utils.subprocess import CommandArgs, make_command +from pip._internal.vcs.versioncontrol import ( + AuthInfo, + RemoteNotFoundError, + RevOptions, + VersionControl, + vcs, +) + +logger = logging.getLogger(__name__) + +_svn_xml_url_re = re.compile('url="([^"]+)"') +_svn_rev_re = re.compile(r'committed-rev="(\d+)"') +_svn_info_xml_rev_re = re.compile(r'\s*revision="(\d+)"') +_svn_info_xml_url_re = re.compile(r"(.*)") + + +class Subversion(VersionControl): + name = "svn" + dirname = ".svn" + repo_name = "checkout" + schemes = ("svn+ssh", "svn+http", "svn+https", "svn+svn", "svn+file") + + @classmethod + def should_add_vcs_url_prefix(cls, remote_url: str) -> bool: + return True + + @staticmethod + def get_base_rev_args(rev: str) -> List[str]: + return ["-r", rev] + + @classmethod + def get_revision(cls, location: str) -> str: + """ + Return the maximum revision for all files under a given location + """ + # Note: taken from setuptools.command.egg_info + revision = 0 + + for base, dirs, _ in os.walk(location): + if cls.dirname not in dirs: + dirs[:] = [] + continue # no sense walking uncontrolled subdirs + dirs.remove(cls.dirname) + entries_fn = os.path.join(base, cls.dirname, "entries") + if not os.path.exists(entries_fn): + # FIXME: should we warn? + continue + + dirurl, localrev = cls._get_svn_url_rev(base) + + if base == location: + assert dirurl is not None + base = dirurl + "/" # save the root url + elif not dirurl or not dirurl.startswith(base): + dirs[:] = [] + continue # not part of the same svn tree, skip it + revision = max(revision, localrev) + return str(revision) + + @classmethod + def get_netloc_and_auth( + cls, netloc: str, scheme: str + ) -> Tuple[str, Tuple[Optional[str], Optional[str]]]: + """ + This override allows the auth information to be passed to svn via the + --username and --password options instead of via the URL. + """ + if scheme == "ssh": + # The --username and --password options can't be used for + # svn+ssh URLs, so keep the auth information in the URL. + return super().get_netloc_and_auth(netloc, scheme) + + return split_auth_from_netloc(netloc) + + @classmethod + def get_url_rev_and_auth(cls, url: str) -> Tuple[str, Optional[str], AuthInfo]: + # hotfix the URL scheme after removing svn+ from svn+ssh:// re-add it + url, rev, user_pass = super().get_url_rev_and_auth(url) + if url.startswith("ssh://"): + url = "svn+" + url + return url, rev, user_pass + + @staticmethod + def make_rev_args( + username: Optional[str], password: Optional[HiddenText] + ) -> CommandArgs: + extra_args: CommandArgs = [] + if username: + extra_args += ["--username", username] + if password: + extra_args += ["--password", password] + + return extra_args + + @classmethod + def get_remote_url(cls, location: str) -> str: + # In cases where the source is in a subdirectory, we have to look up in + # the location until we find a valid project root. + orig_location = location + while not is_installable_dir(location): + last_location = location + location = os.path.dirname(location) + if location == last_location: + # We've traversed up to the root of the filesystem without + # finding a Python project. + logger.warning( + "Could not find Python project for directory %s (tried all " + "parent directories)", + orig_location, + ) + raise RemoteNotFoundError + + url, _rev = cls._get_svn_url_rev(location) + if url is None: + raise RemoteNotFoundError + + return url + + @classmethod + def _get_svn_url_rev(cls, location: str) -> Tuple[Optional[str], int]: + from pip._internal.exceptions import InstallationError + + entries_path = os.path.join(location, cls.dirname, "entries") + if os.path.exists(entries_path): + with open(entries_path) as f: + data = f.read() + else: # subversion >= 1.7 does not have the 'entries' file + data = "" + + url = None + if data.startswith("8") or data.startswith("9") or data.startswith("10"): + entries = list(map(str.splitlines, data.split("\n\x0c\n"))) + del entries[0][0] # get rid of the '8' + url = entries[0][3] + revs = [int(d[9]) for d in entries if len(d) > 9 and d[9]] + [0] + elif data.startswith("= 1.7 + # Note that using get_remote_call_options is not necessary here + # because `svn info` is being run against a local directory. + # We don't need to worry about making sure interactive mode + # is being used to prompt for passwords, because passwords + # are only potentially needed for remote server requests. + xml = cls.run_command( + ["info", "--xml", location], + show_stdout=False, + stdout_only=True, + ) + match = _svn_info_xml_url_re.search(xml) + assert match is not None + url = match.group(1) + revs = [int(m.group(1)) for m in _svn_info_xml_rev_re.finditer(xml)] + except InstallationError: + url, revs = None, [] + + if revs: + rev = max(revs) + else: + rev = 0 + + return url, rev + + @classmethod + def is_commit_id_equal(cls, dest: str, name: Optional[str]) -> bool: + """Always assume the versions don't match""" + return False + + def __init__(self, use_interactive: Optional[bool] = None) -> None: + if use_interactive is None: + use_interactive = is_console_interactive() + self.use_interactive = use_interactive + + # This member is used to cache the fetched version of the current + # ``svn`` client. + # Special value definitions: + # None: Not evaluated yet. + # Empty tuple: Could not parse version. + self._vcs_version: Optional[Tuple[int, ...]] = None + + super().__init__() + + def call_vcs_version(self) -> Tuple[int, ...]: + """Query the version of the currently installed Subversion client. + + :return: A tuple containing the parts of the version information or + ``()`` if the version returned from ``svn`` could not be parsed. + :raises: BadCommand: If ``svn`` is not installed. + """ + # Example versions: + # svn, version 1.10.3 (r1842928) + # compiled Feb 25 2019, 14:20:39 on x86_64-apple-darwin17.0.0 + # svn, version 1.7.14 (r1542130) + # compiled Mar 28 2018, 08:49:13 on x86_64-pc-linux-gnu + # svn, version 1.12.0-SlikSvn (SlikSvn/1.12.0) + # compiled May 28 2019, 13:44:56 on x86_64-microsoft-windows6.2 + version_prefix = "svn, version " + version = self.run_command(["--version"], show_stdout=False, stdout_only=True) + if not version.startswith(version_prefix): + return () + + version = version[len(version_prefix) :].split()[0] + version_list = version.partition("-")[0].split(".") + try: + parsed_version = tuple(map(int, version_list)) + except ValueError: + return () + + return parsed_version + + def get_vcs_version(self) -> Tuple[int, ...]: + """Return the version of the currently installed Subversion client. + + If the version of the Subversion client has already been queried, + a cached value will be used. + + :return: A tuple containing the parts of the version information or + ``()`` if the version returned from ``svn`` could not be parsed. + :raises: BadCommand: If ``svn`` is not installed. + """ + if self._vcs_version is not None: + # Use cached version, if available. + # If parsing the version failed previously (empty tuple), + # do not attempt to parse it again. + return self._vcs_version + + vcs_version = self.call_vcs_version() + self._vcs_version = vcs_version + return vcs_version + + def get_remote_call_options(self) -> CommandArgs: + """Return options to be used on calls to Subversion that contact the server. + + These options are applicable for the following ``svn`` subcommands used + in this class. + + - checkout + - switch + - update + + :return: A list of command line arguments to pass to ``svn``. + """ + if not self.use_interactive: + # --non-interactive switch is available since Subversion 0.14.4. + # Subversion < 1.8 runs in interactive mode by default. + return ["--non-interactive"] + + svn_version = self.get_vcs_version() + # By default, Subversion >= 1.8 runs in non-interactive mode if + # stdin is not a TTY. Since that is how pip invokes SVN, in + # call_subprocess(), pip must pass --force-interactive to ensure + # the user can be prompted for a password, if required. + # SVN added the --force-interactive option in SVN 1.8. Since + # e.g. RHEL/CentOS 7, which is supported until 2024, ships with + # SVN 1.7, pip should continue to support SVN 1.7. Therefore, pip + # can't safely add the option if the SVN version is < 1.8 (or unknown). + if svn_version >= (1, 8): + return ["--force-interactive"] + + return [] + + def fetch_new( + self, dest: str, url: HiddenText, rev_options: RevOptions, verbosity: int + ) -> None: + rev_display = rev_options.to_display() + logger.info( + "Checking out %s%s to %s", + url, + rev_display, + display_path(dest), + ) + if verbosity <= 0: + flags = ["--quiet"] + else: + flags = [] + cmd_args = make_command( + "checkout", + *flags, + self.get_remote_call_options(), + rev_options.to_args(), + url, + dest, + ) + self.run_command(cmd_args) + + def switch(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: + cmd_args = make_command( + "switch", + self.get_remote_call_options(), + rev_options.to_args(), + url, + dest, + ) + self.run_command(cmd_args) + + def update(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: + cmd_args = make_command( + "update", + self.get_remote_call_options(), + rev_options.to_args(), + dest, + ) + self.run_command(cmd_args) + + +vcs.register(Subversion) diff --git a/backend/.venv/Lib/site-packages/pip/_internal/vcs/versioncontrol.py b/backend/.venv/Lib/site-packages/pip/_internal/vcs/versioncontrol.py new file mode 100644 index 0000000..a413316 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/vcs/versioncontrol.py @@ -0,0 +1,688 @@ +"""Handles all VCS (version control) support""" + +import logging +import os +import shutil +import sys +import urllib.parse +from dataclasses import dataclass, field +from typing import ( + Any, + Dict, + Iterable, + Iterator, + List, + Literal, + Mapping, + Optional, + Tuple, + Type, + Union, +) + +from pip._internal.cli.spinners import SpinnerInterface +from pip._internal.exceptions import BadCommand, InstallationError +from pip._internal.utils.misc import ( + HiddenText, + ask_path_exists, + backup_dir, + display_path, + hide_url, + hide_value, + is_installable_dir, + rmtree, +) +from pip._internal.utils.subprocess import ( + CommandArgs, + call_subprocess, + format_command_args, + make_command, +) + +__all__ = ["vcs"] + + +logger = logging.getLogger(__name__) + +AuthInfo = Tuple[Optional[str], Optional[str]] + + +def is_url(name: str) -> bool: + """ + Return true if the name looks like a URL. + """ + scheme = urllib.parse.urlsplit(name).scheme + if not scheme: + return False + return scheme in ["http", "https", "file", "ftp"] + vcs.all_schemes + + +def make_vcs_requirement_url( + repo_url: str, rev: str, project_name: str, subdir: Optional[str] = None +) -> str: + """ + Return the URL for a VCS requirement. + + Args: + repo_url: the remote VCS url, with any needed VCS prefix (e.g. "git+"). + project_name: the (unescaped) project name. + """ + egg_project_name = project_name.replace("-", "_") + req = f"{repo_url}@{rev}#egg={egg_project_name}" + if subdir: + req += f"&subdirectory={subdir}" + + return req + + +def find_path_to_project_root_from_repo_root( + location: str, repo_root: str +) -> Optional[str]: + """ + Find the the Python project's root by searching up the filesystem from + `location`. Return the path to project root relative to `repo_root`. + Return None if the project root is `repo_root`, or cannot be found. + """ + # find project root. + orig_location = location + while not is_installable_dir(location): + last_location = location + location = os.path.dirname(location) + if location == last_location: + # We've traversed up to the root of the filesystem without + # finding a Python project. + logger.warning( + "Could not find a Python project for directory %s (tried all " + "parent directories)", + orig_location, + ) + return None + + if os.path.samefile(repo_root, location): + return None + + return os.path.relpath(location, repo_root) + + +class RemoteNotFoundError(Exception): + pass + + +class RemoteNotValidError(Exception): + def __init__(self, url: str): + super().__init__(url) + self.url = url + + +@dataclass(frozen=True) +class RevOptions: + """ + Encapsulates a VCS-specific revision to install, along with any VCS + install options. + + Args: + vc_class: a VersionControl subclass. + rev: the name of the revision to install. + extra_args: a list of extra options. + """ + + vc_class: Type["VersionControl"] + rev: Optional[str] = None + extra_args: CommandArgs = field(default_factory=list) + branch_name: Optional[str] = None + + def __repr__(self) -> str: + return f"" + + @property + def arg_rev(self) -> Optional[str]: + if self.rev is None: + return self.vc_class.default_arg_rev + + return self.rev + + def to_args(self) -> CommandArgs: + """ + Return the VCS-specific command arguments. + """ + args: CommandArgs = [] + rev = self.arg_rev + if rev is not None: + args += self.vc_class.get_base_rev_args(rev) + args += self.extra_args + + return args + + def to_display(self) -> str: + if not self.rev: + return "" + + return f" (to revision {self.rev})" + + def make_new(self, rev: str) -> "RevOptions": + """ + Make a copy of the current instance, but with a new rev. + + Args: + rev: the name of the revision for the new object. + """ + return self.vc_class.make_rev_options(rev, extra_args=self.extra_args) + + +class VcsSupport: + _registry: Dict[str, "VersionControl"] = {} + schemes = ["ssh", "git", "hg", "bzr", "sftp", "svn"] + + def __init__(self) -> None: + # Register more schemes with urlparse for various version control + # systems + urllib.parse.uses_netloc.extend(self.schemes) + super().__init__() + + def __iter__(self) -> Iterator[str]: + return self._registry.__iter__() + + @property + def backends(self) -> List["VersionControl"]: + return list(self._registry.values()) + + @property + def dirnames(self) -> List[str]: + return [backend.dirname for backend in self.backends] + + @property + def all_schemes(self) -> List[str]: + schemes: List[str] = [] + for backend in self.backends: + schemes.extend(backend.schemes) + return schemes + + def register(self, cls: Type["VersionControl"]) -> None: + if not hasattr(cls, "name"): + logger.warning("Cannot register VCS %s", cls.__name__) + return + if cls.name not in self._registry: + self._registry[cls.name] = cls() + logger.debug("Registered VCS backend: %s", cls.name) + + def unregister(self, name: str) -> None: + if name in self._registry: + del self._registry[name] + + def get_backend_for_dir(self, location: str) -> Optional["VersionControl"]: + """ + Return a VersionControl object if a repository of that type is found + at the given directory. + """ + vcs_backends = {} + for vcs_backend in self._registry.values(): + repo_path = vcs_backend.get_repository_root(location) + if not repo_path: + continue + logger.debug("Determine that %s uses VCS: %s", location, vcs_backend.name) + vcs_backends[repo_path] = vcs_backend + + if not vcs_backends: + return None + + # Choose the VCS in the inner-most directory. Since all repository + # roots found here would be either `location` or one of its + # parents, the longest path should have the most path components, + # i.e. the backend representing the inner-most repository. + inner_most_repo_path = max(vcs_backends, key=len) + return vcs_backends[inner_most_repo_path] + + def get_backend_for_scheme(self, scheme: str) -> Optional["VersionControl"]: + """ + Return a VersionControl object or None. + """ + for vcs_backend in self._registry.values(): + if scheme in vcs_backend.schemes: + return vcs_backend + return None + + def get_backend(self, name: str) -> Optional["VersionControl"]: + """ + Return a VersionControl object or None. + """ + name = name.lower() + return self._registry.get(name) + + +vcs = VcsSupport() + + +class VersionControl: + name = "" + dirname = "" + repo_name = "" + # List of supported schemes for this Version Control + schemes: Tuple[str, ...] = () + # Iterable of environment variable names to pass to call_subprocess(). + unset_environ: Tuple[str, ...] = () + default_arg_rev: Optional[str] = None + + @classmethod + def should_add_vcs_url_prefix(cls, remote_url: str) -> bool: + """ + Return whether the vcs prefix (e.g. "git+") should be added to a + repository's remote url when used in a requirement. + """ + return not remote_url.lower().startswith(f"{cls.name}:") + + @classmethod + def get_subdirectory(cls, location: str) -> Optional[str]: + """ + Return the path to Python project root, relative to the repo root. + Return None if the project root is in the repo root. + """ + return None + + @classmethod + def get_requirement_revision(cls, repo_dir: str) -> str: + """ + Return the revision string that should be used in a requirement. + """ + return cls.get_revision(repo_dir) + + @classmethod + def get_src_requirement(cls, repo_dir: str, project_name: str) -> str: + """ + Return the requirement string to use to redownload the files + currently at the given repository directory. + + Args: + project_name: the (unescaped) project name. + + The return value has a form similar to the following: + + {repository_url}@{revision}#egg={project_name} + """ + repo_url = cls.get_remote_url(repo_dir) + + if cls.should_add_vcs_url_prefix(repo_url): + repo_url = f"{cls.name}+{repo_url}" + + revision = cls.get_requirement_revision(repo_dir) + subdir = cls.get_subdirectory(repo_dir) + req = make_vcs_requirement_url(repo_url, revision, project_name, subdir=subdir) + + return req + + @staticmethod + def get_base_rev_args(rev: str) -> List[str]: + """ + Return the base revision arguments for a vcs command. + + Args: + rev: the name of a revision to install. Cannot be None. + """ + raise NotImplementedError + + def is_immutable_rev_checkout(self, url: str, dest: str) -> bool: + """ + Return true if the commit hash checked out at dest matches + the revision in url. + + Always return False, if the VCS does not support immutable commit + hashes. + + This method does not check if there are local uncommitted changes + in dest after checkout, as pip currently has no use case for that. + """ + return False + + @classmethod + def make_rev_options( + cls, rev: Optional[str] = None, extra_args: Optional[CommandArgs] = None + ) -> RevOptions: + """ + Return a RevOptions object. + + Args: + rev: the name of a revision to install. + extra_args: a list of extra options. + """ + return RevOptions(cls, rev, extra_args=extra_args or []) + + @classmethod + def _is_local_repository(cls, repo: str) -> bool: + """ + posix absolute paths start with os.path.sep, + win32 ones start with drive (like c:\\folder) + """ + drive, tail = os.path.splitdrive(repo) + return repo.startswith(os.path.sep) or bool(drive) + + @classmethod + def get_netloc_and_auth( + cls, netloc: str, scheme: str + ) -> Tuple[str, Tuple[Optional[str], Optional[str]]]: + """ + Parse the repository URL's netloc, and return the new netloc to use + along with auth information. + + Args: + netloc: the original repository URL netloc. + scheme: the repository URL's scheme without the vcs prefix. + + This is mainly for the Subversion class to override, so that auth + information can be provided via the --username and --password options + instead of through the URL. For other subclasses like Git without + such an option, auth information must stay in the URL. + + Returns: (netloc, (username, password)). + """ + return netloc, (None, None) + + @classmethod + def get_url_rev_and_auth(cls, url: str) -> Tuple[str, Optional[str], AuthInfo]: + """ + Parse the repository URL to use, and return the URL, revision, + and auth info to use. + + Returns: (url, rev, (username, password)). + """ + scheme, netloc, path, query, frag = urllib.parse.urlsplit(url) + if "+" not in scheme: + raise ValueError( + f"Sorry, {url!r} is a malformed VCS url. " + "The format is +://, " + "e.g. svn+http://myrepo/svn/MyApp#egg=MyApp" + ) + # Remove the vcs prefix. + scheme = scheme.split("+", 1)[1] + netloc, user_pass = cls.get_netloc_and_auth(netloc, scheme) + rev = None + if "@" in path: + path, rev = path.rsplit("@", 1) + if not rev: + raise InstallationError( + f"The URL {url!r} has an empty revision (after @) " + "which is not supported. Include a revision after @ " + "or remove @ from the URL." + ) + url = urllib.parse.urlunsplit((scheme, netloc, path, query, "")) + return url, rev, user_pass + + @staticmethod + def make_rev_args( + username: Optional[str], password: Optional[HiddenText] + ) -> CommandArgs: + """ + Return the RevOptions "extra arguments" to use in obtain(). + """ + return [] + + def get_url_rev_options(self, url: HiddenText) -> Tuple[HiddenText, RevOptions]: + """ + Return the URL and RevOptions object to use in obtain(), + as a tuple (url, rev_options). + """ + secret_url, rev, user_pass = self.get_url_rev_and_auth(url.secret) + username, secret_password = user_pass + password: Optional[HiddenText] = None + if secret_password is not None: + password = hide_value(secret_password) + extra_args = self.make_rev_args(username, password) + rev_options = self.make_rev_options(rev, extra_args=extra_args) + + return hide_url(secret_url), rev_options + + @staticmethod + def normalize_url(url: str) -> str: + """ + Normalize a URL for comparison by unquoting it and removing any + trailing slash. + """ + return urllib.parse.unquote(url).rstrip("/") + + @classmethod + def compare_urls(cls, url1: str, url2: str) -> bool: + """ + Compare two repo URLs for identity, ignoring incidental differences. + """ + return cls.normalize_url(url1) == cls.normalize_url(url2) + + def fetch_new( + self, dest: str, url: HiddenText, rev_options: RevOptions, verbosity: int + ) -> None: + """ + Fetch a revision from a repository, in the case that this is the + first fetch from the repository. + + Args: + dest: the directory to fetch the repository to. + rev_options: a RevOptions object. + verbosity: verbosity level. + """ + raise NotImplementedError + + def switch(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: + """ + Switch the repo at ``dest`` to point to ``URL``. + + Args: + rev_options: a RevOptions object. + """ + raise NotImplementedError + + def update(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: + """ + Update an already-existing repo to the given ``rev_options``. + + Args: + rev_options: a RevOptions object. + """ + raise NotImplementedError + + @classmethod + def is_commit_id_equal(cls, dest: str, name: Optional[str]) -> bool: + """ + Return whether the id of the current commit equals the given name. + + Args: + dest: the repository directory. + name: a string name. + """ + raise NotImplementedError + + def obtain(self, dest: str, url: HiddenText, verbosity: int) -> None: + """ + Install or update in editable mode the package represented by this + VersionControl object. + + :param dest: the repository directory in which to install or update. + :param url: the repository URL starting with a vcs prefix. + :param verbosity: verbosity level. + """ + url, rev_options = self.get_url_rev_options(url) + + if not os.path.exists(dest): + self.fetch_new(dest, url, rev_options, verbosity=verbosity) + return + + rev_display = rev_options.to_display() + if self.is_repository_directory(dest): + existing_url = self.get_remote_url(dest) + if self.compare_urls(existing_url, url.secret): + logger.debug( + "%s in %s exists, and has correct URL (%s)", + self.repo_name.title(), + display_path(dest), + url, + ) + if not self.is_commit_id_equal(dest, rev_options.rev): + logger.info( + "Updating %s %s%s", + display_path(dest), + self.repo_name, + rev_display, + ) + self.update(dest, url, rev_options) + else: + logger.info("Skipping because already up-to-date.") + return + + logger.warning( + "%s %s in %s exists with URL %s", + self.name, + self.repo_name, + display_path(dest), + existing_url, + ) + prompt = ("(s)witch, (i)gnore, (w)ipe, (b)ackup ", ("s", "i", "w", "b")) + else: + logger.warning( + "Directory %s already exists, and is not a %s %s.", + dest, + self.name, + self.repo_name, + ) + # https://github.com/python/mypy/issues/1174 + prompt = ("(i)gnore, (w)ipe, (b)ackup ", ("i", "w", "b")) # type: ignore + + logger.warning( + "The plan is to install the %s repository %s", + self.name, + url, + ) + response = ask_path_exists(f"What to do? {prompt[0]}", prompt[1]) + + if response == "a": + sys.exit(-1) + + if response == "w": + logger.warning("Deleting %s", display_path(dest)) + rmtree(dest) + self.fetch_new(dest, url, rev_options, verbosity=verbosity) + return + + if response == "b": + dest_dir = backup_dir(dest) + logger.warning("Backing up %s to %s", display_path(dest), dest_dir) + shutil.move(dest, dest_dir) + self.fetch_new(dest, url, rev_options, verbosity=verbosity) + return + + # Do nothing if the response is "i". + if response == "s": + logger.info( + "Switching %s %s to %s%s", + self.repo_name, + display_path(dest), + url, + rev_display, + ) + self.switch(dest, url, rev_options) + + def unpack(self, location: str, url: HiddenText, verbosity: int) -> None: + """ + Clean up current location and download the url repository + (and vcs infos) into location + + :param url: the repository URL starting with a vcs prefix. + :param verbosity: verbosity level. + """ + if os.path.exists(location): + rmtree(location) + self.obtain(location, url=url, verbosity=verbosity) + + @classmethod + def get_remote_url(cls, location: str) -> str: + """ + Return the url used at location + + Raises RemoteNotFoundError if the repository does not have a remote + url configured. + """ + raise NotImplementedError + + @classmethod + def get_revision(cls, location: str) -> str: + """ + Return the current commit id of the files at the given location. + """ + raise NotImplementedError + + @classmethod + def run_command( + cls, + cmd: Union[List[str], CommandArgs], + show_stdout: bool = True, + cwd: Optional[str] = None, + on_returncode: 'Literal["raise", "warn", "ignore"]' = "raise", + extra_ok_returncodes: Optional[Iterable[int]] = None, + command_desc: Optional[str] = None, + extra_environ: Optional[Mapping[str, Any]] = None, + spinner: Optional[SpinnerInterface] = None, + log_failed_cmd: bool = True, + stdout_only: bool = False, + ) -> str: + """ + Run a VCS subcommand + This is simply a wrapper around call_subprocess that adds the VCS + command name, and checks that the VCS is available + """ + cmd = make_command(cls.name, *cmd) + if command_desc is None: + command_desc = format_command_args(cmd) + try: + return call_subprocess( + cmd, + show_stdout, + cwd, + on_returncode=on_returncode, + extra_ok_returncodes=extra_ok_returncodes, + command_desc=command_desc, + extra_environ=extra_environ, + unset_environ=cls.unset_environ, + spinner=spinner, + log_failed_cmd=log_failed_cmd, + stdout_only=stdout_only, + ) + except NotADirectoryError: + raise BadCommand(f"Cannot find command {cls.name!r} - invalid PATH") + except FileNotFoundError: + # errno.ENOENT = no such file or directory + # In other words, the VCS executable isn't available + raise BadCommand( + f"Cannot find command {cls.name!r} - do you have " + f"{cls.name!r} installed and in your PATH?" + ) + except PermissionError: + # errno.EACCES = Permission denied + # This error occurs, for instance, when the command is installed + # only for another user. So, the current user don't have + # permission to call the other user command. + raise BadCommand( + f"No permission to execute {cls.name!r} - install it " + f"locally, globally (ask admin), or check your PATH. " + f"See possible solutions at " + f"https://pip.pypa.io/en/latest/reference/pip_freeze/" + f"#fixing-permission-denied." + ) + + @classmethod + def is_repository_directory(cls, path: str) -> bool: + """ + Return whether a directory path is a repository directory. + """ + logger.debug("Checking in %s for %s (%s)...", path, cls.dirname, cls.name) + return os.path.exists(os.path.join(path, cls.dirname)) + + @classmethod + def get_repository_root(cls, location: str) -> Optional[str]: + """ + Return the "root" (top-level) directory controlled by the vcs, + or `None` if the directory is not in any. + + It is meant to be overridden to implement smarter detection + mechanisms for specific vcs. + + This can do more than is_repository_directory() alone. For + example, the Git override checks that Git is actually available. + """ + if cls.is_repository_directory(location): + return location + return None diff --git a/backend/.venv/Lib/site-packages/pip/_internal/wheel_builder.py b/backend/.venv/Lib/site-packages/pip/_internal/wheel_builder.py new file mode 100644 index 0000000..93f8e1f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_internal/wheel_builder.py @@ -0,0 +1,354 @@ +"""Orchestrator for building wheels from InstallRequirements. +""" + +import logging +import os.path +import re +import shutil +from typing import Iterable, List, Optional, Tuple + +from pip._vendor.packaging.utils import canonicalize_name, canonicalize_version +from pip._vendor.packaging.version import InvalidVersion, Version + +from pip._internal.cache import WheelCache +from pip._internal.exceptions import InvalidWheelFilename, UnsupportedWheel +from pip._internal.metadata import FilesystemWheel, get_wheel_distribution +from pip._internal.models.link import Link +from pip._internal.models.wheel import Wheel +from pip._internal.operations.build.wheel import build_wheel_pep517 +from pip._internal.operations.build.wheel_editable import build_wheel_editable +from pip._internal.operations.build.wheel_legacy import build_wheel_legacy +from pip._internal.req.req_install import InstallRequirement +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import ensure_dir, hash_file +from pip._internal.utils.setuptools_build import make_setuptools_clean_args +from pip._internal.utils.subprocess import call_subprocess +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.urls import path_to_url +from pip._internal.vcs import vcs + +logger = logging.getLogger(__name__) + +_egg_info_re = re.compile(r"([a-z0-9_.]+)-([a-z0-9_.!+-]+)", re.IGNORECASE) + +BuildResult = Tuple[List[InstallRequirement], List[InstallRequirement]] + + +def _contains_egg_info(s: str) -> bool: + """Determine whether the string looks like an egg_info. + + :param s: The string to parse. E.g. foo-2.1 + """ + return bool(_egg_info_re.search(s)) + + +def _should_build( + req: InstallRequirement, + need_wheel: bool, +) -> bool: + """Return whether an InstallRequirement should be built into a wheel.""" + if req.constraint: + # never build requirements that are merely constraints + return False + if req.is_wheel: + if need_wheel: + logger.info( + "Skipping %s, due to already being wheel.", + req.name, + ) + return False + + if need_wheel: + # i.e. pip wheel, not pip install + return True + + # From this point, this concerns the pip install command only + # (need_wheel=False). + + if not req.source_dir: + return False + + if req.editable: + # we only build PEP 660 editable requirements + return req.supports_pyproject_editable + + return True + + +def should_build_for_wheel_command( + req: InstallRequirement, +) -> bool: + return _should_build(req, need_wheel=True) + + +def should_build_for_install_command( + req: InstallRequirement, +) -> bool: + return _should_build(req, need_wheel=False) + + +def _should_cache( + req: InstallRequirement, +) -> Optional[bool]: + """ + Return whether a built InstallRequirement can be stored in the persistent + wheel cache, assuming the wheel cache is available, and _should_build() + has determined a wheel needs to be built. + """ + if req.editable or not req.source_dir: + # never cache editable requirements + return False + + if req.link and req.link.is_vcs: + # VCS checkout. Do not cache + # unless it points to an immutable commit hash. + assert not req.editable + assert req.source_dir + vcs_backend = vcs.get_backend_for_scheme(req.link.scheme) + assert vcs_backend + if vcs_backend.is_immutable_rev_checkout(req.link.url, req.source_dir): + return True + return False + + assert req.link + base, ext = req.link.splitext() + if _contains_egg_info(base): + return True + + # Otherwise, do not cache. + return False + + +def _get_cache_dir( + req: InstallRequirement, + wheel_cache: WheelCache, +) -> str: + """Return the persistent or temporary cache directory where the built + wheel need to be stored. + """ + cache_available = bool(wheel_cache.cache_dir) + assert req.link + if cache_available and _should_cache(req): + cache_dir = wheel_cache.get_path_for_link(req.link) + else: + cache_dir = wheel_cache.get_ephem_path_for_link(req.link) + return cache_dir + + +def _verify_one(req: InstallRequirement, wheel_path: str) -> None: + canonical_name = canonicalize_name(req.name or "") + w = Wheel(os.path.basename(wheel_path)) + if canonicalize_name(w.name) != canonical_name: + raise InvalidWheelFilename( + f"Wheel has unexpected file name: expected {canonical_name!r}, " + f"got {w.name!r}", + ) + dist = get_wheel_distribution(FilesystemWheel(wheel_path), canonical_name) + dist_verstr = str(dist.version) + if canonicalize_version(dist_verstr) != canonicalize_version(w.version): + raise InvalidWheelFilename( + f"Wheel has unexpected file name: expected {dist_verstr!r}, " + f"got {w.version!r}", + ) + metadata_version_value = dist.metadata_version + if metadata_version_value is None: + raise UnsupportedWheel("Missing Metadata-Version") + try: + metadata_version = Version(metadata_version_value) + except InvalidVersion: + msg = f"Invalid Metadata-Version: {metadata_version_value}" + raise UnsupportedWheel(msg) + if metadata_version >= Version("1.2") and not isinstance(dist.version, Version): + raise UnsupportedWheel( + f"Metadata 1.2 mandates PEP 440 version, but {dist_verstr!r} is not" + ) + + +def _build_one( + req: InstallRequirement, + output_dir: str, + verify: bool, + build_options: List[str], + global_options: List[str], + editable: bool, +) -> Optional[str]: + """Build one wheel. + + :return: The filename of the built wheel, or None if the build failed. + """ + artifact = "editable" if editable else "wheel" + try: + ensure_dir(output_dir) + except OSError as e: + logger.warning( + "Building %s for %s failed: %s", + artifact, + req.name, + e, + ) + return None + + # Install build deps into temporary directory (PEP 518) + with req.build_env: + wheel_path = _build_one_inside_env( + req, output_dir, build_options, global_options, editable + ) + if wheel_path and verify: + try: + _verify_one(req, wheel_path) + except (InvalidWheelFilename, UnsupportedWheel) as e: + logger.warning("Built %s for %s is invalid: %s", artifact, req.name, e) + return None + return wheel_path + + +def _build_one_inside_env( + req: InstallRequirement, + output_dir: str, + build_options: List[str], + global_options: List[str], + editable: bool, +) -> Optional[str]: + with TempDirectory(kind="wheel") as temp_dir: + assert req.name + if req.use_pep517: + assert req.metadata_directory + assert req.pep517_backend + if global_options: + logger.warning( + "Ignoring --global-option when building %s using PEP 517", req.name + ) + if build_options: + logger.warning( + "Ignoring --build-option when building %s using PEP 517", req.name + ) + if editable: + wheel_path = build_wheel_editable( + name=req.name, + backend=req.pep517_backend, + metadata_directory=req.metadata_directory, + tempd=temp_dir.path, + ) + else: + wheel_path = build_wheel_pep517( + name=req.name, + backend=req.pep517_backend, + metadata_directory=req.metadata_directory, + tempd=temp_dir.path, + ) + else: + wheel_path = build_wheel_legacy( + name=req.name, + setup_py_path=req.setup_py_path, + source_dir=req.unpacked_source_directory, + global_options=global_options, + build_options=build_options, + tempd=temp_dir.path, + ) + + if wheel_path is not None: + wheel_name = os.path.basename(wheel_path) + dest_path = os.path.join(output_dir, wheel_name) + try: + wheel_hash, length = hash_file(wheel_path) + shutil.move(wheel_path, dest_path) + logger.info( + "Created wheel for %s: filename=%s size=%d sha256=%s", + req.name, + wheel_name, + length, + wheel_hash.hexdigest(), + ) + logger.info("Stored in directory: %s", output_dir) + return dest_path + except Exception as e: + logger.warning( + "Building wheel for %s failed: %s", + req.name, + e, + ) + # Ignore return, we can't do anything else useful. + if not req.use_pep517: + _clean_one_legacy(req, global_options) + return None + + +def _clean_one_legacy(req: InstallRequirement, global_options: List[str]) -> bool: + clean_args = make_setuptools_clean_args( + req.setup_py_path, + global_options=global_options, + ) + + logger.info("Running setup.py clean for %s", req.name) + try: + call_subprocess( + clean_args, command_desc="python setup.py clean", cwd=req.source_dir + ) + return True + except Exception: + logger.error("Failed cleaning build dir for %s", req.name) + return False + + +def build( + requirements: Iterable[InstallRequirement], + wheel_cache: WheelCache, + verify: bool, + build_options: List[str], + global_options: List[str], +) -> BuildResult: + """Build wheels. + + :return: The list of InstallRequirement that succeeded to build and + the list of InstallRequirement that failed to build. + """ + if not requirements: + return [], [] + + # Build the wheels. + logger.info( + "Building wheels for collected packages: %s", + ", ".join(req.name for req in requirements), # type: ignore + ) + + with indent_log(): + build_successes, build_failures = [], [] + for req in requirements: + assert req.name + cache_dir = _get_cache_dir(req, wheel_cache) + wheel_file = _build_one( + req, + cache_dir, + verify, + build_options, + global_options, + req.editable and req.permit_editable_wheels, + ) + if wheel_file: + # Record the download origin in the cache + if req.download_info is not None: + # download_info is guaranteed to be set because when we build an + # InstallRequirement it has been through the preparer before, but + # let's be cautious. + wheel_cache.record_download_origin(cache_dir, req.download_info) + # Update the link for this. + req.link = Link(path_to_url(wheel_file)) + req.local_file_path = req.link.file_path + assert req.link.is_wheel + build_successes.append(req) + else: + build_failures.append(req) + + # notify success/failure + if build_successes: + logger.info( + "Successfully built %s", + " ".join([req.name for req in build_successes]), # type: ignore + ) + if build_failures: + logger.info( + "Failed to build %s", + " ".join([req.name for req in build_failures]), # type: ignore + ) + # Return a list of requirements that failed to build + return build_successes, build_failures diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/__init__.py b/backend/.venv/Lib/site-packages/pip/_vendor/__init__.py new file mode 100644 index 0000000..561089c --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/__init__.py @@ -0,0 +1,116 @@ +""" +pip._vendor is for vendoring dependencies of pip to prevent needing pip to +depend on something external. + +Files inside of pip._vendor should be considered immutable and should only be +updated to versions from upstream. +""" +from __future__ import absolute_import + +import glob +import os.path +import sys + +# Downstream redistributors which have debundled our dependencies should also +# patch this value to be true. This will trigger the additional patching +# to cause things like "six" to be available as pip. +DEBUNDLED = False + +# By default, look in this directory for a bunch of .whl files which we will +# add to the beginning of sys.path before attempting to import anything. This +# is done to support downstream re-distributors like Debian and Fedora who +# wish to create their own Wheels for our dependencies to aid in debundling. +WHEEL_DIR = os.path.abspath(os.path.dirname(__file__)) + + +# Define a small helper function to alias our vendored modules to the real ones +# if the vendored ones do not exist. This idea of this was taken from +# https://github.com/kennethreitz/requests/pull/2567. +def vendored(modulename): + vendored_name = "{0}.{1}".format(__name__, modulename) + + try: + __import__(modulename, globals(), locals(), level=0) + except ImportError: + # We can just silently allow import failures to pass here. If we + # got to this point it means that ``import pip._vendor.whatever`` + # failed and so did ``import whatever``. Since we're importing this + # upfront in an attempt to alias imports, not erroring here will + # just mean we get a regular import error whenever pip *actually* + # tries to import one of these modules to use it, which actually + # gives us a better error message than we would have otherwise + # gotten. + pass + else: + sys.modules[vendored_name] = sys.modules[modulename] + base, head = vendored_name.rsplit(".", 1) + setattr(sys.modules[base], head, sys.modules[modulename]) + + +# If we're operating in a debundled setup, then we want to go ahead and trigger +# the aliasing of our vendored libraries as well as looking for wheels to add +# to our sys.path. This will cause all of this code to be a no-op typically +# however downstream redistributors can enable it in a consistent way across +# all platforms. +if DEBUNDLED: + # Actually look inside of WHEEL_DIR to find .whl files and add them to the + # front of our sys.path. + sys.path[:] = glob.glob(os.path.join(WHEEL_DIR, "*.whl")) + sys.path + + # Actually alias all of our vendored dependencies. + vendored("cachecontrol") + vendored("certifi") + vendored("distlib") + vendored("distro") + vendored("packaging") + vendored("packaging.version") + vendored("packaging.specifiers") + vendored("pkg_resources") + vendored("platformdirs") + vendored("progress") + vendored("pyproject_hooks") + vendored("requests") + vendored("requests.exceptions") + vendored("requests.packages") + vendored("requests.packages.urllib3") + vendored("requests.packages.urllib3._collections") + vendored("requests.packages.urllib3.connection") + vendored("requests.packages.urllib3.connectionpool") + vendored("requests.packages.urllib3.contrib") + vendored("requests.packages.urllib3.contrib.ntlmpool") + vendored("requests.packages.urllib3.contrib.pyopenssl") + vendored("requests.packages.urllib3.exceptions") + vendored("requests.packages.urllib3.fields") + vendored("requests.packages.urllib3.filepost") + vendored("requests.packages.urllib3.packages") + vendored("requests.packages.urllib3.packages.ordered_dict") + vendored("requests.packages.urllib3.packages.six") + vendored("requests.packages.urllib3.packages.ssl_match_hostname") + vendored("requests.packages.urllib3.packages.ssl_match_hostname." + "_implementation") + vendored("requests.packages.urllib3.poolmanager") + vendored("requests.packages.urllib3.request") + vendored("requests.packages.urllib3.response") + vendored("requests.packages.urllib3.util") + vendored("requests.packages.urllib3.util.connection") + vendored("requests.packages.urllib3.util.request") + vendored("requests.packages.urllib3.util.response") + vendored("requests.packages.urllib3.util.retry") + vendored("requests.packages.urllib3.util.ssl_") + vendored("requests.packages.urllib3.util.timeout") + vendored("requests.packages.urllib3.util.url") + vendored("resolvelib") + vendored("rich") + vendored("rich.console") + vendored("rich.highlighter") + vendored("rich.logging") + vendored("rich.markup") + vendored("rich.progress") + vendored("rich.segment") + vendored("rich.style") + vendored("rich.text") + vendored("rich.traceback") + if sys.version_info < (3, 11): + vendored("tomli") + vendored("truststore") + vendored("urllib3") diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..00af785b3e16f249cedd8c22d3e573e04f9828c8 GIT binary patch literal 4552 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 z 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 A>Hq)$ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py new file mode 100644 index 0000000..b34b0fc --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 + +"""CacheControl import Interface. + +Make it easy to import from cachecontrol without long namespaces. +""" +__author__ = "Eric Larson" +__email__ = "eric@ionrock.org" +__version__ = "0.14.0" + +from pip._vendor.cachecontrol.adapter import CacheControlAdapter +from pip._vendor.cachecontrol.controller import CacheController +from pip._vendor.cachecontrol.wrapper import CacheControl + +__all__ = [ + "__author__", + "__email__", + "__version__", + "CacheControlAdapter", + "CacheController", + "CacheControl", +] + +import logging + +logging.getLogger(__name__).addHandler(logging.NullHandler()) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..077343e9a66de92088ea575e39938d42c621ee25 GIT binary patch literal 905 zcmaJ<&ui2`6rR~%*(Cj`QiNg&2wnHkw1O9xRx3qNXnPf6V3=lR)9Fq!VUq3AJ?)?1 z&8vt9rGJVSOOcj9K@bn#s=aygWxGrFqH}ojy*Kl|_q{jsd3xGHuy$T=hz})%z8B7T zRYu_IBY?MvArCR^VOH`=tn8Ipg;ixGs(Mw70M}$KGCX654Ox#&&%`K1to|N*7Mz>X z_Usbk_QBn8ft#IAALDE9;NDGijD}fDWAA1^9>H-gMn`7T>hEpQV4rWPIMYfxB1)9b zoR@LNb(;pkX&p%c@HrwK5muGP1n zYY{lxRHrKL&v9@zg^INbIWP(&AxrK@0en{&BA2vY$Z)rzQ5m^zr;Nkrm8 zX3Ug!Cp&fNwWuLie*d4>MuP#Z!-D@I>}i@LaIKJ3=%KREZAcY{A`Wvic0uJbw} z#c1KwqKv(uF$4PC-t9^`az3FeU_pP{TP?q*bZ7VqeteLnD>MjHH_m`^B~Y6Cdo<`k zd%g=z9{Ss2&re0hSK!$?G~}rdovn@rusS(_RYF88GD6(sD6g+aighJ_q8FfS@iEg^ zU@prT<6l-8S1#*lW^rJhPc041^O=Q#{R3@Ypr;q;@$ZUZmj=ewEre&kq4|MvhUQPu j{F?`-Xz>g!pP=P0jn=!~S)+B*Xq`6JzoHF&2e|(Nyod(R literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a45df28c098481c7294e0e3aea7653747ff95a7c GIT binary patch literal 2649 zcmaJ@L2MI86rJ52+Z(U#I3$Kpl3;KO@ga_?q86nkEsY^51cM4xs%vSrc(;z7_1c|X zgKQ;|k*J{JP>?ExLl1C56&&cLz4lb8>IFAJPFIQ4igM^JQs||p{+Zp44GkT|JAeMn z{QdjifB)x~a5#uyocZ)v@n=6mPwB!Nyd!X1--ED>RHSk`Dsx$mqcX4aSsrFV7s@z` znGWl|vOnu*vQH0`#jMC=zur?0W`j%)=u$b94KZ2N!{tae!XeF1LSU;0Z1rY)*;&z_h*{b6PX6e7_+uW6=bg4{o? zBp5l{t@R^YFWi?f;+hOpuR+U{Z$pE}~H~h>LJep`72d|&KdiLv? ztm1>~kytyDXhjk$k=L6uu-nG57LMI2Ji#Mda09)797TX3_Y(-+$XOIqHoQoy z9OO27$UkuLgUELf+6hVb{t~yym1xLc8ma);c!L)-wj-sL$8-QoeyjCMc(<nO?)<^;1_*-KgI=3`l#c z#+|oUapL!(M0+UJ8cH?Ot9b94)Z08wVqp3OxG8iD?i>i+aC;yx0bxqp(8D2j0Qmev zp$jfl+6Lb{gOFzhK)@MWs1dy}cwt_PU;Jn;ZdKwIsmFmmaTYb;5}w!eYEmH7D?0=< zlNGm|*}*C;Xmm~MmY=PN!#O9GB8?^8CWqlR6i#H0!vg{t-nSASZk}ADnZKun_uTP4 z9-VrO_pIXg)}+3+G}MxYR-}=~c;tWLGX?bCIX?d-221cAq5+ZIPE2sk9bP$F;;n5` zcyZ$>4R%QJC1Fu0g*^+Md66$gIx9~CZPb%Ha~F0(iKgRAV`p2QwUJ>X%(C9Qf z;PxWj5; zqJiO@W?CFnURx92!jF5aa{vFN)+E#;OoRu=7%R~}<`SlP4_uRi2- zHYlB}2eS_#5_Oq2HI@%fW>9=+U<~*VM3%orjHxd1-z`_vnyyWeDL6#Cuz3z1n*zsi ze~XAqJVlWWl-NM=XY}v=4RmA!z4eC>-M|N*;pr{E!0q1(^>ERxK_(4w`!`bvhi)`} S754sy#V<|*viLRj#(x1k4@=kp literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aabd11ffd255d70cdff6502fbb81633b8cd04fb9 GIT binary patch literal 6467 zcmahtTWk|qmbc2U@+)={hd6NpCLs-`!AV1aZn`@>l8`_{h`>w_CcP!&st|{=ow-#e zBywiZs-;Or(@R+O2>625?r0d%AM9!$Xnz)s_HU(COfrh6W?Ic^wm_{DhR6(PRou_fRIS4W`mla*Wp_ z^MS%bHNB-bLDw`P1rmg{p16t-DL(6%SQ+d!)q^a^2ZP4rFh~~4# zTX6HF=q{3Jr`1!di+s`kC2wgn$f>Sjj>K$ZaMZSu;RGm;H;p?X%3A80s(aMx@y7(+ zp%y^FbU_p|xr`=?)D7}=2V>CPQ?zSi_2GC8eq~g18-6M3KOrqA(@?`mEkmM>?5GYk4}SyG4Ub6jdB7TK#T)Cl4N- zn9bAc>P#vvPvoXGb$=?I&KGhTnB@L+p2`zwL~>4=h~JQNHzv+zu1=^KP2LX-*HhPI zbz&wn(<=f_%F|x9I&%iSDZ`TEGjp^PhMn&i{JtW^tqns8bpncSZ;@Bqh`V9QRT9GY zcC83K54)ZVJ>^}ohvz=O{P~q9g+=?%J>|A8s2a*U4?N#F@MLPyz9wvc(YgP5=kdSW zu_Cnpu6CD5Ao}PJS<0GC$`)7fdAfKcKEX@yLP%Z9d4pb9WwCDoW@qsdu zX^W<=UJ#1hG+)TE#}f};cInmF4mmDbV3$>$qS~sA54t{L$MX@V1UlYrWq}G zik^$4n`qTNoo30vYlG7ZQOWjK0doRyU9 zE9VQE?z{ocXL3%rr)8??t{IxYnUPgvo^CcZbTN9MI!kjVcAOL44Z>A)jn?i%eT(ja z4%!dJe0XpZL&b?5K*qm?0*tiML0aB=9y<0Yv>rQFiXB^Ym%UB52bKozT`qaws_-`d z?sC^#zv}&>cfIR)sq6T&*43`l%Yi>RNpMHGHL~8ix751#(UB+TSH=@7t$SBnFRcVG zRh+~hx_y4>{JO8J1a9GZ~M(b z4$5>jWB|763;qQ>!Y{a=dcYgl|4(n=DB6}e^~4rF!Eu8ubM(OGc1RfmEj$bV*z{xz&Z4u(7dXmG{DKWefS|qclWbqwtyzF~ z%gtbAiwOy;k)#o6p*kSMxRCMLV}xL+i#F86L@614nWTTAM`!<6+?3@M#!i z*f))_b;GyCxZ5_6K@&Zp<&mxNi@aF%-!OXg`&@KC^rKyG_waD~7i?3G086=CsbiCGML39i>z0YdZ z>RbF7^5>9%ZK`_*YjhU0xfDwqARdxw^g|oI=_4CDpjmWVT%dEdq9CFZWnU4KSJ(V6 zJ(iCHU{9Ml z0$UQEJ6II=atZ*C5?L=kK5YZO8tK zjdb+U7%t1s=1$S$=}zPPbo*F7C&xNjIHhPIEYsENt)Lotz&2~O7%}TY zJ_Op7r2D9>$Z&1MH9?>li|I+kxF-uaNZRv?3Q;{pQGaw7+e%rY z!${%K=4NELew<_1hXgcO=0MRd^-v~v1FocyWPlP{Hw>N6U)OB~s^~^)AOgrP7rIk| z`N3uTZQwPN4tfaX2$qU6l(7--1A=~l1RbyuBJ8SUhcBoz{JwC12;g%$jcx$c*&B zg)6|aEM_@xxF$%LjBC^n0ASasO`Xv+(rx%^?nbL#ot7Y&d{gU<)6k3!L66di?eMYmrCqov(AY6n{AmHMIKN$L}e8gK6NjkUKUs~<1( z^Px8$nJiQkP~UBp)fBEcyk0@sIQUP9OMBOKfKPsdY149!ir4tKGOPHr+`lb8Lhn2LfD54nS z3^l}C(l@gvwkn)X%#2nBI)lmbI~nqD^}G{ljPohaRVjx)t00P>r6R9p-cNK0GA%|H)I zV3aTdi11_YfBzZJJHme=P%tZGn;6@UhcsD$Bnu9SqBEiAvABQ*Cak&>Y!5;oMOR{2 z1-?{J7vehMr7CW|RK?A!wHh~HsZ=T;&GvelGzN9d#Nbsq&KkzEUia2S)mJC%&w&2(Hfv@a+-`L;%%6{T2`-iWbBRm(r_x5XoH5=xC0iIs^r~m)} literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ae37350e154df146d188019bb8d7c86321b56e1b GIT binary patch literal 3790 zcmb_f&2JmW6`$eml1qw|WLZv}#Ie_wT8oZFH-MA0MjXUZoP?+?2emJvRjfz5BWtDQ zE;GB7O+o>LLWdZQp}0LrM_&bB^AF^lON<1luxQa1MGw8%paKIq^}QK>%1WC89YJqq z-oAPB-kW*9dHlLi$Ps8)Z(j5sW(fHQPCCs{1KQev!4`2zg}BsB`Lvp(%Rf1 z$;|#jJQqaOUPBw#Y3nn6C0_C>oaQIk6W8Of*Wlf1w#gnhdcZ2xEr)2&Vd#&{-*J zNveD;DcqR*__96o(dC(6muEjrhOgFRw&3%ttX6}~LD+Oz%ww<09p#gvZ3k)V9hh$s zPAU|FnsOmb8+t{{LTIw2|IamDZNsSOZr0U7!f#&di1R zJE2&KYRuvD!Ezi;Gsg+*GSbsdDERyWb5?lZ&X-nsusVOmTbPf$m`}rk6?U6P^EIz_ z&W3MpD9*{lbHX4Np|2*TS|ibJ^SD{)x>SPcVc5Pk1Z183dHCeF!xP__6D@RN*3q$R zx1Zp!$b+mX0NK&SD2@*SNsLwI*LjlRcWa*DQG{A8XkrY%YSExYFvXBYsAiq)rOC)C zWs^7pod5L4R+un zONS$rZ98T-ei-rQNKdqH z+QpP&;v_5XA;x416Jj> zo#br08oG5K$9dcSq|SWxMc{=IFC#gIcKLd$^ftsE@aOH-quG^5gk6a8KIGLYyQHw6i;$;1Za zgp^PBCp^qC)s4PXr@cUzDOI z@Zu!84=9)Da99iu08=H&dVv?)h>!!96b?jwu$yCD>q;Ho1T2g&TOf7EkN)w4&-Bl; zyW_9^;o8Ho&-D9Qb$z=wfE;cvukQsIY=MQ#(C=@{AhEx#0fctmlk4izgW)9*Q`cdC za!GEp&@&l;<}^r0F9Ly^KXQ1paj&uY>Ag?4uRompcI5Oo=4oXvn%HS+7)W#1Ven(- zzCkED((h(_{c`(hZBJ#lM%PjvebhcKcv9tG$2AHWJwaY45xoOPI0u@Mb61-qcc{!k zIKXMpBRx;j^%|y|K%WLtO{Pb``+#a^Q0g@x>*PtA43BNj{eEsYKe}1ISN>D}*yH@M zZRg<|+w|&C%XvQ84@q4A?mtu-(ET8LpABFWfEff%kai#O~<$R`x-5tMH(( z?R+Y33E8a`(C&s-wfSH!rK&8UOZ1*&SE94sPk0_2{xB#i#HA2KC23JX>UOfvCv zAjOQpD=emv6p^5X`{8gO65@diB#5$YB-~4-0NqS#Om*QPp|Y;?TNv3lhi1ji-vYZk2LU+l?iL znw3#dR6unql|v>nSzlT;7Q-X}p$iw(8gxolL?uu-1y$Es*bIF0y(V|j!@xyOes~!U{0R8&BkQ->-!y{0$|JPzt zUSe5W0R;7GD;;AKp)OFW${Mp1vgYvvPZ=X1jhTT}ePvERfc^x7inRG=H(bAwHA^od zaLS9G&-;(K)D@OqJO=`a*$L8*+1>g60odIs56!{yaJHE4tC4<%4o)IDg+!J+s?_Qg zLCw+fwVMO^4=M)JJjvL$8#=Zv@YNJ=BiWbbZy^uKoA4iDF}FdUrgDbaIx1@z-I!FF zi!!stg20jpORU8@6nju&2|U6it9~}Yj~i7cq~iwu(h>NM2}FDWKOTv|M?sZX5?$ox zg9at$+p2hbM_dA7eC?ulfjrSDrB8Dj)xS3ho%knt`LE>sV{-oQ+UQ^Olh4uxT6ju; a>{*BC#248;0^Q!!IGx-se@~#3PW&4NEhF;) literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6567d4f70ea006688201555fb5883f74ac8fcde6 GIT binary patch literal 16227 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d2e58942be57c9436926901bbe6a929dc5ae490c GIT binary patch literal 4350 zcmc&%TWl2989sB_^&D&qS$K1;%J!NIm?bcJF`7A zi&@Jks6v&UrZSc)t&^8nl`4ghhdlMEFOmAxzTo1@&WNZ~=}X?+n5tEt`u}J4f~`fB z`qHs{ZvTJ2^WV<@pZ!xj9wG2uy?);KLmMGqEj_5YmExW6>1T zBJ`3e738$c*JLwL2&RLDmUK%Ylnx1m23Zhz0%o`nNk;@ClGlkIyhrqwhoX<3j+Vt_ z=o_3Q1uv>umhEb;VOvfL=Itr1K=o-_DB4V8(UweB(9lta&e&urNbx#_z z%3f$(Gfgc6bis>Vnx2099qJSTg=YP8{8sWiVK)VX3ZWz|=mgXd(o&c-{`9ae-UFrd zh%P}N(4)ExeNd0-0q9%wxZbL_+zX^bdO{DuO1KWLq^Nap`1TuTCqr()&gfn z6!@kJKvm}bWkq9l$7b6sX+0K);XsZwP2Z37MfaR5UBH7GO7C?}V|*QUCCI?n~t z97icRu)jbH8Oj`A0!`8F61dEVaI!XlpHS7LVuHSiS7bD2+*TaW+u_ncaNx08Hf!i0 zGw4%RoV=#n^I(gHob|)0qHC^(MsZv~MX$B9a5k(nu z6w|hD^20TU>$`Wiqv!?$@7b)3`*p*a8_sBG{}YZ~psrB>tqu1$Kywf<0I&i}c8==9 zH*UCvV$Qj7L$NL8O~WePP7e7ZbJu0iG^VZTzO@ltF>+``z~FFTA;&3!-QeuJaWfAh zPufgzc&wp2e3|*ql2hUao42jwu7cPoCIk+w4skS)6ZMCGpn|E;y&RA&jzl zI)q*UIvnlf?UJeE7R&a9qAX{#f@Wm_rBKwe?g(Gc!d0k$m|b8l>|TUHg}6eEq6@nC znN-UUi$twc76q79^9CV{BFyTDWs;Or3lhtmnuZJz)Tv2bnv@wH)j@&avVUic|7d33W^)dxPiL%I*BOSWg*)#;U=L%c z&+r(q^qG-c)VekErjeO(43`eWhB@sfb!Li2aa0AGZnIHtbG)g{Hb>DV)jTp%gw&_1 zhGn>_x^TFOnjyV03p^xS zw=+!YzB&h!3Rxtxb)O)w|LMZR>gpZQt@{PMB-DI4MUrBQwE}xm^x9PQCWTaAO)aYG zwN&Rxi9snMo@_z#X9r+dvnuPr^=N%3sC=Zk%2g;;J%QT?pt(zS+DU8sR(xP1KJaMp z{Nwm*OX8D6*L}8j=5a!K6jInhV9P$QSzYhn0Hp#20yKxw{%`hqTUCiVDUm5MNL<9= z-!Z}@fm|b&JWp;**T}r^LcCyYPouvhEDFu>%0dkftUC!Ij|S#u^IFGh=AB^7W?s-Q z4M~w3n7ssy4$7`5zGYh>Rva}~RDHgMf#$}2p63i=-~$2dE6U*m+Z~50XIIZw&aIwX zKl7;L_@mhIfB!x4(ziqiANVrXwj)9R-A*t7oP9?=KKtR>t-ezmeW#Wtw>x^4uGU$% zfi*#e-$6-#eyEpx6n;het?-KU>7g-^d?AL%TBR@I0Ce z?_Yo)-^+!whJ0=vXBNX?-v?>6dNJ!)6;f)m%M6#cdJ*tp2Z^?h^a82yn(q5*QVE17 zXNJb+cMKCWBtxiN$uLXcD(d9PE;UU|s&vka_%-g9LFYZWP|%8A5VM|Td(pA+@rkJ^ z^__{ai(Y^SYBip{AQZ!r>Fx>XpdZT%y-h=zZ=Zz2onJz8muyE9D;M6su$|~wSy*0J zd2jhWNDb>_e@?vowCC_@a3@9%9IQlEBbCHzVqI82z1jBilb*pRo!ynotC!dGk7qxe z-Rd9R=pTLDfBN&&zn|VZe|6*h)y>Y-t|a!h-w*BtN&LXdTgz{)O>V{pcUno`5lFlV z2=#D$C9)jZ3UzOUy8jaD<#tN#Ny6wk9@W2t!Hc4Lw(4JCsecV$-Vql?)(0M}C#5LJw+Y}sbrAnCr`#Vt?&21JcGLD4K%N} z&nFv}1l$MJ@*rsi*OT#mx2HU?A>di)Zsu-0QUj_p0S!32tG8mT8Wn5RTAzB{m0Xg) zj3#^!y|MhpR_yRb?C{$3W^4eWVk_Fe5$)fMDv+2~t}I{q;Of&v$5PZU8P8{tx|jY4 zXZ+7zf_%X{ zx1dSjNyJMG!+NpM-^@D=C=+-61e&^!wz^Jkbe;U<`;WUum*nke>;0qe|8PxSZ}|xQ z)!Dstaz#ULIDStp*>i%r7|cq6#sANcv# z_XJi7h7A@9=R7p`$UnrkKxpS!ATYSy-oGPZfASLVpN8YR0hsT$Mgm87yW0W>caQZ1 z`kuWS4s<^2iUvCQRp5BZ7z&yzfwe$ThVEy_pz%WZ(+ShK|0)l<F2WktDhHo>@V*d)e};%K_%(@sMUMZK ZjBb$8ze#Oh$tV65Gz6jZTY@b|`VY>e_=*4k literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7032fe3b04f9b7c19c3b251e48835bd212ae8560 GIT binary patch literal 6697 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 UY!B`aP4Zp$FMiFzi>>2-00j5}R{#J2 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4ad91d20d9101fb64ce698dbc4293528d6bba7a8 GIT binary patch literal 5264 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0153ecc50ad60612c9b2218bba1af14924cd1abe GIT binary patch literal 1677 zcmaJ>&2QsG6rYJ5$8qX>HFUde+0C|v#Xu7z3Y3Z>mQd|S*$An7!3~OBduYA&N0@PT zY2->lLIR|{x8g4Vl@tF4w^a|uQlv#_g}7Pja@i9zPSPeonJDAmd++z&%)IwzevxGf z&~bNb&HOG2!0${L4z3U2>CY4#0s|P(0yb13WH@0ZY)<8DUgcw%vy!%;3Nhxblr5?v z1c<{|C^u=PZAq14n?P+DH522MHDSxD9AnYS+Br2Bl*(zY$sw2`;#8l;oj^}N<Fg}&E=G-QP2WR~(WpE?&V$Cs=5~Xa9$KOfd)f{njh5M}HmS{UaW&r4;H=e$ zSZlQquC(^UiP}gj;mdRjCHf~@bn1er1m>hfq{TjQV}_X# z5@xp+v-S!XM%3d=oZkb?Ufcg+o?RY-GmJTZVa)R@H^Fwmy6Z=PXBeJlp5lA9YqTx& zKE6&x_KuK4Iz=3W@GlX-g+IXSPr(O0u>2dB@9~RI`IR1D>+v^w{8}V|s|&&OT(I~` z@bas{Tki&MuLf@{M}f(+64f?^*O8@`> literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py new file mode 100644 index 0000000..2c84208 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py @@ -0,0 +1,70 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 +from __future__ import annotations + +import logging +from argparse import ArgumentParser +from typing import TYPE_CHECKING + +from pip._vendor import requests + +from pip._vendor.cachecontrol.adapter import CacheControlAdapter +from pip._vendor.cachecontrol.cache import DictCache +from pip._vendor.cachecontrol.controller import logger + +if TYPE_CHECKING: + from argparse import Namespace + + from pip._vendor.cachecontrol.controller import CacheController + + +def setup_logging() -> None: + logger.setLevel(logging.DEBUG) + handler = logging.StreamHandler() + logger.addHandler(handler) + + +def get_session() -> requests.Session: + adapter = CacheControlAdapter( + DictCache(), cache_etags=True, serializer=None, heuristic=None + ) + sess = requests.Session() + sess.mount("http://", adapter) + sess.mount("https://", adapter) + + sess.cache_controller = adapter.controller # type: ignore[attr-defined] + return sess + + +def get_args() -> Namespace: + parser = ArgumentParser() + parser.add_argument("url", help="The URL to try and cache") + return parser.parse_args() + + +def main() -> None: + args = get_args() + sess = get_session() + + # Make a request to get a response + resp = sess.get(args.url) + + # Turn on logging + setup_logging() + + # try setting the cache + cache_controller: CacheController = ( + sess.cache_controller # type: ignore[attr-defined] + ) + cache_controller.cache_response(resp.request, resp.raw) + + # Now try to get it + if cache_controller.cached_request(resp.request): + print("Cached!") + else: + print("Not cached :(") + + +if __name__ == "__main__": + main() diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py new file mode 100644 index 0000000..fbb4ecc --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py @@ -0,0 +1,161 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 +from __future__ import annotations + +import functools +import types +import zlib +from typing import TYPE_CHECKING, Any, Collection, Mapping + +from pip._vendor.requests.adapters import HTTPAdapter + +from pip._vendor.cachecontrol.cache import DictCache +from pip._vendor.cachecontrol.controller import PERMANENT_REDIRECT_STATUSES, CacheController +from pip._vendor.cachecontrol.filewrapper import CallbackFileWrapper + +if TYPE_CHECKING: + from pip._vendor.requests import PreparedRequest, Response + from pip._vendor.urllib3 import HTTPResponse + + from pip._vendor.cachecontrol.cache import BaseCache + from pip._vendor.cachecontrol.heuristics import BaseHeuristic + from pip._vendor.cachecontrol.serialize import Serializer + + +class CacheControlAdapter(HTTPAdapter): + invalidating_methods = {"PUT", "PATCH", "DELETE"} + + def __init__( + self, + cache: BaseCache | None = None, + cache_etags: bool = True, + controller_class: type[CacheController] | None = None, + serializer: Serializer | None = None, + heuristic: BaseHeuristic | None = None, + cacheable_methods: Collection[str] | None = None, + *args: Any, + **kw: Any, + ) -> None: + super().__init__(*args, **kw) + self.cache = DictCache() if cache is None else cache + self.heuristic = heuristic + self.cacheable_methods = cacheable_methods or ("GET",) + + controller_factory = controller_class or CacheController + self.controller = controller_factory( + self.cache, cache_etags=cache_etags, serializer=serializer + ) + + def send( + self, + request: PreparedRequest, + stream: bool = False, + timeout: None | float | tuple[float, float] | tuple[float, None] = None, + verify: bool | str = True, + cert: (None | bytes | str | tuple[bytes | str, bytes | str]) = None, + proxies: Mapping[str, str] | None = None, + cacheable_methods: Collection[str] | None = None, + ) -> Response: + """ + Send a request. Use the request information to see if it + exists in the cache and cache the response if we need to and can. + """ + cacheable = cacheable_methods or self.cacheable_methods + if request.method in cacheable: + try: + cached_response = self.controller.cached_request(request) + except zlib.error: + cached_response = None + if cached_response: + return self.build_response(request, cached_response, from_cache=True) + + # check for etags and add headers if appropriate + request.headers.update(self.controller.conditional_headers(request)) + + resp = super().send(request, stream, timeout, verify, cert, proxies) + + return resp + + def build_response( + self, + request: PreparedRequest, + response: HTTPResponse, + from_cache: bool = False, + cacheable_methods: Collection[str] | None = None, + ) -> Response: + """ + Build a response by making a request or using the cache. + + This will end up calling send and returning a potentially + cached response + """ + cacheable = cacheable_methods or self.cacheable_methods + if not from_cache and request.method in cacheable: + # Check for any heuristics that might update headers + # before trying to cache. + if self.heuristic: + response = self.heuristic.apply(response) + + # apply any expiration heuristics + if response.status == 304: + # We must have sent an ETag request. This could mean + # that we've been expired already or that we simply + # have an etag. In either case, we want to try and + # update the cache if that is the case. + cached_response = self.controller.update_cached_response( + request, response + ) + + if cached_response is not response: + from_cache = True + + # We are done with the server response, read a + # possible response body (compliant servers will + # not return one, but we cannot be 100% sure) and + # release the connection back to the pool. + response.read(decode_content=False) + response.release_conn() + + response = cached_response + + # We always cache the 301 responses + elif int(response.status) in PERMANENT_REDIRECT_STATUSES: + self.controller.cache_response(request, response) + else: + # Wrap the response file with a wrapper that will cache the + # response when the stream has been consumed. + response._fp = CallbackFileWrapper( # type: ignore[assignment] + response._fp, # type: ignore[arg-type] + functools.partial( + self.controller.cache_response, request, response + ), + ) + if response.chunked: + super_update_chunk_length = response._update_chunk_length + + def _update_chunk_length(self: HTTPResponse) -> None: + super_update_chunk_length() + if self.chunk_left == 0: + self._fp._close() # type: ignore[union-attr] + + response._update_chunk_length = types.MethodType( # type: ignore[method-assign] + _update_chunk_length, response + ) + + resp: Response = super().build_response(request, response) # type: ignore[no-untyped-call] + + # See if we should invalidate the cache. + if request.method in self.invalidating_methods and resp.ok: + assert request.url is not None + cache_url = self.controller.cache_url(request.url) + self.cache.delete(cache_url) + + # Give the request a from_cache attr to let people use it + resp.from_cache = from_cache # type: ignore[attr-defined] + + return resp + + def close(self) -> None: + self.cache.close() + super().close() # type: ignore[no-untyped-call] diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/cache.py b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/cache.py new file mode 100644 index 0000000..3293b00 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/cache.py @@ -0,0 +1,74 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 + +""" +The cache object API for implementing caches. The default is a thread +safe in-memory dictionary. +""" +from __future__ import annotations + +from threading import Lock +from typing import IO, TYPE_CHECKING, MutableMapping + +if TYPE_CHECKING: + from datetime import datetime + + +class BaseCache: + def get(self, key: str) -> bytes | None: + raise NotImplementedError() + + def set( + self, key: str, value: bytes, expires: int | datetime | None = None + ) -> None: + raise NotImplementedError() + + def delete(self, key: str) -> None: + raise NotImplementedError() + + def close(self) -> None: + pass + + +class DictCache(BaseCache): + def __init__(self, init_dict: MutableMapping[str, bytes] | None = None) -> None: + self.lock = Lock() + self.data = init_dict or {} + + def get(self, key: str) -> bytes | None: + return self.data.get(key, None) + + def set( + self, key: str, value: bytes, expires: int | datetime | None = None + ) -> None: + with self.lock: + self.data.update({key: value}) + + def delete(self, key: str) -> None: + with self.lock: + if key in self.data: + self.data.pop(key) + + +class SeparateBodyBaseCache(BaseCache): + """ + In this variant, the body is not stored mixed in with the metadata, but is + passed in (as a bytes-like object) in a separate call to ``set_body()``. + + That is, the expected interaction pattern is:: + + cache.set(key, serialized_metadata) + cache.set_body(key) + + Similarly, the body should be loaded separately via ``get_body()``. + """ + + def set_body(self, key: str, body: bytes) -> None: + raise NotImplementedError() + + def get_body(self, key: str) -> IO[bytes] | None: + """ + Return the body as file-like object. + """ + raise NotImplementedError() diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py new file mode 100644 index 0000000..24ff469 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py @@ -0,0 +1,8 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 + +from pip._vendor.cachecontrol.caches.file_cache import FileCache, SeparateBodyFileCache +from pip._vendor.cachecontrol.caches.redis_cache import RedisCache + +__all__ = ["FileCache", "SeparateBodyFileCache", "RedisCache"] diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c722432a7251683b351405e2f59cf88d035ec283 GIT binary patch literal 438 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6c72ffcaa497353e3ffddcd4e7582229689ce659 GIT binary patch literal 2736 zcmbVO&2JM&6rcUF*I`Wp2}$_g09G+24wb4lP)enyD4>F=N;%YoTASTTSZBTK&aMHw z4$2{iL~0f2CGM$ILTXWZ=&}DpFGOidv;v8$>Y=wFgDUmZ_hxPK0X@)J>CM-hdGGz+ z$Luf3WE+8Y{_?waK_TQ1oU|Iuu?daOfX)+(Sb{@}LQW8HEIMLQ%!x%QC-J%D$VDZm z@UiT~it$`rAXH&7;8h&8n8+mrB9dWZ#iofBr||`eUr%yv6*Zms3nytI++w({7Z`!< zxqey9kqBCUEZ1*YUDpMG>YKXm5w(1&NU!?2Ke-|*>>VP3^upSN8*$mgq_YbIq{i`!7Q1du7R z($za7f0by!glsSwf#xO;!eE}%NC8z8Z7f)LFw5~jf@EpjkIX`BZ4M79-{ zLTQ3ln&_~0SYVw%s$19T3d~)w=I;OkYPNUIRc0%5le3fci%ac&_tidzR%A^XXsg9x zz;*r_Gyt6?fA6d4T@x3YP8Udp1kJ1=a8D3xiD+@KF9MXtTS0A&*7|^FBhCwm!KT(i zXi~081q5VMo7!HJ3uxb_W|1GCql;&2auwuED*s_6g1V{Iga8rct)>)uTI02Tp*d{n z2&go@jHtYdB+zfe*|dmh5(}!fJLaXeW>okz2-|GmcKyI`P0G-rq2zkk89E@8%7MvH z%`nbr$$W6W-GY_|g zibb8k@X@C_Z&3*L!hAyrf*2I+&jFbtPhzB_XGQCnJ3D)J?)>ce`oVg6SxY@k_SEBd zdw)$HdDy*g-ns4E9sK^}cPE#+kIf9Pw0FsEZF zYj=Hou`4xmx^?4)*$efdyPbC~JxC2MrUsW%Czkr&`T5eaHuShDlXKkZ`60Ee9pl0O z@_ao3+WxP&1y0Q7wz0N+DF+)@5tNh|4}QL&B=sTw*ryKfT7@W@!K(LeSGZU2nkPRa9<;=m+G=UI>4v#xE^S&l4DhMQyD(3FOQDGN}k@v3m9l zbxM@!V;<8@hZ+p3vTitz9$ck57AoC#bwh^-%ov5&DWhNVseauKuC_(tqwA(o#&@nS zo0g)emhl)vJYE1VRJe?4$2$1<%3mj~OAkD- z-vi^&@HNIv_8vUwJhOcCpU#5-?Ev0QcECyoSbW5Oiab^|u3=i{uv9g!$mP*WK>aIW zjM1RX+)&Qq&ww0dt>g!c9fi|XjkD=B9k-*nR5=er2}}nPDx8P)A^#4j2f*F>&uAUQ zyI4PvriAG9+N#KXUN1W) IO[bytes]: + # We only want to write to this file, so open it in write only mode + flags = os.O_WRONLY + + # os.O_CREAT | os.O_EXCL will fail if the file already exists, so we only + # will open *new* files. + # We specify this because we want to ensure that the mode we pass is the + # mode of the file. + flags |= os.O_CREAT | os.O_EXCL + + # Do not follow symlinks to prevent someone from making a symlink that + # we follow and insecurely open a cache file. + if hasattr(os, "O_NOFOLLOW"): + flags |= os.O_NOFOLLOW + + # On Windows we'll mark this file as binary + if hasattr(os, "O_BINARY"): + flags |= os.O_BINARY + + # Before we open our file, we want to delete any existing file that is + # there + try: + os.remove(filename) + except OSError: + # The file must not exist already, so we can just skip ahead to opening + pass + + # Open our file, the use of os.O_CREAT | os.O_EXCL will ensure that if a + # race condition happens between the os.remove and this line, that an + # error will be raised. Because we utilize a lockfile this should only + # happen if someone is attempting to attack us. + fd = os.open(filename, flags, fmode) + try: + return os.fdopen(fd, "wb") + + except: + # An error occurred wrapping our FD in a file object + os.close(fd) + raise + + +class _FileCacheMixin: + """Shared implementation for both FileCache variants.""" + + def __init__( + self, + directory: str | Path, + forever: bool = False, + filemode: int = 0o0600, + dirmode: int = 0o0700, + lock_class: type[BaseFileLock] | None = None, + ) -> None: + try: + if lock_class is None: + from filelock import FileLock + + lock_class = FileLock + except ImportError: + notice = dedent( + """ + NOTE: In order to use the FileCache you must have + filelock installed. You can install it via pip: + pip install cachecontrol[filecache] + """ + ) + raise ImportError(notice) + + self.directory = directory + self.forever = forever + self.filemode = filemode + self.dirmode = dirmode + self.lock_class = lock_class + + @staticmethod + def encode(x: str) -> str: + return hashlib.sha224(x.encode()).hexdigest() + + def _fn(self, name: str) -> str: + # NOTE: This method should not change as some may depend on it. + # See: https://github.com/ionrock/cachecontrol/issues/63 + hashed = self.encode(name) + parts = list(hashed[:5]) + [hashed] + return os.path.join(self.directory, *parts) + + def get(self, key: str) -> bytes | None: + name = self._fn(key) + try: + with open(name, "rb") as fh: + return fh.read() + + except FileNotFoundError: + return None + + def set( + self, key: str, value: bytes, expires: int | datetime | None = None + ) -> None: + name = self._fn(key) + self._write(name, value) + + def _write(self, path: str, data: bytes) -> None: + """ + Safely write the data to the given path. + """ + # Make sure the directory exists + try: + os.makedirs(os.path.dirname(path), self.dirmode) + except OSError: + pass + + with self.lock_class(path + ".lock"): + # Write our actual file + with _secure_open_write(path, self.filemode) as fh: + fh.write(data) + + def _delete(self, key: str, suffix: str) -> None: + name = self._fn(key) + suffix + if not self.forever: + try: + os.remove(name) + except FileNotFoundError: + pass + + +class FileCache(_FileCacheMixin, BaseCache): + """ + Traditional FileCache: body is stored in memory, so not suitable for large + downloads. + """ + + def delete(self, key: str) -> None: + self._delete(key, "") + + +class SeparateBodyFileCache(_FileCacheMixin, SeparateBodyBaseCache): + """ + Memory-efficient FileCache: body is stored in a separate file, reducing + peak memory usage. + """ + + def get_body(self, key: str) -> IO[bytes] | None: + name = self._fn(key) + ".body" + try: + return open(name, "rb") + except FileNotFoundError: + return None + + def set_body(self, key: str, body: bytes) -> None: + name = self._fn(key) + ".body" + self._write(name, body) + + def delete(self, key: str) -> None: + self._delete(key, "") + self._delete(key, ".body") + + +def url_to_file_path(url: str, filecache: FileCache) -> str: + """Return the file cache path based on the URL. + + This does not ensure the file exists! + """ + key = CacheController.cache_url(url) + return filecache._fn(key) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py new file mode 100644 index 0000000..f4f68c4 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py @@ -0,0 +1,48 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 +from __future__ import annotations + + +from datetime import datetime, timezone +from typing import TYPE_CHECKING + +from pip._vendor.cachecontrol.cache import BaseCache + +if TYPE_CHECKING: + from redis import Redis + + +class RedisCache(BaseCache): + def __init__(self, conn: Redis[bytes]) -> None: + self.conn = conn + + def get(self, key: str) -> bytes | None: + return self.conn.get(key) + + def set( + self, key: str, value: bytes, expires: int | datetime | None = None + ) -> None: + if not expires: + self.conn.set(key, value) + elif isinstance(expires, datetime): + now_utc = datetime.now(timezone.utc) + if expires.tzinfo is None: + now_utc = now_utc.replace(tzinfo=None) + delta = expires - now_utc + self.conn.setex(key, int(delta.total_seconds()), value) + else: + self.conn.setex(key, expires, value) + + def delete(self, key: str) -> None: + self.conn.delete(key) + + def clear(self) -> None: + """Helper for clearing all the keys in a database. Use with + caution!""" + for key in self.conn.keys(): + self.conn.delete(key) + + def close(self) -> None: + """Redis uses connection pooling, no need to close the connection.""" + pass diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/controller.py b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/controller.py new file mode 100644 index 0000000..d7dd86e --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/controller.py @@ -0,0 +1,499 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 + +""" +The httplib2 algorithms ported for use with requests. +""" +from __future__ import annotations + +import calendar +import logging +import re +import time +from email.utils import parsedate_tz +from typing import TYPE_CHECKING, Collection, Mapping + +from pip._vendor.requests.structures import CaseInsensitiveDict + +from pip._vendor.cachecontrol.cache import DictCache, SeparateBodyBaseCache +from pip._vendor.cachecontrol.serialize import Serializer + +if TYPE_CHECKING: + from typing import Literal + + from pip._vendor.requests import PreparedRequest + from pip._vendor.urllib3 import HTTPResponse + + from pip._vendor.cachecontrol.cache import BaseCache + +logger = logging.getLogger(__name__) + +URI = re.compile(r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?") + +PERMANENT_REDIRECT_STATUSES = (301, 308) + + +def parse_uri(uri: str) -> tuple[str, str, str, str, str]: + """Parses a URI using the regex given in Appendix B of RFC 3986. + + (scheme, authority, path, query, fragment) = parse_uri(uri) + """ + match = URI.match(uri) + assert match is not None + groups = match.groups() + return (groups[1], groups[3], groups[4], groups[6], groups[8]) + + +class CacheController: + """An interface to see if request should cached or not.""" + + def __init__( + self, + cache: BaseCache | None = None, + cache_etags: bool = True, + serializer: Serializer | None = None, + status_codes: Collection[int] | None = None, + ): + self.cache = DictCache() if cache is None else cache + self.cache_etags = cache_etags + self.serializer = serializer or Serializer() + self.cacheable_status_codes = status_codes or (200, 203, 300, 301, 308) + + @classmethod + def _urlnorm(cls, uri: str) -> str: + """Normalize the URL to create a safe key for the cache""" + (scheme, authority, path, query, fragment) = parse_uri(uri) + if not scheme or not authority: + raise Exception("Only absolute URIs are allowed. uri = %s" % uri) + + scheme = scheme.lower() + authority = authority.lower() + + if not path: + path = "/" + + # Could do syntax based normalization of the URI before + # computing the digest. See Section 6.2.2 of Std 66. + request_uri = query and "?".join([path, query]) or path + defrag_uri = scheme + "://" + authority + request_uri + + return defrag_uri + + @classmethod + def cache_url(cls, uri: str) -> str: + return cls._urlnorm(uri) + + def parse_cache_control(self, headers: Mapping[str, str]) -> dict[str, int | None]: + known_directives = { + # https://tools.ietf.org/html/rfc7234#section-5.2 + "max-age": (int, True), + "max-stale": (int, False), + "min-fresh": (int, True), + "no-cache": (None, False), + "no-store": (None, False), + "no-transform": (None, False), + "only-if-cached": (None, False), + "must-revalidate": (None, False), + "public": (None, False), + "private": (None, False), + "proxy-revalidate": (None, False), + "s-maxage": (int, True), + } + + cc_headers = headers.get("cache-control", headers.get("Cache-Control", "")) + + retval: dict[str, int | None] = {} + + for cc_directive in cc_headers.split(","): + if not cc_directive.strip(): + continue + + parts = cc_directive.split("=", 1) + directive = parts[0].strip() + + try: + typ, required = known_directives[directive] + except KeyError: + logger.debug("Ignoring unknown cache-control directive: %s", directive) + continue + + if not typ or not required: + retval[directive] = None + if typ: + try: + retval[directive] = typ(parts[1].strip()) + except IndexError: + if required: + logger.debug( + "Missing value for cache-control " "directive: %s", + directive, + ) + except ValueError: + logger.debug( + "Invalid value for cache-control directive " "%s, must be %s", + directive, + typ.__name__, + ) + + return retval + + def _load_from_cache(self, request: PreparedRequest) -> HTTPResponse | None: + """ + Load a cached response, or return None if it's not available. + """ + # We do not support caching of partial content: so if the request contains a + # Range header then we don't want to load anything from the cache. + if "Range" in request.headers: + return None + + cache_url = request.url + assert cache_url is not None + cache_data = self.cache.get(cache_url) + if cache_data is None: + logger.debug("No cache entry available") + return None + + if isinstance(self.cache, SeparateBodyBaseCache): + body_file = self.cache.get_body(cache_url) + else: + body_file = None + + result = self.serializer.loads(request, cache_data, body_file) + if result is None: + logger.warning("Cache entry deserialization failed, entry ignored") + return result + + def cached_request(self, request: PreparedRequest) -> HTTPResponse | Literal[False]: + """ + Return a cached response if it exists in the cache, otherwise + return False. + """ + assert request.url is not None + cache_url = self.cache_url(request.url) + logger.debug('Looking up "%s" in the cache', cache_url) + cc = self.parse_cache_control(request.headers) + + # Bail out if the request insists on fresh data + if "no-cache" in cc: + logger.debug('Request header has "no-cache", cache bypassed') + return False + + if "max-age" in cc and cc["max-age"] == 0: + logger.debug('Request header has "max_age" as 0, cache bypassed') + return False + + # Check whether we can load the response from the cache: + resp = self._load_from_cache(request) + if not resp: + return False + + # If we have a cached permanent redirect, return it immediately. We + # don't need to test our response for other headers b/c it is + # intrinsically "cacheable" as it is Permanent. + # + # See: + # https://tools.ietf.org/html/rfc7231#section-6.4.2 + # + # Client can try to refresh the value by repeating the request + # with cache busting headers as usual (ie no-cache). + if int(resp.status) in PERMANENT_REDIRECT_STATUSES: + msg = ( + "Returning cached permanent redirect response " + "(ignoring date and etag information)" + ) + logger.debug(msg) + return resp + + headers: CaseInsensitiveDict[str] = CaseInsensitiveDict(resp.headers) + if not headers or "date" not in headers: + if "etag" not in headers: + # Without date or etag, the cached response can never be used + # and should be deleted. + logger.debug("Purging cached response: no date or etag") + self.cache.delete(cache_url) + logger.debug("Ignoring cached response: no date") + return False + + now = time.time() + time_tuple = parsedate_tz(headers["date"]) + assert time_tuple is not None + date = calendar.timegm(time_tuple[:6]) + current_age = max(0, now - date) + logger.debug("Current age based on date: %i", current_age) + + # TODO: There is an assumption that the result will be a + # urllib3 response object. This may not be best since we + # could probably avoid instantiating or constructing the + # response until we know we need it. + resp_cc = self.parse_cache_control(headers) + + # determine freshness + freshness_lifetime = 0 + + # Check the max-age pragma in the cache control header + max_age = resp_cc.get("max-age") + if max_age is not None: + freshness_lifetime = max_age + logger.debug("Freshness lifetime from max-age: %i", freshness_lifetime) + + # If there isn't a max-age, check for an expires header + elif "expires" in headers: + expires = parsedate_tz(headers["expires"]) + if expires is not None: + expire_time = calendar.timegm(expires[:6]) - date + freshness_lifetime = max(0, expire_time) + logger.debug("Freshness lifetime from expires: %i", freshness_lifetime) + + # Determine if we are setting freshness limit in the + # request. Note, this overrides what was in the response. + max_age = cc.get("max-age") + if max_age is not None: + freshness_lifetime = max_age + logger.debug( + "Freshness lifetime from request max-age: %i", freshness_lifetime + ) + + min_fresh = cc.get("min-fresh") + if min_fresh is not None: + # adjust our current age by our min fresh + current_age += min_fresh + logger.debug("Adjusted current age from min-fresh: %i", current_age) + + # Return entry if it is fresh enough + if freshness_lifetime > current_age: + logger.debug('The response is "fresh", returning cached response') + logger.debug("%i > %i", freshness_lifetime, current_age) + return resp + + # we're not fresh. If we don't have an Etag, clear it out + if "etag" not in headers: + logger.debug('The cached response is "stale" with no etag, purging') + self.cache.delete(cache_url) + + # return the original handler + return False + + def conditional_headers(self, request: PreparedRequest) -> dict[str, str]: + resp = self._load_from_cache(request) + new_headers = {} + + if resp: + headers: CaseInsensitiveDict[str] = CaseInsensitiveDict(resp.headers) + + if "etag" in headers: + new_headers["If-None-Match"] = headers["ETag"] + + if "last-modified" in headers: + new_headers["If-Modified-Since"] = headers["Last-Modified"] + + return new_headers + + def _cache_set( + self, + cache_url: str, + request: PreparedRequest, + response: HTTPResponse, + body: bytes | None = None, + expires_time: int | None = None, + ) -> None: + """ + Store the data in the cache. + """ + if isinstance(self.cache, SeparateBodyBaseCache): + # We pass in the body separately; just put a placeholder empty + # string in the metadata. + self.cache.set( + cache_url, + self.serializer.dumps(request, response, b""), + expires=expires_time, + ) + # body is None can happen when, for example, we're only updating + # headers, as is the case in update_cached_response(). + if body is not None: + self.cache.set_body(cache_url, body) + else: + self.cache.set( + cache_url, + self.serializer.dumps(request, response, body), + expires=expires_time, + ) + + def cache_response( + self, + request: PreparedRequest, + response: HTTPResponse, + body: bytes | None = None, + status_codes: Collection[int] | None = None, + ) -> None: + """ + Algorithm for caching requests. + + This assumes a requests Response object. + """ + # From httplib2: Don't cache 206's since we aren't going to + # handle byte range requests + cacheable_status_codes = status_codes or self.cacheable_status_codes + if response.status not in cacheable_status_codes: + logger.debug( + "Status code %s not in %s", response.status, cacheable_status_codes + ) + return + + response_headers: CaseInsensitiveDict[str] = CaseInsensitiveDict( + response.headers + ) + + if "date" in response_headers: + time_tuple = parsedate_tz(response_headers["date"]) + assert time_tuple is not None + date = calendar.timegm(time_tuple[:6]) + else: + date = 0 + + # If we've been given a body, our response has a Content-Length, that + # Content-Length is valid then we can check to see if the body we've + # been given matches the expected size, and if it doesn't we'll just + # skip trying to cache it. + if ( + body is not None + and "content-length" in response_headers + and response_headers["content-length"].isdigit() + and int(response_headers["content-length"]) != len(body) + ): + return + + cc_req = self.parse_cache_control(request.headers) + cc = self.parse_cache_control(response_headers) + + assert request.url is not None + cache_url = self.cache_url(request.url) + logger.debug('Updating cache with response from "%s"', cache_url) + + # Delete it from the cache if we happen to have it stored there + no_store = False + if "no-store" in cc: + no_store = True + logger.debug('Response header has "no-store"') + if "no-store" in cc_req: + no_store = True + logger.debug('Request header has "no-store"') + if no_store and self.cache.get(cache_url): + logger.debug('Purging existing cache entry to honor "no-store"') + self.cache.delete(cache_url) + if no_store: + return + + # https://tools.ietf.org/html/rfc7234#section-4.1: + # A Vary header field-value of "*" always fails to match. + # Storing such a response leads to a deserialization warning + # during cache lookup and is not allowed to ever be served, + # so storing it can be avoided. + if "*" in response_headers.get("vary", ""): + logger.debug('Response header has "Vary: *"') + return + + # If we've been given an etag, then keep the response + if self.cache_etags and "etag" in response_headers: + expires_time = 0 + if response_headers.get("expires"): + expires = parsedate_tz(response_headers["expires"]) + if expires is not None: + expires_time = calendar.timegm(expires[:6]) - date + + expires_time = max(expires_time, 14 * 86400) + + logger.debug(f"etag object cached for {expires_time} seconds") + logger.debug("Caching due to etag") + self._cache_set(cache_url, request, response, body, expires_time) + + # Add to the cache any permanent redirects. We do this before looking + # that the Date headers. + elif int(response.status) in PERMANENT_REDIRECT_STATUSES: + logger.debug("Caching permanent redirect") + self._cache_set(cache_url, request, response, b"") + + # Add to the cache if the response headers demand it. If there + # is no date header then we can't do anything about expiring + # the cache. + elif "date" in response_headers: + time_tuple = parsedate_tz(response_headers["date"]) + assert time_tuple is not None + date = calendar.timegm(time_tuple[:6]) + # cache when there is a max-age > 0 + max_age = cc.get("max-age") + if max_age is not None and max_age > 0: + logger.debug("Caching b/c date exists and max-age > 0") + expires_time = max_age + self._cache_set( + cache_url, + request, + response, + body, + expires_time, + ) + + # If the request can expire, it means we should cache it + # in the meantime. + elif "expires" in response_headers: + if response_headers["expires"]: + expires = parsedate_tz(response_headers["expires"]) + if expires is not None: + expires_time = calendar.timegm(expires[:6]) - date + else: + expires_time = None + + logger.debug( + "Caching b/c of expires header. expires in {} seconds".format( + expires_time + ) + ) + self._cache_set( + cache_url, + request, + response, + body, + expires_time, + ) + + def update_cached_response( + self, request: PreparedRequest, response: HTTPResponse + ) -> HTTPResponse: + """On a 304 we will get a new set of headers that we want to + update our cached value with, assuming we have one. + + This should only ever be called when we've sent an ETag and + gotten a 304 as the response. + """ + assert request.url is not None + cache_url = self.cache_url(request.url) + cached_response = self._load_from_cache(request) + + if not cached_response: + # we didn't have a cached response + return response + + # Lets update our headers with the headers from the new request: + # http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-26#section-4.1 + # + # The server isn't supposed to send headers that would make + # the cached body invalid. But... just in case, we'll be sure + # to strip out ones we know that might be problmatic due to + # typical assumptions. + excluded_headers = ["content-length"] + + cached_response.headers.update( + { + k: v + for k, v in response.headers.items() + if k.lower() not in excluded_headers + } + ) + + # we want a 200 b/c we have content via the cache + cached_response.status = 200 + + # update our cache + self._cache_set(cache_url, request, cached_response) + + return cached_response diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py new file mode 100644 index 0000000..2514390 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py @@ -0,0 +1,119 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 +from __future__ import annotations + +import mmap +from tempfile import NamedTemporaryFile +from typing import TYPE_CHECKING, Any, Callable + +if TYPE_CHECKING: + from http.client import HTTPResponse + + +class CallbackFileWrapper: + """ + Small wrapper around a fp object which will tee everything read into a + buffer, and when that file is closed it will execute a callback with the + contents of that buffer. + + All attributes are proxied to the underlying file object. + + This class uses members with a double underscore (__) leading prefix so as + not to accidentally shadow an attribute. + + The data is stored in a temporary file until it is all available. As long + as the temporary files directory is disk-based (sometimes it's a + memory-backed-``tmpfs`` on Linux), data will be unloaded to disk if memory + pressure is high. For small files the disk usually won't be used at all, + it'll all be in the filesystem memory cache, so there should be no + performance impact. + """ + + def __init__( + self, fp: HTTPResponse, callback: Callable[[bytes], None] | None + ) -> None: + self.__buf = NamedTemporaryFile("rb+", delete=True) + self.__fp = fp + self.__callback = callback + + def __getattr__(self, name: str) -> Any: + # The vaguaries of garbage collection means that self.__fp is + # not always set. By using __getattribute__ and the private + # name[0] allows looking up the attribute value and raising an + # AttributeError when it doesn't exist. This stop thigns from + # infinitely recursing calls to getattr in the case where + # self.__fp hasn't been set. + # + # [0] https://docs.python.org/2/reference/expressions.html#atom-identifiers + fp = self.__getattribute__("_CallbackFileWrapper__fp") + return getattr(fp, name) + + def __is_fp_closed(self) -> bool: + try: + return self.__fp.fp is None + + except AttributeError: + pass + + try: + closed: bool = self.__fp.closed + return closed + + except AttributeError: + pass + + # We just don't cache it then. + # TODO: Add some logging here... + return False + + def _close(self) -> None: + if self.__callback: + if self.__buf.tell() == 0: + # Empty file: + result = b"" + else: + # Return the data without actually loading it into memory, + # relying on Python's buffer API and mmap(). mmap() just gives + # a view directly into the filesystem's memory cache, so it + # doesn't result in duplicate memory use. + self.__buf.seek(0, 0) + result = memoryview( + mmap.mmap(self.__buf.fileno(), 0, access=mmap.ACCESS_READ) + ) + self.__callback(result) + + # We assign this to None here, because otherwise we can get into + # really tricky problems where the CPython interpreter dead locks + # because the callback is holding a reference to something which + # has a __del__ method. Setting this to None breaks the cycle + # and allows the garbage collector to do it's thing normally. + self.__callback = None + + # Closing the temporary file releases memory and frees disk space. + # Important when caching big files. + self.__buf.close() + + def read(self, amt: int | None = None) -> bytes: + data: bytes = self.__fp.read(amt) + if data: + # We may be dealing with b'', a sign that things are over: + # it's passed e.g. after we've already closed self.__buf. + self.__buf.write(data) + if self.__is_fp_closed(): + self._close() + + return data + + def _safe_read(self, amt: int) -> bytes: + data: bytes = self.__fp._safe_read(amt) # type: ignore[attr-defined] + if amt == 2 and data == b"\r\n": + # urllib executes this read to toss the CRLF at the end + # of the chunk. + return data + + self.__buf.write(data) + if self.__is_fp_closed(): + self._close() + + return data diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py new file mode 100644 index 0000000..f6e5634 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py @@ -0,0 +1,154 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 +from __future__ import annotations + +import calendar +import time +from datetime import datetime, timedelta, timezone +from email.utils import formatdate, parsedate, parsedate_tz +from typing import TYPE_CHECKING, Any, Mapping + +if TYPE_CHECKING: + from pip._vendor.urllib3 import HTTPResponse + +TIME_FMT = "%a, %d %b %Y %H:%M:%S GMT" + + +def expire_after(delta: timedelta, date: datetime | None = None) -> datetime: + date = date or datetime.now(timezone.utc) + return date + delta + + +def datetime_to_header(dt: datetime) -> str: + return formatdate(calendar.timegm(dt.timetuple())) + + +class BaseHeuristic: + def warning(self, response: HTTPResponse) -> str | None: + """ + Return a valid 1xx warning header value describing the cache + adjustments. + + The response is provided too allow warnings like 113 + http://tools.ietf.org/html/rfc7234#section-5.5.4 where we need + to explicitly say response is over 24 hours old. + """ + return '110 - "Response is Stale"' + + def update_headers(self, response: HTTPResponse) -> dict[str, str]: + """Update the response headers with any new headers. + + NOTE: This SHOULD always include some Warning header to + signify that the response was cached by the client, not + by way of the provided headers. + """ + return {} + + def apply(self, response: HTTPResponse) -> HTTPResponse: + updated_headers = self.update_headers(response) + + if updated_headers: + response.headers.update(updated_headers) + warning_header_value = self.warning(response) + if warning_header_value is not None: + response.headers.update({"Warning": warning_header_value}) + + return response + + +class OneDayCache(BaseHeuristic): + """ + Cache the response by providing an expires 1 day in the + future. + """ + + def update_headers(self, response: HTTPResponse) -> dict[str, str]: + headers = {} + + if "expires" not in response.headers: + date = parsedate(response.headers["date"]) + expires = expire_after(timedelta(days=1), date=datetime(*date[:6], tzinfo=timezone.utc)) # type: ignore[index,misc] + headers["expires"] = datetime_to_header(expires) + headers["cache-control"] = "public" + return headers + + +class ExpiresAfter(BaseHeuristic): + """ + Cache **all** requests for a defined time period. + """ + + def __init__(self, **kw: Any) -> None: + self.delta = timedelta(**kw) + + def update_headers(self, response: HTTPResponse) -> dict[str, str]: + expires = expire_after(self.delta) + return {"expires": datetime_to_header(expires), "cache-control": "public"} + + def warning(self, response: HTTPResponse) -> str | None: + tmpl = "110 - Automatically cached for %s. Response might be stale" + return tmpl % self.delta + + +class LastModified(BaseHeuristic): + """ + If there is no Expires header already, fall back on Last-Modified + using the heuristic from + http://tools.ietf.org/html/rfc7234#section-4.2.2 + to calculate a reasonable value. + + Firefox also does something like this per + https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching_FAQ + http://lxr.mozilla.org/mozilla-release/source/netwerk/protocol/http/nsHttpResponseHead.cpp#397 + Unlike mozilla we limit this to 24-hr. + """ + + cacheable_by_default_statuses = { + 200, + 203, + 204, + 206, + 300, + 301, + 404, + 405, + 410, + 414, + 501, + } + + def update_headers(self, resp: HTTPResponse) -> dict[str, str]: + headers: Mapping[str, str] = resp.headers + + if "expires" in headers: + return {} + + if "cache-control" in headers and headers["cache-control"] != "public": + return {} + + if resp.status not in self.cacheable_by_default_statuses: + return {} + + if "date" not in headers or "last-modified" not in headers: + return {} + + time_tuple = parsedate_tz(headers["date"]) + assert time_tuple is not None + date = calendar.timegm(time_tuple[:6]) + last_modified = parsedate(headers["last-modified"]) + if last_modified is None: + return {} + + now = time.time() + current_age = max(0, now - date) + delta = date - calendar.timegm(last_modified) + freshness_lifetime = max(0, min(delta / 10, 24 * 3600)) + if freshness_lifetime <= current_age: + return {} + + expires = date + freshness_lifetime + return {"expires": time.strftime(TIME_FMT, time.gmtime(expires))} + + def warning(self, resp: HTTPResponse) -> str | None: + return None diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/py.typed b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py new file mode 100644 index 0000000..a49487a --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py @@ -0,0 +1,146 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 +from __future__ import annotations + +import io +from typing import IO, TYPE_CHECKING, Any, Mapping, cast + +from pip._vendor import msgpack +from pip._vendor.requests.structures import CaseInsensitiveDict +from pip._vendor.urllib3 import HTTPResponse + +if TYPE_CHECKING: + from pip._vendor.requests import PreparedRequest + + +class Serializer: + serde_version = "4" + + def dumps( + self, + request: PreparedRequest, + response: HTTPResponse, + body: bytes | None = None, + ) -> bytes: + response_headers: CaseInsensitiveDict[str] = CaseInsensitiveDict( + response.headers + ) + + if body is None: + # When a body isn't passed in, we'll read the response. We + # also update the response with a new file handler to be + # sure it acts as though it was never read. + body = response.read(decode_content=False) + response._fp = io.BytesIO(body) # type: ignore[assignment] + response.length_remaining = len(body) + + data = { + "response": { + "body": body, # Empty bytestring if body is stored separately + "headers": {str(k): str(v) for k, v in response.headers.items()}, + "status": response.status, + "version": response.version, + "reason": str(response.reason), + "decode_content": response.decode_content, + } + } + + # Construct our vary headers + data["vary"] = {} + if "vary" in response_headers: + varied_headers = response_headers["vary"].split(",") + for header in varied_headers: + header = str(header).strip() + header_value = request.headers.get(header, None) + if header_value is not None: + header_value = str(header_value) + data["vary"][header] = header_value + + return b",".join([f"cc={self.serde_version}".encode(), self.serialize(data)]) + + def serialize(self, data: dict[str, Any]) -> bytes: + return cast(bytes, msgpack.dumps(data, use_bin_type=True)) + + def loads( + self, + request: PreparedRequest, + data: bytes, + body_file: IO[bytes] | None = None, + ) -> HTTPResponse | None: + # Short circuit if we've been given an empty set of data + if not data: + return None + + # Previous versions of this library supported other serialization + # formats, but these have all been removed. + if not data.startswith(f"cc={self.serde_version},".encode()): + return None + + data = data[5:] + return self._loads_v4(request, data, body_file) + + def prepare_response( + self, + request: PreparedRequest, + cached: Mapping[str, Any], + body_file: IO[bytes] | None = None, + ) -> HTTPResponse | None: + """Verify our vary headers match and construct a real urllib3 + HTTPResponse object. + """ + # Special case the '*' Vary value as it means we cannot actually + # determine if the cached response is suitable for this request. + # This case is also handled in the controller code when creating + # a cache entry, but is left here for backwards compatibility. + if "*" in cached.get("vary", {}): + return None + + # Ensure that the Vary headers for the cached response match our + # request + for header, value in cached.get("vary", {}).items(): + if request.headers.get(header, None) != value: + return None + + body_raw = cached["response"].pop("body") + + headers: CaseInsensitiveDict[str] = CaseInsensitiveDict( + data=cached["response"]["headers"] + ) + if headers.get("transfer-encoding", "") == "chunked": + headers.pop("transfer-encoding") + + cached["response"]["headers"] = headers + + try: + body: IO[bytes] + if body_file is None: + body = io.BytesIO(body_raw) + else: + body = body_file + except TypeError: + # This can happen if cachecontrol serialized to v1 format (pickle) + # using Python 2. A Python 2 str(byte string) will be unpickled as + # a Python 3 str (unicode string), which will cause the above to + # fail with: + # + # TypeError: 'str' does not support the buffer interface + body = io.BytesIO(body_raw.encode("utf8")) + + # Discard any `strict` parameter serialized by older version of cachecontrol. + cached["response"].pop("strict", None) + + return HTTPResponse(body=body, preload_content=False, **cached["response"]) + + def _loads_v4( + self, + request: PreparedRequest, + data: bytes, + body_file: IO[bytes] | None = None, + ) -> HTTPResponse | None: + try: + cached = msgpack.loads(data, raw=False) + except ValueError: + return None + + return self.prepare_response(request, cached, body_file) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py new file mode 100644 index 0000000..f618bc3 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py @@ -0,0 +1,43 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 +from __future__ import annotations + +from typing import TYPE_CHECKING, Collection + +from pip._vendor.cachecontrol.adapter import CacheControlAdapter +from pip._vendor.cachecontrol.cache import DictCache + +if TYPE_CHECKING: + from pip._vendor import requests + + from pip._vendor.cachecontrol.cache import BaseCache + from pip._vendor.cachecontrol.controller import CacheController + from pip._vendor.cachecontrol.heuristics import BaseHeuristic + from pip._vendor.cachecontrol.serialize import Serializer + + +def CacheControl( + sess: requests.Session, + cache: BaseCache | None = None, + cache_etags: bool = True, + serializer: Serializer | None = None, + heuristic: BaseHeuristic | None = None, + controller_class: type[CacheController] | None = None, + adapter_class: type[CacheControlAdapter] | None = None, + cacheable_methods: Collection[str] | None = None, +) -> requests.Session: + cache = DictCache() if cache is None else cache + adapter_class = adapter_class or CacheControlAdapter + adapter = adapter_class( + cache, + cache_etags=cache_etags, + serializer=serializer, + heuristic=heuristic, + controller_class=controller_class, + cacheable_methods=cacheable_methods, + ) + sess.mount("http://", adapter) + sess.mount("https://", adapter) + + return sess diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/certifi/__init__.py b/backend/.venv/Lib/site-packages/pip/_vendor/certifi/__init__.py new file mode 100644 index 0000000..f61d77f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/certifi/__init__.py @@ -0,0 +1,4 @@ +from .core import contents, where + +__all__ = ["contents", "where"] +__version__ = "2024.08.30" diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/certifi/__main__.py b/backend/.venv/Lib/site-packages/pip/_vendor/certifi/__main__.py new file mode 100644 index 0000000..0037634 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/certifi/__main__.py @@ -0,0 +1,12 @@ +import argparse + +from pip._vendor.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/pip/_vendor/certifi/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bcbfda50f79a971e253a988089508c815ff2f2e0 GIT binary patch literal 321 zcmYjMJx{|h5Vi9`OQNzNBo<)IkfbUM2muQ#@B@N{mD;A5Bz9!GiOK~3fQ{e4Z((6X zSwLc9L+ZwaBZ0&l?%v(Id#8IIjRIhCc5%cnZT{$sKRCZ+xoycKpn$>>R4{{;lQ|Gj zhq^N-bE%hk3qM-M3-7m9qwG^%->T4O<_N(objU-1-UF1W!ssTbYwu#$9MvSSt6i~T!#!-g*x ZLih%D-oy2W_9fW58@#S<-iK<{YClk+SfT&` literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..24bbbacf4e7281e053fbce4126902d7323defb24 GIT binary patch literal 648 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 ST3S-_cyutG=-?SVr~e17rGtq8 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/certifi/cacert.pem b/backend/.venv/Lib/site-packages/pip/_vendor/certifi/cacert.pem new file mode 100644 index 0000000..3c165a1 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/certifi/cacert.pem @@ -0,0 +1,4929 @@ + +# Issuer: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA +# Subject: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA +# Label: "GlobalSign Root CA" +# Serial: 4835703278459707669005204 +# MD5 Fingerprint: 3e:45:52:15:09:51:92:e1:b7:5d:37:9f:b1:87:29:8a +# SHA1 Fingerprint: b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c +# SHA256 Fingerprint: eb:d4:10:40:e4:bb:3e:c7:42:c9:e3:81:d3:1e:f2:a4:1a:48:b6:68:5c:96:e7:ce:f3:c1:df:6c:d4:33:1c:99 +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw +MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT +aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ +jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp +xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp +1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG +snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ +U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 +9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B +AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz +yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE +38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP +AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad +DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME +HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- + +# Issuer: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited +# Subject: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited +# Label: "Entrust.net Premium 2048 Secure Server CA" +# Serial: 946069240 +# MD5 Fingerprint: ee:29:31:bc:32:7e:9a:e6:e8:b5:f7:51:b4:34:71:90 +# SHA1 Fingerprint: 50:30:06:09:1d:97:d4:f5:ae:39:f7:cb:e7:92:7d:7d:65:2d:34:31 +# SHA256 Fingerprint: 6d:c4:71:72:e0:1c:bc:b0:bf:62:58:0d:89:5f:e2:b8:ac:9a:d4:f8:73:80:1e:0c:10:b9:c8:37:d2:1e:b1:77 +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML +RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 +IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3 +MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 +LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp +YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG +A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq +K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe +sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX +MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT +XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ +HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH +4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub +j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo +U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf +zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b +u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+ +bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er +fF6adulZkMV8gzURZVE= +-----END CERTIFICATE----- + +# Issuer: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust +# Subject: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust +# Label: "Baltimore CyberTrust Root" +# Serial: 33554617 +# MD5 Fingerprint: ac:b6:94:a5:9c:17:e0:d7:91:52:9b:b1:97:06:a6:e4 +# SHA1 Fingerprint: d4:de:20:d0:5e:66:fc:53:fe:1a:50:88:2c:78:db:28:52:ca:e4:74 +# SHA256 Fingerprint: 16:af:57:a9:f6:76:b0:ab:12:60:95:aa:5e:ba:de:f2:2a:b3:11:19:d6:44:ac:95:cd:4b:93:db:f3:f2:6a:eb +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ +RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD +VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX +DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y +ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy +VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr +mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr +IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK +mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu +XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy +dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye +jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 +BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 +DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 +9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx +jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 +Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz +ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS +R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- + +# 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=AAA Certificate Services O=Comodo CA Limited +# Subject: CN=AAA Certificate Services O=Comodo CA Limited +# Label: "Comodo AAA Services root" +# Serial: 1 +# MD5 Fingerprint: 49:79:04:b0:eb:87:19:ac:47:b0:bc:11:51:9b:74:d0 +# SHA1 Fingerprint: d1:eb:23:a4:6d:17:d6:8f:d9:25:64:c2:f1:f1:60:17:64:d8:e3:49 +# SHA256 Fingerprint: d7:a7:a0:fb:5d:7e:27:31:d7:71:e9:48:4e:bc:de:f7:1d:5f:0c:3e:0a:29:48:78:2b:c8:3e:e0:ea:69:9e:f4 +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj +YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM +GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua +BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe +3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 +YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR +rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm +ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU +oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v +QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t +b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF +AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q +GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 +G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi +l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 +smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----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=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com +# Subject: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com +# Label: "XRamp Global CA Root" +# Serial: 107108908803651509692980124233745014957 +# MD5 Fingerprint: a1:0b:44:b3:ca:10:d8:00:6e:9d:0f:d8:0f:92:0a:d1 +# SHA1 Fingerprint: b8:01:86:d1:eb:9c:86:a5:41:04:cf:30:54:f3:4c:52:b7:e5:58:c6 +# SHA256 Fingerprint: ce:cd:dc:90:50:99:d8:da:df:c5:b1:d2:09:b7:37:cb:e2:c1:8c:fb:2c:10:c0:ff:0b:cf:0d:32:86:fc:1a:a2 +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB +gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk +MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY +UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx +NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 +dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy +dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 +38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP +KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q +DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 +qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa +JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi +PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P +BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs +jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 +eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD +ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR +vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa +IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy +i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ +O+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE----- + +# Issuer: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority +# Subject: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority +# Label: "Go Daddy Class 2 CA" +# Serial: 0 +# MD5 Fingerprint: 91:de:06:25:ab:da:fd:32:17:0c:bb:25:17:2a:84:67 +# SHA1 Fingerprint: 27:96:ba:e6:3f:18:01:e2:77:26:1b:a0:d7:77:70:02:8f:20:ee:e4 +# SHA256 Fingerprint: c3:84:6b:f2:4b:9e:93:ca:64:27:4c:0e:c6:7c:1e:cc:5e:02:4f:fc:ac:d2:d7:40:19:35:0e:81:fe:54:6a:e4 +-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh +MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE +YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 +MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo +ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg +MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN +ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA +PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w +wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi +EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY +avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ +YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE +sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h +/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 +IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD +ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy +OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P +TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER +dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf +ReYNnyicsbkqWletNw+vHX/bvZ8= +-----END CERTIFICATE----- + +# Issuer: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority +# Subject: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority +# Label: "Starfield Class 2 CA" +# Serial: 0 +# MD5 Fingerprint: 32:4a:4b:bb:c8:63:69:9b:be:74:9a:c6:dd:1d:46:24 +# SHA1 Fingerprint: ad:7e:1c:28:b0:64:ef:8f:60:03:40:20:14:c3:d0:e3:37:0e:b5:8a +# SHA256 Fingerprint: 14:65:fa:20:53:97:b8:76:fa:a6:f0:a9:95:8e:55:90:e4:0f:cc:7f:aa:4f:b7:c2:c8:67:75:21:fb:5f:b6:58 +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl +MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp +U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw +NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE +ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp +ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 +DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf +8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN ++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 +X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa +K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA +1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G +A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR +zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 +YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD +bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 +L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D +eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp +VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY +WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= +-----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=SwissSign Silver CA - G2 O=SwissSign AG +# Subject: CN=SwissSign Silver CA - G2 O=SwissSign AG +# Label: "SwissSign Silver CA - G2" +# Serial: 5700383053117599563 +# MD5 Fingerprint: e0:06:a1:c9:7d:cf:c9:fc:0d:c0:56:75:96:d8:62:13 +# SHA1 Fingerprint: 9b:aa:e5:9f:56:ee:21:cb:43:5a:be:25:93:df:a7:f0:40:d1:1d:cb +# SHA256 Fingerprint: be:6c:4d:a2:bb:b9:ba:59:b6:f3:93:97:68:37:42:46:c3:c0:05:99:3f:a9:8f:02:0d:1d:ed:be:d4:8a:81:d5 +-----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=SecureSign RootCA11 O=Japan Certification Services, Inc. +# Subject: CN=SecureSign RootCA11 O=Japan Certification Services, Inc. +# Label: "SecureSign RootCA11" +# Serial: 1 +# MD5 Fingerprint: b7:52:74:e2:92:b4:80:93:f2:75:e4:cc:d7:f2:ea:26 +# SHA1 Fingerprint: 3b:c4:9f:48:f8:f3:73:a0:9c:1e:bd:f8:5b:b1:c3:65:c7:d8:11:b3 +# SHA256 Fingerprint: bf:0f:ee:fb:9e:3a:58:1a:d5:f9:e9:db:75:89:98:57:43:d2:61:08:5c:4d:31:4f:6f:5d:72:59:aa:42:16:12 +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDEr +MCkGA1UEChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoG +A1UEAxMTU2VjdXJlU2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0 +MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZp +Y2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RD +QTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvLTJsz +i1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8 +h9uuywGOwvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOV +MdrAG/LuYpmGYz+/3ZMqg6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9 +UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rPO7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni +8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitAbpSACW22s293bzUIUPsC +h8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZXt94wDgYD +VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB +AKChOBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xm +KbabfSVSSUOrTC4rbnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQ +X5Ucv+2rIrVls4W6ng+4reV6G4pQOh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWr +QbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01y8hSyn+B/tlr0/cR7SXf+Of5 +pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061lgeLKBObjBmN +QSdJQO7e5iNEOdyhIta6A/I= +-----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=Entrust Root Certification Authority - G4 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2015 Entrust, Inc. - for authorized use only +# Subject: CN=Entrust Root Certification Authority - G4 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2015 Entrust, Inc. - for authorized use only +# Label: "Entrust Root Certification Authority - G4" +# Serial: 289383649854506086828220374796556676440 +# MD5 Fingerprint: 89:53:f1:83:23:b7:7c:8e:05:f1:8c:71:38:4e:1f:88 +# SHA1 Fingerprint: 14:88:4e:86:26:37:b0:26:af:59:62:5c:40:77:ec:35:29:ba:96:01 +# SHA256 Fingerprint: db:35:17:d1:f6:73:2a:2d:5a:b9:7c:53:3e:c7:07:79:ee:32:70:a6:2f:b4:ac:42:38:37:24:60:e6:f0:1e:88 +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAw +gb4xCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQL +Ex9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykg +MjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAw +BgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0 +MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1 +c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJ +bmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3Qg +Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0MIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3DumSXbcr3DbVZwbPLqGgZ +2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV3imz/f3E +T+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j +5pds8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAM +C1rlLAHGVK/XqsEQe9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73T +DtTUXm6Hnmo9RR3RXRv06QqsYJn7ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNX +wbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5XxNMhIWNlUpEbsZmOeX7m640A +2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV7rtNOzK+mndm +nqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8 +dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwl +N4y6mACXi0mWHv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNj +c0kCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9nMA0GCSqGSIb3DQEBCwUAA4ICAQAS +5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4QjbRaZIxowLByQzTS +Gwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht7LGr +hFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/ +B7NTeLUKYvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uI +AeV8KEsD+UmDfLJ/fOPtjqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbw +H5Lk6rWS02FREAutp9lfx1/cH6NcjKF+m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+ +b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKWRGhXxNUzzxkvFMSUHHuk +2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjAJOgc47Ol +IQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk +5F6G+TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuY +n/PIjhs4ViFqUZPTkcpG2om3PVODLAgfi49T3f+sHw== +-----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 RootCA3 O=SECOM Trust Systems CO.,LTD. +# Subject: CN=Security Communication RootCA3 O=SECOM Trust Systems CO.,LTD. +# Label: "Security Communication RootCA3" +# Serial: 16247922307909811815 +# MD5 Fingerprint: 1c:9a:16:ff:9e:5c:e0:4d:8a:14:01:f4:35:5d:29:26 +# SHA1 Fingerprint: c3:03:c8:22:74:92:e5:61:a2:9c:5f:79:91:2b:1e:44:13:91:30:3a +# SHA256 Fingerprint: 24:a5:5c:2a:b0:51:44:2d:06:17:76:65:41:23:9a:4a:d0:32:d7:c5:51:75:aa:34:ff:de:2f:bc:4f:5c:52:94 +-----BEGIN CERTIFICATE----- +MIIFfzCCA2egAwIBAgIJAOF8N0D9G/5nMA0GCSqGSIb3DQEBDAUAMF0xCzAJBgNV +BAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScw +JQYDVQQDEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTMwHhcNMTYwNjE2 +MDYxNzE2WhcNMzgwMTE4MDYxNzE2WjBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc +U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UEAxMeU2VjdXJpdHkg +Q29tbXVuaWNhdGlvbiBSb290Q0EzMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +CgKCAgEA48lySfcw3gl8qUCBWNO0Ot26YQ+TUG5pPDXC7ltzkBtnTCHsXzW7OT4r +CmDvu20rhvtxosis5FaU+cmvsXLUIKx00rgVrVH+hXShuRD+BYD5UpOzQD11EKzA +lrenfna84xtSGc4RHwsENPXY9Wk8d/Nk9A2qhd7gCVAEF5aEt8iKvE1y/By7z/MG +TfmfZPd+pmaGNXHIEYBMwXFAWB6+oHP2/D5Q4eAvJj1+XCO1eXDe+uDRpdYMQXF7 +9+qMHIjH7Iv10S9VlkZ8WjtYO/u62C21Jdp6Ts9EriGmnpjKIG58u4iFW/vAEGK7 +8vknR+/RiTlDxN/e4UG/VHMgly1s2vPUB6PmudhvrvyMGS7TZ2crldtYXLVqAvO4 +g160a75BflcJdURQVc1aEWEhCmHCqYj9E7wtiS/NYeCVvsq1e+F7NGcLH7YMx3we +GVPKp7FKFSBWFHA9K4IsD50VHUeAR/94mQ4xr28+j+2GaR57GIgUssL8gjMunEst ++3A7caoreyYn8xrC3PsXuKHqy6C0rtOUfnrQq8PsOC0RLoi/1D+tEjtCrI8Cbn3M +0V9hvqG8OmpI6iZVIhZdXw3/JzOfGAN0iltSIEdrRU0id4xVJ/CvHozJgyJUt5rQ +T9nO/NkuHJYosQLTA70lUhw0Zk8jq/R3gpYd0VcwCBEF/VfR2ccCAwEAAaNCMEAw +HQYDVR0OBBYEFGQUfPxYchamCik0FW8qy7z8r6irMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDAUAA4ICAQDcAiMI4u8hOscNtybS +YpOnpSNyByCCYN8Y11StaSWSntkUz5m5UoHPrmyKO1o5yGwBQ8IibQLwYs1OY0PA +FNr0Y/Dq9HHuTofjcan0yVflLl8cebsjqodEV+m9NU1Bu0soo5iyG9kLFwfl9+qd +9XbXv8S2gVj/yP9kaWJ5rW4OH3/uHWnlt3Jxs/6lATWUVCvAUm2PVcTJ0rjLyjQI +UYWg9by0F1jqClx6vWPGOi//lkkZhOpn2ASxYfQAW0q3nHE3GYV5v4GwxxMOdnE+ +OoAGrgYWp421wsTL/0ClXI2lyTrtcoHKXJg80jQDdwj98ClZXSEIx2C/pHF7uNke +gr4Jr2VvKKu/S7XuPghHJ6APbw+LP6yVGPO5DtxnVW5inkYO0QR4ynKudtml+LLf +iAlhi+8kTtFZP1rUPcmTPCtk9YENFpb3ksP+MW/oKjJ0DvRMmEoYDjBU1cXrvMUV +nuiZIesnKwkK2/HmcBhWuwzkvvnoEKQTkrgc4NtnHVMDpCKn3F2SEDzq//wbEBrD +2NCcnWXL0CsnMQMeNuE9dnUM/0Umud1RvCPHX9jYhxBAEg09ODfnRDwYwFMJZI// +1ZqmfHAuc1Uh6N//g7kdPjIe1qZ9LPFm6Vwdp6POXiUyK+OVrCoHzrQoeIY8Laad +TdJ0MN1kURXbg4NR16/9M51NZg== +-----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----- diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/certifi/core.py b/backend/.venv/Lib/site-packages/pip/_vendor/certifi/core.py new file mode 100644 index 0000000..70e0c3b --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/certifi/core.py @@ -0,0 +1,114 @@ +""" +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("pip._vendor.certifi").joinpath("cacert.pem")) + _CACERT_PATH = str(_CACERT_CTX.__enter__()) + atexit.register(exit_cacert_ctx) + + return _CACERT_PATH + + def contents() -> str: + return files("pip._vendor.certifi").joinpath("cacert.pem").read_text(encoding="ascii") + +elif sys.version_info >= (3, 7): + + 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("pip._vendor.certifi", "cacert.pem") + _CACERT_PATH = str(_CACERT_CTX.__enter__()) + atexit.register(exit_cacert_ctx) + + return _CACERT_PATH + + def contents() -> str: + return read_text("pip._vendor.certifi", "cacert.pem", encoding="ascii") + +else: + import os + import types + from typing import Union + + Package = Union[types.ModuleType, str] + Resource = Union[str, "os.PathLike"] + + # This fallback will work for Python versions prior to 3.7 that lack the + # importlib.resources module but relies on the existing `where` function + # so won't address issues with environments like PyOxidizer that don't set + # __file__ on modules. + def read_text( + package: Package, + resource: Resource, + encoding: str = 'utf-8', + errors: str = 'strict' + ) -> str: + with open(where(), encoding=encoding) as data: + return data.read() + + # If we don't have importlib.resources, then we will just do the old logic + # of assuming we're on the filesystem and munge the path directly. + def where() -> str: + f = os.path.dirname(__file__) + + return os.path.join(f, "cacert.pem") + + def contents() -> str: + return read_text("pip._vendor.certifi", "cacert.pem", encoding="ascii") diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/certifi/py.typed b/backend/.venv/Lib/site-packages/pip/_vendor/certifi/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/__init__.py b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/__init__.py new file mode 100644 index 0000000..bf0d6c6 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/__init__.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2023 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +import logging + +__version__ = '0.3.9' + + +class DistlibException(Exception): + pass + + +try: + from logging import NullHandler +except ImportError: # pragma: no cover + + class NullHandler(logging.Handler): + + def handle(self, record): + pass + + def emit(self, record): + pass + + def createLock(self): + self.lock = None + + +logger = logging.getLogger(__name__) +logger.addHandler(NullHandler()) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0a192ce9c2d18a8c1812aedc21fa3d16b6eb26f4 GIT binary patch literal 1272 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/database.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/database.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e67f3de9896481ac0074d0895d74fde747601784 GIT binary patch literal 65584 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 Ce)yvR literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..48f1ed29e557e8cd0d3f4cadba2d153afc1fcf82 GIT binary patch literal 24319 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e40b89a7c77fe1204dd54b43f4c9fb0a90587ecc GIT binary patch literal 59864 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 y;ent#;LC_FlJEKvHmUc`3Gs$640 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0489365b52353443cbbbc245a307daaeed3da756 GIT binary patch literal 41563 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 Z;**TSjIsFB?3yDDx_|FXKhkXY{{XG|&DsC} literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..736d1a4d3a550ea3a54db0d2dd32004f2a1f8b78 GIT binary patch literal 17315 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

R5*9%=OTPu%CLaN~I6DSO} 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/compat.py b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/compat.py new file mode 100644 index 0000000..ca561dd --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/compat.py @@ -0,0 +1,1137 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013-2017 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +from __future__ import absolute_import + +import os +import re +import shutil +import sys + +try: + import ssl +except ImportError: # pragma: no cover + ssl = None + +if sys.version_info[0] < 3: # pragma: no cover + from StringIO import StringIO + string_types = basestring, + text_type = unicode + from types import FileType as file_type + import __builtin__ as builtins + import ConfigParser as configparser + from urlparse import urlparse, urlunparse, urljoin, urlsplit, urlunsplit + from urllib import (urlretrieve, quote as _quote, unquote, url2pathname, + pathname2url, ContentTooShortError, splittype) + + def quote(s): + if isinstance(s, unicode): + s = s.encode('utf-8') + return _quote(s) + + import urllib2 + from urllib2 import (Request, urlopen, URLError, HTTPError, + HTTPBasicAuthHandler, HTTPPasswordMgr, HTTPHandler, + HTTPRedirectHandler, build_opener) + if ssl: + from urllib2 import HTTPSHandler + import httplib + import xmlrpclib + import Queue as queue + from HTMLParser import HTMLParser + import htmlentitydefs + raw_input = raw_input + from itertools import ifilter as filter + from itertools import ifilterfalse as filterfalse + + # Leaving this around for now, in case it needs resurrecting in some way + # _userprog = None + # def splituser(host): + # """splituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]'.""" + # global _userprog + # if _userprog is None: + # import re + # _userprog = re.compile('^(.*)@(.*)$') + + # match = _userprog.match(host) + # if match: return match.group(1, 2) + # return None, host + +else: # pragma: no cover + from io import StringIO + string_types = str, + text_type = str + from io import TextIOWrapper as file_type + import builtins + import configparser + from urllib.parse import (urlparse, urlunparse, urljoin, quote, unquote, + urlsplit, urlunsplit, splittype) + from urllib.request import (urlopen, urlretrieve, Request, url2pathname, + pathname2url, HTTPBasicAuthHandler, + HTTPPasswordMgr, HTTPHandler, + HTTPRedirectHandler, build_opener) + if ssl: + from urllib.request import HTTPSHandler + from urllib.error import HTTPError, URLError, ContentTooShortError + import http.client as httplib + import urllib.request as urllib2 + import xmlrpc.client as xmlrpclib + import queue + from html.parser import HTMLParser + import html.entities as htmlentitydefs + raw_input = input + from itertools import filterfalse + filter = filter + +try: + from ssl import match_hostname, CertificateError +except ImportError: # pragma: no cover + + class CertificateError(ValueError): + pass + + def _dnsname_match(dn, hostname, max_wildcards=1): + """Matching according to RFC 6125, section 6.4.3 + + http://tools.ietf.org/html/rfc6125#section-6.4.3 + """ + pats = [] + if not dn: + return False + + parts = dn.split('.') + leftmost, remainder = parts[0], parts[1:] + + wildcards = leftmost.count('*') + if wildcards > max_wildcards: + # Issue #17980: avoid denials of service by refusing more + # than one wildcard per fragment. A survey of established + # policy among SSL implementations showed it to be a + # reasonable choice. + raise CertificateError( + "too many wildcards in certificate DNS name: " + repr(dn)) + + # speed up common case w/o wildcards + if not wildcards: + return dn.lower() == hostname.lower() + + # RFC 6125, section 6.4.3, subitem 1. + # The client SHOULD NOT attempt to match a presented identifier in which + # the wildcard character comprises a label other than the left-most label. + if leftmost == '*': + # When '*' is a fragment by itself, it matches a non-empty dotless + # fragment. + pats.append('[^.]+') + elif leftmost.startswith('xn--') or hostname.startswith('xn--'): + # RFC 6125, section 6.4.3, subitem 3. + # The client SHOULD NOT attempt to match a presented identifier + # where the wildcard character is embedded within an A-label or + # U-label of an internationalized domain name. + pats.append(re.escape(leftmost)) + else: + # Otherwise, '*' matches any dotless string, e.g. www* + pats.append(re.escape(leftmost).replace(r'\*', '[^.]*')) + + # add the remaining fragments, ignore any wildcards + for frag in remainder: + pats.append(re.escape(frag)) + + pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) + return pat.match(hostname) + + def match_hostname(cert, hostname): + """Verify that *cert* (in decoded format as returned by + SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 + rules are followed, but IP addresses are not accepted for *hostname*. + + CertificateError is raised on failure. On success, the function + returns nothing. + """ + if not cert: + raise ValueError("empty or no certificate, match_hostname needs a " + "SSL socket or SSL context with either " + "CERT_OPTIONAL or CERT_REQUIRED") + dnsnames = [] + san = cert.get('subjectAltName', ()) + for key, value in san: + if key == 'DNS': + if _dnsname_match(value, hostname): + return + dnsnames.append(value) + if not dnsnames: + # The subject is only checked when there is no dNSName entry + # in subjectAltName + for sub in cert.get('subject', ()): + for key, value in sub: + # XXX according to RFC 2818, the most specific Common Name + # must be used. + if key == 'commonName': + if _dnsname_match(value, hostname): + return + dnsnames.append(value) + if len(dnsnames) > 1: + raise CertificateError("hostname %r " + "doesn't match either of %s" % + (hostname, ', '.join(map(repr, dnsnames)))) + elif len(dnsnames) == 1: + raise CertificateError("hostname %r " + "doesn't match %r" % + (hostname, dnsnames[0])) + else: + raise CertificateError("no appropriate commonName or " + "subjectAltName fields were found") + + +try: + from types import SimpleNamespace as Container +except ImportError: # pragma: no cover + + class Container(object): + """ + A generic container for when multiple values need to be returned + """ + + def __init__(self, **kwargs): + self.__dict__.update(kwargs) + + +try: + from shutil import which +except ImportError: # pragma: no cover + # Implementation from Python 3.3 + def which(cmd, mode=os.F_OK | os.X_OK, path=None): + """Given a command, mode, and a PATH string, return the path which + conforms to the given mode on the PATH, or None if there is no such + file. + + `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result + of os.environ.get("PATH"), or can be overridden with a custom search + path. + + """ + + # Check that a given file can be accessed with the correct mode. + # Additionally check that `file` is not a directory, as on Windows + # directories pass the os.access check. + def _access_check(fn, mode): + return (os.path.exists(fn) and os.access(fn, mode) and not os.path.isdir(fn)) + + # If we're given a path with a directory part, look it up directly rather + # than referring to PATH directories. This includes checking relative to the + # current directory, e.g. ./script + if os.path.dirname(cmd): + if _access_check(cmd, mode): + return cmd + return None + + if path is None: + path = os.environ.get("PATH", os.defpath) + if not path: + return None + path = path.split(os.pathsep) + + if sys.platform == "win32": + # The current directory takes precedence on Windows. + if os.curdir not in path: + path.insert(0, os.curdir) + + # PATHEXT is necessary to check on Windows. + pathext = os.environ.get("PATHEXT", "").split(os.pathsep) + # See if the given file matches any of the expected path extensions. + # This will allow us to short circuit when given "python.exe". + # If it does match, only test that one, otherwise we have to try + # others. + if any(cmd.lower().endswith(ext.lower()) for ext in pathext): + files = [cmd] + else: + files = [cmd + ext for ext in pathext] + else: + # On other platforms you don't have things like PATHEXT to tell you + # what file suffixes are executable, so just pass on cmd as-is. + files = [cmd] + + seen = set() + for dir in path: + normdir = os.path.normcase(dir) + if normdir not in seen: + seen.add(normdir) + for thefile in files: + name = os.path.join(dir, thefile) + if _access_check(name, mode): + return name + return None + + +# ZipFile is a context manager in 2.7, but not in 2.6 + +from zipfile import ZipFile as BaseZipFile + +if hasattr(BaseZipFile, '__enter__'): # pragma: no cover + ZipFile = BaseZipFile +else: # pragma: no cover + from zipfile import ZipExtFile as BaseZipExtFile + + class ZipExtFile(BaseZipExtFile): + + def __init__(self, base): + self.__dict__.update(base.__dict__) + + def __enter__(self): + return self + + def __exit__(self, *exc_info): + self.close() + # return None, so if an exception occurred, it will propagate + + class ZipFile(BaseZipFile): + + def __enter__(self): + return self + + def __exit__(self, *exc_info): + self.close() + # return None, so if an exception occurred, it will propagate + + def open(self, *args, **kwargs): + base = BaseZipFile.open(self, *args, **kwargs) + return ZipExtFile(base) + + +try: + from platform import python_implementation +except ImportError: # pragma: no cover + + def python_implementation(): + """Return a string identifying the Python implementation.""" + if 'PyPy' in sys.version: + return 'PyPy' + if os.name == 'java': + return 'Jython' + if sys.version.startswith('IronPython'): + return 'IronPython' + return 'CPython' + + +import sysconfig + +try: + callable = callable +except NameError: # pragma: no cover + from collections.abc import Callable + + def callable(obj): + return isinstance(obj, Callable) + + +try: + fsencode = os.fsencode + fsdecode = os.fsdecode +except AttributeError: # pragma: no cover + # Issue #99: on some systems (e.g. containerised), + # sys.getfilesystemencoding() returns None, and we need a real value, + # so fall back to utf-8. From the CPython 2.7 docs relating to Unix and + # sys.getfilesystemencoding(): the return value is "the user’s preference + # according to the result of nl_langinfo(CODESET), or None if the + # nl_langinfo(CODESET) failed." + _fsencoding = sys.getfilesystemencoding() or 'utf-8' + if _fsencoding == 'mbcs': + _fserrors = 'strict' + else: + _fserrors = 'surrogateescape' + + def fsencode(filename): + if isinstance(filename, bytes): + return filename + elif isinstance(filename, text_type): + return filename.encode(_fsencoding, _fserrors) + else: + raise TypeError("expect bytes or str, not %s" % + type(filename).__name__) + + def fsdecode(filename): + if isinstance(filename, text_type): + return filename + elif isinstance(filename, bytes): + return filename.decode(_fsencoding, _fserrors) + else: + raise TypeError("expect bytes or str, not %s" % + type(filename).__name__) + + +try: + from tokenize import detect_encoding +except ImportError: # pragma: no cover + from codecs import BOM_UTF8, lookup + + cookie_re = re.compile(r"coding[:=]\s*([-\w.]+)") + + def _get_normal_name(orig_enc): + """Imitates get_normal_name in tokenizer.c.""" + # Only care about the first 12 characters. + enc = orig_enc[:12].lower().replace("_", "-") + if enc == "utf-8" or enc.startswith("utf-8-"): + return "utf-8" + if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \ + enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")): + return "iso-8859-1" + return orig_enc + + def detect_encoding(readline): + """ + The detect_encoding() function is used to detect the encoding that should + be used to decode a Python source file. It requires one argument, readline, + in the same way as the tokenize() generator. + + It will call readline a maximum of twice, and return the encoding used + (as a string) and a list of any lines (left as bytes) it has read in. + + It detects the encoding from the presence of a utf-8 bom or an encoding + cookie as specified in pep-0263. If both a bom and a cookie are present, + but disagree, a SyntaxError will be raised. If the encoding cookie is an + invalid charset, raise a SyntaxError. Note that if a utf-8 bom is found, + 'utf-8-sig' is returned. + + If no encoding is specified, then the default of 'utf-8' will be returned. + """ + try: + filename = readline.__self__.name + except AttributeError: + filename = None + bom_found = False + encoding = None + default = 'utf-8' + + def read_or_stop(): + try: + return readline() + except StopIteration: + return b'' + + def find_cookie(line): + try: + # Decode as UTF-8. Either the line is an encoding declaration, + # in which case it should be pure ASCII, or it must be UTF-8 + # per default encoding. + line_string = line.decode('utf-8') + except UnicodeDecodeError: + msg = "invalid or missing encoding declaration" + if filename is not None: + msg = '{} for {!r}'.format(msg, filename) + raise SyntaxError(msg) + + matches = cookie_re.findall(line_string) + if not matches: + return None + encoding = _get_normal_name(matches[0]) + try: + codec = lookup(encoding) + except LookupError: + # This behaviour mimics the Python interpreter + if filename is None: + msg = "unknown encoding: " + encoding + else: + msg = "unknown encoding for {!r}: {}".format( + filename, encoding) + raise SyntaxError(msg) + + if bom_found: + if codec.name != 'utf-8': + # This behaviour mimics the Python interpreter + if filename is None: + msg = 'encoding problem: utf-8' + else: + msg = 'encoding problem for {!r}: utf-8'.format( + filename) + raise SyntaxError(msg) + encoding += '-sig' + return encoding + + first = read_or_stop() + if first.startswith(BOM_UTF8): + bom_found = True + first = first[3:] + default = 'utf-8-sig' + if not first: + return default, [] + + encoding = find_cookie(first) + if encoding: + return encoding, [first] + + second = read_or_stop() + if not second: + return default, [first] + + encoding = find_cookie(second) + if encoding: + return encoding, [first, second] + + return default, [first, second] + + +# For converting & <-> & etc. +try: + from html import escape +except ImportError: + from cgi import escape +if sys.version_info[:2] < (3, 4): + unescape = HTMLParser().unescape +else: + from html import unescape + +try: + from collections import ChainMap +except ImportError: # pragma: no cover + from collections import MutableMapping + + try: + from reprlib import recursive_repr as _recursive_repr + except ImportError: + + def _recursive_repr(fillvalue='...'): + ''' + Decorator to make a repr function return fillvalue for a recursive + call + ''' + + def decorating_function(user_function): + repr_running = set() + + def wrapper(self): + key = id(self), get_ident() + if key in repr_running: + return fillvalue + repr_running.add(key) + try: + result = user_function(self) + finally: + repr_running.discard(key) + return result + + # Can't use functools.wraps() here because of bootstrap issues + wrapper.__module__ = getattr(user_function, '__module__') + wrapper.__doc__ = getattr(user_function, '__doc__') + wrapper.__name__ = getattr(user_function, '__name__') + wrapper.__annotations__ = getattr(user_function, + '__annotations__', {}) + return wrapper + + return decorating_function + + class ChainMap(MutableMapping): + ''' + A ChainMap groups multiple dicts (or other mappings) together + to create a single, updateable view. + + The underlying mappings are stored in a list. That list is public and can + accessed or updated using the *maps* attribute. There is no other state. + + Lookups search the underlying mappings successively until a key is found. + In contrast, writes, updates, and deletions only operate on the first + mapping. + ''' + + def __init__(self, *maps): + '''Initialize a ChainMap by setting *maps* to the given mappings. + If no mappings are provided, a single empty dictionary is used. + + ''' + self.maps = list(maps) or [{}] # always at least one map + + def __missing__(self, key): + raise KeyError(key) + + def __getitem__(self, key): + for mapping in self.maps: + try: + return mapping[ + key] # can't use 'key in mapping' with defaultdict + except KeyError: + pass + return self.__missing__( + key) # support subclasses that define __missing__ + + def get(self, key, default=None): + return self[key] if key in self else default + + def __len__(self): + return len(set().union( + *self.maps)) # reuses stored hash values if possible + + def __iter__(self): + return iter(set().union(*self.maps)) + + def __contains__(self, key): + return any(key in m for m in self.maps) + + def __bool__(self): + return any(self.maps) + + @_recursive_repr() + def __repr__(self): + return '{0.__class__.__name__}({1})'.format( + self, ', '.join(map(repr, self.maps))) + + @classmethod + def fromkeys(cls, iterable, *args): + 'Create a ChainMap with a single dict created from the iterable.' + return cls(dict.fromkeys(iterable, *args)) + + def copy(self): + 'New ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]' + return self.__class__(self.maps[0].copy(), *self.maps[1:]) + + __copy__ = copy + + def new_child(self): # like Django's Context.push() + 'New ChainMap with a new dict followed by all previous maps.' + return self.__class__({}, *self.maps) + + @property + def parents(self): # like Django's Context.pop() + 'New ChainMap from maps[1:].' + return self.__class__(*self.maps[1:]) + + def __setitem__(self, key, value): + self.maps[0][key] = value + + def __delitem__(self, key): + try: + del self.maps[0][key] + except KeyError: + raise KeyError( + 'Key not found in the first mapping: {!r}'.format(key)) + + def popitem(self): + 'Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.' + try: + return self.maps[0].popitem() + except KeyError: + raise KeyError('No keys found in the first mapping.') + + def pop(self, key, *args): + 'Remove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].' + try: + return self.maps[0].pop(key, *args) + except KeyError: + raise KeyError( + 'Key not found in the first mapping: {!r}'.format(key)) + + def clear(self): + 'Clear maps[0], leaving maps[1:] intact.' + self.maps[0].clear() + + +try: + from importlib.util import cache_from_source # Python >= 3.4 +except ImportError: # pragma: no cover + + def cache_from_source(path, debug_override=None): + assert path.endswith('.py') + if debug_override is None: + debug_override = __debug__ + if debug_override: + suffix = 'c' + else: + suffix = 'o' + return path + suffix + + +try: + from collections import OrderedDict +except ImportError: # pragma: no cover + # {{{ http://code.activestate.com/recipes/576693/ (r9) + # Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy. + # Passes Python2.7's test suite and incorporates all the latest updates. + try: + from thread import get_ident as _get_ident + except ImportError: + from dummy_thread import get_ident as _get_ident + + try: + from _abcoll import KeysView, ValuesView, ItemsView + except ImportError: + pass + + class OrderedDict(dict): + 'Dictionary that remembers insertion order' + + # An inherited dict maps keys to values. + # The inherited dict provides __getitem__, __len__, __contains__, and get. + # The remaining methods are order-aware. + # Big-O running times for all methods are the same as for regular dictionaries. + + # The internal self.__map dictionary maps keys to links in a doubly linked list. + # The circular doubly linked list starts and ends with a sentinel element. + # The sentinel element never gets deleted (this simplifies the algorithm). + # Each link is stored as a list of length three: [PREV, NEXT, KEY]. + + def __init__(self, *args, **kwds): + '''Initialize an ordered dictionary. Signature is the same as for + regular dictionaries, but keyword arguments are not recommended + because their insertion order is arbitrary. + + ''' + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % + len(args)) + try: + self.__root + except AttributeError: + self.__root = root = [] # sentinel node + root[:] = [root, root, None] + self.__map = {} + self.__update(*args, **kwds) + + def __setitem__(self, key, value, dict_setitem=dict.__setitem__): + 'od.__setitem__(i, y) <==> od[i]=y' + # Setting a new item creates a new link which goes at the end of the linked + # list, and the inherited dictionary is updated with the new key/value pair. + if key not in self: + root = self.__root + last = root[0] + last[1] = root[0] = self.__map[key] = [last, root, key] + dict_setitem(self, key, value) + + def __delitem__(self, key, dict_delitem=dict.__delitem__): + 'od.__delitem__(y) <==> del od[y]' + # Deleting an existing item uses self.__map to find the link which is + # then removed by updating the links in the predecessor and successor nodes. + dict_delitem(self, key) + link_prev, link_next, key = self.__map.pop(key) + link_prev[1] = link_next + link_next[0] = link_prev + + def __iter__(self): + 'od.__iter__() <==> iter(od)' + root = self.__root + curr = root[1] + while curr is not root: + yield curr[2] + curr = curr[1] + + def __reversed__(self): + 'od.__reversed__() <==> reversed(od)' + root = self.__root + curr = root[0] + while curr is not root: + yield curr[2] + curr = curr[0] + + def clear(self): + 'od.clear() -> None. Remove all items from od.' + try: + for node in self.__map.itervalues(): + del node[:] + root = self.__root + root[:] = [root, root, None] + self.__map.clear() + except AttributeError: + pass + dict.clear(self) + + def popitem(self, last=True): + '''od.popitem() -> (k, v), return and remove a (key, value) pair. + Pairs are returned in LIFO order if last is true or FIFO order if false. + + ''' + if not self: + raise KeyError('dictionary is empty') + root = self.__root + if last: + link = root[0] + link_prev = link[0] + link_prev[1] = root + root[0] = link_prev + else: + link = root[1] + link_next = link[1] + root[1] = link_next + link_next[0] = root + key = link[2] + del self.__map[key] + value = dict.pop(self, key) + return key, value + + # -- the following methods do not depend on the internal structure -- + + def keys(self): + 'od.keys() -> list of keys in od' + return list(self) + + def values(self): + 'od.values() -> list of values in od' + return [self[key] for key in self] + + def items(self): + 'od.items() -> list of (key, value) pairs in od' + return [(key, self[key]) for key in self] + + def iterkeys(self): + 'od.iterkeys() -> an iterator over the keys in od' + return iter(self) + + def itervalues(self): + 'od.itervalues -> an iterator over the values in od' + for k in self: + yield self[k] + + def iteritems(self): + 'od.iteritems -> an iterator over the (key, value) items in od' + for k in self: + yield (k, self[k]) + + def update(*args, **kwds): + '''od.update(E, **F) -> None. Update od from dict/iterable E and F. + + If E is a dict instance, does: for k in E: od[k] = E[k] + If E has a .keys() method, does: for k in E.keys(): od[k] = E[k] + Or if E is an iterable of items, does: for k, v in E: od[k] = v + In either case, this is followed by: for k, v in F.items(): od[k] = v + + ''' + if len(args) > 2: + raise TypeError('update() takes at most 2 positional ' + 'arguments (%d given)' % (len(args), )) + elif not args: + raise TypeError('update() takes at least 1 argument (0 given)') + self = args[0] + # Make progressively weaker assumptions about "other" + other = () + if len(args) == 2: + other = args[1] + if isinstance(other, dict): + for key in other: + self[key] = other[key] + elif hasattr(other, 'keys'): + for key in other.keys(): + self[key] = other[key] + else: + for key, value in other: + self[key] = value + for key, value in kwds.items(): + self[key] = value + + __update = update # let subclasses override update without breaking __init__ + + __marker = object() + + def pop(self, key, default=__marker): + '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value. + If key is not found, d is returned if given, otherwise KeyError is raised. + + ''' + if key in self: + result = self[key] + del self[key] + return result + if default is self.__marker: + raise KeyError(key) + return default + + def setdefault(self, key, default=None): + 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' + if key in self: + return self[key] + self[key] = default + return default + + def __repr__(self, _repr_running=None): + 'od.__repr__() <==> repr(od)' + if not _repr_running: + _repr_running = {} + call_key = id(self), _get_ident() + if call_key in _repr_running: + return '...' + _repr_running[call_key] = 1 + try: + if not self: + return '%s()' % (self.__class__.__name__, ) + return '%s(%r)' % (self.__class__.__name__, self.items()) + finally: + del _repr_running[call_key] + + def __reduce__(self): + 'Return state information for pickling' + items = [[k, self[k]] for k in self] + inst_dict = vars(self).copy() + for k in vars(OrderedDict()): + inst_dict.pop(k, None) + if inst_dict: + return (self.__class__, (items, ), inst_dict) + return self.__class__, (items, ) + + def copy(self): + 'od.copy() -> a shallow copy of od' + return self.__class__(self) + + @classmethod + def fromkeys(cls, iterable, value=None): + '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S + and values equal to v (which defaults to None). + + ''' + d = cls() + for key in iterable: + d[key] = value + return d + + def __eq__(self, other): + '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive + while comparison to a regular mapping is order-insensitive. + + ''' + if isinstance(other, OrderedDict): + return len(self) == len( + other) and self.items() == other.items() + return dict.__eq__(self, other) + + def __ne__(self, other): + return not self == other + + # -- the following methods are only used in Python 2.7 -- + + def viewkeys(self): + "od.viewkeys() -> a set-like object providing a view on od's keys" + return KeysView(self) + + def viewvalues(self): + "od.viewvalues() -> an object providing a view on od's values" + return ValuesView(self) + + def viewitems(self): + "od.viewitems() -> a set-like object providing a view on od's items" + return ItemsView(self) + + +try: + from logging.config import BaseConfigurator, valid_ident +except ImportError: # pragma: no cover + IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I) + + def valid_ident(s): + m = IDENTIFIER.match(s) + if not m: + raise ValueError('Not a valid Python identifier: %r' % s) + return True + + # The ConvertingXXX classes are wrappers around standard Python containers, + # and they serve to convert any suitable values in the container. The + # conversion converts base dicts, lists and tuples to their wrapped + # equivalents, whereas strings which match a conversion format are converted + # appropriately. + # + # Each wrapper should have a configurator attribute holding the actual + # configurator to use for conversion. + + class ConvertingDict(dict): + """A converting dictionary wrapper.""" + + def __getitem__(self, key): + value = dict.__getitem__(self, key) + result = self.configurator.convert(value) + # If the converted value is different, save for next time + if value is not result: + self[key] = result + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + def get(self, key, default=None): + value = dict.get(self, key, default) + result = self.configurator.convert(value) + # If the converted value is different, save for next time + if value is not result: + self[key] = result + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + def pop(self, key, default=None): + value = dict.pop(self, key, default) + result = self.configurator.convert(value) + if value is not result: + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + class ConvertingList(list): + """A converting list wrapper.""" + + def __getitem__(self, key): + value = list.__getitem__(self, key) + result = self.configurator.convert(value) + # If the converted value is different, save for next time + if value is not result: + self[key] = result + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + def pop(self, idx=-1): + value = list.pop(self, idx) + result = self.configurator.convert(value) + if value is not result: + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + return result + + class ConvertingTuple(tuple): + """A converting tuple wrapper.""" + + def __getitem__(self, key): + value = tuple.__getitem__(self, key) + result = self.configurator.convert(value) + if value is not result: + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + class BaseConfigurator(object): + """ + The configurator base class which defines some useful defaults. + """ + + CONVERT_PATTERN = re.compile(r'^(?P[a-z]+)://(?P.*)$') + + WORD_PATTERN = re.compile(r'^\s*(\w+)\s*') + DOT_PATTERN = re.compile(r'^\.\s*(\w+)\s*') + INDEX_PATTERN = re.compile(r'^\[\s*(\w+)\s*\]\s*') + DIGIT_PATTERN = re.compile(r'^\d+$') + + value_converters = { + 'ext': 'ext_convert', + 'cfg': 'cfg_convert', + } + + # We might want to use a different one, e.g. importlib + importer = staticmethod(__import__) + + def __init__(self, config): + self.config = ConvertingDict(config) + self.config.configurator = self + + def resolve(self, s): + """ + Resolve strings to objects using standard import and attribute + syntax. + """ + name = s.split('.') + used = name.pop(0) + try: + found = self.importer(used) + for frag in name: + used += '.' + frag + try: + found = getattr(found, frag) + except AttributeError: + self.importer(used) + found = getattr(found, frag) + return found + except ImportError: + e, tb = sys.exc_info()[1:] + v = ValueError('Cannot resolve %r: %s' % (s, e)) + v.__cause__, v.__traceback__ = e, tb + raise v + + def ext_convert(self, value): + """Default converter for the ext:// protocol.""" + return self.resolve(value) + + def cfg_convert(self, value): + """Default converter for the cfg:// protocol.""" + rest = value + m = self.WORD_PATTERN.match(rest) + if m is None: + raise ValueError("Unable to convert %r" % value) + else: + rest = rest[m.end():] + d = self.config[m.groups()[0]] + while rest: + m = self.DOT_PATTERN.match(rest) + if m: + d = d[m.groups()[0]] + else: + m = self.INDEX_PATTERN.match(rest) + if m: + idx = m.groups()[0] + if not self.DIGIT_PATTERN.match(idx): + d = d[idx] + else: + try: + n = int( + idx + ) # try as number first (most likely) + d = d[n] + except TypeError: + d = d[idx] + if m: + rest = rest[m.end():] + else: + raise ValueError('Unable to convert ' + '%r at %r' % (value, rest)) + # rest should be empty + return d + + def convert(self, value): + """ + Convert values to an appropriate type. dicts, lists and tuples are + replaced by their converting alternatives. Strings are checked to + see if they have a conversion format and are converted if they do. + """ + if not isinstance(value, ConvertingDict) and isinstance( + value, dict): + value = ConvertingDict(value) + value.configurator = self + elif not isinstance(value, ConvertingList) and isinstance( + value, list): + value = ConvertingList(value) + value.configurator = self + elif not isinstance(value, ConvertingTuple) and isinstance(value, tuple): + value = ConvertingTuple(value) + value.configurator = self + elif isinstance(value, string_types): + m = self.CONVERT_PATTERN.match(value) + if m: + d = m.groupdict() + prefix = d['prefix'] + converter = self.value_converters.get(prefix, None) + if converter: + suffix = d['suffix'] + converter = getattr(self, converter) + value = converter(suffix) + return value + + def configure_custom(self, config): + """Configure an object with a user-supplied factory.""" + c = config.pop('()') + if not callable(c): + c = self.resolve(c) + props = config.pop('.', None) + # Check for valid identifiers + kwargs = dict([(k, config[k]) for k in config if valid_ident(k)]) + result = c(**kwargs) + if props: + for name, value in props.items(): + setattr(result, name, value) + return result + + def as_tuple(self, value): + """Utility function which converts lists to tuples.""" + if isinstance(value, list): + value = tuple(value) + return value diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/database.py b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/database.py new file mode 100644 index 0000000..c0f896a --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/database.py @@ -0,0 +1,1329 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2023 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +"""PEP 376 implementation.""" + +from __future__ import unicode_literals + +import base64 +import codecs +import contextlib +import hashlib +import logging +import os +import posixpath +import sys +import zipimport + +from . import DistlibException, resources +from .compat import StringIO +from .version import get_scheme, UnsupportedVersionError +from .metadata import (Metadata, METADATA_FILENAME, WHEEL_METADATA_FILENAME, LEGACY_METADATA_FILENAME) +from .util import (parse_requirement, cached_property, parse_name_and_version, read_exports, write_exports, CSVReader, + CSVWriter) + +__all__ = [ + 'Distribution', 'BaseInstalledDistribution', 'InstalledDistribution', 'EggInfoDistribution', 'DistributionPath' +] + +logger = logging.getLogger(__name__) + +EXPORTS_FILENAME = 'pydist-exports.json' +COMMANDS_FILENAME = 'pydist-commands.json' + +DIST_FILES = ('INSTALLER', METADATA_FILENAME, 'RECORD', 'REQUESTED', 'RESOURCES', EXPORTS_FILENAME, 'SHARED') + +DISTINFO_EXT = '.dist-info' + + +class _Cache(object): + """ + A simple cache mapping names and .dist-info paths to distributions + """ + + def __init__(self): + """ + Initialise an instance. There is normally one for each DistributionPath. + """ + self.name = {} + self.path = {} + self.generated = False + + def clear(self): + """ + Clear the cache, setting it to its initial state. + """ + self.name.clear() + self.path.clear() + self.generated = False + + def add(self, dist): + """ + Add a distribution to the cache. + :param dist: The distribution to add. + """ + if dist.path not in self.path: + self.path[dist.path] = dist + self.name.setdefault(dist.key, []).append(dist) + + +class DistributionPath(object): + """ + Represents a set of distributions installed on a path (typically sys.path). + """ + + def __init__(self, path=None, include_egg=False): + """ + Create an instance from a path, optionally including legacy (distutils/ + setuptools/distribute) distributions. + :param path: The path to use, as a list of directories. If not specified, + sys.path is used. + :param include_egg: If True, this instance will look for and return legacy + distributions as well as those based on PEP 376. + """ + if path is None: + path = sys.path + self.path = path + self._include_dist = True + self._include_egg = include_egg + + self._cache = _Cache() + self._cache_egg = _Cache() + self._cache_enabled = True + self._scheme = get_scheme('default') + + def _get_cache_enabled(self): + return self._cache_enabled + + def _set_cache_enabled(self, value): + self._cache_enabled = value + + cache_enabled = property(_get_cache_enabled, _set_cache_enabled) + + def clear_cache(self): + """ + Clears the internal cache. + """ + self._cache.clear() + self._cache_egg.clear() + + def _yield_distributions(self): + """ + Yield .dist-info and/or .egg(-info) distributions. + """ + # We need to check if we've seen some resources already, because on + # some Linux systems (e.g. some Debian/Ubuntu variants) there are + # symlinks which alias other files in the environment. + seen = set() + for path in self.path: + finder = resources.finder_for_path(path) + if finder is None: + continue + r = finder.find('') + if not r or not r.is_container: + continue + rset = sorted(r.resources) + for entry in rset: + r = finder.find(entry) + if not r or r.path in seen: + continue + try: + if self._include_dist and entry.endswith(DISTINFO_EXT): + possible_filenames = [METADATA_FILENAME, WHEEL_METADATA_FILENAME, LEGACY_METADATA_FILENAME] + for metadata_filename in possible_filenames: + metadata_path = posixpath.join(entry, metadata_filename) + pydist = finder.find(metadata_path) + if pydist: + break + else: + continue + + with contextlib.closing(pydist.as_stream()) as stream: + metadata = Metadata(fileobj=stream, scheme='legacy') + logger.debug('Found %s', r.path) + seen.add(r.path) + yield new_dist_class(r.path, metadata=metadata, env=self) + elif self._include_egg and entry.endswith(('.egg-info', '.egg')): + logger.debug('Found %s', r.path) + seen.add(r.path) + yield old_dist_class(r.path, self) + except Exception as e: + msg = 'Unable to read distribution at %s, perhaps due to bad metadata: %s' + logger.warning(msg, r.path, e) + import warnings + warnings.warn(msg % (r.path, e), stacklevel=2) + + def _generate_cache(self): + """ + Scan the path for distributions and populate the cache with + those that are found. + """ + gen_dist = not self._cache.generated + gen_egg = self._include_egg and not self._cache_egg.generated + if gen_dist or gen_egg: + for dist in self._yield_distributions(): + if isinstance(dist, InstalledDistribution): + self._cache.add(dist) + else: + self._cache_egg.add(dist) + + if gen_dist: + self._cache.generated = True + if gen_egg: + self._cache_egg.generated = True + + @classmethod + def distinfo_dirname(cls, name, version): + """ + The *name* and *version* parameters are converted into their + filename-escaped form, i.e. any ``'-'`` characters are replaced + with ``'_'`` other than the one in ``'dist-info'`` and the one + separating the name from the version number. + + :parameter name: is converted to a standard distribution name by replacing + any runs of non- alphanumeric characters with a single + ``'-'``. + :type name: string + :parameter version: is converted to a standard version string. Spaces + become dots, and all other non-alphanumeric characters + (except dots) become dashes, with runs of multiple + dashes condensed to a single dash. + :type version: string + :returns: directory name + :rtype: string""" + name = name.replace('-', '_') + return '-'.join([name, version]) + DISTINFO_EXT + + def get_distributions(self): + """ + Provides an iterator that looks for distributions and returns + :class:`InstalledDistribution` or + :class:`EggInfoDistribution` instances for each one of them. + + :rtype: iterator of :class:`InstalledDistribution` and + :class:`EggInfoDistribution` instances + """ + if not self._cache_enabled: + for dist in self._yield_distributions(): + yield dist + else: + self._generate_cache() + + for dist in self._cache.path.values(): + yield dist + + if self._include_egg: + for dist in self._cache_egg.path.values(): + yield dist + + def get_distribution(self, name): + """ + Looks for a named distribution on the path. + + This function only returns the first result found, as no more than one + value is expected. If nothing is found, ``None`` is returned. + + :rtype: :class:`InstalledDistribution`, :class:`EggInfoDistribution` + or ``None`` + """ + result = None + name = name.lower() + if not self._cache_enabled: + for dist in self._yield_distributions(): + if dist.key == name: + result = dist + break + else: + self._generate_cache() + + if name in self._cache.name: + result = self._cache.name[name][0] + elif self._include_egg and name in self._cache_egg.name: + result = self._cache_egg.name[name][0] + return result + + def provides_distribution(self, name, version=None): + """ + Iterates over all distributions to find which distributions provide *name*. + If a *version* is provided, it will be used to filter the results. + + This function only returns the first result found, since no more than + one values are expected. If the directory is not found, returns ``None``. + + :parameter version: a version specifier that indicates the version + required, conforming to the format in ``PEP-345`` + + :type name: string + :type version: string + """ + matcher = None + if version is not None: + try: + matcher = self._scheme.matcher('%s (%s)' % (name, version)) + except ValueError: + raise DistlibException('invalid name or version: %r, %r' % (name, version)) + + for dist in self.get_distributions(): + # We hit a problem on Travis where enum34 was installed and doesn't + # have a provides attribute ... + if not hasattr(dist, 'provides'): + logger.debug('No "provides": %s', dist) + else: + provided = dist.provides + + for p in provided: + p_name, p_ver = parse_name_and_version(p) + if matcher is None: + if p_name == name: + yield dist + break + else: + if p_name == name and matcher.match(p_ver): + yield dist + break + + def get_file_path(self, name, relative_path): + """ + Return the path to a resource file. + """ + dist = self.get_distribution(name) + if dist is None: + raise LookupError('no distribution named %r found' % name) + return dist.get_resource_path(relative_path) + + def get_exported_entries(self, category, name=None): + """ + Return all of the exported entries in a particular category. + + :param category: The category to search for entries. + :param name: If specified, only entries with that name are returned. + """ + for dist in self.get_distributions(): + r = dist.exports + if category in r: + d = r[category] + if name is not None: + if name in d: + yield d[name] + else: + for v in d.values(): + yield v + + +class Distribution(object): + """ + A base class for distributions, whether installed or from indexes. + Either way, it must have some metadata, so that's all that's needed + for construction. + """ + + build_time_dependency = False + """ + Set to True if it's known to be only a build-time dependency (i.e. + not needed after installation). + """ + + requested = False + """A boolean that indicates whether the ``REQUESTED`` metadata file is + present (in other words, whether the package was installed by user + request or it was installed as a dependency).""" + + def __init__(self, metadata): + """ + Initialise an instance. + :param metadata: The instance of :class:`Metadata` describing this + distribution. + """ + self.metadata = metadata + self.name = metadata.name + self.key = self.name.lower() # for case-insensitive comparisons + self.version = metadata.version + self.locator = None + self.digest = None + self.extras = None # additional features requested + self.context = None # environment marker overrides + self.download_urls = set() + self.digests = {} + + @property + def source_url(self): + """ + The source archive download URL for this distribution. + """ + return self.metadata.source_url + + download_url = source_url # Backward compatibility + + @property + def name_and_version(self): + """ + A utility property which displays the name and version in parentheses. + """ + return '%s (%s)' % (self.name, self.version) + + @property + def provides(self): + """ + A set of distribution names and versions provided by this distribution. + :return: A set of "name (version)" strings. + """ + plist = self.metadata.provides + s = '%s (%s)' % (self.name, self.version) + if s not in plist: + plist.append(s) + return plist + + def _get_requirements(self, req_attr): + md = self.metadata + reqts = getattr(md, req_attr) + logger.debug('%s: got requirements %r from metadata: %r', self.name, req_attr, reqts) + return set(md.get_requirements(reqts, extras=self.extras, env=self.context)) + + @property + def run_requires(self): + return self._get_requirements('run_requires') + + @property + def meta_requires(self): + return self._get_requirements('meta_requires') + + @property + def build_requires(self): + return self._get_requirements('build_requires') + + @property + def test_requires(self): + return self._get_requirements('test_requires') + + @property + def dev_requires(self): + return self._get_requirements('dev_requires') + + def matches_requirement(self, req): + """ + Say if this instance matches (fulfills) a requirement. + :param req: The requirement to match. + :rtype req: str + :return: True if it matches, else False. + """ + # Requirement may contain extras - parse to lose those + # from what's passed to the matcher + r = parse_requirement(req) + scheme = get_scheme(self.metadata.scheme) + try: + matcher = scheme.matcher(r.requirement) + except UnsupportedVersionError: + # XXX compat-mode if cannot read the version + logger.warning('could not read version %r - using name only', req) + name = req.split()[0] + matcher = scheme.matcher(name) + + name = matcher.key # case-insensitive + + result = False + for p in self.provides: + p_name, p_ver = parse_name_and_version(p) + if p_name != name: + continue + try: + result = matcher.match(p_ver) + break + except UnsupportedVersionError: + pass + return result + + def __repr__(self): + """ + Return a textual representation of this instance, + """ + if self.source_url: + suffix = ' [%s]' % self.source_url + else: + suffix = '' + return '' % (self.name, self.version, suffix) + + def __eq__(self, other): + """ + See if this distribution is the same as another. + :param other: The distribution to compare with. To be equal to one + another. distributions must have the same type, name, + version and source_url. + :return: True if it is the same, else False. + """ + if type(other) is not type(self): + result = False + else: + result = (self.name == other.name and self.version == other.version and self.source_url == other.source_url) + return result + + def __hash__(self): + """ + Compute hash in a way which matches the equality test. + """ + return hash(self.name) + hash(self.version) + hash(self.source_url) + + +class BaseInstalledDistribution(Distribution): + """ + This is the base class for installed distributions (whether PEP 376 or + legacy). + """ + + hasher = None + + def __init__(self, metadata, path, env=None): + """ + Initialise an instance. + :param metadata: An instance of :class:`Metadata` which describes the + distribution. This will normally have been initialised + from a metadata file in the ``path``. + :param path: The path of the ``.dist-info`` or ``.egg-info`` + directory for the distribution. + :param env: This is normally the :class:`DistributionPath` + instance where this distribution was found. + """ + super(BaseInstalledDistribution, self).__init__(metadata) + self.path = path + self.dist_path = env + + def get_hash(self, data, hasher=None): + """ + Get the hash of some data, using a particular hash algorithm, if + specified. + + :param data: The data to be hashed. + :type data: bytes + :param hasher: The name of a hash implementation, supported by hashlib, + or ``None``. Examples of valid values are ``'sha1'``, + ``'sha224'``, ``'sha384'``, '``sha256'``, ``'md5'`` and + ``'sha512'``. If no hasher is specified, the ``hasher`` + attribute of the :class:`InstalledDistribution` instance + is used. If the hasher is determined to be ``None``, MD5 + is used as the hashing algorithm. + :returns: The hash of the data. If a hasher was explicitly specified, + the returned hash will be prefixed with the specified hasher + followed by '='. + :rtype: str + """ + if hasher is None: + hasher = self.hasher + if hasher is None: + hasher = hashlib.md5 + prefix = '' + else: + hasher = getattr(hashlib, hasher) + prefix = '%s=' % self.hasher + digest = hasher(data).digest() + digest = base64.urlsafe_b64encode(digest).rstrip(b'=').decode('ascii') + return '%s%s' % (prefix, digest) + + +class InstalledDistribution(BaseInstalledDistribution): + """ + Created with the *path* of the ``.dist-info`` directory provided to the + constructor. It reads the metadata contained in ``pydist.json`` when it is + instantiated., or uses a passed in Metadata instance (useful for when + dry-run mode is being used). + """ + + hasher = 'sha256' + + def __init__(self, path, metadata=None, env=None): + self.modules = [] + self.finder = finder = resources.finder_for_path(path) + if finder is None: + raise ValueError('finder unavailable for %s' % path) + if env and env._cache_enabled and path in env._cache.path: + metadata = env._cache.path[path].metadata + elif metadata is None: + r = finder.find(METADATA_FILENAME) + # Temporary - for Wheel 0.23 support + if r is None: + r = finder.find(WHEEL_METADATA_FILENAME) + # Temporary - for legacy support + if r is None: + r = finder.find(LEGACY_METADATA_FILENAME) + if r is None: + raise ValueError('no %s found in %s' % (METADATA_FILENAME, path)) + with contextlib.closing(r.as_stream()) as stream: + metadata = Metadata(fileobj=stream, scheme='legacy') + + super(InstalledDistribution, self).__init__(metadata, path, env) + + if env and env._cache_enabled: + env._cache.add(self) + + r = finder.find('REQUESTED') + self.requested = r is not None + p = os.path.join(path, 'top_level.txt') + if os.path.exists(p): + with open(p, 'rb') as f: + data = f.read().decode('utf-8') + self.modules = data.splitlines() + + def __repr__(self): + return '' % (self.name, self.version, self.path) + + def __str__(self): + return "%s %s" % (self.name, self.version) + + def _get_records(self): + """ + Get the list of installed files for the distribution + :return: A list of tuples of path, hash and size. Note that hash and + size might be ``None`` for some entries. The path is exactly + as stored in the file (which is as in PEP 376). + """ + results = [] + r = self.get_distinfo_resource('RECORD') + with contextlib.closing(r.as_stream()) as stream: + with CSVReader(stream=stream) as record_reader: + # Base location is parent dir of .dist-info dir + # base_location = os.path.dirname(self.path) + # base_location = os.path.abspath(base_location) + for row in record_reader: + missing = [None for i in range(len(row), 3)] + path, checksum, size = row + missing + # if not os.path.isabs(path): + # path = path.replace('/', os.sep) + # path = os.path.join(base_location, path) + results.append((path, checksum, size)) + return results + + @cached_property + def exports(self): + """ + Return the information exported by this distribution. + :return: A dictionary of exports, mapping an export category to a dict + of :class:`ExportEntry` instances describing the individual + export entries, and keyed by name. + """ + result = {} + r = self.get_distinfo_resource(EXPORTS_FILENAME) + if r: + result = self.read_exports() + return result + + def read_exports(self): + """ + Read exports data from a file in .ini format. + + :return: A dictionary of exports, mapping an export category to a list + of :class:`ExportEntry` instances describing the individual + export entries. + """ + result = {} + r = self.get_distinfo_resource(EXPORTS_FILENAME) + if r: + with contextlib.closing(r.as_stream()) as stream: + result = read_exports(stream) + return result + + def write_exports(self, exports): + """ + Write a dictionary of exports to a file in .ini format. + :param exports: A dictionary of exports, mapping an export category to + a list of :class:`ExportEntry` instances describing the + individual export entries. + """ + rf = self.get_distinfo_file(EXPORTS_FILENAME) + with open(rf, 'w') as f: + write_exports(exports, f) + + def get_resource_path(self, relative_path): + """ + NOTE: This API may change in the future. + + Return the absolute path to a resource file with the given relative + path. + + :param relative_path: The path, relative to .dist-info, of the resource + of interest. + :return: The absolute path where the resource is to be found. + """ + r = self.get_distinfo_resource('RESOURCES') + with contextlib.closing(r.as_stream()) as stream: + with CSVReader(stream=stream) as resources_reader: + for relative, destination in resources_reader: + if relative == relative_path: + return destination + raise KeyError('no resource file with relative path %r ' + 'is installed' % relative_path) + + def list_installed_files(self): + """ + Iterates over the ``RECORD`` entries and returns a tuple + ``(path, hash, size)`` for each line. + + :returns: iterator of (path, hash, size) + """ + for result in self._get_records(): + yield result + + def write_installed_files(self, paths, prefix, dry_run=False): + """ + Writes the ``RECORD`` file, using the ``paths`` iterable passed in. Any + existing ``RECORD`` file is silently overwritten. + + prefix is used to determine when to write absolute paths. + """ + prefix = os.path.join(prefix, '') + base = os.path.dirname(self.path) + base_under_prefix = base.startswith(prefix) + base = os.path.join(base, '') + record_path = self.get_distinfo_file('RECORD') + logger.info('creating %s', record_path) + if dry_run: + return None + with CSVWriter(record_path) as writer: + for path in paths: + if os.path.isdir(path) or path.endswith(('.pyc', '.pyo')): + # do not put size and hash, as in PEP-376 + hash_value = size = '' + else: + size = '%d' % os.path.getsize(path) + with open(path, 'rb') as fp: + hash_value = self.get_hash(fp.read()) + if path.startswith(base) or (base_under_prefix and path.startswith(prefix)): + path = os.path.relpath(path, base) + writer.writerow((path, hash_value, size)) + + # add the RECORD file itself + if record_path.startswith(base): + record_path = os.path.relpath(record_path, base) + writer.writerow((record_path, '', '')) + return record_path + + def check_installed_files(self): + """ + Checks that the hashes and sizes of the files in ``RECORD`` are + matched by the files themselves. Returns a (possibly empty) list of + mismatches. Each entry in the mismatch list will be a tuple consisting + of the path, 'exists', 'size' or 'hash' according to what didn't match + (existence is checked first, then size, then hash), the expected + value and the actual value. + """ + mismatches = [] + base = os.path.dirname(self.path) + record_path = self.get_distinfo_file('RECORD') + for path, hash_value, size in self.list_installed_files(): + if not os.path.isabs(path): + path = os.path.join(base, path) + if path == record_path: + continue + if not os.path.exists(path): + mismatches.append((path, 'exists', True, False)) + elif os.path.isfile(path): + actual_size = str(os.path.getsize(path)) + if size and actual_size != size: + mismatches.append((path, 'size', size, actual_size)) + elif hash_value: + if '=' in hash_value: + hasher = hash_value.split('=', 1)[0] + else: + hasher = None + + with open(path, 'rb') as f: + actual_hash = self.get_hash(f.read(), hasher) + if actual_hash != hash_value: + mismatches.append((path, 'hash', hash_value, actual_hash)) + return mismatches + + @cached_property + def shared_locations(self): + """ + A dictionary of shared locations whose keys are in the set 'prefix', + 'purelib', 'platlib', 'scripts', 'headers', 'data' and 'namespace'. + The corresponding value is the absolute path of that category for + this distribution, and takes into account any paths selected by the + user at installation time (e.g. via command-line arguments). In the + case of the 'namespace' key, this would be a list of absolute paths + for the roots of namespace packages in this distribution. + + The first time this property is accessed, the relevant information is + read from the SHARED file in the .dist-info directory. + """ + result = {} + shared_path = os.path.join(self.path, 'SHARED') + if os.path.isfile(shared_path): + with codecs.open(shared_path, 'r', encoding='utf-8') as f: + lines = f.read().splitlines() + for line in lines: + key, value = line.split('=', 1) + if key == 'namespace': + result.setdefault(key, []).append(value) + else: + result[key] = value + return result + + def write_shared_locations(self, paths, dry_run=False): + """ + Write shared location information to the SHARED file in .dist-info. + :param paths: A dictionary as described in the documentation for + :meth:`shared_locations`. + :param dry_run: If True, the action is logged but no file is actually + written. + :return: The path of the file written to. + """ + shared_path = os.path.join(self.path, 'SHARED') + logger.info('creating %s', shared_path) + if dry_run: + return None + lines = [] + for key in ('prefix', 'lib', 'headers', 'scripts', 'data'): + path = paths[key] + if os.path.isdir(paths[key]): + lines.append('%s=%s' % (key, path)) + for ns in paths.get('namespace', ()): + lines.append('namespace=%s' % ns) + + with codecs.open(shared_path, 'w', encoding='utf-8') as f: + f.write('\n'.join(lines)) + return shared_path + + def get_distinfo_resource(self, path): + if path not in DIST_FILES: + raise DistlibException('invalid path for a dist-info file: ' + '%r at %r' % (path, self.path)) + finder = resources.finder_for_path(self.path) + if finder is None: + raise DistlibException('Unable to get a finder for %s' % self.path) + return finder.find(path) + + def get_distinfo_file(self, path): + """ + Returns a path located under the ``.dist-info`` directory. Returns a + string representing the path. + + :parameter path: a ``'/'``-separated path relative to the + ``.dist-info`` directory or an absolute path; + If *path* is an absolute path and doesn't start + with the ``.dist-info`` directory path, + a :class:`DistlibException` is raised + :type path: str + :rtype: str + """ + # Check if it is an absolute path # XXX use relpath, add tests + if path.find(os.sep) >= 0: + # it's an absolute path? + distinfo_dirname, path = path.split(os.sep)[-2:] + if distinfo_dirname != self.path.split(os.sep)[-1]: + raise DistlibException('dist-info file %r does not belong to the %r %s ' + 'distribution' % (path, self.name, self.version)) + + # The file must be relative + if path not in DIST_FILES: + raise DistlibException('invalid path for a dist-info file: ' + '%r at %r' % (path, self.path)) + + return os.path.join(self.path, path) + + def list_distinfo_files(self): + """ + Iterates over the ``RECORD`` entries and returns paths for each line if + the path is pointing to a file located in the ``.dist-info`` directory + or one of its subdirectories. + + :returns: iterator of paths + """ + base = os.path.dirname(self.path) + for path, checksum, size in self._get_records(): + # XXX add separator or use real relpath algo + if not os.path.isabs(path): + path = os.path.join(base, path) + if path.startswith(self.path): + yield path + + def __eq__(self, other): + return (isinstance(other, InstalledDistribution) and self.path == other.path) + + # See http://docs.python.org/reference/datamodel#object.__hash__ + __hash__ = object.__hash__ + + +class EggInfoDistribution(BaseInstalledDistribution): + """Created with the *path* of the ``.egg-info`` directory or file provided + to the constructor. It reads the metadata contained in the file itself, or + if the given path happens to be a directory, the metadata is read from the + file ``PKG-INFO`` under that directory.""" + + requested = True # as we have no way of knowing, assume it was + shared_locations = {} + + def __init__(self, path, env=None): + + def set_name_and_version(s, n, v): + s.name = n + s.key = n.lower() # for case-insensitive comparisons + s.version = v + + self.path = path + self.dist_path = env + if env and env._cache_enabled and path in env._cache_egg.path: + metadata = env._cache_egg.path[path].metadata + set_name_and_version(self, metadata.name, metadata.version) + else: + metadata = self._get_metadata(path) + + # Need to be set before caching + set_name_and_version(self, metadata.name, metadata.version) + + if env and env._cache_enabled: + env._cache_egg.add(self) + super(EggInfoDistribution, self).__init__(metadata, path, env) + + def _get_metadata(self, path): + requires = None + + def parse_requires_data(data): + """Create a list of dependencies from a requires.txt file. + + *data*: the contents of a setuptools-produced requires.txt file. + """ + reqs = [] + lines = data.splitlines() + for line in lines: + line = line.strip() + # sectioned files have bare newlines (separating sections) + if not line: # pragma: no cover + continue + if line.startswith('['): # pragma: no cover + logger.warning('Unexpected line: quitting requirement scan: %r', line) + break + r = parse_requirement(line) + if not r: # pragma: no cover + logger.warning('Not recognised as a requirement: %r', line) + continue + if r.extras: # pragma: no cover + logger.warning('extra requirements in requires.txt are ' + 'not supported') + if not r.constraints: + reqs.append(r.name) + else: + cons = ', '.join('%s%s' % c for c in r.constraints) + reqs.append('%s (%s)' % (r.name, cons)) + return reqs + + def parse_requires_path(req_path): + """Create a list of dependencies from a requires.txt file. + + *req_path*: the path to a setuptools-produced requires.txt file. + """ + + reqs = [] + try: + with codecs.open(req_path, 'r', 'utf-8') as fp: + reqs = parse_requires_data(fp.read()) + except IOError: + pass + return reqs + + tl_path = tl_data = None + if path.endswith('.egg'): + if os.path.isdir(path): + p = os.path.join(path, 'EGG-INFO') + meta_path = os.path.join(p, 'PKG-INFO') + metadata = Metadata(path=meta_path, scheme='legacy') + req_path = os.path.join(p, 'requires.txt') + tl_path = os.path.join(p, 'top_level.txt') + requires = parse_requires_path(req_path) + else: + # FIXME handle the case where zipfile is not available + zipf = zipimport.zipimporter(path) + fileobj = StringIO(zipf.get_data('EGG-INFO/PKG-INFO').decode('utf8')) + metadata = Metadata(fileobj=fileobj, scheme='legacy') + try: + data = zipf.get_data('EGG-INFO/requires.txt') + tl_data = zipf.get_data('EGG-INFO/top_level.txt').decode('utf-8') + requires = parse_requires_data(data.decode('utf-8')) + except IOError: + requires = None + elif path.endswith('.egg-info'): + if os.path.isdir(path): + req_path = os.path.join(path, 'requires.txt') + requires = parse_requires_path(req_path) + path = os.path.join(path, 'PKG-INFO') + tl_path = os.path.join(path, 'top_level.txt') + metadata = Metadata(path=path, scheme='legacy') + else: + raise DistlibException('path must end with .egg-info or .egg, ' + 'got %r' % path) + + if requires: + metadata.add_requirements(requires) + # look for top-level modules in top_level.txt, if present + if tl_data is None: + if tl_path is not None and os.path.exists(tl_path): + with open(tl_path, 'rb') as f: + tl_data = f.read().decode('utf-8') + if not tl_data: + tl_data = [] + else: + tl_data = tl_data.splitlines() + self.modules = tl_data + return metadata + + def __repr__(self): + return '' % (self.name, self.version, self.path) + + def __str__(self): + return "%s %s" % (self.name, self.version) + + def check_installed_files(self): + """ + Checks that the hashes and sizes of the files in ``RECORD`` are + matched by the files themselves. Returns a (possibly empty) list of + mismatches. Each entry in the mismatch list will be a tuple consisting + of the path, 'exists', 'size' or 'hash' according to what didn't match + (existence is checked first, then size, then hash), the expected + value and the actual value. + """ + mismatches = [] + record_path = os.path.join(self.path, 'installed-files.txt') + if os.path.exists(record_path): + for path, _, _ in self.list_installed_files(): + if path == record_path: + continue + if not os.path.exists(path): + mismatches.append((path, 'exists', True, False)) + return mismatches + + def list_installed_files(self): + """ + Iterates over the ``installed-files.txt`` entries and returns a tuple + ``(path, hash, size)`` for each line. + + :returns: a list of (path, hash, size) + """ + + def _md5(path): + f = open(path, 'rb') + try: + content = f.read() + finally: + f.close() + return hashlib.md5(content).hexdigest() + + def _size(path): + return os.stat(path).st_size + + record_path = os.path.join(self.path, 'installed-files.txt') + result = [] + if os.path.exists(record_path): + with codecs.open(record_path, 'r', encoding='utf-8') as f: + for line in f: + line = line.strip() + p = os.path.normpath(os.path.join(self.path, line)) + # "./" is present as a marker between installed files + # and installation metadata files + if not os.path.exists(p): + logger.warning('Non-existent file: %s', p) + if p.endswith(('.pyc', '.pyo')): + continue + # otherwise fall through and fail + if not os.path.isdir(p): + result.append((p, _md5(p), _size(p))) + result.append((record_path, None, None)) + return result + + def list_distinfo_files(self, absolute=False): + """ + Iterates over the ``installed-files.txt`` entries and returns paths for + each line if the path is pointing to a file located in the + ``.egg-info`` directory or one of its subdirectories. + + :parameter absolute: If *absolute* is ``True``, each returned path is + transformed into a local absolute path. Otherwise the + raw value from ``installed-files.txt`` is returned. + :type absolute: boolean + :returns: iterator of paths + """ + record_path = os.path.join(self.path, 'installed-files.txt') + if os.path.exists(record_path): + skip = True + with codecs.open(record_path, 'r', encoding='utf-8') as f: + for line in f: + line = line.strip() + if line == './': + skip = False + continue + if not skip: + p = os.path.normpath(os.path.join(self.path, line)) + if p.startswith(self.path): + if absolute: + yield p + else: + yield line + + def __eq__(self, other): + return (isinstance(other, EggInfoDistribution) and self.path == other.path) + + # See http://docs.python.org/reference/datamodel#object.__hash__ + __hash__ = object.__hash__ + + +new_dist_class = InstalledDistribution +old_dist_class = EggInfoDistribution + + +class DependencyGraph(object): + """ + Represents a dependency graph between distributions. + + The dependency relationships are stored in an ``adjacency_list`` that maps + distributions to a list of ``(other, label)`` tuples where ``other`` + is a distribution and the edge is labeled with ``label`` (i.e. the version + specifier, if such was provided). Also, for more efficient traversal, for + every distribution ``x``, a list of predecessors is kept in + ``reverse_list[x]``. An edge from distribution ``a`` to + distribution ``b`` means that ``a`` depends on ``b``. If any missing + dependencies are found, they are stored in ``missing``, which is a + dictionary that maps distributions to a list of requirements that were not + provided by any other distributions. + """ + + def __init__(self): + self.adjacency_list = {} + self.reverse_list = {} + self.missing = {} + + def add_distribution(self, distribution): + """Add the *distribution* to the graph. + + :type distribution: :class:`distutils2.database.InstalledDistribution` + or :class:`distutils2.database.EggInfoDistribution` + """ + self.adjacency_list[distribution] = [] + self.reverse_list[distribution] = [] + # self.missing[distribution] = [] + + def add_edge(self, x, y, label=None): + """Add an edge from distribution *x* to distribution *y* with the given + *label*. + + :type x: :class:`distutils2.database.InstalledDistribution` or + :class:`distutils2.database.EggInfoDistribution` + :type y: :class:`distutils2.database.InstalledDistribution` or + :class:`distutils2.database.EggInfoDistribution` + :type label: ``str`` or ``None`` + """ + self.adjacency_list[x].append((y, label)) + # multiple edges are allowed, so be careful + if x not in self.reverse_list[y]: + self.reverse_list[y].append(x) + + def add_missing(self, distribution, requirement): + """ + Add a missing *requirement* for the given *distribution*. + + :type distribution: :class:`distutils2.database.InstalledDistribution` + or :class:`distutils2.database.EggInfoDistribution` + :type requirement: ``str`` + """ + logger.debug('%s missing %r', distribution, requirement) + self.missing.setdefault(distribution, []).append(requirement) + + def _repr_dist(self, dist): + return '%s %s' % (dist.name, dist.version) + + def repr_node(self, dist, level=1): + """Prints only a subgraph""" + output = [self._repr_dist(dist)] + for other, label in self.adjacency_list[dist]: + dist = self._repr_dist(other) + if label is not None: + dist = '%s [%s]' % (dist, label) + output.append(' ' * level + str(dist)) + suboutput = self.repr_node(other, level + 1) + subs = suboutput.split('\n') + output.extend(subs[1:]) + return '\n'.join(output) + + def to_dot(self, f, skip_disconnected=True): + """Writes a DOT output for the graph to the provided file *f*. + + If *skip_disconnected* is set to ``True``, then all distributions + that are not dependent on any other distribution are skipped. + + :type f: has to support ``file``-like operations + :type skip_disconnected: ``bool`` + """ + disconnected = [] + + f.write("digraph dependencies {\n") + for dist, adjs in self.adjacency_list.items(): + if len(adjs) == 0 and not skip_disconnected: + disconnected.append(dist) + for other, label in adjs: + if label is not None: + f.write('"%s" -> "%s" [label="%s"]\n' % (dist.name, other.name, label)) + else: + f.write('"%s" -> "%s"\n' % (dist.name, other.name)) + if not skip_disconnected and len(disconnected) > 0: + f.write('subgraph disconnected {\n') + f.write('label = "Disconnected"\n') + f.write('bgcolor = red\n') + + for dist in disconnected: + f.write('"%s"' % dist.name) + f.write('\n') + f.write('}\n') + f.write('}\n') + + def topological_sort(self): + """ + Perform a topological sort of the graph. + :return: A tuple, the first element of which is a topologically sorted + list of distributions, and the second element of which is a + list of distributions that cannot be sorted because they have + circular dependencies and so form a cycle. + """ + result = [] + # Make a shallow copy of the adjacency list + alist = {} + for k, v in self.adjacency_list.items(): + alist[k] = v[:] + while True: + # See what we can remove in this run + to_remove = [] + for k, v in list(alist.items())[:]: + if not v: + to_remove.append(k) + del alist[k] + if not to_remove: + # What's left in alist (if anything) is a cycle. + break + # Remove from the adjacency list of others + for k, v in alist.items(): + alist[k] = [(d, r) for d, r in v if d not in to_remove] + logger.debug('Moving to result: %s', ['%s (%s)' % (d.name, d.version) for d in to_remove]) + result.extend(to_remove) + return result, list(alist.keys()) + + def __repr__(self): + """Representation of the graph""" + output = [] + for dist, adjs in self.adjacency_list.items(): + output.append(self.repr_node(dist)) + return '\n'.join(output) + + +def make_graph(dists, scheme='default'): + """Makes a dependency graph from the given distributions. + + :parameter dists: a list of distributions + :type dists: list of :class:`distutils2.database.InstalledDistribution` and + :class:`distutils2.database.EggInfoDistribution` instances + :rtype: a :class:`DependencyGraph` instance + """ + scheme = get_scheme(scheme) + graph = DependencyGraph() + provided = {} # maps names to lists of (version, dist) tuples + + # first, build the graph and find out what's provided + for dist in dists: + graph.add_distribution(dist) + + for p in dist.provides: + name, version = parse_name_and_version(p) + logger.debug('Add to provided: %s, %s, %s', name, version, dist) + provided.setdefault(name, []).append((version, dist)) + + # now make the edges + for dist in dists: + requires = (dist.run_requires | dist.meta_requires | dist.build_requires | dist.dev_requires) + for req in requires: + try: + matcher = scheme.matcher(req) + except UnsupportedVersionError: + # XXX compat-mode if cannot read the version + logger.warning('could not read version %r - using name only', req) + name = req.split()[0] + matcher = scheme.matcher(name) + + name = matcher.key # case-insensitive + + matched = False + if name in provided: + for version, provider in provided[name]: + try: + match = matcher.match(version) + except UnsupportedVersionError: + match = False + + if match: + graph.add_edge(dist, provider, req) + matched = True + break + if not matched: + graph.add_missing(dist, req) + return graph + + +def get_dependent_dists(dists, dist): + """Recursively generate a list of distributions from *dists* that are + dependent on *dist*. + + :param dists: a list of distributions + :param dist: a distribution, member of *dists* for which we are interested + """ + if dist not in dists: + raise DistlibException('given distribution %r is not a member ' + 'of the list' % dist.name) + graph = make_graph(dists) + + dep = [dist] # dependent distributions + todo = graph.reverse_list[dist] # list of nodes we should inspect + + while todo: + d = todo.pop() + dep.append(d) + for succ in graph.reverse_list[d]: + if succ not in dep: + todo.append(succ) + + dep.pop(0) # remove dist from dep, was there to prevent infinite loops + return dep + + +def get_required_dists(dists, dist): + """Recursively generate a list of distributions from *dists* that are + required by *dist*. + + :param dists: a list of distributions + :param dist: a distribution, member of *dists* for which we are interested + in finding the dependencies. + """ + if dist not in dists: + raise DistlibException('given distribution %r is not a member ' + 'of the list' % dist.name) + graph = make_graph(dists) + + req = set() # required distributions + todo = graph.adjacency_list[dist] # list of nodes we should inspect + seen = set(t[0] for t in todo) # already added to todo + + while todo: + d = todo.pop()[0] + req.add(d) + pred_list = graph.adjacency_list[d] + for pred in pred_list: + d = pred[0] + if d not in req and d not in seen: + seen.add(d) + todo.append(pred) + return req + + +def make_dist(name, version, **kwargs): + """ + A convenience method for making a dist given just a name and version. + """ + summary = kwargs.pop('summary', 'Placeholder for summary') + md = Metadata(**kwargs) + md.name = name + md.version = version + md.summary = summary or 'Placeholder for summary' + return Distribution(md) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/index.py b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/index.py new file mode 100644 index 0000000..56cd286 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/index.py @@ -0,0 +1,508 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013-2023 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +import hashlib +import logging +import os +import shutil +import subprocess +import tempfile +try: + from threading import Thread +except ImportError: # pragma: no cover + from dummy_threading import Thread + +from . import DistlibException +from .compat import (HTTPBasicAuthHandler, Request, HTTPPasswordMgr, + urlparse, build_opener, string_types) +from .util import zip_dir, ServerProxy + +logger = logging.getLogger(__name__) + +DEFAULT_INDEX = 'https://pypi.org/pypi' +DEFAULT_REALM = 'pypi' + + +class PackageIndex(object): + """ + This class represents a package index compatible with PyPI, the Python + Package Index. + """ + + boundary = b'----------ThIs_Is_tHe_distlib_index_bouNdaRY_$' + + def __init__(self, url=None): + """ + Initialise an instance. + + :param url: The URL of the index. If not specified, the URL for PyPI is + used. + """ + self.url = url or DEFAULT_INDEX + self.read_configuration() + scheme, netloc, path, params, query, frag = urlparse(self.url) + if params or query or frag or scheme not in ('http', 'https'): + raise DistlibException('invalid repository: %s' % self.url) + self.password_handler = None + self.ssl_verifier = None + self.gpg = None + self.gpg_home = None + with open(os.devnull, 'w') as sink: + # Use gpg by default rather than gpg2, as gpg2 insists on + # prompting for passwords + for s in ('gpg', 'gpg2'): + try: + rc = subprocess.check_call([s, '--version'], stdout=sink, + stderr=sink) + if rc == 0: + self.gpg = s + break + except OSError: + pass + + def _get_pypirc_command(self): + """ + Get the distutils command for interacting with PyPI configurations. + :return: the command. + """ + from .util import _get_pypirc_command as cmd + return cmd() + + def read_configuration(self): + """ + Read the PyPI access configuration as supported by distutils. This populates + ``username``, ``password``, ``realm`` and ``url`` attributes from the + configuration. + """ + from .util import _load_pypirc + cfg = _load_pypirc(self) + self.username = cfg.get('username') + self.password = cfg.get('password') + self.realm = cfg.get('realm', 'pypi') + self.url = cfg.get('repository', self.url) + + def save_configuration(self): + """ + Save the PyPI access configuration. You must have set ``username`` and + ``password`` attributes before calling this method. + """ + self.check_credentials() + from .util import _store_pypirc + _store_pypirc(self) + + def check_credentials(self): + """ + Check that ``username`` and ``password`` have been set, and raise an + exception if not. + """ + if self.username is None or self.password is None: + raise DistlibException('username and password must be set') + pm = HTTPPasswordMgr() + _, netloc, _, _, _, _ = urlparse(self.url) + pm.add_password(self.realm, netloc, self.username, self.password) + self.password_handler = HTTPBasicAuthHandler(pm) + + def register(self, metadata): # pragma: no cover + """ + Register a distribution on PyPI, using the provided metadata. + + :param metadata: A :class:`Metadata` instance defining at least a name + and version number for the distribution to be + registered. + :return: The HTTP response received from PyPI upon submission of the + request. + """ + self.check_credentials() + metadata.validate() + d = metadata.todict() + d[':action'] = 'verify' + request = self.encode_request(d.items(), []) + self.send_request(request) + d[':action'] = 'submit' + request = self.encode_request(d.items(), []) + return self.send_request(request) + + def _reader(self, name, stream, outbuf): + """ + Thread runner for reading lines of from a subprocess into a buffer. + + :param name: The logical name of the stream (used for logging only). + :param stream: The stream to read from. This will typically a pipe + connected to the output stream of a subprocess. + :param outbuf: The list to append the read lines to. + """ + while True: + s = stream.readline() + if not s: + break + s = s.decode('utf-8').rstrip() + outbuf.append(s) + logger.debug('%s: %s' % (name, s)) + stream.close() + + def get_sign_command(self, filename, signer, sign_password, keystore=None): # pragma: no cover + """ + Return a suitable command for signing a file. + + :param filename: The pathname to the file to be signed. + :param signer: The identifier of the signer of the file. + :param sign_password: The passphrase for the signer's + private key used for signing. + :param keystore: The path to a directory which contains the keys + used in verification. If not specified, the + instance's ``gpg_home`` attribute is used instead. + :return: The signing command as a list suitable to be + passed to :class:`subprocess.Popen`. + """ + cmd = [self.gpg, '--status-fd', '2', '--no-tty'] + if keystore is None: + keystore = self.gpg_home + if keystore: + cmd.extend(['--homedir', keystore]) + if sign_password is not None: + cmd.extend(['--batch', '--passphrase-fd', '0']) + td = tempfile.mkdtemp() + sf = os.path.join(td, os.path.basename(filename) + '.asc') + cmd.extend(['--detach-sign', '--armor', '--local-user', + signer, '--output', sf, filename]) + logger.debug('invoking: %s', ' '.join(cmd)) + return cmd, sf + + def run_command(self, cmd, input_data=None): + """ + Run a command in a child process , passing it any input data specified. + + :param cmd: The command to run. + :param input_data: If specified, this must be a byte string containing + data to be sent to the child process. + :return: A tuple consisting of the subprocess' exit code, a list of + lines read from the subprocess' ``stdout``, and a list of + lines read from the subprocess' ``stderr``. + """ + kwargs = { + 'stdout': subprocess.PIPE, + 'stderr': subprocess.PIPE, + } + if input_data is not None: + kwargs['stdin'] = subprocess.PIPE + stdout = [] + stderr = [] + p = subprocess.Popen(cmd, **kwargs) + # We don't use communicate() here because we may need to + # get clever with interacting with the command + t1 = Thread(target=self._reader, args=('stdout', p.stdout, stdout)) + t1.start() + t2 = Thread(target=self._reader, args=('stderr', p.stderr, stderr)) + t2.start() + if input_data is not None: + p.stdin.write(input_data) + p.stdin.close() + + p.wait() + t1.join() + t2.join() + return p.returncode, stdout, stderr + + def sign_file(self, filename, signer, sign_password, keystore=None): # pragma: no cover + """ + Sign a file. + + :param filename: The pathname to the file to be signed. + :param signer: The identifier of the signer of the file. + :param sign_password: The passphrase for the signer's + private key used for signing. + :param keystore: The path to a directory which contains the keys + used in signing. If not specified, the instance's + ``gpg_home`` attribute is used instead. + :return: The absolute pathname of the file where the signature is + stored. + """ + cmd, sig_file = self.get_sign_command(filename, signer, sign_password, + keystore) + rc, stdout, stderr = self.run_command(cmd, + sign_password.encode('utf-8')) + if rc != 0: + raise DistlibException('sign command failed with error ' + 'code %s' % rc) + return sig_file + + def upload_file(self, metadata, filename, signer=None, sign_password=None, + filetype='sdist', pyversion='source', keystore=None): + """ + Upload a release file to the index. + + :param metadata: A :class:`Metadata` instance defining at least a name + and version number for the file to be uploaded. + :param filename: The pathname of the file to be uploaded. + :param signer: The identifier of the signer of the file. + :param sign_password: The passphrase for the signer's + private key used for signing. + :param filetype: The type of the file being uploaded. This is the + distutils command which produced that file, e.g. + ``sdist`` or ``bdist_wheel``. + :param pyversion: The version of Python which the release relates + to. For code compatible with any Python, this would + be ``source``, otherwise it would be e.g. ``3.2``. + :param keystore: The path to a directory which contains the keys + used in signing. If not specified, the instance's + ``gpg_home`` attribute is used instead. + :return: The HTTP response received from PyPI upon submission of the + request. + """ + self.check_credentials() + if not os.path.exists(filename): + raise DistlibException('not found: %s' % filename) + metadata.validate() + d = metadata.todict() + sig_file = None + if signer: + if not self.gpg: + logger.warning('no signing program available - not signed') + else: + sig_file = self.sign_file(filename, signer, sign_password, + keystore) + with open(filename, 'rb') as f: + file_data = f.read() + md5_digest = hashlib.md5(file_data).hexdigest() + sha256_digest = hashlib.sha256(file_data).hexdigest() + d.update({ + ':action': 'file_upload', + 'protocol_version': '1', + 'filetype': filetype, + 'pyversion': pyversion, + 'md5_digest': md5_digest, + 'sha256_digest': sha256_digest, + }) + files = [('content', os.path.basename(filename), file_data)] + if sig_file: + with open(sig_file, 'rb') as f: + sig_data = f.read() + files.append(('gpg_signature', os.path.basename(sig_file), + sig_data)) + shutil.rmtree(os.path.dirname(sig_file)) + request = self.encode_request(d.items(), files) + return self.send_request(request) + + def upload_documentation(self, metadata, doc_dir): # pragma: no cover + """ + Upload documentation to the index. + + :param metadata: A :class:`Metadata` instance defining at least a name + and version number for the documentation to be + uploaded. + :param doc_dir: The pathname of the directory which contains the + documentation. This should be the directory that + contains the ``index.html`` for the documentation. + :return: The HTTP response received from PyPI upon submission of the + request. + """ + self.check_credentials() + if not os.path.isdir(doc_dir): + raise DistlibException('not a directory: %r' % doc_dir) + fn = os.path.join(doc_dir, 'index.html') + if not os.path.exists(fn): + raise DistlibException('not found: %r' % fn) + metadata.validate() + name, version = metadata.name, metadata.version + zip_data = zip_dir(doc_dir).getvalue() + fields = [(':action', 'doc_upload'), + ('name', name), ('version', version)] + files = [('content', name, zip_data)] + request = self.encode_request(fields, files) + return self.send_request(request) + + def get_verify_command(self, signature_filename, data_filename, + keystore=None): + """ + Return a suitable command for verifying a file. + + :param signature_filename: The pathname to the file containing the + signature. + :param data_filename: The pathname to the file containing the + signed data. + :param keystore: The path to a directory which contains the keys + used in verification. If not specified, the + instance's ``gpg_home`` attribute is used instead. + :return: The verifying command as a list suitable to be + passed to :class:`subprocess.Popen`. + """ + cmd = [self.gpg, '--status-fd', '2', '--no-tty'] + if keystore is None: + keystore = self.gpg_home + if keystore: + cmd.extend(['--homedir', keystore]) + cmd.extend(['--verify', signature_filename, data_filename]) + logger.debug('invoking: %s', ' '.join(cmd)) + return cmd + + def verify_signature(self, signature_filename, data_filename, + keystore=None): + """ + Verify a signature for a file. + + :param signature_filename: The pathname to the file containing the + signature. + :param data_filename: The pathname to the file containing the + signed data. + :param keystore: The path to a directory which contains the keys + used in verification. If not specified, the + instance's ``gpg_home`` attribute is used instead. + :return: True if the signature was verified, else False. + """ + if not self.gpg: + raise DistlibException('verification unavailable because gpg ' + 'unavailable') + cmd = self.get_verify_command(signature_filename, data_filename, + keystore) + rc, stdout, stderr = self.run_command(cmd) + if rc not in (0, 1): + raise DistlibException('verify command failed with error code %s' % rc) + return rc == 0 + + def download_file(self, url, destfile, digest=None, reporthook=None): + """ + This is a convenience method for downloading a file from an URL. + Normally, this will be a file from the index, though currently + no check is made for this (i.e. a file can be downloaded from + anywhere). + + The method is just like the :func:`urlretrieve` function in the + standard library, except that it allows digest computation to be + done during download and checking that the downloaded data + matched any expected value. + + :param url: The URL of the file to be downloaded (assumed to be + available via an HTTP GET request). + :param destfile: The pathname where the downloaded file is to be + saved. + :param digest: If specified, this must be a (hasher, value) + tuple, where hasher is the algorithm used (e.g. + ``'md5'``) and ``value`` is the expected value. + :param reporthook: The same as for :func:`urlretrieve` in the + standard library. + """ + if digest is None: + digester = None + logger.debug('No digest specified') + else: + if isinstance(digest, (list, tuple)): + hasher, digest = digest + else: + hasher = 'md5' + digester = getattr(hashlib, hasher)() + logger.debug('Digest specified: %s' % digest) + # The following code is equivalent to urlretrieve. + # We need to do it this way so that we can compute the + # digest of the file as we go. + with open(destfile, 'wb') as dfp: + # addinfourl is not a context manager on 2.x + # so we have to use try/finally + sfp = self.send_request(Request(url)) + try: + headers = sfp.info() + blocksize = 8192 + size = -1 + read = 0 + blocknum = 0 + if "content-length" in headers: + size = int(headers["Content-Length"]) + if reporthook: + reporthook(blocknum, blocksize, size) + while True: + block = sfp.read(blocksize) + if not block: + break + read += len(block) + dfp.write(block) + if digester: + digester.update(block) + blocknum += 1 + if reporthook: + reporthook(blocknum, blocksize, size) + finally: + sfp.close() + + # check that we got the whole file, if we can + if size >= 0 and read < size: + raise DistlibException( + 'retrieval incomplete: got only %d out of %d bytes' + % (read, size)) + # if we have a digest, it must match. + if digester: + actual = digester.hexdigest() + if digest != actual: + raise DistlibException('%s digest mismatch for %s: expected ' + '%s, got %s' % (hasher, destfile, + digest, actual)) + logger.debug('Digest verified: %s', digest) + + def send_request(self, req): + """ + Send a standard library :class:`Request` to PyPI and return its + response. + + :param req: The request to send. + :return: The HTTP response from PyPI (a standard library HTTPResponse). + """ + handlers = [] + if self.password_handler: + handlers.append(self.password_handler) + if self.ssl_verifier: + handlers.append(self.ssl_verifier) + opener = build_opener(*handlers) + return opener.open(req) + + def encode_request(self, fields, files): + """ + Encode fields and files for posting to an HTTP server. + + :param fields: The fields to send as a list of (fieldname, value) + tuples. + :param files: The files to send as a list of (fieldname, filename, + file_bytes) tuple. + """ + # Adapted from packaging, which in turn was adapted from + # http://code.activestate.com/recipes/146306 + + parts = [] + boundary = self.boundary + for k, values in fields: + if not isinstance(values, (list, tuple)): + values = [values] + + for v in values: + parts.extend(( + b'--' + boundary, + ('Content-Disposition: form-data; name="%s"' % + k).encode('utf-8'), + b'', + v.encode('utf-8'))) + for key, filename, value in files: + parts.extend(( + b'--' + boundary, + ('Content-Disposition: form-data; name="%s"; filename="%s"' % + (key, filename)).encode('utf-8'), + b'', + value)) + + parts.extend((b'--' + boundary + b'--', b'')) + + body = b'\r\n'.join(parts) + ct = b'multipart/form-data; boundary=' + boundary + headers = { + 'Content-type': ct, + 'Content-length': str(len(body)) + } + return Request(self.url, body, headers) + + def search(self, terms, operator=None): # pragma: no cover + if isinstance(terms, string_types): + terms = {'name': terms} + rpc_proxy = ServerProxy(self.url, timeout=3.0) + try: + return rpc_proxy.search(terms, operator or 'and') + finally: + rpc_proxy('close')() diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/locators.py b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/locators.py new file mode 100644 index 0000000..222c1bf --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/locators.py @@ -0,0 +1,1295 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2023 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# + +import gzip +from io import BytesIO +import json +import logging +import os +import posixpath +import re +try: + import threading +except ImportError: # pragma: no cover + import dummy_threading as threading +import zlib + +from . import DistlibException +from .compat import (urljoin, urlparse, urlunparse, url2pathname, pathname2url, queue, quote, unescape, build_opener, + HTTPRedirectHandler as BaseRedirectHandler, text_type, Request, HTTPError, URLError) +from .database import Distribution, DistributionPath, make_dist +from .metadata import Metadata, MetadataInvalidError +from .util import (cached_property, ensure_slash, split_filename, get_project_data, parse_requirement, + parse_name_and_version, ServerProxy, normalize_name) +from .version import get_scheme, UnsupportedVersionError +from .wheel import Wheel, is_compatible + +logger = logging.getLogger(__name__) + +HASHER_HASH = re.compile(r'^(\w+)=([a-f0-9]+)') +CHARSET = re.compile(r';\s*charset\s*=\s*(.*)\s*$', re.I) +HTML_CONTENT_TYPE = re.compile('text/html|application/x(ht)?ml') +DEFAULT_INDEX = 'https://pypi.org/pypi' + + +def get_all_distribution_names(url=None): + """ + Return all distribution names known by an index. + :param url: The URL of the index. + :return: A list of all known distribution names. + """ + if url is None: + url = DEFAULT_INDEX + client = ServerProxy(url, timeout=3.0) + try: + return client.list_packages() + finally: + client('close')() + + +class RedirectHandler(BaseRedirectHandler): + """ + A class to work around a bug in some Python 3.2.x releases. + """ + + # There's a bug in the base version for some 3.2.x + # (e.g. 3.2.2 on Ubuntu Oneiric). If a Location header + # returns e.g. /abc, it bails because it says the scheme '' + # is bogus, when actually it should use the request's + # URL for the scheme. See Python issue #13696. + def http_error_302(self, req, fp, code, msg, headers): + # Some servers (incorrectly) return multiple Location headers + # (so probably same goes for URI). Use first header. + newurl = None + for key in ('location', 'uri'): + if key in headers: + newurl = headers[key] + break + if newurl is None: # pragma: no cover + return + urlparts = urlparse(newurl) + if urlparts.scheme == '': + newurl = urljoin(req.get_full_url(), newurl) + if hasattr(headers, 'replace_header'): + headers.replace_header(key, newurl) + else: + headers[key] = newurl + return BaseRedirectHandler.http_error_302(self, req, fp, code, msg, headers) + + http_error_301 = http_error_303 = http_error_307 = http_error_302 + + +class Locator(object): + """ + A base class for locators - things that locate distributions. + """ + source_extensions = ('.tar.gz', '.tar.bz2', '.tar', '.zip', '.tgz', '.tbz') + binary_extensions = ('.egg', '.exe', '.whl') + excluded_extensions = ('.pdf', ) + + # A list of tags indicating which wheels you want to match. The default + # value of None matches against the tags compatible with the running + # Python. If you want to match other values, set wheel_tags on a locator + # instance to a list of tuples (pyver, abi, arch) which you want to match. + wheel_tags = None + + downloadable_extensions = source_extensions + ('.whl', ) + + def __init__(self, scheme='default'): + """ + Initialise an instance. + :param scheme: Because locators look for most recent versions, they + need to know the version scheme to use. This specifies + the current PEP-recommended scheme - use ``'legacy'`` + if you need to support existing distributions on PyPI. + """ + self._cache = {} + self.scheme = scheme + # Because of bugs in some of the handlers on some of the platforms, + # we use our own opener rather than just using urlopen. + self.opener = build_opener(RedirectHandler()) + # If get_project() is called from locate(), the matcher instance + # is set from the requirement passed to locate(). See issue #18 for + # why this can be useful to know. + self.matcher = None + self.errors = queue.Queue() + + def get_errors(self): + """ + Return any errors which have occurred. + """ + result = [] + while not self.errors.empty(): # pragma: no cover + try: + e = self.errors.get(False) + result.append(e) + except self.errors.Empty: + continue + self.errors.task_done() + return result + + def clear_errors(self): + """ + Clear any errors which may have been logged. + """ + # Just get the errors and throw them away + self.get_errors() + + def clear_cache(self): + self._cache.clear() + + def _get_scheme(self): + return self._scheme + + def _set_scheme(self, value): + self._scheme = value + + scheme = property(_get_scheme, _set_scheme) + + def _get_project(self, name): + """ + For a given project, get a dictionary mapping available versions to Distribution + instances. + + This should be implemented in subclasses. + + If called from a locate() request, self.matcher will be set to a + matcher for the requirement to satisfy, otherwise it will be None. + """ + raise NotImplementedError('Please implement in the subclass') + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + raise NotImplementedError('Please implement in the subclass') + + def get_project(self, name): + """ + For a given project, get a dictionary mapping available versions to Distribution + instances. + + This calls _get_project to do all the work, and just implements a caching layer on top. + """ + if self._cache is None: # pragma: no cover + result = self._get_project(name) + elif name in self._cache: + result = self._cache[name] + else: + self.clear_errors() + result = self._get_project(name) + self._cache[name] = result + return result + + def score_url(self, url): + """ + Give an url a score which can be used to choose preferred URLs + for a given project release. + """ + t = urlparse(url) + basename = posixpath.basename(t.path) + compatible = True + is_wheel = basename.endswith('.whl') + is_downloadable = basename.endswith(self.downloadable_extensions) + if is_wheel: + compatible = is_compatible(Wheel(basename), self.wheel_tags) + return (t.scheme == 'https', 'pypi.org' in t.netloc, is_downloadable, is_wheel, compatible, basename) + + def prefer_url(self, url1, url2): + """ + Choose one of two URLs where both are candidates for distribution + archives for the same version of a distribution (for example, + .tar.gz vs. zip). + + The current implementation favours https:// URLs over http://, archives + from PyPI over those from other locations, wheel compatibility (if a + wheel) and then the archive name. + """ + result = url2 + if url1: + s1 = self.score_url(url1) + s2 = self.score_url(url2) + if s1 > s2: + result = url1 + if result != url2: + logger.debug('Not replacing %r with %r', url1, url2) + else: + logger.debug('Replacing %r with %r', url1, url2) + return result + + def split_filename(self, filename, project_name): + """ + Attempt to split a filename in project name, version and Python version. + """ + return split_filename(filename, project_name) + + def convert_url_to_download_info(self, url, project_name): + """ + See if a URL is a candidate for a download URL for a project (the URL + has typically been scraped from an HTML page). + + If it is, a dictionary is returned with keys "name", "version", + "filename" and "url"; otherwise, None is returned. + """ + + def same_project(name1, name2): + return normalize_name(name1) == normalize_name(name2) + + result = None + scheme, netloc, path, params, query, frag = urlparse(url) + if frag.lower().startswith('egg='): # pragma: no cover + logger.debug('%s: version hint in fragment: %r', project_name, frag) + m = HASHER_HASH.match(frag) + if m: + algo, digest = m.groups() + else: + algo, digest = None, None + origpath = path + if path and path[-1] == '/': # pragma: no cover + path = path[:-1] + if path.endswith('.whl'): + try: + wheel = Wheel(path) + if not is_compatible(wheel, self.wheel_tags): + logger.debug('Wheel not compatible: %s', path) + else: + if project_name is None: + include = True + else: + include = same_project(wheel.name, project_name) + if include: + result = { + 'name': wheel.name, + 'version': wheel.version, + 'filename': wheel.filename, + 'url': urlunparse((scheme, netloc, origpath, params, query, '')), + 'python-version': ', '.join(['.'.join(list(v[2:])) for v in wheel.pyver]), + } + except Exception: # pragma: no cover + logger.warning('invalid path for wheel: %s', path) + elif not path.endswith(self.downloadable_extensions): # pragma: no cover + logger.debug('Not downloadable: %s', path) + else: # downloadable extension + path = filename = posixpath.basename(path) + for ext in self.downloadable_extensions: + if path.endswith(ext): + path = path[:-len(ext)] + t = self.split_filename(path, project_name) + if not t: # pragma: no cover + logger.debug('No match for project/version: %s', path) + else: + name, version, pyver = t + if not project_name or same_project(project_name, name): + result = { + 'name': name, + 'version': version, + 'filename': filename, + 'url': urlunparse((scheme, netloc, origpath, params, query, '')), + } + if pyver: # pragma: no cover + result['python-version'] = pyver + break + if result and algo: + result['%s_digest' % algo] = digest + return result + + def _get_digest(self, info): + """ + Get a digest from a dictionary by looking at a "digests" dictionary + or keys of the form 'algo_digest'. + + Returns a 2-tuple (algo, digest) if found, else None. Currently + looks only for SHA256, then MD5. + """ + result = None + if 'digests' in info: + digests = info['digests'] + for algo in ('sha256', 'md5'): + if algo in digests: + result = (algo, digests[algo]) + break + if not result: + for algo in ('sha256', 'md5'): + key = '%s_digest' % algo + if key in info: + result = (algo, info[key]) + break + return result + + def _update_version_data(self, result, info): + """ + Update a result dictionary (the final result from _get_project) with a + dictionary for a specific version, which typically holds information + gleaned from a filename or URL for an archive for the distribution. + """ + name = info.pop('name') + version = info.pop('version') + if version in result: + dist = result[version] + md = dist.metadata + else: + dist = make_dist(name, version, scheme=self.scheme) + md = dist.metadata + dist.digest = digest = self._get_digest(info) + url = info['url'] + result['digests'][url] = digest + if md.source_url != info['url']: + md.source_url = self.prefer_url(md.source_url, url) + result['urls'].setdefault(version, set()).add(url) + dist.locator = self + result[version] = dist + + def locate(self, requirement, prereleases=False): + """ + Find the most recent distribution which matches the given + requirement. + + :param requirement: A requirement of the form 'foo (1.0)' or perhaps + 'foo (>= 1.0, < 2.0, != 1.3)' + :param prereleases: If ``True``, allow pre-release versions + to be located. Otherwise, pre-release versions + are not returned. + :return: A :class:`Distribution` instance, or ``None`` if no such + distribution could be located. + """ + result = None + r = parse_requirement(requirement) + if r is None: # pragma: no cover + raise DistlibException('Not a valid requirement: %r' % requirement) + scheme = get_scheme(self.scheme) + self.matcher = matcher = scheme.matcher(r.requirement) + logger.debug('matcher: %s (%s)', matcher, type(matcher).__name__) + versions = self.get_project(r.name) + if len(versions) > 2: # urls and digests keys are present + # sometimes, versions are invalid + slist = [] + vcls = matcher.version_class + for k in versions: + if k in ('urls', 'digests'): + continue + try: + if not matcher.match(k): + pass # logger.debug('%s did not match %r', matcher, k) + else: + if prereleases or not vcls(k).is_prerelease: + slist.append(k) + except Exception: # pragma: no cover + logger.warning('error matching %s with %r', matcher, k) + pass # slist.append(k) + if len(slist) > 1: + slist = sorted(slist, key=scheme.key) + if slist: + logger.debug('sorted list: %s', slist) + version = slist[-1] + result = versions[version] + if result: + if r.extras: + result.extras = r.extras + result.download_urls = versions.get('urls', {}).get(version, set()) + d = {} + sd = versions.get('digests', {}) + for url in result.download_urls: + if url in sd: # pragma: no cover + d[url] = sd[url] + result.digests = d + self.matcher = None + return result + + +class PyPIRPCLocator(Locator): + """ + This locator uses XML-RPC to locate distributions. It therefore + cannot be used with simple mirrors (that only mirror file content). + """ + + def __init__(self, url, **kwargs): + """ + Initialise an instance. + + :param url: The URL to use for XML-RPC. + :param kwargs: Passed to the superclass constructor. + """ + super(PyPIRPCLocator, self).__init__(**kwargs) + self.base_url = url + self.client = ServerProxy(url, timeout=3.0) + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + return set(self.client.list_packages()) + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + versions = self.client.package_releases(name, True) + for v in versions: + urls = self.client.release_urls(name, v) + data = self.client.release_data(name, v) + metadata = Metadata(scheme=self.scheme) + metadata.name = data['name'] + metadata.version = data['version'] + metadata.license = data.get('license') + metadata.keywords = data.get('keywords', []) + metadata.summary = data.get('summary') + dist = Distribution(metadata) + if urls: + info = urls[0] + metadata.source_url = info['url'] + dist.digest = self._get_digest(info) + dist.locator = self + result[v] = dist + for info in urls: + url = info['url'] + digest = self._get_digest(info) + result['urls'].setdefault(v, set()).add(url) + result['digests'][url] = digest + return result + + +class PyPIJSONLocator(Locator): + """ + This locator uses PyPI's JSON interface. It's very limited in functionality + and probably not worth using. + """ + + def __init__(self, url, **kwargs): + super(PyPIJSONLocator, self).__init__(**kwargs) + self.base_url = ensure_slash(url) + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + raise NotImplementedError('Not available from this locator') + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + url = urljoin(self.base_url, '%s/json' % quote(name)) + try: + resp = self.opener.open(url) + data = resp.read().decode() # for now + d = json.loads(data) + md = Metadata(scheme=self.scheme) + data = d['info'] + md.name = data['name'] + md.version = data['version'] + md.license = data.get('license') + md.keywords = data.get('keywords', []) + md.summary = data.get('summary') + dist = Distribution(md) + dist.locator = self + # urls = d['urls'] + result[md.version] = dist + for info in d['urls']: + url = info['url'] + dist.download_urls.add(url) + dist.digests[url] = self._get_digest(info) + result['urls'].setdefault(md.version, set()).add(url) + result['digests'][url] = self._get_digest(info) + # Now get other releases + for version, infos in d['releases'].items(): + if version == md.version: + continue # already done + omd = Metadata(scheme=self.scheme) + omd.name = md.name + omd.version = version + odist = Distribution(omd) + odist.locator = self + result[version] = odist + for info in infos: + url = info['url'] + odist.download_urls.add(url) + odist.digests[url] = self._get_digest(info) + result['urls'].setdefault(version, set()).add(url) + result['digests'][url] = self._get_digest(info) + + +# for info in urls: +# md.source_url = info['url'] +# dist.digest = self._get_digest(info) +# dist.locator = self +# for info in urls: +# url = info['url'] +# result['urls'].setdefault(md.version, set()).add(url) +# result['digests'][url] = self._get_digest(info) + except Exception as e: + self.errors.put(text_type(e)) + logger.exception('JSON fetch failed: %s', e) + return result + + +class Page(object): + """ + This class represents a scraped HTML page. + """ + # The following slightly hairy-looking regex just looks for the contents of + # an anchor link, which has an attribute "href" either immediately preceded + # or immediately followed by a "rel" attribute. The attribute values can be + # declared with double quotes, single quotes or no quotes - which leads to + # the length of the expression. + _href = re.compile( + """ +(rel\\s*=\\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\\s\n]*))\\s+)? +href\\s*=\\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\\s\n]*)) +(\\s+rel\\s*=\\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\\s\n]*)))? +""", re.I | re.S | re.X) + _base = re.compile(r"""]+)""", re.I | re.S) + + def __init__(self, data, url): + """ + Initialise an instance with the Unicode page contents and the URL they + came from. + """ + self.data = data + self.base_url = self.url = url + m = self._base.search(self.data) + if m: + self.base_url = m.group(1) + + _clean_re = re.compile(r'[^a-z0-9$&+,/:;=?@.#%_\\|-]', re.I) + + @cached_property + def links(self): + """ + Return the URLs of all the links on a page together with information + about their "rel" attribute, for determining which ones to treat as + downloads and which ones to queue for further scraping. + """ + + def clean(url): + "Tidy up an URL." + scheme, netloc, path, params, query, frag = urlparse(url) + return urlunparse((scheme, netloc, quote(path), params, query, frag)) + + result = set() + for match in self._href.finditer(self.data): + d = match.groupdict('') + rel = (d['rel1'] or d['rel2'] or d['rel3'] or d['rel4'] or d['rel5'] or d['rel6']) + url = d['url1'] or d['url2'] or d['url3'] + url = urljoin(self.base_url, url) + url = unescape(url) + url = self._clean_re.sub(lambda m: '%%%2x' % ord(m.group(0)), url) + result.add((url, rel)) + # We sort the result, hoping to bring the most recent versions + # to the front + result = sorted(result, key=lambda t: t[0], reverse=True) + return result + + +class SimpleScrapingLocator(Locator): + """ + A locator which scrapes HTML pages to locate downloads for a distribution. + This runs multiple threads to do the I/O; performance is at least as good + as pip's PackageFinder, which works in an analogous fashion. + """ + + # These are used to deal with various Content-Encoding schemes. + decoders = { + 'deflate': zlib.decompress, + 'gzip': lambda b: gzip.GzipFile(fileobj=BytesIO(b)).read(), + 'none': lambda b: b, + } + + def __init__(self, url, timeout=None, num_workers=10, **kwargs): + """ + Initialise an instance. + :param url: The root URL to use for scraping. + :param timeout: The timeout, in seconds, to be applied to requests. + This defaults to ``None`` (no timeout specified). + :param num_workers: The number of worker threads you want to do I/O, + This defaults to 10. + :param kwargs: Passed to the superclass. + """ + super(SimpleScrapingLocator, self).__init__(**kwargs) + self.base_url = ensure_slash(url) + self.timeout = timeout + self._page_cache = {} + self._seen = set() + self._to_fetch = queue.Queue() + self._bad_hosts = set() + self.skip_externals = False + self.num_workers = num_workers + self._lock = threading.RLock() + # See issue #45: we need to be resilient when the locator is used + # in a thread, e.g. with concurrent.futures. We can't use self._lock + # as it is for coordinating our internal threads - the ones created + # in _prepare_threads. + self._gplock = threading.RLock() + self.platform_check = False # See issue #112 + + def _prepare_threads(self): + """ + Threads are created only when get_project is called, and terminate + before it returns. They are there primarily to parallelise I/O (i.e. + fetching web pages). + """ + self._threads = [] + for i in range(self.num_workers): + t = threading.Thread(target=self._fetch) + t.daemon = True + t.start() + self._threads.append(t) + + def _wait_threads(self): + """ + Tell all the threads to terminate (by sending a sentinel value) and + wait for them to do so. + """ + # Note that you need two loops, since you can't say which + # thread will get each sentinel + for t in self._threads: + self._to_fetch.put(None) # sentinel + for t in self._threads: + t.join() + self._threads = [] + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + with self._gplock: + self.result = result + self.project_name = name + url = urljoin(self.base_url, '%s/' % quote(name)) + self._seen.clear() + self._page_cache.clear() + self._prepare_threads() + try: + logger.debug('Queueing %s', url) + self._to_fetch.put(url) + self._to_fetch.join() + finally: + self._wait_threads() + del self.result + return result + + platform_dependent = re.compile(r'\b(linux_(i\d86|x86_64|arm\w+)|' + r'win(32|_amd64)|macosx_?\d+)\b', re.I) + + def _is_platform_dependent(self, url): + """ + Does an URL refer to a platform-specific download? + """ + return self.platform_dependent.search(url) + + def _process_download(self, url): + """ + See if an URL is a suitable download for a project. + + If it is, register information in the result dictionary (for + _get_project) about the specific version it's for. + + Note that the return value isn't actually used other than as a boolean + value. + """ + if self.platform_check and self._is_platform_dependent(url): + info = None + else: + info = self.convert_url_to_download_info(url, self.project_name) + logger.debug('process_download: %s -> %s', url, info) + if info: + with self._lock: # needed because self.result is shared + self._update_version_data(self.result, info) + return info + + def _should_queue(self, link, referrer, rel): + """ + Determine whether a link URL from a referring page and with a + particular "rel" attribute should be queued for scraping. + """ + scheme, netloc, path, _, _, _ = urlparse(link) + if path.endswith(self.source_extensions + self.binary_extensions + self.excluded_extensions): + result = False + elif self.skip_externals and not link.startswith(self.base_url): + result = False + elif not referrer.startswith(self.base_url): + result = False + elif rel not in ('homepage', 'download'): + result = False + elif scheme not in ('http', 'https', 'ftp'): + result = False + elif self._is_platform_dependent(link): + result = False + else: + host = netloc.split(':', 1)[0] + if host.lower() == 'localhost': + result = False + else: + result = True + logger.debug('should_queue: %s (%s) from %s -> %s', link, rel, referrer, result) + return result + + def _fetch(self): + """ + Get a URL to fetch from the work queue, get the HTML page, examine its + links for download candidates and candidates for further scraping. + + This is a handy method to run in a thread. + """ + while True: + url = self._to_fetch.get() + try: + if url: + page = self.get_page(url) + if page is None: # e.g. after an error + continue + for link, rel in page.links: + if link not in self._seen: + try: + self._seen.add(link) + if (not self._process_download(link) and self._should_queue(link, url, rel)): + logger.debug('Queueing %s from %s', link, url) + self._to_fetch.put(link) + except MetadataInvalidError: # e.g. invalid versions + pass + except Exception as e: # pragma: no cover + self.errors.put(text_type(e)) + finally: + # always do this, to avoid hangs :-) + self._to_fetch.task_done() + if not url: + # logger.debug('Sentinel seen, quitting.') + break + + def get_page(self, url): + """ + Get the HTML for an URL, possibly from an in-memory cache. + + XXX TODO Note: this cache is never actually cleared. It's assumed that + the data won't get stale over the lifetime of a locator instance (not + necessarily true for the default_locator). + """ + # http://peak.telecommunity.com/DevCenter/EasyInstall#package-index-api + scheme, netloc, path, _, _, _ = urlparse(url) + if scheme == 'file' and os.path.isdir(url2pathname(path)): + url = urljoin(ensure_slash(url), 'index.html') + + if url in self._page_cache: + result = self._page_cache[url] + logger.debug('Returning %s from cache: %s', url, result) + else: + host = netloc.split(':', 1)[0] + result = None + if host in self._bad_hosts: + logger.debug('Skipping %s due to bad host %s', url, host) + else: + req = Request(url, headers={'Accept-encoding': 'identity'}) + try: + logger.debug('Fetching %s', url) + resp = self.opener.open(req, timeout=self.timeout) + logger.debug('Fetched %s', url) + headers = resp.info() + content_type = headers.get('Content-Type', '') + if HTML_CONTENT_TYPE.match(content_type): + final_url = resp.geturl() + data = resp.read() + encoding = headers.get('Content-Encoding') + if encoding: + decoder = self.decoders[encoding] # fail if not found + data = decoder(data) + encoding = 'utf-8' + m = CHARSET.search(content_type) + if m: + encoding = m.group(1) + try: + data = data.decode(encoding) + except UnicodeError: # pragma: no cover + data = data.decode('latin-1') # fallback + result = Page(data, final_url) + self._page_cache[final_url] = result + except HTTPError as e: + if e.code != 404: + logger.exception('Fetch failed: %s: %s', url, e) + except URLError as e: # pragma: no cover + logger.exception('Fetch failed: %s: %s', url, e) + with self._lock: + self._bad_hosts.add(host) + except Exception as e: # pragma: no cover + logger.exception('Fetch failed: %s: %s', url, e) + finally: + self._page_cache[url] = result # even if None (failure) + return result + + _distname_re = re.compile(']*>([^<]+)<') + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + result = set() + page = self.get_page(self.base_url) + if not page: + raise DistlibException('Unable to get %s' % self.base_url) + for match in self._distname_re.finditer(page.data): + result.add(match.group(1)) + return result + + +class DirectoryLocator(Locator): + """ + This class locates distributions in a directory tree. + """ + + def __init__(self, path, **kwargs): + """ + Initialise an instance. + :param path: The root of the directory tree to search. + :param kwargs: Passed to the superclass constructor, + except for: + * recursive - if True (the default), subdirectories are + recursed into. If False, only the top-level directory + is searched, + """ + self.recursive = kwargs.pop('recursive', True) + super(DirectoryLocator, self).__init__(**kwargs) + path = os.path.abspath(path) + if not os.path.isdir(path): # pragma: no cover + raise DistlibException('Not a directory: %r' % path) + self.base_dir = path + + def should_include(self, filename, parent): + """ + Should a filename be considered as a candidate for a distribution + archive? As well as the filename, the directory which contains it + is provided, though not used by the current implementation. + """ + return filename.endswith(self.downloadable_extensions) + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + for root, dirs, files in os.walk(self.base_dir): + for fn in files: + if self.should_include(fn, root): + fn = os.path.join(root, fn) + url = urlunparse(('file', '', pathname2url(os.path.abspath(fn)), '', '', '')) + info = self.convert_url_to_download_info(url, name) + if info: + self._update_version_data(result, info) + if not self.recursive: + break + return result + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + result = set() + for root, dirs, files in os.walk(self.base_dir): + for fn in files: + if self.should_include(fn, root): + fn = os.path.join(root, fn) + url = urlunparse(('file', '', pathname2url(os.path.abspath(fn)), '', '', '')) + info = self.convert_url_to_download_info(url, None) + if info: + result.add(info['name']) + if not self.recursive: + break + return result + + +class JSONLocator(Locator): + """ + This locator uses special extended metadata (not available on PyPI) and is + the basis of performant dependency resolution in distlib. Other locators + require archive downloads before dependencies can be determined! As you + might imagine, that can be slow. + """ + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + raise NotImplementedError('Not available from this locator') + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + data = get_project_data(name) + if data: + for info in data.get('files', []): + if info['ptype'] != 'sdist' or info['pyversion'] != 'source': + continue + # We don't store summary in project metadata as it makes + # the data bigger for no benefit during dependency + # resolution + dist = make_dist(data['name'], + info['version'], + summary=data.get('summary', 'Placeholder for summary'), + scheme=self.scheme) + md = dist.metadata + md.source_url = info['url'] + # TODO SHA256 digest + if 'digest' in info and info['digest']: + dist.digest = ('md5', info['digest']) + md.dependencies = info.get('requirements', {}) + dist.exports = info.get('exports', {}) + result[dist.version] = dist + result['urls'].setdefault(dist.version, set()).add(info['url']) + return result + + +class DistPathLocator(Locator): + """ + This locator finds installed distributions in a path. It can be useful for + adding to an :class:`AggregatingLocator`. + """ + + def __init__(self, distpath, **kwargs): + """ + Initialise an instance. + + :param distpath: A :class:`DistributionPath` instance to search. + """ + super(DistPathLocator, self).__init__(**kwargs) + assert isinstance(distpath, DistributionPath) + self.distpath = distpath + + def _get_project(self, name): + dist = self.distpath.get_distribution(name) + if dist is None: + result = {'urls': {}, 'digests': {}} + else: + result = { + dist.version: dist, + 'urls': { + dist.version: set([dist.source_url]) + }, + 'digests': { + dist.version: set([None]) + } + } + return result + + +class AggregatingLocator(Locator): + """ + This class allows you to chain and/or merge a list of locators. + """ + + def __init__(self, *locators, **kwargs): + """ + Initialise an instance. + + :param locators: The list of locators to search. + :param kwargs: Passed to the superclass constructor, + except for: + * merge - if False (the default), the first successful + search from any of the locators is returned. If True, + the results from all locators are merged (this can be + slow). + """ + self.merge = kwargs.pop('merge', False) + self.locators = locators + super(AggregatingLocator, self).__init__(**kwargs) + + def clear_cache(self): + super(AggregatingLocator, self).clear_cache() + for locator in self.locators: + locator.clear_cache() + + def _set_scheme(self, value): + self._scheme = value + for locator in self.locators: + locator.scheme = value + + scheme = property(Locator.scheme.fget, _set_scheme) + + def _get_project(self, name): + result = {} + for locator in self.locators: + d = locator.get_project(name) + if d: + if self.merge: + files = result.get('urls', {}) + digests = result.get('digests', {}) + # next line could overwrite result['urls'], result['digests'] + result.update(d) + df = result.get('urls') + if files and df: + for k, v in files.items(): + if k in df: + df[k] |= v + else: + df[k] = v + dd = result.get('digests') + if digests and dd: + dd.update(digests) + else: + # See issue #18. If any dists are found and we're looking + # for specific constraints, we only return something if + # a match is found. For example, if a DirectoryLocator + # returns just foo (1.0) while we're looking for + # foo (>= 2.0), we'll pretend there was nothing there so + # that subsequent locators can be queried. Otherwise we + # would just return foo (1.0) which would then lead to a + # failure to find foo (>= 2.0), because other locators + # weren't searched. Note that this only matters when + # merge=False. + if self.matcher is None: + found = True + else: + found = False + for k in d: + if self.matcher.match(k): + found = True + break + if found: + result = d + break + return result + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + result = set() + for locator in self.locators: + try: + result |= locator.get_distribution_names() + except NotImplementedError: + pass + return result + + +# We use a legacy scheme simply because most of the dists on PyPI use legacy +# versions which don't conform to PEP 440. +default_locator = AggregatingLocator( + # JSONLocator(), # don't use as PEP 426 is withdrawn + SimpleScrapingLocator('https://pypi.org/simple/', timeout=3.0), + scheme='legacy') + +locate = default_locator.locate + + +class DependencyFinder(object): + """ + Locate dependencies for distributions. + """ + + def __init__(self, locator=None): + """ + Initialise an instance, using the specified locator + to locate distributions. + """ + self.locator = locator or default_locator + self.scheme = get_scheme(self.locator.scheme) + + def add_distribution(self, dist): + """ + Add a distribution to the finder. This will update internal information + about who provides what. + :param dist: The distribution to add. + """ + logger.debug('adding distribution %s', dist) + name = dist.key + self.dists_by_name[name] = dist + self.dists[(name, dist.version)] = dist + for p in dist.provides: + name, version = parse_name_and_version(p) + logger.debug('Add to provided: %s, %s, %s', name, version, dist) + self.provided.setdefault(name, set()).add((version, dist)) + + def remove_distribution(self, dist): + """ + Remove a distribution from the finder. This will update internal + information about who provides what. + :param dist: The distribution to remove. + """ + logger.debug('removing distribution %s', dist) + name = dist.key + del self.dists_by_name[name] + del self.dists[(name, dist.version)] + for p in dist.provides: + name, version = parse_name_and_version(p) + logger.debug('Remove from provided: %s, %s, %s', name, version, dist) + s = self.provided[name] + s.remove((version, dist)) + if not s: + del self.provided[name] + + def get_matcher(self, reqt): + """ + Get a version matcher for a requirement. + :param reqt: The requirement + :type reqt: str + :return: A version matcher (an instance of + :class:`distlib.version.Matcher`). + """ + try: + matcher = self.scheme.matcher(reqt) + except UnsupportedVersionError: # pragma: no cover + # XXX compat-mode if cannot read the version + name = reqt.split()[0] + matcher = self.scheme.matcher(name) + return matcher + + def find_providers(self, reqt): + """ + Find the distributions which can fulfill a requirement. + + :param reqt: The requirement. + :type reqt: str + :return: A set of distribution which can fulfill the requirement. + """ + matcher = self.get_matcher(reqt) + name = matcher.key # case-insensitive + result = set() + provided = self.provided + if name in provided: + for version, provider in provided[name]: + try: + match = matcher.match(version) + except UnsupportedVersionError: + match = False + + if match: + result.add(provider) + break + return result + + def try_to_replace(self, provider, other, problems): + """ + Attempt to replace one provider with another. This is typically used + when resolving dependencies from multiple sources, e.g. A requires + (B >= 1.0) while C requires (B >= 1.1). + + For successful replacement, ``provider`` must meet all the requirements + which ``other`` fulfills. + + :param provider: The provider we are trying to replace with. + :param other: The provider we're trying to replace. + :param problems: If False is returned, this will contain what + problems prevented replacement. This is currently + a tuple of the literal string 'cantreplace', + ``provider``, ``other`` and the set of requirements + that ``provider`` couldn't fulfill. + :return: True if we can replace ``other`` with ``provider``, else + False. + """ + rlist = self.reqts[other] + unmatched = set() + for s in rlist: + matcher = self.get_matcher(s) + if not matcher.match(provider.version): + unmatched.add(s) + if unmatched: + # can't replace other with provider + problems.add(('cantreplace', provider, other, frozenset(unmatched))) + result = False + else: + # can replace other with provider + self.remove_distribution(other) + del self.reqts[other] + for s in rlist: + self.reqts.setdefault(provider, set()).add(s) + self.add_distribution(provider) + result = True + return result + + def find(self, requirement, meta_extras=None, prereleases=False): + """ + Find a distribution and all distributions it depends on. + + :param requirement: The requirement specifying the distribution to + find, or a Distribution instance. + :param meta_extras: A list of meta extras such as :test:, :build: and + so on. + :param prereleases: If ``True``, allow pre-release versions to be + returned - otherwise, don't return prereleases + unless they're all that's available. + + Return a set of :class:`Distribution` instances and a set of + problems. + + The distributions returned should be such that they have the + :attr:`required` attribute set to ``True`` if they were + from the ``requirement`` passed to ``find()``, and they have the + :attr:`build_time_dependency` attribute set to ``True`` unless they + are post-installation dependencies of the ``requirement``. + + The problems should be a tuple consisting of the string + ``'unsatisfied'`` and the requirement which couldn't be satisfied + by any distribution known to the locator. + """ + + self.provided = {} + self.dists = {} + self.dists_by_name = {} + self.reqts = {} + + meta_extras = set(meta_extras or []) + if ':*:' in meta_extras: + meta_extras.remove(':*:') + # :meta: and :run: are implicitly included + meta_extras |= set([':test:', ':build:', ':dev:']) + + if isinstance(requirement, Distribution): + dist = odist = requirement + logger.debug('passed %s as requirement', odist) + else: + dist = odist = self.locator.locate(requirement, prereleases=prereleases) + if dist is None: + raise DistlibException('Unable to locate %r' % requirement) + logger.debug('located %s', odist) + dist.requested = True + problems = set() + todo = set([dist]) + install_dists = set([odist]) + while todo: + dist = todo.pop() + name = dist.key # case-insensitive + if name not in self.dists_by_name: + self.add_distribution(dist) + else: + # import pdb; pdb.set_trace() + other = self.dists_by_name[name] + if other != dist: + self.try_to_replace(dist, other, problems) + + ireqts = dist.run_requires | dist.meta_requires + sreqts = dist.build_requires + ereqts = set() + if meta_extras and dist in install_dists: + for key in ('test', 'build', 'dev'): + e = ':%s:' % key + if e in meta_extras: + ereqts |= getattr(dist, '%s_requires' % key) + all_reqts = ireqts | sreqts | ereqts + for r in all_reqts: + providers = self.find_providers(r) + if not providers: + logger.debug('No providers found for %r', r) + provider = self.locator.locate(r, prereleases=prereleases) + # If no provider is found and we didn't consider + # prereleases, consider them now. + if provider is None and not prereleases: + provider = self.locator.locate(r, prereleases=True) + if provider is None: + logger.debug('Cannot satisfy %r', r) + problems.add(('unsatisfied', r)) + else: + n, v = provider.key, provider.version + if (n, v) not in self.dists: + todo.add(provider) + providers.add(provider) + if r in ireqts and dist in install_dists: + install_dists.add(provider) + logger.debug('Adding %s to install_dists', provider.name_and_version) + for p in providers: + name = p.key + if name not in self.dists_by_name: + self.reqts.setdefault(p, set()).add(r) + else: + other = self.dists_by_name[name] + if other != p: + # see if other can be replaced by p + self.try_to_replace(p, other, problems) + + dists = set(self.dists.values()) + for dist in dists: + dist.build_time_dependency = dist not in install_dists + if dist.build_time_dependency: + logger.debug('%s is a build-time dependency only.', dist.name_and_version) + logger.debug('find done for %s', odist) + return dists, problems diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/manifest.py b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/manifest.py new file mode 100644 index 0000000..420dcf1 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/manifest.py @@ -0,0 +1,384 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2023 Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +""" +Class representing the list of files in a distribution. + +Equivalent to distutils.filelist, but fixes some problems. +""" +import fnmatch +import logging +import os +import re +import sys + +from . import DistlibException +from .compat import fsdecode +from .util import convert_path + + +__all__ = ['Manifest'] + +logger = logging.getLogger(__name__) + +# a \ followed by some spaces + EOL +_COLLAPSE_PATTERN = re.compile('\\\\w*\n', re.M) +_COMMENTED_LINE = re.compile('#.*?(?=\n)|\n(?=$)', re.M | re.S) + +# +# Due to the different results returned by fnmatch.translate, we need +# to do slightly different processing for Python 2.7 and 3.2 ... this needed +# to be brought in for Python 3.6 onwards. +# +_PYTHON_VERSION = sys.version_info[:2] + + +class Manifest(object): + """ + A list of files built by exploring the filesystem and filtered by applying various + patterns to what we find there. + """ + + def __init__(self, base=None): + """ + Initialise an instance. + + :param base: The base directory to explore under. + """ + self.base = os.path.abspath(os.path.normpath(base or os.getcwd())) + self.prefix = self.base + os.sep + self.allfiles = None + self.files = set() + + # + # Public API + # + + def findall(self): + """Find all files under the base and set ``allfiles`` to the absolute + pathnames of files found. + """ + from stat import S_ISREG, S_ISDIR, S_ISLNK + + self.allfiles = allfiles = [] + root = self.base + stack = [root] + pop = stack.pop + push = stack.append + + while stack: + root = pop() + names = os.listdir(root) + + for name in names: + fullname = os.path.join(root, name) + + # Avoid excess stat calls -- just one will do, thank you! + stat = os.stat(fullname) + mode = stat.st_mode + if S_ISREG(mode): + allfiles.append(fsdecode(fullname)) + elif S_ISDIR(mode) and not S_ISLNK(mode): + push(fullname) + + def add(self, item): + """ + Add a file to the manifest. + + :param item: The pathname to add. This can be relative to the base. + """ + if not item.startswith(self.prefix): + item = os.path.join(self.base, item) + self.files.add(os.path.normpath(item)) + + def add_many(self, items): + """ + Add a list of files to the manifest. + + :param items: The pathnames to add. These can be relative to the base. + """ + for item in items: + self.add(item) + + def sorted(self, wantdirs=False): + """ + Return sorted files in directory order + """ + + def add_dir(dirs, d): + dirs.add(d) + logger.debug('add_dir added %s', d) + if d != self.base: + parent, _ = os.path.split(d) + assert parent not in ('', '/') + add_dir(dirs, parent) + + result = set(self.files) # make a copy! + if wantdirs: + dirs = set() + for f in result: + add_dir(dirs, os.path.dirname(f)) + result |= dirs + return [os.path.join(*path_tuple) for path_tuple in + sorted(os.path.split(path) for path in result)] + + def clear(self): + """Clear all collected files.""" + self.files = set() + self.allfiles = [] + + def process_directive(self, directive): + """ + Process a directive which either adds some files from ``allfiles`` to + ``files``, or removes some files from ``files``. + + :param directive: The directive to process. This should be in a format + compatible with distutils ``MANIFEST.in`` files: + + http://docs.python.org/distutils/sourcedist.html#commands + """ + # Parse the line: split it up, make sure the right number of words + # is there, and return the relevant words. 'action' is always + # defined: it's the first word of the line. Which of the other + # three are defined depends on the action; it'll be either + # patterns, (dir and patterns), or (dirpattern). + action, patterns, thedir, dirpattern = self._parse_directive(directive) + + # OK, now we know that the action is valid and we have the + # right number of words on the line for that action -- so we + # can proceed with minimal error-checking. + if action == 'include': + for pattern in patterns: + if not self._include_pattern(pattern, anchor=True): + logger.warning('no files found matching %r', pattern) + + elif action == 'exclude': + for pattern in patterns: + self._exclude_pattern(pattern, anchor=True) + + elif action == 'global-include': + for pattern in patterns: + if not self._include_pattern(pattern, anchor=False): + logger.warning('no files found matching %r ' + 'anywhere in distribution', pattern) + + elif action == 'global-exclude': + for pattern in patterns: + self._exclude_pattern(pattern, anchor=False) + + elif action == 'recursive-include': + for pattern in patterns: + if not self._include_pattern(pattern, prefix=thedir): + logger.warning('no files found matching %r ' + 'under directory %r', pattern, thedir) + + elif action == 'recursive-exclude': + for pattern in patterns: + self._exclude_pattern(pattern, prefix=thedir) + + elif action == 'graft': + if not self._include_pattern(None, prefix=dirpattern): + logger.warning('no directories found matching %r', + dirpattern) + + elif action == 'prune': + if not self._exclude_pattern(None, prefix=dirpattern): + logger.warning('no previously-included directories found ' + 'matching %r', dirpattern) + else: # pragma: no cover + # This should never happen, as it should be caught in + # _parse_template_line + raise DistlibException( + 'invalid action %r' % action) + + # + # Private API + # + + def _parse_directive(self, directive): + """ + Validate a directive. + :param directive: The directive to validate. + :return: A tuple of action, patterns, thedir, dir_patterns + """ + words = directive.split() + if len(words) == 1 and words[0] not in ('include', 'exclude', + 'global-include', + 'global-exclude', + 'recursive-include', + 'recursive-exclude', + 'graft', 'prune'): + # no action given, let's use the default 'include' + words.insert(0, 'include') + + action = words[0] + patterns = thedir = dir_pattern = None + + if action in ('include', 'exclude', + 'global-include', 'global-exclude'): + if len(words) < 2: + raise DistlibException( + '%r expects ...' % action) + + patterns = [convert_path(word) for word in words[1:]] + + elif action in ('recursive-include', 'recursive-exclude'): + if len(words) < 3: + raise DistlibException( + '%r expects

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ˉ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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c4eff7eb319fbd7c634e479afbf0ad44d78f242e GIT binary patch literal 30347 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 l@9f(@GwLj=83TGS1}~;{{X;nor(Ye literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cc701f7234bdb56c5137a4cdd5905693d6bdfb33 GIT binary patch literal 52548 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

...' % action) + + thedir = convert_path(words[1]) + patterns = [convert_path(word) for word in words[2:]] + + elif action in ('graft', 'prune'): + if len(words) != 2: + raise DistlibException( + '%r expects a single ' % action) + + dir_pattern = convert_path(words[1]) + + else: + raise DistlibException('unknown action %r' % action) + + return action, patterns, thedir, dir_pattern + + def _include_pattern(self, pattern, anchor=True, prefix=None, + is_regex=False): + """Select strings (presumably filenames) from 'self.files' that + match 'pattern', a Unix-style wildcard (glob) pattern. + + Patterns are not quite the same as implemented by the 'fnmatch' + module: '*' and '?' match non-special characters, where "special" + is platform-dependent: slash on Unix; colon, slash, and backslash on + DOS/Windows; and colon on Mac OS. + + If 'anchor' is true (the default), then the pattern match is more + stringent: "*.py" will match "foo.py" but not "foo/bar.py". If + 'anchor' is false, both of these will match. + + If 'prefix' is supplied, then only filenames starting with 'prefix' + (itself a pattern) and ending with 'pattern', with anything in between + them, will match. 'anchor' is ignored in this case. + + If 'is_regex' is true, 'anchor' and 'prefix' are ignored, and + 'pattern' is assumed to be either a string containing a regex or a + regex object -- no translation is done, the regex is just compiled + and used as-is. + + Selected strings will be added to self.files. + + Return True if files are found. + """ + # XXX docstring lying about what the special chars are? + found = False + pattern_re = self._translate_pattern(pattern, anchor, prefix, is_regex) + + # delayed loading of allfiles list + if self.allfiles is None: + self.findall() + + for name in self.allfiles: + if pattern_re.search(name): + self.files.add(name) + found = True + return found + + def _exclude_pattern(self, pattern, anchor=True, prefix=None, + is_regex=False): + """Remove strings (presumably filenames) from 'files' that match + 'pattern'. + + Other parameters are the same as for 'include_pattern()', above. + The list 'self.files' is modified in place. Return True if files are + found. + + This API is public to allow e.g. exclusion of SCM subdirs, e.g. when + packaging source distributions + """ + found = False + pattern_re = self._translate_pattern(pattern, anchor, prefix, is_regex) + for f in list(self.files): + if pattern_re.search(f): + self.files.remove(f) + found = True + return found + + def _translate_pattern(self, pattern, anchor=True, prefix=None, + is_regex=False): + """Translate a shell-like wildcard pattern to a compiled regular + expression. + + Return the compiled regex. If 'is_regex' true, + then 'pattern' is directly compiled to a regex (if it's a string) + or just returned as-is (assumes it's a regex object). + """ + if is_regex: + if isinstance(pattern, str): + return re.compile(pattern) + else: + return pattern + + if _PYTHON_VERSION > (3, 2): + # ditch start and end characters + start, _, end = self._glob_to_re('_').partition('_') + + if pattern: + pattern_re = self._glob_to_re(pattern) + if _PYTHON_VERSION > (3, 2): + assert pattern_re.startswith(start) and pattern_re.endswith(end) + else: + pattern_re = '' + + base = re.escape(os.path.join(self.base, '')) + if prefix is not None: + # ditch end of pattern character + if _PYTHON_VERSION <= (3, 2): + empty_pattern = self._glob_to_re('') + prefix_re = self._glob_to_re(prefix)[:-len(empty_pattern)] + else: + prefix_re = self._glob_to_re(prefix) + assert prefix_re.startswith(start) and prefix_re.endswith(end) + prefix_re = prefix_re[len(start): len(prefix_re) - len(end)] + sep = os.sep + if os.sep == '\\': + sep = r'\\' + if _PYTHON_VERSION <= (3, 2): + pattern_re = '^' + base + sep.join((prefix_re, + '.*' + pattern_re)) + else: + pattern_re = pattern_re[len(start): len(pattern_re) - len(end)] + pattern_re = r'%s%s%s%s.*%s%s' % (start, base, prefix_re, sep, + pattern_re, end) + else: # no prefix -- respect anchor flag + if anchor: + if _PYTHON_VERSION <= (3, 2): + pattern_re = '^' + base + pattern_re + else: + pattern_re = r'%s%s%s' % (start, base, pattern_re[len(start):]) + + return re.compile(pattern_re) + + def _glob_to_re(self, pattern): + """Translate a shell-like glob pattern to a regular expression. + + Return a string containing the regex. Differs from + 'fnmatch.translate()' in that '*' does not match "special characters" + (which are platform-specific). + """ + pattern_re = fnmatch.translate(pattern) + + # '?' and '*' in the glob pattern become '.' and '.*' in the RE, which + # IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix, + # and by extension they shouldn't match such "special characters" under + # any OS. So change all non-escaped dots in the RE to match any + # character except the special characters (currently: just os.sep). + sep = os.sep + if os.sep == '\\': + # we're using a regex to manipulate a regex, so we need + # to escape the backslash twice + sep = r'\\\\' + escaped = r'\1[^%s]' % sep + pattern_re = re.sub(r'((? y, + '!=': lambda x, y: x != y, + '<': lambda x, y: x < y, + '<=': lambda x, y: x == y or x < y, + '>': lambda x, y: x > y, + '>=': lambda x, y: x == y or x > y, + 'and': lambda x, y: x and y, + 'or': lambda x, y: x or y, + 'in': lambda x, y: x in y, + 'not in': lambda x, y: x not in y, + } + + def evaluate(self, expr, context): + """ + Evaluate a marker expression returned by the :func:`parse_requirement` + function in the specified context. + """ + if isinstance(expr, string_types): + if expr[0] in '\'"': + result = expr[1:-1] + else: + if expr not in context: + raise SyntaxError('unknown variable: %s' % expr) + result = context[expr] + else: + assert isinstance(expr, dict) + op = expr['op'] + if op not in self.operations: + raise NotImplementedError('op not implemented: %s' % op) + elhs = expr['lhs'] + erhs = expr['rhs'] + if _is_literal(expr['lhs']) and _is_literal(expr['rhs']): + raise SyntaxError('invalid comparison: %s %s %s' % (elhs, op, erhs)) + + lhs = self.evaluate(elhs, context) + rhs = self.evaluate(erhs, context) + if ((_is_version_marker(elhs) or _is_version_marker(erhs)) and + op in ('<', '<=', '>', '>=', '===', '==', '!=', '~=')): + lhs = LV(lhs) + rhs = LV(rhs) + elif _is_version_marker(elhs) and op in ('in', 'not in'): + lhs = LV(lhs) + rhs = _get_versions(rhs) + result = self.operations[op](lhs, rhs) + return result + + +_DIGITS = re.compile(r'\d+\.\d+') + + +def default_context(): + + def format_full_version(info): + version = '%s.%s.%s' % (info.major, info.minor, info.micro) + kind = info.releaselevel + if kind != 'final': + version += kind[0] + str(info.serial) + return version + + if hasattr(sys, 'implementation'): + implementation_version = format_full_version(sys.implementation.version) + implementation_name = sys.implementation.name + else: + implementation_version = '0' + implementation_name = '' + + ppv = platform.python_version() + m = _DIGITS.match(ppv) + pv = m.group(0) + result = { + 'implementation_name': implementation_name, + 'implementation_version': implementation_version, + 'os_name': os.name, + 'platform_machine': platform.machine(), + 'platform_python_implementation': platform.python_implementation(), + 'platform_release': platform.release(), + 'platform_system': platform.system(), + 'platform_version': platform.version(), + 'platform_in_venv': str(in_venv()), + 'python_full_version': ppv, + 'python_version': pv, + 'sys_platform': sys.platform, + } + return result + + +DEFAULT_CONTEXT = default_context() +del default_context + +evaluator = Evaluator() + + +def interpret(marker, execution_context=None): + """ + Interpret a marker and return a result depending on environment. + + :param marker: The marker to interpret. + :type marker: str + :param execution_context: The context used for name lookup. + :type execution_context: mapping + """ + try: + expr, rest = parse_marker(marker) + except Exception as e: + raise SyntaxError('Unable to interpret marker syntax: %s: %s' % (marker, e)) + if rest and rest[0] != '#': + raise SyntaxError('unexpected trailing data in marker: %s: %s' % (marker, rest)) + context = dict(DEFAULT_CONTEXT) + if execution_context: + context.update(execution_context) + return evaluator.evaluate(expr, context) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/metadata.py b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/metadata.py new file mode 100644 index 0000000..ce9a34b --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/metadata.py @@ -0,0 +1,1031 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +"""Implementation of the Metadata for Python packages PEPs. + +Supports all metadata formats (1.0, 1.1, 1.2, 1.3/2.1 and 2.2). +""" +from __future__ import unicode_literals + +import codecs +from email import message_from_file +import json +import logging +import re + +from . import DistlibException, __version__ +from .compat import StringIO, string_types, text_type +from .markers import interpret +from .util import extract_by_key, get_extras +from .version import get_scheme, PEP440_VERSION_RE + +logger = logging.getLogger(__name__) + + +class MetadataMissingError(DistlibException): + """A required metadata is missing""" + + +class MetadataConflictError(DistlibException): + """Attempt to read or write metadata fields that are conflictual.""" + + +class MetadataUnrecognizedVersionError(DistlibException): + """Unknown metadata version number.""" + + +class MetadataInvalidError(DistlibException): + """A metadata value is invalid""" + + +# public API of this module +__all__ = ['Metadata', 'PKG_INFO_ENCODING', 'PKG_INFO_PREFERRED_VERSION'] + +# Encoding used for the PKG-INFO files +PKG_INFO_ENCODING = 'utf-8' + +# preferred version. Hopefully will be changed +# to 1.2 once PEP 345 is supported everywhere +PKG_INFO_PREFERRED_VERSION = '1.1' + +_LINE_PREFIX_1_2 = re.compile('\n \\|') +_LINE_PREFIX_PRE_1_2 = re.compile('\n ') +_241_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', 'Summary', 'Description', 'Keywords', 'Home-page', + 'Author', 'Author-email', 'License') + +_314_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', 'Supported-Platform', 'Summary', 'Description', + 'Keywords', 'Home-page', 'Author', 'Author-email', 'License', 'Classifier', 'Download-URL', 'Obsoletes', + 'Provides', 'Requires') + +_314_MARKERS = ('Obsoletes', 'Provides', 'Requires', 'Classifier', 'Download-URL') + +_345_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', 'Supported-Platform', 'Summary', 'Description', + 'Keywords', 'Home-page', 'Author', 'Author-email', 'Maintainer', 'Maintainer-email', 'License', + 'Classifier', 'Download-URL', 'Obsoletes-Dist', 'Project-URL', 'Provides-Dist', 'Requires-Dist', + 'Requires-Python', 'Requires-External') + +_345_MARKERS = ('Provides-Dist', 'Requires-Dist', 'Requires-Python', 'Obsoletes-Dist', 'Requires-External', + 'Maintainer', 'Maintainer-email', 'Project-URL') + +_426_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', 'Supported-Platform', 'Summary', 'Description', + 'Keywords', 'Home-page', 'Author', 'Author-email', 'Maintainer', 'Maintainer-email', 'License', + 'Classifier', 'Download-URL', 'Obsoletes-Dist', 'Project-URL', 'Provides-Dist', 'Requires-Dist', + 'Requires-Python', 'Requires-External', 'Private-Version', 'Obsoleted-By', 'Setup-Requires-Dist', + 'Extension', 'Provides-Extra') + +_426_MARKERS = ('Private-Version', 'Provides-Extra', 'Obsoleted-By', 'Setup-Requires-Dist', 'Extension') + +# See issue #106: Sometimes 'Requires' and 'Provides' occur wrongly in +# the metadata. Include them in the tuple literal below to allow them +# (for now). +# Ditto for Obsoletes - see issue #140. +_566_FIELDS = _426_FIELDS + ('Description-Content-Type', 'Requires', 'Provides', 'Obsoletes') + +_566_MARKERS = ('Description-Content-Type', ) + +_643_MARKERS = ('Dynamic', 'License-File') + +_643_FIELDS = _566_FIELDS + _643_MARKERS + +_ALL_FIELDS = set() +_ALL_FIELDS.update(_241_FIELDS) +_ALL_FIELDS.update(_314_FIELDS) +_ALL_FIELDS.update(_345_FIELDS) +_ALL_FIELDS.update(_426_FIELDS) +_ALL_FIELDS.update(_566_FIELDS) +_ALL_FIELDS.update(_643_FIELDS) + +EXTRA_RE = re.compile(r'''extra\s*==\s*("([^"]+)"|'([^']+)')''') + + +def _version2fieldlist(version): + if version == '1.0': + return _241_FIELDS + elif version == '1.1': + return _314_FIELDS + elif version == '1.2': + return _345_FIELDS + elif version in ('1.3', '2.1'): + # avoid adding field names if already there + return _345_FIELDS + tuple(f for f in _566_FIELDS if f not in _345_FIELDS) + elif version == '2.0': + raise ValueError('Metadata 2.0 is withdrawn and not supported') + # return _426_FIELDS + elif version == '2.2': + return _643_FIELDS + raise MetadataUnrecognizedVersionError(version) + + +def _best_version(fields): + """Detect the best version depending on the fields used.""" + + def _has_marker(keys, markers): + return any(marker in keys for marker in markers) + + keys = [key for key, value in fields.items() if value not in ([], 'UNKNOWN', None)] + possible_versions = ['1.0', '1.1', '1.2', '1.3', '2.1', '2.2'] # 2.0 removed + + # first let's try to see if a field is not part of one of the version + for key in keys: + if key not in _241_FIELDS and '1.0' in possible_versions: + possible_versions.remove('1.0') + logger.debug('Removed 1.0 due to %s', key) + if key not in _314_FIELDS and '1.1' in possible_versions: + possible_versions.remove('1.1') + logger.debug('Removed 1.1 due to %s', key) + if key not in _345_FIELDS and '1.2' in possible_versions: + possible_versions.remove('1.2') + logger.debug('Removed 1.2 due to %s', key) + if key not in _566_FIELDS and '1.3' in possible_versions: + possible_versions.remove('1.3') + logger.debug('Removed 1.3 due to %s', key) + if key not in _566_FIELDS and '2.1' in possible_versions: + if key != 'Description': # In 2.1, description allowed after headers + possible_versions.remove('2.1') + logger.debug('Removed 2.1 due to %s', key) + if key not in _643_FIELDS and '2.2' in possible_versions: + possible_versions.remove('2.2') + logger.debug('Removed 2.2 due to %s', key) + # if key not in _426_FIELDS and '2.0' in possible_versions: + # possible_versions.remove('2.0') + # logger.debug('Removed 2.0 due to %s', key) + + # possible_version contains qualified versions + if len(possible_versions) == 1: + return possible_versions[0] # found ! + elif len(possible_versions) == 0: + logger.debug('Out of options - unknown metadata set: %s', fields) + raise MetadataConflictError('Unknown metadata set') + + # let's see if one unique marker is found + is_1_1 = '1.1' in possible_versions and _has_marker(keys, _314_MARKERS) + is_1_2 = '1.2' in possible_versions and _has_marker(keys, _345_MARKERS) + is_2_1 = '2.1' in possible_versions and _has_marker(keys, _566_MARKERS) + # is_2_0 = '2.0' in possible_versions and _has_marker(keys, _426_MARKERS) + is_2_2 = '2.2' in possible_versions and _has_marker(keys, _643_MARKERS) + if int(is_1_1) + int(is_1_2) + int(is_2_1) + int(is_2_2) > 1: + raise MetadataConflictError('You used incompatible 1.1/1.2/2.1/2.2 fields') + + # we have the choice, 1.0, or 1.2, 2.1 or 2.2 + # - 1.0 has a broken Summary field but works with all tools + # - 1.1 is to avoid + # - 1.2 fixes Summary but has little adoption + # - 2.1 adds more features + # - 2.2 is the latest + if not is_1_1 and not is_1_2 and not is_2_1 and not is_2_2: + # we couldn't find any specific marker + if PKG_INFO_PREFERRED_VERSION in possible_versions: + return PKG_INFO_PREFERRED_VERSION + if is_1_1: + return '1.1' + if is_1_2: + return '1.2' + if is_2_1: + return '2.1' + # if is_2_2: + # return '2.2' + + return '2.2' + + +# This follows the rules about transforming keys as described in +# https://www.python.org/dev/peps/pep-0566/#id17 +_ATTR2FIELD = {name.lower().replace("-", "_"): name for name in _ALL_FIELDS} +_FIELD2ATTR = {field: attr for attr, field in _ATTR2FIELD.items()} + +_PREDICATE_FIELDS = ('Requires-Dist', 'Obsoletes-Dist', 'Provides-Dist') +_VERSIONS_FIELDS = ('Requires-Python', ) +_VERSION_FIELDS = ('Version', ) +_LISTFIELDS = ('Platform', 'Classifier', 'Obsoletes', 'Requires', 'Provides', 'Obsoletes-Dist', 'Provides-Dist', + 'Requires-Dist', 'Requires-External', 'Project-URL', 'Supported-Platform', 'Setup-Requires-Dist', + 'Provides-Extra', 'Extension', 'License-File') +_LISTTUPLEFIELDS = ('Project-URL', ) + +_ELEMENTSFIELD = ('Keywords', ) + +_UNICODEFIELDS = ('Author', 'Maintainer', 'Summary', 'Description') + +_MISSING = object() + +_FILESAFE = re.compile('[^A-Za-z0-9.]+') + + +def _get_name_and_version(name, version, for_filename=False): + """Return the distribution name with version. + + If for_filename is true, return a filename-escaped form.""" + if for_filename: + # For both name and version any runs of non-alphanumeric or '.' + # characters are replaced with a single '-'. Additionally any + # spaces in the version string become '.' + name = _FILESAFE.sub('-', name) + version = _FILESAFE.sub('-', version.replace(' ', '.')) + return '%s-%s' % (name, version) + + +class LegacyMetadata(object): + """The legacy metadata of a release. + + Supports versions 1.0, 1.1, 1.2, 2.0 and 1.3/2.1 (auto-detected). You can + instantiate the class with one of these arguments (or none): + - *path*, the path to a metadata file + - *fileobj* give a file-like object with metadata as content + - *mapping* is a dict-like object + - *scheme* is a version scheme name + """ + + # TODO document the mapping API and UNKNOWN default key + + def __init__(self, path=None, fileobj=None, mapping=None, scheme='default'): + if [path, fileobj, mapping].count(None) < 2: + raise TypeError('path, fileobj and mapping are exclusive') + self._fields = {} + self.requires_files = [] + self._dependencies = None + self.scheme = scheme + if path is not None: + self.read(path) + elif fileobj is not None: + self.read_file(fileobj) + elif mapping is not None: + self.update(mapping) + self.set_metadata_version() + + def set_metadata_version(self): + self._fields['Metadata-Version'] = _best_version(self._fields) + + def _write_field(self, fileobj, name, value): + fileobj.write('%s: %s\n' % (name, value)) + + def __getitem__(self, name): + return self.get(name) + + def __setitem__(self, name, value): + return self.set(name, value) + + def __delitem__(self, name): + field_name = self._convert_name(name) + try: + del self._fields[field_name] + except KeyError: + raise KeyError(name) + + def __contains__(self, name): + return (name in self._fields or self._convert_name(name) in self._fields) + + def _convert_name(self, name): + if name in _ALL_FIELDS: + return name + name = name.replace('-', '_').lower() + return _ATTR2FIELD.get(name, name) + + def _default_value(self, name): + if name in _LISTFIELDS or name in _ELEMENTSFIELD: + return [] + return 'UNKNOWN' + + def _remove_line_prefix(self, value): + if self.metadata_version in ('1.0', '1.1'): + return _LINE_PREFIX_PRE_1_2.sub('\n', value) + else: + return _LINE_PREFIX_1_2.sub('\n', value) + + def __getattr__(self, name): + if name in _ATTR2FIELD: + return self[name] + raise AttributeError(name) + + # + # Public API + # + + def get_fullname(self, filesafe=False): + """ + Return the distribution name with version. + + If filesafe is true, return a filename-escaped form. + """ + return _get_name_and_version(self['Name'], self['Version'], filesafe) + + def is_field(self, name): + """return True if name is a valid metadata key""" + name = self._convert_name(name) + return name in _ALL_FIELDS + + def is_multi_field(self, name): + name = self._convert_name(name) + return name in _LISTFIELDS + + def read(self, filepath): + """Read the metadata values from a file path.""" + fp = codecs.open(filepath, 'r', encoding='utf-8') + try: + self.read_file(fp) + finally: + fp.close() + + def read_file(self, fileob): + """Read the metadata values from a file object.""" + msg = message_from_file(fileob) + self._fields['Metadata-Version'] = msg['metadata-version'] + + # When reading, get all the fields we can + for field in _ALL_FIELDS: + if field not in msg: + continue + if field in _LISTFIELDS: + # we can have multiple lines + values = msg.get_all(field) + if field in _LISTTUPLEFIELDS and values is not None: + values = [tuple(value.split(',')) for value in values] + self.set(field, values) + else: + # single line + value = msg[field] + if value is not None and value != 'UNKNOWN': + self.set(field, value) + + # PEP 566 specifies that the body be used for the description, if + # available + body = msg.get_payload() + self["Description"] = body if body else self["Description"] + # logger.debug('Attempting to set metadata for %s', self) + # self.set_metadata_version() + + def write(self, filepath, skip_unknown=False): + """Write the metadata fields to filepath.""" + fp = codecs.open(filepath, 'w', encoding='utf-8') + try: + self.write_file(fp, skip_unknown) + finally: + fp.close() + + def write_file(self, fileobject, skip_unknown=False): + """Write the PKG-INFO format data to a file object.""" + self.set_metadata_version() + + for field in _version2fieldlist(self['Metadata-Version']): + values = self.get(field) + if skip_unknown and values in ('UNKNOWN', [], ['UNKNOWN']): + continue + if field in _ELEMENTSFIELD: + self._write_field(fileobject, field, ','.join(values)) + continue + if field not in _LISTFIELDS: + if field == 'Description': + if self.metadata_version in ('1.0', '1.1'): + values = values.replace('\n', '\n ') + else: + values = values.replace('\n', '\n |') + values = [values] + + if field in _LISTTUPLEFIELDS: + values = [','.join(value) for value in values] + + for value in values: + self._write_field(fileobject, field, value) + + def update(self, other=None, **kwargs): + """Set metadata values from the given iterable `other` and kwargs. + + Behavior is like `dict.update`: If `other` has a ``keys`` method, + they are looped over and ``self[key]`` is assigned ``other[key]``. + Else, ``other`` is an iterable of ``(key, value)`` iterables. + + Keys that don't match a metadata field or that have an empty value are + dropped. + """ + + def _set(key, value): + if key in _ATTR2FIELD and value: + self.set(self._convert_name(key), value) + + if not other: + # other is None or empty container + pass + elif hasattr(other, 'keys'): + for k in other.keys(): + _set(k, other[k]) + else: + for k, v in other: + _set(k, v) + + if kwargs: + for k, v in kwargs.items(): + _set(k, v) + + def set(self, name, value): + """Control then set a metadata field.""" + name = self._convert_name(name) + + if ((name in _ELEMENTSFIELD or name == 'Platform') and not isinstance(value, (list, tuple))): + if isinstance(value, string_types): + value = [v.strip() for v in value.split(',')] + else: + value = [] + elif (name in _LISTFIELDS and not isinstance(value, (list, tuple))): + if isinstance(value, string_types): + value = [value] + else: + value = [] + + if logger.isEnabledFor(logging.WARNING): + project_name = self['Name'] + + scheme = get_scheme(self.scheme) + if name in _PREDICATE_FIELDS and value is not None: + for v in value: + # check that the values are valid + if not scheme.is_valid_matcher(v.split(';')[0]): + logger.warning("'%s': '%s' is not valid (field '%s')", project_name, v, name) + # FIXME this rejects UNKNOWN, is that right? + elif name in _VERSIONS_FIELDS and value is not None: + if not scheme.is_valid_constraint_list(value): + logger.warning("'%s': '%s' is not a valid version (field '%s')", project_name, value, name) + elif name in _VERSION_FIELDS and value is not None: + if not scheme.is_valid_version(value): + logger.warning("'%s': '%s' is not a valid version (field '%s')", project_name, value, name) + + if name in _UNICODEFIELDS: + if name == 'Description': + value = self._remove_line_prefix(value) + + self._fields[name] = value + + def get(self, name, default=_MISSING): + """Get a metadata field.""" + name = self._convert_name(name) + if name not in self._fields: + if default is _MISSING: + default = self._default_value(name) + return default + if name in _UNICODEFIELDS: + value = self._fields[name] + return value + elif name in _LISTFIELDS: + value = self._fields[name] + if value is None: + return [] + res = [] + for val in value: + if name not in _LISTTUPLEFIELDS: + res.append(val) + else: + # That's for Project-URL + res.append((val[0], val[1])) + return res + + elif name in _ELEMENTSFIELD: + value = self._fields[name] + if isinstance(value, string_types): + return value.split(',') + return self._fields[name] + + def check(self, strict=False): + """Check if the metadata is compliant. If strict is True then raise if + no Name or Version are provided""" + self.set_metadata_version() + + # XXX should check the versions (if the file was loaded) + missing, warnings = [], [] + + for attr in ('Name', 'Version'): # required by PEP 345 + if attr not in self: + missing.append(attr) + + if strict and missing != []: + msg = 'missing required metadata: %s' % ', '.join(missing) + raise MetadataMissingError(msg) + + for attr in ('Home-page', 'Author'): + if attr not in self: + missing.append(attr) + + # checking metadata 1.2 (XXX needs to check 1.1, 1.0) + if self['Metadata-Version'] != '1.2': + return missing, warnings + + scheme = get_scheme(self.scheme) + + def are_valid_constraints(value): + for v in value: + if not scheme.is_valid_matcher(v.split(';')[0]): + return False + return True + + for fields, controller in ((_PREDICATE_FIELDS, are_valid_constraints), + (_VERSIONS_FIELDS, scheme.is_valid_constraint_list), (_VERSION_FIELDS, + scheme.is_valid_version)): + for field in fields: + value = self.get(field, None) + if value is not None and not controller(value): + warnings.append("Wrong value for '%s': %s" % (field, value)) + + return missing, warnings + + def todict(self, skip_missing=False): + """Return fields as a dict. + + Field names will be converted to use the underscore-lowercase style + instead of hyphen-mixed case (i.e. home_page instead of Home-page). + This is as per https://www.python.org/dev/peps/pep-0566/#id17. + """ + self.set_metadata_version() + + fields = _version2fieldlist(self['Metadata-Version']) + + data = {} + + for field_name in fields: + if not skip_missing or field_name in self._fields: + key = _FIELD2ATTR[field_name] + if key != 'project_url': + data[key] = self[field_name] + else: + data[key] = [','.join(u) for u in self[field_name]] + + return data + + def add_requirements(self, requirements): + if self['Metadata-Version'] == '1.1': + # we can't have 1.1 metadata *and* Setuptools requires + for field in ('Obsoletes', 'Requires', 'Provides'): + if field in self: + del self[field] + self['Requires-Dist'] += requirements + + # Mapping API + # TODO could add iter* variants + + def keys(self): + return list(_version2fieldlist(self['Metadata-Version'])) + + def __iter__(self): + for key in self.keys(): + yield key + + def values(self): + return [self[key] for key in self.keys()] + + def items(self): + return [(key, self[key]) for key in self.keys()] + + def __repr__(self): + return '<%s %s %s>' % (self.__class__.__name__, self.name, self.version) + + +METADATA_FILENAME = 'pydist.json' +WHEEL_METADATA_FILENAME = 'metadata.json' +LEGACY_METADATA_FILENAME = 'METADATA' + + +class Metadata(object): + """ + The metadata of a release. This implementation uses 2.1 + metadata where possible. If not possible, it wraps a LegacyMetadata + instance which handles the key-value metadata format. + """ + + METADATA_VERSION_MATCHER = re.compile(r'^\d+(\.\d+)*$') + + NAME_MATCHER = re.compile('^[0-9A-Z]([0-9A-Z_.-]*[0-9A-Z])?$', re.I) + + FIELDNAME_MATCHER = re.compile('^[A-Z]([0-9A-Z-]*[0-9A-Z])?$', re.I) + + VERSION_MATCHER = PEP440_VERSION_RE + + SUMMARY_MATCHER = re.compile('.{1,2047}') + + METADATA_VERSION = '2.0' + + GENERATOR = 'distlib (%s)' % __version__ + + MANDATORY_KEYS = { + 'name': (), + 'version': (), + 'summary': ('legacy', ), + } + + INDEX_KEYS = ('name version license summary description author ' + 'author_email keywords platform home_page classifiers ' + 'download_url') + + DEPENDENCY_KEYS = ('extras run_requires test_requires build_requires ' + 'dev_requires provides meta_requires obsoleted_by ' + 'supports_environments') + + SYNTAX_VALIDATORS = { + 'metadata_version': (METADATA_VERSION_MATCHER, ()), + 'name': (NAME_MATCHER, ('legacy', )), + 'version': (VERSION_MATCHER, ('legacy', )), + 'summary': (SUMMARY_MATCHER, ('legacy', )), + 'dynamic': (FIELDNAME_MATCHER, ('legacy', )), + } + + __slots__ = ('_legacy', '_data', 'scheme') + + def __init__(self, path=None, fileobj=None, mapping=None, scheme='default'): + if [path, fileobj, mapping].count(None) < 2: + raise TypeError('path, fileobj and mapping are exclusive') + self._legacy = None + self._data = None + self.scheme = scheme + # import pdb; pdb.set_trace() + if mapping is not None: + try: + self._validate_mapping(mapping, scheme) + self._data = mapping + except MetadataUnrecognizedVersionError: + self._legacy = LegacyMetadata(mapping=mapping, scheme=scheme) + self.validate() + else: + data = None + if path: + with open(path, 'rb') as f: + data = f.read() + elif fileobj: + data = fileobj.read() + if data is None: + # Initialised with no args - to be added + self._data = { + 'metadata_version': self.METADATA_VERSION, + 'generator': self.GENERATOR, + } + else: + if not isinstance(data, text_type): + data = data.decode('utf-8') + try: + self._data = json.loads(data) + self._validate_mapping(self._data, scheme) + except ValueError: + # Note: MetadataUnrecognizedVersionError does not + # inherit from ValueError (it's a DistlibException, + # which should not inherit from ValueError). + # The ValueError comes from the json.load - if that + # succeeds and we get a validation error, we want + # that to propagate + self._legacy = LegacyMetadata(fileobj=StringIO(data), scheme=scheme) + self.validate() + + common_keys = set(('name', 'version', 'license', 'keywords', 'summary')) + + none_list = (None, list) + none_dict = (None, dict) + + mapped_keys = { + 'run_requires': ('Requires-Dist', list), + 'build_requires': ('Setup-Requires-Dist', list), + 'dev_requires': none_list, + 'test_requires': none_list, + 'meta_requires': none_list, + 'extras': ('Provides-Extra', list), + 'modules': none_list, + 'namespaces': none_list, + 'exports': none_dict, + 'commands': none_dict, + 'classifiers': ('Classifier', list), + 'source_url': ('Download-URL', None), + 'metadata_version': ('Metadata-Version', None), + } + + del none_list, none_dict + + def __getattribute__(self, key): + common = object.__getattribute__(self, 'common_keys') + mapped = object.__getattribute__(self, 'mapped_keys') + if key in mapped: + lk, maker = mapped[key] + if self._legacy: + if lk is None: + result = None if maker is None else maker() + else: + result = self._legacy.get(lk) + else: + value = None if maker is None else maker() + if key not in ('commands', 'exports', 'modules', 'namespaces', 'classifiers'): + result = self._data.get(key, value) + else: + # special cases for PEP 459 + sentinel = object() + result = sentinel + d = self._data.get('extensions') + if d: + if key == 'commands': + result = d.get('python.commands', value) + elif key == 'classifiers': + d = d.get('python.details') + if d: + result = d.get(key, value) + else: + d = d.get('python.exports') + if not d: + d = self._data.get('python.exports') + if d: + result = d.get(key, value) + if result is sentinel: + result = value + elif key not in common: + result = object.__getattribute__(self, key) + elif self._legacy: + result = self._legacy.get(key) + else: + result = self._data.get(key) + return result + + def _validate_value(self, key, value, scheme=None): + if key in self.SYNTAX_VALIDATORS: + pattern, exclusions = self.SYNTAX_VALIDATORS[key] + if (scheme or self.scheme) not in exclusions: + m = pattern.match(value) + if not m: + raise MetadataInvalidError("'%s' is an invalid value for " + "the '%s' property" % (value, key)) + + def __setattr__(self, key, value): + self._validate_value(key, value) + common = object.__getattribute__(self, 'common_keys') + mapped = object.__getattribute__(self, 'mapped_keys') + if key in mapped: + lk, _ = mapped[key] + if self._legacy: + if lk is None: + raise NotImplementedError + self._legacy[lk] = value + elif key not in ('commands', 'exports', 'modules', 'namespaces', 'classifiers'): + self._data[key] = value + else: + # special cases for PEP 459 + d = self._data.setdefault('extensions', {}) + if key == 'commands': + d['python.commands'] = value + elif key == 'classifiers': + d = d.setdefault('python.details', {}) + d[key] = value + else: + d = d.setdefault('python.exports', {}) + d[key] = value + elif key not in common: + object.__setattr__(self, key, value) + else: + if key == 'keywords': + if isinstance(value, string_types): + value = value.strip() + if value: + value = value.split() + else: + value = [] + if self._legacy: + self._legacy[key] = value + else: + self._data[key] = value + + @property + def name_and_version(self): + return _get_name_and_version(self.name, self.version, True) + + @property + def provides(self): + if self._legacy: + result = self._legacy['Provides-Dist'] + else: + result = self._data.setdefault('provides', []) + s = '%s (%s)' % (self.name, self.version) + if s not in result: + result.append(s) + return result + + @provides.setter + def provides(self, value): + if self._legacy: + self._legacy['Provides-Dist'] = value + else: + self._data['provides'] = value + + def get_requirements(self, reqts, extras=None, env=None): + """ + Base method to get dependencies, given a set of extras + to satisfy and an optional environment context. + :param reqts: A list of sometimes-wanted dependencies, + perhaps dependent on extras and environment. + :param extras: A list of optional components being requested. + :param env: An optional environment for marker evaluation. + """ + if self._legacy: + result = reqts + else: + result = [] + extras = get_extras(extras or [], self.extras) + for d in reqts: + if 'extra' not in d and 'environment' not in d: + # unconditional + include = True + else: + if 'extra' not in d: + # Not extra-dependent - only environment-dependent + include = True + else: + include = d.get('extra') in extras + if include: + # Not excluded because of extras, check environment + marker = d.get('environment') + if marker: + include = interpret(marker, env) + if include: + result.extend(d['requires']) + for key in ('build', 'dev', 'test'): + e = ':%s:' % key + if e in extras: + extras.remove(e) + # A recursive call, but it should terminate since 'test' + # has been removed from the extras + reqts = self._data.get('%s_requires' % key, []) + result.extend(self.get_requirements(reqts, extras=extras, env=env)) + return result + + @property + def dictionary(self): + if self._legacy: + return self._from_legacy() + return self._data + + @property + def dependencies(self): + if self._legacy: + raise NotImplementedError + else: + return extract_by_key(self._data, self.DEPENDENCY_KEYS) + + @dependencies.setter + def dependencies(self, value): + if self._legacy: + raise NotImplementedError + else: + self._data.update(value) + + def _validate_mapping(self, mapping, scheme): + if mapping.get('metadata_version') != self.METADATA_VERSION: + raise MetadataUnrecognizedVersionError() + missing = [] + for key, exclusions in self.MANDATORY_KEYS.items(): + if key not in mapping: + if scheme not in exclusions: + missing.append(key) + if missing: + msg = 'Missing metadata items: %s' % ', '.join(missing) + raise MetadataMissingError(msg) + for k, v in mapping.items(): + self._validate_value(k, v, scheme) + + def validate(self): + if self._legacy: + missing, warnings = self._legacy.check(True) + if missing or warnings: + logger.warning('Metadata: missing: %s, warnings: %s', missing, warnings) + else: + self._validate_mapping(self._data, self.scheme) + + def todict(self): + if self._legacy: + return self._legacy.todict(True) + else: + result = extract_by_key(self._data, self.INDEX_KEYS) + return result + + def _from_legacy(self): + assert self._legacy and not self._data + result = { + 'metadata_version': self.METADATA_VERSION, + 'generator': self.GENERATOR, + } + lmd = self._legacy.todict(True) # skip missing ones + for k in ('name', 'version', 'license', 'summary', 'description', 'classifier'): + if k in lmd: + if k == 'classifier': + nk = 'classifiers' + else: + nk = k + result[nk] = lmd[k] + kw = lmd.get('Keywords', []) + if kw == ['']: + kw = [] + result['keywords'] = kw + keys = (('requires_dist', 'run_requires'), ('setup_requires_dist', 'build_requires')) + for ok, nk in keys: + if ok in lmd and lmd[ok]: + result[nk] = [{'requires': lmd[ok]}] + result['provides'] = self.provides + # author = {} + # maintainer = {} + return result + + LEGACY_MAPPING = { + 'name': 'Name', + 'version': 'Version', + ('extensions', 'python.details', 'license'): 'License', + 'summary': 'Summary', + 'description': 'Description', + ('extensions', 'python.project', 'project_urls', 'Home'): 'Home-page', + ('extensions', 'python.project', 'contacts', 0, 'name'): 'Author', + ('extensions', 'python.project', 'contacts', 0, 'email'): 'Author-email', + 'source_url': 'Download-URL', + ('extensions', 'python.details', 'classifiers'): 'Classifier', + } + + def _to_legacy(self): + + def process_entries(entries): + reqts = set() + for e in entries: + extra = e.get('extra') + env = e.get('environment') + rlist = e['requires'] + for r in rlist: + if not env and not extra: + reqts.add(r) + else: + marker = '' + if extra: + marker = 'extra == "%s"' % extra + if env: + if marker: + marker = '(%s) and %s' % (env, marker) + else: + marker = env + reqts.add(';'.join((r, marker))) + return reqts + + assert self._data and not self._legacy + result = LegacyMetadata() + nmd = self._data + # import pdb; pdb.set_trace() + for nk, ok in self.LEGACY_MAPPING.items(): + if not isinstance(nk, tuple): + if nk in nmd: + result[ok] = nmd[nk] + else: + d = nmd + found = True + for k in nk: + try: + d = d[k] + except (KeyError, IndexError): + found = False + break + if found: + result[ok] = d + r1 = process_entries(self.run_requires + self.meta_requires) + r2 = process_entries(self.build_requires + self.dev_requires) + if self.extras: + result['Provides-Extra'] = sorted(self.extras) + result['Requires-Dist'] = sorted(r1) + result['Setup-Requires-Dist'] = sorted(r2) + # TODO: any other fields wanted + return result + + def write(self, path=None, fileobj=None, legacy=False, skip_unknown=True): + if [path, fileobj].count(None) != 1: + raise ValueError('Exactly one of path and fileobj is needed') + self.validate() + if legacy: + if self._legacy: + legacy_md = self._legacy + else: + legacy_md = self._to_legacy() + if path: + legacy_md.write(path, skip_unknown=skip_unknown) + else: + legacy_md.write_file(fileobj, skip_unknown=skip_unknown) + else: + if self._legacy: + d = self._from_legacy() + else: + d = self._data + if fileobj: + json.dump(d, fileobj, ensure_ascii=True, indent=2, sort_keys=True) + else: + with codecs.open(path, 'w', 'utf-8') as f: + json.dump(d, f, ensure_ascii=True, indent=2, sort_keys=True) + + def add_requirements(self, requirements): + if self._legacy: + self._legacy.add_requirements(requirements) + else: + run_requires = self._data.setdefault('run_requires', []) + always = None + for entry in run_requires: + if 'environment' not in entry and 'extra' not in entry: + always = entry + break + if always is None: + always = {'requires': requirements} + run_requires.insert(0, always) + else: + rset = set(always['requires']) | set(requirements) + always['requires'] = sorted(rset) + + def __repr__(self): + name = self.name or '(no name)' + version = self.version or 'no version' + return '<%s %s %s (%s)>' % (self.__class__.__name__, self.metadata_version, name, version) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/resources.py b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/resources.py new file mode 100644 index 0000000..fef52aa --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/resources.py @@ -0,0 +1,358 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013-2017 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +from __future__ import unicode_literals + +import bisect +import io +import logging +import os +import pkgutil +import sys +import types +import zipimport + +from . import DistlibException +from .util import cached_property, get_cache_base, Cache + +logger = logging.getLogger(__name__) + + +cache = None # created when needed + + +class ResourceCache(Cache): + def __init__(self, base=None): + if base is None: + # Use native string to avoid issues on 2.x: see Python #20140. + base = os.path.join(get_cache_base(), str('resource-cache')) + super(ResourceCache, self).__init__(base) + + def is_stale(self, resource, path): + """ + Is the cache stale for the given resource? + + :param resource: The :class:`Resource` being cached. + :param path: The path of the resource in the cache. + :return: True if the cache is stale. + """ + # Cache invalidation is a hard problem :-) + return True + + def get(self, resource): + """ + Get a resource into the cache, + + :param resource: A :class:`Resource` instance. + :return: The pathname of the resource in the cache. + """ + prefix, path = resource.finder.get_cache_info(resource) + if prefix is None: + result = path + else: + result = os.path.join(self.base, self.prefix_to_dir(prefix), path) + dirname = os.path.dirname(result) + if not os.path.isdir(dirname): + os.makedirs(dirname) + if not os.path.exists(result): + stale = True + else: + stale = self.is_stale(resource, path) + if stale: + # write the bytes of the resource to the cache location + with open(result, 'wb') as f: + f.write(resource.bytes) + return result + + +class ResourceBase(object): + def __init__(self, finder, name): + self.finder = finder + self.name = name + + +class Resource(ResourceBase): + """ + A class representing an in-package resource, such as a data file. This is + not normally instantiated by user code, but rather by a + :class:`ResourceFinder` which manages the resource. + """ + is_container = False # Backwards compatibility + + def as_stream(self): + """ + Get the resource as a stream. + + This is not a property to make it obvious that it returns a new stream + each time. + """ + return self.finder.get_stream(self) + + @cached_property + def file_path(self): + global cache + if cache is None: + cache = ResourceCache() + return cache.get(self) + + @cached_property + def bytes(self): + return self.finder.get_bytes(self) + + @cached_property + def size(self): + return self.finder.get_size(self) + + +class ResourceContainer(ResourceBase): + is_container = True # Backwards compatibility + + @cached_property + def resources(self): + return self.finder.get_resources(self) + + +class ResourceFinder(object): + """ + Resource finder for file system resources. + """ + + if sys.platform.startswith('java'): + skipped_extensions = ('.pyc', '.pyo', '.class') + else: + skipped_extensions = ('.pyc', '.pyo') + + def __init__(self, module): + self.module = module + self.loader = getattr(module, '__loader__', None) + self.base = os.path.dirname(getattr(module, '__file__', '')) + + def _adjust_path(self, path): + return os.path.realpath(path) + + def _make_path(self, resource_name): + # Issue #50: need to preserve type of path on Python 2.x + # like os.path._get_sep + if isinstance(resource_name, bytes): # should only happen on 2.x + sep = b'/' + else: + sep = '/' + parts = resource_name.split(sep) + parts.insert(0, self.base) + result = os.path.join(*parts) + return self._adjust_path(result) + + def _find(self, path): + return os.path.exists(path) + + def get_cache_info(self, resource): + return None, resource.path + + def find(self, resource_name): + path = self._make_path(resource_name) + if not self._find(path): + result = None + else: + if self._is_directory(path): + result = ResourceContainer(self, resource_name) + else: + result = Resource(self, resource_name) + result.path = path + return result + + def get_stream(self, resource): + return open(resource.path, 'rb') + + def get_bytes(self, resource): + with open(resource.path, 'rb') as f: + return f.read() + + def get_size(self, resource): + return os.path.getsize(resource.path) + + def get_resources(self, resource): + def allowed(f): + return (f != '__pycache__' and not + f.endswith(self.skipped_extensions)) + return set([f for f in os.listdir(resource.path) if allowed(f)]) + + def is_container(self, resource): + return self._is_directory(resource.path) + + _is_directory = staticmethod(os.path.isdir) + + def iterator(self, resource_name): + resource = self.find(resource_name) + if resource is not None: + todo = [resource] + while todo: + resource = todo.pop(0) + yield resource + if resource.is_container: + rname = resource.name + for name in resource.resources: + if not rname: + new_name = name + else: + new_name = '/'.join([rname, name]) + child = self.find(new_name) + if child.is_container: + todo.append(child) + else: + yield child + + +class ZipResourceFinder(ResourceFinder): + """ + Resource finder for resources in .zip files. + """ + def __init__(self, module): + super(ZipResourceFinder, self).__init__(module) + archive = self.loader.archive + self.prefix_len = 1 + len(archive) + # PyPy doesn't have a _files attr on zipimporter, and you can't set one + if hasattr(self.loader, '_files'): + self._files = self.loader._files + else: + self._files = zipimport._zip_directory_cache[archive] + self.index = sorted(self._files) + + def _adjust_path(self, path): + return path + + def _find(self, path): + path = path[self.prefix_len:] + if path in self._files: + result = True + else: + if path and path[-1] != os.sep: + path = path + os.sep + i = bisect.bisect(self.index, path) + try: + result = self.index[i].startswith(path) + except IndexError: + result = False + if not result: + logger.debug('_find failed: %r %r', path, self.loader.prefix) + else: + logger.debug('_find worked: %r %r', path, self.loader.prefix) + return result + + def get_cache_info(self, resource): + prefix = self.loader.archive + path = resource.path[1 + len(prefix):] + return prefix, path + + def get_bytes(self, resource): + return self.loader.get_data(resource.path) + + def get_stream(self, resource): + return io.BytesIO(self.get_bytes(resource)) + + def get_size(self, resource): + path = resource.path[self.prefix_len:] + return self._files[path][3] + + def get_resources(self, resource): + path = resource.path[self.prefix_len:] + if path and path[-1] != os.sep: + path += os.sep + plen = len(path) + result = set() + i = bisect.bisect(self.index, path) + while i < len(self.index): + if not self.index[i].startswith(path): + break + s = self.index[i][plen:] + result.add(s.split(os.sep, 1)[0]) # only immediate children + i += 1 + return result + + def _is_directory(self, path): + path = path[self.prefix_len:] + if path and path[-1] != os.sep: + path += os.sep + i = bisect.bisect(self.index, path) + try: + result = self.index[i].startswith(path) + except IndexError: + result = False + return result + + +_finder_registry = { + type(None): ResourceFinder, + zipimport.zipimporter: ZipResourceFinder +} + +try: + # In Python 3.6, _frozen_importlib -> _frozen_importlib_external + try: + import _frozen_importlib_external as _fi + except ImportError: + import _frozen_importlib as _fi + _finder_registry[_fi.SourceFileLoader] = ResourceFinder + _finder_registry[_fi.FileFinder] = ResourceFinder + # See issue #146 + _finder_registry[_fi.SourcelessFileLoader] = ResourceFinder + del _fi +except (ImportError, AttributeError): + pass + + +def register_finder(loader, finder_maker): + _finder_registry[type(loader)] = finder_maker + + +_finder_cache = {} + + +def finder(package): + """ + Return a resource finder for a package. + :param package: The name of the package. + :return: A :class:`ResourceFinder` instance for the package. + """ + if package in _finder_cache: + result = _finder_cache[package] + else: + if package not in sys.modules: + __import__(package) + module = sys.modules[package] + path = getattr(module, '__path__', None) + if path is None: + raise DistlibException('You cannot get a finder for a module, ' + 'only for a package') + loader = getattr(module, '__loader__', None) + finder_maker = _finder_registry.get(type(loader)) + if finder_maker is None: + raise DistlibException('Unable to locate finder for %r' % package) + result = finder_maker(module) + _finder_cache[package] = result + return result + + +_dummy_module = types.ModuleType(str('__dummy__')) + + +def finder_for_path(path): + """ + Return a resource finder for a path, which should represent a container. + + :param path: The path. + :return: A :class:`ResourceFinder` instance for the path. + """ + result = None + # calls any path hooks, gets importer into cache + pkgutil.get_importer(path) + loader = sys.path_importer_cache.get(path) + finder = _finder_registry.get(type(loader)) + if finder: + module = _dummy_module + module.__file__ = os.path.join(path, '') + module.__loader__ = loader + result = finder(module) + return result diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/scripts.py b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/scripts.py new file mode 100644 index 0000000..b1fc705 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/scripts.py @@ -0,0 +1,447 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013-2023 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +from io import BytesIO +import logging +import os +import re +import struct +import sys +import time +from zipfile import ZipInfo + +from .compat import sysconfig, detect_encoding, ZipFile +from .resources import finder +from .util import (FileOperator, get_export_entry, convert_path, get_executable, get_platform, in_venv) + +logger = logging.getLogger(__name__) + +_DEFAULT_MANIFEST = ''' + + + + + + + + + + + + +'''.strip() + +# check if Python is called on the first line with this expression +FIRST_LINE_RE = re.compile(b'^#!.*pythonw?[0-9.]*([ \t].*)?$') +SCRIPT_TEMPLATE = r'''# -*- coding: utf-8 -*- +import re +import sys +from %(module)s import %(import_name)s +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(%(func)s()) +''' + +# Pre-fetch the contents of all executable wrapper stubs. +# This is to address https://github.com/pypa/pip/issues/12666. +# When updating pip, we rename the old pip in place before installing the +# new version. If we try to fetch a wrapper *after* that rename, the finder +# machinery will be confused as the package is no longer available at the +# location where it was imported from. So we load everything into memory in +# advance. + +if os.name == 'nt' or (os.name == 'java' and os._name == 'nt'): + # Issue 31: don't hardcode an absolute package name, but + # determine it relative to the current package + DISTLIB_PACKAGE = __name__.rsplit('.', 1)[0] + + WRAPPERS = { + r.name: r.bytes + for r in finder(DISTLIB_PACKAGE).iterator("") + if r.name.endswith(".exe") + } + + +def enquote_executable(executable): + if ' ' in executable: + # make sure we quote only the executable in case of env + # for example /usr/bin/env "/dir with spaces/bin/jython" + # instead of "/usr/bin/env /dir with spaces/bin/jython" + # otherwise whole + if executable.startswith('/usr/bin/env '): + env, _executable = executable.split(' ', 1) + if ' ' in _executable and not _executable.startswith('"'): + executable = '%s "%s"' % (env, _executable) + else: + if not executable.startswith('"'): + executable = '"%s"' % executable + return executable + + +# Keep the old name around (for now), as there is at least one project using it! +_enquote_executable = enquote_executable + + +class ScriptMaker(object): + """ + A class to copy or create scripts from source scripts or callable + specifications. + """ + script_template = SCRIPT_TEMPLATE + + executable = None # for shebangs + + def __init__(self, source_dir, target_dir, add_launchers=True, dry_run=False, fileop=None): + self.source_dir = source_dir + self.target_dir = target_dir + self.add_launchers = add_launchers + self.force = False + self.clobber = False + # It only makes sense to set mode bits on POSIX. + self.set_mode = (os.name == 'posix') or (os.name == 'java' and os._name == 'posix') + self.variants = set(('', 'X.Y')) + self._fileop = fileop or FileOperator(dry_run) + + self._is_nt = os.name == 'nt' or (os.name == 'java' and os._name == 'nt') + self.version_info = sys.version_info + + def _get_alternate_executable(self, executable, options): + if options.get('gui', False) and self._is_nt: # pragma: no cover + dn, fn = os.path.split(executable) + fn = fn.replace('python', 'pythonw') + executable = os.path.join(dn, fn) + return executable + + if sys.platform.startswith('java'): # pragma: no cover + + def _is_shell(self, executable): + """ + Determine if the specified executable is a script + (contains a #! line) + """ + try: + with open(executable) as fp: + return fp.read(2) == '#!' + except (OSError, IOError): + logger.warning('Failed to open %s', executable) + return False + + def _fix_jython_executable(self, executable): + if self._is_shell(executable): + # Workaround for Jython is not needed on Linux systems. + import java + + if java.lang.System.getProperty('os.name') == 'Linux': + return executable + elif executable.lower().endswith('jython.exe'): + # Use wrapper exe for Jython on Windows + return executable + return '/usr/bin/env %s' % executable + + def _build_shebang(self, executable, post_interp): + """ + Build a shebang line. In the simple case (on Windows, or a shebang line + which is not too long or contains spaces) use a simple formulation for + the shebang. Otherwise, use /bin/sh as the executable, with a contrived + shebang which allows the script to run either under Python or sh, using + suitable quoting. Thanks to Harald Nordgren for his input. + + See also: http://www.in-ulm.de/~mascheck/various/shebang/#length + https://hg.mozilla.org/mozilla-central/file/tip/mach + """ + if os.name != 'posix': + simple_shebang = True + elif getattr(sys, "cross_compiling", False): + # In a cross-compiling environment, the shebang will likely be a + # script; this *must* be invoked with the "safe" version of the + # shebang, or else using os.exec() to run the entry script will + # fail, raising "OSError 8 [Errno 8] Exec format error". + simple_shebang = False + else: + # Add 3 for '#!' prefix and newline suffix. + shebang_length = len(executable) + len(post_interp) + 3 + if sys.platform == 'darwin': + max_shebang_length = 512 + else: + max_shebang_length = 127 + simple_shebang = ((b' ' not in executable) and (shebang_length <= max_shebang_length)) + + if simple_shebang: + result = b'#!' + executable + post_interp + b'\n' + else: + result = b'#!/bin/sh\n' + result += b"'''exec' " + executable + post_interp + b' "$0" "$@"\n' + result += b"' '''\n" + return result + + def _get_shebang(self, encoding, post_interp=b'', options=None): + enquote = True + if self.executable: + executable = self.executable + enquote = False # assume this will be taken care of + elif not sysconfig.is_python_build(): + executable = get_executable() + elif in_venv(): # pragma: no cover + executable = os.path.join(sysconfig.get_path('scripts'), 'python%s' % sysconfig.get_config_var('EXE')) + else: # pragma: no cover + if os.name == 'nt': + # for Python builds from source on Windows, no Python executables with + # a version suffix are created, so we use python.exe + executable = os.path.join(sysconfig.get_config_var('BINDIR'), + 'python%s' % (sysconfig.get_config_var('EXE'))) + else: + executable = os.path.join( + sysconfig.get_config_var('BINDIR'), + 'python%s%s' % (sysconfig.get_config_var('VERSION'), sysconfig.get_config_var('EXE'))) + if options: + executable = self._get_alternate_executable(executable, options) + + if sys.platform.startswith('java'): # pragma: no cover + executable = self._fix_jython_executable(executable) + + # Normalise case for Windows - COMMENTED OUT + # executable = os.path.normcase(executable) + # N.B. The normalising operation above has been commented out: See + # issue #124. Although paths in Windows are generally case-insensitive, + # they aren't always. For example, a path containing a ẞ (which is a + # LATIN CAPITAL LETTER SHARP S - U+1E9E) is normcased to ß (which is a + # LATIN SMALL LETTER SHARP S' - U+00DF). The two are not considered by + # Windows as equivalent in path names. + + # If the user didn't specify an executable, it may be necessary to + # cater for executable paths with spaces (not uncommon on Windows) + if enquote: + executable = enquote_executable(executable) + # Issue #51: don't use fsencode, since we later try to + # check that the shebang is decodable using utf-8. + executable = executable.encode('utf-8') + # in case of IronPython, play safe and enable frames support + if (sys.platform == 'cli' and '-X:Frames' not in post_interp and + '-X:FullFrames' not in post_interp): # pragma: no cover + post_interp += b' -X:Frames' + shebang = self._build_shebang(executable, post_interp) + # Python parser starts to read a script using UTF-8 until + # it gets a #coding:xxx cookie. The shebang has to be the + # first line of a file, the #coding:xxx cookie cannot be + # written before. So the shebang has to be decodable from + # UTF-8. + try: + shebang.decode('utf-8') + except UnicodeDecodeError: # pragma: no cover + raise ValueError('The shebang (%r) is not decodable from utf-8' % shebang) + # If the script is encoded to a custom encoding (use a + # #coding:xxx cookie), the shebang has to be decodable from + # the script encoding too. + if encoding != 'utf-8': + try: + shebang.decode(encoding) + except UnicodeDecodeError: # pragma: no cover + raise ValueError('The shebang (%r) is not decodable ' + 'from the script encoding (%r)' % (shebang, encoding)) + return shebang + + def _get_script_text(self, entry): + return self.script_template % dict( + module=entry.prefix, import_name=entry.suffix.split('.')[0], func=entry.suffix) + + manifest = _DEFAULT_MANIFEST + + def get_manifest(self, exename): + base = os.path.basename(exename) + return self.manifest % base + + def _write_script(self, names, shebang, script_bytes, filenames, ext): + use_launcher = self.add_launchers and self._is_nt + if not use_launcher: + script_bytes = shebang + script_bytes + else: # pragma: no cover + if ext == 'py': + launcher = self._get_launcher('t') + else: + launcher = self._get_launcher('w') + stream = BytesIO() + with ZipFile(stream, 'w') as zf: + source_date_epoch = os.environ.get('SOURCE_DATE_EPOCH') + if source_date_epoch: + date_time = time.gmtime(int(source_date_epoch))[:6] + zinfo = ZipInfo(filename='__main__.py', date_time=date_time) + zf.writestr(zinfo, script_bytes) + else: + zf.writestr('__main__.py', script_bytes) + zip_data = stream.getvalue() + script_bytes = launcher + shebang + zip_data + for name in names: + outname = os.path.join(self.target_dir, name) + if use_launcher: # pragma: no cover + n, e = os.path.splitext(outname) + if e.startswith('.py'): + outname = n + outname = '%s.exe' % outname + try: + self._fileop.write_binary_file(outname, script_bytes) + except Exception: + # Failed writing an executable - it might be in use. + logger.warning('Failed to write executable - trying to ' + 'use .deleteme logic') + dfname = '%s.deleteme' % outname + if os.path.exists(dfname): + os.remove(dfname) # Not allowed to fail here + os.rename(outname, dfname) # nor here + self._fileop.write_binary_file(outname, script_bytes) + logger.debug('Able to replace executable using ' + '.deleteme logic') + try: + os.remove(dfname) + except Exception: + pass # still in use - ignore error + else: + if self._is_nt and not outname.endswith('.' + ext): # pragma: no cover + outname = '%s.%s' % (outname, ext) + if os.path.exists(outname) and not self.clobber: + logger.warning('Skipping existing file %s', outname) + continue + self._fileop.write_binary_file(outname, script_bytes) + if self.set_mode: + self._fileop.set_executable_mode([outname]) + filenames.append(outname) + + variant_separator = '-' + + def get_script_filenames(self, name): + result = set() + if '' in self.variants: + result.add(name) + if 'X' in self.variants: + result.add('%s%s' % (name, self.version_info[0])) + if 'X.Y' in self.variants: + result.add('%s%s%s.%s' % (name, self.variant_separator, self.version_info[0], self.version_info[1])) + return result + + def _make_script(self, entry, filenames, options=None): + post_interp = b'' + if options: + args = options.get('interpreter_args', []) + if args: + args = ' %s' % ' '.join(args) + post_interp = args.encode('utf-8') + shebang = self._get_shebang('utf-8', post_interp, options=options) + script = self._get_script_text(entry).encode('utf-8') + scriptnames = self.get_script_filenames(entry.name) + if options and options.get('gui', False): + ext = 'pyw' + else: + ext = 'py' + self._write_script(scriptnames, shebang, script, filenames, ext) + + def _copy_script(self, script, filenames): + adjust = False + script = os.path.join(self.source_dir, convert_path(script)) + outname = os.path.join(self.target_dir, os.path.basename(script)) + if not self.force and not self._fileop.newer(script, outname): + logger.debug('not copying %s (up-to-date)', script) + return + + # Always open the file, but ignore failures in dry-run mode -- + # that way, we'll get accurate feedback if we can read the + # script. + try: + f = open(script, 'rb') + except IOError: # pragma: no cover + if not self.dry_run: + raise + f = None + else: + first_line = f.readline() + if not first_line: # pragma: no cover + logger.warning('%s is an empty file (skipping)', script) + return + + match = FIRST_LINE_RE.match(first_line.replace(b'\r\n', b'\n')) + if match: + adjust = True + post_interp = match.group(1) or b'' + + if not adjust: + if f: + f.close() + self._fileop.copy_file(script, outname) + if self.set_mode: + self._fileop.set_executable_mode([outname]) + filenames.append(outname) + else: + logger.info('copying and adjusting %s -> %s', script, self.target_dir) + if not self._fileop.dry_run: + encoding, lines = detect_encoding(f.readline) + f.seek(0) + shebang = self._get_shebang(encoding, post_interp) + if b'pythonw' in first_line: # pragma: no cover + ext = 'pyw' + else: + ext = 'py' + n = os.path.basename(outname) + self._write_script([n], shebang, f.read(), filenames, ext) + if f: + f.close() + + @property + def dry_run(self): + return self._fileop.dry_run + + @dry_run.setter + def dry_run(self, value): + self._fileop.dry_run = value + + if os.name == 'nt' or (os.name == 'java' and os._name == 'nt'): # pragma: no cover + # Executable launcher support. + # Launchers are from https://bitbucket.org/vinay.sajip/simple_launcher/ + + def _get_launcher(self, kind): + if struct.calcsize('P') == 8: # 64-bit + bits = '64' + else: + bits = '32' + platform_suffix = '-arm' if get_platform() == 'win-arm64' else '' + name = '%s%s%s.exe' % (kind, bits, platform_suffix) + if name not in WRAPPERS: + msg = ('Unable to find resource %s in package %s' % + (name, DISTLIB_PACKAGE)) + raise ValueError(msg) + return WRAPPERS[name] + + # Public API follows + + def make(self, specification, options=None): + """ + Make a script. + + :param specification: The specification, which is either a valid export + entry specification (to make a script from a + callable) or a filename (to make a script by + copying from a source location). + :param options: A dictionary of options controlling script generation. + :return: A list of all absolute pathnames written to. + """ + filenames = [] + entry = get_export_entry(specification) + if entry is None: + self._copy_script(specification, filenames) + else: + self._make_script(entry, filenames, options=options) + return filenames + + def make_multiple(self, specifications, options=None): + """ + Take a list of specifications and make scripts from them, + :param specifications: A list of specifications. + :return: A list of all absolute pathnames written to, + """ + filenames = [] + for specification in specifications: + filenames.extend(self.make(specification, options)) + return filenames diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/t32.exe b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/t32.exe new file mode 100644 index 0000000000000000000000000000000000000000..52154f0be32cc2bdbf98af131d477900667d0abd GIT binary patch literal 97792 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

XMwe#*Lv$g8jIpIBEV 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 w+IyK^N3WCD*(>mhAj=irKyR>D9b+D<@QBhV6U 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

qx{CqlSNQ_YhQ()VtG-D; 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 z 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 bB!6W7g#4-b3-g!cLzth+PZapSNrC?c%T_@< literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/wheel.py b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/wheel.py new file mode 100644 index 0000000..62ab10f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/wheel.py @@ -0,0 +1,1100 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013-2023 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +from __future__ import unicode_literals + +import base64 +import codecs +import datetime +from email import message_from_file +import hashlib +import json +import logging +import os +import posixpath +import re +import shutil +import sys +import tempfile +import zipfile + +from . import __version__, DistlibException +from .compat import sysconfig, ZipFile, fsdecode, text_type, filter +from .database import InstalledDistribution +from .metadata import Metadata, WHEEL_METADATA_FILENAME, LEGACY_METADATA_FILENAME +from .util import (FileOperator, convert_path, CSVReader, CSVWriter, Cache, cached_property, get_cache_base, + read_exports, tempdir, get_platform) +from .version import NormalizedVersion, UnsupportedVersionError + +logger = logging.getLogger(__name__) + +cache = None # created when needed + +if hasattr(sys, 'pypy_version_info'): # pragma: no cover + IMP_PREFIX = 'pp' +elif sys.platform.startswith('java'): # pragma: no cover + IMP_PREFIX = 'jy' +elif sys.platform == 'cli': # pragma: no cover + IMP_PREFIX = 'ip' +else: + IMP_PREFIX = 'cp' + +VER_SUFFIX = sysconfig.get_config_var('py_version_nodot') +if not VER_SUFFIX: # pragma: no cover + VER_SUFFIX = '%s%s' % sys.version_info[:2] +PYVER = 'py' + VER_SUFFIX +IMPVER = IMP_PREFIX + VER_SUFFIX + +ARCH = get_platform().replace('-', '_').replace('.', '_') + +ABI = sysconfig.get_config_var('SOABI') +if ABI and ABI.startswith('cpython-'): + ABI = ABI.replace('cpython-', 'cp').split('-')[0] +else: + + def _derive_abi(): + parts = ['cp', VER_SUFFIX] + if sysconfig.get_config_var('Py_DEBUG'): + parts.append('d') + if IMP_PREFIX == 'cp': + vi = sys.version_info[:2] + if vi < (3, 8): + wpm = sysconfig.get_config_var('WITH_PYMALLOC') + if wpm is None: + wpm = True + if wpm: + parts.append('m') + if vi < (3, 3): + us = sysconfig.get_config_var('Py_UNICODE_SIZE') + if us == 4 or (us is None and sys.maxunicode == 0x10FFFF): + parts.append('u') + return ''.join(parts) + + ABI = _derive_abi() + del _derive_abi + +FILENAME_RE = re.compile( + r''' +(?P[^-]+) +-(?P\d+[^-]*) +(-(?P\d+[^-]*))? +-(?P\w+\d+(\.\w+\d+)*) +-(?P\w+) +-(?P\w+(\.\w+)*) +\.whl$ +''', re.IGNORECASE | re.VERBOSE) + +NAME_VERSION_RE = re.compile(r''' +(?P[^-]+) +-(?P\d+[^-]*) +(-(?P\d+[^-]*))?$ +''', re.IGNORECASE | re.VERBOSE) + +SHEBANG_RE = re.compile(br'\s*#![^\r\n]*') +SHEBANG_DETAIL_RE = re.compile(br'^(\s*#!("[^"]+"|\S+))\s+(.*)$') +SHEBANG_PYTHON = b'#!python' +SHEBANG_PYTHONW = b'#!pythonw' + +if os.sep == '/': + to_posix = lambda o: o +else: + to_posix = lambda o: o.replace(os.sep, '/') + +if sys.version_info[0] < 3: + import imp +else: + imp = None + import importlib.machinery + import importlib.util + + +def _get_suffixes(): + if imp: + return [s[0] for s in imp.get_suffixes()] + else: + return importlib.machinery.EXTENSION_SUFFIXES + + +def _load_dynamic(name, path): + # https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly + if imp: + return imp.load_dynamic(name, path) + else: + spec = importlib.util.spec_from_file_location(name, path) + module = importlib.util.module_from_spec(spec) + sys.modules[name] = module + spec.loader.exec_module(module) + return module + + +class Mounter(object): + + def __init__(self): + self.impure_wheels = {} + self.libs = {} + + def add(self, pathname, extensions): + self.impure_wheels[pathname] = extensions + self.libs.update(extensions) + + def remove(self, pathname): + extensions = self.impure_wheels.pop(pathname) + for k, v in extensions: + if k in self.libs: + del self.libs[k] + + def find_module(self, fullname, path=None): + if fullname in self.libs: + result = self + else: + result = None + return result + + def load_module(self, fullname): + if fullname in sys.modules: + result = sys.modules[fullname] + else: + if fullname not in self.libs: + raise ImportError('unable to find extension for %s' % fullname) + result = _load_dynamic(fullname, self.libs[fullname]) + result.__loader__ = self + parts = fullname.rsplit('.', 1) + if len(parts) > 1: + result.__package__ = parts[0] + return result + + +_hook = Mounter() + + +class Wheel(object): + """ + Class to build and install from Wheel files (PEP 427). + """ + + wheel_version = (1, 1) + hash_kind = 'sha256' + + def __init__(self, filename=None, sign=False, verify=False): + """ + Initialise an instance using a (valid) filename. + """ + self.sign = sign + self.should_verify = verify + self.buildver = '' + self.pyver = [PYVER] + self.abi = ['none'] + self.arch = ['any'] + self.dirname = os.getcwd() + if filename is None: + self.name = 'dummy' + self.version = '0.1' + self._filename = self.filename + else: + m = NAME_VERSION_RE.match(filename) + if m: + info = m.groupdict('') + self.name = info['nm'] + # Reinstate the local version separator + self.version = info['vn'].replace('_', '-') + self.buildver = info['bn'] + self._filename = self.filename + else: + dirname, filename = os.path.split(filename) + m = FILENAME_RE.match(filename) + if not m: + raise DistlibException('Invalid name or ' + 'filename: %r' % filename) + if dirname: + self.dirname = os.path.abspath(dirname) + self._filename = filename + info = m.groupdict('') + self.name = info['nm'] + self.version = info['vn'] + self.buildver = info['bn'] + self.pyver = info['py'].split('.') + self.abi = info['bi'].split('.') + self.arch = info['ar'].split('.') + + @property + def filename(self): + """ + Build and return a filename from the various components. + """ + if self.buildver: + buildver = '-' + self.buildver + else: + buildver = '' + pyver = '.'.join(self.pyver) + abi = '.'.join(self.abi) + arch = '.'.join(self.arch) + # replace - with _ as a local version separator + version = self.version.replace('-', '_') + return '%s-%s%s-%s-%s-%s.whl' % (self.name, version, buildver, pyver, abi, arch) + + @property + def exists(self): + path = os.path.join(self.dirname, self.filename) + return os.path.isfile(path) + + @property + def tags(self): + for pyver in self.pyver: + for abi in self.abi: + for arch in self.arch: + yield pyver, abi, arch + + @cached_property + def metadata(self): + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + info_dir = '%s.dist-info' % name_ver + wrapper = codecs.getreader('utf-8') + with ZipFile(pathname, 'r') as zf: + self.get_wheel_metadata(zf) + # wv = wheel_metadata['Wheel-Version'].split('.', 1) + # file_version = tuple([int(i) for i in wv]) + # if file_version < (1, 1): + # fns = [WHEEL_METADATA_FILENAME, METADATA_FILENAME, + # LEGACY_METADATA_FILENAME] + # else: + # fns = [WHEEL_METADATA_FILENAME, METADATA_FILENAME] + fns = [WHEEL_METADATA_FILENAME, LEGACY_METADATA_FILENAME] + result = None + for fn in fns: + try: + metadata_filename = posixpath.join(info_dir, fn) + with zf.open(metadata_filename) as bf: + wf = wrapper(bf) + result = Metadata(fileobj=wf) + if result: + break + except KeyError: + pass + if not result: + raise ValueError('Invalid wheel, because metadata is ' + 'missing: looked in %s' % ', '.join(fns)) + return result + + def get_wheel_metadata(self, zf): + name_ver = '%s-%s' % (self.name, self.version) + info_dir = '%s.dist-info' % name_ver + metadata_filename = posixpath.join(info_dir, 'WHEEL') + with zf.open(metadata_filename) as bf: + wf = codecs.getreader('utf-8')(bf) + message = message_from_file(wf) + return dict(message) + + @cached_property + def info(self): + pathname = os.path.join(self.dirname, self.filename) + with ZipFile(pathname, 'r') as zf: + result = self.get_wheel_metadata(zf) + return result + + def process_shebang(self, data): + m = SHEBANG_RE.match(data) + if m: + end = m.end() + shebang, data_after_shebang = data[:end], data[end:] + # Preserve any arguments after the interpreter + if b'pythonw' in shebang.lower(): + shebang_python = SHEBANG_PYTHONW + else: + shebang_python = SHEBANG_PYTHON + m = SHEBANG_DETAIL_RE.match(shebang) + if m: + args = b' ' + m.groups()[-1] + else: + args = b'' + shebang = shebang_python + args + data = shebang + data_after_shebang + else: + cr = data.find(b'\r') + lf = data.find(b'\n') + if cr < 0 or cr > lf: + term = b'\n' + else: + if data[cr:cr + 2] == b'\r\n': + term = b'\r\n' + else: + term = b'\r' + data = SHEBANG_PYTHON + term + data + return data + + def get_hash(self, data, hash_kind=None): + if hash_kind is None: + hash_kind = self.hash_kind + try: + hasher = getattr(hashlib, hash_kind) + except AttributeError: + raise DistlibException('Unsupported hash algorithm: %r' % hash_kind) + result = hasher(data).digest() + result = base64.urlsafe_b64encode(result).rstrip(b'=').decode('ascii') + return hash_kind, result + + def write_record(self, records, record_path, archive_record_path): + records = list(records) # make a copy, as mutated + records.append((archive_record_path, '', '')) + with CSVWriter(record_path) as writer: + for row in records: + writer.writerow(row) + + def write_records(self, info, libdir, archive_paths): + records = [] + distinfo, info_dir = info + # hasher = getattr(hashlib, self.hash_kind) + for ap, p in archive_paths: + with open(p, 'rb') as f: + data = f.read() + digest = '%s=%s' % self.get_hash(data) + size = os.path.getsize(p) + records.append((ap, digest, size)) + + p = os.path.join(distinfo, 'RECORD') + ap = to_posix(os.path.join(info_dir, 'RECORD')) + self.write_record(records, p, ap) + archive_paths.append((ap, p)) + + def build_zip(self, pathname, archive_paths): + with ZipFile(pathname, 'w', zipfile.ZIP_DEFLATED) as zf: + for ap, p in archive_paths: + logger.debug('Wrote %s to %s in wheel', p, ap) + zf.write(p, ap) + + def build(self, paths, tags=None, wheel_version=None): + """ + Build a wheel from files in specified paths, and use any specified tags + when determining the name of the wheel. + """ + if tags is None: + tags = {} + + libkey = list(filter(lambda o: o in paths, ('purelib', 'platlib')))[0] + if libkey == 'platlib': + is_pure = 'false' + default_pyver = [IMPVER] + default_abi = [ABI] + default_arch = [ARCH] + else: + is_pure = 'true' + default_pyver = [PYVER] + default_abi = ['none'] + default_arch = ['any'] + + self.pyver = tags.get('pyver', default_pyver) + self.abi = tags.get('abi', default_abi) + self.arch = tags.get('arch', default_arch) + + libdir = paths[libkey] + + name_ver = '%s-%s' % (self.name, self.version) + data_dir = '%s.data' % name_ver + info_dir = '%s.dist-info' % name_ver + + archive_paths = [] + + # First, stuff which is not in site-packages + for key in ('data', 'headers', 'scripts'): + if key not in paths: + continue + path = paths[key] + if os.path.isdir(path): + for root, dirs, files in os.walk(path): + for fn in files: + p = fsdecode(os.path.join(root, fn)) + rp = os.path.relpath(p, path) + ap = to_posix(os.path.join(data_dir, key, rp)) + archive_paths.append((ap, p)) + if key == 'scripts' and not p.endswith('.exe'): + with open(p, 'rb') as f: + data = f.read() + data = self.process_shebang(data) + with open(p, 'wb') as f: + f.write(data) + + # Now, stuff which is in site-packages, other than the + # distinfo stuff. + path = libdir + distinfo = None + for root, dirs, files in os.walk(path): + if root == path: + # At the top level only, save distinfo for later + # and skip it for now + for i, dn in enumerate(dirs): + dn = fsdecode(dn) + if dn.endswith('.dist-info'): + distinfo = os.path.join(root, dn) + del dirs[i] + break + assert distinfo, '.dist-info directory expected, not found' + + for fn in files: + # comment out next suite to leave .pyc files in + if fsdecode(fn).endswith(('.pyc', '.pyo')): + continue + p = os.path.join(root, fn) + rp = to_posix(os.path.relpath(p, path)) + archive_paths.append((rp, p)) + + # Now distinfo. Assumed to be flat, i.e. os.listdir is enough. + files = os.listdir(distinfo) + for fn in files: + if fn not in ('RECORD', 'INSTALLER', 'SHARED', 'WHEEL'): + p = fsdecode(os.path.join(distinfo, fn)) + ap = to_posix(os.path.join(info_dir, fn)) + archive_paths.append((ap, p)) + + wheel_metadata = [ + 'Wheel-Version: %d.%d' % (wheel_version or self.wheel_version), + 'Generator: distlib %s' % __version__, + 'Root-Is-Purelib: %s' % is_pure, + ] + for pyver, abi, arch in self.tags: + wheel_metadata.append('Tag: %s-%s-%s' % (pyver, abi, arch)) + p = os.path.join(distinfo, 'WHEEL') + with open(p, 'w') as f: + f.write('\n'.join(wheel_metadata)) + ap = to_posix(os.path.join(info_dir, 'WHEEL')) + archive_paths.append((ap, p)) + + # sort the entries by archive path. Not needed by any spec, but it + # keeps the archive listing and RECORD tidier than they would otherwise + # be. Use the number of path segments to keep directory entries together, + # and keep the dist-info stuff at the end. + def sorter(t): + ap = t[0] + n = ap.count('/') + if '.dist-info' in ap: + n += 10000 + return (n, ap) + + archive_paths = sorted(archive_paths, key=sorter) + + # Now, at last, RECORD. + # Paths in here are archive paths - nothing else makes sense. + self.write_records((distinfo, info_dir), libdir, archive_paths) + # Now, ready to build the zip file + pathname = os.path.join(self.dirname, self.filename) + self.build_zip(pathname, archive_paths) + return pathname + + def skip_entry(self, arcname): + """ + Determine whether an archive entry should be skipped when verifying + or installing. + """ + # The signature file won't be in RECORD, + # and we don't currently don't do anything with it + # We also skip directories, as they won't be in RECORD + # either. See: + # + # https://github.com/pypa/wheel/issues/294 + # https://github.com/pypa/wheel/issues/287 + # https://github.com/pypa/wheel/pull/289 + # + return arcname.endswith(('/', '/RECORD.jws')) + + def install(self, paths, maker, **kwargs): + """ + Install a wheel to the specified paths. If kwarg ``warner`` is + specified, it should be a callable, which will be called with two + tuples indicating the wheel version of this software and the wheel + version in the file, if there is a discrepancy in the versions. + This can be used to issue any warnings to raise any exceptions. + If kwarg ``lib_only`` is True, only the purelib/platlib files are + installed, and the headers, scripts, data and dist-info metadata are + not written. If kwarg ``bytecode_hashed_invalidation`` is True, written + bytecode will try to use file-hash based invalidation (PEP-552) on + supported interpreter versions (CPython 3.7+). + + The return value is a :class:`InstalledDistribution` instance unless + ``options.lib_only`` is True, in which case the return value is ``None``. + """ + + dry_run = maker.dry_run + warner = kwargs.get('warner') + lib_only = kwargs.get('lib_only', False) + bc_hashed_invalidation = kwargs.get('bytecode_hashed_invalidation', False) + + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + data_dir = '%s.data' % name_ver + info_dir = '%s.dist-info' % name_ver + + metadata_name = posixpath.join(info_dir, LEGACY_METADATA_FILENAME) + wheel_metadata_name = posixpath.join(info_dir, 'WHEEL') + record_name = posixpath.join(info_dir, 'RECORD') + + wrapper = codecs.getreader('utf-8') + + with ZipFile(pathname, 'r') as zf: + with zf.open(wheel_metadata_name) as bwf: + wf = wrapper(bwf) + message = message_from_file(wf) + wv = message['Wheel-Version'].split('.', 1) + file_version = tuple([int(i) for i in wv]) + if (file_version != self.wheel_version) and warner: + warner(self.wheel_version, file_version) + + if message['Root-Is-Purelib'] == 'true': + libdir = paths['purelib'] + else: + libdir = paths['platlib'] + + records = {} + with zf.open(record_name) as bf: + with CSVReader(stream=bf) as reader: + for row in reader: + p = row[0] + records[p] = row + + data_pfx = posixpath.join(data_dir, '') + info_pfx = posixpath.join(info_dir, '') + script_pfx = posixpath.join(data_dir, 'scripts', '') + + # make a new instance rather than a copy of maker's, + # as we mutate it + fileop = FileOperator(dry_run=dry_run) + fileop.record = True # so we can rollback if needed + + bc = not sys.dont_write_bytecode # Double negatives. Lovely! + + outfiles = [] # for RECORD writing + + # for script copying/shebang processing + workdir = tempfile.mkdtemp() + # set target dir later + # we default add_launchers to False, as the + # Python Launcher should be used instead + maker.source_dir = workdir + maker.target_dir = None + try: + for zinfo in zf.infolist(): + arcname = zinfo.filename + if isinstance(arcname, text_type): + u_arcname = arcname + else: + u_arcname = arcname.decode('utf-8') + if self.skip_entry(u_arcname): + continue + row = records[u_arcname] + if row[2] and str(zinfo.file_size) != row[2]: + raise DistlibException('size mismatch for ' + '%s' % u_arcname) + if row[1]: + kind, value = row[1].split('=', 1) + with zf.open(arcname) as bf: + data = bf.read() + _, digest = self.get_hash(data, kind) + if digest != value: + raise DistlibException('digest mismatch for ' + '%s' % arcname) + + if lib_only and u_arcname.startswith((info_pfx, data_pfx)): + logger.debug('lib_only: skipping %s', u_arcname) + continue + is_script = (u_arcname.startswith(script_pfx) and not u_arcname.endswith('.exe')) + + if u_arcname.startswith(data_pfx): + _, where, rp = u_arcname.split('/', 2) + outfile = os.path.join(paths[where], convert_path(rp)) + else: + # meant for site-packages. + if u_arcname in (wheel_metadata_name, record_name): + continue + outfile = os.path.join(libdir, convert_path(u_arcname)) + if not is_script: + with zf.open(arcname) as bf: + fileop.copy_stream(bf, outfile) + # Issue #147: permission bits aren't preserved. Using + # zf.extract(zinfo, libdir) should have worked, but didn't, + # see https://www.thetopsites.net/article/53834422.shtml + # So ... manually preserve permission bits as given in zinfo + if os.name == 'posix': + # just set the normal permission bits + os.chmod(outfile, (zinfo.external_attr >> 16) & 0x1FF) + outfiles.append(outfile) + # Double check the digest of the written file + if not dry_run and row[1]: + with open(outfile, 'rb') as bf: + data = bf.read() + _, newdigest = self.get_hash(data, kind) + if newdigest != digest: + raise DistlibException('digest mismatch ' + 'on write for ' + '%s' % outfile) + if bc and outfile.endswith('.py'): + try: + pyc = fileop.byte_compile(outfile, hashed_invalidation=bc_hashed_invalidation) + outfiles.append(pyc) + except Exception: + # Don't give up if byte-compilation fails, + # but log it and perhaps warn the user + logger.warning('Byte-compilation failed', exc_info=True) + else: + fn = os.path.basename(convert_path(arcname)) + workname = os.path.join(workdir, fn) + with zf.open(arcname) as bf: + fileop.copy_stream(bf, workname) + + dn, fn = os.path.split(outfile) + maker.target_dir = dn + filenames = maker.make(fn) + fileop.set_executable_mode(filenames) + outfiles.extend(filenames) + + if lib_only: + logger.debug('lib_only: returning None') + dist = None + else: + # Generate scripts + + # Try to get pydist.json so we can see if there are + # any commands to generate. If this fails (e.g. because + # of a legacy wheel), log a warning but don't give up. + commands = None + file_version = self.info['Wheel-Version'] + if file_version == '1.0': + # Use legacy info + ep = posixpath.join(info_dir, 'entry_points.txt') + try: + with zf.open(ep) as bwf: + epdata = read_exports(bwf) + commands = {} + for key in ('console', 'gui'): + k = '%s_scripts' % key + if k in epdata: + commands['wrap_%s' % key] = d = {} + for v in epdata[k].values(): + s = '%s:%s' % (v.prefix, v.suffix) + if v.flags: + s += ' [%s]' % ','.join(v.flags) + d[v.name] = s + except Exception: + logger.warning('Unable to read legacy script ' + 'metadata, so cannot generate ' + 'scripts') + else: + try: + with zf.open(metadata_name) as bwf: + wf = wrapper(bwf) + commands = json.load(wf).get('extensions') + if commands: + commands = commands.get('python.commands') + except Exception: + logger.warning('Unable to read JSON metadata, so ' + 'cannot generate scripts') + if commands: + console_scripts = commands.get('wrap_console', {}) + gui_scripts = commands.get('wrap_gui', {}) + if console_scripts or gui_scripts: + script_dir = paths.get('scripts', '') + if not os.path.isdir(script_dir): + raise ValueError('Valid script path not ' + 'specified') + maker.target_dir = script_dir + for k, v in console_scripts.items(): + script = '%s = %s' % (k, v) + filenames = maker.make(script) + fileop.set_executable_mode(filenames) + + if gui_scripts: + options = {'gui': True} + for k, v in gui_scripts.items(): + script = '%s = %s' % (k, v) + filenames = maker.make(script, options) + fileop.set_executable_mode(filenames) + + p = os.path.join(libdir, info_dir) + dist = InstalledDistribution(p) + + # Write SHARED + paths = dict(paths) # don't change passed in dict + del paths['purelib'] + del paths['platlib'] + paths['lib'] = libdir + p = dist.write_shared_locations(paths, dry_run) + if p: + outfiles.append(p) + + # Write RECORD + dist.write_installed_files(outfiles, paths['prefix'], dry_run) + return dist + except Exception: # pragma: no cover + logger.exception('installation failed.') + fileop.rollback() + raise + finally: + shutil.rmtree(workdir) + + def _get_dylib_cache(self): + global cache + if cache is None: + # Use native string to avoid issues on 2.x: see Python #20140. + base = os.path.join(get_cache_base(), str('dylib-cache'), '%s.%s' % sys.version_info[:2]) + cache = Cache(base) + return cache + + def _get_extensions(self): + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + info_dir = '%s.dist-info' % name_ver + arcname = posixpath.join(info_dir, 'EXTENSIONS') + wrapper = codecs.getreader('utf-8') + result = [] + with ZipFile(pathname, 'r') as zf: + try: + with zf.open(arcname) as bf: + wf = wrapper(bf) + extensions = json.load(wf) + cache = self._get_dylib_cache() + prefix = cache.prefix_to_dir(self.filename, use_abspath=False) + cache_base = os.path.join(cache.base, prefix) + if not os.path.isdir(cache_base): + os.makedirs(cache_base) + for name, relpath in extensions.items(): + dest = os.path.join(cache_base, convert_path(relpath)) + if not os.path.exists(dest): + extract = True + else: + file_time = os.stat(dest).st_mtime + file_time = datetime.datetime.fromtimestamp(file_time) + info = zf.getinfo(relpath) + wheel_time = datetime.datetime(*info.date_time) + extract = wheel_time > file_time + if extract: + zf.extract(relpath, cache_base) + result.append((name, dest)) + except KeyError: + pass + return result + + def is_compatible(self): + """ + Determine if a wheel is compatible with the running system. + """ + return is_compatible(self) + + def is_mountable(self): + """ + Determine if a wheel is asserted as mountable by its metadata. + """ + return True # for now - metadata details TBD + + def mount(self, append=False): + pathname = os.path.abspath(os.path.join(self.dirname, self.filename)) + if not self.is_compatible(): + msg = 'Wheel %s not compatible with this Python.' % pathname + raise DistlibException(msg) + if not self.is_mountable(): + msg = 'Wheel %s is marked as not mountable.' % pathname + raise DistlibException(msg) + if pathname in sys.path: + logger.debug('%s already in path', pathname) + else: + if append: + sys.path.append(pathname) + else: + sys.path.insert(0, pathname) + extensions = self._get_extensions() + if extensions: + if _hook not in sys.meta_path: + sys.meta_path.append(_hook) + _hook.add(pathname, extensions) + + def unmount(self): + pathname = os.path.abspath(os.path.join(self.dirname, self.filename)) + if pathname not in sys.path: + logger.debug('%s not in path', pathname) + else: + sys.path.remove(pathname) + if pathname in _hook.impure_wheels: + _hook.remove(pathname) + if not _hook.impure_wheels: + if _hook in sys.meta_path: + sys.meta_path.remove(_hook) + + def verify(self): + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + # data_dir = '%s.data' % name_ver + info_dir = '%s.dist-info' % name_ver + + # metadata_name = posixpath.join(info_dir, LEGACY_METADATA_FILENAME) + wheel_metadata_name = posixpath.join(info_dir, 'WHEEL') + record_name = posixpath.join(info_dir, 'RECORD') + + wrapper = codecs.getreader('utf-8') + + with ZipFile(pathname, 'r') as zf: + with zf.open(wheel_metadata_name) as bwf: + wf = wrapper(bwf) + message_from_file(wf) + # wv = message['Wheel-Version'].split('.', 1) + # file_version = tuple([int(i) for i in wv]) + # TODO version verification + + records = {} + with zf.open(record_name) as bf: + with CSVReader(stream=bf) as reader: + for row in reader: + p = row[0] + records[p] = row + + for zinfo in zf.infolist(): + arcname = zinfo.filename + if isinstance(arcname, text_type): + u_arcname = arcname + else: + u_arcname = arcname.decode('utf-8') + # See issue #115: some wheels have .. in their entries, but + # in the filename ... e.g. __main__..py ! So the check is + # updated to look for .. in the directory portions + p = u_arcname.split('/') + if '..' in p: + raise DistlibException('invalid entry in ' + 'wheel: %r' % u_arcname) + + if self.skip_entry(u_arcname): + continue + row = records[u_arcname] + if row[2] and str(zinfo.file_size) != row[2]: + raise DistlibException('size mismatch for ' + '%s' % u_arcname) + if row[1]: + kind, value = row[1].split('=', 1) + with zf.open(arcname) as bf: + data = bf.read() + _, digest = self.get_hash(data, kind) + if digest != value: + raise DistlibException('digest mismatch for ' + '%s' % arcname) + + def update(self, modifier, dest_dir=None, **kwargs): + """ + Update the contents of a wheel in a generic way. The modifier should + be a callable which expects a dictionary argument: its keys are + archive-entry paths, and its values are absolute filesystem paths + where the contents the corresponding archive entries can be found. The + modifier is free to change the contents of the files pointed to, add + new entries and remove entries, before returning. This method will + extract the entire contents of the wheel to a temporary location, call + the modifier, and then use the passed (and possibly updated) + dictionary to write a new wheel. If ``dest_dir`` is specified, the new + wheel is written there -- otherwise, the original wheel is overwritten. + + The modifier should return True if it updated the wheel, else False. + This method returns the same value the modifier returns. + """ + + def get_version(path_map, info_dir): + version = path = None + key = '%s/%s' % (info_dir, LEGACY_METADATA_FILENAME) + if key not in path_map: + key = '%s/PKG-INFO' % info_dir + if key in path_map: + path = path_map[key] + version = Metadata(path=path).version + return version, path + + def update_version(version, path): + updated = None + try: + NormalizedVersion(version) + i = version.find('-') + if i < 0: + updated = '%s+1' % version + else: + parts = [int(s) for s in version[i + 1:].split('.')] + parts[-1] += 1 + updated = '%s+%s' % (version[:i], '.'.join(str(i) for i in parts)) + except UnsupportedVersionError: + logger.debug('Cannot update non-compliant (PEP-440) ' + 'version %r', version) + if updated: + md = Metadata(path=path) + md.version = updated + legacy = path.endswith(LEGACY_METADATA_FILENAME) + md.write(path=path, legacy=legacy) + logger.debug('Version updated from %r to %r', version, updated) + + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + info_dir = '%s.dist-info' % name_ver + record_name = posixpath.join(info_dir, 'RECORD') + with tempdir() as workdir: + with ZipFile(pathname, 'r') as zf: + path_map = {} + for zinfo in zf.infolist(): + arcname = zinfo.filename + if isinstance(arcname, text_type): + u_arcname = arcname + else: + u_arcname = arcname.decode('utf-8') + if u_arcname == record_name: + continue + if '..' in u_arcname: + raise DistlibException('invalid entry in ' + 'wheel: %r' % u_arcname) + zf.extract(zinfo, workdir) + path = os.path.join(workdir, convert_path(u_arcname)) + path_map[u_arcname] = path + + # Remember the version. + original_version, _ = get_version(path_map, info_dir) + # Files extracted. Call the modifier. + modified = modifier(path_map, **kwargs) + if modified: + # Something changed - need to build a new wheel. + current_version, path = get_version(path_map, info_dir) + if current_version and (current_version == original_version): + # Add or update local version to signify changes. + update_version(current_version, path) + # Decide where the new wheel goes. + if dest_dir is None: + fd, newpath = tempfile.mkstemp(suffix='.whl', prefix='wheel-update-', dir=workdir) + os.close(fd) + else: + if not os.path.isdir(dest_dir): + raise DistlibException('Not a directory: %r' % dest_dir) + newpath = os.path.join(dest_dir, self.filename) + archive_paths = list(path_map.items()) + distinfo = os.path.join(workdir, info_dir) + info = distinfo, info_dir + self.write_records(info, workdir, archive_paths) + self.build_zip(newpath, archive_paths) + if dest_dir is None: + shutil.copyfile(newpath, pathname) + return modified + + +def _get_glibc_version(): + import platform + ver = platform.libc_ver() + result = [] + if ver[0] == 'glibc': + for s in ver[1].split('.'): + result.append(int(s) if s.isdigit() else 0) + result = tuple(result) + return result + + +def compatible_tags(): + """ + Return (pyver, abi, arch) tuples compatible with this Python. + """ + class _Version: + def __init__(self, major, minor): + self.major = major + self.major_minor = (major, minor) + self.string = ''.join((str(major), str(minor))) + + def __str__(self): + return self.string + + + versions = [ + _Version(sys.version_info.major, minor_version) + for minor_version in range(sys.version_info.minor, -1, -1) + ] + abis = [] + for suffix in _get_suffixes(): + if suffix.startswith('.abi'): + abis.append(suffix.split('.', 2)[1]) + abis.sort() + if ABI != 'none': + abis.insert(0, ABI) + abis.append('none') + result = [] + + arches = [ARCH] + if sys.platform == 'darwin': + m = re.match(r'(\w+)_(\d+)_(\d+)_(\w+)$', ARCH) + if m: + name, major, minor, arch = m.groups() + minor = int(minor) + matches = [arch] + if arch in ('i386', 'ppc'): + matches.append('fat') + if arch in ('i386', 'ppc', 'x86_64'): + matches.append('fat3') + if arch in ('ppc64', 'x86_64'): + matches.append('fat64') + if arch in ('i386', 'x86_64'): + matches.append('intel') + if arch in ('i386', 'x86_64', 'intel', 'ppc', 'ppc64'): + matches.append('universal') + while minor >= 0: + for match in matches: + s = '%s_%s_%s_%s' % (name, major, minor, match) + if s != ARCH: # already there + arches.append(s) + minor -= 1 + + # Most specific - our Python version, ABI and arch + for i, version_object in enumerate(versions): + version = str(version_object) + add_abis = [] + + if i == 0: + add_abis = abis + + if IMP_PREFIX == 'cp' and version_object.major_minor >= (3, 2): + limited_api_abi = 'abi' + str(version_object.major) + if limited_api_abi not in add_abis: + add_abis.append(limited_api_abi) + + for abi in add_abis: + for arch in arches: + result.append((''.join((IMP_PREFIX, version)), abi, arch)) + # manylinux + if abi != 'none' and sys.platform.startswith('linux'): + arch = arch.replace('linux_', '') + parts = _get_glibc_version() + if len(parts) == 2: + if parts >= (2, 5): + result.append((''.join((IMP_PREFIX, version)), abi, 'manylinux1_%s' % arch)) + if parts >= (2, 12): + result.append((''.join((IMP_PREFIX, version)), abi, 'manylinux2010_%s' % arch)) + if parts >= (2, 17): + result.append((''.join((IMP_PREFIX, version)), abi, 'manylinux2014_%s' % arch)) + result.append((''.join( + (IMP_PREFIX, version)), abi, 'manylinux_%s_%s_%s' % (parts[0], parts[1], arch))) + + # where no ABI / arch dependency, but IMP_PREFIX dependency + for i, version_object in enumerate(versions): + version = str(version_object) + result.append((''.join((IMP_PREFIX, version)), 'none', 'any')) + if i == 0: + result.append((''.join((IMP_PREFIX, version[0])), 'none', 'any')) + + # no IMP_PREFIX, ABI or arch dependency + for i, version_object in enumerate(versions): + version = str(version_object) + result.append((''.join(('py', version)), 'none', 'any')) + if i == 0: + result.append((''.join(('py', version[0])), 'none', 'any')) + + return set(result) + + +COMPATIBLE_TAGS = compatible_tags() + +del compatible_tags + + +def is_compatible(wheel, tags=None): + if not isinstance(wheel, Wheel): + wheel = Wheel(wheel) # assume it's a filename + result = False + if tags is None: + tags = COMPATIBLE_TAGS + for ver, abi, arch in tags: + if ver in wheel.pyver and abi in wheel.abi and arch in wheel.arch: + result = True + break + return result diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distro/__init__.py b/backend/.venv/Lib/site-packages/pip/_vendor/distro/__init__.py new file mode 100644 index 0000000..7686fe8 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/distro/__init__.py @@ -0,0 +1,54 @@ +from .distro import ( + NORMALIZED_DISTRO_ID, + NORMALIZED_LSB_ID, + NORMALIZED_OS_ID, + LinuxDistribution, + __version__, + build_number, + codename, + distro_release_attr, + distro_release_info, + id, + info, + like, + linux_distribution, + lsb_release_attr, + lsb_release_info, + major_version, + minor_version, + name, + os_release_attr, + os_release_info, + uname_attr, + uname_info, + version, + version_parts, +) + +__all__ = [ + "NORMALIZED_DISTRO_ID", + "NORMALIZED_LSB_ID", + "NORMALIZED_OS_ID", + "LinuxDistribution", + "build_number", + "codename", + "distro_release_attr", + "distro_release_info", + "id", + "info", + "like", + "linux_distribution", + "lsb_release_attr", + "lsb_release_info", + "major_version", + "minor_version", + "name", + "os_release_attr", + "os_release_info", + "uname_attr", + "uname_info", + "version", + "version_parts", +] + +__version__ = __version__ diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distro/__main__.py b/backend/.venv/Lib/site-packages/pip/_vendor/distro/__main__.py new file mode 100644 index 0000000..0c01d5b --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/distro/__main__.py @@ -0,0 +1,4 @@ +from .distro import main + +if __name__ == "__main__": + main() diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distro/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/distro/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6fa7df26f3b377f4dfe8c0b5c3ae8567efffb013 GIT binary patch literal 963 zcmcJNzi-n(6vxkwo1{tH{A`nUK&%%jrq*TDj4IjPx`riA#=ew`IUt@M1ym>0Wl^FX@o5gbPg6j(# zd}0xcoS2~l4!YoC2}Dp-XouEHwTpoVp*V*?uKgO6*lhD~T<3tHHQ zHg=$cUFc#DdbkejxB(m3hdvHq;ILB`xt|@_6t?nZY3TiMto?9cdWT2H2hYd*@M^?I z`zNoDkNEz`w3pQJ$qSNNOVZIvacC@6ele11rsX8hWTH%+^K+q78**+MlU&9TS2<3E zHq~ho2^FF+-H1{Wu0<@uRPZp%^dF*B?-Jw6$aqEM#d0Q0CniT;Yh?$ z`xu@jdeNHkQL3e_S9H}(()(qWg`!F=r-Qfc-o=Gpxf|K|i`nO)&eCCD+q-AlBdie0 zgeqZ`KyO6X2@QfzSR*tEEkc{nA#@2n!a8At&?gKCn}jWk!{L@G-~Qjfx>xAn|82ok zI1l5P^Dpe$y0KqxUp@}rCwi97!>I_=S(a{x(`k~cOsdoEX`)3i38yomqG0D-sPkYf zCqXJRv27D(;i*W2xt#CX>r+vpcW4(;kUUs@?aaD30 g=f>T1+#B`}T+@f2dxN_Bp>p+zHMc(2^#hyw8$|{Nga7~l literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distro/__pycache__/__main__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/distro/__pycache__/__main__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..08299e4837d38aa45f1924b5eda89e680de2c389 GIT binary patch literal 295 zcmXv}%}N6?5T4mA5|rMxPv8pMy^D$eAD5Ff>xHx~rK zlea=|JvG604m01(_s!qOV6Y3puJ2Cud5FI;*;=vz%cB5ZL4w37)Od>sDv?Qb2;gV} z3g0(EgpPD1OaCwwGVIe@Xwy^9W90lMBmIulzIE1-pookSwc`8@mT|=D{^FQDT37i- zl!}>$*5{%u?aZ{=O!Cq?#m1tnl#y&SS7y$x^q6_wsysAQVxl~2bW`xaN$ZOLUB!0) tsOfroQd>Ejsxue=j(7TDa0`Nn-?0Bf_FkSo$-!4jpDz~#(xIb)UIXiwP(}a% literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distro/__pycache__/distro.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/distro/__pycache__/distro.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2d813ddcf0c8c6362c2917f116adf3db1122b460 GIT binary patch literal 53795 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distro/distro.py b/backend/.venv/Lib/site-packages/pip/_vendor/distro/distro.py new file mode 100644 index 0000000..78ccdfa --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/distro/distro.py @@ -0,0 +1,1403 @@ +#!/usr/bin/env python +# Copyright 2015-2021 Nir Cohen +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +The ``distro`` package (``distro`` stands for Linux Distribution) provides +information about the Linux distribution it runs on, such as a reliable +machine-readable distro ID, or version information. + +It is the recommended replacement for Python's original +:py:func:`platform.linux_distribution` function, but it provides much more +functionality. An alternative implementation became necessary because Python +3.5 deprecated this function, and Python 3.8 removed it altogether. Its +predecessor function :py:func:`platform.dist` was already deprecated since +Python 2.6 and removed in Python 3.8. Still, there are many cases in which +access to OS distribution information is needed. See `Python issue 1322 +`_ for more information. +""" + +import argparse +import json +import logging +import os +import re +import shlex +import subprocess +import sys +import warnings +from typing import ( + Any, + Callable, + Dict, + Iterable, + Optional, + Sequence, + TextIO, + Tuple, + Type, +) + +try: + from typing import TypedDict +except ImportError: + # Python 3.7 + TypedDict = dict + +__version__ = "1.9.0" + + +class VersionDict(TypedDict): + major: str + minor: str + build_number: str + + +class InfoDict(TypedDict): + id: str + version: str + version_parts: VersionDict + like: str + codename: str + + +_UNIXCONFDIR = os.environ.get("UNIXCONFDIR", "/etc") +_UNIXUSRLIBDIR = os.environ.get("UNIXUSRLIBDIR", "/usr/lib") +_OS_RELEASE_BASENAME = "os-release" + +#: Translation table for normalizing the "ID" attribute defined in os-release +#: files, for use by the :func:`distro.id` method. +#: +#: * Key: Value as defined in the os-release file, translated to lower case, +#: with blanks translated to underscores. +#: +#: * Value: Normalized value. +NORMALIZED_OS_ID = { + "ol": "oracle", # Oracle Linux + "opensuse-leap": "opensuse", # Newer versions of OpenSuSE report as opensuse-leap +} + +#: Translation table for normalizing the "Distributor ID" attribute returned by +#: the lsb_release command, for use by the :func:`distro.id` method. +#: +#: * Key: Value as returned by the lsb_release command, translated to lower +#: case, with blanks translated to underscores. +#: +#: * Value: Normalized value. +NORMALIZED_LSB_ID = { + "enterpriseenterpriseas": "oracle", # Oracle Enterprise Linux 4 + "enterpriseenterpriseserver": "oracle", # Oracle Linux 5 + "redhatenterpriseworkstation": "rhel", # RHEL 6, 7 Workstation + "redhatenterpriseserver": "rhel", # RHEL 6, 7 Server + "redhatenterprisecomputenode": "rhel", # RHEL 6 ComputeNode +} + +#: Translation table for normalizing the distro ID derived from the file name +#: of distro release files, for use by the :func:`distro.id` method. +#: +#: * Key: Value as derived from the file name of a distro release file, +#: translated to lower case, with blanks translated to underscores. +#: +#: * Value: Normalized value. +NORMALIZED_DISTRO_ID = { + "redhat": "rhel", # RHEL 6.x, 7.x +} + +# Pattern for content of distro release file (reversed) +_DISTRO_RELEASE_CONTENT_REVERSED_PATTERN = re.compile( + r"(?:[^)]*\)(.*)\()? *(?:STL )?([\d.+\-a-z]*\d) *(?:esaeler *)?(.+)" +) + +# Pattern for base file name of distro release file +_DISTRO_RELEASE_BASENAME_PATTERN = re.compile(r"(\w+)[-_](release|version)$") + +# Base file names to be looked up for if _UNIXCONFDIR is not readable. +_DISTRO_RELEASE_BASENAMES = [ + "SuSE-release", + "altlinux-release", + "arch-release", + "base-release", + "centos-release", + "fedora-release", + "gentoo-release", + "mageia-release", + "mandrake-release", + "mandriva-release", + "mandrivalinux-release", + "manjaro-release", + "oracle-release", + "redhat-release", + "rocky-release", + "sl-release", + "slackware-version", +] + +# Base file names to be ignored when searching for distro release file +_DISTRO_RELEASE_IGNORE_BASENAMES = ( + "debian_version", + "lsb-release", + "oem-release", + _OS_RELEASE_BASENAME, + "system-release", + "plesk-release", + "iredmail-release", + "board-release", + "ec2_version", +) + + +def linux_distribution(full_distribution_name: bool = True) -> Tuple[str, str, str]: + """ + .. deprecated:: 1.6.0 + + :func:`distro.linux_distribution()` is deprecated. It should only be + used as a compatibility shim with Python's + :py:func:`platform.linux_distribution()`. Please use :func:`distro.id`, + :func:`distro.version` and :func:`distro.name` instead. + + Return information about the current OS distribution as a tuple + ``(id_name, version, codename)`` with items as follows: + + * ``id_name``: If *full_distribution_name* is false, the result of + :func:`distro.id`. Otherwise, the result of :func:`distro.name`. + + * ``version``: The result of :func:`distro.version`. + + * ``codename``: The extra item (usually in parentheses) after the + os-release version number, or the result of :func:`distro.codename`. + + The interface of this function is compatible with the original + :py:func:`platform.linux_distribution` function, supporting a subset of + its parameters. + + The data it returns may not exactly be the same, because it uses more data + sources than the original function, and that may lead to different data if + the OS distribution is not consistent across multiple data sources it + provides (there are indeed such distributions ...). + + Another reason for differences is the fact that the :func:`distro.id` + method normalizes the distro ID string to a reliable machine-readable value + for a number of popular OS distributions. + """ + warnings.warn( + "distro.linux_distribution() is deprecated. It should only be used as a " + "compatibility shim with Python's platform.linux_distribution(). Please use " + "distro.id(), distro.version() and distro.name() instead.", + DeprecationWarning, + stacklevel=2, + ) + return _distro.linux_distribution(full_distribution_name) + + +def id() -> str: + """ + Return the distro ID of the current distribution, as a + machine-readable string. + + For a number of OS distributions, the returned distro ID value is + *reliable*, in the sense that it is documented and that it does not change + across releases of the distribution. + + This package maintains the following reliable distro ID values: + + ============== ========================================= + Distro ID Distribution + ============== ========================================= + "ubuntu" Ubuntu + "debian" Debian + "rhel" RedHat Enterprise Linux + "centos" CentOS + "fedora" Fedora + "sles" SUSE Linux Enterprise Server + "opensuse" openSUSE + "amzn" Amazon Linux + "arch" Arch Linux + "buildroot" Buildroot + "cloudlinux" CloudLinux OS + "exherbo" Exherbo Linux + "gentoo" GenToo Linux + "ibm_powerkvm" IBM PowerKVM + "kvmibm" KVM for IBM z Systems + "linuxmint" Linux Mint + "mageia" Mageia + "mandriva" Mandriva Linux + "parallels" Parallels + "pidora" Pidora + "raspbian" Raspbian + "oracle" Oracle Linux (and Oracle Enterprise Linux) + "scientific" Scientific Linux + "slackware" Slackware + "xenserver" XenServer + "openbsd" OpenBSD + "netbsd" NetBSD + "freebsd" FreeBSD + "midnightbsd" MidnightBSD + "rocky" Rocky Linux + "aix" AIX + "guix" Guix System + "altlinux" ALT Linux + ============== ========================================= + + If you have a need to get distros for reliable IDs added into this set, + or if you find that the :func:`distro.id` function returns a different + distro ID for one of the listed distros, please create an issue in the + `distro issue tracker`_. + + **Lookup hierarchy and transformations:** + + First, the ID is obtained from the following sources, in the specified + order. The first available and non-empty value is used: + + * the value of the "ID" attribute of the os-release file, + + * the value of the "Distributor ID" attribute returned by the lsb_release + command, + + * the first part of the file name of the distro release file, + + The so determined ID value then passes the following transformations, + before it is returned by this method: + + * it is translated to lower case, + + * blanks (which should not be there anyway) are translated to underscores, + + * a normalization of the ID is performed, based upon + `normalization tables`_. The purpose of this normalization is to ensure + that the ID is as reliable as possible, even across incompatible changes + in the OS distributions. A common reason for an incompatible change is + the addition of an os-release file, or the addition of the lsb_release + command, with ID values that differ from what was previously determined + from the distro release file name. + """ + return _distro.id() + + +def name(pretty: bool = False) -> str: + """ + Return the name of the current OS distribution, as a human-readable + string. + + If *pretty* is false, the name is returned without version or codename. + (e.g. "CentOS Linux") + + If *pretty* is true, the version and codename are appended. + (e.g. "CentOS Linux 7.1.1503 (Core)") + + **Lookup hierarchy:** + + The name is obtained from the following sources, in the specified order. + The first available and non-empty value is used: + + * If *pretty* is false: + + - the value of the "NAME" attribute of the os-release file, + + - the value of the "Distributor ID" attribute returned by the lsb_release + command, + + - the value of the "" field of the distro release file. + + * If *pretty* is true: + + - the value of the "PRETTY_NAME" attribute of the os-release file, + + - the value of the "Description" attribute returned by the lsb_release + command, + + - the value of the "" field of the distro release file, appended + with the value of the pretty version ("" and "" + fields) of the distro release file, if available. + """ + return _distro.name(pretty) + + +def version(pretty: bool = False, best: bool = False) -> str: + """ + Return the version of the current OS distribution, as a human-readable + string. + + If *pretty* is false, the version is returned without codename (e.g. + "7.0"). + + If *pretty* is true, the codename in parenthesis is appended, if the + codename is non-empty (e.g. "7.0 (Maipo)"). + + Some distributions provide version numbers with different precisions in + the different sources of distribution information. Examining the different + sources in a fixed priority order does not always yield the most precise + version (e.g. for Debian 8.2, or CentOS 7.1). + + Some other distributions may not provide this kind of information. In these + cases, an empty string would be returned. This behavior can be observed + with rolling releases distributions (e.g. Arch Linux). + + The *best* parameter can be used to control the approach for the returned + version: + + If *best* is false, the first non-empty version number in priority order of + the examined sources is returned. + + If *best* is true, the most precise version number out of all examined + sources is returned. + + **Lookup hierarchy:** + + In all cases, the version number is obtained from the following sources. + If *best* is false, this order represents the priority order: + + * the value of the "VERSION_ID" attribute of the os-release file, + * the value of the "Release" attribute returned by the lsb_release + command, + * the version number parsed from the "" field of the first line + of the distro release file, + * the version number parsed from the "PRETTY_NAME" attribute of the + os-release file, if it follows the format of the distro release files. + * the version number parsed from the "Description" attribute returned by + the lsb_release command, if it follows the format of the distro release + files. + """ + return _distro.version(pretty, best) + + +def version_parts(best: bool = False) -> Tuple[str, str, str]: + """ + Return the version of the current OS distribution as a tuple + ``(major, minor, build_number)`` with items as follows: + + * ``major``: The result of :func:`distro.major_version`. + + * ``minor``: The result of :func:`distro.minor_version`. + + * ``build_number``: The result of :func:`distro.build_number`. + + For a description of the *best* parameter, see the :func:`distro.version` + method. + """ + return _distro.version_parts(best) + + +def major_version(best: bool = False) -> str: + """ + Return the major version of the current OS distribution, as a string, + if provided. + Otherwise, the empty string is returned. The major version is the first + part of the dot-separated version string. + + For a description of the *best* parameter, see the :func:`distro.version` + method. + """ + return _distro.major_version(best) + + +def minor_version(best: bool = False) -> str: + """ + Return the minor version of the current OS distribution, as a string, + if provided. + Otherwise, the empty string is returned. The minor version is the second + part of the dot-separated version string. + + For a description of the *best* parameter, see the :func:`distro.version` + method. + """ + return _distro.minor_version(best) + + +def build_number(best: bool = False) -> str: + """ + Return the build number of the current OS distribution, as a string, + if provided. + Otherwise, the empty string is returned. The build number is the third part + of the dot-separated version string. + + For a description of the *best* parameter, see the :func:`distro.version` + method. + """ + return _distro.build_number(best) + + +def like() -> str: + """ + Return a space-separated list of distro IDs of distributions that are + closely related to the current OS distribution in regards to packaging + and programming interfaces, for example distributions the current + distribution is a derivative from. + + **Lookup hierarchy:** + + This information item is only provided by the os-release file. + For details, see the description of the "ID_LIKE" attribute in the + `os-release man page + `_. + """ + return _distro.like() + + +def codename() -> str: + """ + Return the codename for the release of the current OS distribution, + as a string. + + If the distribution does not have a codename, an empty string is returned. + + Note that the returned codename is not always really a codename. For + example, openSUSE returns "x86_64". This function does not handle such + cases in any special way and just returns the string it finds, if any. + + **Lookup hierarchy:** + + * the codename within the "VERSION" attribute of the os-release file, if + provided, + + * the value of the "Codename" attribute returned by the lsb_release + command, + + * the value of the "" field of the distro release file. + """ + return _distro.codename() + + +def info(pretty: bool = False, best: bool = False) -> InfoDict: + """ + Return certain machine-readable information items about the current OS + distribution in a dictionary, as shown in the following example: + + .. sourcecode:: python + + { + 'id': 'rhel', + 'version': '7.0', + 'version_parts': { + 'major': '7', + 'minor': '0', + 'build_number': '' + }, + 'like': 'fedora', + 'codename': 'Maipo' + } + + The dictionary structure and keys are always the same, regardless of which + information items are available in the underlying data sources. The values + for the various keys are as follows: + + * ``id``: The result of :func:`distro.id`. + + * ``version``: The result of :func:`distro.version`. + + * ``version_parts -> major``: The result of :func:`distro.major_version`. + + * ``version_parts -> minor``: The result of :func:`distro.minor_version`. + + * ``version_parts -> build_number``: The result of + :func:`distro.build_number`. + + * ``like``: The result of :func:`distro.like`. + + * ``codename``: The result of :func:`distro.codename`. + + For a description of the *pretty* and *best* parameters, see the + :func:`distro.version` method. + """ + return _distro.info(pretty, best) + + +def os_release_info() -> Dict[str, str]: + """ + Return a dictionary containing key-value pairs for the information items + from the os-release file data source of the current OS distribution. + + See `os-release file`_ for details about these information items. + """ + return _distro.os_release_info() + + +def lsb_release_info() -> Dict[str, str]: + """ + Return a dictionary containing key-value pairs for the information items + from the lsb_release command data source of the current OS distribution. + + See `lsb_release command output`_ for details about these information + items. + """ + return _distro.lsb_release_info() + + +def distro_release_info() -> Dict[str, str]: + """ + Return a dictionary containing key-value pairs for the information items + from the distro release file data source of the current OS distribution. + + See `distro release file`_ for details about these information items. + """ + return _distro.distro_release_info() + + +def uname_info() -> Dict[str, str]: + """ + Return a dictionary containing key-value pairs for the information items + from the distro release file data source of the current OS distribution. + """ + return _distro.uname_info() + + +def os_release_attr(attribute: str) -> str: + """ + Return a single named information item from the os-release file data source + of the current OS distribution. + + Parameters: + + * ``attribute`` (string): Key of the information item. + + Returns: + + * (string): Value of the information item, if the item exists. + The empty string, if the item does not exist. + + See `os-release file`_ for details about these information items. + """ + return _distro.os_release_attr(attribute) + + +def lsb_release_attr(attribute: str) -> str: + """ + Return a single named information item from the lsb_release command output + data source of the current OS distribution. + + Parameters: + + * ``attribute`` (string): Key of the information item. + + Returns: + + * (string): Value of the information item, if the item exists. + The empty string, if the item does not exist. + + See `lsb_release command output`_ for details about these information + items. + """ + return _distro.lsb_release_attr(attribute) + + +def distro_release_attr(attribute: str) -> str: + """ + Return a single named information item from the distro release file + data source of the current OS distribution. + + Parameters: + + * ``attribute`` (string): Key of the information item. + + Returns: + + * (string): Value of the information item, if the item exists. + The empty string, if the item does not exist. + + See `distro release file`_ for details about these information items. + """ + return _distro.distro_release_attr(attribute) + + +def uname_attr(attribute: str) -> str: + """ + Return a single named information item from the distro release file + data source of the current OS distribution. + + Parameters: + + * ``attribute`` (string): Key of the information item. + + Returns: + + * (string): Value of the information item, if the item exists. + The empty string, if the item does not exist. + """ + return _distro.uname_attr(attribute) + + +try: + from functools import cached_property +except ImportError: + # Python < 3.8 + class cached_property: # type: ignore + """A version of @property which caches the value. On access, it calls the + underlying function and sets the value in `__dict__` so future accesses + will not re-call the property. + """ + + def __init__(self, f: Callable[[Any], Any]) -> None: + self._fname = f.__name__ + self._f = f + + def __get__(self, obj: Any, owner: Type[Any]) -> Any: + assert obj is not None, f"call {self._fname} on an instance" + ret = obj.__dict__[self._fname] = self._f(obj) + return ret + + +class LinuxDistribution: + """ + Provides information about a OS distribution. + + This package creates a private module-global instance of this class with + default initialization arguments, that is used by the + `consolidated accessor functions`_ and `single source accessor functions`_. + By using default initialization arguments, that module-global instance + returns data about the current OS distribution (i.e. the distro this + package runs on). + + Normally, it is not necessary to create additional instances of this class. + However, in situations where control is needed over the exact data sources + that are used, instances of this class can be created with a specific + distro release file, or a specific os-release file, or without invoking the + lsb_release command. + """ + + def __init__( + self, + include_lsb: Optional[bool] = None, + os_release_file: str = "", + distro_release_file: str = "", + include_uname: Optional[bool] = None, + root_dir: Optional[str] = None, + include_oslevel: Optional[bool] = None, + ) -> None: + """ + The initialization method of this class gathers information from the + available data sources, and stores that in private instance attributes. + Subsequent access to the information items uses these private instance + attributes, so that the data sources are read only once. + + Parameters: + + * ``include_lsb`` (bool): Controls whether the + `lsb_release command output`_ is included as a data source. + + If the lsb_release command is not available in the program execution + path, the data source for the lsb_release command will be empty. + + * ``os_release_file`` (string): The path name of the + `os-release file`_ that is to be used as a data source. + + An empty string (the default) will cause the default path name to + be used (see `os-release file`_ for details). + + If the specified or defaulted os-release file does not exist, the + data source for the os-release file will be empty. + + * ``distro_release_file`` (string): The path name of the + `distro release file`_ that is to be used as a data source. + + An empty string (the default) will cause a default search algorithm + to be used (see `distro release file`_ for details). + + If the specified distro release file does not exist, or if no default + distro release file can be found, the data source for the distro + release file will be empty. + + * ``include_uname`` (bool): Controls whether uname command output is + included as a data source. If the uname command is not available in + the program execution path the data source for the uname command will + be empty. + + * ``root_dir`` (string): The absolute path to the root directory to use + to find distro-related information files. Note that ``include_*`` + parameters must not be enabled in combination with ``root_dir``. + + * ``include_oslevel`` (bool): Controls whether (AIX) oslevel command + output is included as a data source. If the oslevel command is not + available in the program execution path the data source will be + empty. + + Public instance attributes: + + * ``os_release_file`` (string): The path name of the + `os-release file`_ that is actually used as a data source. The + empty string if no distro release file is used as a data source. + + * ``distro_release_file`` (string): The path name of the + `distro release file`_ that is actually used as a data source. The + empty string if no distro release file is used as a data source. + + * ``include_lsb`` (bool): The result of the ``include_lsb`` parameter. + This controls whether the lsb information will be loaded. + + * ``include_uname`` (bool): The result of the ``include_uname`` + parameter. This controls whether the uname information will + be loaded. + + * ``include_oslevel`` (bool): The result of the ``include_oslevel`` + parameter. This controls whether (AIX) oslevel information will be + loaded. + + * ``root_dir`` (string): The result of the ``root_dir`` parameter. + The absolute path to the root directory to use to find distro-related + information files. + + Raises: + + * :py:exc:`ValueError`: Initialization parameters combination is not + supported. + + * :py:exc:`OSError`: Some I/O issue with an os-release file or distro + release file. + + * :py:exc:`UnicodeError`: A data source has unexpected characters or + uses an unexpected encoding. + """ + self.root_dir = root_dir + self.etc_dir = os.path.join(root_dir, "etc") if root_dir else _UNIXCONFDIR + self.usr_lib_dir = ( + os.path.join(root_dir, "usr/lib") if root_dir else _UNIXUSRLIBDIR + ) + + if os_release_file: + self.os_release_file = os_release_file + else: + etc_dir_os_release_file = os.path.join(self.etc_dir, _OS_RELEASE_BASENAME) + usr_lib_os_release_file = os.path.join( + self.usr_lib_dir, _OS_RELEASE_BASENAME + ) + + # NOTE: The idea is to respect order **and** have it set + # at all times for API backwards compatibility. + if os.path.isfile(etc_dir_os_release_file) or not os.path.isfile( + usr_lib_os_release_file + ): + self.os_release_file = etc_dir_os_release_file + else: + self.os_release_file = usr_lib_os_release_file + + self.distro_release_file = distro_release_file or "" # updated later + + is_root_dir_defined = root_dir is not None + if is_root_dir_defined and (include_lsb or include_uname or include_oslevel): + raise ValueError( + "Including subprocess data sources from specific root_dir is disallowed" + " to prevent false information" + ) + self.include_lsb = ( + include_lsb if include_lsb is not None else not is_root_dir_defined + ) + self.include_uname = ( + include_uname if include_uname is not None else not is_root_dir_defined + ) + self.include_oslevel = ( + include_oslevel if include_oslevel is not None else not is_root_dir_defined + ) + + def __repr__(self) -> str: + """Return repr of all info""" + return ( + "LinuxDistribution(" + "os_release_file={self.os_release_file!r}, " + "distro_release_file={self.distro_release_file!r}, " + "include_lsb={self.include_lsb!r}, " + "include_uname={self.include_uname!r}, " + "include_oslevel={self.include_oslevel!r}, " + "root_dir={self.root_dir!r}, " + "_os_release_info={self._os_release_info!r}, " + "_lsb_release_info={self._lsb_release_info!r}, " + "_distro_release_info={self._distro_release_info!r}, " + "_uname_info={self._uname_info!r}, " + "_oslevel_info={self._oslevel_info!r})".format(self=self) + ) + + def linux_distribution( + self, full_distribution_name: bool = True + ) -> Tuple[str, str, str]: + """ + Return information about the OS distribution that is compatible + with Python's :func:`platform.linux_distribution`, supporting a subset + of its parameters. + + For details, see :func:`distro.linux_distribution`. + """ + return ( + self.name() if full_distribution_name else self.id(), + self.version(), + self._os_release_info.get("release_codename") or self.codename(), + ) + + def id(self) -> str: + """Return the distro ID of the OS distribution, as a string. + + For details, see :func:`distro.id`. + """ + + def normalize(distro_id: str, table: Dict[str, str]) -> str: + distro_id = distro_id.lower().replace(" ", "_") + return table.get(distro_id, distro_id) + + distro_id = self.os_release_attr("id") + if distro_id: + return normalize(distro_id, NORMALIZED_OS_ID) + + distro_id = self.lsb_release_attr("distributor_id") + if distro_id: + return normalize(distro_id, NORMALIZED_LSB_ID) + + distro_id = self.distro_release_attr("id") + if distro_id: + return normalize(distro_id, NORMALIZED_DISTRO_ID) + + distro_id = self.uname_attr("id") + if distro_id: + return normalize(distro_id, NORMALIZED_DISTRO_ID) + + return "" + + def name(self, pretty: bool = False) -> str: + """ + Return the name of the OS distribution, as a string. + + For details, see :func:`distro.name`. + """ + name = ( + self.os_release_attr("name") + or self.lsb_release_attr("distributor_id") + or self.distro_release_attr("name") + or self.uname_attr("name") + ) + if pretty: + name = self.os_release_attr("pretty_name") or self.lsb_release_attr( + "description" + ) + if not name: + name = self.distro_release_attr("name") or self.uname_attr("name") + version = self.version(pretty=True) + if version: + name = f"{name} {version}" + return name or "" + + def version(self, pretty: bool = False, best: bool = False) -> str: + """ + Return the version of the OS distribution, as a string. + + For details, see :func:`distro.version`. + """ + versions = [ + self.os_release_attr("version_id"), + self.lsb_release_attr("release"), + self.distro_release_attr("version_id"), + self._parse_distro_release_content(self.os_release_attr("pretty_name")).get( + "version_id", "" + ), + self._parse_distro_release_content( + self.lsb_release_attr("description") + ).get("version_id", ""), + self.uname_attr("release"), + ] + if self.uname_attr("id").startswith("aix"): + # On AIX platforms, prefer oslevel command output. + versions.insert(0, self.oslevel_info()) + elif self.id() == "debian" or "debian" in self.like().split(): + # On Debian-like, add debian_version file content to candidates list. + versions.append(self._debian_version) + version = "" + if best: + # This algorithm uses the last version in priority order that has + # the best precision. If the versions are not in conflict, that + # does not matter; otherwise, using the last one instead of the + # first one might be considered a surprise. + for v in versions: + if v.count(".") > version.count(".") or version == "": + version = v + else: + for v in versions: + if v != "": + version = v + break + if pretty and version and self.codename(): + version = f"{version} ({self.codename()})" + return version + + def version_parts(self, best: bool = False) -> Tuple[str, str, str]: + """ + Return the version of the OS distribution, as a tuple of version + numbers. + + For details, see :func:`distro.version_parts`. + """ + version_str = self.version(best=best) + if version_str: + version_regex = re.compile(r"(\d+)\.?(\d+)?\.?(\d+)?") + matches = version_regex.match(version_str) + if matches: + major, minor, build_number = matches.groups() + return major, minor or "", build_number or "" + return "", "", "" + + def major_version(self, best: bool = False) -> str: + """ + Return the major version number of the current distribution. + + For details, see :func:`distro.major_version`. + """ + return self.version_parts(best)[0] + + def minor_version(self, best: bool = False) -> str: + """ + Return the minor version number of the current distribution. + + For details, see :func:`distro.minor_version`. + """ + return self.version_parts(best)[1] + + def build_number(self, best: bool = False) -> str: + """ + Return the build number of the current distribution. + + For details, see :func:`distro.build_number`. + """ + return self.version_parts(best)[2] + + def like(self) -> str: + """ + Return the IDs of distributions that are like the OS distribution. + + For details, see :func:`distro.like`. + """ + return self.os_release_attr("id_like") or "" + + def codename(self) -> str: + """ + Return the codename of the OS distribution. + + For details, see :func:`distro.codename`. + """ + try: + # Handle os_release specially since distros might purposefully set + # this to empty string to have no codename + return self._os_release_info["codename"] + except KeyError: + return ( + self.lsb_release_attr("codename") + or self.distro_release_attr("codename") + or "" + ) + + def info(self, pretty: bool = False, best: bool = False) -> InfoDict: + """ + Return certain machine-readable information about the OS + distribution. + + For details, see :func:`distro.info`. + """ + return InfoDict( + id=self.id(), + version=self.version(pretty, best), + version_parts=VersionDict( + major=self.major_version(best), + minor=self.minor_version(best), + build_number=self.build_number(best), + ), + like=self.like(), + codename=self.codename(), + ) + + def os_release_info(self) -> Dict[str, str]: + """ + Return a dictionary containing key-value pairs for the information + items from the os-release file data source of the OS distribution. + + For details, see :func:`distro.os_release_info`. + """ + return self._os_release_info + + def lsb_release_info(self) -> Dict[str, str]: + """ + Return a dictionary containing key-value pairs for the information + items from the lsb_release command data source of the OS + distribution. + + For details, see :func:`distro.lsb_release_info`. + """ + return self._lsb_release_info + + def distro_release_info(self) -> Dict[str, str]: + """ + Return a dictionary containing key-value pairs for the information + items from the distro release file data source of the OS + distribution. + + For details, see :func:`distro.distro_release_info`. + """ + return self._distro_release_info + + def uname_info(self) -> Dict[str, str]: + """ + Return a dictionary containing key-value pairs for the information + items from the uname command data source of the OS distribution. + + For details, see :func:`distro.uname_info`. + """ + return self._uname_info + + def oslevel_info(self) -> str: + """ + Return AIX' oslevel command output. + """ + return self._oslevel_info + + def os_release_attr(self, attribute: str) -> str: + """ + Return a single named information item from the os-release file data + source of the OS distribution. + + For details, see :func:`distro.os_release_attr`. + """ + return self._os_release_info.get(attribute, "") + + def lsb_release_attr(self, attribute: str) -> str: + """ + Return a single named information item from the lsb_release command + output data source of the OS distribution. + + For details, see :func:`distro.lsb_release_attr`. + """ + return self._lsb_release_info.get(attribute, "") + + def distro_release_attr(self, attribute: str) -> str: + """ + Return a single named information item from the distro release file + data source of the OS distribution. + + For details, see :func:`distro.distro_release_attr`. + """ + return self._distro_release_info.get(attribute, "") + + def uname_attr(self, attribute: str) -> str: + """ + Return a single named information item from the uname command + output data source of the OS distribution. + + For details, see :func:`distro.uname_attr`. + """ + return self._uname_info.get(attribute, "") + + @cached_property + def _os_release_info(self) -> Dict[str, str]: + """ + Get the information items from the specified os-release file. + + Returns: + A dictionary containing all information items. + """ + if os.path.isfile(self.os_release_file): + with open(self.os_release_file, encoding="utf-8") as release_file: + return self._parse_os_release_content(release_file) + return {} + + @staticmethod + def _parse_os_release_content(lines: TextIO) -> Dict[str, str]: + """ + Parse the lines of an os-release file. + + Parameters: + + * lines: Iterable through the lines in the os-release file. + Each line must be a unicode string or a UTF-8 encoded byte + string. + + Returns: + A dictionary containing all information items. + """ + props = {} + lexer = shlex.shlex(lines, posix=True) + lexer.whitespace_split = True + + tokens = list(lexer) + for token in tokens: + # At this point, all shell-like parsing has been done (i.e. + # comments processed, quotes and backslash escape sequences + # processed, multi-line values assembled, trailing newlines + # stripped, etc.), so the tokens are now either: + # * variable assignments: var=value + # * commands or their arguments (not allowed in os-release) + # Ignore any tokens that are not variable assignments + if "=" in token: + k, v = token.split("=", 1) + props[k.lower()] = v + + if "version" in props: + # extract release codename (if any) from version attribute + match = re.search(r"\((\D+)\)|,\s*(\D+)", props["version"]) + if match: + release_codename = match.group(1) or match.group(2) + props["codename"] = props["release_codename"] = release_codename + + if "version_codename" in props: + # os-release added a version_codename field. Use that in + # preference to anything else Note that some distros purposefully + # do not have code names. They should be setting + # version_codename="" + props["codename"] = props["version_codename"] + elif "ubuntu_codename" in props: + # Same as above but a non-standard field name used on older Ubuntus + props["codename"] = props["ubuntu_codename"] + + return props + + @cached_property + def _lsb_release_info(self) -> Dict[str, str]: + """ + Get the information items from the lsb_release command output. + + Returns: + A dictionary containing all information items. + """ + if not self.include_lsb: + return {} + try: + cmd = ("lsb_release", "-a") + stdout = subprocess.check_output(cmd, stderr=subprocess.DEVNULL) + # Command not found or lsb_release returned error + except (OSError, subprocess.CalledProcessError): + return {} + content = self._to_str(stdout).splitlines() + return self._parse_lsb_release_content(content) + + @staticmethod + def _parse_lsb_release_content(lines: Iterable[str]) -> Dict[str, str]: + """ + Parse the output of the lsb_release command. + + Parameters: + + * lines: Iterable through the lines of the lsb_release output. + Each line must be a unicode string or a UTF-8 encoded byte + string. + + Returns: + A dictionary containing all information items. + """ + props = {} + for line in lines: + kv = line.strip("\n").split(":", 1) + if len(kv) != 2: + # Ignore lines without colon. + continue + k, v = kv + props.update({k.replace(" ", "_").lower(): v.strip()}) + return props + + @cached_property + def _uname_info(self) -> Dict[str, str]: + if not self.include_uname: + return {} + try: + cmd = ("uname", "-rs") + stdout = subprocess.check_output(cmd, stderr=subprocess.DEVNULL) + except OSError: + return {} + content = self._to_str(stdout).splitlines() + return self._parse_uname_content(content) + + @cached_property + def _oslevel_info(self) -> str: + if not self.include_oslevel: + return "" + try: + stdout = subprocess.check_output("oslevel", stderr=subprocess.DEVNULL) + except (OSError, subprocess.CalledProcessError): + return "" + return self._to_str(stdout).strip() + + @cached_property + def _debian_version(self) -> str: + try: + with open( + os.path.join(self.etc_dir, "debian_version"), encoding="ascii" + ) as fp: + return fp.readline().rstrip() + except FileNotFoundError: + return "" + + @staticmethod + def _parse_uname_content(lines: Sequence[str]) -> Dict[str, str]: + if not lines: + return {} + props = {} + match = re.search(r"^([^\s]+)\s+([\d\.]+)", lines[0].strip()) + if match: + name, version = match.groups() + + # This is to prevent the Linux kernel version from + # appearing as the 'best' version on otherwise + # identifiable distributions. + if name == "Linux": + return {} + props["id"] = name.lower() + props["name"] = name + props["release"] = version + return props + + @staticmethod + def _to_str(bytestring: bytes) -> str: + encoding = sys.getfilesystemencoding() + return bytestring.decode(encoding) + + @cached_property + def _distro_release_info(self) -> Dict[str, str]: + """ + Get the information items from the specified distro release file. + + Returns: + A dictionary containing all information items. + """ + if self.distro_release_file: + # If it was specified, we use it and parse what we can, even if + # its file name or content does not match the expected pattern. + distro_info = self._parse_distro_release_file(self.distro_release_file) + basename = os.path.basename(self.distro_release_file) + # The file name pattern for user-specified distro release files + # is somewhat more tolerant (compared to when searching for the + # file), because we want to use what was specified as best as + # possible. + match = _DISTRO_RELEASE_BASENAME_PATTERN.match(basename) + else: + try: + basenames = [ + basename + for basename in os.listdir(self.etc_dir) + if basename not in _DISTRO_RELEASE_IGNORE_BASENAMES + and os.path.isfile(os.path.join(self.etc_dir, basename)) + ] + # We sort for repeatability in cases where there are multiple + # distro specific files; e.g. CentOS, Oracle, Enterprise all + # containing `redhat-release` on top of their own. + basenames.sort() + except OSError: + # This may occur when /etc is not readable but we can't be + # sure about the *-release files. Check common entries of + # /etc for information. If they turn out to not be there the + # error is handled in `_parse_distro_release_file()`. + basenames = _DISTRO_RELEASE_BASENAMES + for basename in basenames: + match = _DISTRO_RELEASE_BASENAME_PATTERN.match(basename) + if match is None: + continue + filepath = os.path.join(self.etc_dir, basename) + distro_info = self._parse_distro_release_file(filepath) + # The name is always present if the pattern matches. + if "name" not in distro_info: + continue + self.distro_release_file = filepath + break + else: # the loop didn't "break": no candidate. + return {} + + if match is not None: + distro_info["id"] = match.group(1) + + # CloudLinux < 7: manually enrich info with proper id. + if "cloudlinux" in distro_info.get("name", "").lower(): + distro_info["id"] = "cloudlinux" + + return distro_info + + def _parse_distro_release_file(self, filepath: str) -> Dict[str, str]: + """ + Parse a distro release file. + + Parameters: + + * filepath: Path name of the distro release file. + + Returns: + A dictionary containing all information items. + """ + try: + with open(filepath, encoding="utf-8") as fp: + # Only parse the first line. For instance, on SLES there + # are multiple lines. We don't want them... + return self._parse_distro_release_content(fp.readline()) + except OSError: + # Ignore not being able to read a specific, seemingly version + # related file. + # See https://github.com/python-distro/distro/issues/162 + return {} + + @staticmethod + def _parse_distro_release_content(line: str) -> Dict[str, str]: + """ + Parse a line from a distro release file. + + Parameters: + * line: Line from the distro release file. Must be a unicode string + or a UTF-8 encoded byte string. + + Returns: + A dictionary containing all information items. + """ + matches = _DISTRO_RELEASE_CONTENT_REVERSED_PATTERN.match(line.strip()[::-1]) + distro_info = {} + if matches: + # regexp ensures non-None + distro_info["name"] = matches.group(3)[::-1] + if matches.group(2): + distro_info["version_id"] = matches.group(2)[::-1] + if matches.group(1): + distro_info["codename"] = matches.group(1)[::-1] + elif line: + distro_info["name"] = line.strip() + return distro_info + + +_distro = LinuxDistribution() + + +def main() -> None: + logger = logging.getLogger(__name__) + logger.setLevel(logging.DEBUG) + logger.addHandler(logging.StreamHandler(sys.stdout)) + + parser = argparse.ArgumentParser(description="OS distro info tool") + parser.add_argument( + "--json", "-j", help="Output in machine readable format", action="store_true" + ) + + parser.add_argument( + "--root-dir", + "-r", + type=str, + dest="root_dir", + help="Path to the root filesystem directory (defaults to /)", + ) + + args = parser.parse_args() + + if args.root_dir: + dist = LinuxDistribution( + include_lsb=False, + include_uname=False, + include_oslevel=False, + root_dir=args.root_dir, + ) + else: + dist = _distro + + if args.json: + logger.info(json.dumps(dist.info(), indent=4, sort_keys=True)) + else: + logger.info("Name: %s", dist.name(pretty=True)) + distribution_version = dist.version(pretty=True) + logger.info("Version: %s", distribution_version) + distribution_codename = dist.codename() + logger.info("Codename: %s", distribution_codename) + + +if __name__ == "__main__": + main() diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distro/py.typed b/backend/.venv/Lib/site-packages/pip/_vendor/distro/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/idna/__init__.py b/backend/.venv/Lib/site-packages/pip/_vendor/idna/__init__.py new file mode 100644 index 0000000..a40eeaf --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/idna/__init__.py @@ -0,0 +1,44 @@ +from .package_data import __version__ +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 + +__all__ = [ + "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/pip/_vendor/idna/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3246d943370a5a5c98cea4666ed21c37c98ecb6e GIT binary patch literal 884 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 G2>u6_A{dzG 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ce5ae327807288b9ec25509458a68c200a78ada9 GIT binary patch literal 2636 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 W-k!eF%>Gc|>a3FKUd8M);{OMJ{8Ie@ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/idna/codec.py b/backend/.venv/Lib/site-packages/pip/_vendor/idna/codec.py new file mode 100644 index 0000000..c855a4d --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/idna/codec.py @@ -0,0 +1,118 @@ +from .core import encode, decode, alabel, ulabel, IDNAError +import codecs +import re +from typing import Any, Tuple, Optional + +_unicode_dots_re = re.compile('[\u002e\u3002\uff0e\uff61]') + +class Codec(codecs.Codec): + + def encode(self, data: str, errors: str = 'strict') -> 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/pip/_vendor/idna/compat.py b/backend/.venv/Lib/site-packages/pip/_vendor/idna/compat.py new file mode 100644 index 0000000..786e6bd --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/idna/compat.py @@ -0,0 +1,13 @@ +from .core import * +from .codec import * +from typing import Any, Union + +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/pip/_vendor/idna/core.py b/backend/.venv/Lib/site-packages/pip/_vendor/idna/core.py new file mode 100644 index 0000000..0dae61a --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/idna/core.py @@ -0,0 +1,395 @@ +from . import idnadata +import bisect +import unicodedata +import re +from typing import Union, Optional +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 = None # type: Optional[str] + for (idx, cp) in enumerate(label, 1): + direction = unicodedata.bidirectional(cp) + + if rtl: + # Bidi rule 2 + if not direction 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 not direction 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']): + if not valid_contextj(label, pos): + raise InvalidCodepointContext('Joiner {} not allowed 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 = None # type: Optional[str] + 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/pip/_vendor/idna/idnadata.py b/backend/.venv/Lib/site-packages/pip/_vendor/idna/idnadata.py new file mode 100644 index 0000000..c61dcf9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/idna/idnadata.py @@ -0,0 +1,4245 @@ +# 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/pip/_vendor/idna/intranges.py b/backend/.venv/Lib/site-packages/pip/_vendor/idna/intranges.py new file mode 100644 index 0000000..6a43b04 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/idna/intranges.py @@ -0,0 +1,54 @@ +""" +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/pip/_vendor/idna/package_data.py b/backend/.venv/Lib/site-packages/pip/_vendor/idna/package_data.py new file mode 100644 index 0000000..ed81113 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/idna/package_data.py @@ -0,0 +1,2 @@ +__version__ = '3.7' + diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/idna/py.typed b/backend/.venv/Lib/site-packages/pip/_vendor/idna/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/idna/uts46data.py b/backend/.venv/Lib/site-packages/pip/_vendor/idna/uts46data.py new file mode 100644 index 0000000..6a1eddb --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/idna/uts46data.py @@ -0,0 +1,8598 @@ +# 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/pip/_vendor/msgpack/__init__.py b/backend/.venv/Lib/site-packages/pip/_vendor/msgpack/__init__.py new file mode 100644 index 0000000..919b86f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/msgpack/__init__.py @@ -0,0 +1,55 @@ +from .exceptions import * +from .ext import ExtType, Timestamp + +import os + + +version = (1, 0, 8) +__version__ = "1.0.8" + + +if os.environ.get("MSGPACK_PUREPYTHON"): + from .fallback import Packer, unpackb, Unpacker +else: + try: + from ._cmsgpack import Packer, unpackb, Unpacker + except ImportError: + from .fallback import Packer, unpackb, Unpacker + + +def pack(o, stream, **kwargs): + """ + Pack object `o` and write it to `stream` + + See :class:`Packer` for options. + """ + packer = Packer(**kwargs) + stream.write(packer.pack(o)) + + +def packb(o, **kwargs): + """ + Pack object `o` and return packed bytes + + See :class:`Packer` for options. + """ + return Packer(**kwargs).pack(o) + + +def unpack(stream, **kwargs): + """ + Unpack an object from `stream`. + + Raises `ExtraData` when `stream` contains extra bytes. + See :class:`Unpacker` for options. + """ + data = stream.read() + return unpackb(data, **kwargs) + + +# alias for compatibility to simplejson/marshal/pickle. +load = unpack +loads = unpackb + +dump = pack +dumps = packb diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9df20bd144931275ba5825d0e0a4fa94c0c6c64f GIT binary patch literal 1744 zcmb7E&u<$=6rS;}?X}l-5|gwFE3 z-u{$K#u3=9kFQ#9$p}3aosL1@x5Hg%Hj#-;Tth#Eu<$}PY=`uaE$I^UB~z}+x@?B^ zuo=-KM6RZe_8x1heaAXSt{HuV1DC3Bs#1&DaXoIUx@sr%1V)Y;6Spa~@%eI zm~p^fQw8iJeR`Ux`U|8-?1tfBy}Fqq#y6UPM$>%G7YpW&7ua*CiX=XSu#H|F9l(8!!fl6wLGF(p60n) ziFuS5b}8Tu>#&@^==S#rxQRg=JnSFEW%1&y%(2TO z!FfEg&@kvc;}J1MC=>D$@jNrGEYji!f)pbkt_^Vtlk%v>eMT7IXC#+5>m_&<_rK1)zog zNT5{zcJj=|96;;ljvQZ~T$|iDwK??l(8CYDIs2=u9l}CX=_Uj^-DF*Y&U4AakSr{c zbz-8rDVavu(CUZ(nFva}Me1liMW$9>@d*1Ld7w#%DjV`M;XfDrUKpZj047AIX;e_a z!{UZAJq`X@F?R;QrzDZyR);oj0{o_G+p6|$-xD>nC1>aWtT>s9Jj`sOCaNAM3dV#z z3L11j#tCHz;*!PzNIEe#Bg^xrWKZ0vSAS(XR8bK;{d{4>WkE^0w`oi#0M%hhekGGy4>v zEn$pz(cm7+JVmi~1gZV4=uT>&rGhU<*7Ixm_3^dwt@NwENEi0xi$BX3+p-iM+f&B2 zm9c|(6u*4XAHnAj(hAPBUqni(CGRLbt?=(rRd~s@@Sp8F7$r_0AS||Bexh84OT%N& Wn8?eI@rgn7c(7;UHRbObUly-p@mFWSrMl{_kE8wuuMJqvyMA<`#WKHc!W7hG68K>P; zJyfEHJ%H3(_rM>h_$hl?Zk4b6fwIYo6Yq_aG>wV`Bl-Ew_ujns=FNNWRi)w*Sl|5c zS@elT$e*|wui}Uq{07VgG09gXBxfWvIQhMh%NmA8O+X9Wn4qRcEkNxlw4l); z9Q@&G*cx{LFWth6+-l5enG3RcJ~y%NaMA$XhRf$0<$l?#1i7i48l%l%37884x<*JE zW@t1DebXysi{B?*7ChT|9`J4&iRAdzBc?bFVx|;r2}zacaLUJGMJ0caD>th>*v}x$Eir$T++175~_OpxfjvWXJ-PbQTn7s`=UpWSd!9I z(14{uo3c2jTuLE7&H;UP5a|*2KJLYF{jwl!G=LQ=(X1>X(MIQytBeUk1JpeuSJuca3jed)(rz!^ zZGFj7R+kHCb;eT_F(g{Jh&vqyLU%j)mnxlqEM$kJJNWL$_nst&ERI4t$}5&B22QFVH zChW!|iS&tQ)S-Hv+!zlto8!e`ELn=jE%`2-l50Q|T7>x`v4F9qqa;dw|9E+F``Q@$ z0M)UKPRZ3f^o8|H<4*Wp-$baV2O+-dOm1$)8o0!eahk<*EOsgLzif_l#kyj z8CuFJ-(tOwO=SzXz0t`kyN6u1VsWI+WmOd4f@bcKIiKbu_;dLonAejp2Ijh87{<^n z8qRq%B=8$98%F8;{UL$h&_RB2!f&2`^itq%6D6zXYcGA=tzNriW#ctj8WzjOgV#%R aNZ@}>Np(np+ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9c76974c1acf563384524c9575b17b59e211a8c8 GIT binary patch literal 8173 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 z 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 34 + elif len(b) == 12: + nanoseconds, seconds = struct.unpack("!Iq", b) + else: + raise ValueError( + "Timestamp type can only be created from 32, 64, or 96-bit byte objects" + ) + return Timestamp(seconds, nanoseconds) + + def to_bytes(self): + """Pack this Timestamp object into bytes. + + Used for pure-Python msgpack packing. + + :returns data: Payload for EXT message with code -1 (timestamp type) + :rtype: bytes + """ + if (self.seconds >> 34) == 0: # seconds is non-negative and fits in 34 bits + data64 = self.nanoseconds << 34 | self.seconds + if data64 & 0xFFFFFFFF00000000 == 0: + # nanoseconds is zero and seconds < 2**32, so timestamp 32 + data = struct.pack("!L", data64) + else: + # timestamp 64 + data = struct.pack("!Q", data64) + else: + # timestamp 96 + data = struct.pack("!Iq", self.nanoseconds, self.seconds) + return data + + @staticmethod + def from_unix(unix_sec): + """Create a Timestamp from posix timestamp in seconds. + + :param unix_float: Posix timestamp in seconds. + :type unix_float: int or float + """ + seconds = int(unix_sec // 1) + nanoseconds = int((unix_sec % 1) * 10**9) + return Timestamp(seconds, nanoseconds) + + def to_unix(self): + """Get the timestamp as a floating-point value. + + :returns: posix timestamp + :rtype: float + """ + return self.seconds + self.nanoseconds / 1e9 + + @staticmethod + def from_unix_nano(unix_ns): + """Create a Timestamp from posix timestamp in nanoseconds. + + :param int unix_ns: Posix timestamp in nanoseconds. + :rtype: Timestamp + """ + return Timestamp(*divmod(unix_ns, 10**9)) + + def to_unix_nano(self): + """Get the timestamp as a unixtime in nanoseconds. + + :returns: posix timestamp in nanoseconds + :rtype: int + """ + return self.seconds * 10**9 + self.nanoseconds + + def to_datetime(self): + """Get the timestamp as a UTC datetime. + + :rtype: `datetime.datetime` + """ + utc = datetime.timezone.utc + return datetime.datetime.fromtimestamp(0, utc) + datetime.timedelta(seconds=self.to_unix()) + + @staticmethod + def from_datetime(dt): + """Create a Timestamp from datetime with tzinfo. + + :rtype: Timestamp + """ + return Timestamp.from_unix(dt.timestamp()) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/msgpack/fallback.py b/backend/.venv/Lib/site-packages/pip/_vendor/msgpack/fallback.py new file mode 100644 index 0000000..a174162 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/msgpack/fallback.py @@ -0,0 +1,951 @@ +"""Fallback pure Python implementation of msgpack""" +from datetime import datetime as _DateTime +import sys +import struct + + +if hasattr(sys, "pypy_version_info"): + # StringIO is slow on PyPy, StringIO is faster. However: PyPy's own + # StringBuilder is fastest. + from __pypy__ import newlist_hint + + try: + from __pypy__.builders import BytesBuilder as StringBuilder + except ImportError: + from __pypy__.builders import StringBuilder + USING_STRINGBUILDER = True + + class StringIO: + def __init__(self, s=b""): + if s: + self.builder = StringBuilder(len(s)) + self.builder.append(s) + else: + self.builder = StringBuilder() + + def write(self, s): + if isinstance(s, memoryview): + s = s.tobytes() + elif isinstance(s, bytearray): + s = bytes(s) + self.builder.append(s) + + def getvalue(self): + return self.builder.build() + +else: + USING_STRINGBUILDER = False + from io import BytesIO as StringIO + + newlist_hint = lambda size: [] + + +from .exceptions import BufferFull, OutOfData, ExtraData, FormatError, StackError + +from .ext import ExtType, Timestamp + + +EX_SKIP = 0 +EX_CONSTRUCT = 1 +EX_READ_ARRAY_HEADER = 2 +EX_READ_MAP_HEADER = 3 + +TYPE_IMMEDIATE = 0 +TYPE_ARRAY = 1 +TYPE_MAP = 2 +TYPE_RAW = 3 +TYPE_BIN = 4 +TYPE_EXT = 5 + +DEFAULT_RECURSE_LIMIT = 511 + + +def _check_type_strict(obj, t, type=type, tuple=tuple): + if type(t) is tuple: + return type(obj) in t + else: + return type(obj) is t + + +def _get_data_from_buffer(obj): + view = memoryview(obj) + if view.itemsize != 1: + raise ValueError("cannot unpack from multi-byte object") + return view + + +def unpackb(packed, **kwargs): + """ + Unpack an object from `packed`. + + Raises ``ExtraData`` when *packed* contains extra bytes. + Raises ``ValueError`` when *packed* is incomplete. + Raises ``FormatError`` when *packed* is not valid msgpack. + Raises ``StackError`` when *packed* contains too nested. + Other exceptions can be raised during unpacking. + + See :class:`Unpacker` for options. + """ + unpacker = Unpacker(None, max_buffer_size=len(packed), **kwargs) + unpacker.feed(packed) + try: + ret = unpacker._unpack() + except OutOfData: + raise ValueError("Unpack failed: incomplete input") + except RecursionError: + raise StackError + if unpacker._got_extradata(): + raise ExtraData(ret, unpacker._get_extradata()) + return ret + + +_NO_FORMAT_USED = "" +_MSGPACK_HEADERS = { + 0xC4: (1, _NO_FORMAT_USED, TYPE_BIN), + 0xC5: (2, ">H", TYPE_BIN), + 0xC6: (4, ">I", TYPE_BIN), + 0xC7: (2, "Bb", TYPE_EXT), + 0xC8: (3, ">Hb", TYPE_EXT), + 0xC9: (5, ">Ib", TYPE_EXT), + 0xCA: (4, ">f"), + 0xCB: (8, ">d"), + 0xCC: (1, _NO_FORMAT_USED), + 0xCD: (2, ">H"), + 0xCE: (4, ">I"), + 0xCF: (8, ">Q"), + 0xD0: (1, "b"), + 0xD1: (2, ">h"), + 0xD2: (4, ">i"), + 0xD3: (8, ">q"), + 0xD4: (1, "b1s", TYPE_EXT), + 0xD5: (2, "b2s", TYPE_EXT), + 0xD6: (4, "b4s", TYPE_EXT), + 0xD7: (8, "b8s", TYPE_EXT), + 0xD8: (16, "b16s", TYPE_EXT), + 0xD9: (1, _NO_FORMAT_USED, TYPE_RAW), + 0xDA: (2, ">H", TYPE_RAW), + 0xDB: (4, ">I", TYPE_RAW), + 0xDC: (2, ">H", TYPE_ARRAY), + 0xDD: (4, ">I", TYPE_ARRAY), + 0xDE: (2, ">H", TYPE_MAP), + 0xDF: (4, ">I", TYPE_MAP), +} + + +class Unpacker: + """Streaming unpacker. + + Arguments: + + :param file_like: + File-like object having `.read(n)` method. + If specified, unpacker reads serialized data from it and `.feed()` is not usable. + + :param int read_size: + Used as `file_like.read(read_size)`. (default: `min(16*1024, max_buffer_size)`) + + :param bool use_list: + If true, unpack msgpack array to Python list. + Otherwise, unpack to Python tuple. (default: True) + + :param bool raw: + If true, unpack msgpack raw to Python bytes. + Otherwise, unpack to Python str by decoding with UTF-8 encoding (default). + + :param int timestamp: + Control how timestamp type is unpacked: + + 0 - Timestamp + 1 - float (Seconds from the EPOCH) + 2 - int (Nanoseconds from the EPOCH) + 3 - datetime.datetime (UTC). + + :param bool strict_map_key: + If true (default), only str or bytes are accepted for map (dict) keys. + + :param object_hook: + When specified, it should be callable. + Unpacker calls it with a dict argument after unpacking msgpack map. + (See also simplejson) + + :param object_pairs_hook: + When specified, it should be callable. + Unpacker calls it with a list of key-value pairs after unpacking msgpack map. + (See also simplejson) + + :param str unicode_errors: + The error handler for decoding unicode. (default: 'strict') + This option should be used only when you have msgpack data which + contains invalid UTF-8 string. + + :param int max_buffer_size: + Limits size of data waiting unpacked. 0 means 2**32-1. + The default value is 100*1024*1024 (100MiB). + Raises `BufferFull` exception when it is insufficient. + You should set this parameter when unpacking data from untrusted source. + + :param int max_str_len: + Deprecated, use *max_buffer_size* instead. + Limits max length of str. (default: max_buffer_size) + + :param int max_bin_len: + Deprecated, use *max_buffer_size* instead. + Limits max length of bin. (default: max_buffer_size) + + :param int max_array_len: + Limits max length of array. + (default: max_buffer_size) + + :param int max_map_len: + Limits max length of map. + (default: max_buffer_size//2) + + :param int max_ext_len: + Deprecated, use *max_buffer_size* instead. + Limits max size of ext type. (default: max_buffer_size) + + Example of streaming deserialize from file-like object:: + + unpacker = Unpacker(file_like) + for o in unpacker: + process(o) + + Example of streaming deserialize from socket:: + + unpacker = Unpacker() + while True: + buf = sock.recv(1024**2) + if not buf: + break + unpacker.feed(buf) + for o in unpacker: + process(o) + + Raises ``ExtraData`` when *packed* contains extra bytes. + Raises ``OutOfData`` when *packed* is incomplete. + Raises ``FormatError`` when *packed* is not valid msgpack. + Raises ``StackError`` when *packed* contains too nested. + Other exceptions can be raised during unpacking. + """ + + def __init__( + self, + file_like=None, + read_size=0, + use_list=True, + raw=False, + timestamp=0, + strict_map_key=True, + object_hook=None, + object_pairs_hook=None, + list_hook=None, + unicode_errors=None, + max_buffer_size=100 * 1024 * 1024, + ext_hook=ExtType, + max_str_len=-1, + max_bin_len=-1, + max_array_len=-1, + max_map_len=-1, + max_ext_len=-1, + ): + if unicode_errors is None: + unicode_errors = "strict" + + if file_like is None: + self._feeding = True + else: + if not callable(file_like.read): + raise TypeError("`file_like.read` must be callable") + self.file_like = file_like + self._feeding = False + + #: array of bytes fed. + self._buffer = bytearray() + #: Which position we currently reads + self._buff_i = 0 + + # When Unpacker is used as an iterable, between the calls to next(), + # the buffer is not "consumed" completely, for efficiency sake. + # Instead, it is done sloppily. To make sure we raise BufferFull at + # the correct moments, we have to keep track of how sloppy we were. + # Furthermore, when the buffer is incomplete (that is: in the case + # we raise an OutOfData) we need to rollback the buffer to the correct + # state, which _buf_checkpoint records. + self._buf_checkpoint = 0 + + if not max_buffer_size: + max_buffer_size = 2**31 - 1 + if max_str_len == -1: + max_str_len = max_buffer_size + if max_bin_len == -1: + max_bin_len = max_buffer_size + if max_array_len == -1: + max_array_len = max_buffer_size + if max_map_len == -1: + max_map_len = max_buffer_size // 2 + if max_ext_len == -1: + max_ext_len = max_buffer_size + + self._max_buffer_size = max_buffer_size + if read_size > self._max_buffer_size: + raise ValueError("read_size must be smaller than max_buffer_size") + self._read_size = read_size or min(self._max_buffer_size, 16 * 1024) + self._raw = bool(raw) + self._strict_map_key = bool(strict_map_key) + self._unicode_errors = unicode_errors + self._use_list = use_list + if not (0 <= timestamp <= 3): + raise ValueError("timestamp must be 0..3") + self._timestamp = timestamp + self._list_hook = list_hook + self._object_hook = object_hook + self._object_pairs_hook = object_pairs_hook + self._ext_hook = ext_hook + self._max_str_len = max_str_len + self._max_bin_len = max_bin_len + self._max_array_len = max_array_len + self._max_map_len = max_map_len + self._max_ext_len = max_ext_len + self._stream_offset = 0 + + if list_hook is not None and not callable(list_hook): + raise TypeError("`list_hook` is not callable") + if object_hook is not None and not callable(object_hook): + raise TypeError("`object_hook` is not callable") + if object_pairs_hook is not None and not callable(object_pairs_hook): + raise TypeError("`object_pairs_hook` is not callable") + if object_hook is not None and object_pairs_hook is not None: + raise TypeError("object_pairs_hook and object_hook are mutually exclusive") + if not callable(ext_hook): + raise TypeError("`ext_hook` is not callable") + + def feed(self, next_bytes): + assert self._feeding + view = _get_data_from_buffer(next_bytes) + if len(self._buffer) - self._buff_i + len(view) > self._max_buffer_size: + raise BufferFull + + # Strip buffer before checkpoint before reading file. + if self._buf_checkpoint > 0: + del self._buffer[: self._buf_checkpoint] + self._buff_i -= self._buf_checkpoint + self._buf_checkpoint = 0 + + # Use extend here: INPLACE_ADD += doesn't reliably typecast memoryview in jython + self._buffer.extend(view) + + def _consume(self): + """Gets rid of the used parts of the buffer.""" + self._stream_offset += self._buff_i - self._buf_checkpoint + self._buf_checkpoint = self._buff_i + + def _got_extradata(self): + return self._buff_i < len(self._buffer) + + def _get_extradata(self): + return self._buffer[self._buff_i :] + + def read_bytes(self, n): + ret = self._read(n, raise_outofdata=False) + self._consume() + return ret + + def _read(self, n, raise_outofdata=True): + # (int) -> bytearray + self._reserve(n, raise_outofdata=raise_outofdata) + i = self._buff_i + ret = self._buffer[i : i + n] + self._buff_i = i + len(ret) + return ret + + def _reserve(self, n, raise_outofdata=True): + remain_bytes = len(self._buffer) - self._buff_i - n + + # Fast path: buffer has n bytes already + if remain_bytes >= 0: + return + + if self._feeding: + self._buff_i = self._buf_checkpoint + raise OutOfData + + # Strip buffer before checkpoint before reading file. + if self._buf_checkpoint > 0: + del self._buffer[: self._buf_checkpoint] + self._buff_i -= self._buf_checkpoint + self._buf_checkpoint = 0 + + # Read from file + remain_bytes = -remain_bytes + if remain_bytes + len(self._buffer) > self._max_buffer_size: + raise BufferFull + while remain_bytes > 0: + to_read_bytes = max(self._read_size, remain_bytes) + read_data = self.file_like.read(to_read_bytes) + if not read_data: + break + assert isinstance(read_data, bytes) + self._buffer += read_data + remain_bytes -= len(read_data) + + if len(self._buffer) < n + self._buff_i and raise_outofdata: + self._buff_i = 0 # rollback + raise OutOfData + + def _read_header(self): + typ = TYPE_IMMEDIATE + n = 0 + obj = None + self._reserve(1) + b = self._buffer[self._buff_i] + self._buff_i += 1 + if b & 0b10000000 == 0: + obj = b + elif b & 0b11100000 == 0b11100000: + obj = -1 - (b ^ 0xFF) + elif b & 0b11100000 == 0b10100000: + n = b & 0b00011111 + typ = TYPE_RAW + if n > self._max_str_len: + raise ValueError(f"{n} exceeds max_str_len({self._max_str_len})") + obj = self._read(n) + elif b & 0b11110000 == 0b10010000: + n = b & 0b00001111 + typ = TYPE_ARRAY + if n > self._max_array_len: + raise ValueError(f"{n} exceeds max_array_len({self._max_array_len})") + elif b & 0b11110000 == 0b10000000: + n = b & 0b00001111 + typ = TYPE_MAP + if n > self._max_map_len: + raise ValueError(f"{n} exceeds max_map_len({self._max_map_len})") + elif b == 0xC0: + obj = None + elif b == 0xC2: + obj = False + elif b == 0xC3: + obj = True + elif 0xC4 <= b <= 0xC6: + size, fmt, typ = _MSGPACK_HEADERS[b] + self._reserve(size) + if len(fmt) > 0: + n = struct.unpack_from(fmt, self._buffer, self._buff_i)[0] + else: + n = self._buffer[self._buff_i] + self._buff_i += size + if n > self._max_bin_len: + raise ValueError(f"{n} exceeds max_bin_len({self._max_bin_len})") + obj = self._read(n) + elif 0xC7 <= b <= 0xC9: + size, fmt, typ = _MSGPACK_HEADERS[b] + self._reserve(size) + L, n = struct.unpack_from(fmt, self._buffer, self._buff_i) + self._buff_i += size + if L > self._max_ext_len: + raise ValueError(f"{L} exceeds max_ext_len({self._max_ext_len})") + obj = self._read(L) + elif 0xCA <= b <= 0xD3: + size, fmt = _MSGPACK_HEADERS[b] + self._reserve(size) + if len(fmt) > 0: + obj = struct.unpack_from(fmt, self._buffer, self._buff_i)[0] + else: + obj = self._buffer[self._buff_i] + self._buff_i += size + elif 0xD4 <= b <= 0xD8: + size, fmt, typ = _MSGPACK_HEADERS[b] + if self._max_ext_len < size: + raise ValueError(f"{size} exceeds max_ext_len({self._max_ext_len})") + self._reserve(size + 1) + n, obj = struct.unpack_from(fmt, self._buffer, self._buff_i) + self._buff_i += size + 1 + elif 0xD9 <= b <= 0xDB: + size, fmt, typ = _MSGPACK_HEADERS[b] + self._reserve(size) + if len(fmt) > 0: + (n,) = struct.unpack_from(fmt, self._buffer, self._buff_i) + else: + n = self._buffer[self._buff_i] + self._buff_i += size + if n > self._max_str_len: + raise ValueError(f"{n} exceeds max_str_len({self._max_str_len})") + obj = self._read(n) + elif 0xDC <= b <= 0xDD: + size, fmt, typ = _MSGPACK_HEADERS[b] + self._reserve(size) + (n,) = struct.unpack_from(fmt, self._buffer, self._buff_i) + self._buff_i += size + if n > self._max_array_len: + raise ValueError(f"{n} exceeds max_array_len({self._max_array_len})") + elif 0xDE <= b <= 0xDF: + size, fmt, typ = _MSGPACK_HEADERS[b] + self._reserve(size) + (n,) = struct.unpack_from(fmt, self._buffer, self._buff_i) + self._buff_i += size + if n > self._max_map_len: + raise ValueError(f"{n} exceeds max_map_len({self._max_map_len})") + else: + raise FormatError("Unknown header: 0x%x" % b) + return typ, n, obj + + def _unpack(self, execute=EX_CONSTRUCT): + typ, n, obj = self._read_header() + + if execute == EX_READ_ARRAY_HEADER: + if typ != TYPE_ARRAY: + raise ValueError("Expected array") + return n + if execute == EX_READ_MAP_HEADER: + if typ != TYPE_MAP: + raise ValueError("Expected map") + return n + # TODO should we eliminate the recursion? + if typ == TYPE_ARRAY: + if execute == EX_SKIP: + for i in range(n): + # TODO check whether we need to call `list_hook` + self._unpack(EX_SKIP) + return + ret = newlist_hint(n) + for i in range(n): + ret.append(self._unpack(EX_CONSTRUCT)) + if self._list_hook is not None: + ret = self._list_hook(ret) + # TODO is the interaction between `list_hook` and `use_list` ok? + return ret if self._use_list else tuple(ret) + if typ == TYPE_MAP: + if execute == EX_SKIP: + for i in range(n): + # TODO check whether we need to call hooks + self._unpack(EX_SKIP) + self._unpack(EX_SKIP) + return + if self._object_pairs_hook is not None: + ret = self._object_pairs_hook( + (self._unpack(EX_CONSTRUCT), self._unpack(EX_CONSTRUCT)) for _ in range(n) + ) + else: + ret = {} + for _ in range(n): + key = self._unpack(EX_CONSTRUCT) + if self._strict_map_key and type(key) not in (str, bytes): + raise ValueError("%s is not allowed for map key" % str(type(key))) + if isinstance(key, str): + key = sys.intern(key) + ret[key] = self._unpack(EX_CONSTRUCT) + if self._object_hook is not None: + ret = self._object_hook(ret) + return ret + if execute == EX_SKIP: + return + if typ == TYPE_RAW: + if self._raw: + obj = bytes(obj) + else: + obj = obj.decode("utf_8", self._unicode_errors) + return obj + if typ == TYPE_BIN: + return bytes(obj) + if typ == TYPE_EXT: + if n == -1: # timestamp + ts = Timestamp.from_bytes(bytes(obj)) + if self._timestamp == 1: + return ts.to_unix() + elif self._timestamp == 2: + return ts.to_unix_nano() + elif self._timestamp == 3: + return ts.to_datetime() + else: + return ts + else: + return self._ext_hook(n, bytes(obj)) + assert typ == TYPE_IMMEDIATE + return obj + + def __iter__(self): + return self + + def __next__(self): + try: + ret = self._unpack(EX_CONSTRUCT) + self._consume() + return ret + except OutOfData: + self._consume() + raise StopIteration + except RecursionError: + raise StackError + + next = __next__ + + def skip(self): + self._unpack(EX_SKIP) + self._consume() + + def unpack(self): + try: + ret = self._unpack(EX_CONSTRUCT) + except RecursionError: + raise StackError + self._consume() + return ret + + def read_array_header(self): + ret = self._unpack(EX_READ_ARRAY_HEADER) + self._consume() + return ret + + def read_map_header(self): + ret = self._unpack(EX_READ_MAP_HEADER) + self._consume() + return ret + + def tell(self): + return self._stream_offset + + +class Packer: + """ + MessagePack Packer + + Usage:: + + packer = Packer() + astream.write(packer.pack(a)) + astream.write(packer.pack(b)) + + Packer's constructor has some keyword arguments: + + :param default: + When specified, it should be callable. + Convert user type to builtin type that Packer supports. + See also simplejson's document. + + :param bool use_single_float: + Use single precision float type for float. (default: False) + + :param bool autoreset: + Reset buffer after each pack and return its content as `bytes`. (default: True). + If set this to false, use `bytes()` to get content and `.reset()` to clear buffer. + + :param bool use_bin_type: + Use bin type introduced in msgpack spec 2.0 for bytes. + It also enables str8 type for unicode. (default: True) + + :param bool strict_types: + If set to true, types will be checked to be exact. Derived classes + from serializable types will not be serialized and will be + treated as unsupported type and forwarded to default. + Additionally tuples will not be serialized as lists. + This is useful when trying to implement accurate serialization + for python types. + + :param bool datetime: + If set to true, datetime with tzinfo is packed into Timestamp type. + Note that the tzinfo is stripped in the timestamp. + You can get UTC datetime with `timestamp=3` option of the Unpacker. + + :param str unicode_errors: + The error handler for encoding unicode. (default: 'strict') + DO NOT USE THIS!! This option is kept for very specific usage. + + Example of streaming deserialize from file-like object:: + + unpacker = Unpacker(file_like) + for o in unpacker: + process(o) + + Example of streaming deserialize from socket:: + + unpacker = Unpacker() + while True: + buf = sock.recv(1024**2) + if not buf: + break + unpacker.feed(buf) + for o in unpacker: + process(o) + + Raises ``ExtraData`` when *packed* contains extra bytes. + Raises ``OutOfData`` when *packed* is incomplete. + Raises ``FormatError`` when *packed* is not valid msgpack. + Raises ``StackError`` when *packed* contains too nested. + Other exceptions can be raised during unpacking. + """ + + def __init__( + self, + default=None, + use_single_float=False, + autoreset=True, + use_bin_type=True, + strict_types=False, + datetime=False, + unicode_errors=None, + ): + self._strict_types = strict_types + self._use_float = use_single_float + self._autoreset = autoreset + self._use_bin_type = use_bin_type + self._buffer = StringIO() + self._datetime = bool(datetime) + self._unicode_errors = unicode_errors or "strict" + if default is not None: + if not callable(default): + raise TypeError("default must be callable") + self._default = default + + def _pack( + self, + obj, + nest_limit=DEFAULT_RECURSE_LIMIT, + check=isinstance, + check_type_strict=_check_type_strict, + ): + default_used = False + if self._strict_types: + check = check_type_strict + list_types = list + else: + list_types = (list, tuple) + while True: + if nest_limit < 0: + raise ValueError("recursion limit exceeded") + if obj is None: + return self._buffer.write(b"\xc0") + if check(obj, bool): + if obj: + return self._buffer.write(b"\xc3") + return self._buffer.write(b"\xc2") + if check(obj, int): + if 0 <= obj < 0x80: + return self._buffer.write(struct.pack("B", obj)) + if -0x20 <= obj < 0: + return self._buffer.write(struct.pack("b", obj)) + if 0x80 <= obj <= 0xFF: + return self._buffer.write(struct.pack("BB", 0xCC, obj)) + if -0x80 <= obj < 0: + return self._buffer.write(struct.pack(">Bb", 0xD0, obj)) + if 0xFF < obj <= 0xFFFF: + return self._buffer.write(struct.pack(">BH", 0xCD, obj)) + if -0x8000 <= obj < -0x80: + return self._buffer.write(struct.pack(">Bh", 0xD1, obj)) + if 0xFFFF < obj <= 0xFFFFFFFF: + return self._buffer.write(struct.pack(">BI", 0xCE, obj)) + if -0x80000000 <= obj < -0x8000: + return self._buffer.write(struct.pack(">Bi", 0xD2, obj)) + if 0xFFFFFFFF < obj <= 0xFFFFFFFFFFFFFFFF: + return self._buffer.write(struct.pack(">BQ", 0xCF, obj)) + if -0x8000000000000000 <= obj < -0x80000000: + return self._buffer.write(struct.pack(">Bq", 0xD3, obj)) + if not default_used and self._default is not None: + obj = self._default(obj) + default_used = True + continue + raise OverflowError("Integer value out of range") + if check(obj, (bytes, bytearray)): + n = len(obj) + if n >= 2**32: + raise ValueError("%s is too large" % type(obj).__name__) + self._pack_bin_header(n) + return self._buffer.write(obj) + if check(obj, str): + obj = obj.encode("utf-8", self._unicode_errors) + n = len(obj) + if n >= 2**32: + raise ValueError("String is too large") + self._pack_raw_header(n) + return self._buffer.write(obj) + if check(obj, memoryview): + n = obj.nbytes + if n >= 2**32: + raise ValueError("Memoryview is too large") + self._pack_bin_header(n) + return self._buffer.write(obj) + if check(obj, float): + if self._use_float: + return self._buffer.write(struct.pack(">Bf", 0xCA, obj)) + return self._buffer.write(struct.pack(">Bd", 0xCB, obj)) + if check(obj, (ExtType, Timestamp)): + if check(obj, Timestamp): + code = -1 + data = obj.to_bytes() + else: + code = obj.code + data = obj.data + assert isinstance(code, int) + assert isinstance(data, bytes) + L = len(data) + if L == 1: + self._buffer.write(b"\xd4") + elif L == 2: + self._buffer.write(b"\xd5") + elif L == 4: + self._buffer.write(b"\xd6") + elif L == 8: + self._buffer.write(b"\xd7") + elif L == 16: + self._buffer.write(b"\xd8") + elif L <= 0xFF: + self._buffer.write(struct.pack(">BB", 0xC7, L)) + elif L <= 0xFFFF: + self._buffer.write(struct.pack(">BH", 0xC8, L)) + else: + self._buffer.write(struct.pack(">BI", 0xC9, L)) + self._buffer.write(struct.pack("b", code)) + self._buffer.write(data) + return + if check(obj, list_types): + n = len(obj) + self._pack_array_header(n) + for i in range(n): + self._pack(obj[i], nest_limit - 1) + return + if check(obj, dict): + return self._pack_map_pairs(len(obj), obj.items(), nest_limit - 1) + + if self._datetime and check(obj, _DateTime) and obj.tzinfo is not None: + obj = Timestamp.from_datetime(obj) + default_used = 1 + continue + + if not default_used and self._default is not None: + obj = self._default(obj) + default_used = 1 + continue + + if self._datetime and check(obj, _DateTime): + raise ValueError(f"Cannot serialize {obj!r} where tzinfo=None") + + raise TypeError(f"Cannot serialize {obj!r}") + + def pack(self, obj): + try: + self._pack(obj) + except: + self._buffer = StringIO() # force reset + raise + if self._autoreset: + ret = self._buffer.getvalue() + self._buffer = StringIO() + return ret + + def pack_map_pairs(self, pairs): + self._pack_map_pairs(len(pairs), pairs) + if self._autoreset: + ret = self._buffer.getvalue() + self._buffer = StringIO() + return ret + + def pack_array_header(self, n): + if n >= 2**32: + raise ValueError + self._pack_array_header(n) + if self._autoreset: + ret = self._buffer.getvalue() + self._buffer = StringIO() + return ret + + def pack_map_header(self, n): + if n >= 2**32: + raise ValueError + self._pack_map_header(n) + if self._autoreset: + ret = self._buffer.getvalue() + self._buffer = StringIO() + return ret + + def pack_ext_type(self, typecode, data): + if not isinstance(typecode, int): + raise TypeError("typecode must have int type.") + if not 0 <= typecode <= 127: + raise ValueError("typecode should be 0-127") + if not isinstance(data, bytes): + raise TypeError("data must have bytes type") + L = len(data) + if L > 0xFFFFFFFF: + raise ValueError("Too large data") + if L == 1: + self._buffer.write(b"\xd4") + elif L == 2: + self._buffer.write(b"\xd5") + elif L == 4: + self._buffer.write(b"\xd6") + elif L == 8: + self._buffer.write(b"\xd7") + elif L == 16: + self._buffer.write(b"\xd8") + elif L <= 0xFF: + self._buffer.write(b"\xc7" + struct.pack("B", L)) + elif L <= 0xFFFF: + self._buffer.write(b"\xc8" + struct.pack(">H", L)) + else: + self._buffer.write(b"\xc9" + struct.pack(">I", L)) + self._buffer.write(struct.pack("B", typecode)) + self._buffer.write(data) + + def _pack_array_header(self, n): + if n <= 0x0F: + return self._buffer.write(struct.pack("B", 0x90 + n)) + if n <= 0xFFFF: + return self._buffer.write(struct.pack(">BH", 0xDC, n)) + if n <= 0xFFFFFFFF: + return self._buffer.write(struct.pack(">BI", 0xDD, n)) + raise ValueError("Array is too large") + + def _pack_map_header(self, n): + if n <= 0x0F: + return self._buffer.write(struct.pack("B", 0x80 + n)) + if n <= 0xFFFF: + return self._buffer.write(struct.pack(">BH", 0xDE, n)) + if n <= 0xFFFFFFFF: + return self._buffer.write(struct.pack(">BI", 0xDF, n)) + raise ValueError("Dict is too large") + + def _pack_map_pairs(self, n, pairs, nest_limit=DEFAULT_RECURSE_LIMIT): + self._pack_map_header(n) + for k, v in pairs: + self._pack(k, nest_limit - 1) + self._pack(v, nest_limit - 1) + + def _pack_raw_header(self, n): + if n <= 0x1F: + self._buffer.write(struct.pack("B", 0xA0 + n)) + elif self._use_bin_type and n <= 0xFF: + self._buffer.write(struct.pack(">BB", 0xD9, n)) + elif n <= 0xFFFF: + self._buffer.write(struct.pack(">BH", 0xDA, n)) + elif n <= 0xFFFFFFFF: + self._buffer.write(struct.pack(">BI", 0xDB, n)) + else: + raise ValueError("Raw is too large") + + def _pack_bin_header(self, n): + if not self._use_bin_type: + return self._pack_raw_header(n) + elif n <= 0xFF: + return self._buffer.write(struct.pack(">BB", 0xC4, n)) + elif n <= 0xFFFF: + return self._buffer.write(struct.pack(">BH", 0xC5, n)) + elif n <= 0xFFFFFFFF: + return self._buffer.write(struct.pack(">BI", 0xC6, n)) + else: + raise ValueError("Bin is too large") + + def bytes(self): + """Return internal buffer contents as bytes object""" + return self._buffer.getvalue() + + def reset(self): + """Reset internal buffer. + + This method is useful only when autoreset=False. + """ + self._buffer = StringIO() + + def getbuffer(self): + """Return view of internal buffer.""" + if USING_STRINGBUILDER: + return memoryview(self.bytes()) + else: + return self._buffer.getbuffer() diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__init__.py b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__init__.py new file mode 100644 index 0000000..9ba41d8 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__init__.py @@ -0,0 +1,15 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +__title__ = "packaging" +__summary__ = "Core utilities for Python packages" +__uri__ = "https://github.com/pypa/packaging" + +__version__ = "24.1" + +__author__ = "Donald Stufft and individual contributors" +__email__ = "donald@stufft.io" + +__license__ = "BSD-2-Clause or Apache-2.0" +__copyright__ = "2014 %s" % __author__ diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f0f7b2ad58536876695dcf98ee731553595bb38b GIT binary patch literal 561 zcmYLGO^?$s5Ovya)25rM2M)ji1tgHVQj*=O2ebkNbWaEn(%wQO%Z=T3*wl{vQIwp* zuYkY6Z{ftP>ZuZcpwiwr;ci*&9ISbsH*dzzzkJ_AHa>iQ2|EX&KYMT+jsMB@iA}yE ziV{Sf#G#F(L7PdFwvrY-N{(ndX;YWAsy0H2TXu%sO}8M~6`2E{S5GEFvcPD_K?764 zOvvCo}1pmT=triZaI%O#Pe1un)$!r^wsqyoV$@GvIEK1bTzcCsab{J_Z}V_fZJ ze2gD1cDI8CD!9(=} literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_elffile.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_elffile.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..40947e994218950c6e83e6de2e2060b7c1440cc8 GIT binary patch literal 4970 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 OhPxRia-Sfi+x{PGfF}$9 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_manylinux.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_manylinux.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..80d567c788f5e4f9beb93f1cd9a481c4c40f8d95 GIT binary patch literal 9688 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 u%J%p0;Q{2{&y;#xZ+ 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6d8129f31741b39f7811f5b2939cefeeaa948412 GIT binary patch literal 3244 zcmc&#&2Jk;6rWwM9VfBlKpf&UY3nMjsDXR|0)a{|pzA#xUdJ2KTo`HJ&U^D_-kbOFo8Qvu zF-GI7uRn4Q;*9+TraO$zr2QF94w%k9Wj5PqwsxYcl@iG~JL#yEG^wGJMy#iylZM{Y zh_#GD-0JAdU(d!qu?KWoNwZl=w>2KC>bAablnk23X&$3_!Z!E_@yV)T$B7^9;}gV> z_3u7xFetv6_L!2I5oeMsflWhWhJ z_y3q~TRheSW4+?72L>DvNzzq!7bq_{hSedCDKV7VuMpW|e`cnB{^T(G(-&u%+o#Ff zB8C0&hQH2*)hRoYs1ZuRv0i*6aKmF=jM7hJiFnwO&nqtyrdjvNhpBWMBswm&VF`c`;p`<~>I!zm0`0iO(69v5NGM}}4||aSSt>!c$ZHkf+2;L~5o!$- zz03^)O}QbeMkn?KEtniUmmbPnR)tNmgjgZ6PNPs#US z%ru`i?5#THDbswmRjGGYVgv$Mwalm?au(8{F~(W3ADsiyVo>97rDIF39U3 zZ-U55mJvZS3fxta1Wmjji0rd-U5np1Txc`;ohP(-Ud{8EPai%yC;9Y|kLBqI(W=r~ zRa&di$|_M-iLw!*{Et-}pFh3x{&W0Q?%{;$`BPta>JPOnL(l`5pg zeR4&>u~0n`A8s3ZL3TzLyLF+`F#w}7y*oDt%Pa)($Z8MbZ>Tov!8om56XGSlhzuPt zSk$u8BArt3E~^ZPqS6Ln4gnwW;b2_S+p>&z<|2XsD97U^dJTSkLui#~L)3wb(T0$3 z2^ZIda&Z%955l%=+(?&z-7DC32js%*Lc)O{N55ba93l+?uHS);;m_Dh8A5498=@e; z7cwN_I@C!24a@=%cA;zmdOPzGWhC+V1JdvSi@@WVZ!yOI{*Lx literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_tokenizer.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_tokenizer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..24fabc75de3e494eb11017cd10faff9b73bb4cb1 GIT binary patch literal 7918 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 SuwP6tlMGY+IYCHm@&5p}_7&y; literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9ea873bdce1433a4749e90cff725fae23d6bca4b GIT binary patch literal 11014 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 F`(Ip8U&sIe literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/metadata.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/metadata.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6d560527a64f8006e2d00629139f96574a88e577 GIT binary patch literal 24956 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6cc7c2270c5b18e73d4caad9db29550cd6d282aa GIT binary patch literal 38742 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 Ida|+oZ!D$YF#rGn literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d08066f03bbc0d311b0989e360f97f71e93b24b9 GIT binary patch literal 23222 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�(hg@^wt%DQF2Rr3@X##U8W-gW%hs z!8*CYY?@h>)V2Fz*)Z;=4@V76(195~3#A31WTa28K(=85qIi*#=sP15_zu!G~1wQ7aQ}xCQ7Yx8#OHlJ7v@8DGJNO64nAPZ1(N z1x!O3r`Qz=ewPA9y_jz>BVo)<>|M(EOA3}KpfjEI((#*=_7e&i(R+zvM9J2P&5~)q z{9UeYu?e~Ok4xkrcDO9W^Z#h!_{Lvy_B)*84rji@72V;ScR0%(uK0g)9lzEXc+Ed> z2!376@mubit7glW%vEWK)O$1L%`=9(#T7~S^`e;~I8r4Bl8uR{=3bbwL8fq!uN7`! z;gf1vyX#}CVVfq!l_%>~3E7H^D{o2+-H2R|%m*@MTNnK4vK=YT{cA%f-|{hsV0Dx) z;;Zj@47_vI#q&q`RTF-%dW`&8{$5EPU%Z0j;_W-L^;@z{TUU$^@%vWDTJ*6Mv201p ziWcv?mbw)^tH=#LojsM7%@SRM4`u~Za B^AP|5 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..47cc07a44a02b62ab0eeeb429930ee5423f05355 GIT binary patch literal 7344 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 mzPn3!F%(-MsjjVGG z&VW7($bn$=@)cn4)o`I6j`hN&03g&3~07OTYr3Moc=>&VQyI_j!O3$g{ttHssScQ9_c$5FlNO=KpKKS z`OkIV0T^npS+q6I+ZuEI3%0grj-5-6lb?5d?pEy=RvEg|x&mlvT`?nPeU8ahO{O#F zmnv#Mxqkn8?sUFF$edl`E3*Cb{C1u5#N5rfuxjt!zzO7i_xp1DXH2uMzqIDH^TTS-8 z+$&SCwC2p2CA%}*o;x_xrrO$7w*C7TEy(Wv4l%G^vcE^>>gTMg{j|PI%au;zhFt%( z!oc_s`rGe|U5+z{(3giSJ=M&YuUGasn6Dfhv^V%9aus!-Gz2F}0?6O*lQ5v4h}NM; z$y?bF_#!H{XA23XY{W|vN+U%H>oXb5Mr;DFM{Vw<3=ACrUD9-#AQvNo-4oUgGB=1v# z*f*L4NKJ+k$u|siD$9dy3aJIob|H=dUxAz8s}8Nn`pv}vYL(!xe1ezZ&%@(Opu5IE zx=~M;X;w^7BSbQ{Wx(YzV?Uv_5LAHYj}*lNI1!XMbtSrPP}4`<8DVJ6C9`(z)cUpG>YWRK@mHh9TI*05&;Ln|HDG@Ou5fN z4Z~rmfRi|ZWJQ1B$tI)(c<$-12z?yultiwF)sM6Aa3Q_PBMSL{g=-uCSD;%cO6nF2 z2h}Z%;CK?ezoc9Pe>FJxvZ$utD{9cwLbCZI64dxut0`)lB$zb{iM>JcNb~(l8QJ&OzgBQiLRNC7yfhN1pWv{3697t z)L?ZK^;;{VT7QEq-ymNe`TiXV-=OYgn=@OR#ZwKro|)Ded8XsRMb*_cZ|lyOzjoED z4W8NkdDor{col{+XFFdY_`I+~l{@-U8*I6HM|S6Q=TzqsyZ7nNfAs#nm-r<*Qwg4W zTT6CmIy@DgX~@@gsi=CXrYU=B`pu~~)#i8eHJ4Q6S_bY{rjJe?%|-InK;i_hL&tuL zII4ZsNl^#kJ$U>L>OUDT33G MpK?>%_1xqC0L(&(?EnA( literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..271f1885db2fef2fddccad7e3bcfed503227154e GIT binary patch literal 19510 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 None: + self._f = f + + try: + ident = self._read("16B") + except struct.error: + raise ELFInvalid("unable to parse identification") + magic = bytes(ident[:4]) + if magic != b"\x7fELF": + raise ELFInvalid(f"invalid magic: {magic!r}") + + self.capacity = ident[4] # Format for program header (bitness). + self.encoding = ident[5] # Data structure encoding (endianness). + + try: + # e_fmt: Format for program header. + # p_fmt: Format for section header. + # p_idx: Indexes to find p_type, p_offset, and p_filesz. + e_fmt, self._p_fmt, self._p_idx = { + (1, 1): ("HHIIIIIHHH", ">IIIIIIII", (0, 1, 4)), # 32-bit MSB. + (2, 1): ("HHIQQQIHHH", ">IIQQQQQQ", (0, 2, 5)), # 64-bit MSB. + }[(self.capacity, self.encoding)] + except KeyError: + raise ELFInvalid( + f"unrecognized capacity ({self.capacity}) or " + f"encoding ({self.encoding})" + ) + + try: + ( + _, + self.machine, # Architecture type. + _, + _, + self._e_phoff, # Offset of program header. + _, + self.flags, # Processor-specific flags. + _, + self._e_phentsize, # Size of section. + self._e_phnum, # Number of sections. + ) = self._read(e_fmt) + except struct.error as e: + raise ELFInvalid("unable to parse machine and section information") from e + + def _read(self, fmt: str) -> tuple[int, ...]: + return struct.unpack(fmt, self._f.read(struct.calcsize(fmt))) + + @property + def interpreter(self) -> str | None: + """ + The path recorded in the ``PT_INTERP`` section header. + """ + for index in range(self._e_phnum): + self._f.seek(self._e_phoff + self._e_phentsize * index) + try: + data = self._read(self._p_fmt) + except struct.error: + continue + if data[self._p_idx[0]] != 3: # Not PT_INTERP. + continue + self._f.seek(data[self._p_idx[1]]) + return os.fsdecode(self._f.read(data[self._p_idx[2]])).strip("\0") + return None diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/_manylinux.py b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/_manylinux.py new file mode 100644 index 0000000..08f651f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/_manylinux.py @@ -0,0 +1,262 @@ +from __future__ import annotations + +import collections +import contextlib +import functools +import os +import re +import sys +import warnings +from typing import Generator, Iterator, NamedTuple, Sequence + +from ._elffile import EIClass, EIData, ELFFile, EMachine + +EF_ARM_ABIMASK = 0xFF000000 +EF_ARM_ABI_VER5 = 0x05000000 +EF_ARM_ABI_FLOAT_HARD = 0x00000400 + + +# `os.PathLike` not a generic type until Python 3.9, so sticking with `str` +# as the type for `path` until then. +@contextlib.contextmanager +def _parse_elf(path: str) -> Generator[ELFFile | None, None, None]: + try: + with open(path, "rb") as f: + yield ELFFile(f) + except (OSError, TypeError, ValueError): + yield None + + +def _is_linux_armhf(executable: str) -> bool: + # hard-float ABI can be detected from the ELF header of the running + # process + # https://static.docs.arm.com/ihi0044/g/aaelf32.pdf + with _parse_elf(executable) as f: + return ( + f is not None + and f.capacity == EIClass.C32 + and f.encoding == EIData.Lsb + and f.machine == EMachine.Arm + and f.flags & EF_ARM_ABIMASK == EF_ARM_ABI_VER5 + and f.flags & EF_ARM_ABI_FLOAT_HARD == EF_ARM_ABI_FLOAT_HARD + ) + + +def _is_linux_i686(executable: str) -> bool: + with _parse_elf(executable) as f: + return ( + f is not None + and f.capacity == EIClass.C32 + and f.encoding == EIData.Lsb + and f.machine == EMachine.I386 + ) + + +def _have_compatible_abi(executable: str, archs: Sequence[str]) -> bool: + if "armv7l" in archs: + return _is_linux_armhf(executable) + if "i686" in archs: + return _is_linux_i686(executable) + allowed_archs = { + "x86_64", + "aarch64", + "ppc64", + "ppc64le", + "s390x", + "loongarch64", + "riscv64", + } + return any(arch in allowed_archs for arch in archs) + + +# If glibc ever changes its major version, we need to know what the last +# minor version was, so we can build the complete list of all versions. +# For now, guess what the highest minor version might be, assume it will +# be 50 for testing. Once this actually happens, update the dictionary +# with the actual value. +_LAST_GLIBC_MINOR: dict[int, int] = collections.defaultdict(lambda: 50) + + +class _GLibCVersion(NamedTuple): + major: int + minor: int + + +def _glibc_version_string_confstr() -> str | None: + """ + Primary implementation of glibc_version_string using os.confstr. + """ + # os.confstr is quite a bit faster than ctypes.DLL. It's also less likely + # to be broken or missing. This strategy is used in the standard library + # platform module. + # https://github.com/python/cpython/blob/fcf1d003bf4f0100c/Lib/platform.py#L175-L183 + try: + # Should be a string like "glibc 2.17". + version_string: str | None = os.confstr("CS_GNU_LIBC_VERSION") + assert version_string is not None + _, version = version_string.rsplit() + except (AssertionError, AttributeError, OSError, ValueError): + # os.confstr() or CS_GNU_LIBC_VERSION not available (or a bad value)... + return None + return version + + +def _glibc_version_string_ctypes() -> str | None: + """ + Fallback implementation of glibc_version_string using ctypes. + """ + try: + import ctypes + except ImportError: + return None + + # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen + # manpage says, "If filename is NULL, then the returned handle is for the + # main program". This way we can let the linker do the work to figure out + # which libc our process is actually using. + # + # We must also handle the special case where the executable is not a + # dynamically linked executable. This can occur when using musl libc, + # for example. In this situation, dlopen() will error, leading to an + # OSError. Interestingly, at least in the case of musl, there is no + # errno set on the OSError. The single string argument used to construct + # OSError comes from libc itself and is therefore not portable to + # hard code here. In any case, failure to call dlopen() means we + # can proceed, so we bail on our attempt. + try: + process_namespace = ctypes.CDLL(None) + except OSError: + return None + + try: + gnu_get_libc_version = process_namespace.gnu_get_libc_version + except AttributeError: + # Symbol doesn't exist -> therefore, we are not linked to + # glibc. + return None + + # Call gnu_get_libc_version, which returns a string like "2.5" + gnu_get_libc_version.restype = ctypes.c_char_p + version_str: str = gnu_get_libc_version() + # py2 / py3 compatibility: + if not isinstance(version_str, str): + version_str = version_str.decode("ascii") + + return version_str + + +def _glibc_version_string() -> str | None: + """Returns glibc version string, or None if not using glibc.""" + return _glibc_version_string_confstr() or _glibc_version_string_ctypes() + + +def _parse_glibc_version(version_str: str) -> tuple[int, int]: + """Parse glibc version. + + We use a regexp instead of str.split because we want to discard any + random junk that might come after the minor version -- this might happen + in patched/forked versions of glibc (e.g. Linaro's version of glibc + uses version strings like "2.20-2014.11"). See gh-3588. + """ + m = re.match(r"(?P[0-9]+)\.(?P[0-9]+)", version_str) + if not m: + warnings.warn( + f"Expected glibc version with 2 components major.minor," + f" got: {version_str}", + RuntimeWarning, + ) + return -1, -1 + return int(m.group("major")), int(m.group("minor")) + + +@functools.lru_cache +def _get_glibc_version() -> tuple[int, int]: + version_str = _glibc_version_string() + if version_str is None: + return (-1, -1) + return _parse_glibc_version(version_str) + + +# From PEP 513, PEP 600 +def _is_compatible(arch: str, version: _GLibCVersion) -> bool: + sys_glibc = _get_glibc_version() + if sys_glibc < version: + return False + # Check for presence of _manylinux module. + try: + import _manylinux + except ImportError: + return True + if hasattr(_manylinux, "manylinux_compatible"): + result = _manylinux.manylinux_compatible(version[0], version[1], arch) + if result is not None: + return bool(result) + return True + if version == _GLibCVersion(2, 5): + if hasattr(_manylinux, "manylinux1_compatible"): + return bool(_manylinux.manylinux1_compatible) + if version == _GLibCVersion(2, 12): + if hasattr(_manylinux, "manylinux2010_compatible"): + return bool(_manylinux.manylinux2010_compatible) + if version == _GLibCVersion(2, 17): + if hasattr(_manylinux, "manylinux2014_compatible"): + return bool(_manylinux.manylinux2014_compatible) + return True + + +_LEGACY_MANYLINUX_MAP = { + # CentOS 7 w/ glibc 2.17 (PEP 599) + (2, 17): "manylinux2014", + # CentOS 6 w/ glibc 2.12 (PEP 571) + (2, 12): "manylinux2010", + # CentOS 5 w/ glibc 2.5 (PEP 513) + (2, 5): "manylinux1", +} + + +def platform_tags(archs: Sequence[str]) -> Iterator[str]: + """Generate manylinux tags compatible to the current platform. + + :param archs: Sequence of compatible architectures. + The first one shall be the closest to the actual architecture and be the part of + platform tag after the ``linux_`` prefix, e.g. ``x86_64``. + The ``linux_`` prefix is assumed as a prerequisite for the current platform to + be manylinux-compatible. + + :returns: An iterator of compatible manylinux tags. + """ + if not _have_compatible_abi(sys.executable, archs): + return + # Oldest glibc to be supported regardless of architecture is (2, 17). + too_old_glibc2 = _GLibCVersion(2, 16) + if set(archs) & {"x86_64", "i686"}: + # On x86/i686 also oldest glibc to be supported is (2, 5). + too_old_glibc2 = _GLibCVersion(2, 4) + current_glibc = _GLibCVersion(*_get_glibc_version()) + glibc_max_list = [current_glibc] + # We can assume compatibility across glibc major versions. + # https://sourceware.org/bugzilla/show_bug.cgi?id=24636 + # + # Build a list of maximum glibc versions so that we can + # output the canonical list of all glibc from current_glibc + # down to too_old_glibc2, including all intermediary versions. + for glibc_major in range(current_glibc.major - 1, 1, -1): + glibc_minor = _LAST_GLIBC_MINOR[glibc_major] + glibc_max_list.append(_GLibCVersion(glibc_major, glibc_minor)) + for arch in archs: + for glibc_max in glibc_max_list: + if glibc_max.major == too_old_glibc2.major: + min_minor = too_old_glibc2.minor + else: + # For other glibc major versions oldest supported is (x, 0). + min_minor = -1 + for glibc_minor in range(glibc_max.minor, min_minor, -1): + glibc_version = _GLibCVersion(glibc_max.major, glibc_minor) + tag = "manylinux_{}_{}".format(*glibc_version) + if _is_compatible(arch, glibc_version): + yield f"{tag}_{arch}" + # Handle the legacy manylinux1, manylinux2010, manylinux2014 tags. + if glibc_version in _LEGACY_MANYLINUX_MAP: + legacy_tag = _LEGACY_MANYLINUX_MAP[glibc_version] + if _is_compatible(arch, glibc_version): + yield f"{legacy_tag}_{arch}" diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/_musllinux.py b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/_musllinux.py new file mode 100644 index 0000000..d2bf30b --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/_musllinux.py @@ -0,0 +1,85 @@ +"""PEP 656 support. + +This module implements logic to detect if the currently running Python is +linked against musl, and what musl version is used. +""" + +from __future__ import annotations + +import functools +import re +import subprocess +import sys +from typing import Iterator, NamedTuple, Sequence + +from ._elffile import ELFFile + + +class _MuslVersion(NamedTuple): + major: int + minor: int + + +def _parse_musl_version(output: str) -> _MuslVersion | None: + lines = [n for n in (n.strip() for n in output.splitlines()) if n] + if len(lines) < 2 or lines[0][:4] != "musl": + return None + m = re.match(r"Version (\d+)\.(\d+)", lines[1]) + if not m: + return None + return _MuslVersion(major=int(m.group(1)), minor=int(m.group(2))) + + +@functools.lru_cache +def _get_musl_version(executable: str) -> _MuslVersion | None: + """Detect currently-running musl runtime version. + + This is done by checking the specified executable's dynamic linking + information, and invoking the loader to parse its output for a version + string. If the loader is musl, the output would be something like:: + + musl libc (x86_64) + Version 1.2.2 + Dynamic Program Loader + """ + try: + with open(executable, "rb") as f: + ld = ELFFile(f).interpreter + except (OSError, TypeError, ValueError): + return None + if ld is None or "musl" not in ld: + return None + proc = subprocess.run([ld], stderr=subprocess.PIPE, text=True) + return _parse_musl_version(proc.stderr) + + +def platform_tags(archs: Sequence[str]) -> Iterator[str]: + """Generate musllinux tags compatible to the current platform. + + :param archs: Sequence of compatible architectures. + The first one shall be the closest to the actual architecture and be the part of + platform tag after the ``linux_`` prefix, e.g. ``x86_64``. + The ``linux_`` prefix is assumed as a prerequisite for the current platform to + be musllinux-compatible. + + :returns: An iterator of compatible musllinux tags. + """ + sys_musl = _get_musl_version(sys.executable) + if sys_musl is None: # Python not dynamically linked against musl. + return + for arch in archs: + for minor in range(sys_musl.minor, -1, -1): + yield f"musllinux_{sys_musl.major}_{minor}_{arch}" + + +if __name__ == "__main__": # pragma: no cover + import sysconfig + + plat = sysconfig.get_platform() + assert plat.startswith("linux-"), "not linux" + + print("plat:", plat) + print("musl:", _get_musl_version(sys.executable)) + print("tags:", end=" ") + for t in platform_tags(re.sub(r"[.-]", "_", plat.split("-", 1)[-1])): + print(t, end="\n ") diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/_parser.py b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/_parser.py new file mode 100644 index 0000000..c1238c0 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/_parser.py @@ -0,0 +1,354 @@ +"""Handwritten parser of dependency specifiers. + +The docstring for each __parse_* function contains EBNF-inspired grammar representing +the implementation. +""" + +from __future__ import annotations + +import ast +from typing import NamedTuple, Sequence, Tuple, Union + +from ._tokenizer import DEFAULT_RULES, Tokenizer + + +class Node: + def __init__(self, value: str) -> None: + self.value = value + + def __str__(self) -> str: + return self.value + + def __repr__(self) -> str: + return f"<{self.__class__.__name__}('{self}')>" + + def serialize(self) -> str: + raise NotImplementedError + + +class Variable(Node): + def serialize(self) -> str: + return str(self) + + +class Value(Node): + def serialize(self) -> str: + return f'"{self}"' + + +class Op(Node): + def serialize(self) -> str: + return str(self) + + +MarkerVar = Union[Variable, Value] +MarkerItem = Tuple[MarkerVar, Op, MarkerVar] +MarkerAtom = Union[MarkerItem, Sequence["MarkerAtom"]] +MarkerList = Sequence[Union["MarkerList", MarkerAtom, str]] + + +class ParsedRequirement(NamedTuple): + name: str + url: str + extras: list[str] + specifier: str + marker: MarkerList | None + + +# -------------------------------------------------------------------------------------- +# Recursive descent parser for dependency specifier +# -------------------------------------------------------------------------------------- +def parse_requirement(source: str) -> ParsedRequirement: + return _parse_requirement(Tokenizer(source, rules=DEFAULT_RULES)) + + +def _parse_requirement(tokenizer: Tokenizer) -> ParsedRequirement: + """ + requirement = WS? IDENTIFIER WS? extras WS? requirement_details + """ + tokenizer.consume("WS") + + name_token = tokenizer.expect( + "IDENTIFIER", expected="package name at the start of dependency specifier" + ) + name = name_token.text + tokenizer.consume("WS") + + extras = _parse_extras(tokenizer) + tokenizer.consume("WS") + + url, specifier, marker = _parse_requirement_details(tokenizer) + tokenizer.expect("END", expected="end of dependency specifier") + + return ParsedRequirement(name, url, extras, specifier, marker) + + +def _parse_requirement_details( + tokenizer: Tokenizer, +) -> tuple[str, str, MarkerList | None]: + """ + requirement_details = AT URL (WS requirement_marker?)? + | specifier WS? (requirement_marker)? + """ + + specifier = "" + url = "" + marker = None + + if tokenizer.check("AT"): + tokenizer.read() + tokenizer.consume("WS") + + url_start = tokenizer.position + url = tokenizer.expect("URL", expected="URL after @").text + if tokenizer.check("END", peek=True): + return (url, specifier, marker) + + tokenizer.expect("WS", expected="whitespace after URL") + + # The input might end after whitespace. + if tokenizer.check("END", peek=True): + return (url, specifier, marker) + + marker = _parse_requirement_marker( + tokenizer, span_start=url_start, after="URL and whitespace" + ) + else: + specifier_start = tokenizer.position + specifier = _parse_specifier(tokenizer) + tokenizer.consume("WS") + + if tokenizer.check("END", peek=True): + return (url, specifier, marker) + + marker = _parse_requirement_marker( + tokenizer, + span_start=specifier_start, + after=( + "version specifier" + if specifier + else "name and no valid version specifier" + ), + ) + + return (url, specifier, marker) + + +def _parse_requirement_marker( + tokenizer: Tokenizer, *, span_start: int, after: str +) -> MarkerList: + """ + requirement_marker = SEMICOLON marker WS? + """ + + if not tokenizer.check("SEMICOLON"): + tokenizer.raise_syntax_error( + f"Expected end or semicolon (after {after})", + span_start=span_start, + ) + tokenizer.read() + + marker = _parse_marker(tokenizer) + tokenizer.consume("WS") + + return marker + + +def _parse_extras(tokenizer: Tokenizer) -> list[str]: + """ + extras = (LEFT_BRACKET wsp* extras_list? wsp* RIGHT_BRACKET)? + """ + if not tokenizer.check("LEFT_BRACKET", peek=True): + return [] + + with tokenizer.enclosing_tokens( + "LEFT_BRACKET", + "RIGHT_BRACKET", + around="extras", + ): + tokenizer.consume("WS") + extras = _parse_extras_list(tokenizer) + tokenizer.consume("WS") + + return extras + + +def _parse_extras_list(tokenizer: Tokenizer) -> list[str]: + """ + extras_list = identifier (wsp* ',' wsp* identifier)* + """ + extras: list[str] = [] + + if not tokenizer.check("IDENTIFIER"): + return extras + + extras.append(tokenizer.read().text) + + while True: + tokenizer.consume("WS") + if tokenizer.check("IDENTIFIER", peek=True): + tokenizer.raise_syntax_error("Expected comma between extra names") + elif not tokenizer.check("COMMA"): + break + + tokenizer.read() + tokenizer.consume("WS") + + extra_token = tokenizer.expect("IDENTIFIER", expected="extra name after comma") + extras.append(extra_token.text) + + return extras + + +def _parse_specifier(tokenizer: Tokenizer) -> str: + """ + specifier = LEFT_PARENTHESIS WS? version_many WS? RIGHT_PARENTHESIS + | WS? version_many WS? + """ + with tokenizer.enclosing_tokens( + "LEFT_PARENTHESIS", + "RIGHT_PARENTHESIS", + around="version specifier", + ): + tokenizer.consume("WS") + parsed_specifiers = _parse_version_many(tokenizer) + tokenizer.consume("WS") + + return parsed_specifiers + + +def _parse_version_many(tokenizer: Tokenizer) -> str: + """ + version_many = (SPECIFIER (WS? COMMA WS? SPECIFIER)*)? + """ + parsed_specifiers = "" + while tokenizer.check("SPECIFIER"): + span_start = tokenizer.position + parsed_specifiers += tokenizer.read().text + if tokenizer.check("VERSION_PREFIX_TRAIL", peek=True): + tokenizer.raise_syntax_error( + ".* suffix can only be used with `==` or `!=` operators", + span_start=span_start, + span_end=tokenizer.position + 1, + ) + if tokenizer.check("VERSION_LOCAL_LABEL_TRAIL", peek=True): + tokenizer.raise_syntax_error( + "Local version label can only be used with `==` or `!=` operators", + span_start=span_start, + span_end=tokenizer.position, + ) + tokenizer.consume("WS") + if not tokenizer.check("COMMA"): + break + parsed_specifiers += tokenizer.read().text + tokenizer.consume("WS") + + return parsed_specifiers + + +# -------------------------------------------------------------------------------------- +# Recursive descent parser for marker expression +# -------------------------------------------------------------------------------------- +def parse_marker(source: str) -> MarkerList: + return _parse_full_marker(Tokenizer(source, rules=DEFAULT_RULES)) + + +def _parse_full_marker(tokenizer: Tokenizer) -> MarkerList: + retval = _parse_marker(tokenizer) + tokenizer.expect("END", expected="end of marker expression") + return retval + + +def _parse_marker(tokenizer: Tokenizer) -> MarkerList: + """ + marker = marker_atom (BOOLOP marker_atom)+ + """ + expression = [_parse_marker_atom(tokenizer)] + while tokenizer.check("BOOLOP"): + token = tokenizer.read() + expr_right = _parse_marker_atom(tokenizer) + expression.extend((token.text, expr_right)) + return expression + + +def _parse_marker_atom(tokenizer: Tokenizer) -> MarkerAtom: + """ + marker_atom = WS? LEFT_PARENTHESIS WS? marker WS? RIGHT_PARENTHESIS WS? + | WS? marker_item WS? + """ + + tokenizer.consume("WS") + if tokenizer.check("LEFT_PARENTHESIS", peek=True): + with tokenizer.enclosing_tokens( + "LEFT_PARENTHESIS", + "RIGHT_PARENTHESIS", + around="marker expression", + ): + tokenizer.consume("WS") + marker: MarkerAtom = _parse_marker(tokenizer) + tokenizer.consume("WS") + else: + marker = _parse_marker_item(tokenizer) + tokenizer.consume("WS") + return marker + + +def _parse_marker_item(tokenizer: Tokenizer) -> MarkerItem: + """ + marker_item = WS? marker_var WS? marker_op WS? marker_var WS? + """ + tokenizer.consume("WS") + marker_var_left = _parse_marker_var(tokenizer) + tokenizer.consume("WS") + marker_op = _parse_marker_op(tokenizer) + tokenizer.consume("WS") + marker_var_right = _parse_marker_var(tokenizer) + tokenizer.consume("WS") + return (marker_var_left, marker_op, marker_var_right) + + +def _parse_marker_var(tokenizer: Tokenizer) -> MarkerVar: + """ + marker_var = VARIABLE | QUOTED_STRING + """ + if tokenizer.check("VARIABLE"): + return process_env_var(tokenizer.read().text.replace(".", "_")) + elif tokenizer.check("QUOTED_STRING"): + return process_python_str(tokenizer.read().text) + else: + tokenizer.raise_syntax_error( + message="Expected a marker variable or quoted string" + ) + + +def process_env_var(env_var: str) -> Variable: + if env_var in ("platform_python_implementation", "python_implementation"): + return Variable("platform_python_implementation") + else: + return Variable(env_var) + + +def process_python_str(python_str: str) -> Value: + value = ast.literal_eval(python_str) + return Value(str(value)) + + +def _parse_marker_op(tokenizer: Tokenizer) -> Op: + """ + marker_op = IN | NOT IN | OP + """ + if tokenizer.check("IN"): + tokenizer.read() + return Op("in") + elif tokenizer.check("NOT"): + tokenizer.read() + tokenizer.expect("WS", expected="whitespace after 'not'") + tokenizer.expect("IN", expected="'in' after 'not'") + return Op("not in") + elif tokenizer.check("OP"): + return Op(tokenizer.read().text) + else: + return tokenizer.raise_syntax_error( + "Expected marker operator, one of " + "<=, <, !=, ==, >=, >, ~=, ===, in, not in" + ) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/_structures.py b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/_structures.py new file mode 100644 index 0000000..90a6465 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/_structures.py @@ -0,0 +1,61 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +class InfinityType: + def __repr__(self) -> str: + return "Infinity" + + def __hash__(self) -> int: + return hash(repr(self)) + + def __lt__(self, other: object) -> bool: + return False + + def __le__(self, other: object) -> bool: + return False + + def __eq__(self, other: object) -> bool: + return isinstance(other, self.__class__) + + def __gt__(self, other: object) -> bool: + return True + + def __ge__(self, other: object) -> bool: + return True + + def __neg__(self: object) -> "NegativeInfinityType": + return NegativeInfinity + + +Infinity = InfinityType() + + +class NegativeInfinityType: + def __repr__(self) -> str: + return "-Infinity" + + def __hash__(self) -> int: + return hash(repr(self)) + + def __lt__(self, other: object) -> bool: + return True + + def __le__(self, other: object) -> bool: + return True + + def __eq__(self, other: object) -> bool: + return isinstance(other, self.__class__) + + def __gt__(self, other: object) -> bool: + return False + + def __ge__(self, other: object) -> bool: + return False + + def __neg__(self: object) -> InfinityType: + return Infinity + + +NegativeInfinity = NegativeInfinityType() diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/_tokenizer.py b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/_tokenizer.py new file mode 100644 index 0000000..89d0416 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/_tokenizer.py @@ -0,0 +1,194 @@ +from __future__ import annotations + +import contextlib +import re +from dataclasses import dataclass +from typing import Iterator, NoReturn + +from .specifiers import Specifier + + +@dataclass +class Token: + name: str + text: str + position: int + + +class ParserSyntaxError(Exception): + """The provided source text could not be parsed correctly.""" + + def __init__( + self, + message: str, + *, + source: str, + span: tuple[int, int], + ) -> None: + self.span = span + self.message = message + self.source = source + + super().__init__() + + def __str__(self) -> str: + marker = " " * self.span[0] + "~" * (self.span[1] - self.span[0]) + "^" + return "\n ".join([self.message, self.source, marker]) + + +DEFAULT_RULES: dict[str, str | re.Pattern[str]] = { + "LEFT_PARENTHESIS": r"\(", + "RIGHT_PARENTHESIS": r"\)", + "LEFT_BRACKET": r"\[", + "RIGHT_BRACKET": r"\]", + "SEMICOLON": r";", + "COMMA": r",", + "QUOTED_STRING": re.compile( + r""" + ( + ('[^']*') + | + ("[^"]*") + ) + """, + re.VERBOSE, + ), + "OP": r"(===|==|~=|!=|<=|>=|<|>)", + "BOOLOP": r"\b(or|and)\b", + "IN": r"\bin\b", + "NOT": r"\bnot\b", + "VARIABLE": re.compile( + r""" + \b( + python_version + |python_full_version + |os[._]name + |sys[._]platform + |platform_(release|system) + |platform[._](version|machine|python_implementation) + |python_implementation + |implementation_(name|version) + |extra + )\b + """, + re.VERBOSE, + ), + "SPECIFIER": re.compile( + Specifier._operator_regex_str + Specifier._version_regex_str, + re.VERBOSE | re.IGNORECASE, + ), + "AT": r"\@", + "URL": r"[^ \t]+", + "IDENTIFIER": r"\b[a-zA-Z0-9][a-zA-Z0-9._-]*\b", + "VERSION_PREFIX_TRAIL": r"\.\*", + "VERSION_LOCAL_LABEL_TRAIL": r"\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*", + "WS": r"[ \t]+", + "END": r"$", +} + + +class Tokenizer: + """Context-sensitive token parsing. + + Provides methods to examine the input stream to check whether the next token + matches. + """ + + def __init__( + self, + source: str, + *, + rules: dict[str, str | re.Pattern[str]], + ) -> None: + self.source = source + self.rules: dict[str, re.Pattern[str]] = { + name: re.compile(pattern) for name, pattern in rules.items() + } + self.next_token: Token | None = None + self.position = 0 + + def consume(self, name: str) -> None: + """Move beyond provided token name, if at current position.""" + if self.check(name): + self.read() + + def check(self, name: str, *, peek: bool = False) -> bool: + """Check whether the next token has the provided name. + + By default, if the check succeeds, the token *must* be read before + another check. If `peek` is set to `True`, the token is not loaded and + would need to be checked again. + """ + assert ( + self.next_token is None + ), f"Cannot check for {name!r}, already have {self.next_token!r}" + assert name in self.rules, f"Unknown token name: {name!r}" + + expression = self.rules[name] + + match = expression.match(self.source, self.position) + if match is None: + return False + if not peek: + self.next_token = Token(name, match[0], self.position) + return True + + def expect(self, name: str, *, expected: str) -> Token: + """Expect a certain token name next, failing with a syntax error otherwise. + + The token is *not* read. + """ + if not self.check(name): + raise self.raise_syntax_error(f"Expected {expected}") + return self.read() + + def read(self) -> Token: + """Consume the next token and return it.""" + token = self.next_token + assert token is not None + + self.position += len(token.text) + self.next_token = None + + return token + + def raise_syntax_error( + self, + message: str, + *, + span_start: int | None = None, + span_end: int | None = None, + ) -> NoReturn: + """Raise ParserSyntaxError at the given position.""" + span = ( + self.position if span_start is None else span_start, + self.position if span_end is None else span_end, + ) + raise ParserSyntaxError( + message, + source=self.source, + span=span, + ) + + @contextlib.contextmanager + def enclosing_tokens( + self, open_token: str, close_token: str, *, around: str + ) -> Iterator[None]: + if self.check(open_token): + open_position = self.position + self.read() + else: + open_position = None + + yield + + if open_position is None: + return + + if not self.check(close_token): + self.raise_syntax_error( + f"Expected matching {close_token} for {open_token}, after {around}", + span_start=open_position, + ) + + self.read() diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/markers.py b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/markers.py new file mode 100644 index 0000000..7ac7bb6 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/markers.py @@ -0,0 +1,325 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import operator +import os +import platform +import sys +from typing import Any, Callable, TypedDict, cast + +from ._parser import MarkerAtom, MarkerList, Op, Value, Variable +from ._parser import parse_marker as _parse_marker +from ._tokenizer import ParserSyntaxError +from .specifiers import InvalidSpecifier, Specifier +from .utils import canonicalize_name + +__all__ = [ + "InvalidMarker", + "UndefinedComparison", + "UndefinedEnvironmentName", + "Marker", + "default_environment", +] + +Operator = Callable[[str, str], bool] + + +class InvalidMarker(ValueError): + """ + An invalid marker was found, users should refer to PEP 508. + """ + + +class UndefinedComparison(ValueError): + """ + An invalid operation was attempted on a value that doesn't support it. + """ + + +class UndefinedEnvironmentName(ValueError): + """ + A name was attempted to be used that does not exist inside of the + environment. + """ + + +class Environment(TypedDict): + implementation_name: str + """The implementation's identifier, e.g. ``'cpython'``.""" + + implementation_version: str + """ + The implementation's version, e.g. ``'3.13.0a2'`` for CPython 3.13.0a2, or + ``'7.3.13'`` for PyPy3.10 v7.3.13. + """ + + os_name: str + """ + The value of :py:data:`os.name`. The name of the operating system dependent module + imported, e.g. ``'posix'``. + """ + + platform_machine: str + """ + Returns the machine type, e.g. ``'i386'``. + + An empty string if the value cannot be determined. + """ + + platform_release: str + """ + The system's release, e.g. ``'2.2.0'`` or ``'NT'``. + + An empty string if the value cannot be determined. + """ + + platform_system: str + """ + The system/OS name, e.g. ``'Linux'``, ``'Windows'`` or ``'Java'``. + + An empty string if the value cannot be determined. + """ + + platform_version: str + """ + The system's release version, e.g. ``'#3 on degas'``. + + An empty string if the value cannot be determined. + """ + + python_full_version: str + """ + The Python version as string ``'major.minor.patchlevel'``. + + Note that unlike the Python :py:data:`sys.version`, this value will always include + the patchlevel (it defaults to 0). + """ + + platform_python_implementation: str + """ + A string identifying the Python implementation, e.g. ``'CPython'``. + """ + + python_version: str + """The Python version as string ``'major.minor'``.""" + + sys_platform: str + """ + This string contains a platform identifier that can be used to append + platform-specific components to :py:data:`sys.path`, for instance. + + For Unix systems, except on Linux and AIX, this is the lowercased OS name as + returned by ``uname -s`` with the first part of the version as returned by + ``uname -r`` appended, e.g. ``'sunos5'`` or ``'freebsd8'``, at the time when Python + was built. + """ + + +def _normalize_extra_values(results: Any) -> Any: + """ + Normalize extra values. + """ + if isinstance(results[0], tuple): + lhs, op, rhs = results[0] + if isinstance(lhs, Variable) and lhs.value == "extra": + normalized_extra = canonicalize_name(rhs.value) + rhs = Value(normalized_extra) + elif isinstance(rhs, Variable) and rhs.value == "extra": + normalized_extra = canonicalize_name(lhs.value) + lhs = Value(normalized_extra) + results[0] = lhs, op, rhs + return results + + +def _format_marker( + marker: list[str] | MarkerAtom | str, first: bool | None = True +) -> str: + assert isinstance(marker, (list, tuple, str)) + + # Sometimes we have a structure like [[...]] which is a single item list + # where the single item is itself it's own list. In that case we want skip + # the rest of this function so that we don't get extraneous () on the + # outside. + if ( + isinstance(marker, list) + and len(marker) == 1 + and isinstance(marker[0], (list, tuple)) + ): + return _format_marker(marker[0]) + + if isinstance(marker, list): + inner = (_format_marker(m, first=False) for m in marker) + if first: + return " ".join(inner) + else: + return "(" + " ".join(inner) + ")" + elif isinstance(marker, tuple): + return " ".join([m.serialize() for m in marker]) + else: + return marker + + +_operators: dict[str, Operator] = { + "in": lambda lhs, rhs: lhs in rhs, + "not in": lambda lhs, rhs: lhs not in rhs, + "<": operator.lt, + "<=": operator.le, + "==": operator.eq, + "!=": operator.ne, + ">=": operator.ge, + ">": operator.gt, +} + + +def _eval_op(lhs: str, op: Op, rhs: str) -> bool: + try: + spec = Specifier("".join([op.serialize(), rhs])) + except InvalidSpecifier: + pass + else: + return spec.contains(lhs, prereleases=True) + + oper: Operator | None = _operators.get(op.serialize()) + if oper is None: + raise UndefinedComparison(f"Undefined {op!r} on {lhs!r} and {rhs!r}.") + + return oper(lhs, rhs) + + +def _normalize(*values: str, key: str) -> tuple[str, ...]: + # PEP 685 – Comparison of extra names for optional distribution dependencies + # https://peps.python.org/pep-0685/ + # > When comparing extra names, tools MUST normalize the names being + # > compared using the semantics outlined in PEP 503 for names + if key == "extra": + return tuple(canonicalize_name(v) for v in values) + + # other environment markers don't have such standards + return values + + +def _evaluate_markers(markers: MarkerList, environment: dict[str, str]) -> bool: + groups: list[list[bool]] = [[]] + + for marker in markers: + assert isinstance(marker, (list, tuple, str)) + + if isinstance(marker, list): + groups[-1].append(_evaluate_markers(marker, environment)) + elif isinstance(marker, tuple): + lhs, op, rhs = marker + + if isinstance(lhs, Variable): + environment_key = lhs.value + lhs_value = environment[environment_key] + rhs_value = rhs.value + else: + lhs_value = lhs.value + environment_key = rhs.value + rhs_value = environment[environment_key] + + lhs_value, rhs_value = _normalize(lhs_value, rhs_value, key=environment_key) + groups[-1].append(_eval_op(lhs_value, op, rhs_value)) + else: + assert marker in ["and", "or"] + if marker == "or": + groups.append([]) + + return any(all(item) for item in groups) + + +def format_full_version(info: sys._version_info) -> str: + version = "{0.major}.{0.minor}.{0.micro}".format(info) + kind = info.releaselevel + if kind != "final": + version += kind[0] + str(info.serial) + return version + + +def default_environment() -> Environment: + iver = format_full_version(sys.implementation.version) + implementation_name = sys.implementation.name + return { + "implementation_name": implementation_name, + "implementation_version": iver, + "os_name": os.name, + "platform_machine": platform.machine(), + "platform_release": platform.release(), + "platform_system": platform.system(), + "platform_version": platform.version(), + "python_full_version": platform.python_version(), + "platform_python_implementation": platform.python_implementation(), + "python_version": ".".join(platform.python_version_tuple()[:2]), + "sys_platform": sys.platform, + } + + +class Marker: + def __init__(self, marker: str) -> None: + # Note: We create a Marker object without calling this constructor in + # packaging.requirements.Requirement. If any additional logic is + # added here, make sure to mirror/adapt Requirement. + try: + self._markers = _normalize_extra_values(_parse_marker(marker)) + # The attribute `_markers` can be described in terms of a recursive type: + # MarkerList = List[Union[Tuple[Node, ...], str, MarkerList]] + # + # For example, the following expression: + # python_version > "3.6" or (python_version == "3.6" and os_name == "unix") + # + # is parsed into: + # [ + # (, ')>, ), + # 'and', + # [ + # (, , ), + # 'or', + # (, , ) + # ] + # ] + except ParserSyntaxError as e: + raise InvalidMarker(str(e)) from e + + def __str__(self) -> str: + return _format_marker(self._markers) + + def __repr__(self) -> str: + return f"" + + def __hash__(self) -> int: + return hash((self.__class__.__name__, str(self))) + + def __eq__(self, other: Any) -> bool: + if not isinstance(other, Marker): + return NotImplemented + + return str(self) == str(other) + + def evaluate(self, environment: dict[str, str] | None = None) -> bool: + """Evaluate a marker. + + Return the boolean from evaluating the given marker against the + environment. environment is an optional argument to override all or + part of the determined environment. + + The environment is determined from the current Python process. + """ + current_environment = cast("dict[str, str]", default_environment()) + current_environment["extra"] = "" + # Work around platform.python_version() returning something that is not PEP 440 + # compliant for non-tagged Python builds. We preserve default_environment()'s + # behavior of returning platform.python_version() verbatim, and leave it to the + # caller to provide a syntactically valid version if they want to override it. + if current_environment["python_full_version"].endswith("+"): + current_environment["python_full_version"] += "local" + if environment is not None: + current_environment.update(environment) + # The API used to allow setting extra to None. We need to handle this + # case for backwards compatibility. + if current_environment["extra"] is None: + current_environment["extra"] = "" + + return _evaluate_markers(self._markers, current_environment) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/metadata.py b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/metadata.py new file mode 100644 index 0000000..eb8dc84 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/metadata.py @@ -0,0 +1,804 @@ +from __future__ import annotations + +import email.feedparser +import email.header +import email.message +import email.parser +import email.policy +import typing +from typing import ( + Any, + Callable, + Generic, + Literal, + TypedDict, + cast, +) + +from . import requirements, specifiers, utils +from . import version as version_module + +T = typing.TypeVar("T") + + +try: + ExceptionGroup +except NameError: # pragma: no cover + + class ExceptionGroup(Exception): + """A minimal implementation of :external:exc:`ExceptionGroup` from Python 3.11. + + If :external:exc:`ExceptionGroup` is already defined by Python itself, + that version is used instead. + """ + + message: str + exceptions: list[Exception] + + def __init__(self, message: str, exceptions: list[Exception]) -> None: + self.message = message + self.exceptions = exceptions + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self.message!r}, {self.exceptions!r})" + +else: # pragma: no cover + ExceptionGroup = ExceptionGroup + + +class InvalidMetadata(ValueError): + """A metadata field contains invalid data.""" + + field: str + """The name of the field that contains invalid data.""" + + def __init__(self, field: str, message: str) -> None: + self.field = field + super().__init__(message) + + +# The RawMetadata class attempts to make as few assumptions about the underlying +# serialization formats as possible. The idea is that as long as a serialization +# formats offer some very basic primitives in *some* way then we can support +# serializing to and from that format. +class RawMetadata(TypedDict, total=False): + """A dictionary of raw core metadata. + + Each field in core metadata maps to a key of this dictionary (when data is + provided). The key is lower-case and underscores are used instead of dashes + compared to the equivalent core metadata field. Any core metadata field that + can be specified multiple times or can hold multiple values in a single + field have a key with a plural name. See :class:`Metadata` whose attributes + match the keys of this dictionary. + + Core metadata fields that can be specified multiple times are stored as a + list or dict depending on which is appropriate for the field. Any fields + which hold multiple values in a single field are stored as a list. + + """ + + # Metadata 1.0 - PEP 241 + metadata_version: str + name: str + version: str + platforms: list[str] + summary: str + description: str + keywords: list[str] + home_page: str + author: str + author_email: str + license: str + + # Metadata 1.1 - PEP 314 + supported_platforms: list[str] + download_url: str + classifiers: list[str] + requires: list[str] + provides: list[str] + obsoletes: list[str] + + # Metadata 1.2 - PEP 345 + maintainer: str + maintainer_email: str + requires_dist: list[str] + provides_dist: list[str] + obsoletes_dist: list[str] + requires_python: str + requires_external: list[str] + project_urls: dict[str, str] + + # Metadata 2.0 + # PEP 426 attempted to completely revamp the metadata format + # but got stuck without ever being able to build consensus on + # it and ultimately ended up withdrawn. + # + # However, a number of tools had started emitting METADATA with + # `2.0` Metadata-Version, so for historical reasons, this version + # was skipped. + + # Metadata 2.1 - PEP 566 + description_content_type: str + provides_extra: list[str] + + # Metadata 2.2 - PEP 643 + dynamic: list[str] + + # Metadata 2.3 - PEP 685 + # No new fields were added in PEP 685, just some edge case were + # tightened up to provide better interoptability. + + +_STRING_FIELDS = { + "author", + "author_email", + "description", + "description_content_type", + "download_url", + "home_page", + "license", + "maintainer", + "maintainer_email", + "metadata_version", + "name", + "requires_python", + "summary", + "version", +} + +_LIST_FIELDS = { + "classifiers", + "dynamic", + "obsoletes", + "obsoletes_dist", + "platforms", + "provides", + "provides_dist", + "provides_extra", + "requires", + "requires_dist", + "requires_external", + "supported_platforms", +} + +_DICT_FIELDS = { + "project_urls", +} + + +def _parse_keywords(data: str) -> list[str]: + """Split a string of comma-separate keyboards into a list of keywords.""" + return [k.strip() for k in data.split(",")] + + +def _parse_project_urls(data: list[str]) -> dict[str, str]: + """Parse a list of label/URL string pairings separated by a comma.""" + urls = {} + for pair in data: + # Our logic is slightly tricky here as we want to try and do + # *something* reasonable with malformed data. + # + # The main thing that we have to worry about, is data that does + # not have a ',' at all to split the label from the Value. There + # isn't a singular right answer here, and we will fail validation + # later on (if the caller is validating) so it doesn't *really* + # matter, but since the missing value has to be an empty str + # and our return value is dict[str, str], if we let the key + # be the missing value, then they'd have multiple '' values that + # overwrite each other in a accumulating dict. + # + # The other potentional issue is that it's possible to have the + # same label multiple times in the metadata, with no solid "right" + # answer with what to do in that case. As such, we'll do the only + # thing we can, which is treat the field as unparseable and add it + # to our list of unparsed fields. + parts = [p.strip() for p in pair.split(",", 1)] + parts.extend([""] * (max(0, 2 - len(parts)))) # Ensure 2 items + + # TODO: The spec doesn't say anything about if the keys should be + # considered case sensitive or not... logically they should + # be case-preserving and case-insensitive, but doing that + # would open up more cases where we might have duplicate + # entries. + label, url = parts + if label in urls: + # The label already exists in our set of urls, so this field + # is unparseable, and we can just add the whole thing to our + # unparseable data and stop processing it. + raise KeyError("duplicate labels in project urls") + urls[label] = url + + return urls + + +def _get_payload(msg: email.message.Message, source: bytes | str) -> str: + """Get the body of the message.""" + # If our source is a str, then our caller has managed encodings for us, + # and we don't need to deal with it. + if isinstance(source, str): + payload: str = msg.get_payload() + return payload + # If our source is a bytes, then we're managing the encoding and we need + # to deal with it. + else: + bpayload: bytes = msg.get_payload(decode=True) + try: + return bpayload.decode("utf8", "strict") + except UnicodeDecodeError: + raise ValueError("payload in an invalid encoding") + + +# The various parse_FORMAT functions here are intended to be as lenient as +# possible in their parsing, while still returning a correctly typed +# RawMetadata. +# +# To aid in this, we also generally want to do as little touching of the +# data as possible, except where there are possibly some historic holdovers +# that make valid data awkward to work with. +# +# While this is a lower level, intermediate format than our ``Metadata`` +# class, some light touch ups can make a massive difference in usability. + +# Map METADATA fields to RawMetadata. +_EMAIL_TO_RAW_MAPPING = { + "author": "author", + "author-email": "author_email", + "classifier": "classifiers", + "description": "description", + "description-content-type": "description_content_type", + "download-url": "download_url", + "dynamic": "dynamic", + "home-page": "home_page", + "keywords": "keywords", + "license": "license", + "maintainer": "maintainer", + "maintainer-email": "maintainer_email", + "metadata-version": "metadata_version", + "name": "name", + "obsoletes": "obsoletes", + "obsoletes-dist": "obsoletes_dist", + "platform": "platforms", + "project-url": "project_urls", + "provides": "provides", + "provides-dist": "provides_dist", + "provides-extra": "provides_extra", + "requires": "requires", + "requires-dist": "requires_dist", + "requires-external": "requires_external", + "requires-python": "requires_python", + "summary": "summary", + "supported-platform": "supported_platforms", + "version": "version", +} +_RAW_TO_EMAIL_MAPPING = {raw: email for email, raw in _EMAIL_TO_RAW_MAPPING.items()} + + +def parse_email(data: bytes | str) -> tuple[RawMetadata, dict[str, list[str]]]: + """Parse a distribution's metadata stored as email headers (e.g. from ``METADATA``). + + This function returns a two-item tuple of dicts. The first dict is of + recognized fields from the core metadata specification. Fields that can be + parsed and translated into Python's built-in types are converted + appropriately. All other fields are left as-is. Fields that are allowed to + appear multiple times are stored as lists. + + The second dict contains all other fields from the metadata. This includes + any unrecognized fields. It also includes any fields which are expected to + be parsed into a built-in type but were not formatted appropriately. Finally, + any fields that are expected to appear only once but are repeated are + included in this dict. + + """ + raw: dict[str, str | list[str] | dict[str, str]] = {} + unparsed: dict[str, list[str]] = {} + + if isinstance(data, str): + parsed = email.parser.Parser(policy=email.policy.compat32).parsestr(data) + else: + parsed = email.parser.BytesParser(policy=email.policy.compat32).parsebytes(data) + + # We have to wrap parsed.keys() in a set, because in the case of multiple + # values for a key (a list), the key will appear multiple times in the + # list of keys, but we're avoiding that by using get_all(). + for name in frozenset(parsed.keys()): + # Header names in RFC are case insensitive, so we'll normalize to all + # lower case to make comparisons easier. + name = name.lower() + + # We use get_all() here, even for fields that aren't multiple use, + # because otherwise someone could have e.g. two Name fields, and we + # would just silently ignore it rather than doing something about it. + headers = parsed.get_all(name) or [] + + # The way the email module works when parsing bytes is that it + # unconditionally decodes the bytes as ascii using the surrogateescape + # handler. When you pull that data back out (such as with get_all() ), + # it looks to see if the str has any surrogate escapes, and if it does + # it wraps it in a Header object instead of returning the string. + # + # As such, we'll look for those Header objects, and fix up the encoding. + value = [] + # Flag if we have run into any issues processing the headers, thus + # signalling that the data belongs in 'unparsed'. + valid_encoding = True + for h in headers: + # It's unclear if this can return more types than just a Header or + # a str, so we'll just assert here to make sure. + assert isinstance(h, (email.header.Header, str)) + + # If it's a header object, we need to do our little dance to get + # the real data out of it. In cases where there is invalid data + # we're going to end up with mojibake, but there's no obvious, good + # way around that without reimplementing parts of the Header object + # ourselves. + # + # That should be fine since, if mojibacked happens, this key is + # going into the unparsed dict anyways. + if isinstance(h, email.header.Header): + # The Header object stores it's data as chunks, and each chunk + # can be independently encoded, so we'll need to check each + # of them. + chunks: list[tuple[bytes, str | None]] = [] + for bin, encoding in email.header.decode_header(h): + try: + bin.decode("utf8", "strict") + except UnicodeDecodeError: + # Enable mojibake. + encoding = "latin1" + valid_encoding = False + else: + encoding = "utf8" + chunks.append((bin, encoding)) + + # Turn our chunks back into a Header object, then let that + # Header object do the right thing to turn them into a + # string for us. + value.append(str(email.header.make_header(chunks))) + # This is already a string, so just add it. + else: + value.append(h) + + # We've processed all of our values to get them into a list of str, + # but we may have mojibake data, in which case this is an unparsed + # field. + if not valid_encoding: + unparsed[name] = value + continue + + raw_name = _EMAIL_TO_RAW_MAPPING.get(name) + if raw_name is None: + # This is a bit of a weird situation, we've encountered a key that + # we don't know what it means, so we don't know whether it's meant + # to be a list or not. + # + # Since we can't really tell one way or another, we'll just leave it + # as a list, even though it may be a single item list, because that's + # what makes the most sense for email headers. + unparsed[name] = value + continue + + # If this is one of our string fields, then we'll check to see if our + # value is a list of a single item. If it is then we'll assume that + # it was emitted as a single string, and unwrap the str from inside + # the list. + # + # If it's any other kind of data, then we haven't the faintest clue + # what we should parse it as, and we have to just add it to our list + # of unparsed stuff. + if raw_name in _STRING_FIELDS and len(value) == 1: + raw[raw_name] = value[0] + # If this is one of our list of string fields, then we can just assign + # the value, since email *only* has strings, and our get_all() call + # above ensures that this is a list. + elif raw_name in _LIST_FIELDS: + raw[raw_name] = value + # Special Case: Keywords + # The keywords field is implemented in the metadata spec as a str, + # but it conceptually is a list of strings, and is serialized using + # ", ".join(keywords), so we'll do some light data massaging to turn + # this into what it logically is. + elif raw_name == "keywords" and len(value) == 1: + raw[raw_name] = _parse_keywords(value[0]) + # Special Case: Project-URL + # The project urls is implemented in the metadata spec as a list of + # specially-formatted strings that represent a key and a value, which + # is fundamentally a mapping, however the email format doesn't support + # mappings in a sane way, so it was crammed into a list of strings + # instead. + # + # We will do a little light data massaging to turn this into a map as + # it logically should be. + elif raw_name == "project_urls": + try: + raw[raw_name] = _parse_project_urls(value) + except KeyError: + unparsed[name] = value + # Nothing that we've done has managed to parse this, so it'll just + # throw it in our unparseable data and move on. + else: + unparsed[name] = value + + # We need to support getting the Description from the message payload in + # addition to getting it from the the headers. This does mean, though, there + # is the possibility of it being set both ways, in which case we put both + # in 'unparsed' since we don't know which is right. + try: + payload = _get_payload(parsed, data) + except ValueError: + unparsed.setdefault("description", []).append( + parsed.get_payload(decode=isinstance(data, bytes)) + ) + else: + if payload: + # Check to see if we've already got a description, if so then both + # it, and this body move to unparseable. + if "description" in raw: + description_header = cast(str, raw.pop("description")) + unparsed.setdefault("description", []).extend( + [description_header, payload] + ) + elif "description" in unparsed: + unparsed["description"].append(payload) + else: + raw["description"] = payload + + # We need to cast our `raw` to a metadata, because a TypedDict only support + # literal key names, but we're computing our key names on purpose, but the + # way this function is implemented, our `TypedDict` can only have valid key + # names. + return cast(RawMetadata, raw), unparsed + + +_NOT_FOUND = object() + + +# Keep the two values in sync. +_VALID_METADATA_VERSIONS = ["1.0", "1.1", "1.2", "2.1", "2.2", "2.3"] +_MetadataVersion = Literal["1.0", "1.1", "1.2", "2.1", "2.2", "2.3"] + +_REQUIRED_ATTRS = frozenset(["metadata_version", "name", "version"]) + + +class _Validator(Generic[T]): + """Validate a metadata field. + + All _process_*() methods correspond to a core metadata field. The method is + called with the field's raw value. If the raw value is valid it is returned + in its "enriched" form (e.g. ``version.Version`` for the ``Version`` field). + If the raw value is invalid, :exc:`InvalidMetadata` is raised (with a cause + as appropriate). + """ + + name: str + raw_name: str + added: _MetadataVersion + + def __init__( + self, + *, + added: _MetadataVersion = "1.0", + ) -> None: + self.added = added + + def __set_name__(self, _owner: Metadata, name: str) -> None: + self.name = name + self.raw_name = _RAW_TO_EMAIL_MAPPING[name] + + def __get__(self, instance: Metadata, _owner: type[Metadata]) -> T: + # With Python 3.8, the caching can be replaced with functools.cached_property(). + # No need to check the cache as attribute lookup will resolve into the + # instance's __dict__ before __get__ is called. + cache = instance.__dict__ + value = instance._raw.get(self.name) + + # To make the _process_* methods easier, we'll check if the value is None + # and if this field is NOT a required attribute, and if both of those + # things are true, we'll skip the the converter. This will mean that the + # converters never have to deal with the None union. + if self.name in _REQUIRED_ATTRS or value is not None: + try: + converter: Callable[[Any], T] = getattr(self, f"_process_{self.name}") + except AttributeError: + pass + else: + value = converter(value) + + cache[self.name] = value + try: + del instance._raw[self.name] # type: ignore[misc] + except KeyError: + pass + + return cast(T, value) + + def _invalid_metadata( + self, msg: str, cause: Exception | None = None + ) -> InvalidMetadata: + exc = InvalidMetadata( + self.raw_name, msg.format_map({"field": repr(self.raw_name)}) + ) + exc.__cause__ = cause + return exc + + def _process_metadata_version(self, value: str) -> _MetadataVersion: + # Implicitly makes Metadata-Version required. + if value not in _VALID_METADATA_VERSIONS: + raise self._invalid_metadata(f"{value!r} is not a valid metadata version") + return cast(_MetadataVersion, value) + + def _process_name(self, value: str) -> str: + if not value: + raise self._invalid_metadata("{field} is a required field") + # Validate the name as a side-effect. + try: + utils.canonicalize_name(value, validate=True) + except utils.InvalidName as exc: + raise self._invalid_metadata( + f"{value!r} is invalid for {{field}}", cause=exc + ) + else: + return value + + def _process_version(self, value: str) -> version_module.Version: + if not value: + raise self._invalid_metadata("{field} is a required field") + try: + return version_module.parse(value) + except version_module.InvalidVersion as exc: + raise self._invalid_metadata( + f"{value!r} is invalid for {{field}}", cause=exc + ) + + def _process_summary(self, value: str) -> str: + """Check the field contains no newlines.""" + if "\n" in value: + raise self._invalid_metadata("{field} must be a single line") + return value + + def _process_description_content_type(self, value: str) -> str: + content_types = {"text/plain", "text/x-rst", "text/markdown"} + message = email.message.EmailMessage() + message["content-type"] = value + + content_type, parameters = ( + # Defaults to `text/plain` if parsing failed. + message.get_content_type().lower(), + message["content-type"].params, + ) + # Check if content-type is valid or defaulted to `text/plain` and thus was + # not parseable. + if content_type not in content_types or content_type not in value.lower(): + raise self._invalid_metadata( + f"{{field}} must be one of {list(content_types)}, not {value!r}" + ) + + charset = parameters.get("charset", "UTF-8") + if charset != "UTF-8": + raise self._invalid_metadata( + f"{{field}} can only specify the UTF-8 charset, not {list(charset)}" + ) + + markdown_variants = {"GFM", "CommonMark"} + variant = parameters.get("variant", "GFM") # Use an acceptable default. + if content_type == "text/markdown" and variant not in markdown_variants: + raise self._invalid_metadata( + f"valid Markdown variants for {{field}} are {list(markdown_variants)}, " + f"not {variant!r}", + ) + return value + + def _process_dynamic(self, value: list[str]) -> list[str]: + for dynamic_field in map(str.lower, value): + if dynamic_field in {"name", "version", "metadata-version"}: + raise self._invalid_metadata( + f"{value!r} is not allowed as a dynamic field" + ) + elif dynamic_field not in _EMAIL_TO_RAW_MAPPING: + raise self._invalid_metadata(f"{value!r} is not a valid dynamic field") + return list(map(str.lower, value)) + + def _process_provides_extra( + self, + value: list[str], + ) -> list[utils.NormalizedName]: + normalized_names = [] + try: + for name in value: + normalized_names.append(utils.canonicalize_name(name, validate=True)) + except utils.InvalidName as exc: + raise self._invalid_metadata( + f"{name!r} is invalid for {{field}}", cause=exc + ) + else: + return normalized_names + + def _process_requires_python(self, value: str) -> specifiers.SpecifierSet: + try: + return specifiers.SpecifierSet(value) + except specifiers.InvalidSpecifier as exc: + raise self._invalid_metadata( + f"{value!r} is invalid for {{field}}", cause=exc + ) + + def _process_requires_dist( + self, + value: list[str], + ) -> list[requirements.Requirement]: + reqs = [] + try: + for req in value: + reqs.append(requirements.Requirement(req)) + except requirements.InvalidRequirement as exc: + raise self._invalid_metadata(f"{req!r} is invalid for {{field}}", cause=exc) + else: + return reqs + + +class Metadata: + """Representation of distribution metadata. + + Compared to :class:`RawMetadata`, this class provides objects representing + metadata fields instead of only using built-in types. Any invalid metadata + will cause :exc:`InvalidMetadata` to be raised (with a + :py:attr:`~BaseException.__cause__` attribute as appropriate). + """ + + _raw: RawMetadata + + @classmethod + def from_raw(cls, data: RawMetadata, *, validate: bool = True) -> Metadata: + """Create an instance from :class:`RawMetadata`. + + If *validate* is true, all metadata will be validated. All exceptions + related to validation will be gathered and raised as an :class:`ExceptionGroup`. + """ + ins = cls() + ins._raw = data.copy() # Mutations occur due to caching enriched values. + + if validate: + exceptions: list[Exception] = [] + try: + metadata_version = ins.metadata_version + metadata_age = _VALID_METADATA_VERSIONS.index(metadata_version) + except InvalidMetadata as metadata_version_exc: + exceptions.append(metadata_version_exc) + metadata_version = None + + # Make sure to check for the fields that are present, the required + # fields (so their absence can be reported). + fields_to_check = frozenset(ins._raw) | _REQUIRED_ATTRS + # Remove fields that have already been checked. + fields_to_check -= {"metadata_version"} + + for key in fields_to_check: + try: + if metadata_version: + # Can't use getattr() as that triggers descriptor protocol which + # will fail due to no value for the instance argument. + try: + field_metadata_version = cls.__dict__[key].added + except KeyError: + exc = InvalidMetadata(key, f"unrecognized field: {key!r}") + exceptions.append(exc) + continue + field_age = _VALID_METADATA_VERSIONS.index( + field_metadata_version + ) + if field_age > metadata_age: + field = _RAW_TO_EMAIL_MAPPING[key] + exc = InvalidMetadata( + field, + "{field} introduced in metadata version " + "{field_metadata_version}, not {metadata_version}", + ) + exceptions.append(exc) + continue + getattr(ins, key) + except InvalidMetadata as exc: + exceptions.append(exc) + + if exceptions: + raise ExceptionGroup("invalid metadata", exceptions) + + return ins + + @classmethod + def from_email(cls, data: bytes | str, *, validate: bool = True) -> Metadata: + """Parse metadata from email headers. + + If *validate* is true, the metadata will be validated. All exceptions + related to validation will be gathered and raised as an :class:`ExceptionGroup`. + """ + raw, unparsed = parse_email(data) + + if validate: + exceptions: list[Exception] = [] + for unparsed_key in unparsed: + if unparsed_key in _EMAIL_TO_RAW_MAPPING: + message = f"{unparsed_key!r} has invalid data" + else: + message = f"unrecognized field: {unparsed_key!r}" + exceptions.append(InvalidMetadata(unparsed_key, message)) + + if exceptions: + raise ExceptionGroup("unparsed", exceptions) + + try: + return cls.from_raw(raw, validate=validate) + except ExceptionGroup as exc_group: + raise ExceptionGroup( + "invalid or unparsed metadata", exc_group.exceptions + ) from None + + metadata_version: _Validator[_MetadataVersion] = _Validator() + """:external:ref:`core-metadata-metadata-version` + (required; validated to be a valid metadata version)""" + name: _Validator[str] = _Validator() + """:external:ref:`core-metadata-name` + (required; validated using :func:`~packaging.utils.canonicalize_name` and its + *validate* parameter)""" + version: _Validator[version_module.Version] = _Validator() + """:external:ref:`core-metadata-version` (required)""" + dynamic: _Validator[list[str] | None] = _Validator( + added="2.2", + ) + """:external:ref:`core-metadata-dynamic` + (validated against core metadata field names and lowercased)""" + platforms: _Validator[list[str] | None] = _Validator() + """:external:ref:`core-metadata-platform`""" + supported_platforms: _Validator[list[str] | None] = _Validator(added="1.1") + """:external:ref:`core-metadata-supported-platform`""" + summary: _Validator[str | None] = _Validator() + """:external:ref:`core-metadata-summary` (validated to contain no newlines)""" + description: _Validator[str | None] = _Validator() # TODO 2.1: can be in body + """:external:ref:`core-metadata-description`""" + description_content_type: _Validator[str | None] = _Validator(added="2.1") + """:external:ref:`core-metadata-description-content-type` (validated)""" + keywords: _Validator[list[str] | None] = _Validator() + """:external:ref:`core-metadata-keywords`""" + home_page: _Validator[str | None] = _Validator() + """:external:ref:`core-metadata-home-page`""" + download_url: _Validator[str | None] = _Validator(added="1.1") + """:external:ref:`core-metadata-download-url`""" + author: _Validator[str | None] = _Validator() + """:external:ref:`core-metadata-author`""" + author_email: _Validator[str | None] = _Validator() + """:external:ref:`core-metadata-author-email`""" + maintainer: _Validator[str | None] = _Validator(added="1.2") + """:external:ref:`core-metadata-maintainer`""" + maintainer_email: _Validator[str | None] = _Validator(added="1.2") + """:external:ref:`core-metadata-maintainer-email`""" + license: _Validator[str | None] = _Validator() + """:external:ref:`core-metadata-license`""" + classifiers: _Validator[list[str] | None] = _Validator(added="1.1") + """:external:ref:`core-metadata-classifier`""" + requires_dist: _Validator[list[requirements.Requirement] | None] = _Validator( + added="1.2" + ) + """:external:ref:`core-metadata-requires-dist`""" + requires_python: _Validator[specifiers.SpecifierSet | None] = _Validator( + added="1.2" + ) + """:external:ref:`core-metadata-requires-python`""" + # Because `Requires-External` allows for non-PEP 440 version specifiers, we + # don't do any processing on the values. + requires_external: _Validator[list[str] | None] = _Validator(added="1.2") + """:external:ref:`core-metadata-requires-external`""" + project_urls: _Validator[dict[str, str] | None] = _Validator(added="1.2") + """:external:ref:`core-metadata-project-url`""" + # PEP 685 lets us raise an error if an extra doesn't pass `Name` validation + # regardless of metadata version. + provides_extra: _Validator[list[utils.NormalizedName] | None] = _Validator( + added="2.1", + ) + """:external:ref:`core-metadata-provides-extra`""" + provides_dist: _Validator[list[str] | None] = _Validator(added="1.2") + """:external:ref:`core-metadata-provides-dist`""" + obsoletes_dist: _Validator[list[str] | None] = _Validator(added="1.2") + """:external:ref:`core-metadata-obsoletes-dist`""" + requires: _Validator[list[str] | None] = _Validator(added="1.1") + """``Requires`` (deprecated)""" + provides: _Validator[list[str] | None] = _Validator(added="1.1") + """``Provides`` (deprecated)""" + obsoletes: _Validator[list[str] | None] = _Validator(added="1.1") + """``Obsoletes`` (deprecated)""" diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/py.typed b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/requirements.py b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/requirements.py new file mode 100644 index 0000000..4e068c9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/requirements.py @@ -0,0 +1,91 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import annotations + +from typing import Any, Iterator + +from ._parser import parse_requirement as _parse_requirement +from ._tokenizer import ParserSyntaxError +from .markers import Marker, _normalize_extra_values +from .specifiers import SpecifierSet +from .utils import canonicalize_name + + +class InvalidRequirement(ValueError): + """ + An invalid requirement was found, users should refer to PEP 508. + """ + + +class Requirement: + """Parse a requirement. + + Parse a given requirement string into its parts, such as name, specifier, + URL, and extras. Raises InvalidRequirement on a badly-formed requirement + string. + """ + + # TODO: Can we test whether something is contained within a requirement? + # If so how do we do that? Do we need to test against the _name_ of + # the thing as well as the version? What about the markers? + # TODO: Can we normalize the name and extra name? + + def __init__(self, requirement_string: str) -> None: + try: + parsed = _parse_requirement(requirement_string) + except ParserSyntaxError as e: + raise InvalidRequirement(str(e)) from e + + self.name: str = parsed.name + self.url: str | None = parsed.url or None + self.extras: set[str] = set(parsed.extras or []) + self.specifier: SpecifierSet = SpecifierSet(parsed.specifier) + self.marker: Marker | None = None + if parsed.marker is not None: + self.marker = Marker.__new__(Marker) + self.marker._markers = _normalize_extra_values(parsed.marker) + + def _iter_parts(self, name: str) -> Iterator[str]: + yield name + + if self.extras: + formatted_extras = ",".join(sorted(self.extras)) + yield f"[{formatted_extras}]" + + if self.specifier: + yield str(self.specifier) + + if self.url: + yield f"@ {self.url}" + if self.marker: + yield " " + + if self.marker: + yield f"; {self.marker}" + + def __str__(self) -> str: + return "".join(self._iter_parts(self.name)) + + def __repr__(self) -> str: + return f"" + + def __hash__(self) -> int: + return hash( + ( + self.__class__.__name__, + *self._iter_parts(canonicalize_name(self.name)), + ) + ) + + def __eq__(self, other: Any) -> bool: + if not isinstance(other, Requirement): + return NotImplemented + + return ( + canonicalize_name(self.name) == canonicalize_name(other.name) + and self.extras == other.extras + and self.specifier == other.specifier + and self.url == other.url + and self.marker == other.marker + ) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/specifiers.py b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/specifiers.py new file mode 100644 index 0000000..f3ac480 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/specifiers.py @@ -0,0 +1,1009 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +""" +.. testsetup:: + + from pip._vendor.packaging.specifiers import Specifier, SpecifierSet, InvalidSpecifier + from pip._vendor.packaging.version import Version +""" + +from __future__ import annotations + +import abc +import itertools +import re +from typing import Callable, Iterable, Iterator, TypeVar, Union + +from .utils import canonicalize_version +from .version import Version + +UnparsedVersion = Union[Version, str] +UnparsedVersionVar = TypeVar("UnparsedVersionVar", bound=UnparsedVersion) +CallableOperator = Callable[[Version, str], bool] + + +def _coerce_version(version: UnparsedVersion) -> Version: + if not isinstance(version, Version): + version = Version(version) + return version + + +class InvalidSpecifier(ValueError): + """ + Raised when attempting to create a :class:`Specifier` with a specifier + string that is invalid. + + >>> Specifier("lolwat") + Traceback (most recent call last): + ... + packaging.specifiers.InvalidSpecifier: Invalid specifier: 'lolwat' + """ + + +class BaseSpecifier(metaclass=abc.ABCMeta): + @abc.abstractmethod + def __str__(self) -> str: + """ + Returns the str representation of this Specifier-like object. This + should be representative of the Specifier itself. + """ + + @abc.abstractmethod + def __hash__(self) -> int: + """ + Returns a hash value for this Specifier-like object. + """ + + @abc.abstractmethod + def __eq__(self, other: object) -> bool: + """ + Returns a boolean representing whether or not the two Specifier-like + objects are equal. + + :param other: The other object to check against. + """ + + @property + @abc.abstractmethod + def prereleases(self) -> bool | None: + """Whether or not pre-releases as a whole are allowed. + + This can be set to either ``True`` or ``False`` to explicitly enable or disable + prereleases or it can be set to ``None`` (the default) to use default semantics. + """ + + @prereleases.setter + def prereleases(self, value: bool) -> None: + """Setter for :attr:`prereleases`. + + :param value: The value to set. + """ + + @abc.abstractmethod + def contains(self, item: str, prereleases: bool | None = None) -> bool: + """ + Determines if the given item is contained within this specifier. + """ + + @abc.abstractmethod + def filter( + self, iterable: Iterable[UnparsedVersionVar], prereleases: bool | None = None + ) -> Iterator[UnparsedVersionVar]: + """ + Takes an iterable of items and filters them so that only items which + are contained within this specifier are allowed in it. + """ + + +class Specifier(BaseSpecifier): + """This class abstracts handling of version specifiers. + + .. tip:: + + It is generally not required to instantiate this manually. You should instead + prefer to work with :class:`SpecifierSet` instead, which can parse + comma-separated version specifiers (which is what package metadata contains). + """ + + _operator_regex_str = r""" + (?P(~=|==|!=|<=|>=|<|>|===)) + """ + _version_regex_str = r""" + (?P + (?: + # The identity operators allow for an escape hatch that will + # do an exact string match of the version you wish to install. + # This will not be parsed by PEP 440 and we cannot determine + # any semantic meaning from it. This operator is discouraged + # but included entirely as an escape hatch. + (?<====) # Only match for the identity operator + \s* + [^\s;)]* # The arbitrary version can be just about anything, + # we match everything except for whitespace, a + # semi-colon for marker support, and a closing paren + # since versions can be enclosed in them. + ) + | + (?: + # The (non)equality operators allow for wild card and local + # versions to be specified so we have to define these two + # operators separately to enable that. + (?<===|!=) # Only match for equals and not equals + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)* # release + + # You cannot use a wild card and a pre-release, post-release, a dev or + # local version together so group them with a | and make them optional. + (?: + \.\* # Wild card syntax of .* + | + (?: # pre release + [-_\.]? + (alpha|beta|preview|pre|a|b|c|rc) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local + )? + ) + | + (?: + # The compatible operator requires at least two digits in the + # release segment. + (?<=~=) # Only match for the compatible operator + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *) + (?: # pre release + [-_\.]? + (alpha|beta|preview|pre|a|b|c|rc) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + ) + | + (?: + # All other operators only allow a sub set of what the + # (non)equality operators do. Specifically they do not allow + # local versions to be specified nor do they allow the prefix + # matching wild cards. + (?=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + "===": "arbitrary", + } + + def __init__(self, spec: str = "", prereleases: bool | None = None) -> None: + """Initialize a Specifier instance. + + :param spec: + The string representation of a specifier which will be parsed and + normalized before use. + :param prereleases: + This tells the specifier if it should accept prerelease versions if + applicable or not. The default of ``None`` will autodetect it from the + given specifiers. + :raises InvalidSpecifier: + If the given specifier is invalid (i.e. bad syntax). + """ + match = self._regex.search(spec) + if not match: + raise InvalidSpecifier(f"Invalid specifier: '{spec}'") + + self._spec: tuple[str, str] = ( + match.group("operator").strip(), + match.group("version").strip(), + ) + + # Store whether or not this Specifier should accept prereleases + self._prereleases = prereleases + + # https://github.com/python/mypy/pull/13475#pullrequestreview-1079784515 + @property # type: ignore[override] + def prereleases(self) -> bool: + # If there is an explicit prereleases set for this, then we'll just + # blindly use that. + if self._prereleases is not None: + return self._prereleases + + # Look at all of our specifiers and determine if they are inclusive + # operators, and if they are if they are including an explicit + # prerelease. + operator, version = self._spec + if operator in ["==", ">=", "<=", "~=", "==="]: + # The == specifier can include a trailing .*, if it does we + # want to remove before parsing. + if operator == "==" and version.endswith(".*"): + version = version[:-2] + + # Parse the version, and if it is a pre-release than this + # specifier allows pre-releases. + if Version(version).is_prerelease: + return True + + return False + + @prereleases.setter + def prereleases(self, value: bool) -> None: + self._prereleases = value + + @property + def operator(self) -> str: + """The operator of this specifier. + + >>> Specifier("==1.2.3").operator + '==' + """ + return self._spec[0] + + @property + def version(self) -> str: + """The version of this specifier. + + >>> Specifier("==1.2.3").version + '1.2.3' + """ + return self._spec[1] + + def __repr__(self) -> str: + """A representation of the Specifier that shows all internal state. + + >>> Specifier('>=1.0.0') + =1.0.0')> + >>> Specifier('>=1.0.0', prereleases=False) + =1.0.0', prereleases=False)> + >>> Specifier('>=1.0.0', prereleases=True) + =1.0.0', prereleases=True)> + """ + pre = ( + f", prereleases={self.prereleases!r}" + if self._prereleases is not None + else "" + ) + + return f"<{self.__class__.__name__}({str(self)!r}{pre})>" + + def __str__(self) -> str: + """A string representation of the Specifier that can be round-tripped. + + >>> str(Specifier('>=1.0.0')) + '>=1.0.0' + >>> str(Specifier('>=1.0.0', prereleases=False)) + '>=1.0.0' + """ + return "{}{}".format(*self._spec) + + @property + def _canonical_spec(self) -> tuple[str, str]: + canonical_version = canonicalize_version( + self._spec[1], + strip_trailing_zero=(self._spec[0] != "~="), + ) + return self._spec[0], canonical_version + + def __hash__(self) -> int: + return hash(self._canonical_spec) + + def __eq__(self, other: object) -> bool: + """Whether or not the two Specifier-like objects are equal. + + :param other: The other object to check against. + + The value of :attr:`prereleases` is ignored. + + >>> Specifier("==1.2.3") == Specifier("== 1.2.3.0") + True + >>> (Specifier("==1.2.3", prereleases=False) == + ... Specifier("==1.2.3", prereleases=True)) + True + >>> Specifier("==1.2.3") == "==1.2.3" + True + >>> Specifier("==1.2.3") == Specifier("==1.2.4") + False + >>> Specifier("==1.2.3") == Specifier("~=1.2.3") + False + """ + if isinstance(other, str): + try: + other = self.__class__(str(other)) + except InvalidSpecifier: + return NotImplemented + elif not isinstance(other, self.__class__): + return NotImplemented + + return self._canonical_spec == other._canonical_spec + + def _get_operator(self, op: str) -> CallableOperator: + operator_callable: CallableOperator = getattr( + self, f"_compare_{self._operators[op]}" + ) + return operator_callable + + def _compare_compatible(self, prospective: Version, spec: str) -> bool: + # Compatible releases have an equivalent combination of >= and ==. That + # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to + # implement this in terms of the other specifiers instead of + # implementing it ourselves. The only thing we need to do is construct + # the other specifiers. + + # We want everything but the last item in the version, but we want to + # ignore suffix segments. + prefix = _version_join( + list(itertools.takewhile(_is_not_suffix, _version_split(spec)))[:-1] + ) + + # Add the prefix notation to the end of our string + prefix += ".*" + + return self._get_operator(">=")(prospective, spec) and self._get_operator("==")( + prospective, prefix + ) + + def _compare_equal(self, prospective: Version, spec: str) -> bool: + # We need special logic to handle prefix matching + if spec.endswith(".*"): + # In the case of prefix matching we want to ignore local segment. + normalized_prospective = canonicalize_version( + prospective.public, strip_trailing_zero=False + ) + # Get the normalized version string ignoring the trailing .* + normalized_spec = canonicalize_version(spec[:-2], strip_trailing_zero=False) + # Split the spec out by bangs and dots, and pretend that there is + # an implicit dot in between a release segment and a pre-release segment. + split_spec = _version_split(normalized_spec) + + # Split the prospective version out by bangs and dots, and pretend + # that there is an implicit dot in between a release segment and + # a pre-release segment. + split_prospective = _version_split(normalized_prospective) + + # 0-pad the prospective version before shortening it to get the correct + # shortened version. + padded_prospective, _ = _pad_version(split_prospective, split_spec) + + # Shorten the prospective version to be the same length as the spec + # so that we can determine if the specifier is a prefix of the + # prospective version or not. + shortened_prospective = padded_prospective[: len(split_spec)] + + return shortened_prospective == split_spec + else: + # Convert our spec string into a Version + spec_version = Version(spec) + + # If the specifier does not have a local segment, then we want to + # act as if the prospective version also does not have a local + # segment. + if not spec_version.local: + prospective = Version(prospective.public) + + return prospective == spec_version + + def _compare_not_equal(self, prospective: Version, spec: str) -> bool: + return not self._compare_equal(prospective, spec) + + def _compare_less_than_equal(self, prospective: Version, spec: str) -> bool: + # NB: Local version identifiers are NOT permitted in the version + # specifier, so local version labels can be universally removed from + # the prospective version. + return Version(prospective.public) <= Version(spec) + + def _compare_greater_than_equal(self, prospective: Version, spec: str) -> bool: + # NB: Local version identifiers are NOT permitted in the version + # specifier, so local version labels can be universally removed from + # the prospective version. + return Version(prospective.public) >= Version(spec) + + def _compare_less_than(self, prospective: Version, spec_str: str) -> bool: + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec_str) + + # Check to see if the prospective version is less than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective < spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a pre-release version, that we do not accept pre-release + # versions for the version mentioned in the specifier (e.g. <3.1 should + # not match 3.1.dev0, but should match 3.0.dev0). + if not spec.is_prerelease and prospective.is_prerelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # less than the spec version *and* it's not a pre-release of the same + # version in the spec. + return True + + def _compare_greater_than(self, prospective: Version, spec_str: str) -> bool: + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec_str) + + # Check to see if the prospective version is greater than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective > spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a post-release version, that we do not accept + # post-release versions for the version mentioned in the specifier + # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0). + if not spec.is_postrelease and prospective.is_postrelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # Ensure that we do not allow a local version of the version mentioned + # in the specifier, which is technically greater than, to match. + if prospective.local is not None: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # greater than the spec version *and* it's not a pre-release of the + # same version in the spec. + return True + + def _compare_arbitrary(self, prospective: Version, spec: str) -> bool: + return str(prospective).lower() == str(spec).lower() + + def __contains__(self, item: str | Version) -> bool: + """Return whether or not the item is contained in this specifier. + + :param item: The item to check for. + + This is used for the ``in`` operator and behaves the same as + :meth:`contains` with no ``prereleases`` argument passed. + + >>> "1.2.3" in Specifier(">=1.2.3") + True + >>> Version("1.2.3") in Specifier(">=1.2.3") + True + >>> "1.0.0" in Specifier(">=1.2.3") + False + >>> "1.3.0a1" in Specifier(">=1.2.3") + False + >>> "1.3.0a1" in Specifier(">=1.2.3", prereleases=True) + True + """ + return self.contains(item) + + def contains(self, item: UnparsedVersion, prereleases: bool | None = None) -> bool: + """Return whether or not the item is contained in this specifier. + + :param item: + The item to check for, which can be a version string or a + :class:`Version` instance. + :param prereleases: + Whether or not to match prereleases with this Specifier. If set to + ``None`` (the default), it uses :attr:`prereleases` to determine + whether or not prereleases are allowed. + + >>> Specifier(">=1.2.3").contains("1.2.3") + True + >>> Specifier(">=1.2.3").contains(Version("1.2.3")) + True + >>> Specifier(">=1.2.3").contains("1.0.0") + False + >>> Specifier(">=1.2.3").contains("1.3.0a1") + False + >>> Specifier(">=1.2.3", prereleases=True).contains("1.3.0a1") + True + >>> Specifier(">=1.2.3").contains("1.3.0a1", prereleases=True) + True + """ + + # Determine if prereleases are to be allowed or not. + if prereleases is None: + prereleases = self.prereleases + + # Normalize item to a Version, this allows us to have a shortcut for + # "2.0" in Specifier(">=2") + normalized_item = _coerce_version(item) + + # Determine if we should be supporting prereleases in this specifier + # or not, if we do not support prereleases than we can short circuit + # logic if this version is a prereleases. + if normalized_item.is_prerelease and not prereleases: + return False + + # Actually do the comparison to determine if this item is contained + # within this Specifier or not. + operator_callable: CallableOperator = self._get_operator(self.operator) + return operator_callable(normalized_item, self.version) + + def filter( + self, iterable: Iterable[UnparsedVersionVar], prereleases: bool | None = None + ) -> Iterator[UnparsedVersionVar]: + """Filter items in the given iterable, that match the specifier. + + :param iterable: + An iterable that can contain version strings and :class:`Version` instances. + The items in the iterable will be filtered according to the specifier. + :param prereleases: + Whether or not to allow prereleases in the returned iterator. If set to + ``None`` (the default), it will be intelligently decide whether to allow + prereleases or not (based on the :attr:`prereleases` attribute, and + whether the only versions matching are prereleases). + + This method is smarter than just ``filter(Specifier().contains, [...])`` + because it implements the rule from :pep:`440` that a prerelease item + SHOULD be accepted if no other versions match the given specifier. + + >>> list(Specifier(">=1.2.3").filter(["1.2", "1.3", "1.5a1"])) + ['1.3'] + >>> list(Specifier(">=1.2.3").filter(["1.2", "1.2.3", "1.3", Version("1.4")])) + ['1.2.3', '1.3', ] + >>> list(Specifier(">=1.2.3").filter(["1.2", "1.5a1"])) + ['1.5a1'] + >>> list(Specifier(">=1.2.3").filter(["1.3", "1.5a1"], prereleases=True)) + ['1.3', '1.5a1'] + >>> list(Specifier(">=1.2.3", prereleases=True).filter(["1.3", "1.5a1"])) + ['1.3', '1.5a1'] + """ + + yielded = False + found_prereleases = [] + + kw = {"prereleases": prereleases if prereleases is not None else True} + + # Attempt to iterate over all the values in the iterable and if any of + # them match, yield them. + for version in iterable: + parsed_version = _coerce_version(version) + + if self.contains(parsed_version, **kw): + # If our version is a prerelease, and we were not set to allow + # prereleases, then we'll store it for later in case nothing + # else matches this specifier. + if parsed_version.is_prerelease and not ( + prereleases or self.prereleases + ): + found_prereleases.append(version) + # Either this is not a prerelease, or we should have been + # accepting prereleases from the beginning. + else: + yielded = True + yield version + + # Now that we've iterated over everything, determine if we've yielded + # any values, and if we have not and we have any prereleases stored up + # then we will go ahead and yield the prereleases. + if not yielded and found_prereleases: + for version in found_prereleases: + yield version + + +_prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$") + + +def _version_split(version: str) -> list[str]: + """Split version into components. + + The split components are intended for version comparison. The logic does + not attempt to retain the original version string, so joining the + components back with :func:`_version_join` may not produce the original + version string. + """ + result: list[str] = [] + + epoch, _, rest = version.rpartition("!") + result.append(epoch or "0") + + for item in rest.split("."): + match = _prefix_regex.search(item) + if match: + result.extend(match.groups()) + else: + result.append(item) + return result + + +def _version_join(components: list[str]) -> str: + """Join split version components into a version string. + + This function assumes the input came from :func:`_version_split`, where the + first component must be the epoch (either empty or numeric), and all other + components numeric. + """ + epoch, *rest = components + return f"{epoch}!{'.'.join(rest)}" + + +def _is_not_suffix(segment: str) -> bool: + return not any( + segment.startswith(prefix) for prefix in ("dev", "a", "b", "rc", "post") + ) + + +def _pad_version(left: list[str], right: list[str]) -> tuple[list[str], list[str]]: + left_split, right_split = [], [] + + # Get the release segment of our versions + left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left))) + right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right))) + + # Get the rest of our versions + left_split.append(left[len(left_split[0]) :]) + right_split.append(right[len(right_split[0]) :]) + + # Insert our padding + left_split.insert(1, ["0"] * max(0, len(right_split[0]) - len(left_split[0]))) + right_split.insert(1, ["0"] * max(0, len(left_split[0]) - len(right_split[0]))) + + return ( + list(itertools.chain.from_iterable(left_split)), + list(itertools.chain.from_iterable(right_split)), + ) + + +class SpecifierSet(BaseSpecifier): + """This class abstracts handling of a set of version specifiers. + + It can be passed a single specifier (``>=3.0``), a comma-separated list of + specifiers (``>=3.0,!=3.1``), or no specifier at all. + """ + + def __init__(self, specifiers: str = "", prereleases: bool | None = None) -> None: + """Initialize a SpecifierSet instance. + + :param specifiers: + The string representation of a specifier or a comma-separated list of + specifiers which will be parsed and normalized before use. + :param prereleases: + This tells the SpecifierSet if it should accept prerelease versions if + applicable or not. The default of ``None`` will autodetect it from the + given specifiers. + + :raises InvalidSpecifier: + If the given ``specifiers`` are not parseable than this exception will be + raised. + """ + + # Split on `,` to break each individual specifier into it's own item, and + # strip each item to remove leading/trailing whitespace. + split_specifiers = [s.strip() for s in specifiers.split(",") if s.strip()] + + # Make each individual specifier a Specifier and save in a frozen set for later. + self._specs = frozenset(map(Specifier, split_specifiers)) + + # Store our prereleases value so we can use it later to determine if + # we accept prereleases or not. + self._prereleases = prereleases + + @property + def prereleases(self) -> bool | None: + # If we have been given an explicit prerelease modifier, then we'll + # pass that through here. + if self._prereleases is not None: + return self._prereleases + + # If we don't have any specifiers, and we don't have a forced value, + # then we'll just return None since we don't know if this should have + # pre-releases or not. + if not self._specs: + return None + + # Otherwise we'll see if any of the given specifiers accept + # prereleases, if any of them do we'll return True, otherwise False. + return any(s.prereleases for s in self._specs) + + @prereleases.setter + def prereleases(self, value: bool) -> None: + self._prereleases = value + + def __repr__(self) -> str: + """A representation of the specifier set that shows all internal state. + + Note that the ordering of the individual specifiers within the set may not + match the input string. + + >>> SpecifierSet('>=1.0.0,!=2.0.0') + =1.0.0')> + >>> SpecifierSet('>=1.0.0,!=2.0.0', prereleases=False) + =1.0.0', prereleases=False)> + >>> SpecifierSet('>=1.0.0,!=2.0.0', prereleases=True) + =1.0.0', prereleases=True)> + """ + pre = ( + f", prereleases={self.prereleases!r}" + if self._prereleases is not None + else "" + ) + + return f"" + + def __str__(self) -> str: + """A string representation of the specifier set that can be round-tripped. + + Note that the ordering of the individual specifiers within the set may not + match the input string. + + >>> str(SpecifierSet(">=1.0.0,!=1.0.1")) + '!=1.0.1,>=1.0.0' + >>> str(SpecifierSet(">=1.0.0,!=1.0.1", prereleases=False)) + '!=1.0.1,>=1.0.0' + """ + return ",".join(sorted(str(s) for s in self._specs)) + + def __hash__(self) -> int: + return hash(self._specs) + + def __and__(self, other: SpecifierSet | str) -> SpecifierSet: + """Return a SpecifierSet which is a combination of the two sets. + + :param other: The other object to combine with. + + >>> SpecifierSet(">=1.0.0,!=1.0.1") & '<=2.0.0,!=2.0.1' + =1.0.0')> + >>> SpecifierSet(">=1.0.0,!=1.0.1") & SpecifierSet('<=2.0.0,!=2.0.1') + =1.0.0')> + """ + if isinstance(other, str): + other = SpecifierSet(other) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + specifier = SpecifierSet() + specifier._specs = frozenset(self._specs | other._specs) + + if self._prereleases is None and other._prereleases is not None: + specifier._prereleases = other._prereleases + elif self._prereleases is not None and other._prereleases is None: + specifier._prereleases = self._prereleases + elif self._prereleases == other._prereleases: + specifier._prereleases = self._prereleases + else: + raise ValueError( + "Cannot combine SpecifierSets with True and False prerelease " + "overrides." + ) + + return specifier + + def __eq__(self, other: object) -> bool: + """Whether or not the two SpecifierSet-like objects are equal. + + :param other: The other object to check against. + + The value of :attr:`prereleases` is ignored. + + >>> SpecifierSet(">=1.0.0,!=1.0.1") == SpecifierSet(">=1.0.0,!=1.0.1") + True + >>> (SpecifierSet(">=1.0.0,!=1.0.1", prereleases=False) == + ... SpecifierSet(">=1.0.0,!=1.0.1", prereleases=True)) + True + >>> SpecifierSet(">=1.0.0,!=1.0.1") == ">=1.0.0,!=1.0.1" + True + >>> SpecifierSet(">=1.0.0,!=1.0.1") == SpecifierSet(">=1.0.0") + False + >>> SpecifierSet(">=1.0.0,!=1.0.1") == SpecifierSet(">=1.0.0,!=1.0.2") + False + """ + if isinstance(other, (str, Specifier)): + other = SpecifierSet(str(other)) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + return self._specs == other._specs + + def __len__(self) -> int: + """Returns the number of specifiers in this specifier set.""" + return len(self._specs) + + def __iter__(self) -> Iterator[Specifier]: + """ + Returns an iterator over all the underlying :class:`Specifier` instances + in this specifier set. + + >>> sorted(SpecifierSet(">=1.0.0,!=1.0.1"), key=str) + [, =1.0.0')>] + """ + return iter(self._specs) + + def __contains__(self, item: UnparsedVersion) -> bool: + """Return whether or not the item is contained in this specifier. + + :param item: The item to check for. + + This is used for the ``in`` operator and behaves the same as + :meth:`contains` with no ``prereleases`` argument passed. + + >>> "1.2.3" in SpecifierSet(">=1.0.0,!=1.0.1") + True + >>> Version("1.2.3") in SpecifierSet(">=1.0.0,!=1.0.1") + True + >>> "1.0.1" in SpecifierSet(">=1.0.0,!=1.0.1") + False + >>> "1.3.0a1" in SpecifierSet(">=1.0.0,!=1.0.1") + False + >>> "1.3.0a1" in SpecifierSet(">=1.0.0,!=1.0.1", prereleases=True) + True + """ + return self.contains(item) + + def contains( + self, + item: UnparsedVersion, + prereleases: bool | None = None, + installed: bool | None = None, + ) -> bool: + """Return whether or not the item is contained in this SpecifierSet. + + :param item: + The item to check for, which can be a version string or a + :class:`Version` instance. + :param prereleases: + Whether or not to match prereleases with this SpecifierSet. If set to + ``None`` (the default), it uses :attr:`prereleases` to determine + whether or not prereleases are allowed. + + >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.2.3") + True + >>> SpecifierSet(">=1.0.0,!=1.0.1").contains(Version("1.2.3")) + True + >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.0.1") + False + >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.3.0a1") + False + >>> SpecifierSet(">=1.0.0,!=1.0.1", prereleases=True).contains("1.3.0a1") + True + >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.3.0a1", prereleases=True) + True + """ + # Ensure that our item is a Version instance. + if not isinstance(item, Version): + item = Version(item) + + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # We can determine if we're going to allow pre-releases by looking to + # see if any of the underlying items supports them. If none of them do + # and this item is a pre-release then we do not allow it and we can + # short circuit that here. + # Note: This means that 1.0.dev1 would not be contained in something + # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0 + if not prereleases and item.is_prerelease: + return False + + if installed and item.is_prerelease: + item = Version(item.base_version) + + # We simply dispatch to the underlying specs here to make sure that the + # given version is contained within all of them. + # Note: This use of all() here means that an empty set of specifiers + # will always return True, this is an explicit design decision. + return all(s.contains(item, prereleases=prereleases) for s in self._specs) + + def filter( + self, iterable: Iterable[UnparsedVersionVar], prereleases: bool | None = None + ) -> Iterator[UnparsedVersionVar]: + """Filter items in the given iterable, that match the specifiers in this set. + + :param iterable: + An iterable that can contain version strings and :class:`Version` instances. + The items in the iterable will be filtered according to the specifier. + :param prereleases: + Whether or not to allow prereleases in the returned iterator. If set to + ``None`` (the default), it will be intelligently decide whether to allow + prereleases or not (based on the :attr:`prereleases` attribute, and + whether the only versions matching are prereleases). + + This method is smarter than just ``filter(SpecifierSet(...).contains, [...])`` + because it implements the rule from :pep:`440` that a prerelease item + SHOULD be accepted if no other versions match the given specifier. + + >>> list(SpecifierSet(">=1.2.3").filter(["1.2", "1.3", "1.5a1"])) + ['1.3'] + >>> list(SpecifierSet(">=1.2.3").filter(["1.2", "1.3", Version("1.4")])) + ['1.3', ] + >>> list(SpecifierSet(">=1.2.3").filter(["1.2", "1.5a1"])) + [] + >>> list(SpecifierSet(">=1.2.3").filter(["1.3", "1.5a1"], prereleases=True)) + ['1.3', '1.5a1'] + >>> list(SpecifierSet(">=1.2.3", prereleases=True).filter(["1.3", "1.5a1"])) + ['1.3', '1.5a1'] + + An "empty" SpecifierSet will filter items based on the presence of prerelease + versions in the set. + + >>> list(SpecifierSet("").filter(["1.3", "1.5a1"])) + ['1.3'] + >>> list(SpecifierSet("").filter(["1.5a1"])) + ['1.5a1'] + >>> list(SpecifierSet("", prereleases=True).filter(["1.3", "1.5a1"])) + ['1.3', '1.5a1'] + >>> list(SpecifierSet("").filter(["1.3", "1.5a1"], prereleases=True)) + ['1.3', '1.5a1'] + """ + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # If we have any specifiers, then we want to wrap our iterable in the + # filter method for each one, this will act as a logical AND amongst + # each specifier. + if self._specs: + for spec in self._specs: + iterable = spec.filter(iterable, prereleases=bool(prereleases)) + return iter(iterable) + # If we do not have any specifiers, then we need to have a rough filter + # which will filter out any pre-releases, unless there are no final + # releases. + else: + filtered: list[UnparsedVersionVar] = [] + found_prereleases: list[UnparsedVersionVar] = [] + + for item in iterable: + parsed_version = _coerce_version(item) + + # Store any item which is a pre-release for later unless we've + # already found a final version or we are accepting prereleases + if parsed_version.is_prerelease and not prereleases: + if not filtered: + found_prereleases.append(item) + else: + filtered.append(item) + + # If we've found no items except for pre-releases, then we'll go + # ahead and use the pre-releases + if not filtered and found_prereleases and prereleases is None: + return iter(found_prereleases) + + return iter(filtered) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/tags.py b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/tags.py new file mode 100644 index 0000000..703f0ed --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/tags.py @@ -0,0 +1,627 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import logging +import platform +import re +import struct +import subprocess +import sys +import sysconfig +from importlib.machinery import EXTENSION_SUFFIXES +from typing import ( + Iterable, + Iterator, + Sequence, + Tuple, + cast, +) + +from . import _manylinux, _musllinux + +logger = logging.getLogger(__name__) + +PythonVersion = Sequence[int] +AppleVersion = Tuple[int, int] + +INTERPRETER_SHORT_NAMES: dict[str, str] = { + "python": "py", # Generic. + "cpython": "cp", + "pypy": "pp", + "ironpython": "ip", + "jython": "jy", +} + + +_32_BIT_INTERPRETER = struct.calcsize("P") == 4 + + +class Tag: + """ + A representation of the tag triple for a wheel. + + Instances are considered immutable and thus are hashable. Equality checking + is also supported. + """ + + __slots__ = ["_interpreter", "_abi", "_platform", "_hash"] + + def __init__(self, interpreter: str, abi: str, platform: str) -> None: + self._interpreter = interpreter.lower() + self._abi = abi.lower() + self._platform = platform.lower() + # The __hash__ of every single element in a Set[Tag] will be evaluated each time + # that a set calls its `.disjoint()` method, which may be called hundreds of + # times when scanning a page of links for packages with tags matching that + # Set[Tag]. Pre-computing the value here produces significant speedups for + # downstream consumers. + self._hash = hash((self._interpreter, self._abi, self._platform)) + + @property + def interpreter(self) -> str: + return self._interpreter + + @property + def abi(self) -> str: + return self._abi + + @property + def platform(self) -> str: + return self._platform + + def __eq__(self, other: object) -> bool: + if not isinstance(other, Tag): + return NotImplemented + + return ( + (self._hash == other._hash) # Short-circuit ASAP for perf reasons. + and (self._platform == other._platform) + and (self._abi == other._abi) + and (self._interpreter == other._interpreter) + ) + + def __hash__(self) -> int: + return self._hash + + def __str__(self) -> str: + return f"{self._interpreter}-{self._abi}-{self._platform}" + + def __repr__(self) -> str: + return f"<{self} @ {id(self)}>" + + +def parse_tag(tag: str) -> frozenset[Tag]: + """ + Parses the provided tag (e.g. `py3-none-any`) into a frozenset of Tag instances. + + Returning a set is required due to the possibility that the tag is a + compressed tag set. + """ + tags = set() + interpreters, abis, platforms = tag.split("-") + for interpreter in interpreters.split("."): + for abi in abis.split("."): + for platform_ in platforms.split("."): + tags.add(Tag(interpreter, abi, platform_)) + return frozenset(tags) + + +def _get_config_var(name: str, warn: bool = False) -> int | str | None: + value: int | str | None = sysconfig.get_config_var(name) + if value is None and warn: + logger.debug( + "Config variable '%s' is unset, Python ABI tag may be incorrect", name + ) + return value + + +def _normalize_string(string: str) -> str: + return string.replace(".", "_").replace("-", "_").replace(" ", "_") + + +def _is_threaded_cpython(abis: list[str]) -> bool: + """ + Determine if the ABI corresponds to a threaded (`--disable-gil`) build. + + The threaded builds are indicated by a "t" in the abiflags. + """ + if len(abis) == 0: + return False + # expect e.g., cp313 + m = re.match(r"cp\d+(.*)", abis[0]) + if not m: + return False + abiflags = m.group(1) + return "t" in abiflags + + +def _abi3_applies(python_version: PythonVersion, threading: bool) -> bool: + """ + Determine if the Python version supports abi3. + + PEP 384 was first implemented in Python 3.2. The threaded (`--disable-gil`) + builds do not support abi3. + """ + return len(python_version) > 1 and tuple(python_version) >= (3, 2) and not threading + + +def _cpython_abis(py_version: PythonVersion, warn: bool = False) -> list[str]: + py_version = tuple(py_version) # To allow for version comparison. + abis = [] + version = _version_nodot(py_version[:2]) + threading = debug = pymalloc = ucs4 = "" + with_debug = _get_config_var("Py_DEBUG", warn) + has_refcount = hasattr(sys, "gettotalrefcount") + # Windows doesn't set Py_DEBUG, so checking for support of debug-compiled + # extension modules is the best option. + # https://github.com/pypa/pip/issues/3383#issuecomment-173267692 + has_ext = "_d.pyd" in EXTENSION_SUFFIXES + if with_debug or (with_debug is None and (has_refcount or has_ext)): + debug = "d" + if py_version >= (3, 13) and _get_config_var("Py_GIL_DISABLED", warn): + threading = "t" + if py_version < (3, 8): + with_pymalloc = _get_config_var("WITH_PYMALLOC", warn) + if with_pymalloc or with_pymalloc is None: + pymalloc = "m" + if py_version < (3, 3): + unicode_size = _get_config_var("Py_UNICODE_SIZE", warn) + if unicode_size == 4 or ( + unicode_size is None and sys.maxunicode == 0x10FFFF + ): + ucs4 = "u" + elif debug: + # Debug builds can also load "normal" extension modules. + # We can also assume no UCS-4 or pymalloc requirement. + abis.append(f"cp{version}{threading}") + abis.insert(0, f"cp{version}{threading}{debug}{pymalloc}{ucs4}") + return abis + + +def cpython_tags( + python_version: PythonVersion | None = None, + abis: Iterable[str] | None = None, + platforms: Iterable[str] | None = None, + *, + warn: bool = False, +) -> Iterator[Tag]: + """ + Yields the tags for a CPython interpreter. + + The tags consist of: + - cp-- + - cp-abi3- + - cp-none- + - cp-abi3- # Older Python versions down to 3.2. + + If python_version only specifies a major version then user-provided ABIs and + the 'none' ABItag will be used. + + If 'abi3' or 'none' are specified in 'abis' then they will be yielded at + their normal position and not at the beginning. + """ + if not python_version: + python_version = sys.version_info[:2] + + interpreter = f"cp{_version_nodot(python_version[:2])}" + + if abis is None: + if len(python_version) > 1: + abis = _cpython_abis(python_version, warn) + else: + abis = [] + abis = list(abis) + # 'abi3' and 'none' are explicitly handled later. + for explicit_abi in ("abi3", "none"): + try: + abis.remove(explicit_abi) + except ValueError: + pass + + platforms = list(platforms or platform_tags()) + for abi in abis: + for platform_ in platforms: + yield Tag(interpreter, abi, platform_) + + threading = _is_threaded_cpython(abis) + use_abi3 = _abi3_applies(python_version, threading) + if use_abi3: + yield from (Tag(interpreter, "abi3", platform_) for platform_ in platforms) + yield from (Tag(interpreter, "none", platform_) for platform_ in platforms) + + if use_abi3: + for minor_version in range(python_version[1] - 1, 1, -1): + for platform_ in platforms: + interpreter = "cp{version}".format( + version=_version_nodot((python_version[0], minor_version)) + ) + yield Tag(interpreter, "abi3", platform_) + + +def _generic_abi() -> list[str]: + """ + Return the ABI tag based on EXT_SUFFIX. + """ + # The following are examples of `EXT_SUFFIX`. + # We want to keep the parts which are related to the ABI and remove the + # parts which are related to the platform: + # - linux: '.cpython-310-x86_64-linux-gnu.so' => cp310 + # - mac: '.cpython-310-darwin.so' => cp310 + # - win: '.cp310-win_amd64.pyd' => cp310 + # - win: '.pyd' => cp37 (uses _cpython_abis()) + # - pypy: '.pypy38-pp73-x86_64-linux-gnu.so' => pypy38_pp73 + # - graalpy: '.graalpy-38-native-x86_64-darwin.dylib' + # => graalpy_38_native + + ext_suffix = _get_config_var("EXT_SUFFIX", warn=True) + if not isinstance(ext_suffix, str) or ext_suffix[0] != ".": + raise SystemError("invalid sysconfig.get_config_var('EXT_SUFFIX')") + parts = ext_suffix.split(".") + if len(parts) < 3: + # CPython3.7 and earlier uses ".pyd" on Windows. + return _cpython_abis(sys.version_info[:2]) + soabi = parts[1] + if soabi.startswith("cpython"): + # non-windows + abi = "cp" + soabi.split("-")[1] + elif soabi.startswith("cp"): + # windows + abi = soabi.split("-")[0] + elif soabi.startswith("pypy"): + abi = "-".join(soabi.split("-")[:2]) + elif soabi.startswith("graalpy"): + abi = "-".join(soabi.split("-")[:3]) + elif soabi: + # pyston, ironpython, others? + abi = soabi + else: + return [] + return [_normalize_string(abi)] + + +def generic_tags( + interpreter: str | None = None, + abis: Iterable[str] | None = None, + platforms: Iterable[str] | None = None, + *, + warn: bool = False, +) -> Iterator[Tag]: + """ + Yields the tags for a generic interpreter. + + The tags consist of: + - -- + + The "none" ABI will be added if it was not explicitly provided. + """ + if not interpreter: + interp_name = interpreter_name() + interp_version = interpreter_version(warn=warn) + interpreter = "".join([interp_name, interp_version]) + if abis is None: + abis = _generic_abi() + else: + abis = list(abis) + platforms = list(platforms or platform_tags()) + if "none" not in abis: + abis.append("none") + for abi in abis: + for platform_ in platforms: + yield Tag(interpreter, abi, platform_) + + +def _py_interpreter_range(py_version: PythonVersion) -> Iterator[str]: + """ + Yields Python versions in descending order. + + After the latest version, the major-only version will be yielded, and then + all previous versions of that major version. + """ + if len(py_version) > 1: + yield f"py{_version_nodot(py_version[:2])}" + yield f"py{py_version[0]}" + if len(py_version) > 1: + for minor in range(py_version[1] - 1, -1, -1): + yield f"py{_version_nodot((py_version[0], minor))}" + + +def compatible_tags( + python_version: PythonVersion | None = None, + interpreter: str | None = None, + platforms: Iterable[str] | None = None, +) -> Iterator[Tag]: + """ + Yields the sequence of tags that are compatible with a specific version of Python. + + The tags consist of: + - py*-none- + - -none-any # ... if `interpreter` is provided. + - py*-none-any + """ + if not python_version: + python_version = sys.version_info[:2] + platforms = list(platforms or platform_tags()) + for version in _py_interpreter_range(python_version): + for platform_ in platforms: + yield Tag(version, "none", platform_) + if interpreter: + yield Tag(interpreter, "none", "any") + for version in _py_interpreter_range(python_version): + yield Tag(version, "none", "any") + + +def _mac_arch(arch: str, is_32bit: bool = _32_BIT_INTERPRETER) -> str: + if not is_32bit: + return arch + + if arch.startswith("ppc"): + return "ppc" + + return "i386" + + +def _mac_binary_formats(version: AppleVersion, cpu_arch: str) -> list[str]: + formats = [cpu_arch] + if cpu_arch == "x86_64": + if version < (10, 4): + return [] + formats.extend(["intel", "fat64", "fat32"]) + + elif cpu_arch == "i386": + if version < (10, 4): + return [] + formats.extend(["intel", "fat32", "fat"]) + + elif cpu_arch == "ppc64": + # TODO: Need to care about 32-bit PPC for ppc64 through 10.2? + if version > (10, 5) or version < (10, 4): + return [] + formats.append("fat64") + + elif cpu_arch == "ppc": + if version > (10, 6): + return [] + formats.extend(["fat32", "fat"]) + + if cpu_arch in {"arm64", "x86_64"}: + formats.append("universal2") + + if cpu_arch in {"x86_64", "i386", "ppc64", "ppc", "intel"}: + formats.append("universal") + + return formats + + +def mac_platforms( + version: AppleVersion | None = None, arch: str | None = None +) -> Iterator[str]: + """ + Yields the platform tags for a macOS system. + + The `version` parameter is a two-item tuple specifying the macOS version to + generate platform tags for. The `arch` parameter is the CPU architecture to + generate platform tags for. Both parameters default to the appropriate value + for the current system. + """ + version_str, _, cpu_arch = platform.mac_ver() + if version is None: + version = cast("AppleVersion", tuple(map(int, version_str.split(".")[:2]))) + if version == (10, 16): + # When built against an older macOS SDK, Python will report macOS 10.16 + # instead of the real version. + version_str = subprocess.run( + [ + sys.executable, + "-sS", + "-c", + "import platform; print(platform.mac_ver()[0])", + ], + check=True, + env={"SYSTEM_VERSION_COMPAT": "0"}, + stdout=subprocess.PIPE, + text=True, + ).stdout + version = cast("AppleVersion", tuple(map(int, version_str.split(".")[:2]))) + else: + version = version + if arch is None: + arch = _mac_arch(cpu_arch) + else: + arch = arch + + if (10, 0) <= version and version < (11, 0): + # Prior to Mac OS 11, each yearly release of Mac OS bumped the + # "minor" version number. The major version was always 10. + for minor_version in range(version[1], -1, -1): + compat_version = 10, minor_version + binary_formats = _mac_binary_formats(compat_version, arch) + for binary_format in binary_formats: + yield "macosx_{major}_{minor}_{binary_format}".format( + major=10, minor=minor_version, binary_format=binary_format + ) + + if version >= (11, 0): + # Starting with Mac OS 11, each yearly release bumps the major version + # number. The minor versions are now the midyear updates. + for major_version in range(version[0], 10, -1): + compat_version = major_version, 0 + binary_formats = _mac_binary_formats(compat_version, arch) + for binary_format in binary_formats: + yield "macosx_{major}_{minor}_{binary_format}".format( + major=major_version, minor=0, binary_format=binary_format + ) + + if version >= (11, 0): + # Mac OS 11 on x86_64 is compatible with binaries from previous releases. + # Arm64 support was introduced in 11.0, so no Arm binaries from previous + # releases exist. + # + # However, the "universal2" binary format can have a + # macOS version earlier than 11.0 when the x86_64 part of the binary supports + # that version of macOS. + if arch == "x86_64": + for minor_version in range(16, 3, -1): + compat_version = 10, minor_version + binary_formats = _mac_binary_formats(compat_version, arch) + for binary_format in binary_formats: + yield "macosx_{major}_{minor}_{binary_format}".format( + major=compat_version[0], + minor=compat_version[1], + binary_format=binary_format, + ) + else: + for minor_version in range(16, 3, -1): + compat_version = 10, minor_version + binary_format = "universal2" + yield "macosx_{major}_{minor}_{binary_format}".format( + major=compat_version[0], + minor=compat_version[1], + binary_format=binary_format, + ) + + +def ios_platforms( + version: AppleVersion | None = None, multiarch: str | None = None +) -> Iterator[str]: + """ + Yields the platform tags for an iOS system. + + :param version: A two-item tuple specifying the iOS version to generate + platform tags for. Defaults to the current iOS version. + :param multiarch: The CPU architecture+ABI to generate platform tags for - + (the value used by `sys.implementation._multiarch` e.g., + `arm64_iphoneos` or `x84_64_iphonesimulator`). Defaults to the current + multiarch value. + """ + if version is None: + # if iOS is the current platform, ios_ver *must* be defined. However, + # it won't exist for CPython versions before 3.13, which causes a mypy + # error. + _, release, _, _ = platform.ios_ver() # type: ignore[attr-defined] + version = cast("AppleVersion", tuple(map(int, release.split(".")[:2]))) + + if multiarch is None: + multiarch = sys.implementation._multiarch + multiarch = multiarch.replace("-", "_") + + ios_platform_template = "ios_{major}_{minor}_{multiarch}" + + # Consider any iOS major.minor version from the version requested, down to + # 12.0. 12.0 is the first iOS version that is known to have enough features + # to support CPython. Consider every possible minor release up to X.9. There + # highest the minor has ever gone is 8 (14.8 and 15.8) but having some extra + # candidates that won't ever match doesn't really hurt, and it saves us from + # having to keep an explicit list of known iOS versions in the code. Return + # the results descending order of version number. + + # If the requested major version is less than 12, there won't be any matches. + if version[0] < 12: + return + + # Consider the actual X.Y version that was requested. + yield ios_platform_template.format( + major=version[0], minor=version[1], multiarch=multiarch + ) + + # Consider every minor version from X.0 to the minor version prior to the + # version requested by the platform. + for minor in range(version[1] - 1, -1, -1): + yield ios_platform_template.format( + major=version[0], minor=minor, multiarch=multiarch + ) + + for major in range(version[0] - 1, 11, -1): + for minor in range(9, -1, -1): + yield ios_platform_template.format( + major=major, minor=minor, multiarch=multiarch + ) + + +def _linux_platforms(is_32bit: bool = _32_BIT_INTERPRETER) -> Iterator[str]: + linux = _normalize_string(sysconfig.get_platform()) + if not linux.startswith("linux_"): + # we should never be here, just yield the sysconfig one and return + yield linux + return + if is_32bit: + if linux == "linux_x86_64": + linux = "linux_i686" + elif linux == "linux_aarch64": + linux = "linux_armv8l" + _, arch = linux.split("_", 1) + archs = {"armv8l": ["armv8l", "armv7l"]}.get(arch, [arch]) + yield from _manylinux.platform_tags(archs) + yield from _musllinux.platform_tags(archs) + for arch in archs: + yield f"linux_{arch}" + + +def _generic_platforms() -> Iterator[str]: + yield _normalize_string(sysconfig.get_platform()) + + +def platform_tags() -> Iterator[str]: + """ + Provides the platform tags for this installation. + """ + if platform.system() == "Darwin": + return mac_platforms() + elif platform.system() == "iOS": + return ios_platforms() + elif platform.system() == "Linux": + return _linux_platforms() + else: + return _generic_platforms() + + +def interpreter_name() -> str: + """ + Returns the name of the running interpreter. + + Some implementations have a reserved, two-letter abbreviation which will + be returned when appropriate. + """ + name = sys.implementation.name + return INTERPRETER_SHORT_NAMES.get(name) or name + + +def interpreter_version(*, warn: bool = False) -> str: + """ + Returns the version of the running interpreter. + """ + version = _get_config_var("py_version_nodot", warn=warn) + if version: + version = str(version) + else: + version = _version_nodot(sys.version_info[:2]) + return version + + +def _version_nodot(version: PythonVersion) -> str: + return "".join(map(str, version)) + + +def sys_tags(*, warn: bool = False) -> Iterator[Tag]: + """ + Returns the sequence of tag triples for the running interpreter. + + The order of the sequence corresponds to priority order for the + interpreter, from most to least important. + """ + + interp_name = interpreter_name() + if interp_name == "cp": + yield from cpython_tags(warn=warn) + else: + yield from generic_tags() + + if interp_name == "pp": + interp = "pp3" + elif interp_name == "cp": + interp = "cp" + interpreter_version(warn=warn) + else: + interp = None + yield from compatible_tags(interpreter=interp) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/utils.py b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/utils.py new file mode 100644 index 0000000..d33da5b --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/utils.py @@ -0,0 +1,174 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import re +from typing import NewType, Tuple, Union, cast + +from .tags import Tag, parse_tag +from .version import InvalidVersion, Version + +BuildTag = Union[Tuple[()], Tuple[int, str]] +NormalizedName = NewType("NormalizedName", str) + + +class InvalidName(ValueError): + """ + An invalid distribution name; users should refer to the packaging user guide. + """ + + +class InvalidWheelFilename(ValueError): + """ + An invalid wheel filename was found, users should refer to PEP 427. + """ + + +class InvalidSdistFilename(ValueError): + """ + An invalid sdist filename was found, users should refer to the packaging user guide. + """ + + +# Core metadata spec for `Name` +_validate_regex = re.compile( + r"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$", re.IGNORECASE +) +_canonicalize_regex = re.compile(r"[-_.]+") +_normalized_regex = re.compile(r"^([a-z0-9]|[a-z0-9]([a-z0-9-](?!--))*[a-z0-9])$") +# PEP 427: The build number must start with a digit. +_build_tag_regex = re.compile(r"(\d+)(.*)") + + +def canonicalize_name(name: str, *, validate: bool = False) -> NormalizedName: + if validate and not _validate_regex.match(name): + raise InvalidName(f"name is invalid: {name!r}") + # This is taken from PEP 503. + value = _canonicalize_regex.sub("-", name).lower() + return cast(NormalizedName, value) + + +def is_normalized_name(name: str) -> bool: + return _normalized_regex.match(name) is not None + + +def canonicalize_version( + version: Version | str, *, strip_trailing_zero: bool = True +) -> str: + """ + This is very similar to Version.__str__, but has one subtle difference + with the way it handles the release segment. + """ + if isinstance(version, str): + try: + parsed = Version(version) + except InvalidVersion: + # Legacy versions cannot be normalized + return version + else: + parsed = version + + parts = [] + + # Epoch + if parsed.epoch != 0: + parts.append(f"{parsed.epoch}!") + + # Release segment + release_segment = ".".join(str(x) for x in parsed.release) + if strip_trailing_zero: + # NB: This strips trailing '.0's to normalize + release_segment = re.sub(r"(\.0)+$", "", release_segment) + parts.append(release_segment) + + # Pre-release + if parsed.pre is not None: + parts.append("".join(str(x) for x in parsed.pre)) + + # Post-release + if parsed.post is not None: + parts.append(f".post{parsed.post}") + + # Development release + if parsed.dev is not None: + parts.append(f".dev{parsed.dev}") + + # Local version segment + if parsed.local is not None: + parts.append(f"+{parsed.local}") + + return "".join(parts) + + +def parse_wheel_filename( + filename: str, +) -> tuple[NormalizedName, Version, BuildTag, frozenset[Tag]]: + if not filename.endswith(".whl"): + raise InvalidWheelFilename( + f"Invalid wheel filename (extension must be '.whl'): {filename}" + ) + + filename = filename[:-4] + dashes = filename.count("-") + if dashes not in (4, 5): + raise InvalidWheelFilename( + f"Invalid wheel filename (wrong number of parts): {filename}" + ) + + parts = filename.split("-", dashes - 2) + name_part = parts[0] + # See PEP 427 for the rules on escaping the project name. + if "__" in name_part or re.match(r"^[\w\d._]*$", name_part, re.UNICODE) is None: + raise InvalidWheelFilename(f"Invalid project name: {filename}") + name = canonicalize_name(name_part) + + try: + version = Version(parts[1]) + except InvalidVersion as e: + raise InvalidWheelFilename( + f"Invalid wheel filename (invalid version): {filename}" + ) from e + + if dashes == 5: + build_part = parts[2] + build_match = _build_tag_regex.match(build_part) + if build_match is None: + raise InvalidWheelFilename( + f"Invalid build number: {build_part} in '{filename}'" + ) + build = cast(BuildTag, (int(build_match.group(1)), build_match.group(2))) + else: + build = () + tags = parse_tag(parts[-1]) + return (name, version, build, tags) + + +def parse_sdist_filename(filename: str) -> tuple[NormalizedName, Version]: + if filename.endswith(".tar.gz"): + file_stem = filename[: -len(".tar.gz")] + elif filename.endswith(".zip"): + file_stem = filename[: -len(".zip")] + else: + raise InvalidSdistFilename( + f"Invalid sdist filename (extension must be '.tar.gz' or '.zip'):" + f" {filename}" + ) + + # We are requiring a PEP 440 version, which cannot contain dashes, + # so we split on the last dash. + name_part, sep, version_part = file_stem.rpartition("-") + if not sep: + raise InvalidSdistFilename(f"Invalid sdist filename: {filename}") + + name = canonicalize_name(name_part) + + try: + version = Version(version_part) + except InvalidVersion as e: + raise InvalidSdistFilename( + f"Invalid sdist filename (invalid version): {filename}" + ) from e + + return (name, version) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/packaging/version.py b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/version.py new file mode 100644 index 0000000..8b0a040 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/packaging/version.py @@ -0,0 +1,563 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +""" +.. testsetup:: + + from pip._vendor.packaging.version import parse, Version +""" + +from __future__ import annotations + +import itertools +import re +from typing import Any, Callable, NamedTuple, SupportsInt, Tuple, Union + +from ._structures import Infinity, InfinityType, NegativeInfinity, NegativeInfinityType + +__all__ = ["VERSION_PATTERN", "parse", "Version", "InvalidVersion"] + +LocalType = Tuple[Union[int, str], ...] + +CmpPrePostDevType = Union[InfinityType, NegativeInfinityType, Tuple[str, int]] +CmpLocalType = Union[ + NegativeInfinityType, + Tuple[Union[Tuple[int, str], Tuple[NegativeInfinityType, Union[int, str]]], ...], +] +CmpKey = Tuple[ + int, + Tuple[int, ...], + CmpPrePostDevType, + CmpPrePostDevType, + CmpPrePostDevType, + CmpLocalType, +] +VersionComparisonMethod = Callable[[CmpKey, CmpKey], bool] + + +class _Version(NamedTuple): + epoch: int + release: tuple[int, ...] + dev: tuple[str, int] | None + pre: tuple[str, int] | None + post: tuple[str, int] | None + local: LocalType | None + + +def parse(version: str) -> Version: + """Parse the given version string. + + >>> parse('1.0.dev1') + + + :param version: The version string to parse. + :raises InvalidVersion: When the version string is not a valid version. + """ + return Version(version) + + +class InvalidVersion(ValueError): + """Raised when a version string is not a valid version. + + >>> Version("invalid") + Traceback (most recent call last): + ... + packaging.version.InvalidVersion: Invalid version: 'invalid' + """ + + +class _BaseVersion: + _key: tuple[Any, ...] + + def __hash__(self) -> int: + return hash(self._key) + + # Please keep the duplicated `isinstance` check + # in the six comparisons hereunder + # unless you find a way to avoid adding overhead function calls. + def __lt__(self, other: _BaseVersion) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key < other._key + + def __le__(self, other: _BaseVersion) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key <= other._key + + def __eq__(self, other: object) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key == other._key + + def __ge__(self, other: _BaseVersion) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key >= other._key + + def __gt__(self, other: _BaseVersion) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key > other._key + + def __ne__(self, other: object) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key != other._key + + +# Deliberately not anchored to the start and end of the string, to make it +# easier for 3rd party code to reuse +_VERSION_PATTERN = r""" + v? + (?: + (?:(?P[0-9]+)!)? # epoch + (?P[0-9]+(?:\.[0-9]+)*) # release segment + (?P

!I7S{BS4i1|@R7s@ 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/t64.exe b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/t64.exe new file mode 100644 index 0000000000000000000000000000000000000000..e8bebdba6d8f242244bf397ab067965d47c5093e GIT binary patch literal 108032 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%0AHbpwE%ZM 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 H#ex3;_fXA_ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/util.py b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/util.py new file mode 100644 index 0000000..0d5bd7a --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/util.py @@ -0,0 +1,1984 @@ +# +# Copyright (C) 2012-2023 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +import codecs +from collections import deque +import contextlib +import csv +from glob import iglob as std_iglob +import io +import json +import logging +import os +import py_compile +import re +import socket +try: + import ssl +except ImportError: # pragma: no cover + ssl = None +import subprocess +import sys +import tarfile +import tempfile +import textwrap + +try: + import threading +except ImportError: # pragma: no cover + import dummy_threading as threading +import time + +from . import DistlibException +from .compat import (string_types, text_type, shutil, raw_input, StringIO, cache_from_source, urlopen, urljoin, httplib, + xmlrpclib, HTTPHandler, BaseConfigurator, valid_ident, Container, configparser, URLError, ZipFile, + fsdecode, unquote, urlparse) + +logger = logging.getLogger(__name__) + +# +# Requirement parsing code as per PEP 508 +# + +IDENTIFIER = re.compile(r'^([\w\.-]+)\s*') +VERSION_IDENTIFIER = re.compile(r'^([\w\.*+-]+)\s*') +COMPARE_OP = re.compile(r'^(<=?|>=?|={2,3}|[~!]=)\s*') +MARKER_OP = re.compile(r'^((<=?)|(>=?)|={2,3}|[~!]=|in|not\s+in)\s*') +OR = re.compile(r'^or\b\s*') +AND = re.compile(r'^and\b\s*') +NON_SPACE = re.compile(r'(\S+)\s*') +STRING_CHUNK = re.compile(r'([\s\w\.{}()*+#:;,/?!~`@$%^&=|<>\[\]-]+)') + + +def parse_marker(marker_string): + """ + Parse a marker string and return a dictionary containing a marker expression. + + The dictionary will contain keys "op", "lhs" and "rhs" for non-terminals in + the expression grammar, or strings. A string contained in quotes is to be + interpreted as a literal string, and a string not contained in quotes is a + variable (such as os_name). + """ + + def marker_var(remaining): + # either identifier, or literal string + m = IDENTIFIER.match(remaining) + if m: + result = m.groups()[0] + remaining = remaining[m.end():] + elif not remaining: + raise SyntaxError('unexpected end of input') + else: + q = remaining[0] + if q not in '\'"': + raise SyntaxError('invalid expression: %s' % remaining) + oq = '\'"'.replace(q, '') + remaining = remaining[1:] + parts = [q] + while remaining: + # either a string chunk, or oq, or q to terminate + if remaining[0] == q: + break + elif remaining[0] == oq: + parts.append(oq) + remaining = remaining[1:] + else: + m = STRING_CHUNK.match(remaining) + if not m: + raise SyntaxError('error in string literal: %s' % remaining) + parts.append(m.groups()[0]) + remaining = remaining[m.end():] + else: + s = ''.join(parts) + raise SyntaxError('unterminated string: %s' % s) + parts.append(q) + result = ''.join(parts) + remaining = remaining[1:].lstrip() # skip past closing quote + return result, remaining + + def marker_expr(remaining): + if remaining and remaining[0] == '(': + result, remaining = marker(remaining[1:].lstrip()) + if remaining[0] != ')': + raise SyntaxError('unterminated parenthesis: %s' % remaining) + remaining = remaining[1:].lstrip() + else: + lhs, remaining = marker_var(remaining) + while remaining: + m = MARKER_OP.match(remaining) + if not m: + break + op = m.groups()[0] + remaining = remaining[m.end():] + rhs, remaining = marker_var(remaining) + lhs = {'op': op, 'lhs': lhs, 'rhs': rhs} + result = lhs + return result, remaining + + def marker_and(remaining): + lhs, remaining = marker_expr(remaining) + while remaining: + m = AND.match(remaining) + if not m: + break + remaining = remaining[m.end():] + rhs, remaining = marker_expr(remaining) + lhs = {'op': 'and', 'lhs': lhs, 'rhs': rhs} + return lhs, remaining + + def marker(remaining): + lhs, remaining = marker_and(remaining) + while remaining: + m = OR.match(remaining) + if not m: + break + remaining = remaining[m.end():] + rhs, remaining = marker_and(remaining) + lhs = {'op': 'or', 'lhs': lhs, 'rhs': rhs} + return lhs, remaining + + return marker(marker_string) + + +def parse_requirement(req): + """ + Parse a requirement passed in as a string. Return a Container + whose attributes contain the various parts of the requirement. + """ + remaining = req.strip() + if not remaining or remaining.startswith('#'): + return None + m = IDENTIFIER.match(remaining) + if not m: + raise SyntaxError('name expected: %s' % remaining) + distname = m.groups()[0] + remaining = remaining[m.end():] + extras = mark_expr = versions = uri = None + if remaining and remaining[0] == '[': + i = remaining.find(']', 1) + if i < 0: + raise SyntaxError('unterminated extra: %s' % remaining) + s = remaining[1:i] + remaining = remaining[i + 1:].lstrip() + extras = [] + while s: + m = IDENTIFIER.match(s) + if not m: + raise SyntaxError('malformed extra: %s' % s) + extras.append(m.groups()[0]) + s = s[m.end():] + if not s: + break + if s[0] != ',': + raise SyntaxError('comma expected in extras: %s' % s) + s = s[1:].lstrip() + if not extras: + extras = None + if remaining: + if remaining[0] == '@': + # it's a URI + remaining = remaining[1:].lstrip() + m = NON_SPACE.match(remaining) + if not m: + raise SyntaxError('invalid URI: %s' % remaining) + uri = m.groups()[0] + t = urlparse(uri) + # there are issues with Python and URL parsing, so this test + # is a bit crude. See bpo-20271, bpo-23505. Python doesn't + # always parse invalid URLs correctly - it should raise + # exceptions for malformed URLs + if not (t.scheme and t.netloc): + raise SyntaxError('Invalid URL: %s' % uri) + remaining = remaining[m.end():].lstrip() + else: + + def get_versions(ver_remaining): + """ + Return a list of operator, version tuples if any are + specified, else None. + """ + m = COMPARE_OP.match(ver_remaining) + versions = None + if m: + versions = [] + while True: + op = m.groups()[0] + ver_remaining = ver_remaining[m.end():] + m = VERSION_IDENTIFIER.match(ver_remaining) + if not m: + raise SyntaxError('invalid version: %s' % ver_remaining) + v = m.groups()[0] + versions.append((op, v)) + ver_remaining = ver_remaining[m.end():] + if not ver_remaining or ver_remaining[0] != ',': + break + ver_remaining = ver_remaining[1:].lstrip() + # Some packages have a trailing comma which would break things + # See issue #148 + if not ver_remaining: + break + m = COMPARE_OP.match(ver_remaining) + if not m: + raise SyntaxError('invalid constraint: %s' % ver_remaining) + if not versions: + versions = None + return versions, ver_remaining + + if remaining[0] != '(': + versions, remaining = get_versions(remaining) + else: + i = remaining.find(')', 1) + if i < 0: + raise SyntaxError('unterminated parenthesis: %s' % remaining) + s = remaining[1:i] + remaining = remaining[i + 1:].lstrip() + # As a special diversion from PEP 508, allow a version number + # a.b.c in parentheses as a synonym for ~= a.b.c (because this + # is allowed in earlier PEPs) + if COMPARE_OP.match(s): + versions, _ = get_versions(s) + else: + m = VERSION_IDENTIFIER.match(s) + if not m: + raise SyntaxError('invalid constraint: %s' % s) + v = m.groups()[0] + s = s[m.end():].lstrip() + if s: + raise SyntaxError('invalid constraint: %s' % s) + versions = [('~=', v)] + + if remaining: + if remaining[0] != ';': + raise SyntaxError('invalid requirement: %s' % remaining) + remaining = remaining[1:].lstrip() + + mark_expr, remaining = parse_marker(remaining) + + if remaining and remaining[0] != '#': + raise SyntaxError('unexpected trailing data: %s' % remaining) + + if not versions: + rs = distname + else: + rs = '%s %s' % (distname, ', '.join(['%s %s' % con for con in versions])) + return Container(name=distname, extras=extras, constraints=versions, marker=mark_expr, url=uri, requirement=rs) + + +def get_resources_dests(resources_root, rules): + """Find destinations for resources files""" + + def get_rel_path(root, path): + # normalizes and returns a lstripped-/-separated path + root = root.replace(os.path.sep, '/') + path = path.replace(os.path.sep, '/') + assert path.startswith(root) + return path[len(root):].lstrip('/') + + destinations = {} + for base, suffix, dest in rules: + prefix = os.path.join(resources_root, base) + for abs_base in iglob(prefix): + abs_glob = os.path.join(abs_base, suffix) + for abs_path in iglob(abs_glob): + resource_file = get_rel_path(resources_root, abs_path) + if dest is None: # remove the entry if it was here + destinations.pop(resource_file, None) + else: + rel_path = get_rel_path(abs_base, abs_path) + rel_dest = dest.replace(os.path.sep, '/').rstrip('/') + destinations[resource_file] = rel_dest + '/' + rel_path + return destinations + + +def in_venv(): + if hasattr(sys, 'real_prefix'): + # virtualenv venvs + result = True + else: + # PEP 405 venvs + result = sys.prefix != getattr(sys, 'base_prefix', sys.prefix) + return result + + +def get_executable(): + # The __PYVENV_LAUNCHER__ dance is apparently no longer needed, as + # changes to the stub launcher mean that sys.executable always points + # to the stub on OS X + # if sys.platform == 'darwin' and ('__PYVENV_LAUNCHER__' + # in os.environ): + # result = os.environ['__PYVENV_LAUNCHER__'] + # else: + # result = sys.executable + # return result + # Avoid normcasing: see issue #143 + # result = os.path.normcase(sys.executable) + result = sys.executable + if not isinstance(result, text_type): + result = fsdecode(result) + return result + + +def proceed(prompt, allowed_chars, error_prompt=None, default=None): + p = prompt + while True: + s = raw_input(p) + p = prompt + if not s and default: + s = default + if s: + c = s[0].lower() + if c in allowed_chars: + break + if error_prompt: + p = '%c: %s\n%s' % (c, error_prompt, prompt) + return c + + +def extract_by_key(d, keys): + if isinstance(keys, string_types): + keys = keys.split() + result = {} + for key in keys: + if key in d: + result[key] = d[key] + return result + + +def read_exports(stream): + if sys.version_info[0] >= 3: + # needs to be a text stream + stream = codecs.getreader('utf-8')(stream) + # Try to load as JSON, falling back on legacy format + data = stream.read() + stream = StringIO(data) + try: + jdata = json.load(stream) + result = jdata['extensions']['python.exports']['exports'] + for group, entries in result.items(): + for k, v in entries.items(): + s = '%s = %s' % (k, v) + entry = get_export_entry(s) + assert entry is not None + entries[k] = entry + return result + except Exception: + stream.seek(0, 0) + + def read_stream(cp, stream): + if hasattr(cp, 'read_file'): + cp.read_file(stream) + else: + cp.readfp(stream) + + cp = configparser.ConfigParser() + try: + read_stream(cp, stream) + except configparser.MissingSectionHeaderError: + stream.close() + data = textwrap.dedent(data) + stream = StringIO(data) + read_stream(cp, stream) + + result = {} + for key in cp.sections(): + result[key] = entries = {} + for name, value in cp.items(key): + s = '%s = %s' % (name, value) + entry = get_export_entry(s) + assert entry is not None + # entry.dist = self + entries[name] = entry + return result + + +def write_exports(exports, stream): + if sys.version_info[0] >= 3: + # needs to be a text stream + stream = codecs.getwriter('utf-8')(stream) + cp = configparser.ConfigParser() + for k, v in exports.items(): + # TODO check k, v for valid values + cp.add_section(k) + for entry in v.values(): + if entry.suffix is None: + s = entry.prefix + else: + s = '%s:%s' % (entry.prefix, entry.suffix) + if entry.flags: + s = '%s [%s]' % (s, ', '.join(entry.flags)) + cp.set(k, entry.name, s) + cp.write(stream) + + +@contextlib.contextmanager +def tempdir(): + td = tempfile.mkdtemp() + try: + yield td + finally: + shutil.rmtree(td) + + +@contextlib.contextmanager +def chdir(d): + cwd = os.getcwd() + try: + os.chdir(d) + yield + finally: + os.chdir(cwd) + + +@contextlib.contextmanager +def socket_timeout(seconds=15): + cto = socket.getdefaulttimeout() + try: + socket.setdefaulttimeout(seconds) + yield + finally: + socket.setdefaulttimeout(cto) + + +class cached_property(object): + + def __init__(self, func): + self.func = func + # for attr in ('__name__', '__module__', '__doc__'): + # setattr(self, attr, getattr(func, attr, None)) + + def __get__(self, obj, cls=None): + if obj is None: + return self + value = self.func(obj) + object.__setattr__(obj, self.func.__name__, value) + # obj.__dict__[self.func.__name__] = value = self.func(obj) + return value + + +def convert_path(pathname): + """Return 'pathname' as a name that will work on the native filesystem. + + The path is split on '/' and put back together again using the current + directory separator. Needed because filenames in the setup script are + always supplied in Unix style, and have to be converted to the local + convention before we can actually use them in the filesystem. Raises + ValueError on non-Unix-ish systems if 'pathname' either starts or + ends with a slash. + """ + if os.sep == '/': + return pathname + if not pathname: + return pathname + if pathname[0] == '/': + raise ValueError("path '%s' cannot be absolute" % pathname) + if pathname[-1] == '/': + raise ValueError("path '%s' cannot end with '/'" % pathname) + + paths = pathname.split('/') + while os.curdir in paths: + paths.remove(os.curdir) + if not paths: + return os.curdir + return os.path.join(*paths) + + +class FileOperator(object): + + def __init__(self, dry_run=False): + self.dry_run = dry_run + self.ensured = set() + self._init_record() + + def _init_record(self): + self.record = False + self.files_written = set() + self.dirs_created = set() + + def record_as_written(self, path): + if self.record: + self.files_written.add(path) + + def newer(self, source, target): + """Tell if the target is newer than the source. + + Returns true if 'source' exists and is more recently modified than + 'target', or if 'source' exists and 'target' doesn't. + + Returns false if both exist and 'target' is the same age or younger + than 'source'. Raise PackagingFileError if 'source' does not exist. + + Note that this test is not very accurate: files created in the same + second will have the same "age". + """ + if not os.path.exists(source): + raise DistlibException("file '%r' does not exist" % os.path.abspath(source)) + if not os.path.exists(target): + return True + + return os.stat(source).st_mtime > os.stat(target).st_mtime + + def copy_file(self, infile, outfile, check=True): + """Copy a file respecting dry-run and force flags. + """ + self.ensure_dir(os.path.dirname(outfile)) + logger.info('Copying %s to %s', infile, outfile) + if not self.dry_run: + msg = None + if check: + if os.path.islink(outfile): + msg = '%s is a symlink' % outfile + elif os.path.exists(outfile) and not os.path.isfile(outfile): + msg = '%s is a non-regular file' % outfile + if msg: + raise ValueError(msg + ' which would be overwritten') + shutil.copyfile(infile, outfile) + self.record_as_written(outfile) + + def copy_stream(self, instream, outfile, encoding=None): + assert not os.path.isdir(outfile) + self.ensure_dir(os.path.dirname(outfile)) + logger.info('Copying stream %s to %s', instream, outfile) + if not self.dry_run: + if encoding is None: + outstream = open(outfile, 'wb') + else: + outstream = codecs.open(outfile, 'w', encoding=encoding) + try: + shutil.copyfileobj(instream, outstream) + finally: + outstream.close() + self.record_as_written(outfile) + + def write_binary_file(self, path, data): + self.ensure_dir(os.path.dirname(path)) + if not self.dry_run: + if os.path.exists(path): + os.remove(path) + with open(path, 'wb') as f: + f.write(data) + self.record_as_written(path) + + def write_text_file(self, path, data, encoding): + self.write_binary_file(path, data.encode(encoding)) + + def set_mode(self, bits, mask, files): + if os.name == 'posix' or (os.name == 'java' and os._name == 'posix'): + # Set the executable bits (owner, group, and world) on + # all the files specified. + for f in files: + if self.dry_run: + logger.info("changing mode of %s", f) + else: + mode = (os.stat(f).st_mode | bits) & mask + logger.info("changing mode of %s to %o", f, mode) + os.chmod(f, mode) + + set_executable_mode = lambda s, f: s.set_mode(0o555, 0o7777, f) + + def ensure_dir(self, path): + path = os.path.abspath(path) + if path not in self.ensured and not os.path.exists(path): + self.ensured.add(path) + d, f = os.path.split(path) + self.ensure_dir(d) + logger.info('Creating %s' % path) + if not self.dry_run: + os.mkdir(path) + if self.record: + self.dirs_created.add(path) + + def byte_compile(self, path, optimize=False, force=False, prefix=None, hashed_invalidation=False): + dpath = cache_from_source(path, not optimize) + logger.info('Byte-compiling %s to %s', path, dpath) + if not self.dry_run: + if force or self.newer(path, dpath): + if not prefix: + diagpath = None + else: + assert path.startswith(prefix) + diagpath = path[len(prefix):] + compile_kwargs = {} + if hashed_invalidation and hasattr(py_compile, 'PycInvalidationMode'): + if not isinstance(hashed_invalidation, py_compile.PycInvalidationMode): + hashed_invalidation = py_compile.PycInvalidationMode.CHECKED_HASH + compile_kwargs['invalidation_mode'] = hashed_invalidation + py_compile.compile(path, dpath, diagpath, True, **compile_kwargs) # raise error + self.record_as_written(dpath) + return dpath + + def ensure_removed(self, path): + if os.path.exists(path): + if os.path.isdir(path) and not os.path.islink(path): + logger.debug('Removing directory tree at %s', path) + if not self.dry_run: + shutil.rmtree(path) + if self.record: + if path in self.dirs_created: + self.dirs_created.remove(path) + else: + if os.path.islink(path): + s = 'link' + else: + s = 'file' + logger.debug('Removing %s %s', s, path) + if not self.dry_run: + os.remove(path) + if self.record: + if path in self.files_written: + self.files_written.remove(path) + + def is_writable(self, path): + result = False + while not result: + if os.path.exists(path): + result = os.access(path, os.W_OK) + break + parent = os.path.dirname(path) + if parent == path: + break + path = parent + return result + + def commit(self): + """ + Commit recorded changes, turn off recording, return + changes. + """ + assert self.record + result = self.files_written, self.dirs_created + self._init_record() + return result + + def rollback(self): + if not self.dry_run: + for f in list(self.files_written): + if os.path.exists(f): + os.remove(f) + # dirs should all be empty now, except perhaps for + # __pycache__ subdirs + # reverse so that subdirs appear before their parents + dirs = sorted(self.dirs_created, reverse=True) + for d in dirs: + flist = os.listdir(d) + if flist: + assert flist == ['__pycache__'] + sd = os.path.join(d, flist[0]) + os.rmdir(sd) + os.rmdir(d) # should fail if non-empty + self._init_record() + + +def resolve(module_name, dotted_path): + if module_name in sys.modules: + mod = sys.modules[module_name] + else: + mod = __import__(module_name) + if dotted_path is None: + result = mod + else: + parts = dotted_path.split('.') + result = getattr(mod, parts.pop(0)) + for p in parts: + result = getattr(result, p) + return result + + +class ExportEntry(object): + + def __init__(self, name, prefix, suffix, flags): + self.name = name + self.prefix = prefix + self.suffix = suffix + self.flags = flags + + @cached_property + def value(self): + return resolve(self.prefix, self.suffix) + + def __repr__(self): # pragma: no cover + return '' % (self.name, self.prefix, self.suffix, self.flags) + + def __eq__(self, other): + if not isinstance(other, ExportEntry): + result = False + else: + result = (self.name == other.name and self.prefix == other.prefix and self.suffix == other.suffix and + self.flags == other.flags) + return result + + __hash__ = object.__hash__ + + +ENTRY_RE = re.compile( + r'''(?P([^\[]\S*)) + \s*=\s*(?P(\w+)([:\.]\w+)*) + \s*(\[\s*(?P[\w-]+(=\w+)?(,\s*\w+(=\w+)?)*)\s*\])? + ''', re.VERBOSE) + + +def get_export_entry(specification): + m = ENTRY_RE.search(specification) + if not m: + result = None + if '[' in specification or ']' in specification: + raise DistlibException("Invalid specification " + "'%s'" % specification) + else: + d = m.groupdict() + name = d['name'] + path = d['callable'] + colons = path.count(':') + if colons == 0: + prefix, suffix = path, None + else: + if colons != 1: + raise DistlibException("Invalid specification " + "'%s'" % specification) + prefix, suffix = path.split(':') + flags = d['flags'] + if flags is None: + if '[' in specification or ']' in specification: + raise DistlibException("Invalid specification " + "'%s'" % specification) + flags = [] + else: + flags = [f.strip() for f in flags.split(',')] + result = ExportEntry(name, prefix, suffix, flags) + return result + + +def get_cache_base(suffix=None): + """ + Return the default base location for distlib caches. If the directory does + not exist, it is created. Use the suffix provided for the base directory, + and default to '.distlib' if it isn't provided. + + On Windows, if LOCALAPPDATA is defined in the environment, then it is + assumed to be a directory, and will be the parent directory of the result. + On POSIX, and on Windows if LOCALAPPDATA is not defined, the user's home + directory - using os.expanduser('~') - will be the parent directory of + the result. + + The result is just the directory '.distlib' in the parent directory as + determined above, or with the name specified with ``suffix``. + """ + if suffix is None: + suffix = '.distlib' + if os.name == 'nt' and 'LOCALAPPDATA' in os.environ: + result = os.path.expandvars('$localappdata') + else: + # Assume posix, or old Windows + result = os.path.expanduser('~') + # we use 'isdir' instead of 'exists', because we want to + # fail if there's a file with that name + if os.path.isdir(result): + usable = os.access(result, os.W_OK) + if not usable: + logger.warning('Directory exists but is not writable: %s', result) + else: + try: + os.makedirs(result) + usable = True + except OSError: + logger.warning('Unable to create %s', result, exc_info=True) + usable = False + if not usable: + result = tempfile.mkdtemp() + logger.warning('Default location unusable, using %s', result) + return os.path.join(result, suffix) + + +def path_to_cache_dir(path, use_abspath=True): + """ + Convert an absolute path to a directory name for use in a cache. + + The algorithm used is: + + #. On Windows, any ``':'`` in the drive is replaced with ``'---'``. + #. Any occurrence of ``os.sep`` is replaced with ``'--'``. + #. ``'.cache'`` is appended. + """ + d, p = os.path.splitdrive(os.path.abspath(path) if use_abspath else path) + if d: + d = d.replace(':', '---') + p = p.replace(os.sep, '--') + return d + p + '.cache' + + +def ensure_slash(s): + if not s.endswith('/'): + return s + '/' + return s + + +def parse_credentials(netloc): + username = password = None + if '@' in netloc: + prefix, netloc = netloc.rsplit('@', 1) + if ':' not in prefix: + username = prefix + else: + username, password = prefix.split(':', 1) + if username: + username = unquote(username) + if password: + password = unquote(password) + return username, password, netloc + + +def get_process_umask(): + result = os.umask(0o22) + os.umask(result) + return result + + +def is_string_sequence(seq): + result = True + i = None + for i, s in enumerate(seq): + if not isinstance(s, string_types): + result = False + break + assert i is not None + return result + + +PROJECT_NAME_AND_VERSION = re.compile('([a-z0-9_]+([.-][a-z_][a-z0-9_]*)*)-' + '([a-z0-9_.+-]+)', re.I) +PYTHON_VERSION = re.compile(r'-py(\d\.?\d?)') + + +def split_filename(filename, project_name=None): + """ + Extract name, version, python version from a filename (no extension) + + Return name, version, pyver or None + """ + result = None + pyver = None + filename = unquote(filename).replace(' ', '-') + m = PYTHON_VERSION.search(filename) + if m: + pyver = m.group(1) + filename = filename[:m.start()] + if project_name and len(filename) > len(project_name) + 1: + m = re.match(re.escape(project_name) + r'\b', filename) + if m: + n = m.end() + result = filename[:n], filename[n + 1:], pyver + if result is None: + m = PROJECT_NAME_AND_VERSION.match(filename) + if m: + result = m.group(1), m.group(3), pyver + return result + + +# Allow spaces in name because of legacy dists like "Twisted Core" +NAME_VERSION_RE = re.compile(r'(?P[\w .-]+)\s*' + r'\(\s*(?P[^\s)]+)\)$') + + +def parse_name_and_version(p): + """ + A utility method used to get name and version from a string. + + From e.g. a Provides-Dist value. + + :param p: A value in a form 'foo (1.0)' + :return: The name and version as a tuple. + """ + m = NAME_VERSION_RE.match(p) + if not m: + raise DistlibException('Ill-formed name/version string: \'%s\'' % p) + d = m.groupdict() + return d['name'].strip().lower(), d['ver'] + + +def get_extras(requested, available): + result = set() + requested = set(requested or []) + available = set(available or []) + if '*' in requested: + requested.remove('*') + result |= available + for r in requested: + if r == '-': + result.add(r) + elif r.startswith('-'): + unwanted = r[1:] + if unwanted not in available: + logger.warning('undeclared extra: %s' % unwanted) + if unwanted in result: + result.remove(unwanted) + else: + if r not in available: + logger.warning('undeclared extra: %s' % r) + result.add(r) + return result + + +# +# Extended metadata functionality +# + + +def _get_external_data(url): + result = {} + try: + # urlopen might fail if it runs into redirections, + # because of Python issue #13696. Fixed in locators + # using a custom redirect handler. + resp = urlopen(url) + headers = resp.info() + ct = headers.get('Content-Type') + if not ct.startswith('application/json'): + logger.debug('Unexpected response for JSON request: %s', ct) + else: + reader = codecs.getreader('utf-8')(resp) + # data = reader.read().decode('utf-8') + # result = json.loads(data) + result = json.load(reader) + except Exception as e: + logger.exception('Failed to get external data for %s: %s', url, e) + return result + + +_external_data_base_url = 'https://www.red-dove.com/pypi/projects/' + + +def get_project_data(name): + url = '%s/%s/project.json' % (name[0].upper(), name) + url = urljoin(_external_data_base_url, url) + result = _get_external_data(url) + return result + + +def get_package_data(name, version): + url = '%s/%s/package-%s.json' % (name[0].upper(), name, version) + url = urljoin(_external_data_base_url, url) + return _get_external_data(url) + + +class Cache(object): + """ + A class implementing a cache for resources that need to live in the file system + e.g. shared libraries. This class was moved from resources to here because it + could be used by other modules, e.g. the wheel module. + """ + + def __init__(self, base): + """ + Initialise an instance. + + :param base: The base directory where the cache should be located. + """ + # we use 'isdir' instead of 'exists', because we want to + # fail if there's a file with that name + if not os.path.isdir(base): # pragma: no cover + os.makedirs(base) + if (os.stat(base).st_mode & 0o77) != 0: + logger.warning('Directory \'%s\' is not private', base) + self.base = os.path.abspath(os.path.normpath(base)) + + def prefix_to_dir(self, prefix, use_abspath=True): + """ + Converts a resource prefix to a directory name in the cache. + """ + return path_to_cache_dir(prefix, use_abspath=use_abspath) + + def clear(self): + """ + Clear the cache. + """ + not_removed = [] + for fn in os.listdir(self.base): + fn = os.path.join(self.base, fn) + try: + if os.path.islink(fn) or os.path.isfile(fn): + os.remove(fn) + elif os.path.isdir(fn): + shutil.rmtree(fn) + except Exception: + not_removed.append(fn) + return not_removed + + +class EventMixin(object): + """ + A very simple publish/subscribe system. + """ + + def __init__(self): + self._subscribers = {} + + def add(self, event, subscriber, append=True): + """ + Add a subscriber for an event. + + :param event: The name of an event. + :param subscriber: The subscriber to be added (and called when the + event is published). + :param append: Whether to append or prepend the subscriber to an + existing subscriber list for the event. + """ + subs = self._subscribers + if event not in subs: + subs[event] = deque([subscriber]) + else: + sq = subs[event] + if append: + sq.append(subscriber) + else: + sq.appendleft(subscriber) + + def remove(self, event, subscriber): + """ + Remove a subscriber for an event. + + :param event: The name of an event. + :param subscriber: The subscriber to be removed. + """ + subs = self._subscribers + if event not in subs: + raise ValueError('No subscribers: %r' % event) + subs[event].remove(subscriber) + + def get_subscribers(self, event): + """ + Return an iterator for the subscribers for an event. + :param event: The event to return subscribers for. + """ + return iter(self._subscribers.get(event, ())) + + def publish(self, event, *args, **kwargs): + """ + Publish a event and return a list of values returned by its + subscribers. + + :param event: The event to publish. + :param args: The positional arguments to pass to the event's + subscribers. + :param kwargs: The keyword arguments to pass to the event's + subscribers. + """ + result = [] + for subscriber in self.get_subscribers(event): + try: + value = subscriber(event, *args, **kwargs) + except Exception: + logger.exception('Exception during event publication') + value = None + result.append(value) + logger.debug('publish %s: args = %s, kwargs = %s, result = %s', event, args, kwargs, result) + return result + + +# +# Simple sequencing +# +class Sequencer(object): + + def __init__(self): + self._preds = {} + self._succs = {} + self._nodes = set() # nodes with no preds/succs + + def add_node(self, node): + self._nodes.add(node) + + def remove_node(self, node, edges=False): + if node in self._nodes: + self._nodes.remove(node) + if edges: + for p in set(self._preds.get(node, ())): + self.remove(p, node) + for s in set(self._succs.get(node, ())): + self.remove(node, s) + # Remove empties + for k, v in list(self._preds.items()): + if not v: + del self._preds[k] + for k, v in list(self._succs.items()): + if not v: + del self._succs[k] + + def add(self, pred, succ): + assert pred != succ + self._preds.setdefault(succ, set()).add(pred) + self._succs.setdefault(pred, set()).add(succ) + + def remove(self, pred, succ): + assert pred != succ + try: + preds = self._preds[succ] + succs = self._succs[pred] + except KeyError: # pragma: no cover + raise ValueError('%r not a successor of anything' % succ) + try: + preds.remove(pred) + succs.remove(succ) + except KeyError: # pragma: no cover + raise ValueError('%r not a successor of %r' % (succ, pred)) + + def is_step(self, step): + return (step in self._preds or step in self._succs or step in self._nodes) + + def get_steps(self, final): + if not self.is_step(final): + raise ValueError('Unknown: %r' % final) + result = [] + todo = [] + seen = set() + todo.append(final) + while todo: + step = todo.pop(0) + if step in seen: + # if a step was already seen, + # move it to the end (so it will appear earlier + # when reversed on return) ... but not for the + # final step, as that would be confusing for + # users + if step != final: + result.remove(step) + result.append(step) + else: + seen.add(step) + result.append(step) + preds = self._preds.get(step, ()) + todo.extend(preds) + return reversed(result) + + @property + def strong_connections(self): + # http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm + index_counter = [0] + stack = [] + lowlinks = {} + index = {} + result = [] + + graph = self._succs + + def strongconnect(node): + # set the depth index for this node to the smallest unused index + index[node] = index_counter[0] + lowlinks[node] = index_counter[0] + index_counter[0] += 1 + stack.append(node) + + # Consider successors + try: + successors = graph[node] + except Exception: + successors = [] + for successor in successors: + if successor not in lowlinks: + # Successor has not yet been visited + strongconnect(successor) + lowlinks[node] = min(lowlinks[node], lowlinks[successor]) + elif successor in stack: + # the successor is in the stack and hence in the current + # strongly connected component (SCC) + lowlinks[node] = min(lowlinks[node], index[successor]) + + # If `node` is a root node, pop the stack and generate an SCC + if lowlinks[node] == index[node]: + connected_component = [] + + while True: + successor = stack.pop() + connected_component.append(successor) + if successor == node: + break + component = tuple(connected_component) + # storing the result + result.append(component) + + for node in graph: + if node not in lowlinks: + strongconnect(node) + + return result + + @property + def dot(self): + result = ['digraph G {'] + for succ in self._preds: + preds = self._preds[succ] + for pred in preds: + result.append(' %s -> %s;' % (pred, succ)) + for node in self._nodes: + result.append(' %s;' % node) + result.append('}') + return '\n'.join(result) + + +# +# Unarchiving functionality for zip, tar, tgz, tbz, whl +# + +ARCHIVE_EXTENSIONS = ('.tar.gz', '.tar.bz2', '.tar', '.zip', '.tgz', '.tbz', '.whl') + + +def unarchive(archive_filename, dest_dir, format=None, check=True): + + def check_path(path): + if not isinstance(path, text_type): + path = path.decode('utf-8') + p = os.path.abspath(os.path.join(dest_dir, path)) + if not p.startswith(dest_dir) or p[plen] != os.sep: + raise ValueError('path outside destination: %r' % p) + + dest_dir = os.path.abspath(dest_dir) + plen = len(dest_dir) + archive = None + if format is None: + if archive_filename.endswith(('.zip', '.whl')): + format = 'zip' + elif archive_filename.endswith(('.tar.gz', '.tgz')): + format = 'tgz' + mode = 'r:gz' + elif archive_filename.endswith(('.tar.bz2', '.tbz')): + format = 'tbz' + mode = 'r:bz2' + elif archive_filename.endswith('.tar'): + format = 'tar' + mode = 'r' + else: # pragma: no cover + raise ValueError('Unknown format for %r' % archive_filename) + try: + if format == 'zip': + archive = ZipFile(archive_filename, 'r') + if check: + names = archive.namelist() + for name in names: + check_path(name) + else: + archive = tarfile.open(archive_filename, mode) + if check: + names = archive.getnames() + for name in names: + check_path(name) + if format != 'zip' and sys.version_info[0] < 3: + # See Python issue 17153. If the dest path contains Unicode, + # tarfile extraction fails on Python 2.x if a member path name + # contains non-ASCII characters - it leads to an implicit + # bytes -> unicode conversion using ASCII to decode. + for tarinfo in archive.getmembers(): + if not isinstance(tarinfo.name, text_type): + tarinfo.name = tarinfo.name.decode('utf-8') + + # Limit extraction of dangerous items, if this Python + # allows it easily. If not, just trust the input. + # See: https://docs.python.org/3/library/tarfile.html#extraction-filters + def extraction_filter(member, path): + """Run tarfile.tar_filter, but raise the expected ValueError""" + # This is only called if the current Python has tarfile filters + try: + return tarfile.tar_filter(member, path) + except tarfile.FilterError as exc: + raise ValueError(str(exc)) + + archive.extraction_filter = extraction_filter + + archive.extractall(dest_dir) + + finally: + if archive: + archive.close() + + +def zip_dir(directory): + """zip a directory tree into a BytesIO object""" + result = io.BytesIO() + dlen = len(directory) + with ZipFile(result, "w") as zf: + for root, dirs, files in os.walk(directory): + for name in files: + full = os.path.join(root, name) + rel = root[dlen:] + dest = os.path.join(rel, name) + zf.write(full, dest) + return result + + +# +# Simple progress bar +# + +UNITS = ('', 'K', 'M', 'G', 'T', 'P') + + +class Progress(object): + unknown = 'UNKNOWN' + + def __init__(self, minval=0, maxval=100): + assert maxval is None or maxval >= minval + self.min = self.cur = minval + self.max = maxval + self.started = None + self.elapsed = 0 + self.done = False + + def update(self, curval): + assert self.min <= curval + assert self.max is None or curval <= self.max + self.cur = curval + now = time.time() + if self.started is None: + self.started = now + else: + self.elapsed = now - self.started + + def increment(self, incr): + assert incr >= 0 + self.update(self.cur + incr) + + def start(self): + self.update(self.min) + return self + + def stop(self): + if self.max is not None: + self.update(self.max) + self.done = True + + @property + def maximum(self): + return self.unknown if self.max is None else self.max + + @property + def percentage(self): + if self.done: + result = '100 %' + elif self.max is None: + result = ' ?? %' + else: + v = 100.0 * (self.cur - self.min) / (self.max - self.min) + result = '%3d %%' % v + return result + + def format_duration(self, duration): + if (duration <= 0) and self.max is None or self.cur == self.min: + result = '??:??:??' + # elif duration < 1: + # result = '--:--:--' + else: + result = time.strftime('%H:%M:%S', time.gmtime(duration)) + return result + + @property + def ETA(self): + if self.done: + prefix = 'Done' + t = self.elapsed + # import pdb; pdb.set_trace() + else: + prefix = 'ETA ' + if self.max is None: + t = -1 + elif self.elapsed == 0 or (self.cur == self.min): + t = 0 + else: + # import pdb; pdb.set_trace() + t = float(self.max - self.min) + t /= self.cur - self.min + t = (t - 1) * self.elapsed + return '%s: %s' % (prefix, self.format_duration(t)) + + @property + def speed(self): + if self.elapsed == 0: + result = 0.0 + else: + result = (self.cur - self.min) / self.elapsed + for unit in UNITS: + if result < 1000: + break + result /= 1000.0 + return '%d %sB/s' % (result, unit) + + +# +# Glob functionality +# + +RICH_GLOB = re.compile(r'\{([^}]*)\}') +_CHECK_RECURSIVE_GLOB = re.compile(r'[^/\\,{]\*\*|\*\*[^/\\,}]') +_CHECK_MISMATCH_SET = re.compile(r'^[^{]*\}|\{[^}]*$') + + +def iglob(path_glob): + """Extended globbing function that supports ** and {opt1,opt2,opt3}.""" + if _CHECK_RECURSIVE_GLOB.search(path_glob): + msg = """invalid glob %r: recursive glob "**" must be used alone""" + raise ValueError(msg % path_glob) + if _CHECK_MISMATCH_SET.search(path_glob): + msg = """invalid glob %r: mismatching set marker '{' or '}'""" + raise ValueError(msg % path_glob) + return _iglob(path_glob) + + +def _iglob(path_glob): + rich_path_glob = RICH_GLOB.split(path_glob, 1) + if len(rich_path_glob) > 1: + assert len(rich_path_glob) == 3, rich_path_glob + prefix, set, suffix = rich_path_glob + for item in set.split(','): + for path in _iglob(''.join((prefix, item, suffix))): + yield path + else: + if '**' not in path_glob: + for item in std_iglob(path_glob): + yield item + else: + prefix, radical = path_glob.split('**', 1) + if prefix == '': + prefix = '.' + if radical == '': + radical = '*' + else: + # we support both + radical = radical.lstrip('/') + radical = radical.lstrip('\\') + for path, dir, files in os.walk(prefix): + path = os.path.normpath(path) + for fn in _iglob(os.path.join(path, radical)): + yield fn + + +if ssl: + from .compat import (HTTPSHandler as BaseHTTPSHandler, match_hostname, CertificateError) + + # + # HTTPSConnection which verifies certificates/matches domains + # + + class HTTPSConnection(httplib.HTTPSConnection): + ca_certs = None # set this to the path to the certs file (.pem) + check_domain = True # only used if ca_certs is not None + + # noinspection PyPropertyAccess + def connect(self): + sock = socket.create_connection((self.host, self.port), self.timeout) + if getattr(self, '_tunnel_host', False): + self.sock = sock + self._tunnel() + + context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + if hasattr(ssl, 'OP_NO_SSLv2'): + context.options |= ssl.OP_NO_SSLv2 + if getattr(self, 'cert_file', None): + context.load_cert_chain(self.cert_file, self.key_file) + kwargs = {} + if self.ca_certs: + context.verify_mode = ssl.CERT_REQUIRED + context.load_verify_locations(cafile=self.ca_certs) + if getattr(ssl, 'HAS_SNI', False): + kwargs['server_hostname'] = self.host + + self.sock = context.wrap_socket(sock, **kwargs) + if self.ca_certs and self.check_domain: + try: + match_hostname(self.sock.getpeercert(), self.host) + logger.debug('Host verified: %s', self.host) + except CertificateError: # pragma: no cover + self.sock.shutdown(socket.SHUT_RDWR) + self.sock.close() + raise + + class HTTPSHandler(BaseHTTPSHandler): + + def __init__(self, ca_certs, check_domain=True): + BaseHTTPSHandler.__init__(self) + self.ca_certs = ca_certs + self.check_domain = check_domain + + def _conn_maker(self, *args, **kwargs): + """ + This is called to create a connection instance. Normally you'd + pass a connection class to do_open, but it doesn't actually check for + a class, and just expects a callable. As long as we behave just as a + constructor would have, we should be OK. If it ever changes so that + we *must* pass a class, we'll create an UnsafeHTTPSConnection class + which just sets check_domain to False in the class definition, and + choose which one to pass to do_open. + """ + result = HTTPSConnection(*args, **kwargs) + if self.ca_certs: + result.ca_certs = self.ca_certs + result.check_domain = self.check_domain + return result + + def https_open(self, req): + try: + return self.do_open(self._conn_maker, req) + except URLError as e: + if 'certificate verify failed' in str(e.reason): + raise CertificateError('Unable to verify server certificate ' + 'for %s' % req.host) + else: + raise + + # + # To prevent against mixing HTTP traffic with HTTPS (examples: A Man-In-The- + # Middle proxy using HTTP listens on port 443, or an index mistakenly serves + # HTML containing a http://xyz link when it should be https://xyz), + # you can use the following handler class, which does not allow HTTP traffic. + # + # It works by inheriting from HTTPHandler - so build_opener won't add a + # handler for HTTP itself. + # + class HTTPSOnlyHandler(HTTPSHandler, HTTPHandler): + + def http_open(self, req): + raise URLError('Unexpected HTTP request on what should be a secure ' + 'connection: %s' % req) + + +# +# XML-RPC with timeouts +# +class Transport(xmlrpclib.Transport): + + def __init__(self, timeout, use_datetime=0): + self.timeout = timeout + xmlrpclib.Transport.__init__(self, use_datetime) + + def make_connection(self, host): + h, eh, x509 = self.get_host_info(host) + if not self._connection or host != self._connection[0]: + self._extra_headers = eh + self._connection = host, httplib.HTTPConnection(h) + return self._connection[1] + + +if ssl: + + class SafeTransport(xmlrpclib.SafeTransport): + + def __init__(self, timeout, use_datetime=0): + self.timeout = timeout + xmlrpclib.SafeTransport.__init__(self, use_datetime) + + def make_connection(self, host): + h, eh, kwargs = self.get_host_info(host) + if not kwargs: + kwargs = {} + kwargs['timeout'] = self.timeout + if not self._connection or host != self._connection[0]: + self._extra_headers = eh + self._connection = host, httplib.HTTPSConnection(h, None, **kwargs) + return self._connection[1] + + +class ServerProxy(xmlrpclib.ServerProxy): + + def __init__(self, uri, **kwargs): + self.timeout = timeout = kwargs.pop('timeout', None) + # The above classes only come into play if a timeout + # is specified + if timeout is not None: + # scheme = splittype(uri) # deprecated as of Python 3.8 + scheme = urlparse(uri)[0] + use_datetime = kwargs.get('use_datetime', 0) + if scheme == 'https': + tcls = SafeTransport + else: + tcls = Transport + kwargs['transport'] = t = tcls(timeout, use_datetime=use_datetime) + self.transport = t + xmlrpclib.ServerProxy.__init__(self, uri, **kwargs) + + +# +# CSV functionality. This is provided because on 2.x, the csv module can't +# handle Unicode. However, we need to deal with Unicode in e.g. RECORD files. +# + + +def _csv_open(fn, mode, **kwargs): + if sys.version_info[0] < 3: + mode += 'b' + else: + kwargs['newline'] = '' + # Python 3 determines encoding from locale. Force 'utf-8' + # file encoding to match other forced utf-8 encoding + kwargs['encoding'] = 'utf-8' + return open(fn, mode, **kwargs) + + +class CSVBase(object): + defaults = { + 'delimiter': str(','), # The strs are used because we need native + 'quotechar': str('"'), # str in the csv API (2.x won't take + 'lineterminator': str('\n') # Unicode) + } + + def __enter__(self): + return self + + def __exit__(self, *exc_info): + self.stream.close() + + +class CSVReader(CSVBase): + + def __init__(self, **kwargs): + if 'stream' in kwargs: + stream = kwargs['stream'] + if sys.version_info[0] >= 3: + # needs to be a text stream + stream = codecs.getreader('utf-8')(stream) + self.stream = stream + else: + self.stream = _csv_open(kwargs['path'], 'r') + self.reader = csv.reader(self.stream, **self.defaults) + + def __iter__(self): + return self + + def next(self): + result = next(self.reader) + if sys.version_info[0] < 3: + for i, item in enumerate(result): + if not isinstance(item, text_type): + result[i] = item.decode('utf-8') + return result + + __next__ = next + + +class CSVWriter(CSVBase): + + def __init__(self, fn, **kwargs): + self.stream = _csv_open(fn, 'w') + self.writer = csv.writer(self.stream, **self.defaults) + + def writerow(self, row): + if sys.version_info[0] < 3: + r = [] + for item in row: + if isinstance(item, text_type): + item = item.encode('utf-8') + r.append(item) + row = r + self.writer.writerow(row) + + +# +# Configurator functionality +# + + +class Configurator(BaseConfigurator): + + value_converters = dict(BaseConfigurator.value_converters) + value_converters['inc'] = 'inc_convert' + + def __init__(self, config, base=None): + super(Configurator, self).__init__(config) + self.base = base or os.getcwd() + + def configure_custom(self, config): + + def convert(o): + if isinstance(o, (list, tuple)): + result = type(o)([convert(i) for i in o]) + elif isinstance(o, dict): + if '()' in o: + result = self.configure_custom(o) + else: + result = {} + for k in o: + result[k] = convert(o[k]) + else: + result = self.convert(o) + return result + + c = config.pop('()') + if not callable(c): + c = self.resolve(c) + props = config.pop('.', None) + # Check for valid identifiers + args = config.pop('[]', ()) + if args: + args = tuple([convert(o) for o in args]) + items = [(k, convert(config[k])) for k in config if valid_ident(k)] + kwargs = dict(items) + result = c(*args, **kwargs) + if props: + for n, v in props.items(): + setattr(result, n, convert(v)) + return result + + def __getitem__(self, key): + result = self.config[key] + if isinstance(result, dict) and '()' in result: + self.config[key] = result = self.configure_custom(result) + return result + + def inc_convert(self, value): + """Default converter for the inc:// protocol.""" + if not os.path.isabs(value): + value = os.path.join(self.base, value) + with codecs.open(value, 'r', encoding='utf-8') as f: + result = json.load(f) + return result + + +class SubprocessMixin(object): + """ + Mixin for running subprocesses and capturing their output + """ + + def __init__(self, verbose=False, progress=None): + self.verbose = verbose + self.progress = progress + + def reader(self, stream, context): + """ + Read lines from a subprocess' output stream and either pass to a progress + callable (if specified) or write progress information to sys.stderr. + """ + progress = self.progress + verbose = self.verbose + while True: + s = stream.readline() + if not s: + break + if progress is not None: + progress(s, context) + else: + if not verbose: + sys.stderr.write('.') + else: + sys.stderr.write(s.decode('utf-8')) + sys.stderr.flush() + stream.close() + + def run_command(self, cmd, **kwargs): + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs) + t1 = threading.Thread(target=self.reader, args=(p.stdout, 'stdout')) + t1.start() + t2 = threading.Thread(target=self.reader, args=(p.stderr, 'stderr')) + t2.start() + p.wait() + t1.join() + t2.join() + if self.progress is not None: + self.progress('done.', 'main') + elif self.verbose: + sys.stderr.write('done.\n') + return p + + +def normalize_name(name): + """Normalize a python package name a la PEP 503""" + # https://www.python.org/dev/peps/pep-0503/#normalized-names + return re.sub('[-_.]+', '-', name).lower() + + +# def _get_pypirc_command(): +# """ +# Get the distutils command for interacting with PyPI configurations. +# :return: the command. +# """ +# from distutils.core import Distribution +# from distutils.config import PyPIRCCommand +# d = Distribution() +# return PyPIRCCommand(d) + + +class PyPIRCFile(object): + + DEFAULT_REPOSITORY = 'https://upload.pypi.org/legacy/' + DEFAULT_REALM = 'pypi' + + def __init__(self, fn=None, url=None): + if fn is None: + fn = os.path.join(os.path.expanduser('~'), '.pypirc') + self.filename = fn + self.url = url + + def read(self): + result = {} + + if os.path.exists(self.filename): + repository = self.url or self.DEFAULT_REPOSITORY + + config = configparser.RawConfigParser() + config.read(self.filename) + sections = config.sections() + if 'distutils' in sections: + # let's get the list of servers + index_servers = config.get('distutils', 'index-servers') + _servers = [server.strip() for server in index_servers.split('\n') if server.strip() != ''] + if _servers == []: + # nothing set, let's try to get the default pypi + if 'pypi' in sections: + _servers = ['pypi'] + else: + for server in _servers: + result = {'server': server} + result['username'] = config.get(server, 'username') + + # optional params + for key, default in (('repository', self.DEFAULT_REPOSITORY), ('realm', self.DEFAULT_REALM), + ('password', None)): + if config.has_option(server, key): + result[key] = config.get(server, key) + else: + result[key] = default + + # work around people having "repository" for the "pypi" + # section of their config set to the HTTP (rather than + # HTTPS) URL + if (server == 'pypi' and repository in (self.DEFAULT_REPOSITORY, 'pypi')): + result['repository'] = self.DEFAULT_REPOSITORY + elif (result['server'] != repository and result['repository'] != repository): + result = {} + elif 'server-login' in sections: + # old format + server = 'server-login' + if config.has_option(server, 'repository'): + repository = config.get(server, 'repository') + else: + repository = self.DEFAULT_REPOSITORY + result = { + 'username': config.get(server, 'username'), + 'password': config.get(server, 'password'), + 'repository': repository, + 'server': server, + 'realm': self.DEFAULT_REALM + } + return result + + def update(self, username, password): + # import pdb; pdb.set_trace() + config = configparser.RawConfigParser() + fn = self.filename + config.read(fn) + if not config.has_section('pypi'): + config.add_section('pypi') + config.set('pypi', 'username', username) + config.set('pypi', 'password', password) + with open(fn, 'w') as f: + config.write(f) + + +def _load_pypirc(index): + """ + Read the PyPI access configuration as supported by distutils. + """ + return PyPIRCFile(url=index.url).read() + + +def _store_pypirc(index): + PyPIRCFile().update(index.username, index.password) + + +# +# get_platform()/get_host_platform() copied from Python 3.10.a0 source, with some minor +# tweaks +# + + +def get_host_platform(): + """Return a string that identifies the current platform. This is used mainly to + distinguish platform-specific build directories and platform-specific built + distributions. Typically includes the OS name and version and the + architecture (as supplied by 'os.uname()'), although the exact information + included depends on the OS; eg. on Linux, the kernel version isn't + particularly important. + + Examples of returned values: + linux-i586 + linux-alpha (?) + solaris-2.6-sun4u + + Windows will return one of: + win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc) + win32 (all others - specifically, sys.platform is returned) + + For other non-POSIX platforms, currently just returns 'sys.platform'. + + """ + if os.name == 'nt': + if 'amd64' in sys.version.lower(): + return 'win-amd64' + if '(arm)' in sys.version.lower(): + return 'win-arm32' + if '(arm64)' in sys.version.lower(): + return 'win-arm64' + return sys.platform + + # Set for cross builds explicitly + if "_PYTHON_HOST_PLATFORM" in os.environ: + return os.environ["_PYTHON_HOST_PLATFORM"] + + if os.name != 'posix' or not hasattr(os, 'uname'): + # XXX what about the architecture? NT is Intel or Alpha, + # Mac OS is M68k or PPC, etc. + return sys.platform + + # Try to distinguish various flavours of Unix + + (osname, host, release, version, machine) = os.uname() + + # Convert the OS name to lowercase, remove '/' characters, and translate + # spaces (for "Power Macintosh") + osname = osname.lower().replace('/', '') + machine = machine.replace(' ', '_').replace('/', '-') + + if osname[:5] == 'linux': + # At least on Linux/Intel, 'machine' is the processor -- + # i386, etc. + # XXX what about Alpha, SPARC, etc? + return "%s-%s" % (osname, machine) + + elif osname[:5] == 'sunos': + if release[0] >= '5': # SunOS 5 == Solaris 2 + osname = 'solaris' + release = '%d.%s' % (int(release[0]) - 3, release[2:]) + # We can't use 'platform.architecture()[0]' because a + # bootstrap problem. We use a dict to get an error + # if some suspicious happens. + bitness = {2147483647: '32bit', 9223372036854775807: '64bit'} + machine += '.%s' % bitness[sys.maxsize] + # fall through to standard osname-release-machine representation + elif osname[:3] == 'aix': + from _aix_support import aix_platform + return aix_platform() + elif osname[:6] == 'cygwin': + osname = 'cygwin' + rel_re = re.compile(r'[\d.]+', re.ASCII) + m = rel_re.match(release) + if m: + release = m.group() + elif osname[:6] == 'darwin': + import _osx_support + try: + from distutils import sysconfig + except ImportError: + import sysconfig + osname, release, machine = _osx_support.get_platform_osx(sysconfig.get_config_vars(), osname, release, machine) + + return '%s-%s-%s' % (osname, release, machine) + + +_TARGET_TO_PLAT = { + 'x86': 'win32', + 'x64': 'win-amd64', + 'arm': 'win-arm32', +} + + +def get_platform(): + if os.name != 'nt': + return get_host_platform() + cross_compilation_target = os.environ.get('VSCMD_ARG_TGT_ARCH') + if cross_compilation_target not in _TARGET_TO_PLAT: + return get_host_platform() + return _TARGET_TO_PLAT[cross_compilation_target] diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/version.py b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/version.py new file mode 100644 index 0000000..d70a96e --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/version.py @@ -0,0 +1,750 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2023 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +""" +Implementation of a flexible versioning scheme providing support for PEP-440, +setuptools-compatible and semantic versioning. +""" + +import logging +import re + +from .compat import string_types +from .util import parse_requirement + +__all__ = ['NormalizedVersion', 'NormalizedMatcher', + 'LegacyVersion', 'LegacyMatcher', + 'SemanticVersion', 'SemanticMatcher', + 'UnsupportedVersionError', 'get_scheme'] + +logger = logging.getLogger(__name__) + + +class UnsupportedVersionError(ValueError): + """This is an unsupported version.""" + pass + + +class Version(object): + def __init__(self, s): + self._string = s = s.strip() + self._parts = parts = self.parse(s) + assert isinstance(parts, tuple) + assert len(parts) > 0 + + def parse(self, s): + raise NotImplementedError('please implement in a subclass') + + def _check_compatible(self, other): + if type(self) != type(other): + raise TypeError('cannot compare %r and %r' % (self, other)) + + def __eq__(self, other): + self._check_compatible(other) + return self._parts == other._parts + + def __ne__(self, other): + return not self.__eq__(other) + + def __lt__(self, other): + self._check_compatible(other) + return self._parts < other._parts + + def __gt__(self, other): + return not (self.__lt__(other) or self.__eq__(other)) + + def __le__(self, other): + return self.__lt__(other) or self.__eq__(other) + + def __ge__(self, other): + return self.__gt__(other) or self.__eq__(other) + + # See http://docs.python.org/reference/datamodel#object.__hash__ + def __hash__(self): + return hash(self._parts) + + def __repr__(self): + return "%s('%s')" % (self.__class__.__name__, self._string) + + def __str__(self): + return self._string + + @property + def is_prerelease(self): + raise NotImplementedError('Please implement in subclasses.') + + +class Matcher(object): + version_class = None + + # value is either a callable or the name of a method + _operators = { + '<': lambda v, c, p: v < c, + '>': lambda v, c, p: v > c, + '<=': lambda v, c, p: v == c or v < c, + '>=': lambda v, c, p: v == c or v > c, + '==': lambda v, c, p: v == c, + '===': lambda v, c, p: v == c, + # by default, compatible => >=. + '~=': lambda v, c, p: v == c or v > c, + '!=': lambda v, c, p: v != c, + } + + # this is a method only to support alternative implementations + # via overriding + def parse_requirement(self, s): + return parse_requirement(s) + + def __init__(self, s): + if self.version_class is None: + raise ValueError('Please specify a version class') + self._string = s = s.strip() + r = self.parse_requirement(s) + if not r: + raise ValueError('Not valid: %r' % s) + self.name = r.name + self.key = self.name.lower() # for case-insensitive comparisons + clist = [] + if r.constraints: + # import pdb; pdb.set_trace() + for op, s in r.constraints: + if s.endswith('.*'): + if op not in ('==', '!='): + raise ValueError('\'.*\' not allowed for ' + '%r constraints' % op) + # Could be a partial version (e.g. for '2.*') which + # won't parse as a version, so keep it as a string + vn, prefix = s[:-2], True + # Just to check that vn is a valid version + self.version_class(vn) + else: + # Should parse as a version, so we can create an + # instance for the comparison + vn, prefix = self.version_class(s), False + clist.append((op, vn, prefix)) + self._parts = tuple(clist) + + def match(self, version): + """ + Check if the provided version matches the constraints. + + :param version: The version to match against this instance. + :type version: String or :class:`Version` instance. + """ + if isinstance(version, string_types): + version = self.version_class(version) + for operator, constraint, prefix in self._parts: + f = self._operators.get(operator) + if isinstance(f, string_types): + f = getattr(self, f) + if not f: + msg = ('%r not implemented ' + 'for %s' % (operator, self.__class__.__name__)) + raise NotImplementedError(msg) + if not f(version, constraint, prefix): + return False + return True + + @property + def exact_version(self): + result = None + if len(self._parts) == 1 and self._parts[0][0] in ('==', '==='): + result = self._parts[0][1] + return result + + def _check_compatible(self, other): + if type(self) != type(other) or self.name != other.name: + raise TypeError('cannot compare %s and %s' % (self, other)) + + def __eq__(self, other): + self._check_compatible(other) + return self.key == other.key and self._parts == other._parts + + def __ne__(self, other): + return not self.__eq__(other) + + # See http://docs.python.org/reference/datamodel#object.__hash__ + def __hash__(self): + return hash(self.key) + hash(self._parts) + + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self._string) + + def __str__(self): + return self._string + + +PEP440_VERSION_RE = re.compile(r'^v?(\d+!)?(\d+(\.\d+)*)((a|alpha|b|beta|c|rc|pre|preview)(\d+)?)?' + r'(\.(post|r|rev)(\d+)?)?([._-]?(dev)(\d+)?)?' + r'(\+([a-zA-Z\d]+(\.[a-zA-Z\d]+)?))?$', re.I) + + +def _pep_440_key(s): + s = s.strip() + m = PEP440_VERSION_RE.match(s) + if not m: + raise UnsupportedVersionError('Not a valid version: %s' % s) + groups = m.groups() + nums = tuple(int(v) for v in groups[1].split('.')) + while len(nums) > 1 and nums[-1] == 0: + nums = nums[:-1] + + if not groups[0]: + epoch = 0 + else: + epoch = int(groups[0][:-1]) + pre = groups[4:6] + post = groups[7:9] + dev = groups[10:12] + local = groups[13] + if pre == (None, None): + pre = () + else: + if pre[1] is None: + pre = pre[0], 0 + else: + pre = pre[0], int(pre[1]) + if post == (None, None): + post = () + else: + if post[1] is None: + post = post[0], 0 + else: + post = post[0], int(post[1]) + if dev == (None, None): + dev = () + else: + if dev[1] is None: + dev = dev[0], 0 + else: + dev = dev[0], int(dev[1]) + if local is None: + local = () + else: + parts = [] + for part in local.split('.'): + # to ensure that numeric compares as > lexicographic, avoid + # comparing them directly, but encode a tuple which ensures + # correct sorting + if part.isdigit(): + part = (1, int(part)) + else: + part = (0, part) + parts.append(part) + local = tuple(parts) + if not pre: + # either before pre-release, or final release and after + if not post and dev: + # before pre-release + pre = ('a', -1) # to sort before a0 + else: + pre = ('z',) # to sort after all pre-releases + # now look at the state of post and dev. + if not post: + post = ('_',) # sort before 'a' + if not dev: + dev = ('final',) + + return epoch, nums, pre, post, dev, local + + +_normalized_key = _pep_440_key + + +class NormalizedVersion(Version): + """A rational version. + + Good: + 1.2 # equivalent to "1.2.0" + 1.2.0 + 1.2a1 + 1.2.3a2 + 1.2.3b1 + 1.2.3c1 + 1.2.3.4 + TODO: fill this out + + Bad: + 1 # minimum two numbers + 1.2a # release level must have a release serial + 1.2.3b + """ + def parse(self, s): + result = _normalized_key(s) + # _normalized_key loses trailing zeroes in the release + # clause, since that's needed to ensure that X.Y == X.Y.0 == X.Y.0.0 + # However, PEP 440 prefix matching needs it: for example, + # (~= 1.4.5.0) matches differently to (~= 1.4.5.0.0). + m = PEP440_VERSION_RE.match(s) # must succeed + groups = m.groups() + self._release_clause = tuple(int(v) for v in groups[1].split('.')) + return result + + PREREL_TAGS = set(['a', 'b', 'c', 'rc', 'dev']) + + @property + def is_prerelease(self): + return any(t[0] in self.PREREL_TAGS for t in self._parts if t) + + +def _match_prefix(x, y): + x = str(x) + y = str(y) + if x == y: + return True + if not x.startswith(y): + return False + n = len(y) + return x[n] == '.' + + +class NormalizedMatcher(Matcher): + version_class = NormalizedVersion + + # value is either a callable or the name of a method + _operators = { + '~=': '_match_compatible', + '<': '_match_lt', + '>': '_match_gt', + '<=': '_match_le', + '>=': '_match_ge', + '==': '_match_eq', + '===': '_match_arbitrary', + '!=': '_match_ne', + } + + def _adjust_local(self, version, constraint, prefix): + if prefix: + strip_local = '+' not in constraint and version._parts[-1] + else: + # both constraint and version are + # NormalizedVersion instances. + # If constraint does not have a local component, + # ensure the version doesn't, either. + strip_local = not constraint._parts[-1] and version._parts[-1] + if strip_local: + s = version._string.split('+', 1)[0] + version = self.version_class(s) + return version, constraint + + def _match_lt(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if version >= constraint: + return False + release_clause = constraint._release_clause + pfx = '.'.join([str(i) for i in release_clause]) + return not _match_prefix(version, pfx) + + def _match_gt(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if version <= constraint: + return False + release_clause = constraint._release_clause + pfx = '.'.join([str(i) for i in release_clause]) + return not _match_prefix(version, pfx) + + def _match_le(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + return version <= constraint + + def _match_ge(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + return version >= constraint + + def _match_eq(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if not prefix: + result = (version == constraint) + else: + result = _match_prefix(version, constraint) + return result + + def _match_arbitrary(self, version, constraint, prefix): + return str(version) == str(constraint) + + def _match_ne(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if not prefix: + result = (version != constraint) + else: + result = not _match_prefix(version, constraint) + return result + + def _match_compatible(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if version == constraint: + return True + if version < constraint: + return False +# if not prefix: +# return True + release_clause = constraint._release_clause + if len(release_clause) > 1: + release_clause = release_clause[:-1] + pfx = '.'.join([str(i) for i in release_clause]) + return _match_prefix(version, pfx) + + +_REPLACEMENTS = ( + (re.compile('[.+-]$'), ''), # remove trailing puncts + (re.compile(r'^[.](\d)'), r'0.\1'), # .N -> 0.N at start + (re.compile('^[.-]'), ''), # remove leading puncts + (re.compile(r'^\((.*)\)$'), r'\1'), # remove parentheses + (re.compile(r'^v(ersion)?\s*(\d+)'), r'\2'), # remove leading v(ersion) + (re.compile(r'^r(ev)?\s*(\d+)'), r'\2'), # remove leading v(ersion) + (re.compile('[.]{2,}'), '.'), # multiple runs of '.' + (re.compile(r'\b(alfa|apha)\b'), 'alpha'), # misspelt alpha + (re.compile(r'\b(pre-alpha|prealpha)\b'), + 'pre.alpha'), # standardise + (re.compile(r'\(beta\)$'), 'beta'), # remove parentheses +) + +_SUFFIX_REPLACEMENTS = ( + (re.compile('^[:~._+-]+'), ''), # remove leading puncts + (re.compile('[,*")([\\]]'), ''), # remove unwanted chars + (re.compile('[~:+_ -]'), '.'), # replace illegal chars + (re.compile('[.]{2,}'), '.'), # multiple runs of '.' + (re.compile(r'\.$'), ''), # trailing '.' +) + +_NUMERIC_PREFIX = re.compile(r'(\d+(\.\d+)*)') + + +def _suggest_semantic_version(s): + """ + Try to suggest a semantic form for a version for which + _suggest_normalized_version couldn't come up with anything. + """ + result = s.strip().lower() + for pat, repl in _REPLACEMENTS: + result = pat.sub(repl, result) + if not result: + result = '0.0.0' + + # Now look for numeric prefix, and separate it out from + # the rest. + # import pdb; pdb.set_trace() + m = _NUMERIC_PREFIX.match(result) + if not m: + prefix = '0.0.0' + suffix = result + else: + prefix = m.groups()[0].split('.') + prefix = [int(i) for i in prefix] + while len(prefix) < 3: + prefix.append(0) + if len(prefix) == 3: + suffix = result[m.end():] + else: + suffix = '.'.join([str(i) for i in prefix[3:]]) + result[m.end():] + prefix = prefix[:3] + prefix = '.'.join([str(i) for i in prefix]) + suffix = suffix.strip() + if suffix: + # import pdb; pdb.set_trace() + # massage the suffix. + for pat, repl in _SUFFIX_REPLACEMENTS: + suffix = pat.sub(repl, suffix) + + if not suffix: + result = prefix + else: + sep = '-' if 'dev' in suffix else '+' + result = prefix + sep + suffix + if not is_semver(result): + result = None + return result + + +def _suggest_normalized_version(s): + """Suggest a normalized version close to the given version string. + + If you have a version string that isn't rational (i.e. NormalizedVersion + doesn't like it) then you might be able to get an equivalent (or close) + rational version from this function. + + This does a number of simple normalizations to the given string, based + on observation of versions currently in use on PyPI. Given a dump of + those version during PyCon 2009, 4287 of them: + - 2312 (53.93%) match NormalizedVersion without change + with the automatic suggestion + - 3474 (81.04%) match when using this suggestion method + + @param s {str} An irrational version string. + @returns A rational version string, or None, if couldn't determine one. + """ + try: + _normalized_key(s) + return s # already rational + except UnsupportedVersionError: + pass + + rs = s.lower() + + # part of this could use maketrans + for orig, repl in (('-alpha', 'a'), ('-beta', 'b'), ('alpha', 'a'), + ('beta', 'b'), ('rc', 'c'), ('-final', ''), + ('-pre', 'c'), + ('-release', ''), ('.release', ''), ('-stable', ''), + ('+', '.'), ('_', '.'), (' ', ''), ('.final', ''), + ('final', '')): + rs = rs.replace(orig, repl) + + # if something ends with dev or pre, we add a 0 + rs = re.sub(r"pre$", r"pre0", rs) + rs = re.sub(r"dev$", r"dev0", rs) + + # if we have something like "b-2" or "a.2" at the end of the + # version, that is probably beta, alpha, etc + # let's remove the dash or dot + rs = re.sub(r"([abc]|rc)[\-\.](\d+)$", r"\1\2", rs) + + # 1.0-dev-r371 -> 1.0.dev371 + # 0.1-dev-r79 -> 0.1.dev79 + rs = re.sub(r"[\-\.](dev)[\-\.]?r?(\d+)$", r".\1\2", rs) + + # Clean: 2.0.a.3, 2.0.b1, 0.9.0~c1 + rs = re.sub(r"[.~]?([abc])\.?", r"\1", rs) + + # Clean: v0.3, v1.0 + if rs.startswith('v'): + rs = rs[1:] + + # Clean leading '0's on numbers. + # TODO: unintended side-effect on, e.g., "2003.05.09" + # PyPI stats: 77 (~2%) better + rs = re.sub(r"\b0+(\d+)(?!\d)", r"\1", rs) + + # Clean a/b/c with no version. E.g. "1.0a" -> "1.0a0". Setuptools infers + # zero. + # PyPI stats: 245 (7.56%) better + rs = re.sub(r"(\d+[abc])$", r"\g<1>0", rs) + + # the 'dev-rNNN' tag is a dev tag + rs = re.sub(r"\.?(dev-r|dev\.r)\.?(\d+)$", r".dev\2", rs) + + # clean the - when used as a pre delimiter + rs = re.sub(r"-(a|b|c)(\d+)$", r"\1\2", rs) + + # a terminal "dev" or "devel" can be changed into ".dev0" + rs = re.sub(r"[\.\-](dev|devel)$", r".dev0", rs) + + # a terminal "dev" can be changed into ".dev0" + rs = re.sub(r"(?![\.\-])dev$", r".dev0", rs) + + # a terminal "final" or "stable" can be removed + rs = re.sub(r"(final|stable)$", "", rs) + + # The 'r' and the '-' tags are post release tags + # 0.4a1.r10 -> 0.4a1.post10 + # 0.9.33-17222 -> 0.9.33.post17222 + # 0.9.33-r17222 -> 0.9.33.post17222 + rs = re.sub(r"\.?(r|-|-r)\.?(\d+)$", r".post\2", rs) + + # Clean 'r' instead of 'dev' usage: + # 0.9.33+r17222 -> 0.9.33.dev17222 + # 1.0dev123 -> 1.0.dev123 + # 1.0.git123 -> 1.0.dev123 + # 1.0.bzr123 -> 1.0.dev123 + # 0.1a0dev.123 -> 0.1a0.dev123 + # PyPI stats: ~150 (~4%) better + rs = re.sub(r"\.?(dev|git|bzr)\.?(\d+)$", r".dev\2", rs) + + # Clean '.pre' (normalized from '-pre' above) instead of 'c' usage: + # 0.2.pre1 -> 0.2c1 + # 0.2-c1 -> 0.2c1 + # 1.0preview123 -> 1.0c123 + # PyPI stats: ~21 (0.62%) better + rs = re.sub(r"\.?(pre|preview|-c)(\d+)$", r"c\g<2>", rs) + + # Tcl/Tk uses "px" for their post release markers + rs = re.sub(r"p(\d+)$", r".post\1", rs) + + try: + _normalized_key(rs) + except UnsupportedVersionError: + rs = None + return rs + +# +# Legacy version processing (distribute-compatible) +# + + +_VERSION_PART = re.compile(r'([a-z]+|\d+|[\.-])', re.I) +_VERSION_REPLACE = { + 'pre': 'c', + 'preview': 'c', + '-': 'final-', + 'rc': 'c', + 'dev': '@', + '': None, + '.': None, +} + + +def _legacy_key(s): + def get_parts(s): + result = [] + for p in _VERSION_PART.split(s.lower()): + p = _VERSION_REPLACE.get(p, p) + if p: + if '0' <= p[:1] <= '9': + p = p.zfill(8) + else: + p = '*' + p + result.append(p) + result.append('*final') + return result + + result = [] + for p in get_parts(s): + if p.startswith('*'): + if p < '*final': + while result and result[-1] == '*final-': + result.pop() + while result and result[-1] == '00000000': + result.pop() + result.append(p) + return tuple(result) + + +class LegacyVersion(Version): + def parse(self, s): + return _legacy_key(s) + + @property + def is_prerelease(self): + result = False + for x in self._parts: + if (isinstance(x, string_types) and x.startswith('*') and x < '*final'): + result = True + break + return result + + +class LegacyMatcher(Matcher): + version_class = LegacyVersion + + _operators = dict(Matcher._operators) + _operators['~='] = '_match_compatible' + + numeric_re = re.compile(r'^(\d+(\.\d+)*)') + + def _match_compatible(self, version, constraint, prefix): + if version < constraint: + return False + m = self.numeric_re.match(str(constraint)) + if not m: + logger.warning('Cannot compute compatible match for version %s ' + ' and constraint %s', version, constraint) + return True + s = m.groups()[0] + if '.' in s: + s = s.rsplit('.', 1)[0] + return _match_prefix(version, s) + +# +# Semantic versioning +# + + +_SEMVER_RE = re.compile(r'^(\d+)\.(\d+)\.(\d+)' + r'(-[a-z0-9]+(\.[a-z0-9-]+)*)?' + r'(\+[a-z0-9]+(\.[a-z0-9-]+)*)?$', re.I) + + +def is_semver(s): + return _SEMVER_RE.match(s) + + +def _semantic_key(s): + def make_tuple(s, absent): + if s is None: + result = (absent,) + else: + parts = s[1:].split('.') + # We can't compare ints and strings on Python 3, so fudge it + # by zero-filling numeric values so simulate a numeric comparison + result = tuple([p.zfill(8) if p.isdigit() else p for p in parts]) + return result + + m = is_semver(s) + if not m: + raise UnsupportedVersionError(s) + groups = m.groups() + major, minor, patch = [int(i) for i in groups[:3]] + # choose the '|' and '*' so that versions sort correctly + pre, build = make_tuple(groups[3], '|'), make_tuple(groups[5], '*') + return (major, minor, patch), pre, build + + +class SemanticVersion(Version): + def parse(self, s): + return _semantic_key(s) + + @property + def is_prerelease(self): + return self._parts[1][0] != '|' + + +class SemanticMatcher(Matcher): + version_class = SemanticVersion + + +class VersionScheme(object): + def __init__(self, key, matcher, suggester=None): + self.key = key + self.matcher = matcher + self.suggester = suggester + + def is_valid_version(self, s): + try: + self.matcher.version_class(s) + result = True + except UnsupportedVersionError: + result = False + return result + + def is_valid_matcher(self, s): + try: + self.matcher(s) + result = True + except UnsupportedVersionError: + result = False + return result + + def is_valid_constraint_list(self, s): + """ + Used for processing some metadata fields + """ + # See issue #140. Be tolerant of a single trailing comma. + if s.endswith(','): + s = s[:-1] + return self.is_valid_matcher('dummy_name (%s)' % s) + + def suggest(self, s): + if self.suggester is None: + result = None + else: + result = self.suggester(s) + return result + + +_SCHEMES = { + 'normalized': VersionScheme(_normalized_key, NormalizedMatcher, + _suggest_normalized_version), + 'legacy': VersionScheme(_legacy_key, LegacyMatcher, lambda self, s: s), + 'semantic': VersionScheme(_semantic_key, SemanticMatcher, + _suggest_semantic_version), +} + +_SCHEMES['default'] = _SCHEMES['normalized'] + + +def get_scheme(name): + if name not in _SCHEMES: + raise ValueError('unknown scheme name: %r' % name) + return _SCHEMES[name] diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/w32.exe b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/w32.exe new file mode 100644 index 0000000000000000000000000000000000000000..4ee2d3a31b59e8b50f433ecdf0be9e496e8cc3b8 GIT binary patch literal 91648 zcmeFae|%KMxj%k3yGb@-le0hq;dg{!!Jx)2QPL&2NH)YubYozb6#{w->ALj?hI0Tb zfutv^IULt|d$ph1tM^LLe(bgP*4xStt3bli1S)Dki}6A=wyDl~VvT~yA~EOle&*~Z zLEHPee|*2M?>}EO=bV{&=9!sio_Xe(XP%j@zU@)LDhPrNe}*9l2k@qU9{&9A9|*qL*S!FoDk2>;;Q0JsgS!E#|Np=L2Pm*g>+^@! ze&i91{FPlELF?b0n7dSnw8>K<1Jbpj5K{a`{t6`RF%zVzp#$RtAuNQP=%hh(?A64I^Ygs)dNNee8#q3xXNzV;c>_P>vRaEk?dT?X4biy~du%5rpGZV<1M3 zzmNFhrHE_%95G^j>^H-I1F8V$R{33Z_8aO_-fc?lLSFI>WH*S(_W$| zEz50})3iji%A$Gg#qH6Gk|F&Kt#dsmrqZ{-9|(1WDpBu{%Lw&M0}{1yNNwzAKSwdH zR5U**Gx~fn0CfuEkR<$t!$OHl9 zn!q6&MqJoZ%kG^j2(?;2E8}DqR_2m)FOSE|AZ&Toiyeia3pGY5lG?_n`QATWAQ)P~|=!tEXsh zU$OUmI32|X0sO>hxy%N6qa0nJRrgw}d&0u}YG%mze@J;(U`x%C4pUIGv77 zYdch^dxXJmzmH`Af4w&Dz+yxwM~mvw2kB~EzrK>1K%}}q&D9nbz*$4Azlc|z<5~q= zS_0MWoYuw>9sH6QpeR}~%g}S{HRnr&vEDsi%B*t7Hvd((s@{G=a_2XY(c2$fzmBt< z(&zApufh;=4XAR0&2|VvFbJNQ;SVKdEHzo!k7SH3I~W!zQl)-hAmjn|sQ0`N+~8yP z@Rpv}cpsK=zRGhC%Qr^73EyEKAc+(7!Z9e(o>7!?9svgY>>cz5Skm1gzolDU1C>$Q$#bsOzzk^=+Iwq-t^8C&P<4uKOr4fmo6 z-xK$*vIn$9+8f_Hp02dp+$S3Xwf@j>9!M=^+SoPd^XTG3(RB{+HAbG@{odwc?PBq; zW<~BvO2UxFD~Vyrp>?(=(tPX@jHaLxvnic6cb&cA9U|w)1&CX>W$O)=DctzS{7BaXS3D){WO&bYlpvW?)} z-UNLhseA+V_8BQxxoAjPwZ_{(hWfeAl+_JMPNi|kkg`E~ zHytAW_lL8LQc5=ROQ?ozsNq2Z*d(We{d5SH&|^U1W6j9joI}G$D53rjZyJ-AMo{QQ z4i^MmxFQ;P5=a6*cJ*!OrK5Rf7^7$rAO|DIkSJsbf*6U6bl4^R73l$lak^HG^x}gZ z8#0VeThUv*guw)OXD}-x8i$iPBO*Fza5cbOXy0BOe23S0-?uvbI+hCKU;|D9x~D>?c=hFcrP$2 zx~3zT|sZ!mvFLn z@U`oBqzyVkZAkc-l!S4pP4s~RaepQ>A}U}a;eH~CTT1b0ZKwj^K6ZA1H(cpVLknDj(J>*9+R9G)3H>K?yaf1XL)kzAQujFqyC@Re;^qR0g&Wyh&aTt!C)Fq0OntaVW-w zmOs?I4z&a-+PXDK{jnr-toT638u_*^=mE;2*^(_>sHcZ#D{Z!5jgKt?o11;u8F>rM zUx|UH7ezOv>Eo#m6aH3l>Ry606`Dh&0s5hM=P%#|lv8-NWLNi|1&p548KL)|5UH>< z?QsgYjz^!OkzB7jZs;)8P_~-}Nw=#la)#8d5GToJ=fS2?h4d!ZKu~+t-Mu+~*Z8I{ zawJF77uizgQuncjPxLhHQ)C;UY)w4d%akn`h(^xS2Iz#~1icDUbDSybjaZackNWcp|c0DgU zoVMQVthdBuhHUE~^%dq0#wRTvHq1OvsjlC7>8$v~J;AJH!L6BZ#^_reSdp1~ua# z!q-9y)GIq@&X$YA&Nb2Hh2hygmIH$Wk&Y8PkYxO7lmg*T#LI}<*87quqLE%q62P<) zn4$+Mpmj!lY4w_2X-lh*9G5>YK5{al^=rJ=(JG`kdCDoIw4Y3&Q(bNP1Avend|83@%ex?0*%A&donqn~TCUiUGly;CIiY0<`f)6* z>dV}6A^XkeU@*uX=q$bLKaoEM zfzA$s3xYAtpmnh(+aa$fvJ51KC#_RUm=9IeI`pDY6Y>Ek*0F2?@SqSi17gXBc4V^C zsI4YI0pw_)o78Ko9J;;U{d;Kwx?e3)W?47dYP3ScIB;sYk>gUDaZ>59xn)N~U#dw;`O52-3W78xL~nNQ zH7F33hN6c0P*jjT2L&ngG};hq#e?mp>e5WO61wztHHaw!z=0;D9csZNs3qJTn?)@X zXwr->(!_@wK2^$BQ#tF`Nz+2~#nO`{IiNbGkxZpnB4M~N)I;p{%xrX(odt;mqiQMrjqI5s^?E z-%{(&s*T;sCpLV$FE-r7PRtjCvP|h?1eO@rQ8xAxqSQ>|O%oqQrBIaBot2?McT2g1 zr>;x&c5|#+U6=lRr?>YR(4e`o_XWH*j|W3)!~{eLZ?8@Npwrv)A_wR>kOb%%1?b@b zCOa3RF-oITkmq;uRzr3XIqt(CBxYfJ@r!iHj@UI68)N$}1M7261yN~v!+wRK0gg^` z8)9ie#-2#UVuc1krkddxE!YtJelo~0v5(PFl<8XZaxesgwZMJ_7C6CEv5*s_E0K)i zN`_&uwYDS9jYN$`K79GNXb`buvC`ao@Wie0-%Dh9; zM7A1Ph#A=}gsFN+wev-BYApJ-Pdh3dfRMjq_E)7{tGY|g)v7}3%{DF9opZpkRFEcU zIh(SvV6NIEXR;^V=+_Lb(&kRzmW9Mg8ZwQf+u21I(kpF<9q?>Qlk=3SO=&2^qGxM% zVD{K35i7zYHo+u7pVQS=8z}QS#g-ESYFTHGoRO!pryw|!Lh%FWfd@dbo$==hpwSUA zr1xN8$ct9@bF&dvTFSOOL0($?p19xURuW4aa+JhvTQPkUiu?O9?e~+$i0E+?ox!8q zpmZ74PN||EO6c|V?tUqzFCuv!eJrI-%UL>C5#{vCKx67ouwgzkENYUTSGGHH3@Q$?P{XM_M`r8O&R% ze@Cl!K;ZnT_*1kf_bV;xLW{b@{g$t_sGYY6^*TlM>XKr-UPp@C^@+sJB%_H_uyzJh zJ5!ugOB(pao~`%#14=pZpdc5p>#oLdnaP^3gzVxx8~uWdtuvBMi^0-@CHg4K{sb(m zB_f7=dDyY8EWHRgq?}q7rBMa$`UNI}*I*gItkJ<=q<-powd^heV82FOrvQlz5w)f+ zc0dr83bEZD$Qyq+ZyoYy9uS~T=o#*g#!Rha52b`{KK9~b@H#*^0TIxSv?tOvTcq%E z$iXj^4`;Q1n4#IgK89p>cStr=C{4Wv*>7mRun8HqzrG&k;~2Z{dO>I^Cuu53>C9SA zvXshV6KN$kI-~IRx%(StHxJ*AvbRpvUN1h@egW1SXAOJ)GC^p**&#HcX?nKOQ3wOl zlb~*@uP}ouiM+;1N}JQib^sXad~=lv4(#@?@bC`n1?5x2^#=9h`+~*NEcIyL9s>S3-_)fk?QthQ9r#Ss zkFAg1V62HnZx~)rPmD}Fhww~^LezJH!tBk9{`g0*KL-3dV)rBoYidT#E42`st}_Am zIVf%yV0$!`p=B^$#1~k&p!YL3I03dJue~9Y>$>_MKt)Z^Jb6&+=W8AHWizE|P<@mO zB#|zVL~1XrSGl%ZRv`by)fWE~=v7-AHvESLV1?o20Cx4XW6(|1>V*4Mc{1CM!aD`% zE&{s`pPCT=4}6zZ+c%Hrg|anNyV>zNNKW^wJC=oeT&GqKehTwq!*$V$EPFW_Ew)Z% z2MO^}cTAezDV%@=*2nwUU!d&=5tY>`5IvMOJ0zOc4Z)nlY`k0=t@?w!Sv6G6fUzl$ z;x>4;VXiefmYyxVYoQl?fX0A5AcGlzqh<}H2%y69= z94zzZZMlq$d5+pJ>=aeYdBXwFJ_@jPulTFRyunI`16_(u5bZt5u2mLb??KP(^qwc9 z5mss~{{_+}fussdv><1>*!me_wTtfV25h&u8;8V)UPeT~xR#75Fv9yQ1!4XUn`Mcm zF;V;;g!}x)A+51L9s!iQ?tH^qrSZHV&3cKZQP(N=J6p1}_Cai7wCkB#j6Pz;NAz)g z?s0c-P19m9T5eqfq9^?9hp2AQ$G)sE+temKK(cUy#hWPZp6?yfi~P)vo)1#&t*~7R z(rmDc;Z3w!(7c-r=pEkkSgc1bN9me3Fa8S6KaCF9YSC%bJ$5!3^+&g{pTn5kDL``- z;y)y)n;nH(XECJrpzMsdm@!VhFYE{jpF+oN132wM^p?p^>FP2$Pr9N^E|9O}*hOHc zeF*kjuZjFdj+`&FeuN3d)y95@7_4;)%;ByQEekH;mbbB{$C7o-GAW%p!rQC!Y(FI_ zVG5CvY_P1M%-c90=A|SEC@To{WnR0CbbjHw`oWQhf$#bYV-> zYsb^be+I%B6OQ#VGO5vDwPQ|ulIJ1Wk(AFG(4r)Nz6`WrIF#yfCW{8to&rot$zXHe zJjmiP@(h!IfEYKkmN`JDpz>@F<|`q*0?TrIU>}KnA3Yz9P_!E9#xoiz;bd{ZRLUcJ z5LBaQ>G^m!J)e4uo_o9KdGG|D^$$Ou;IC*Oe?4`KzamHZ>)AH``uA7xdh&!M9_NIYirmI{UbuiZ#cY=A(bC(_|i#v1&B0 z6aAdWcIA!q^P2!5KEk>j>OO3!)pm%g85%t&vpYrs|BVC29|6;f`^N`JGrUUNzXaLp zA>}4$o%QY`(irn#KWvo(BHFPu9}j5x5A{l!pjHn_iy`dA{fn@Cr=0oX{%a_62Vjo? z7G|0@EaR1L2{L7-OxTd)=28p7XaWSkcc{31uzOnD9PbcqUL^H@M=c~T6b1K1jKiN# z9BJbxM9^bKd?R=o8%J5x-~B=CIF_xqVF!4<4f~^h_JN3A<0JghR>0Qgql1}i^aQvzva}nPuTE;R6XMlA#Px~!y>l4$V<0@YWB-k zosU0D!McPdCyLvxN7^r@qonBcr>IOAa5O6~wFIT!&lm8J;&!t!v|&`JEytv5w;t28 znigftR>N!eK!rOuxZEKWV(#^j+~lJF&83_Ik+%EOK`wm}SC%1KwmP+290Tok$v)Ul zbG>BMmSeI(!2=Z~Hk(8!AsisVHSc+=cW50gS0GpmNw9tw?W47d9cCvkWO7Ct%>3vH zDrp|cxw$aLa`OTOu0WSzpYdxZrFF>6O-k6!O36zU?GHrSwguhkc2HzrktaO00d#>tHSbGLyYzk*-x1 zml#q>vMTb7;#Vc-jgtMwzf%jvk%1wq=d(94uP1A92A^sHuLKr4DcuwMui*T{NJ9j&gxbWgA6hZ21J;h&I_yUOYuqRx|4q#m##8B(ObaF@3!P}u) z6h4#+weihIc$_ioG9ygjW223kHIkiJ@W4#u(| z*H~v$dL~a#C7vEhOozIv!$1Yzu2(B|42w^-VQY#@O0(5iB|rn~$C@Ikft8tcuZuxe zQ3LG(teTuK$vMkphdcpGJ6fh;&d%h9EZNC^Gm<&3A&Kol7%egt1oy=)S7?it!KGuR z1m6Egu4ELD#JG`tpH?!9X3KSK6TZ|%Z~!U@BmqMJbREY!r(RvLW0>Hlz!+*kIpFIb zX+I*Q@3LpUEeLxGpH-a15?$2UZ@elbX zGZX5xl-q{gRG+~raI2Qk=lNJ4eY!ihOw}^#mBri2?z)6Rlq;4Q?D4PbSTmyKl}N7>iGnlawFcX7Tbr| zILGt@p~O|RHw=A(RyiFV1%Ii;hoDmZbga7S9RgWJIrko;Zu$#~;L{wo0!p6z!36I0^{oPXQ70vxoH*53|M8M`L)GmazI;KnwRdf-D>R z^1j_%J07;kSp!Wi$YOzNj}bC`z*Aw7CSl3r258uVwtkcHfGefxes(#1W6~xs6EI=6 zxqSiVO>e@Lpgy2yrM@JkjvW`2a^mH~a#`xB6H5yu4eyljL z!aRn^1J$>Y2?2fSfxVfA>9xBT?2 zlRZVK8*8}i_lSu9QwVGC>f6W)+0u(Y1$FngCn_wpXK zNExtk9Mi4gY)rD`)uFTEH^}5B)05+o##JEVcS9oRjCngcJm= zH!{t87U0mC1cJYT;Qs-Sq(s3~&t3!BVl0Fz$7%154{*~mvZus}59e3$SI%Pono+=C>3RG$*U4X3I`De(hv^=?G_SB{A%ENUEW#Vcojny4 z<~Ehi^d{m9{I{DD_bf!HGkqSOSuibhrZ3>BNt=ynfZ5%O)sSg?F-;wNwgCua{k97< zzzof;9wFN)4?fA}p_CHXk0oM1wP`w~;d$a>tldl5WvT&G~^mNDZEsjJSbs}kxe z^6G?Jl(M8yA_o;EaR(Mdi3VwolGrLuW_>U#C3T?EPslnEzavc$UbY}w&vBhms)sCk z*2`HW39EqUB^S9`2A#z-7nT{~F*px)A_``p~ppteftWazj zz^B5-Nw-!>%M?~1U8%5a=`!pIh>_jMQRYpEkrROF^d=A#lvkbc7~bRF;~M8c%p*qr zoyU9lR$`~OpTOcz;4u(O6C;n}16B&<&%@9{lvmTnb)x<8Cd9(~Qjnz)yoLHb3R@}N zrm$SeTLn6xQuzwY5F=B7aWE#df!N-0|D`V{yQ}PO-Z*3&CJsDL1?t!E*tuD&hEg%J zl6l5Azbc?ST|B_e!QF79IIgFS>mG675+i3x<7({3HvZGV6)s$F_Dk6kDG|2%Lk@I0 zyP*bECT&2Bv;s)!$QT7e50=X^btTV|9?C-w%v2CTJPV|JM>eVfy-QyTU#LQ!yl`x? zlakW}eReoAw2&v~k0ei1I&vx5B8=e|7yP4^NE28mnxAA6=f@bq(?d;&fgTa{l3yV7 zn2?WZo`>m?)TTn{-$r^Kc$apss~lwT+h$W2soU)8w&`k>lbhnh&d|Ki(CS|Um+K67 zu>qgo4jD=-SkiHN+X|(c7CE?sUAzF$3 zwY88ESObYIv=HIBjD;`w*=ER+V33D3+Y198%=-?XpZ%UkSL**r-VD9^cfyOWD1iO>J>chIb@~hXG?ZZi(h}Oty7&c@psuII z)1>C_^4&k!!_@V5b(Xq*x^jy%CF|HY)LiRi*u=qv)YuEMY_g$FBen0VG6w*YR zxKz1tWy7b@s*jZmJ)SMXL#pzwrBDm=mlqZCyXuy^QG z?<#Ue@mJgfUqo)Gz6Qrfe&-J!!s$z;lGW2p$&T|Urej+-=IPtMBCQWmeOD9 zYGTPP$>j31fN%0>o9(Vra)=6O8692&l7f%O=mSnHeqcwv*=Bvidi3@i*s}pQ)`E`H4u_at?pAU4omB!HwsbP8g0dcdC`gou?p=cMK^(+ z{5-DBaLy(Fzh}5xF*!PZE1wXICx7g1q>^*O`E{2Lz zYxUzGYjfFmHs9SN&sWL|F%t_?VTj)B&rnB{qqKh{YO5gmZ#D8MUO5WGq60DPG1Lbt zciC!(G=Y1G1++J{W9-LfH1=?4#C@e!g+WtFohkS0LwaA)bt~T8G$j3qF!) zUu8>?6rX~a6XZI)vdD?9&eK*D6|B0|S5p)6RgUn0xi@iCtthf@Q0G!30a~K1wgY;B zYl^nXp$rd8Zs1s`d@(H9+@Ec^D!On>bnS1P+Bno$dB7&fCqfo##WFklQMDkvgl`^r z1_Awr4L`)dCfXE$m@%NW4KB4oS_lUSPI93Q>`6C@{<*`P(|u-q#MQuaJU1J!osbg0g$DJEqRC>zpw^hrQKCzzqQ7Yit^ZA zng&pjBX&5_&>5A(z6t2u#h=@3q-D;C+CCTXr7q$k$0$)c3sTlQ$x*2c7j1tNP8{pk z#grlrh#KghYDTR#qYHAze~2;%v?Wl=Co0%jlyU;bn*p}`3`)Hm3VMgVdAKkg-VbLv z2R(Q|~VNN#@t8>Y)x4w(k~;|%gZfjwv+ zxEBs60wkEJBRkL+!5~&G(S^Li*hIH!o%-G30=5x*(&RRGQ5M+-AWM0Z=suX(R-=2k zC3B`+%xM7!=cE;La)52Yzz(vjM>4^#sgF~a=$QewhLTdtPzXDWm0tEwfQ$j_e01-q z81+ZZmSOWmp6Fw9D3NQ>Y3b zbl6n6pF^2uGpW$f;VM$+_#V{L6CrX_RNeCoLVKR0$1mye0v<_w3|Uok&NK99na>6> z@agvk99CFL+pwB%==L8kPV7DY^ zp>aEJlJd1!I4xM*F3rXt4*yB`mY1N2{`x7*vO-io5BduQIl-)!t-v zM55>>yOyEXXmINgrEfxik}j))mazK*bs-i<0{aM)s{Ya;s?%S8d%D_J#uE)$`*lx%Dla_=vao)6Lhsfy;CmQVg9)| z4(6YWHf-|Ta=Tjnmb(0Q#LG*xTQ;cGU7gD}JPb4xvp~yXASYHFT23E6tUOp&eYSCm zR(%!()dFkPit%>CdshD=dl9+Rj8s>`qRw&5GPZ80HCFWm^(i1GOu@8Lfg7U0-oh?r zFvim^trq+sQ+3MFyj|+@4cNT4gG{4LZ~#;o?e#scTpDZ}4H~5sFbPF-1Jo{~3*5?2 zPtYkdEJKrg7Blj@K~Cdu@Ox0txW;+5J1Pe*lv;!WJ#Fh zGfKNgAmPcGLn+2?!bj=3=(b*DQgV0+@hxC?43p=G_1?t-I#h9rIR9b7E89CO*RBTT zm3lk8sh6ue^3)xhIvzX*;x6lW@FpZ~_@1h~Qn|vPeZEU%VeL^;}R1WGs_86)YL$Rm_&=;Yi@H2L>Y5arauxaiv zN~wjgj2xxeu#1!H=1?An2E_dkFkvS%2z%AHKr~K^(i3CogT8>76(>`PNwLW8C)(U> zGhn#N^0T9VK&)#3CG{bmj@N++{A?!*;^o-GPWA(Wp%jp@i^%xD$nL`JNG%DpL#u>y zKaGQ}9I$eM8M@O9Ei^-G%+O*pRBeVlX6Sk|RAGj$F+){mXpR|LTTb0Xg-oCbkn44b z5!0r!BZPTnDw=Q}O#s!!W`lZ6g4F%XTL4PYJYe?HY?z7xK;tu=lYE5p&Z&_+4~%6ta%s$B z3$YafTNF0iOIM(}p(b!+z&IU}=)LDCb=>JthzIz1I32p32Y8pBR>}zi9@R7~_RuhZ ztS=`(_(&?{1SD{$!lK6G!Vn;>mCcksOCfZUTDIbusY+GY+zpK+R& zDlZ^{jXMcuD5dOLDa{wgX%i+{S;NFHy#S>fQ`5CTq+c zYY^eaG{jC#0K3qnJSn=&iP$AP_LXF;balIt=8G;okep!22_Aw`E9c~Uo6daM{KngR z$O|5ms%f0$?!Er74f}EPI35y$<^)aoIWWw{>EQx6ph9aRH&IyO6Q5x~X25vMYTkf0 zMe{z4f#kJ5)<~ODIA#Md#!3Kbl89jUqkGAbVz4_{MKa%i;Dvsi9-v3yZ=N22nnzFv z2#Oy69Td)v8vEyAG@4COAEIxZLQsr(4Igksq|8;@lLkl&E!0torHifY&5O9*@e{bx znwH0^0`ajU+L5}{T8x%tDYZqbT5N^a^wPXqzqtRt4A-eZw8Bn4b?|62%B6$Ca{1USuJ8E z31LD&rhV}Wkkec!;RwC`N^UE-4`*2b^ja_r{B`5rEVUKj3 zY9^~JjxD0)V^le8vy54!CNq#?ObK?k<9E(85SQ5=B{8W1I}sqM?RR;IN>1v{eI)+I zIBq5F^)I1{IOKIEs2;R|h1?g#mb(B5b>{>|1uXecf-=pBmni}x0Ah!`Q;02p1r3^q zi4)aHGR1l6(P*TdG67eaYJ zQ2b7X zR9{z1|Kj(9R5&`FUx6BvD3P!XGNh%hwq1_ptq-T$fvdi3`f|zcDW|1+1FMZjr~n*P zqcmS@-9@%!8EBY_z-UhpE_jcvBlj`u@5y}(q_08UiS$xF0u>Y>;-p+hCWVONY%Xw` zOPguFf8FI%`2_<;AXX`|N*begwuo(G20bW$)n@Tx3=?k=B^C6~0s@^H?XC`H&Q0ee0 zbE2?}P79V|sf14-<_1pcIJPGSef(>JL@T0dWi z(?ufF13p$VomRRym7uk&J8bF>ySl^C{=Rcudvu5M`RAX1iIf2JEr5$(KTIq5U3r#P zr{@-VF#6yO1P=*3&W^a7<-wFNYVMnk0XJr7;6NvX%HT7$*l;N9q(|Uh)HFR3;azR5 zE&QGgkGr$s{I1Af0ooBE`CHi1CY3~=`UDZ;zGLD(tNYm2NyY6RU-YpYN)H#_%I==V zd1}`(3l4*{w8^K@U0di17i29;}uB& zOp&7iAsAQ*b1l1q0~Hb79`;f(1MLgB{DazhSijXIV`ronX#N!yb{(J3zqQ9HCfbrqnXFyW+X|J7Q?_O|t;n6>jMfzD zIm#DPwmK+S7_I4Pb?Vj*9H(%<(a@1{oy>&OBKIF#1UbyU(TC}6BRES-?B<7umT!_~ zC_C>Gq{-UW5SY`BN%Jg*3$#>rJ%D4-5B~$+m!^KWHG~ZPIOrd`l9_ z?VG;TI!2BI^%ag`R`NZE4jNz^&>xWG19VHru$-&K*l*F1*htxp%AjG`dOy&F#)>Wf zNR{*UDs3g@{rGJ7u-RZ=k_?vs*=*41Ww9lMZ*hMo)>aNwk(l3)n5dWepm)=tps4E* z#Ybp#*>vp1KUx5OJ#_e<0Y!x6aCLesgtlrS-h*#feh}3?23w7dXR?c&W#o&jtq-Bk*?kzibeMOUO>7BJR}^B4-7tP zN2)!MkLHnzztce#pFtxWcci2ig&>ijm!PuGa_0qoE^G*LVe>_^xwUK$okm4XwcT+!vqGF5|4hA2p&s!<>Re^xChu5`Z_uNZ9++qDN@LA~fqR7|?Jd=WV~g|r8W zVu)CW^GvsC4-&}`nv4+4qiMgxpxZ~e*gr!lR2@54=a6nFaAE*{mD3~lGg+7M#*;S>Hj+Ji*@ z@@>>x)5?BAb)xD{_CVV1qa;=ZK-~DSW2A3)nteN7%S7$Rp%O56%pst%^+Ry4Uv3+X zc2Km^$-BDK&%T71z>Qid&pPxmoojVt0RpaA=+{czgVMZ!x`>5osME5@&;E)}n3#jG zmke`zM<#Y7iG{V!b$m(6-G{c3-1&JgCg5I-X55d*C*aCW(A;)l0-nxZqv%a{C1+tj zRRpu}OUOaCta*@Frp>IBY%5B~U49lse~`Et@yg<3@DQLcW0YI&H5uXn9dl9o^5|%b z*zyoaR*Mrjj%alsdkDp7a-Vi{9$fujmGjZiXw~6*<-(M$wtA(l5ZnFwP5fL;*uqc7 z%%qj>p%Xxli3*2gg3s;jk9?lINoiTW-!cW^7j>4w*81NCLq zABZivkTAHR&D}1x(Cs}MuA;EP{%nmMB1r5Ky5HTNroCInotGNFcen_pa$nyQfaX_; z)Fl0TqpdtgCJgu2ByfBv$IkTgI_9MADb}j8g1~8xP$|6m(8fOUPaUj`hzIKqxx$8K09fogw(tn(1 z#<_6s&@Q31()KkkX|aWdJ2^>v6Sn0BPHSA;{s`Q_&k+hvHri-3aGC^VXEfbxYtrw7 zKXfykXVb$2tM%;YGH&ru+CE23_yR7W;JTF?FlLrOpGnruH5dFRs7v@IYQW;rvy_BY zw&BzMwK_=)P#-;;z&hzpJ!6@2(JDS1!k5AO9Ct%PO@hf`4Nj|Iiq{7?6VYZH@#f(p z;OImUHo|X|rO(48xMdb}&pc#_KFF|Aa+{G>QV#lQj{3dn;WvT=D+lw?;$>VnphfNf z7+35oxRRLOSPITcfLjcCL7CSf{SRx_{xxiLG>;ltd;=jgs|JkD|0%|UCPuhs{Dj2O zWVmp-&R}y5_U}#z8rqNxTi2_NJ??Tkv)#B-8|1zXWz%1Pww-jV5Pj_9(*P#Uz;Tsc z#mL(}&vb!EIYrQBC66J`iC-K7Fb~0VV!6IMr7@&zX{X;K5ocj{{TXm$r?5(gcC6`r ztLseDg*4go3(_s6GHm{11GE@M;2jGBaPW8t7mdK@xTT6O0O7AH!e<#S%c9crCAlnT z(rHEIRbxFeD)lz({H)VrDfvz_B?K<)_od*_pnkQVZ3mx0wqfH5tThWqJ_Qeo&GWOF zD9Fe9QBDvRzG-bF+Q~CCFLZ!t`Rco%rMVk-7LD0PjlmYiC4MfXDsV!OpUWa?ohEQU z6+fEsVmsi2(DKz)Ln&Iq+&0jz-~{C=yNvU{-=>-o(Px6_`joOpyPQWWO!UXq$t2mD z1uwhCAqLqcRO&4*2=|^;NBG%6UI@GtXf1582>^mSGj0j(#W5uBS+)Xgpq}{C`zVP% zW)a?$kp6o|30nV{(&^Yq&n3;^7n84hLt++jO z^vFQ+d;#_)Iv8-#H#|^6W^pr<(Qo zZ;l828ybY!e&l$-V4(~GXXm)mKYHEqlW{&k<2rf&7eF5I{cLHpN4y}2*}Coh)f<0sKJ^7^dD7VzJ4^| zf>}sXSA-{5q-_W05#YggJ!Uks6%=908r*XU*_i|<$9>0^39xt3Swbnxg9RPTT@9aJ zVoN4Fa7`4R7sbbv_eE>_wBzI2gYnyH={mk-Y-TF90w6sr=jH?w51Wa`wndPy+@yD0APUPe=k1 zKmoC(iLm2-l_j`f7ni5pTu_|25jV5AFYcHT0Norcv5ds7{-ytb{wnHPU65LPE=WK{LG`CexMDy9o(4;rMz%jZEX$v!>xia=Loc5;_JC6 zbyu~$)viy%W+yH#we#ZCk>bi4hv4l&@($(EF+x7^@`=)%-b`_q&;Ibv2=C8?+8_Ud zHwi9xV#_D^e9j|AKBRXVrheW4e#TNcMh8Vq+CgN_LDvQKbW}>sFt!vJTj05V0kbcp z@prMrB69_ulNVbwphEq{mLK2)Zt*{mYjDjIK~k$q{48dE4@*V3J9Zxe@B{ZJ9l_bp z5eBV-M5oN)`XrHdd2B^LSo{MylkVjx#CmQAKZybj76)A}J)q)5cjX#4+r)jArE0F8 zM|(6%5AG^+W}#;=C4gGw_(N8IrEj{nik}b)53g3eed?-SFvK*rA5IENAxwvOkGi%u z!i)vZbD!I8cXQpOVHS%5LM>pMM*!I?(6LcO{ANINFZ%#o+f#1tbdqt`iV_=iI-Fqe znVGL0$*hN($%46a>&-au>V8vf$p8`veKGQ-jSlxYq|#j#B}Hj%U5Qrjuz0AgDr^f% zQ>tL7Ix^TrLqhq}u)4|#a~54j{CzW4p29wOn^*G$UP-5pd{k4vRy%SMZgWl?YQ;Un z5CKm1FSJSB4b`9@YTr!uQ=Wrt&+KRXlcpMK-aV+0dGiu!DF5pgG*(nAa_510)s?vm zG|~F{z*1Y47L&fe>&En^3)#4Egl>Ae3m5k^H4Y1{<1{h44BI$lAw4HTDYsXiaA$gm9vO=3$gs)o9zi7n(c05g1c zlRH~ZZ?fBTYg6Gxt*)O=?Z(tPI2oRIcZvtPoC+ZCIAl*J-Tw3eYF%C#6PzUF4ucu=X z8MZ1Z56+9((n}rI94&KKwb8mFBVC{CuIraGc*4`@CnL;nMEC^0cjzG=Z3Fx=RERD^ z`avbwPS4je&9-}}k!gDRE(sMX?jV>Sqhbk?V2d=`@MKbr65ko=P+_#FfUKhzmKaSWt+8I z_h{lk#WiTs+-0pRuSv%eVtdxEiJI8DGI#DWT1BKnmoF>s)+Y>hKLM9Yh($ZgH(Lhf zrns*EBqLD?XXbuv=ZxMXNmpRB$qQ4LdG(Svf>PZFkIsHfYvd)-_ZviE2N6@P7}3!E zpif*e-`Zp>Ph&W*VTF651|68WuPLQB6-8BQYcn7pnF62n#>(y~| zl~r3BdOp4vv9wTbAI5@mCS9PYlx1U+kd~*;a5ld@fS9O-a(kV)Y>snD8r{Hs32%?# zk~N%5R;9RP9&W5oWJ|w>S8=^+B~D2Yr_jd*e9YA{J1R0R&(^OX&dD@^Bb;@HiNG)3 z#97CT&oYsq{wW5UN(?jwV_M3!4P+1l<)-Ob^_qaP0ESM1NQ?gn>WE4HaQZr&beqh| z-b{&DwiKUgNjyv{OX6-ZavObY>=WW^@sV5sVlC4{`u9zMA^8wm(gx*~!t6hn&8@mQClA8vF=S zXO)uI-PE!lT|lw?+@e02eS5U*TTMJ;&-Rj>B?re}Bgs6ww1Lo?lNB_kJgi=@)34t_ z#}aW9G$yCHwm;iyY*mi>oW{#8xeQbFu3-srid0U~0(4jb*Tt-~?1W zhBr%4&-o(JM= z6Ye8|LjmwcsVK6=l({y-JwgI#9aU|nE`izVV%L}+*Q;?16Y>-7gngnAq8^K85_=}c z(FzVLJ%^9!$i9^CdvWEkPLpCUkPv~z6P@y9@kOSo-w z5^VJd7~B2w|AgCWS=V8z-{0b;0U8o1UK)l!im9Ej470Gm#Y^=_GI^6a zGFk+>L@j-&$*+p(*Si23W znXv4D*|A`B0|+K{BFk^FJ$0}RDYP{Zc?BP|X-LB4<7~`u1MXqz z4RQZubuUAbx|c5GRrem{&*$j*cn_ZS?$ct+Gk}L@uJwX?@M*-A@f_mA+YlYSp{HI+ ztllb$`;UnGn!4g1LFo~RJ2j5$du>_bzLt`H#E0$e%(hOAP!V*M{w+k+M5g#q4)7R7 zk@GvrG^RwUxoFc*@KPgYdrdl+6fh}66o~g=ZH01il1r*mm{nR>+#wagZ#WMDF|rS- zS$hdQz8{}Tls;|o=SRLR@qfj4GmodSAAgi`@L)WG&wAyHE97Dg65p2U9I6Nu2DN?! ziEZ#Hij1#B46YN#=l9yO#r?mB>rofZ)=^R!0Y6L465>~;@XoyiFC`LQIs%iVKs=3O zq?EB3DIEV0iYqldaidhDBtnu$N!%r2mA)0H)sSR1iA=ijgLvRl^1I~m)(gpKtSRC@ zN3=;0XZ)ul--Yo<@Xc?wyjGrqE11(3$`fGTO=bj*;&&5p!eyp@(@cFffjSvGQLkHg z>IUpG@{c>kmU8}auh_DXf5>7>G5^>mw#?=qtHqWn^zkgQ1t|CyUbjX$hjm7%m!Yo+ z=H2!2ei-F>vp0x8ye19bEr;>sXZq-TAD!u2DmlRbx0w#)V&r`+Ig}%Xot&EplgZT@ zXEKujp6J0L6vHpMQ4jXxQ{|UaL!DM10s77ek(~D3;_o6j7@^jdpvq$8I3i6Xh4F*< z9!--olkwU?%1weh{V)*;yfnZu6q+ohtr=3EqC&-%3y>99ri|PDG5x}i044DV>0;2THdX=Y{5N0Dy(G$NGbr>@y(2{RyRW|6P zE|aXp&f;M~jS?-S2~QLs8Rd`or&#VN&r*ej_=or&LqlBJKLezRcM(Wplla5GfDgo$ z*YH#l8^wnY@%ZnGk9_zg$)h`^dz8dIQjwClSB(4&X(l;VM5)%C;_c6FVaW2)4HDB0+xEe)c3bs5LIh zgKC7tI_T;gOLv^3&o+@!M$Kw^%PKKod=%i?vLQ9{7(SAnZtVRD0^*?~#$IAIXb=h&uESShaEl~1l+W1@(_9DCSilYdgUO|;Jdg7 z@yu9=su75$>#vl@Cwl(M822BgE zBcloR4L~J(*Q7oqBWS)Ikl_+6DJZ{r#gfZeK8k&&x{B@GktV`>shzp z=OY9u!`hCGsB^_UJKfVye5V{F*@8}Z4qdBp=?Wuj@h`{&13x%%rJf68k}X`UXTT_! z7cLCet5ND&{5k}l01~u=-S{fz0<-ua#j2bYpL57X`b=|D3KyEQ(k<*Ec%dl=XOHABa>=riv ztJwdf9OQyc{+{*}H5Xf}cW8W~x>#chu^uFVVC2ls7xb%?C~uZN*BsGiiwxe2sdn)O{RSCv+Yu*%u-%nxkaR_|L0==; zO2A)AGUecNC>E!LjlJ~2uHOTQXL(#u<7%eH6=G;3*oWfWNS6aYPb&>eB5`pv(PD;3VvYFj<~m(=kOz(}+a07ZN%yLuF2+XzGq5CN_RxZm57 z&&G|ytOQK_he*b@5qS_k|11-#K=5!IR*(#7Z z>0;Qa!`M7bDTqs6LO$yJki3OljF34nNt;q&O44S>zo%%^f^_U5phoW8Ay@nqdp=*_BdwEF9AU7nR zR=yDX!gPVMuNIzT?qDiAyi_GYd#hmo)^V+bq&-{5B#x zf-J~DKi#&}AMi0@Kaq)C;cvuj7G1c5Zts+ThcjiU4*TbSMe1Do6yP@4nNF8dk@&<7 zZ8(37lb%#AlQ|T9l5Jgwm#L5bv6;{F-zb1b!#uKP^uqx8DH(v)#p=s)@pEMOWtK9# zoJhX=Yl}OgtJ5(3yz?%a#l0eOkhh5Pc4A*BhO-##4lpvAgFYD9BceSNMVg6yl&RR& zVGIMlx!y4dA%R+|87g*sDs8DP6R?3MG%wJHuHx{_zdZ@J zfudLn>2Crwvy#?K^5^_$W6E1IomBucMjBl)WR5htNR#huEH=m4p7FpFl`($UrSzf->eQiDyKT34H2&D1`_<+`0@ zvd4*KJN!j)(%NgcsS_csnwHF#=^jGw&~Ikr*P|+F$9J)j3Dc#0S4L|Zd^sGuW{Ue_ zzDkyHy-CiAMkX1%U`?ua?8-2_j#f)03P5o!XK>h>uC)C{)5St5z3F0>{I9@d>$m~l z05JWbnPN*E)u5h}Y>Ttxj7t67&HA5tLKhNf@<0XgV+2$|r(wYrnRHQ2<>%r>(sK4LUA=N^JoHNUL}q z?Wn>{i?gKV_!*jVY&-e@JcnJj#B5~Ft_(EKY@C59FV#{#hYgpTAl6DF6G^Kam2p2L zDzayGqzObZ%HWLWA`&fGw+6j#RSE^eGU6=g;1|S}%^?3^@b(ed`ppwiCGht0*S5}B zh?|md0t!NIH?h20Du5p_vyiQFQGsm5rCHjlA=)UZt&KLGXW5w7Xs$l$C`YN+Z~ivz zyIe3f-=HPhKTM0-MC^uM>tl~&(;O!%aYAW+GP`v+;3ovfX$im)RPE^nSE;28PnhM& z%M8vKW2&B#+}*GpzH44WSYPH!O74=R@k4$kXaIh;v^eHJneg~({eEmRnX_hx zvqi|X(xvqQQ9zk`ZN6F+GSD4I0MOKgahJV6lh5bikT5+B@&U$x}l$*D7?p>gvn z{RSp6T5aI)%^!GPei>2*w**Q#5&Y!9VAmeH-AdmGM@7TZqmc@H(4dYsQVPt#!j{U82)_g7!u5D@9V4TK5(%Z*gM%?R|^JXltDj^`7;y zStcurk#}KrIzWbih}S7k81y;?PbS!=%zIX{HB}o;IA5joSc_vXA#>Yr@o18kRY~)z zq(XKCIw>v&&NbMx_%gRuKG}n=?ufq&K(+e3J`Ht)P$0Ad(Ds=Zz<6*xVbyu~)`XpO z6~lG-y8?eR@aI&RM}D?!)pmd;iso& zK()J!Rgw}_D5x{pe0+5ZIJ<&l8~DUeYTRzh2CcjT+(o-P{heHe!Y?*Qy(cgX`Y;l( z=R<>~2iP`YJd>|`+ni(ARW3%CS){qm8?l@+cJl1Vg}h(Sc%63b-`fuwPVE`Lun&Wb zwcyDw6^g^31U2eOIlsyk|5qIJ188Bw!n19FDuhY;-`O>Y>J)NNZ~bZ0bGF(T@tmzT z>;!!+t9%9pXJ|M8J8Sgvbn=x6V&A{%xTSSP8txtaN;<#9IjyLvu&K5B%chNAR<%|e z^3H+wCb8u?a1RKSCT)TP67c`H7x+mu;u@DJ?1jD11Q#i&ljK9W zqAv*^uvw!M{+!;kb2{bptZJNZ%knzGgmXIG?NSA15{n?shf;~xY=qLx5MC6rVYP)c zTst(g!#ixz3oxx5po{M~7i1$YO}F7GBnPk9@=Nfz%RoIm@I@3OPaz1|#RbEhc3>1d z=1G3~Y?AJS&v@j14#V*4#t+_uPxR9kT-a;dQjEhmVq^`X#6#X;mr*6Q%tW9{j4a2C zZb}}e?V$Jsgs_IdPlm9K3y3(*aYv*RxK0%jD-pqczu;rg@(8FLw({SqzLwRTNm5O0 z*+SG$q)B1;LWmKvALCcrK6&}DAg`uYbH6R}Z$|}RLn1)M2k!*qqmtr70emD&|FAe& zy4XT~re+OJnUQmjpav0AJL8#rs_dN$tAkKJjE6iGHN6$9k|1mPKkR)8Tvb)O{$f&8 z6iiJV%A?{?m|~8I!y!O{Kv7h*G(rIZ5fILCD3zl?iAPMEXEU{I{IndJ%rU3RAsfsF zt*katNoi_DuK)9_z4zgOXjb>T_jmvITkxK>_8Q;!UGJKwmyId}uK|=NgRns)(%vR1 z%M*U$zjWce9nGa;|6oODFWsf$VX%dmXL;R>9VWXI$|48hN$kDpJ$K~Wfi+rz-KkxXWFa-D5)a?VJuqXge5pDgVzT?ZnhWi|I{}2m( z?d?@<-iD#-xb)oH;cKZ;lgv{!$t+i~HS3Zr94Eq=im20IlPrYU51ZprRiP?!Z8e$w zk}9`#r(-z}vVY(}wtNK!U8q6!SKq*{--}x6-2^?3@-dhwSI4L|@5j)0#b#s+m!}6K zcC{H9ONjPB|DMmfX3wW(7A1KAyHKGPKC&5Zj`gy z_F+G<>lqbHd{72)FlE9y<|p1@Ic{zzZUF(oc`iib#WqtSEnLci^h4*KuyqZcdmMKN z==nkB9Itv!Xd`h_6u@M7-?%hBvS`|`~=ynf-4 zj_zXP^e|7H8NpG*?Vc6iz|wzH!{BW-w=eLyWQ={suo}wPbGH>$wy%~QCd5QEe7L9X z!u!Xr$L53P&giOMd$gCF>i)3+XF}Ie&V-;*T631HoxT@bKZX<#Dqu_kEdL#+c#E2}4Jeuu)J@vzh1r6-&A1M?s5$*!E{zNF<27n?UPgu1 zQolzn@?~EwhD@g+8HS2Y+>&8jxd&!}7Tg?^>SQA#=Fj#f4p=iE>E|5f7dq0{?(+&t zso0S?^7R0;6{d+xAd|WRzmqtzhmwbLbIxtfLteYW&d>10%kc}I z02X-i4XEU|HFu6QOB!4Bt$)!s{$b~DNw)ix&*_ato!#un*qdXA2=<9!(4K$Isns&* zzNPnBF`e-m9gE7n^Re02%WDr7!&lvld<`ml0?tdJ2T@-SyW;?Fd~`g7QCfYReO)-r zW6@AgM7wYp?m+b_+N~mg#}zr|I$eI1FAtnl#Y=@m;VGA|rMjP@T^>Xb8(iSJ(B+Ca z?nIh4KsF#1FaaU`MSEbiElN*vmuK}zF>|xv(OC|5!v6K|Mn|1098{k-jBVdQ=7jN-amCXsQGV&m( zIu9EEacXrH((U#DQjxe=EvW3%`*GR^^TS4-{Ho_kF!Lk?PVhm`ORX@c0u}=n4fX1H zXyGugq8}CaPAcxb+gOBbL5nalr9stue!!AMG&I;>G&TvRMYNyMym233(V&4C>f@B2W}lle0o!9_ zi}%re)(>e1pjL4Xio8`F{!eQPFD;-uc68RCoyQy!h>pMVwN1ER& z<6uJV7m#sIQ!ygU%4pcF;19MB>kGf=oDK_ZOux1v@PXx7x}M{6yO`_hhAES-YG%7t zS^TFXvv3Zxa%7eVu4hEd_0HguWIF~(7%o{vMXwdaB`iv_U4w|=-a#J3u5=h$tsqu( z!9_}R!Fb?%M9ne#)wDuoSW+dW6vPlKv&gAcL!E%k1QhL^3d>*oILytzM>F&euGpH+!s zP8aJ!&GFh0U*dQVFL8`fFL9vF!uvXy4$@!ZXr^7`LZ;we)o1xkUrS0a^{hCE=ETIx z6PM?2$Ma$KKPYUt~?diNK$)vjf;|UtWxN=l&cG1W?fzMtLHqN@$j-Y zU%^}DC+<*MX=D9EOGZ$mSgyIpD3*q>2e=9Qm_Rkb6?S-DJM_ey`(pYB;_@4u&OKAK zS32=-Y;@T6xgOTis6fnxgiZ{yH$wT~mC4u{9OUf7H5Q(I>WcLfdm#FCTn_Vo3#9?) z*X==&Lfm&yiQyb4$w$H3e1-BX1_ykFa)|2{%6>TKTl*EtzJT~QF=*{Q)*o8xC+!}ryX*>Jy98qGT?g5hNCqGmxK>BrQYI>sty|`w`hys}pVlH_K(Bm!S=tG9Bjc-jy{nbXca<~TZo>XEmL>!4faKV_VvdY48S#>7 zs=#7H>em?O6zvSEv1VwL)*A1g@~JE(1#R7>pl!7jSSSU}l@tV2OF>&o0YrdXhYRNo zoG&XeP?_1=J@3QzU6}Wi@4SG0xDUhjTABBdge;M$eamgvJN?KXQbGwpN?>DCh(rQx zF%Vh>@dVcrwU%glbY@jQH#*Ky2eZCHO$9b7W*HCgm~5)x=yzw^y4b`$qFh3nj5ZB7 z{b(H-3l_85DBVwMrgS`&qV(pPm(l~Z-;3a{uXdW+42$-?(t|Xda>aL7?Ng<9)81El zi1v=sduuzD-d1}<>HW3!N*|~_54~uoRnD+#E0k5F_K?z}wPi|=(@K?|pv_nMXl=IA z$7$1*K0(V=`mI`u(o?nZO3%Y%u7OSzHabv}v^KQe zSWIJpGA^XiM;RB>_}c<{SW4qbWxSWh6Uz7?jUOxHqcrYU#wTdpp^U3&d_@`8(D;Hf zs!JuFRK~5eeLxv^(zsX|_s}?B8Bth;HUmb5@+;ORuDx-zQdCC|>V}UYur7=Sp zyU{pN8AE6srHs949Hxx@X+&8D_5*3`sf<<{J1b)(jct@Mn#KSa70Pk^@>C89G@eB< zlp9CW_`NcYqwx!6oIvA;%6Kb{Z^MY8rnwrd7dzW{XT2~Vb?XSu(5!)%@#=B?;1~!H8urcUjQaSI6m@hxE1F=w|n?M=N*J=!!Zf6SHd2>`9<}V(=HGHmEJ)G zKjQT1PK){2CwgM&g}L>(HZ3>1e;#bmc2)GkoGTWUycc>_e2LCg@+XDFkKw~OmbCaMZyTnz7x{=Kj9y!b$;=Kv3TcOcbyK#GUGQ$xH`xJ?Tf z5bkMj1?F?lR(tJ0mE`hmlK*zRKdZz2B8=nGaX)VcQ#=YKAPe@>|w=Z7)9V%$$=lfKX2B7Sv^g{^tm=LG@5r^aRpuVabYN%XeR?(>L@d9%VRCvcoxOK;(Rbc5qJ2qpFj zl$P}Vn)?I$tKSg(hGM3l9nu%EIE70b+G$b13-{~jJ zIAhJm6Hd|CmCIL{u#qCc=_PyDcm5<>IFM1i$;Q9!Hzq2^zlfN$BNn6mJg zVu=cjySYlbktsMNct=N!zDrB2_*_&%da!Z5WC{wvqDIaQq_WpmoO$JHVo6(kIqP}t zE}Dg1o-Gz7^jvfgw}h``Uamt2!NA|irNIMEuY4YcoO9lV4Z%CCpq2_-kd6FXBnl%Yg=gv zWhZn4+2p_Y3_5v5n@PXGu5<{CD^9LTRY$rj>U8585wBAL8HtDg;DaIK7RBG!-(Qr5i|JX&F;CJdTpePTOw*lheZ#C;dxen2w6n z)4^MGenw6&|Ed#|E`;s7lX&!LNTnNPXe%Y_h1Cj^)D9{=J<|N+bRI zm!E_*_1a6(>`&2LfltR~$_#e=6H)B$1x31~h2n(s9e==w^X*<|f|VeYl|;i6jy@N3 zUepXnlpkZJIex>bWF3!PqOo--F8Lff|GaF5$=VN`m3ok1oT@D==?dS-LlsHg*%-m( zls^x}3!GqD97ekx!Ky;QiAw(k*&w^TlM8hmb!UdUAsr33qSY)Az+K0jB1_zFA@ULa zo0@rj?zLaXzX$0^V*{hmf743?ymrmsOpEiR?3KStStiO& zZOT$;=T6x$Qg);Ash4$C#+eUxT9)zCAk2-dUk$RtocAeV-*knCl6tTGBn?jjk*JH3 zvj!Df{?=Y+#*WPx)0n4SDl1SR%gUk=ZSXc606B!?!rSnsn|>&oV_Lo&>0kT+nC{9| zkg+SFthf&Y*Oj$4Kd%kU{;$$Qk1dlf+OV16RK;7*V!hm|jBW&WR15(w49PS3 zas$~Sd-pdBK3=m>(o(dV(u){bCThlCq}mW+&o0`m{MfF;IpR=N1aY6j5BIZrZvaxX zUtlZ^sTg7u&tLI5zM`jD+psdXV&zMTp`(9mH8Kv;UQprNGW-S@i!5rtn4eQ260E8U z4)gI!{Vm#~(>Zp>Y*?L&*78M=QVLQfgRgD9pqYQ8TT;4PXI^}Gce|n@Eh}o$a)nmla@O8J->Bl~MIU#p=gr3*_a|x<7=gQJsE5aGdM0W)w8K84 zIS?rHKpPpN1!8c0uhYB z3z9M3vl=;@F7!l8fICqAu&E6v!ctyE`n;wDH!Ib{@mGDq^b)6E2b-r~Log|~h=*UD zZ)-qG;$3$feYH2?$ya~p+iQoYldtOF>jyOszN*gJ{O=v8<*FwI^=GowsaNM*&aIS{ zJ&&fKbi+aZZa%@^k~QkLQvLF!=+Y8R{l24qSE=8f_|=vb;O7vgAaUvy-{_qNYuoW@ z^n@A}@)*D?a8ajTd8?^;>NTYi`bT)!)Q%ha8qWo9UgM25yvC&sZb-nMAl&%V&RMzb zybs>4_VU}ntM{hEIV(>4qcf_YL*?1b!FZcM`wF@A((Mgd<-OrH^gJXQ=Y*zqk}uI9EH6r)uA< zeX6#Mk?5yteceyh(we7gPhwgrtNwU&*zU9-9xPkk@;Z8OTXC`jKESob&`L{mj_RD& zd93rEJTCth#T+TuJXafyt2xvGs=aV+uz}vo--NNKj7IPBmt1C#@~2>)uk0NtT;&hA zoIJ~&FgtLrwj1`p>Y48>tSa41OfZ98n(gw6gSE6QzX>+Z5*m37_D$npt#TSd&#N^! ziSk}Xyq#;tOGn1rT*b>T^g&dNG`q*h@A4mfiCv6sjN`WqTcqPRoT_#FhEug4z+NXv zz*N4A-omo&S4J3?Sn|;Gu>3hV=`0B-U+ywn%I|@Bk=MY!_NyJYd-S#kq9bO61&fTZ zx$rZvm-2DF?qfB1D+`fhNz9$qo^ClYX{INsL5S#}VHG9`xEBiOyM$jcB-o;ba)3N@9x zkJ<21{yKK}QC803OztLh1^kQ0u#dxcHn}6w7N^eSLU@7zzR}o4v<8C$2hZeE5)ne^ zg`qqV;m($jVEuIM<8X50IZww_JKGypJ2{nTW7n(Q2UVUdgaqgw138te zKaQbmqZRsTGg{)X8-90}kU>PKd@uZ{6SM5j0`Eeentd5g#GiW;ovPZZBOzOe|E6J8 z3F@x(vXaw?Frlo3r9VOQZ;42G8rIfsw<>>3s-oGVVO0y2$KA>wE%ksn^n`HbvzZ(& zoiIuZf)CWs#rDyOq(G{3vGi?guDV5Tr1T~!de)bBh1ob6OV0_~_Aim|<-A*8os8{^ z9KgA3m47%HE7|cshm)}{11Fx0oyC)}*Q%4TU%~B+$}ES@3%!oBWgFRoI4W)}Dmj5< zyq!vO=HbZ{lst}!V$~U0X0=6~k^K}VuFd&6OK8LkS1tyX4~DoH>{c}jPRf#>sN2x( zWE5w&2?z2146O4y?;Li{nN(HY00`6wh0|y7E6N^Yp6G|YA0rcR(ExsVe3I_yaf*s8 zds7F_*iP21R4yfjDrcUeq__DhvX$^WZ;*3?ve~7dx9#>kN{y=Aao+X`ctw8U44z79 z15{bnY7vN+Fjh>09Hj#0C;D3?w;5~9z z$@_>fWMRn%&~}%+gJ0yNC~pcs$Y=!cFKNm6cjMYIi!D%R$eC@p0K|XGFm=XuSk*%n z&A>-m8s}?OY2|laXKPLJjN-HuIJ?f)D(;!Wp(FukYn9L$XKU%flnS1l<=I*yU1mRp zqlYj^RXMpItflno2Wuy@cILraT`*h+YspjnU~SYXb*fgO2tMFK2{_>>I(}`FAzJmF z`yHVnwsEqIR!;T1%Ok{EVU1DeW$WWK6&9I)4ptI)=v+ltRrNiAd0Aa3^{TI;evAY2 zEnd9FUSH!YxB^#yVpo;!hI*d- zAn){6JXp~XtZendcV?R(u0T6iag}@Pveq&}3;YEcy_q$FROf7u$qkGPr&9U**g^c3 zDS1I1OJ7=R1keSH=WM&{MsGyEnH;WYr8jNp!G?^`UO!zk@~?1|6rO-3d2F-e$n12d z;xtae!v^OpWf=_#S@k$CQ&zH&AJ|Q$^}(?pRkPdshALZIce#PCH853S6q*GpX~u;s z8|+V2bSx@UL{_xc1E72}I}M_6a)SMM#RoCxdV?q|HtR%Pz_l+=)g04<2viup!j;u!eC`Szvw3P@mzT&{eHqHNm^d}KwMAnqAxsbyArgyGk~i5h#5=E#_~Jox<6w5 zh?C#APIt`lidNc6tk~<^(4K=4$muAXn_oFSkB#ciF~_xfK!)3`v{#vgK4R3L%T^Bw zY4NLJjU6MU;k;D7aZ!w)@9ywG=1xUZe0Z0IH-{6fSZO=MeT!0XYq5uM@shzJf9(nv zLfi$5$BRv_T%mE)Zs2OgV5;JCbF^jbxW%B$|4r<=Ejn&BV#Uq`x3MPoX>yR4 zY3q@Nde^c(PWvD;CgK3)+{$?&xH@#!6;9mJIp{R5lx$*LBiaNk9CRA5vkb=mBsE1~ z+cPX|ZsnYV>ByrBOVLp8^RpT|u}j-Gz0{+qo@Yg4UW1PS8Au3^B$ykqQj=N875j0) zDwYs@#$jg{4`LdxOYu=0W(hAEwY3PH7+?$Ne>LB=@x?YAecuue0OOFEDxsCy%cwPQ z?mcu|bNki0r+WSyn_zd7`@1)o@2_~9bo+0tm!RzgKh?!Ib9rEX;q&+``qg7zCrlF0 zvGjTmt3m$vZ65`GjU1cRK<457ChjsS*$Us>B^3~+g5+EJ-{OHy-VTOGV*bVHXmyMe z@8vhatWCf^1O19ecVsw&6b5H*TjEai1f+zhvpj01=3g=Zo+@5b6&N?$t8F?cXdmc> zwOW|5B*$$w&rCv-vk{x4;wzn{dw>+q|A%*CPq(feBa9J+7D{%~FU*0!CE)BgUWf9Vgu&lT-+cct_?^*UcrYB=j1I!13^4h^?e3MB^WPQk8&Qy4sE!3gvZ){+g8Cah{^j# z`?;IS$AH6G4P}d25TTX4C(w2BTis_k4=2=dk>6t0l6aEd8HL-f)eY5w+AL+qm#0v1 z;{95CAiZ*15wG;KA-;+$o%@6L;B^AeaTSelyWd{_hqjhQ3Xket1L}NzMNkrDOuOw( z*77{6AKmr8Gyrw&RxMi=g`;NcFyzc5yn&fT~VpGrFggz2Q3a@ z8)RH)eXPK5^S0u8Z2Q@<)+}#qI$MrHfR|-)5)(6RzF7^l*~y^I$pg(Tg3l*tZ(~HK z-m-Lh_rp|z{fDB?XiKWNUt7hG3IOGJEU%J3jVm$(HEv%p=IWBCf&vsD=3pYO631-| zVV~R5vIZq;?Is{yEZ5?Wx-ntLY$LICGjyh>I(K+(1t|*isluz< zbJ4g1($))Ch4j$w+5$Iqa{=%1$Hn7GS}SF+4cC?wns@*Ob+ljW_Y zJPt}%GDbvpv@|4CvESYdPD7QGo~mt2X^2zZxB%o|4(5Rq++>MuirUcgiioiD{)_(r ziJ`sxi+_P$*86pA(i(9K>x}W-Ca8`+p-#nx+-O-ndYvH!GqXHz#;&s}Ep9W=@Y<1} zU5P{up4{3SX>UwKO5lR63FCedU&y-gpbpo@9wjZqy@!=H0s5i!?5DWnMh@{W z8V)VX8}~So8=4<*R6>bS9UN4~ln29vXzj?&xt?c_l@0U6k*>uhh;fh}$89hsWO*BL z?0HPZ!O6@Nri$avey@}^EuHR7_Vm=_{1`4cU_5rLwmSon0N?Wz8HF#F;)5B`xWWa6 zg%#>J(1QvUr#Mb88q>UZw8vHUtJS5UxDwv2itUJ-i}kxT@e-l6&broH)wXzy?_s1| zv@^g}cL(CoOs`L{zKo3X#ii5OSgOUM4~M&gC7~I7xZR2@AI*V|3xHuy;oW+X|-A0wRqP9EA-Va~c+Uhn>pzcJ4smW*4dvNRh8r|CnMpQS18< zQ=e6@@Gy$|0VlVVV*S8ZJA}x2zkU@+H&M73DD?V7U6-sSBHg0?KK4dhUxf@N7Dds1 zi9%noIqdhs>2r{5!Bh}!)OcDi3?j_S;r)vv!AK?(h8lrOCfSHue~vc#q0*?zj@xl0 z8R*%s(LTDJv@&|_7>wqY5j+%Quk2_)jU!0@#k^M(N#P`|#z^;IJXD<&1qT8`O$ms( zI-&agWzF?184dMbx7Yqf;kchX$$#T)Z>*{4lPZVK&Hr6kG5Ae@?tp#+bc}{=ovC{Y z+tt)@(rJ(*#@pd+SQghaXi-zgm-8L_JQg;s=u*>mfn%R%h2}`{F05!=?c!+fDBZmDVx_ohbmERA=PuRC z`j>1Is2UCxeNnjWyZW}Yih5;_zyeKWZau(oG_|>7E%>>GO>KR^2v`*+!KyGBR=Md` z{NyCyXU47gnU@ELDX=TdgSAl`yt1@q8D6(6^p3$43YKKNYz=s@XXvmP``K}~;GwYB zP!vS)!Qg!(o!dskSL8l-91?=u?19lcr4(m?E(x?TV9 zD)N=8hAf=XOzSwCnQ}{Mh&C-1sO+jh%OA)p>8)}2RJ~pQlBFODDK&o;-FK0W7X|yG z$Lx>j8ztfO+nA?S5!H^&GOKItT^OC}Ey)@eGa*#xu-|7|v=`u>)q$y=MW>ow))EY1 zxfoUseB{DQV8kKAW zaC={)h)L-0Yj_&(YXrZI2R88HkMY391IHElsJknM8}C!F6~u83HUXFSz($KiZtohY z6`ZWD*>Gha(w&F_TVTai+%i>#>fO(Yd;MWGu}W*_N;ecQZ8UPRt)jkjMH`l$_U zwZm9OZ6m;?P^t=D4`Imj$nqSk9U22<^+WZxc5uTbOmAb`i{2CU#*RHd{Y-BNa!lRS zF>!}FKbeT3R-?VPcx>6lI7FW*8{pgf>=ziLB%b}k7$#xJ zk)G#OmWKZ(CmVt z`DtkadSaSwY)ZCWnTNTV!?UwR3;MZGrlx&#Ayo$K8f>Nj)X005N7OKe-|uc8rg5Wm1-+Qa1T?o#GRD znF&8>z}X_YiXO1dMr_yMD;@FW;G5haPPCyEke?}l3ptgeaHRAwlrAs&Z*|B>g;P9Y zAYR>7?lQ;C{J!3m-#LhZ97uyda%&1`wIGE&gq^IYPB+rXhOSdfUNBzWWg2{%*qbtI zrqk1vPTg|FSZd}s<2Lyn0enZ}oB2ZC>n=Kn$t&X5{of)Nwdn|P(P83b@~tikQfu-1 zdekju`C@LTs8XTR!_rk(92O;Wlv@**>ioN2^mD~$;&FNTHxp^qo#KUg=$>BRzmXnG z63gh{Nw1G9y*$XIp7%2lS3csjgMZoJ+Jz;@EQ{3~)8+7b(c2Z@S}IM&z&xPR>F8NY zj))CoVm+YOEv%;~GncOKd%DRF@w+gdY2Y$zIZ~dX_@AQcF1-$z`ls>#9eJslQmW#2 ziopew{_1i_?z2{~p+03jngRc8c_x7xlec=!OwO2jq{kEDmOqy-4~$ipLCOW&Y_{Hd z%x1jR<^1yFO#u~Cz;83g0vEPszK5Wf!F1R@rz2l-6>nH;ur1BQH_fcY**dYM(>cS| zL$BTSFqE!pUQn*shgy3ScZfhA2OU%V=sa4H7W!=;<6aTyw?fCR2O*$eLHi?C(Tw)c z1EE)bWEHKTKLNcp^bqK6pl|)qD%wKNgMKybp|^vc@qrbXLP2j2E#R;fa*TfNdsejA z=)Xe04f=ZM=w^!Np>w8WG4yy$O6J2*#fUC5Dns3D$d8aWG8+ zr^#)mB0!_wzv_-QgfB}C1m76*6y=NUFKcQ&G~=48xH%KQgH`z2DMTTh-hXSa;!da$ z+W=-ryc2wbp9*G=g z-NAkr`;%0|K@v5`Be6v4fnptm9g)6?Xe?uI} z-^nPAc-R;2trmgEaMmoeqPuon_Oq2eY z4&!01%@&09iH`eFd}X?Qj|R5%QQ&5mg!EGp1N(bs$kFiS{v8j#vKMN`n+W%s-%Oi0 zF+KLfmAZF1VQNogv>hv&|4nMX{v<QYtK;`8J?G)sq!!- zf3nKIv`P8)lziP!N{%uj9f9}-;$@ryaWNi1j)+g0Ef5Fvd@(d_l88;o5s4`_dwwb$ zpoZpWD%0o;dwzjomz0*8lV*I3w(F+&+#KbaXgBl}8^a2O6YwwKPr#3WyYTSz^7g4$ z-?u@-Mt+T(_y;t-qFM76SGEjn)w)gFtFCTmY2Tq^P^Zpax?Xc_aJTEa_Xz2EeXrhq z`u6J|Iv{M|put0|;WtD?MhzVn9TR(FT>S762_r`(jvg~MY25gmZk{mlmgHMgCQVLF zOP`XFnKd^!x&wea6gLvv0e7&fIy0B{l`PUWgvHn-nzV5GRv@n(Apdm6?Oo z7kE_vd3s#lpBer_>i??EpOpZn)Es|iiu|fJ2jDuhzoKgUzdUNIeFcbWvu;vX&I`x< z1x3Xrcig$Kbdhs$*^;}KF1!1ld+)pdfd?OY_>o5+dwls5E1q1rYV}i3uX*O#=bnGz z#ec0`_tMMjH*DPW%B!!v{>J7vw`|?EeaFtXcJ1D?ci-FZyu1Iv!9(vIe*c3HKRWX9 z(N8}8?DJ#CzxeX26JLMxtycbB#rHq_c(U@RpHH3s<;>Z0zy9`n)gQRw^`ABb7q93q zt0DNGrvHCB{eR5=KWm6D?yef*|7rStFxGvDoIzQ@hX*EYOQw~W82e-JC0$ccGTjq?kgxoxPp0d-w^=L#qX4+Gxq}`A^D+%-D ziE3uN_MCWE^lCYB$i_IGs%wrtJ6ku3dIJ9*7y}BgdZM0ZfOk|>ln+&(5R7f;+0s8@ zTzy~BFC-)>0q4&w7DcY_tr@pM2{9{g7L+f1i2B0U7n(2r_^DJqhvN>%dGlCY( zv!|#r0moDNXl`hVEhXC$m7kxRZ^_KD#HHACCTF03pO29i)zFm8?6g#iE!UEpmzHBm zo0T@%ZcCYz%?|#U92)4B4jHhd$W$bo;j7(|4|RC}Ue$im^2yl?B2n0LE$G78 z+sWWQXWck@=4=e-05}Hc_+DQ*F=uMJh)yU41)>W^{}#h6#N^x@TYhe~B_ky#H9IZe zQk%Z&Je`teLzZURER%Cn(=55^mOOKZmSZ#h*Tgq1e_Cb^QyT zB{{cpsJLwKu@3%&U5YNfJiGI|MqZ_+sVsMQx7Z8Fj4`8!Ue~{dUzK8)j$JG%2KJN` z_mFkTL6`Pjz)CDl&SazvT`T+Rz`bS;)=1$38A-{XVrS+SSh}XoK+TkyZb_S#XPbS^ zrPG-NkuoZ+6t0`5AjeICrBGU?rA^Dl6h#N4G<9&5D@z@Am|LMx{Y_Qu87`ivv0Ueh!fuy#f2HT8-FNh=>At5{`V0H$?gDCOZ>uoztc}M#{cFZk+r8d^OS?yh)pS2t z3y(DeYr5kyEyYjb(`Yc}rvX$Zezn7gM$~k#jbBl8P4^>i@gIZRSGC-0=hHi}7Y`4# z#DchL-Ys)8yQf2ck;AL~CAgVu<9j;6O7AXu-Q#&=lvTV4aCfgAzR$Rt?zoB9#ZQK- zkG&mKCO>P3cP7_#ug!03YEAdr@$XC1-I0X2A7(S1+VP}LuNhBm_q7Ez-D{`Q^6r}M zwZk8J;nMEUzF5<}cKiXGt>XLB!lhEr!FUjL0rn)B>OB+mY_{z<4S`?`y@OmFDk8UG4?BDWEO3Abh&CO3llb)TX#}+k9Tq(i}3NokU z7%_~_txihZ;sO5{0vh8Nj8KjdZxRxLKBo~xh~}QKjn7TBXQvIt@L+h#G!P_KdyQn@ z-3^QCsHb?v+p}$%H_W!Bjm}NVOihc(z&gQX#)H9VzRjM;U`e8cHlxuu(AgsHGw5~2 z6pm7$hf39n#wsSiIaXBzBlJ}GOc)bOY{ zb0nB!;I9vuqcBeH<(ZI{Hnp0=oxO~Fipj~d+hQ;V!2UtcgxmtRT$o7wTtS|~dQSny z46}_<_?X0~QD%BhLB@?jw`hjSnnZN?lSGt9qAef)F~D|!@&Qpq2c5Z=7#)`so)Du3 zu7Tv7p07GJaNoz(C1!qZW)8Zm;(%v#T1uYU<|f`&W_?TBk0Ofh5g2}DPEN^A1baBe zAVR(3(o$xmU0|Q7=VCsjlUzqihrP$-WGF#SjhZzXOI8SvOktv8HFdkU+1(bRfP8Z+8*jN$JUWA;{Fqei zo_7z8>^4Jp@<~E=DnSzOD(dvw2fG(lJPD*!WY8QQksw4r=IMy2c$ym`Pk?1+s;W6K zOC)lMi!N6>3&l&`iP>pbN4(A}E+Rf94-yJ#0R3CNMgcPxNFmZ0ibhiaMT)8sqpF9D zdbollag>OE%+TjfHaG)W@ufM(4WfC-Jmik0qq#V|0nZ@#HjxF2wL2#xgo{ z@>B!=ZEoB&-M&#g;Xlb^Xtuo|gAv_ePfy2~13PiSaRZCo{Gn(i?D-INy)>j^f9$lpl>9Uo zkCVt(H(rfR$vCb#k;t(BCCb_bnGQu=U%4<4 z4={8$jeBD}+`elY=}!2M`VR*#mjjd+zFNDk)fSBOb@{pyx+zPXTcFt+5D4%AGzMUv zT+QcW23*bObAH>;u%q4(KsT;Im~M=hVX6BA7%#<~c1;0S7(n~>0NVEf@SCNC-<-AO zH>w~NW)yVVCmK3SKI0z`VA|OLx=#aG0H`X|9xycE3V+f;{|*3go^R+2pmXn85rFQ+ z0LHTnz@>u6jqerEiO(tk(|Z~~f13cLX+MDO9|7nd2&Rxf1oDN-L)Too@#*?D-7jW; zG55df-;Br9&G7$|I)?8`t$)BOE(iX-xCUHQ>FHW7s{Xxr{ddKF@kMDJgNrYU{&!*c z?@#BVB4D)G7Zm}^zaO{%#uWaSi$a1A`dgmfzN^r{-MV1*g7yaMo;s!*R;KME03z$<{YfHi<801pC|0vv#Bz^#DM0Q!#x34YvbC#Np%_tUx3E1k=Ng1Z#>dI-U#dN zUtu3Sl!G0o|D)>9_PTl2QeK8K*+ssN0v}Cf@wum!X{OG;qr2*k4?+m?CIPo>{23G) zsyFr&mj zcNfEk4HHR8Ng^{dQ`qfx;h;x{1OE>3;DZl}r=NaWy!z^^V(Zqe;-il~66epKXPvKn zDbM(Tym3H#*E8Kf_aHpT&0-(m$|EeIpUZe~jrXbr$L4=8*$jB&8kkt2*%O zF?^k&2ZjHFszvWqy>o_f@caCz2{G_cm5uoE?eoUo=GQ#>&H<2+PX72Fd0~DtG63ov zzyBz?zG>V$2jF8dyd(Z+9`4y+_n^Mdy?bC)hv(l>e(8>I--i#B=MY@YB>?~ZD@VU` zuIhkeE8W2#`NxdkDimtS@EAyXu31~s~a1S=*}vBg&QMhdfOe8{9ssZa{!Gq$ z_wJ1|N;ma^Me!Y_M4?p}+eEs#;E;-NRw9Q(~8?D_` zpOSui-tBT@`W8{R<>Z$1skx#MS(Ls77yoamNQNX#E&TD98Tvha?%uD* zj2W{fJ+Ak2(37XeP9GuVhGaRfw9A&8$0UnFxpK>fF^uokC5*pN${)_2T`QCn-;Vn* z+O?Ab_1j6|WdLXg>*@y65B(GTbv}_tR>db&OqWodI&~7k!NJ&v8X^V_8YIHQaaTi3 zjN;wMks}3eyu(FoFEDIzN?OH7+KP2}g}Tpj93b>W&z~K_o@5EQX zN>N!^DbAift7L_2_3VKbJOOi~5E|d5m`_{_;Xz?;6tm@Y@t|BL zHpq3@H+9IYPepTt?~s7LU7iqwmI@KK7W0@0Kcy0V0ohb6Lik4!{zZh}itz6t{0X=4 zoe|!eAjD01LfDpKPxo3Oo6#Wm=|t|Io|f@GX5mGz>?I-B?Gf_OF}Ls*gzt;+aR@&N;b$TI5`5)>LnJ&fIWm5dQPKw_T zNmuwb2!9>I4?*}*2tOI&XCVASgny{16i@Y(V*N-dwojMhz%nU5T_;7wq3ZCy2u}{Q zK=?KY-yY#RBYZc6AKX-maXqD&K2nOs(-GG)DYmSW;^?93@HMN3WL>#iMnv2YenWVq zvWmO5Yp0+N9Xbzlc?iEDHYO%AGB#q!knqUl>$-O7(kW=zu#U-whsYQ><39$5$jId2 zYv^IvFpJ?H8y^uBI|R{3MT8HzAw0PoJ#^~Sp}pZA6K@TV4UdS7KzL%-y<2ebU;{^b ziH(mn)zCJ9Et9*$17is4(B9G!NX9V!*w~mMvB_68YZVB0c<5?)=$wr3L&6zBL~L@K zX3bjZ?h41C4i+F8S@bK%s{Cz@(B*!Pm$3(^JSfUEiRZK+h8zOpmdo&zw zIFMH{k*KZ=_vFwX0S)STcr=X$hD0$wb_fKi+C98qpO9V+ynL^Sfn&rCkmcUJBOHU;-Qq_^ z$Ak~485-rIri!l-IqFxrweXz3W5{uIF17+3I{cIVTp{A94YIDjoI?z$)t|d`KgI0N zjT$vd^+)EV4RiH9o}M*WEX<4&59UXR^$ViJ+K1aBFOP{Yzx-01IB`N$R8)xXzyDtR{L@L*H~8h3U&J4O{2`W|m0}(G3Wt7ot7m(( zM?=>S4IRqm(#dG(W}~6I3k}^~velNlwbG0-7>8F5w|LLdvuk5GrJ{PLi zty`lI3DHW;mbMP;)T2j_YiVz3-8!&!`)k_;G-+}*`opa{bnVosOQ#-91N^UPjPKU% zJ9g;;zfA+$^$6|}EZTOswrh{88un-k4^0|3zPfGuPF;I6YS{H^!@^?edTkG1U%##h zbIlb^8n+H?d2NqIzP=3``1tr;d^PIWut9@hj04(tYU9-wt_X4!zL9=#+vZ(52KVR@+y(d}{cD4RgMx$G2P^v8 zLUBd0eS7sO3jJ{}OnrDnUs-_%^tu%7O+WOHaH1WKFG552T-*xq5ElIYBjt(E=&=j* z*j?ZQGgJQWP#2^AQfU+4Mt~OW+O=yBoe%`*+@L`NjDT=VM{x>WXlyG6GzOR)hw;Be zkw1(Vqnpc88I;<@80di`b6-+fde7=%zd?mhw)%^rSk2s@Q-=ThWU!lojZ4gPF``E`f^m@%{SjX zq%Raax4}H(T^L8pEnBw8Z@>LkqCJ(Eci{w;Ja+7u#Q0m%9W+Rc!9UY9tsJy|@!osy zJ-%(*w!#~3xS6@T=nB+_yL@i&2dHGz3z0`VuWsGDYf6HGd&6CV?RvoryDE=@4)O#ScR zzhlRa#mL7Fkcnc_vVHq@MFZsn^G%X@fO#e*FT{~$0%cg~hYuf?1eOiv2X&SYmK}z9 z`|Y5|NZ;-?@T!+Fb^+bCRXut+$it7qA9cMnf%uzX=7p*MopQo*KzT{} zT*_fMbQkdf_)i*;2Yug`@_Nva^AXlNsxaSu2(M(msl=-Ca`DGJDP?(auU@@6Ko*Kg z2l7GDW70vLyrdkF|8>zpzLV$7BgzfspY<-rYzm=*8l4@kg5>&HA76kM>9s%>1BE{7pHh{4+l&SCkEt7M5|!8Red3!_-+W zs1m=BayV#+h5Qc%ze&R&9PSH!SEnHaWdZZ#vg;P*o%QJDs8+-ub@4LH@%KSKEMYlg z-BK4Fly~<$G3AOn`A>JY3k=J8#$Am)fig-OK9e#AG(>@hwLiG~xTqNq8_0(*LQJb) zfBjXWov8t&!32|zy7I)N#hs4dfB#(`di626dQPl-c=`}|f38&_cGEXfj`>Q;k;kQs zCk-DPXduRb!|FK`J${-mX5u%UOqi@pj>GmBp)vrtY{zs6U*@?gh4~XF)8DKQ#5FBm1ojm zl;`fOlTfF2LY>qeG_-p~uUiq#{8}_9{5y2$;Hv-8#C!=#0I!1lmBPfS{<6Mxo|8|H`07jF-f z&w_^4pkakg$Dhw)+*$z|G`u(h8d#oLC&i*pGRre*Fv~M(Fv~ORq^_?k{Lj|LpXH40 z3;J0uAPpwero${N?sU*h8mKlEhRT=b43ID07ABvW1sY}ylD|}bCqF`QCJo7;0c&hB z$*nxIPGWfuM_FK<)E{*c+h?;*>aqn-g6R0yu9sR7fAsGc_vzE81Ntb%q=WS$b;=Cs zV4sINX`vn4TC-n9H@3IzGf=(e2$dV>h01lH;RVpJ1~k0!P_8_E62fyCsvLAqL!R_! z`wSY)K1P=}^}x0H&-%iY{{aIAbY@WZtUdcc3Swh^27j@!9yjdQ|XERS&$Gi8B*&iZ}l>Z$I2g}W%;T6!ZelBQ0 zSzvi44J^;BlO967N*b1uhO8Upof)7ZJyOm~jZ!oaPxdj`KAU}vK4{;dE|7oL8EnJY zk07jBvqnDm+;fusQWMPlpnj=xf_Yha@bMJ6t*D=TV?Jm=S$G*V{L3iMtdmyQ2g}Fu z2g?WZhRAz!tn#kxaOngMcYuZkpkXd(psL-+xCLbc>Vo=*_(K+y{6nsbNy{B~+##QT z{&_`@NdxtZ(LtIhTMVlmdRcBS?kBf`hSx!ZD$k&Sb&^@0pFo}TX#NoSK%Q0J0~(fq zhDD&E1adS#Em9%MIw{<(kMT0fJ=6vDKk+x^KP)V)GjSlE*cIZUf%)Q2$E9fb1Lw$8# z%C~FDK0jMA&(Z!a!#;-CoSd9}#FgcdWnkXCd5Q*i`KnDz?L6T(>jajCKT{v=e9_g% zV0kVx%5$x7m+b!#f98F3bTsopKJ&~os_(@<4dw^rj2SarG+c^~OXUgiVV$&|b<&@e zXV5@Z2e0e0YDGR_ugx~pow7@pE;2beSz>R7WWTPUpg`JeHo185VpXm&<)i8y_J!)A zg}i6mz`BZkA@)Z(9-v}*KJb)XR{e(Y#>yG0eRl6-JYzjbs=loVXnd-ef`n+ zR`_3c-F1DjwI>HxAXlItt@7c?C!drfMvRcyTO`ZM$|Tm5< zP_76Z!;l8nr<6msh2+srXQX`ZY2trI?prmZx{rafz&-}cGwY;>XT=l!KOKKz?ynR} zq4Oy}ko9F4_xHg*nCDT3CEO(Ls*@-alHWJpc%$m~U_XqiKZ!eWWgd|R6KF?%Q}#H{ zVc(8?ckm*;mjEoVRQ5tG-K(nCW-@5P=TH4nnHjj}AUN0IMv zO3Z1=Yp%IQqHnEmAs*~+xC3c0!K8ya<0DX}%(z*%zWdlD`9_Hq?X%v;VEg>s+z7ep zo+Qc&zx;9-`F+{*57!LOe)zy9j{5931FeFAfo$8Nv< z_VdIO`$iS8Oq(=Zd+oInd)HJxu+5;%v+rZlL41inWuA0$Y(Smmfn|i{!ORotltK1Q z%(jPPZ;qcKFMnzNlVywY4_R7){bKL4oMJ^>&Y3eudje&N^Ub7*xN*)I zd+${FjfjYlR;yKFcZ$jfx-*PP19elb%ses63Cjm@H+9Mp#|)G!_5+!B=KKcm=W?4L z;Bu6zKSB3mECF-?4~tozH*emoXdr($Z;0}tXh=y(k#TWxO17{juka_Y$#c>|yjc!d z|InUe1j-Nl+FMW#SO!=o7%%H!;C>$Q6bA+dT9NNhV%|vu(p>Z5y3XY&)qgN$ko_N% zuf*rrv11A!y^9dg&$k;)^e;Ht=8n z`j-mFIRfxWL)|tJZR8x_z8!XV0%@*$T<-c!E8@%k59@!F$0ht`d81BTnD49?Ag8J? zfprp9x1y}8_KkH7<(o1`{8Orni((ii21?x9Q3XR-mEvdPI$RW z;cv<*b$1yi4JHsb(nT3!S-A7gJ0nKx!1g6lez zd&&}d&N75L<3Zr@cW`&%?=JtWBi!?&t~?=KoMWFbVS>cITqWNo&)s$UqbyO@Y0ox* zxSQ)E7$ZIQ4{%rbGYxb6i?(M8<&td>>0lWopICpeu48-To+sq(#*G{0!w)~KpCl1`{roCyWDoqE$SUF@_;+ z#Fw(Q1$8HBF>y!#^r^oo?>g4iziR#mlc;<0`rD; z%m>z;ET_yf)Wb4->GM+F|KJ+_?z;NzCvg6iEybrVgH`}AJWBjIRa&i z`mSBORJ}_cu)I>i=FAq{Lh*?(dEM>$}7#I}<> z=9rVbXFjkmVCDnAS?9B^Wj%&5g<97D&HvT7lMW^S?y^x^&dqPL+`8+Ob$-(i^MW!@ zK9feuI^^g)`Uo2GitQ@*Sp1c?iTM4Qx&j`!2jSldOoMwLxKHCBE9pSvvSsGXDp6ma zA2M_1ah%Vo)ODED_kW%4WyI%U=s5j?^q~HsZpLTE?}oR7(c^oop&$PzdZB@*)O8O- z_cHYQhVF0Z?F@a0p%)su)O8Q)+^1y$SOI@?pO!a*vVTjUJYTf0h@74ez$~~t18`UT z=88(~`9MThr(#-x7z>7=&5un>OB;#)ekA7n!(kr+V4u4Mz$K@Q`?GUW&cIqv^oRNy z8|Q+#rf@yhb|zqM_`{zSN|(Zcw6?`9{rxbun~pMlj`bP(oWG#HEk|4MJ?f>S=$}7{ zd9p0@fg|C+C!hoR8z-k=jf3lCoC~#L{+4UrTrYnAl#~ZBD~Iz)R6oN1#ne@(!&f5B zbF4pEM{>MG90=wbhSBFgk9zeK>fFPqH(z7KTr=f*BiFgOzQQ?it`B{1TFQf<{W8{i z+p(U;yg~}*p2iXf_MJHPWc$c^oox~8YW8K>PoW#lR5xR-iff)+YvURZ_b+gbit9UE z_vacL)y0U1eLIc;Fb2)Rcp;1JFWWVabD1vt(d3Cizv?^bG3viuFS`kIw_NYzTG{$a zch@@2T*Pvh2bDg@gX|*^hy#K3JApi5`}M=uN9EH+W7WC@=fkNc{ebnZ@AP%kMBu=6 zU+#h6+&7$dh(#$1(4cgY$P;Y?}!t z4(xM~C+u6lI4?r2^>KZM^N3VTo4~bKt{-#F&s`q5mxXIIT|INgOAvmwhxxkf}&*Yjf&eF;GC}Zw8P#(wDl1J>{S7m~GX(*4i*6G?Y zeXOUXU|wOYJ047%a!#F!>up>k;d&w0sWv{4_or)y-~A?K{xPh10tfErVVU5XEtN?> z`xST#FQ>4uFpGUqf{6#`O~?x>&aZQ=iEA8OE8{v7*EhIM#x*9cZE%f@>q~Pc>u~>q zOi3J+JYwC|T>EBx?&-4*Ah2&kaL0qVF#osRIYe^3>m}g8IZe)ubB%@a$aOBRuW+qV zt#KLY&rKc5q*R$O<#7=B0OiVm_RX*kk%DuVV_6q)ywCnQ=_W4Z0rmG*W~y~Vu2*sG zmTQJwdtPp=7qU!neS~X;4y;j`JYZt(bu`y*pvy6*-u1nMOX`b=O_0 z-ebMX_K)>HWr6&lEHZ84Ld7!ib3ta{r2{^3|enwHLsY$0uhG zl`q|wCo4{%b5bp9HP|qC@ZesU@10FLu#TBKY0{+KIKM5YPMxaefw4zY&0UydAM%|1 zApbeOqb!gg#J{#;obdM^WXrv+t&u)Iur4+RITS>kIBn#9a6a#LKb5@Raoh5dHW@F)_!+_Z_GO5c=c@|8e52uzRd5$;G(bp!XR zl6J}*^NYMD-K>)__wv+VOk1VTbWqo*`oAtb%sw#A97vpZRCC4b7jn*t^7s$ZR_T*o zv;CzkkzU40V4cS@$Ffa2DP!Ef!@Ut5D<%xByQ zLHYXu^I@fkgYzeUSMjV#z~2OxuRp8bE{a!GJDl0|aGlp}=KwDN9sqF}K!0YKb_hZk z0y`55VJ1jN9e1!eE;zSq5f@X~tHrqMRFKDr<;$0^#~RHU)KNcTU&!50J@r(LdIxI& zClN>Pv(G-O?BU0I<;s;Yn9qLmg%@5>`DwOc%xBc;AG#;T^)&2%<~-}~h~qfq?=;IH z$HtV`7cmA&M8A&v8i!zP^$5m+P@Bv+=$A6hKAhQ~G0PO|vSf^#IA-D;!h7h}^v1qU zD6@YoxPHL2Sk_oC5h$+=OO=A*3CF;j^e&mQGk$)7zL9kk%Mo#9-+{7y@Qqb+S+3qU zoNSEWIDX{#m16~tRYEXUdI)%Nt(9YP;!gQzy3fpuQGJ|K7=t|moEZnl;v9Q%E`sAe zjywBf+{rm=_Njn$pdVK|0*`M&9rak#4rRI!}X;XDGzY~&yFiER-3K~%5b5vBTD z9Di`^!Lbkfx*Tsj|7fXX92|#70}tjO?w(QW+^oaMhvPd}$c>IcYCOrlJNxY%H*oAU zH*J_oBk`D&YcQ_GId555Sg7`ha9xdgNqI5(uRP=D;I_4@-#-^)A48GY4dfr%1yyfx zO^*8q7}k`zb@K+x?~Wf<{Nxzw|Fw7R;Z+n@{02e=U!({Eg_KJOe1c%+u{%3EGdr7L zfPev_Am*!p2_XrA5Fj@|q^J?GJPak!D6s|%5;Z`?sKCcdL5hlqZKTM{d_2Slz5pYY zAXs|lLU?HV+5Xo**!%6>-8-){zd3Wx+`V_t@9~^)`==W9$LOB1^~Ua)v4m&W!fI@!;7Z*HI3!r*_H5G&DbxaH^y$8HJ2F=V^6P?#he>o z-dNTgP5#F5H`q0LIWWFbux{X~1-~Y&!<&B*-a+`V#7LXpEPsV4P`$?v( z`JQcjH~bcJRasNd!`D?OM8O_tdT|fH@jva2c}#w@w={Vp;6`RJ2zT_pSn46b z%a|YLLCl8Qav(x^Ce)l4$O4weK%jRx4+?O&UFyPaK^z(oJ}>~5BM}h&d;&x=p9su> zdBATu2#({!k^4;i^PF&ssV(?3=F1@PM1~+GKP=Bkc(gU*Qrn5}c?e?77?~!5Y&p{;2F*sgb{-jCm`e0BMJ1W5*d$J}79dG}({L;drnOc_4bqYAT$VRby)~6wS~Ls1@pjx}n=q zJW4?$(P%Ud6{1JbO!PEbjy9pQs0|*93-B!bGG32Az-6R?w4nFXa#~H-)1&kRJx}kn z23o0Bx;4$3WzDyqv?{ITR*kjAddJ#peP_kmkJ^M~vA5W*4t6}Jx0C9mJK0W=Q|v5u zmN`|<`_574dfu5kJexnp=keuyBj3Sm`5u0rw{|jHh1$#INr{FZ4 zg{R^gya6A^pW_J9oKSLr947T7mln`Dw3M!~M%wf2KiSXON9@n-2o}YnS$F2Lcs7{b z&&IG~wuDu)H`#maTNdk3M>%QEd}lJhPJO7pQPk_>b=7fN>9KmE{=F{JOLdiAqc=iq zGh>vu!66xKL1}mw{uFp4hYom44 zYGX&+_uHpg(23=hyqdqx-{nWRbUzkj<%{wa`L3*&u_{?@P>0lU^}TB9we&i8ojvMF zudg@HTj-U0-*^w`Og&Cd(o^+AdZvCtFVs)#3jLy9rPt~=^xJxu{zxCzpXrnOjE?l9 z{5F19zlV=}<|q3@{84@&9(Wl+_d4Ob@kBfy*W)(CA-zc@AaI zw#<{$WRWbE3*|F%sazq~%1xkIJLDc&C%=&2$uqL4>Z*iFQx)n3Rjc->I?%K0J>;$M z-uL!;Ep=O+rnB^P{ivR!=j*3*xn8E1>sRzT{kncj|5YE*hx8}yOqZ z>r?An%dtJXpIv9SXNXleuQ*>h4Nemt#oO~P{60R4=kmw-eEuANoBzm(+Xrym<#rHr z#d7gm*+Y7AupBG%0k;K!*W2=M@1UC;m9! z1O+LAzVt=8C?A!hBj_0V5hdb5_(8k?tj^zYQ__aqNwP>Td5SzsR+5j&SL8H7)TMo( zFHg`#v<7tK0FAJ2wr;UHTj#7!b`N`?U2fm%_|8X8yxY&cSLBK&lFD@|&nxtLYN=n< zn{}zb#Du*IC}>}!>1Y+&gQB3FWuyl5@JpCai8Rf+%g(T8*(H3p+fv>mAC?tzj(5s$ z@Xz^1@Yzr{fFe?&K zR^O>sUaaSM{k=Kfau3=s2^gBpz{8*k`%wS~aSxmTc4`i0WE1I3d(r3VX1bmJKnGaU zty1e5YnfGLRfCn@Z=JWIVP@TC_q361*&OCrygk=0u}keTK(GnBiQUHHn8i3#Yy_Ld z*0U{a8{5uyvRbyA?PGPUo72-lj^%K$<*S^bd@7&8XT$tk%vbTXd=qHPPO#;5{4;)n z{{Zu`In2jsH`UE|i`^*MRz}MNu-jdrSL4AxcQ<%aPu&2aMKira zUJKn_KcI8;unRW7#;i!-Pp!y9OVN6C2%ViI}HN@jsh=YdvF0lhvU z&&f85stIb5>g+x4Re4*zqh2#TNH5X}VBcV7Lcr-jU^pB`A_}rUMplr6AaM;?$uaOR zQM4yTG=)wC`%yz{X&r5#?VvZQR-siEUQ$Pd*A)Sn4OeSaqMc+X+l6kSm=3mfrkE{? zMTsaCWujbEh)PiY~7RSx4&t!mV2wN7nP0UfD1_~&??sFQTE wPSHbksvfS#=v?sF1-cMyei8V_+29u|jW%D~t|4#@folj{L*N<${}%}S3sXxjq5uE@ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/w64-arm.exe b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/w64-arm.exe new file mode 100644 index 0000000000000000000000000000000000000000..951d5817c9e6d81c94a173a0d9fead7f1f143331 GIT binary patch literal 168448 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/distlib/w64.exe b/backend/.venv/Lib/site-packages/pip/_vendor/distlib/w64.exe new file mode 100644 index 0000000000000000000000000000000000000000..5763076d2878093971a0ef9870e1cde7f556b18b GIT binary patch literal 101888 zcmeFadwf*YwZK2gWXKQ_&Y%ng1RW(P8XvLInmD2vn2|FwQLLg=QPF6m6)O!hf)zD* zk~YI}TKcfpwzjp;YhSmmw^tIhm=GX@hXhm%;seFU8AmiICgFL0-?h&q1nTYY{{H{* z(VTPkbM3X)UVFXvp6Z)cxZEz6E06ze+vRHJDgUa}-+%w7hwPE3ts3e2$M7wuH|NB* zoPPcMuPq8Jth?{-y4&v!)ZG4!Z`>CT+;LZ+F7b`P*S--5UvpjH-uv#n>-?gkf|6|0 ze|zHfzwAHo%+Z1W?_PP%(a-t*v5go8j)Mza&?pPjFVb;B~PDv zugZ~!yyv=H9{Iz+fu~9YdB5J4Lr&GQflArBlyn*ycu3uBioCiiPRnu4l9v@ZuKm~X ztj}@fjgW-wzn&b|od8h(naed{AnpJ1>~XogGO_>5zw_gFEs2xY@+yA>AQ`(5!H|Ce zmuuenb$8w#zuo0}w2}03OYA49_9|s$8zt^A|b= z)fgG8tB?Zc{7bp2^XnGX)sUrd0&ZN_^YP^`DtFg{`zUyoj1^p|F)aU=a?{BD|Nngf z1{yoH#xwMM8>BZH_nStwW)R%pvdtENw^!#d4j!Q3Jt0x;u%1DWs8&?UI zqp9h|dMZ{@7EVpG%WXXwE(usu&!)lC$@Y(yGD**Q*#aX};&qE0cH-v7~&5!7}DrTmchEEO&=>CP%XgXD05h;H+mb|ON zDuZu?%*~ChO7`3WWE|Tw}j30R?cY)kTc(|}~R^fFp9 z*8PyyYwT$05#4<#{T-;{IoMjBxykyEF;2g93WGS*2y{Ki`n^5dZ`f>)ny-R4>xZXG z`4^>884KfMbYlbojMMDa9&fXLbc8X|yKcS|Y8F0cUFmc$^-7NdffYU3M|x>LW8GWoj5TJir%y&^okpKdN3R@I9Z4_e(@RKO8FAGHJ+G0R@Kl@cWoo6h z)PE@aZD$-WgFowM|I*@?i32SfPK#O4cOJIwt5b7J?dsqgb>p>_o_extLzV7$L3Qa{ zBrf_ig*eY zP|IKh=DyU8=Lv+fwla8l>Z5W->3&I`2&=Ky5g+)>^sWv1xK1*~L$!!DPru~lnm z0G%($s?IzF;k|!A>R(?nUl`3CE5kT-Q$9^T&2H{^?QAsk3qBLl1v~7PtzKuIe=BU53)L-4D z!yBuh8JnC67k|p+&lLF+U>ZHo^h?A3b{;e>U0LkoDp&Of#XDU>Dz<+ud5WpMBrnU> z3Ya$oG%&-CbaSWe|0d&MQYRVxxd~5iyE`$?8J)Q)Y_^(R!eDOJ?a3Q=9vgN*n%K;K zNNFjdXd&ImG6{ZW+hZYw{^CYFweSEC0M#)+wqh1 z;32JH22-X7`?Utp52_ET^tZHz3sicy)^Mgu?^o#^TEkeC-mW!_ldRvLB+m`jr{_SJKamds@Lj$l<-O71k+>%sd?Vp2-=1yr z9VE7D^W$jnu;je1a-<8}zd_}^uLqCDJ$mp>l_TBR{{JE;YSP-?YAsCFk9bh-W44Ok z>c+kC2~p#S9UlWvvi*Og>|kdJX|nNMDR5X7*lhcgP64OS>-o?dd*c&y<0u8-gtmXa zQ^4uETnezLs&sQfi7s2wEZtmMGDpb7;U!F{%;Dhtsl7-~J>5?aER-GubawEQPhqKv zG}5@6Wfe2uc9zXQkYnK}DgS4m3m~oR!=r*ZE@7na^~t0c!#clgPqhMd;N!Ktq`$O3&?ITT*3G`t5)AA+A zgJNy}E@@cyrEY5pOq@P$clsEnfZA%^;iTTfR?=CyBr5 z$%mTtF0(s?D|Koz^#Gs!jiGK*Eg8 z;$i!LO4(ZDp6=C3SPgY{7eKhfI`xUHwA2>9(@-RSUAq3#vgmrd2s z#IA}Q=3X^FyQ{^+*lho0KxJ>3>gHo{0m48R{E#Hzc)CB-+w_-=5x^oP{CidwpP!1i}CLx^sn)d=yVC@Ctet(@ttW#=lbH4dB+pByrG zSbz7cIUPscky1A`(`)-5Q{*Rg5}QSc9}#uGshfT2t5Z*1vqNOVxe&9ST3oEH94TFnlFq_(rlfcpb~|-O(J3{o^Q5@3J~vyuP>TB<*eu6LW_+Bsa)hKG8LeP0U27m$7`*#j*Z9k~J?qt}2q)U0JkpF%%@g#>DiM@~H> zKJHjUK8n$aG;}Qu0imEl;e4tC<~V6QqcI|F z)M27?Z_Dyf*7rh)VM*~Zc|P@Y1%wG7eJWoj$+O8nz(-fWf^7exZ7@Z4T32mlMI6R= zG?TBb+^QR`dD_ZtvM>D@$*sIMoT~K-5e$!|&YRogs5bL+Gbe}4mj&d+$!hE)qsF>i zM|h>|9#C`*CS8W=8N*#EWix2wGDM(dlbL$%}4S z?7kg}&PZC)M_e%Ut)gwJRzj=G^h@vGrh(dIeCaG5-DOs7B^z5D5@!-$wrbhNA%)>^mE79OOA;2eHA#(Nvvkjz z(5WpGuCRBBQ=AF!V8Zj&gj3^mRbyke#+acsJYP^lm`0WGHJCw_^%i_f)n7w>MeDl- z>aHFUMwXUTnJ-o=e7q#hld+PF=M*WYiZ0nFXh1W1*=mMqFqKQ$GQW0_Fs9Tz(7j5q zW6e38mYoFKf6sQ8D|Ow;=oHtNoSHZ%%5E1(-Sn|_W3C_%#Qzkk0S*{G`K*&W~UNN@hJ4r+j>N_%`g9O9Wzzzz(xA_fl2VyU9@ zC;@Gt@qyTw=q<72o!C2WFQNfBUI>=58J;`EdXNnlo_zej+FI>2(QGIjEV}lj99LqL z-qz-;?Q65`MDAzpdRwP2{r!@xTzrg;&!)*TU3!X`yB+O6Qoc82u0z?-9&cqr##(2h z!gjdE(6;s5NrI&GGTv30?W#=tbv|H<=Qv+4TGt~}3jc?yXUSSFvfe?l>Tt2!xiT+M z^8CaZ)>f4y&4M6@u``p_TzXrvqP#V88YYK`%%RenPd`hV>=&GV8_7x+hB_DF4l!?@ zXiuUmVr>}EAEG8accV!DjhzX8@!ZB~13i)^Cl)mS$+Z+70F0W$;Rv)(9E zt%|hvWA(bp`cQOX@bhr?`y1J3E?TzmEE!As6=_fpZd`PpG5}>2B&x^GIt^+rHbqr zg3rN=6%X^u;6Ijx$s~ZdT(*A7yaX<-hd~Zq-Ng6Si}?N)fArME{}eo@rasLhGxCcD zU`+iDExN>*Q}k15JLPnyAq$mvhFIjb|54IqOec(0*~Y?0HF0JupMQKGYdO{y#f{_Mfb(BFQTElOg z+}CDG?z@{Lw_jO1V`i^FF$Eb@zAJR&6EEGVb+_rJX8V7u z>UUeuOJ*|PhMyEQsg{>JIeafv-{0ap7W^#Xi3P3r^D*-?p@=EE^DGk486%n*J&B2aKbj!wf6K8gKa!z%S;$(bqwlI*bRy(|m zr|sX-DP+kMER+?!1X`^cumG{DWwN%XYq6GXmUpHtCq0KR(acbLa?&$Z)@CIYlVq+* zS4xUwOJHr?{bfjQljVYHsNZ6PaB0Lk*{LVgdx^3;#LPDE^HeDmvEBC1+o<-WvDPHT zeXv@r22MnkO=rSN+*$50uqM$>s@O@;YpfsApCbS#PN^gz?zeVRMOeZJYX@(L*HuZc z*ccoRGtdU>aDAwlg4+|1SYK09INhh4D_Vs_lB~3*X7x6c1?t~7F2@xgW7cmVsnPS_ z$Xf}o<(eiX5kx${9?dpdIo%sSMK`DW%qCT==rJia+!|gf#ij$obYHJ(AvZDFP-Sx0 zPcP0vIP>Lxrah7~6vi*Kfv|&AA@xV0QDr?2nQN&+^`Wiowr=EGiPhO!1yai+ zwKgMQYAf4I+rky-rJ}mwd@z0`csnAri9KP#z?Oq#Ghb2ZT$s4*%jIl1+hgX=O3(7M z!SG^m5dT(o{Or5g4fIjWxMZdqW(UI|b&A@wM8@HQLI~(hU%Lv~%?6Q9`^Ve(g~=NSb}wG)m?9fH zbuDrLa{v1j2!)vnSXY#zEMY5lS+B5psC8o9EK{&pNc= z_U!ugG+&wHdTun0(PMtII7l;|V7nG;*K0Pcl6^Aid7L8F)6<2hJr9V4PtlUpEa-bv za^e!nG@Z=3+06Xr@l?#*uZ%A@(wm+foueCT*zelBy1faR+Vor?O2hlG40zu)l!>Ht zchuYvOZh#>s0bN)TffJ6`?RQ;w?@CGb56`0of9<<+GwxFL5yS7tm9!Fxy*+hwOgh2 zsNI?PC+(?aujIK8u5`KTr@mgymJ#<@4}=A`MbBOgK+I?QcBJcLHc@!*pOJ|5;Lf_s zK~kAl-n$onNyNtHKmAetJ4Y|wruTiQw;hBDY}DJ*SEOR2d{&%AsI9uESj%>unyGen zF`y>b!F&houCEyfMn812(dM(Jomk_l!5TM84VfqZL

                                          # pre-release
+            [-_\.]?
+            (?Palpha|a|beta|b|preview|pre|c|rc)
+            [-_\.]?
+            (?P[0-9]+)?
+        )?
+        (?P                                         # post release
+            (?:-(?P[0-9]+))
+            |
+            (?:
+                [-_\.]?
+                (?Ppost|rev|r)
+                [-_\.]?
+                (?P[0-9]+)?
+            )
+        )?
+        (?P                                          # dev release
+            [-_\.]?
+            (?Pdev)
+            [-_\.]?
+            (?P[0-9]+)?
+        )?
+    )
+    (?:\+(?P[a-z0-9]+(?:[-_\.][a-z0-9]+)*))?       # local version
+"""
+
+VERSION_PATTERN = _VERSION_PATTERN
+"""
+A string containing the regular expression used to match a valid version.
+
+The pattern is not anchored at either end, and is intended for embedding in larger
+expressions (for example, matching a version number as part of a file name). The
+regular expression should be compiled with the ``re.VERBOSE`` and ``re.IGNORECASE``
+flags set.
+
+:meta hide-value:
+"""
+
+
+class Version(_BaseVersion):
+    """This class abstracts handling of a project's versions.
+
+    A :class:`Version` instance is comparison aware and can be compared and
+    sorted using the standard Python interfaces.
+
+    >>> v1 = Version("1.0a5")
+    >>> v2 = Version("1.0")
+    >>> v1
+    
+    >>> v2
+    
+    >>> v1 < v2
+    True
+    >>> v1 == v2
+    False
+    >>> v1 > v2
+    False
+    >>> v1 >= v2
+    False
+    >>> v1 <= v2
+    True
+    """
+
+    _regex = re.compile(r"^\s*" + VERSION_PATTERN + r"\s*$", re.VERBOSE | re.IGNORECASE)
+    _key: CmpKey
+
+    def __init__(self, version: str) -> None:
+        """Initialize a Version object.
+
+        :param version:
+            The string representation of a version which will be parsed and normalized
+            before use.
+        :raises InvalidVersion:
+            If the ``version`` does not conform to PEP 440 in any way then this
+            exception will be raised.
+        """
+
+        # Validate the version and parse it into pieces
+        match = self._regex.search(version)
+        if not match:
+            raise InvalidVersion(f"Invalid version: '{version}'")
+
+        # Store the parsed out pieces of the version
+        self._version = _Version(
+            epoch=int(match.group("epoch")) if match.group("epoch") else 0,
+            release=tuple(int(i) for i in match.group("release").split(".")),
+            pre=_parse_letter_version(match.group("pre_l"), match.group("pre_n")),
+            post=_parse_letter_version(
+                match.group("post_l"), match.group("post_n1") or match.group("post_n2")
+            ),
+            dev=_parse_letter_version(match.group("dev_l"), match.group("dev_n")),
+            local=_parse_local_version(match.group("local")),
+        )
+
+        # Generate a key which will be used for sorting
+        self._key = _cmpkey(
+            self._version.epoch,
+            self._version.release,
+            self._version.pre,
+            self._version.post,
+            self._version.dev,
+            self._version.local,
+        )
+
+    def __repr__(self) -> str:
+        """A representation of the Version that shows all internal state.
+
+        >>> Version('1.0.0')
+        
+        """
+        return f""
+
+    def __str__(self) -> str:
+        """A string representation of the version that can be rounded-tripped.
+
+        >>> str(Version("1.0a5"))
+        '1.0a5'
+        """
+        parts = []
+
+        # Epoch
+        if self.epoch != 0:
+            parts.append(f"{self.epoch}!")
+
+        # Release segment
+        parts.append(".".join(str(x) for x in self.release))
+
+        # Pre-release
+        if self.pre is not None:
+            parts.append("".join(str(x) for x in self.pre))
+
+        # Post-release
+        if self.post is not None:
+            parts.append(f".post{self.post}")
+
+        # Development release
+        if self.dev is not None:
+            parts.append(f".dev{self.dev}")
+
+        # Local version segment
+        if self.local is not None:
+            parts.append(f"+{self.local}")
+
+        return "".join(parts)
+
+    @property
+    def epoch(self) -> int:
+        """The epoch of the version.
+
+        >>> Version("2.0.0").epoch
+        0
+        >>> Version("1!2.0.0").epoch
+        1
+        """
+        return self._version.epoch
+
+    @property
+    def release(self) -> tuple[int, ...]:
+        """The components of the "release" segment of the version.
+
+        >>> Version("1.2.3").release
+        (1, 2, 3)
+        >>> Version("2.0.0").release
+        (2, 0, 0)
+        >>> Version("1!2.0.0.post0").release
+        (2, 0, 0)
+
+        Includes trailing zeroes but not the epoch or any pre-release / development /
+        post-release suffixes.
+        """
+        return self._version.release
+
+    @property
+    def pre(self) -> tuple[str, int] | None:
+        """The pre-release segment of the version.
+
+        >>> print(Version("1.2.3").pre)
+        None
+        >>> Version("1.2.3a1").pre
+        ('a', 1)
+        >>> Version("1.2.3b1").pre
+        ('b', 1)
+        >>> Version("1.2.3rc1").pre
+        ('rc', 1)
+        """
+        return self._version.pre
+
+    @property
+    def post(self) -> int | None:
+        """The post-release number of the version.
+
+        >>> print(Version("1.2.3").post)
+        None
+        >>> Version("1.2.3.post1").post
+        1
+        """
+        return self._version.post[1] if self._version.post else None
+
+    @property
+    def dev(self) -> int | None:
+        """The development number of the version.
+
+        >>> print(Version("1.2.3").dev)
+        None
+        >>> Version("1.2.3.dev1").dev
+        1
+        """
+        return self._version.dev[1] if self._version.dev else None
+
+    @property
+    def local(self) -> str | None:
+        """The local version segment of the version.
+
+        >>> print(Version("1.2.3").local)
+        None
+        >>> Version("1.2.3+abc").local
+        'abc'
+        """
+        if self._version.local:
+            return ".".join(str(x) for x in self._version.local)
+        else:
+            return None
+
+    @property
+    def public(self) -> str:
+        """The public portion of the version.
+
+        >>> Version("1.2.3").public
+        '1.2.3'
+        >>> Version("1.2.3+abc").public
+        '1.2.3'
+        >>> Version("1.2.3+abc.dev1").public
+        '1.2.3'
+        """
+        return str(self).split("+", 1)[0]
+
+    @property
+    def base_version(self) -> str:
+        """The "base version" of the version.
+
+        >>> Version("1.2.3").base_version
+        '1.2.3'
+        >>> Version("1.2.3+abc").base_version
+        '1.2.3'
+        >>> Version("1!1.2.3+abc.dev1").base_version
+        '1!1.2.3'
+
+        The "base version" is the public version of the project without any pre or post
+        release markers.
+        """
+        parts = []
+
+        # Epoch
+        if self.epoch != 0:
+            parts.append(f"{self.epoch}!")
+
+        # Release segment
+        parts.append(".".join(str(x) for x in self.release))
+
+        return "".join(parts)
+
+    @property
+    def is_prerelease(self) -> bool:
+        """Whether this version is a pre-release.
+
+        >>> Version("1.2.3").is_prerelease
+        False
+        >>> Version("1.2.3a1").is_prerelease
+        True
+        >>> Version("1.2.3b1").is_prerelease
+        True
+        >>> Version("1.2.3rc1").is_prerelease
+        True
+        >>> Version("1.2.3dev1").is_prerelease
+        True
+        """
+        return self.dev is not None or self.pre is not None
+
+    @property
+    def is_postrelease(self) -> bool:
+        """Whether this version is a post-release.
+
+        >>> Version("1.2.3").is_postrelease
+        False
+        >>> Version("1.2.3.post1").is_postrelease
+        True
+        """
+        return self.post is not None
+
+    @property
+    def is_devrelease(self) -> bool:
+        """Whether this version is a development release.
+
+        >>> Version("1.2.3").is_devrelease
+        False
+        >>> Version("1.2.3.dev1").is_devrelease
+        True
+        """
+        return self.dev is not None
+
+    @property
+    def major(self) -> int:
+        """The first item of :attr:`release` or ``0`` if unavailable.
+
+        >>> Version("1.2.3").major
+        1
+        """
+        return self.release[0] if len(self.release) >= 1 else 0
+
+    @property
+    def minor(self) -> int:
+        """The second item of :attr:`release` or ``0`` if unavailable.
+
+        >>> Version("1.2.3").minor
+        2
+        >>> Version("1").minor
+        0
+        """
+        return self.release[1] if len(self.release) >= 2 else 0
+
+    @property
+    def micro(self) -> int:
+        """The third item of :attr:`release` or ``0`` if unavailable.
+
+        >>> Version("1.2.3").micro
+        3
+        >>> Version("1").micro
+        0
+        """
+        return self.release[2] if len(self.release) >= 3 else 0
+
+
+def _parse_letter_version(
+    letter: str | None, number: str | bytes | SupportsInt | None
+) -> tuple[str, int] | None:
+    if letter:
+        # We consider there to be an implicit 0 in a pre-release if there is
+        # not a numeral associated with it.
+        if number is None:
+            number = 0
+
+        # We normalize any letters to their lower case form
+        letter = letter.lower()
+
+        # We consider some words to be alternate spellings of other words and
+        # in those cases we want to normalize the spellings to our preferred
+        # spelling.
+        if letter == "alpha":
+            letter = "a"
+        elif letter == "beta":
+            letter = "b"
+        elif letter in ["c", "pre", "preview"]:
+            letter = "rc"
+        elif letter in ["rev", "r"]:
+            letter = "post"
+
+        return letter, int(number)
+    if not letter and number:
+        # We assume if we are given a number, but we are not given a letter
+        # then this is using the implicit post release syntax (e.g. 1.0-1)
+        letter = "post"
+
+        return letter, int(number)
+
+    return None
+
+
+_local_version_separators = re.compile(r"[\._-]")
+
+
+def _parse_local_version(local: str | None) -> LocalType | None:
+    """
+    Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
+    """
+    if local is not None:
+        return tuple(
+            part.lower() if not part.isdigit() else int(part)
+            for part in _local_version_separators.split(local)
+        )
+    return None
+
+
+def _cmpkey(
+    epoch: int,
+    release: tuple[int, ...],
+    pre: tuple[str, int] | None,
+    post: tuple[str, int] | None,
+    dev: tuple[str, int] | None,
+    local: LocalType | None,
+) -> CmpKey:
+    # When we compare a release version, we want to compare it with all of the
+    # trailing zeros removed. So we'll use a reverse the list, drop all the now
+    # leading zeros until we come to something non zero, then take the rest
+    # re-reverse it back into the correct order and make it a tuple and use
+    # that for our sorting key.
+    _release = tuple(
+        reversed(list(itertools.dropwhile(lambda x: x == 0, reversed(release))))
+    )
+
+    # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
+    # We'll do this by abusing the pre segment, but we _only_ want to do this
+    # if there is not a pre or a post segment. If we have one of those then
+    # the normal sorting rules will handle this case correctly.
+    if pre is None and post is None and dev is not None:
+        _pre: CmpPrePostDevType = NegativeInfinity
+    # Versions without a pre-release (except as noted above) should sort after
+    # those with one.
+    elif pre is None:
+        _pre = Infinity
+    else:
+        _pre = pre
+
+    # Versions without a post segment should sort before those with one.
+    if post is None:
+        _post: CmpPrePostDevType = NegativeInfinity
+
+    else:
+        _post = post
+
+    # Versions without a development segment should sort after those with one.
+    if dev is None:
+        _dev: CmpPrePostDevType = Infinity
+
+    else:
+        _dev = dev
+
+    if local is None:
+        # Versions without a local segment should sort before those with one.
+        _local: CmpLocalType = NegativeInfinity
+    else:
+        # Versions with a local segment need that segment parsed to implement
+        # the sorting rules in PEP440.
+        # - Alpha numeric segments sort before numeric segments
+        # - Alpha numeric segments sort lexicographically
+        # - Numeric segments sort numerically
+        # - Shorter versions sort before longer versions when the prefixes
+        #   match exactly
+        _local = tuple(
+            (i, "") if isinstance(i, int) else (NegativeInfinity, i) for i in local
+        )
+
+    return epoch, _release, _pre, _post, _dev, _local
diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py b/backend/.venv/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py
new file mode 100644
index 0000000..57ce7f1
--- /dev/null
+++ b/backend/.venv/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py
@@ -0,0 +1,3676 @@
+# TODO: Add Generic type annotations to initialized collections.
+# For now we'd simply use implicit Any/Unknown which would add redundant annotations
+# mypy: disable-error-code="var-annotated"
+"""
+Package resource API
+--------------------
+
+A resource is a logical file contained within a package, or a logical
+subdirectory thereof.  The package resource API expects resource names
+to have their path parts separated with ``/``, *not* whatever the local
+path separator is.  Do not use os.path operations to manipulate resource
+names being passed into the API.
+
+The package resource API is designed to work with normal filesystem packages,
+.egg files, and unpacked .egg files.  It can also work in a limited way with
+.zip files and with custom PEP 302 loaders that support the ``get_data()``
+method.
+
+This module is deprecated. Users are directed to :mod:`importlib.resources`,
+:mod:`importlib.metadata` and :pypi:`packaging` instead.
+"""
+
+from __future__ import annotations
+
+import sys
+
+if sys.version_info < (3, 8):  # noqa: UP036 # Check for unsupported versions
+    raise RuntimeError("Python 3.8 or later is required")
+
+import os
+import io
+import time
+import re
+import types
+from typing import (
+    Any,
+    Literal,
+    Dict,
+    Iterator,
+    Mapping,
+    MutableSequence,
+    NamedTuple,
+    NoReturn,
+    Tuple,
+    Union,
+    TYPE_CHECKING,
+    Protocol,
+    Callable,
+    Iterable,
+    TypeVar,
+    overload,
+)
+import zipfile
+import zipimport
+import warnings
+import stat
+import functools
+import pkgutil
+import operator
+import platform
+import collections
+import plistlib
+import email.parser
+import errno
+import tempfile
+import textwrap
+import inspect
+import ntpath
+import posixpath
+import importlib
+import importlib.abc
+import importlib.machinery
+from pkgutil import get_importer
+
+import _imp
+
+# capture these to bypass sandboxing
+from os import utime
+from os import open as os_open
+from os.path import isdir, split
+
+try:
+    from os import mkdir, rename, unlink
+
+    WRITE_SUPPORT = True
+except ImportError:
+    # no write support, probably under GAE
+    WRITE_SUPPORT = False
+
+from pip._internal.utils._jaraco_text import (
+    yield_lines,
+    drop_comment,
+    join_continuation,
+)
+from pip._vendor.packaging import markers as _packaging_markers
+from pip._vendor.packaging import requirements as _packaging_requirements
+from pip._vendor.packaging import utils as _packaging_utils
+from pip._vendor.packaging import version as _packaging_version
+from pip._vendor.platformdirs import user_cache_dir as _user_cache_dir
+
+if TYPE_CHECKING:
+    from _typeshed import BytesPath, StrPath, StrOrBytesPath
+    from pip._vendor.typing_extensions import Self
+
+
+# Patch: Remove deprecation warning from vendored pkg_resources.
+# Setting PYTHONWARNINGS=error to verify builds produce no warnings
+# causes immediate exceptions.
+# See https://github.com/pypa/pip/issues/12243
+
+
+_T = TypeVar("_T")
+_DistributionT = TypeVar("_DistributionT", bound="Distribution")
+# Type aliases
+_NestedStr = Union[str, Iterable[Union[str, Iterable["_NestedStr"]]]]
+_InstallerTypeT = Callable[["Requirement"], "_DistributionT"]
+_InstallerType = Callable[["Requirement"], Union["Distribution", None]]
+_PkgReqType = Union[str, "Requirement"]
+_EPDistType = Union["Distribution", _PkgReqType]
+_MetadataType = Union["IResourceProvider", None]
+_ResolvedEntryPoint = Any  # Can be any attribute in the module
+_ResourceStream = Any  # TODO / Incomplete: A readable file-like object
+# Any object works, but let's indicate we expect something like a module (optionally has __loader__ or __file__)
+_ModuleLike = Union[object, types.ModuleType]
+# Any: Should be _ModuleLike but we end up with issues where _ModuleLike doesn't have _ZipLoaderModule's __loader__
+_ProviderFactoryType = Callable[[Any], "IResourceProvider"]
+_DistFinderType = Callable[[_T, str, bool], Iterable["Distribution"]]
+_NSHandlerType = Callable[[_T, str, str, types.ModuleType], Union[str, None]]
+_AdapterT = TypeVar(
+    "_AdapterT", _DistFinderType[Any], _ProviderFactoryType, _NSHandlerType[Any]
+)
+
+
+# Use _typeshed.importlib.LoaderProtocol once available https://github.com/python/typeshed/pull/11890
+class _LoaderProtocol(Protocol):
+    def load_module(self, fullname: str, /) -> types.ModuleType: ...
+
+
+class _ZipLoaderModule(Protocol):
+    __loader__: zipimport.zipimporter
+
+
+_PEP440_FALLBACK = re.compile(r"^v?(?P(?:[0-9]+!)?[0-9]+(?:\.[0-9]+)*)", re.I)
+
+
+class PEP440Warning(RuntimeWarning):
+    """
+    Used when there is an issue with a version or specifier not complying with
+    PEP 440.
+    """
+
+
+parse_version = _packaging_version.Version
+
+
+_state_vars: dict[str, str] = {}
+
+
+def _declare_state(vartype: str, varname: str, initial_value: _T) -> _T:
+    _state_vars[varname] = vartype
+    return initial_value
+
+
+def __getstate__() -> dict[str, Any]:
+    state = {}
+    g = globals()
+    for k, v in _state_vars.items():
+        state[k] = g['_sget_' + v](g[k])
+    return state
+
+
+def __setstate__(state: dict[str, Any]) -> dict[str, Any]:
+    g = globals()
+    for k, v in state.items():
+        g['_sset_' + _state_vars[k]](k, g[k], v)
+    return state
+
+
+def _sget_dict(val):
+    return val.copy()
+
+
+def _sset_dict(key, ob, state):
+    ob.clear()
+    ob.update(state)
+
+
+def _sget_object(val):
+    return val.__getstate__()
+
+
+def _sset_object(key, ob, state):
+    ob.__setstate__(state)
+
+
+_sget_none = _sset_none = lambda *args: None
+
+
+def get_supported_platform():
+    """Return this platform's maximum compatible version.
+
+    distutils.util.get_platform() normally reports the minimum version
+    of macOS that would be required to *use* extensions produced by
+    distutils.  But what we want when checking compatibility is to know the
+    version of macOS that we are *running*.  To allow usage of packages that
+    explicitly require a newer version of macOS, we must also know the
+    current version of the OS.
+
+    If this condition occurs for any other platform with a version in its
+    platform strings, this function should be extended accordingly.
+    """
+    plat = get_build_platform()
+    m = macosVersionString.match(plat)
+    if m is not None and sys.platform == "darwin":
+        try:
+            plat = 'macosx-%s-%s' % ('.'.join(_macos_vers()[:2]), m.group(3))
+        except ValueError:
+            # not macOS
+            pass
+    return plat
+
+
+__all__ = [
+    # Basic resource access and distribution/entry point discovery
+    'require',
+    'run_script',
+    'get_provider',
+    'get_distribution',
+    'load_entry_point',
+    'get_entry_map',
+    'get_entry_info',
+    'iter_entry_points',
+    'resource_string',
+    'resource_stream',
+    'resource_filename',
+    'resource_listdir',
+    'resource_exists',
+    'resource_isdir',
+    # Environmental control
+    'declare_namespace',
+    'working_set',
+    'add_activation_listener',
+    'find_distributions',
+    'set_extraction_path',
+    'cleanup_resources',
+    'get_default_cache',
+    # Primary implementation classes
+    'Environment',
+    'WorkingSet',
+    'ResourceManager',
+    'Distribution',
+    'Requirement',
+    'EntryPoint',
+    # Exceptions
+    'ResolutionError',
+    'VersionConflict',
+    'DistributionNotFound',
+    'UnknownExtra',
+    'ExtractionError',
+    # Warnings
+    'PEP440Warning',
+    # Parsing functions and string utilities
+    'parse_requirements',
+    'parse_version',
+    'safe_name',
+    'safe_version',
+    'get_platform',
+    'compatible_platforms',
+    'yield_lines',
+    'split_sections',
+    'safe_extra',
+    'to_filename',
+    'invalid_marker',
+    'evaluate_marker',
+    # filesystem utilities
+    'ensure_directory',
+    'normalize_path',
+    # Distribution "precedence" constants
+    'EGG_DIST',
+    'BINARY_DIST',
+    'SOURCE_DIST',
+    'CHECKOUT_DIST',
+    'DEVELOP_DIST',
+    # "Provider" interfaces, implementations, and registration/lookup APIs
+    'IMetadataProvider',
+    'IResourceProvider',
+    'FileMetadata',
+    'PathMetadata',
+    'EggMetadata',
+    'EmptyProvider',
+    'empty_provider',
+    'NullProvider',
+    'EggProvider',
+    'DefaultProvider',
+    'ZipProvider',
+    'register_finder',
+    'register_namespace_handler',
+    'register_loader_type',
+    'fixup_namespace_packages',
+    'get_importer',
+    # Warnings
+    'PkgResourcesDeprecationWarning',
+    # Deprecated/backward compatibility only
+    'run_main',
+    'AvailableDistributions',
+]
+
+
+class ResolutionError(Exception):
+    """Abstract base for dependency resolution errors"""
+
+    def __repr__(self):
+        return self.__class__.__name__ + repr(self.args)
+
+
+class VersionConflict(ResolutionError):
+    """
+    An already-installed version conflicts with the requested version.
+
+    Should be initialized with the installed Distribution and the requested
+    Requirement.
+    """
+
+    _template = "{self.dist} is installed but {self.req} is required"
+
+    @property
+    def dist(self) -> Distribution:
+        return self.args[0]
+
+    @property
+    def req(self) -> Requirement:
+        return self.args[1]
+
+    def report(self):
+        return self._template.format(**locals())
+
+    def with_context(self, required_by: set[Distribution | str]):
+        """
+        If required_by is non-empty, return a version of self that is a
+        ContextualVersionConflict.
+        """
+        if not required_by:
+            return self
+        args = self.args + (required_by,)
+        return ContextualVersionConflict(*args)
+
+
+class ContextualVersionConflict(VersionConflict):
+    """
+    A VersionConflict that accepts a third parameter, the set of the
+    requirements that required the installed Distribution.
+    """
+
+    _template = VersionConflict._template + ' by {self.required_by}'
+
+    @property
+    def required_by(self) -> set[str]:
+        return self.args[2]
+
+
+class DistributionNotFound(ResolutionError):
+    """A requested distribution was not found"""
+
+    _template = (
+        "The '{self.req}' distribution was not found "
+        "and is required by {self.requirers_str}"
+    )
+
+    @property
+    def req(self) -> Requirement:
+        return self.args[0]
+
+    @property
+    def requirers(self) -> set[str] | None:
+        return self.args[1]
+
+    @property
+    def requirers_str(self):
+        if not self.requirers:
+            return 'the application'
+        return ', '.join(self.requirers)
+
+    def report(self):
+        return self._template.format(**locals())
+
+    def __str__(self):
+        return self.report()
+
+
+class UnknownExtra(ResolutionError):
+    """Distribution doesn't have an "extra feature" of the given name"""
+
+
+_provider_factories: dict[type[_ModuleLike], _ProviderFactoryType] = {}
+
+PY_MAJOR = '{}.{}'.format(*sys.version_info)
+EGG_DIST = 3
+BINARY_DIST = 2
+SOURCE_DIST = 1
+CHECKOUT_DIST = 0
+DEVELOP_DIST = -1
+
+
+def register_loader_type(
+    loader_type: type[_ModuleLike], provider_factory: _ProviderFactoryType
+):
+    """Register `provider_factory` to make providers for `loader_type`
+
+    `loader_type` is the type or class of a PEP 302 ``module.__loader__``,
+    and `provider_factory` is a function that, passed a *module* object,
+    returns an ``IResourceProvider`` for that module.
+    """
+    _provider_factories[loader_type] = provider_factory
+
+
+@overload
+def get_provider(moduleOrReq: str) -> IResourceProvider: ...
+@overload
+def get_provider(moduleOrReq: Requirement) -> Distribution: ...
+def get_provider(moduleOrReq: str | Requirement) -> IResourceProvider | Distribution:
+    """Return an IResourceProvider for the named module or requirement"""
+    if isinstance(moduleOrReq, Requirement):
+        return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0]
+    try:
+        module = sys.modules[moduleOrReq]
+    except KeyError:
+        __import__(moduleOrReq)
+        module = sys.modules[moduleOrReq]
+    loader = getattr(module, '__loader__', None)
+    return _find_adapter(_provider_factories, loader)(module)
+
+
+@functools.lru_cache(maxsize=None)
+def _macos_vers():
+    version = platform.mac_ver()[0]
+    # fallback for MacPorts
+    if version == '':
+        plist = '/System/Library/CoreServices/SystemVersion.plist'
+        if os.path.exists(plist):
+            with open(plist, 'rb') as fh:
+                plist_content = plistlib.load(fh)
+            if 'ProductVersion' in plist_content:
+                version = plist_content['ProductVersion']
+    return version.split('.')
+
+
+def _macos_arch(machine):
+    return {'PowerPC': 'ppc', 'Power_Macintosh': 'ppc'}.get(machine, machine)
+
+
+def get_build_platform():
+    """Return this platform's string for platform-specific distributions
+
+    XXX Currently this is the same as ``distutils.util.get_platform()``, but it
+    needs some hacks for Linux and macOS.
+    """
+    from sysconfig import get_platform
+
+    plat = get_platform()
+    if sys.platform == "darwin" and not plat.startswith('macosx-'):
+        try:
+            version = _macos_vers()
+            machine = os.uname()[4].replace(" ", "_")
+            return "macosx-%d.%d-%s" % (
+                int(version[0]),
+                int(version[1]),
+                _macos_arch(machine),
+            )
+        except ValueError:
+            # if someone is running a non-Mac darwin system, this will fall
+            # through to the default implementation
+            pass
+    return plat
+
+
+macosVersionString = re.compile(r"macosx-(\d+)\.(\d+)-(.*)")
+darwinVersionString = re.compile(r"darwin-(\d+)\.(\d+)\.(\d+)-(.*)")
+# XXX backward compat
+get_platform = get_build_platform
+
+
+def compatible_platforms(provided: str | None, required: str | None):
+    """Can code for the `provided` platform run on the `required` platform?
+
+    Returns true if either platform is ``None``, or the platforms are equal.
+
+    XXX Needs compatibility checks for Linux and other unixy OSes.
+    """
+    if provided is None or required is None or provided == required:
+        # easy case
+        return True
+
+    # macOS special cases
+    reqMac = macosVersionString.match(required)
+    if reqMac:
+        provMac = macosVersionString.match(provided)
+
+        # is this a Mac package?
+        if not provMac:
+            # this is backwards compatibility for packages built before
+            # setuptools 0.6. All packages built after this point will
+            # use the new macOS designation.
+            provDarwin = darwinVersionString.match(provided)
+            if provDarwin:
+                dversion = int(provDarwin.group(1))
+                macosversion = "%s.%s" % (reqMac.group(1), reqMac.group(2))
+                if (
+                    dversion == 7
+                    and macosversion >= "10.3"
+                    or dversion == 8
+                    and macosversion >= "10.4"
+                ):
+                    return True
+            # egg isn't macOS or legacy darwin
+            return False
+
+        # are they the same major version and machine type?
+        if provMac.group(1) != reqMac.group(1) or provMac.group(3) != reqMac.group(3):
+            return False
+
+        # is the required OS major update >= the provided one?
+        if int(provMac.group(2)) > int(reqMac.group(2)):
+            return False
+
+        return True
+
+    # XXX Linux and other platforms' special cases should go here
+    return False
+
+
+@overload
+def get_distribution(dist: _DistributionT) -> _DistributionT: ...
+@overload
+def get_distribution(dist: _PkgReqType) -> Distribution: ...
+def get_distribution(dist: Distribution | _PkgReqType) -> Distribution:
+    """Return a current distribution object for a Requirement or string"""
+    if isinstance(dist, str):
+        dist = Requirement.parse(dist)
+    if isinstance(dist, Requirement):
+        # Bad type narrowing, dist has to be a Requirement here, so get_provider has to return Distribution
+        dist = get_provider(dist)  # type: ignore[assignment]
+    if not isinstance(dist, Distribution):
+        raise TypeError("Expected str, Requirement, or Distribution", dist)
+    return dist
+
+
+def load_entry_point(dist: _EPDistType, group: str, name: str) -> _ResolvedEntryPoint:
+    """Return `name` entry point of `group` for `dist` or raise ImportError"""
+    return get_distribution(dist).load_entry_point(group, name)
+
+
+@overload
+def get_entry_map(
+    dist: _EPDistType, group: None = None
+) -> dict[str, dict[str, EntryPoint]]: ...
+@overload
+def get_entry_map(dist: _EPDistType, group: str) -> dict[str, EntryPoint]: ...
+def get_entry_map(dist: _EPDistType, group: str | None = None):
+    """Return the entry point map for `group`, or the full entry map"""
+    return get_distribution(dist).get_entry_map(group)
+
+
+def get_entry_info(dist: _EPDistType, group: str, name: str):
+    """Return the EntryPoint object for `group`+`name`, or ``None``"""
+    return get_distribution(dist).get_entry_info(group, name)
+
+
+class IMetadataProvider(Protocol):
+    def has_metadata(self, name: str) -> bool:
+        """Does the package's distribution contain the named metadata?"""
+
+    def get_metadata(self, name: str) -> str:
+        """The named metadata resource as a string"""
+
+    def get_metadata_lines(self, name: str) -> Iterator[str]:
+        """Yield named metadata resource as list of non-blank non-comment lines
+
+        Leading and trailing whitespace is stripped from each line, and lines
+        with ``#`` as the first non-blank character are omitted."""
+
+    def metadata_isdir(self, name: str) -> bool:
+        """Is the named metadata a directory?  (like ``os.path.isdir()``)"""
+
+    def metadata_listdir(self, name: str) -> list[str]:
+        """List of metadata names in the directory (like ``os.listdir()``)"""
+
+    def run_script(self, script_name: str, namespace: dict[str, Any]) -> None:
+        """Execute the named script in the supplied namespace dictionary"""
+
+
+class IResourceProvider(IMetadataProvider, Protocol):
+    """An object that provides access to package resources"""
+
+    def get_resource_filename(
+        self, manager: ResourceManager, resource_name: str
+    ) -> str:
+        """Return a true filesystem path for `resource_name`
+
+        `manager` must be a ``ResourceManager``"""
+
+    def get_resource_stream(
+        self, manager: ResourceManager, resource_name: str
+    ) -> _ResourceStream:
+        """Return a readable file-like object for `resource_name`
+
+        `manager` must be a ``ResourceManager``"""
+
+    def get_resource_string(
+        self, manager: ResourceManager, resource_name: str
+    ) -> bytes:
+        """Return the contents of `resource_name` as :obj:`bytes`
+
+        `manager` must be a ``ResourceManager``"""
+
+    def has_resource(self, resource_name: str) -> bool:
+        """Does the package contain the named resource?"""
+
+    def resource_isdir(self, resource_name: str) -> bool:
+        """Is the named resource a directory?  (like ``os.path.isdir()``)"""
+
+    def resource_listdir(self, resource_name: str) -> list[str]:
+        """List of resource names in the directory (like ``os.listdir()``)"""
+
+
+class WorkingSet:
+    """A collection of active distributions on sys.path (or a similar list)"""
+
+    def __init__(self, entries: Iterable[str] | None = None):
+        """Create working set from list of path entries (default=sys.path)"""
+        self.entries: list[str] = []
+        self.entry_keys = {}
+        self.by_key = {}
+        self.normalized_to_canonical_keys = {}
+        self.callbacks = []
+
+        if entries is None:
+            entries = sys.path
+
+        for entry in entries:
+            self.add_entry(entry)
+
+    @classmethod
+    def _build_master(cls):
+        """
+        Prepare the master working set.
+        """
+        ws = cls()
+        try:
+            from __main__ import __requires__
+        except ImportError:
+            # The main program does not list any requirements
+            return ws
+
+        # ensure the requirements are met
+        try:
+            ws.require(__requires__)
+        except VersionConflict:
+            return cls._build_from_requirements(__requires__)
+
+        return ws
+
+    @classmethod
+    def _build_from_requirements(cls, req_spec):
+        """
+        Build a working set from a requirement spec. Rewrites sys.path.
+        """
+        # try it without defaults already on sys.path
+        # by starting with an empty path
+        ws = cls([])
+        reqs = parse_requirements(req_spec)
+        dists = ws.resolve(reqs, Environment())
+        for dist in dists:
+            ws.add(dist)
+
+        # add any missing entries from sys.path
+        for entry in sys.path:
+            if entry not in ws.entries:
+                ws.add_entry(entry)
+
+        # then copy back to sys.path
+        sys.path[:] = ws.entries
+        return ws
+
+    def add_entry(self, entry: str):
+        """Add a path item to ``.entries``, finding any distributions on it
+
+        ``find_distributions(entry, True)`` is used to find distributions
+        corresponding to the path entry, and they are added.  `entry` is
+        always appended to ``.entries``, even if it is already present.
+        (This is because ``sys.path`` can contain the same value more than
+        once, and the ``.entries`` of the ``sys.path`` WorkingSet should always
+        equal ``sys.path``.)
+        """
+        self.entry_keys.setdefault(entry, [])
+        self.entries.append(entry)
+        for dist in find_distributions(entry, True):
+            self.add(dist, entry, False)
+
+    def __contains__(self, dist: Distribution) -> bool:
+        """True if `dist` is the active distribution for its project"""
+        return self.by_key.get(dist.key) == dist
+
+    def find(self, req: Requirement) -> Distribution | None:
+        """Find a distribution matching requirement `req`
+
+        If there is an active distribution for the requested project, this
+        returns it as long as it meets the version requirement specified by
+        `req`.  But, if there is an active distribution for the project and it
+        does *not* meet the `req` requirement, ``VersionConflict`` is raised.
+        If there is no active distribution for the requested project, ``None``
+        is returned.
+        """
+        dist = self.by_key.get(req.key)
+
+        if dist is None:
+            canonical_key = self.normalized_to_canonical_keys.get(req.key)
+
+            if canonical_key is not None:
+                req.key = canonical_key
+                dist = self.by_key.get(canonical_key)
+
+        if dist is not None and dist not in req:
+            # XXX add more info
+            raise VersionConflict(dist, req)
+        return dist
+
+    def iter_entry_points(self, group: str, name: str | None = None):
+        """Yield entry point objects from `group` matching `name`
+
+        If `name` is None, yields all entry points in `group` from all
+        distributions in the working set, otherwise only ones matching
+        both `group` and `name` are yielded (in distribution order).
+        """
+        return (
+            entry
+            for dist in self
+            for entry in dist.get_entry_map(group).values()
+            if name is None or name == entry.name
+        )
+
+    def run_script(self, requires: str, script_name: str):
+        """Locate distribution for `requires` and run `script_name` script"""
+        ns = sys._getframe(1).f_globals
+        name = ns['__name__']
+        ns.clear()
+        ns['__name__'] = name
+        self.require(requires)[0].run_script(script_name, ns)
+
+    def __iter__(self) -> Iterator[Distribution]:
+        """Yield distributions for non-duplicate projects in the working set
+
+        The yield order is the order in which the items' path entries were
+        added to the working set.
+        """
+        seen = set()
+        for item in self.entries:
+            if item not in self.entry_keys:
+                # workaround a cache issue
+                continue
+
+            for key in self.entry_keys[item]:
+                if key not in seen:
+                    seen.add(key)
+                    yield self.by_key[key]
+
+    def add(
+        self,
+        dist: Distribution,
+        entry: str | None = None,
+        insert: bool = True,
+        replace: bool = False,
+    ):
+        """Add `dist` to working set, associated with `entry`
+
+        If `entry` is unspecified, it defaults to the ``.location`` of `dist`.
+        On exit from this routine, `entry` is added to the end of the working
+        set's ``.entries`` (if it wasn't already present).
+
+        `dist` is only added to the working set if it's for a project that
+        doesn't already have a distribution in the set, unless `replace=True`.
+        If it's added, any callbacks registered with the ``subscribe()`` method
+        will be called.
+        """
+        if insert:
+            dist.insert_on(self.entries, entry, replace=replace)
+
+        if entry is None:
+            entry = dist.location
+        keys = self.entry_keys.setdefault(entry, [])
+        keys2 = self.entry_keys.setdefault(dist.location, [])
+        if not replace and dist.key in self.by_key:
+            # ignore hidden distros
+            return
+
+        self.by_key[dist.key] = dist
+        normalized_name = _packaging_utils.canonicalize_name(dist.key)
+        self.normalized_to_canonical_keys[normalized_name] = dist.key
+        if dist.key not in keys:
+            keys.append(dist.key)
+        if dist.key not in keys2:
+            keys2.append(dist.key)
+        self._added_new(dist)
+
+    @overload
+    def resolve(
+        self,
+        requirements: Iterable[Requirement],
+        env: Environment | None,
+        installer: _InstallerTypeT[_DistributionT],
+        replace_conflicting: bool = False,
+        extras: tuple[str, ...] | None = None,
+    ) -> list[_DistributionT]: ...
+    @overload
+    def resolve(
+        self,
+        requirements: Iterable[Requirement],
+        env: Environment | None = None,
+        *,
+        installer: _InstallerTypeT[_DistributionT],
+        replace_conflicting: bool = False,
+        extras: tuple[str, ...] | None = None,
+    ) -> list[_DistributionT]: ...
+    @overload
+    def resolve(
+        self,
+        requirements: Iterable[Requirement],
+        env: Environment | None = None,
+        installer: _InstallerType | None = None,
+        replace_conflicting: bool = False,
+        extras: tuple[str, ...] | None = None,
+    ) -> list[Distribution]: ...
+    def resolve(
+        self,
+        requirements: Iterable[Requirement],
+        env: Environment | None = None,
+        installer: _InstallerType | None | _InstallerTypeT[_DistributionT] = None,
+        replace_conflicting: bool = False,
+        extras: tuple[str, ...] | None = None,
+    ) -> list[Distribution] | list[_DistributionT]:
+        """List all distributions needed to (recursively) meet `requirements`
+
+        `requirements` must be a sequence of ``Requirement`` objects.  `env`,
+        if supplied, should be an ``Environment`` instance.  If
+        not supplied, it defaults to all distributions available within any
+        entry or distribution in the working set.  `installer`, if supplied,
+        will be invoked with each requirement that cannot be met by an
+        already-installed distribution; it should return a ``Distribution`` or
+        ``None``.
+
+        Unless `replace_conflicting=True`, raises a VersionConflict exception
+        if
+        any requirements are found on the path that have the correct name but
+        the wrong version.  Otherwise, if an `installer` is supplied it will be
+        invoked to obtain the correct version of the requirement and activate
+        it.
+
+        `extras` is a list of the extras to be used with these requirements.
+        This is important because extra requirements may look like `my_req;
+        extra = "my_extra"`, which would otherwise be interpreted as a purely
+        optional requirement.  Instead, we want to be able to assert that these
+        requirements are truly required.
+        """
+
+        # set up the stack
+        requirements = list(requirements)[::-1]
+        # set of processed requirements
+        processed = set()
+        # key -> dist
+        best = {}
+        to_activate = []
+
+        req_extras = _ReqExtras()
+
+        # Mapping of requirement to set of distributions that required it;
+        # useful for reporting info about conflicts.
+        required_by = collections.defaultdict(set)
+
+        while requirements:
+            # process dependencies breadth-first
+            req = requirements.pop(0)
+            if req in processed:
+                # Ignore cyclic or redundant dependencies
+                continue
+
+            if not req_extras.markers_pass(req, extras):
+                continue
+
+            dist = self._resolve_dist(
+                req, best, replace_conflicting, env, installer, required_by, to_activate
+            )
+
+            # push the new requirements onto the stack
+            new_requirements = dist.requires(req.extras)[::-1]
+            requirements.extend(new_requirements)
+
+            # Register the new requirements needed by req
+            for new_requirement in new_requirements:
+                required_by[new_requirement].add(req.project_name)
+                req_extras[new_requirement] = req.extras
+
+            processed.add(req)
+
+        # return list of distros to activate
+        return to_activate
+
+    def _resolve_dist(
+        self, req, best, replace_conflicting, env, installer, required_by, to_activate
+    ) -> Distribution:
+        dist = best.get(req.key)
+        if dist is None:
+            # Find the best distribution and add it to the map
+            dist = self.by_key.get(req.key)
+            if dist is None or (dist not in req and replace_conflicting):
+                ws = self
+                if env is None:
+                    if dist is None:
+                        env = Environment(self.entries)
+                    else:
+                        # Use an empty environment and workingset to avoid
+                        # any further conflicts with the conflicting
+                        # distribution
+                        env = Environment([])
+                        ws = WorkingSet([])
+                dist = best[req.key] = env.best_match(
+                    req, ws, installer, replace_conflicting=replace_conflicting
+                )
+                if dist is None:
+                    requirers = required_by.get(req, None)
+                    raise DistributionNotFound(req, requirers)
+            to_activate.append(dist)
+        if dist not in req:
+            # Oops, the "best" so far conflicts with a dependency
+            dependent_req = required_by[req]
+            raise VersionConflict(dist, req).with_context(dependent_req)
+        return dist
+
+    @overload
+    def find_plugins(
+        self,
+        plugin_env: Environment,
+        full_env: Environment | None,
+        installer: _InstallerTypeT[_DistributionT],
+        fallback: bool = True,
+    ) -> tuple[list[_DistributionT], dict[Distribution, Exception]]: ...
+    @overload
+    def find_plugins(
+        self,
+        plugin_env: Environment,
+        full_env: Environment | None = None,
+        *,
+        installer: _InstallerTypeT[_DistributionT],
+        fallback: bool = True,
+    ) -> tuple[list[_DistributionT], dict[Distribution, Exception]]: ...
+    @overload
+    def find_plugins(
+        self,
+        plugin_env: Environment,
+        full_env: Environment | None = None,
+        installer: _InstallerType | None = None,
+        fallback: bool = True,
+    ) -> tuple[list[Distribution], dict[Distribution, Exception]]: ...
+    def find_plugins(
+        self,
+        plugin_env: Environment,
+        full_env: Environment | None = None,
+        installer: _InstallerType | None | _InstallerTypeT[_DistributionT] = None,
+        fallback: bool = True,
+    ) -> tuple[
+        list[Distribution] | list[_DistributionT],
+        dict[Distribution, Exception],
+    ]:
+        """Find all activatable distributions in `plugin_env`
+
+        Example usage::
+
+            distributions, errors = working_set.find_plugins(
+                Environment(plugin_dirlist)
+            )
+            # add plugins+libs to sys.path
+            map(working_set.add, distributions)
+            # display errors
+            print('Could not load', errors)
+
+        The `plugin_env` should be an ``Environment`` instance that contains
+        only distributions that are in the project's "plugin directory" or
+        directories. The `full_env`, if supplied, should be an ``Environment``
+        contains all currently-available distributions.  If `full_env` is not
+        supplied, one is created automatically from the ``WorkingSet`` this
+        method is called on, which will typically mean that every directory on
+        ``sys.path`` will be scanned for distributions.
+
+        `installer` is a standard installer callback as used by the
+        ``resolve()`` method. The `fallback` flag indicates whether we should
+        attempt to resolve older versions of a plugin if the newest version
+        cannot be resolved.
+
+        This method returns a 2-tuple: (`distributions`, `error_info`), where
+        `distributions` is a list of the distributions found in `plugin_env`
+        that were loadable, along with any other distributions that are needed
+        to resolve their dependencies.  `error_info` is a dictionary mapping
+        unloadable plugin distributions to an exception instance describing the
+        error that occurred. Usually this will be a ``DistributionNotFound`` or
+        ``VersionConflict`` instance.
+        """
+
+        plugin_projects = list(plugin_env)
+        # scan project names in alphabetic order
+        plugin_projects.sort()
+
+        error_info: dict[Distribution, Exception] = {}
+        distributions: dict[Distribution, Exception | None] = {}
+
+        if full_env is None:
+            env = Environment(self.entries)
+            env += plugin_env
+        else:
+            env = full_env + plugin_env
+
+        shadow_set = self.__class__([])
+        # put all our entries in shadow_set
+        list(map(shadow_set.add, self))
+
+        for project_name in plugin_projects:
+            for dist in plugin_env[project_name]:
+                req = [dist.as_requirement()]
+
+                try:
+                    resolvees = shadow_set.resolve(req, env, installer)
+
+                except ResolutionError as v:
+                    # save error info
+                    error_info[dist] = v
+                    if fallback:
+                        # try the next older version of project
+                        continue
+                    else:
+                        # give up on this project, keep going
+                        break
+
+                else:
+                    list(map(shadow_set.add, resolvees))
+                    distributions.update(dict.fromkeys(resolvees))
+
+                    # success, no need to try any more versions of this project
+                    break
+
+        sorted_distributions = list(distributions)
+        sorted_distributions.sort()
+
+        return sorted_distributions, error_info
+
+    def require(self, *requirements: _NestedStr):
+        """Ensure that distributions matching `requirements` are activated
+
+        `requirements` must be a string or a (possibly-nested) sequence
+        thereof, specifying the distributions and versions required.  The
+        return value is a sequence of the distributions that needed to be
+        activated to fulfill the requirements; all relevant distributions are
+        included, even if they were already activated in this working set.
+        """
+        needed = self.resolve(parse_requirements(requirements))
+
+        for dist in needed:
+            self.add(dist)
+
+        return needed
+
+    def subscribe(
+        self, callback: Callable[[Distribution], object], existing: bool = True
+    ):
+        """Invoke `callback` for all distributions
+
+        If `existing=True` (default),
+        call on all existing ones, as well.
+        """
+        if callback in self.callbacks:
+            return
+        self.callbacks.append(callback)
+        if not existing:
+            return
+        for dist in self:
+            callback(dist)
+
+    def _added_new(self, dist):
+        for callback in self.callbacks:
+            callback(dist)
+
+    def __getstate__(self):
+        return (
+            self.entries[:],
+            self.entry_keys.copy(),
+            self.by_key.copy(),
+            self.normalized_to_canonical_keys.copy(),
+            self.callbacks[:],
+        )
+
+    def __setstate__(self, e_k_b_n_c):
+        entries, keys, by_key, normalized_to_canonical_keys, callbacks = e_k_b_n_c
+        self.entries = entries[:]
+        self.entry_keys = keys.copy()
+        self.by_key = by_key.copy()
+        self.normalized_to_canonical_keys = normalized_to_canonical_keys.copy()
+        self.callbacks = callbacks[:]
+
+
+class _ReqExtras(Dict["Requirement", Tuple[str, ...]]):
+    """
+    Map each requirement to the extras that demanded it.
+    """
+
+    def markers_pass(self, req: Requirement, extras: tuple[str, ...] | None = None):
+        """
+        Evaluate markers for req against each extra that
+        demanded it.
+
+        Return False if the req has a marker and fails
+        evaluation. Otherwise, return True.
+        """
+        extra_evals = (
+            req.marker.evaluate({'extra': extra})
+            for extra in self.get(req, ()) + (extras or (None,))
+        )
+        return not req.marker or any(extra_evals)
+
+
+class Environment:
+    """Searchable snapshot of distributions on a search path"""
+
+    def __init__(
+        self,
+        search_path: Iterable[str] | None = None,
+        platform: str | None = get_supported_platform(),
+        python: str | None = PY_MAJOR,
+    ):
+        """Snapshot distributions available on a search path
+
+        Any distributions found on `search_path` are added to the environment.
+        `search_path` should be a sequence of ``sys.path`` items.  If not
+        supplied, ``sys.path`` is used.
+
+        `platform` is an optional string specifying the name of the platform
+        that platform-specific distributions must be compatible with.  If
+        unspecified, it defaults to the current platform.  `python` is an
+        optional string naming the desired version of Python (e.g. ``'3.6'``);
+        it defaults to the current version.
+
+        You may explicitly set `platform` (and/or `python`) to ``None`` if you
+        wish to map *all* distributions, not just those compatible with the
+        running platform or Python version.
+        """
+        self._distmap = {}
+        self.platform = platform
+        self.python = python
+        self.scan(search_path)
+
+    def can_add(self, dist: Distribution):
+        """Is distribution `dist` acceptable for this environment?
+
+        The distribution must match the platform and python version
+        requirements specified when this environment was created, or False
+        is returned.
+        """
+        py_compat = (
+            self.python is None
+            or dist.py_version is None
+            or dist.py_version == self.python
+        )
+        return py_compat and compatible_platforms(dist.platform, self.platform)
+
+    def remove(self, dist: Distribution):
+        """Remove `dist` from the environment"""
+        self._distmap[dist.key].remove(dist)
+
+    def scan(self, search_path: Iterable[str] | None = None):
+        """Scan `search_path` for distributions usable in this environment
+
+        Any distributions found are added to the environment.
+        `search_path` should be a sequence of ``sys.path`` items.  If not
+        supplied, ``sys.path`` is used.  Only distributions conforming to
+        the platform/python version defined at initialization are added.
+        """
+        if search_path is None:
+            search_path = sys.path
+
+        for item in search_path:
+            for dist in find_distributions(item):
+                self.add(dist)
+
+    def __getitem__(self, project_name: str) -> list[Distribution]:
+        """Return a newest-to-oldest list of distributions for `project_name`
+
+        Uses case-insensitive `project_name` comparison, assuming all the
+        project's distributions use their project's name converted to all
+        lowercase as their key.
+
+        """
+        distribution_key = project_name.lower()
+        return self._distmap.get(distribution_key, [])
+
+    def add(self, dist: Distribution):
+        """Add `dist` if we ``can_add()`` it and it has not already been added"""
+        if self.can_add(dist) and dist.has_version():
+            dists = self._distmap.setdefault(dist.key, [])
+            if dist not in dists:
+                dists.append(dist)
+                dists.sort(key=operator.attrgetter('hashcmp'), reverse=True)
+
+    @overload
+    def best_match(
+        self,
+        req: Requirement,
+        working_set: WorkingSet,
+        installer: _InstallerTypeT[_DistributionT],
+        replace_conflicting: bool = False,
+    ) -> _DistributionT: ...
+    @overload
+    def best_match(
+        self,
+        req: Requirement,
+        working_set: WorkingSet,
+        installer: _InstallerType | None = None,
+        replace_conflicting: bool = False,
+    ) -> Distribution | None: ...
+    def best_match(
+        self,
+        req: Requirement,
+        working_set: WorkingSet,
+        installer: _InstallerType | None | _InstallerTypeT[_DistributionT] = None,
+        replace_conflicting: bool = False,
+    ) -> Distribution | None:
+        """Find distribution best matching `req` and usable on `working_set`
+
+        This calls the ``find(req)`` method of the `working_set` to see if a
+        suitable distribution is already active.  (This may raise
+        ``VersionConflict`` if an unsuitable version of the project is already
+        active in the specified `working_set`.)  If a suitable distribution
+        isn't active, this method returns the newest distribution in the
+        environment that meets the ``Requirement`` in `req`.  If no suitable
+        distribution is found, and `installer` is supplied, then the result of
+        calling the environment's ``obtain(req, installer)`` method will be
+        returned.
+        """
+        try:
+            dist = working_set.find(req)
+        except VersionConflict:
+            if not replace_conflicting:
+                raise
+            dist = None
+        if dist is not None:
+            return dist
+        for dist in self[req.key]:
+            if dist in req:
+                return dist
+        # try to download/install
+        return self.obtain(req, installer)
+
+    @overload
+    def obtain(
+        self,
+        requirement: Requirement,
+        installer: _InstallerTypeT[_DistributionT],
+    ) -> _DistributionT: ...
+    @overload
+    def obtain(
+        self,
+        requirement: Requirement,
+        installer: Callable[[Requirement], None] | None = None,
+    ) -> None: ...
+    @overload
+    def obtain(
+        self,
+        requirement: Requirement,
+        installer: _InstallerType | None = None,
+    ) -> Distribution | None: ...
+    def obtain(
+        self,
+        requirement: Requirement,
+        installer: Callable[[Requirement], None]
+        | _InstallerType
+        | None
+        | _InstallerTypeT[_DistributionT] = None,
+    ) -> Distribution | None:
+        """Obtain a distribution matching `requirement` (e.g. via download)
+
+        Obtain a distro that matches requirement (e.g. via download).  In the
+        base ``Environment`` class, this routine just returns
+        ``installer(requirement)``, unless `installer` is None, in which case
+        None is returned instead.  This method is a hook that allows subclasses
+        to attempt other ways of obtaining a distribution before falling back
+        to the `installer` argument."""
+        return installer(requirement) if installer else None
+
+    def __iter__(self) -> Iterator[str]:
+        """Yield the unique project names of the available distributions"""
+        for key in self._distmap.keys():
+            if self[key]:
+                yield key
+
+    def __iadd__(self, other: Distribution | Environment):
+        """In-place addition of a distribution or environment"""
+        if isinstance(other, Distribution):
+            self.add(other)
+        elif isinstance(other, Environment):
+            for project in other:
+                for dist in other[project]:
+                    self.add(dist)
+        else:
+            raise TypeError("Can't add %r to environment" % (other,))
+        return self
+
+    def __add__(self, other: Distribution | Environment):
+        """Add an environment or distribution to an environment"""
+        new = self.__class__([], platform=None, python=None)
+        for env in self, other:
+            new += env
+        return new
+
+
+# XXX backward compatibility
+AvailableDistributions = Environment
+
+
+class ExtractionError(RuntimeError):
+    """An error occurred extracting a resource
+
+    The following attributes are available from instances of this exception:
+
+    manager
+        The resource manager that raised this exception
+
+    cache_path
+        The base directory for resource extraction
+
+    original_error
+        The exception instance that caused extraction to fail
+    """
+
+    manager: ResourceManager
+    cache_path: str
+    original_error: BaseException | None
+
+
+class ResourceManager:
+    """Manage resource extraction and packages"""
+
+    extraction_path: str | None = None
+
+    def __init__(self):
+        self.cached_files = {}
+
+    def resource_exists(self, package_or_requirement: _PkgReqType, resource_name: str):
+        """Does the named resource exist?"""
+        return get_provider(package_or_requirement).has_resource(resource_name)
+
+    def resource_isdir(self, package_or_requirement: _PkgReqType, resource_name: str):
+        """Is the named resource an existing directory?"""
+        return get_provider(package_or_requirement).resource_isdir(resource_name)
+
+    def resource_filename(
+        self, package_or_requirement: _PkgReqType, resource_name: str
+    ):
+        """Return a true filesystem path for specified resource"""
+        return get_provider(package_or_requirement).get_resource_filename(
+            self, resource_name
+        )
+
+    def resource_stream(self, package_or_requirement: _PkgReqType, resource_name: str):
+        """Return a readable file-like object for specified resource"""
+        return get_provider(package_or_requirement).get_resource_stream(
+            self, resource_name
+        )
+
+    def resource_string(
+        self, package_or_requirement: _PkgReqType, resource_name: str
+    ) -> bytes:
+        """Return specified resource as :obj:`bytes`"""
+        return get_provider(package_or_requirement).get_resource_string(
+            self, resource_name
+        )
+
+    def resource_listdir(self, package_or_requirement: _PkgReqType, resource_name: str):
+        """List the contents of the named resource directory"""
+        return get_provider(package_or_requirement).resource_listdir(resource_name)
+
+    def extraction_error(self) -> NoReturn:
+        """Give an error message for problems extracting file(s)"""
+
+        old_exc = sys.exc_info()[1]
+        cache_path = self.extraction_path or get_default_cache()
+
+        tmpl = textwrap.dedent(
+            """
+            Can't extract file(s) to egg cache
+
+            The following error occurred while trying to extract file(s)
+            to the Python egg cache:
+
+              {old_exc}
+
+            The Python egg cache directory is currently set to:
+
+              {cache_path}
+
+            Perhaps your account does not have write access to this directory?
+            You can change the cache directory by setting the PYTHON_EGG_CACHE
+            environment variable to point to an accessible directory.
+            """
+        ).lstrip()
+        err = ExtractionError(tmpl.format(**locals()))
+        err.manager = self
+        err.cache_path = cache_path
+        err.original_error = old_exc
+        raise err
+
+    def get_cache_path(self, archive_name: str, names: Iterable[StrPath] = ()):
+        """Return absolute location in cache for `archive_name` and `names`
+
+        The parent directory of the resulting path will be created if it does
+        not already exist.  `archive_name` should be the base filename of the
+        enclosing egg (which may not be the name of the enclosing zipfile!),
+        including its ".egg" extension.  `names`, if provided, should be a
+        sequence of path name parts "under" the egg's extraction location.
+
+        This method should only be called by resource providers that need to
+        obtain an extraction location, and only for names they intend to
+        extract, as it tracks the generated names for possible cleanup later.
+        """
+        extract_path = self.extraction_path or get_default_cache()
+        target_path = os.path.join(extract_path, archive_name + '-tmp', *names)
+        try:
+            _bypass_ensure_directory(target_path)
+        except Exception:
+            self.extraction_error()
+
+        self._warn_unsafe_extraction_path(extract_path)
+
+        self.cached_files[target_path] = True
+        return target_path
+
+    @staticmethod
+    def _warn_unsafe_extraction_path(path):
+        """
+        If the default extraction path is overridden and set to an insecure
+        location, such as /tmp, it opens up an opportunity for an attacker to
+        replace an extracted file with an unauthorized payload. Warn the user
+        if a known insecure location is used.
+
+        See Distribute #375 for more details.
+        """
+        if os.name == 'nt' and not path.startswith(os.environ['windir']):
+            # On Windows, permissions are generally restrictive by default
+            #  and temp directories are not writable by other users, so
+            #  bypass the warning.
+            return
+        mode = os.stat(path).st_mode
+        if mode & stat.S_IWOTH or mode & stat.S_IWGRP:
+            msg = (
+                "Extraction path is writable by group/others "
+                "and vulnerable to attack when "
+                "used with get_resource_filename ({path}). "
+                "Consider a more secure "
+                "location (set with .set_extraction_path or the "
+                "PYTHON_EGG_CACHE environment variable)."
+            ).format(**locals())
+            warnings.warn(msg, UserWarning)
+
+    def postprocess(self, tempname: StrOrBytesPath, filename: StrOrBytesPath):
+        """Perform any platform-specific postprocessing of `tempname`
+
+        This is where Mac header rewrites should be done; other platforms don't
+        have anything special they should do.
+
+        Resource providers should call this method ONLY after successfully
+        extracting a compressed resource.  They must NOT call it on resources
+        that are already in the filesystem.
+
+        `tempname` is the current (temporary) name of the file, and `filename`
+        is the name it will be renamed to by the caller after this routine
+        returns.
+        """
+
+        if os.name == 'posix':
+            # Make the resource executable
+            mode = ((os.stat(tempname).st_mode) | 0o555) & 0o7777
+            os.chmod(tempname, mode)
+
+    def set_extraction_path(self, path: str):
+        """Set the base path where resources will be extracted to, if needed.
+
+        If you do not call this routine before any extractions take place, the
+        path defaults to the return value of ``get_default_cache()``.  (Which
+        is based on the ``PYTHON_EGG_CACHE`` environment variable, with various
+        platform-specific fallbacks.  See that routine's documentation for more
+        details.)
+
+        Resources are extracted to subdirectories of this path based upon
+        information given by the ``IResourceProvider``.  You may set this to a
+        temporary directory, but then you must call ``cleanup_resources()`` to
+        delete the extracted files when done.  There is no guarantee that
+        ``cleanup_resources()`` will be able to remove all extracted files.
+
+        (Note: you may not change the extraction path for a given resource
+        manager once resources have been extracted, unless you first call
+        ``cleanup_resources()``.)
+        """
+        if self.cached_files:
+            raise ValueError("Can't change extraction path, files already extracted")
+
+        self.extraction_path = path
+
+    def cleanup_resources(self, force: bool = False) -> list[str]:
+        """
+        Delete all extracted resource files and directories, returning a list
+        of the file and directory names that could not be successfully removed.
+        This function does not have any concurrency protection, so it should
+        generally only be called when the extraction path is a temporary
+        directory exclusive to a single process.  This method is not
+        automatically called; you must call it explicitly or register it as an
+        ``atexit`` function if you wish to ensure cleanup of a temporary
+        directory used for extractions.
+        """
+        # XXX
+        return []
+
+
+def get_default_cache() -> str:
+    """
+    Return the ``PYTHON_EGG_CACHE`` environment variable
+    or a platform-relevant user cache dir for an app
+    named "Python-Eggs".
+    """
+    return os.environ.get('PYTHON_EGG_CACHE') or _user_cache_dir(appname='Python-Eggs')
+
+
+def safe_name(name: str):
+    """Convert an arbitrary string to a standard distribution name
+
+    Any runs of non-alphanumeric/. characters are replaced with a single '-'.
+    """
+    return re.sub('[^A-Za-z0-9.]+', '-', name)
+
+
+def safe_version(version: str):
+    """
+    Convert an arbitrary string to a standard version string
+    """
+    try:
+        # normalize the version
+        return str(_packaging_version.Version(version))
+    except _packaging_version.InvalidVersion:
+        version = version.replace(' ', '.')
+        return re.sub('[^A-Za-z0-9.]+', '-', version)
+
+
+def _forgiving_version(version):
+    """Fallback when ``safe_version`` is not safe enough
+    >>> parse_version(_forgiving_version('0.23ubuntu1'))
+    
+    >>> parse_version(_forgiving_version('0.23-'))
+    
+    >>> parse_version(_forgiving_version('0.-_'))
+    
+    >>> parse_version(_forgiving_version('42.+?1'))
+    
+    >>> parse_version(_forgiving_version('hello world'))
+    
+    """
+    version = version.replace(' ', '.')
+    match = _PEP440_FALLBACK.search(version)
+    if match:
+        safe = match["safe"]
+        rest = version[len(safe) :]
+    else:
+        safe = "0"
+        rest = version
+    local = f"sanitized.{_safe_segment(rest)}".strip(".")
+    return f"{safe}.dev0+{local}"
+
+
+def _safe_segment(segment):
+    """Convert an arbitrary string into a safe segment"""
+    segment = re.sub('[^A-Za-z0-9.]+', '-', segment)
+    segment = re.sub('-[^A-Za-z0-9]+', '-', segment)
+    return re.sub(r'\.[^A-Za-z0-9]+', '.', segment).strip(".-")
+
+
+def safe_extra(extra: str):
+    """Convert an arbitrary string to a standard 'extra' name
+
+    Any runs of non-alphanumeric characters are replaced with a single '_',
+    and the result is always lowercased.
+    """
+    return re.sub('[^A-Za-z0-9.-]+', '_', extra).lower()
+
+
+def to_filename(name: str):
+    """Convert a project or version name to its filename-escaped form
+
+    Any '-' characters are currently replaced with '_'.
+    """
+    return name.replace('-', '_')
+
+
+def invalid_marker(text: str):
+    """
+    Validate text as a PEP 508 environment marker; return an exception
+    if invalid or False otherwise.
+    """
+    try:
+        evaluate_marker(text)
+    except SyntaxError as e:
+        e.filename = None
+        e.lineno = None
+        return e
+    return False
+
+
+def evaluate_marker(text: str, extra: str | None = None) -> bool:
+    """
+    Evaluate a PEP 508 environment marker.
+    Return a boolean indicating the marker result in this environment.
+    Raise SyntaxError if marker is invalid.
+
+    This implementation uses the 'pyparsing' module.
+    """
+    try:
+        marker = _packaging_markers.Marker(text)
+        return marker.evaluate()
+    except _packaging_markers.InvalidMarker as e:
+        raise SyntaxError(e) from e
+
+
+class NullProvider:
+    """Try to implement resources and metadata for arbitrary PEP 302 loaders"""
+
+    egg_name: str | None = None
+    egg_info: str | None = None
+    loader: _LoaderProtocol | None = None
+
+    def __init__(self, module: _ModuleLike):
+        self.loader = getattr(module, '__loader__', None)
+        self.module_path = os.path.dirname(getattr(module, '__file__', ''))
+
+    def get_resource_filename(self, manager: ResourceManager, resource_name: str):
+        return self._fn(self.module_path, resource_name)
+
+    def get_resource_stream(self, manager: ResourceManager, resource_name: str):
+        return io.BytesIO(self.get_resource_string(manager, resource_name))
+
+    def get_resource_string(
+        self, manager: ResourceManager, resource_name: str
+    ) -> bytes:
+        return self._get(self._fn(self.module_path, resource_name))
+
+    def has_resource(self, resource_name: str):
+        return self._has(self._fn(self.module_path, resource_name))
+
+    def _get_metadata_path(self, name):
+        return self._fn(self.egg_info, name)
+
+    def has_metadata(self, name: str) -> bool:
+        if not self.egg_info:
+            return False
+
+        path = self._get_metadata_path(name)
+        return self._has(path)
+
+    def get_metadata(self, name: str):
+        if not self.egg_info:
+            return ""
+        path = self._get_metadata_path(name)
+        value = self._get(path)
+        try:
+            return value.decode('utf-8')
+        except UnicodeDecodeError as exc:
+            # Include the path in the error message to simplify
+            # troubleshooting, and without changing the exception type.
+            exc.reason += ' in {} file at path: {}'.format(name, path)
+            raise
+
+    def get_metadata_lines(self, name: str) -> Iterator[str]:
+        return yield_lines(self.get_metadata(name))
+
+    def resource_isdir(self, resource_name: str):
+        return self._isdir(self._fn(self.module_path, resource_name))
+
+    def metadata_isdir(self, name: str) -> bool:
+        return bool(self.egg_info and self._isdir(self._fn(self.egg_info, name)))
+
+    def resource_listdir(self, resource_name: str):
+        return self._listdir(self._fn(self.module_path, resource_name))
+
+    def metadata_listdir(self, name: str) -> list[str]:
+        if self.egg_info:
+            return self._listdir(self._fn(self.egg_info, name))
+        return []
+
+    def run_script(self, script_name: str, namespace: dict[str, Any]):
+        script = 'scripts/' + script_name
+        if not self.has_metadata(script):
+            raise ResolutionError(
+                "Script {script!r} not found in metadata at {self.egg_info!r}".format(
+                    **locals()
+                ),
+            )
+
+        script_text = self.get_metadata(script).replace('\r\n', '\n')
+        script_text = script_text.replace('\r', '\n')
+        script_filename = self._fn(self.egg_info, script)
+        namespace['__file__'] = script_filename
+        if os.path.exists(script_filename):
+            source = _read_utf8_with_fallback(script_filename)
+            code = compile(source, script_filename, 'exec')
+            exec(code, namespace, namespace)
+        else:
+            from linecache import cache
+
+            cache[script_filename] = (
+                len(script_text),
+                0,
+                script_text.split('\n'),
+                script_filename,
+            )
+            script_code = compile(script_text, script_filename, 'exec')
+            exec(script_code, namespace, namespace)
+
+    def _has(self, path) -> bool:
+        raise NotImplementedError(
+            "Can't perform this operation for unregistered loader type"
+        )
+
+    def _isdir(self, path) -> bool:
+        raise NotImplementedError(
+            "Can't perform this operation for unregistered loader type"
+        )
+
+    def _listdir(self, path) -> list[str]:
+        raise NotImplementedError(
+            "Can't perform this operation for unregistered loader type"
+        )
+
+    def _fn(self, base: str | None, resource_name: str):
+        if base is None:
+            raise TypeError(
+                "`base` parameter in `_fn` is `None`. Either override this method or check the parameter first."
+            )
+        self._validate_resource_path(resource_name)
+        if resource_name:
+            return os.path.join(base, *resource_name.split('/'))
+        return base
+
+    @staticmethod
+    def _validate_resource_path(path):
+        """
+        Validate the resource paths according to the docs.
+        https://setuptools.pypa.io/en/latest/pkg_resources.html#basic-resource-access
+
+        >>> warned = getfixture('recwarn')
+        >>> warnings.simplefilter('always')
+        >>> vrp = NullProvider._validate_resource_path
+        >>> vrp('foo/bar.txt')
+        >>> bool(warned)
+        False
+        >>> vrp('../foo/bar.txt')
+        >>> bool(warned)
+        True
+        >>> warned.clear()
+        >>> vrp('/foo/bar.txt')
+        >>> bool(warned)
+        True
+        >>> vrp('foo/../../bar.txt')
+        >>> bool(warned)
+        True
+        >>> warned.clear()
+        >>> vrp('foo/f../bar.txt')
+        >>> bool(warned)
+        False
+
+        Windows path separators are straight-up disallowed.
+        >>> vrp(r'\\foo/bar.txt')
+        Traceback (most recent call last):
+        ...
+        ValueError: Use of .. or absolute path in a resource path \
+is not allowed.
+
+        >>> vrp(r'C:\\foo/bar.txt')
+        Traceback (most recent call last):
+        ...
+        ValueError: Use of .. or absolute path in a resource path \
+is not allowed.
+
+        Blank values are allowed
+
+        >>> vrp('')
+        >>> bool(warned)
+        False
+
+        Non-string values are not.
+
+        >>> vrp(None)
+        Traceback (most recent call last):
+        ...
+        AttributeError: ...
+        """
+        invalid = (
+            os.path.pardir in path.split(posixpath.sep)
+            or posixpath.isabs(path)
+            or ntpath.isabs(path)
+            or path.startswith("\\")
+        )
+        if not invalid:
+            return
+
+        msg = "Use of .. or absolute path in a resource path is not allowed."
+
+        # Aggressively disallow Windows absolute paths
+        if (path.startswith("\\") or ntpath.isabs(path)) and not posixpath.isabs(path):
+            raise ValueError(msg)
+
+        # for compatibility, warn; in future
+        # raise ValueError(msg)
+        issue_warning(
+            msg[:-1] + " and will raise exceptions in a future release.",
+            DeprecationWarning,
+        )
+
+    def _get(self, path) -> bytes:
+        if hasattr(self.loader, 'get_data') and self.loader:
+            # Already checked get_data exists
+            return self.loader.get_data(path)  # type: ignore[attr-defined]
+        raise NotImplementedError(
+            "Can't perform this operation for loaders without 'get_data()'"
+        )
+
+
+register_loader_type(object, NullProvider)
+
+
+def _parents(path):
+    """
+    yield all parents of path including path
+    """
+    last = None
+    while path != last:
+        yield path
+        last = path
+        path, _ = os.path.split(path)
+
+
+class EggProvider(NullProvider):
+    """Provider based on a virtual filesystem"""
+
+    def __init__(self, module: _ModuleLike):
+        super().__init__(module)
+        self._setup_prefix()
+
+    def _setup_prefix(self):
+        # Assume that metadata may be nested inside a "basket"
+        # of multiple eggs and use module_path instead of .archive.
+        eggs = filter(_is_egg_path, _parents(self.module_path))
+        egg = next(eggs, None)
+        egg and self._set_egg(egg)
+
+    def _set_egg(self, path: str):
+        self.egg_name = os.path.basename(path)
+        self.egg_info = os.path.join(path, 'EGG-INFO')
+        self.egg_root = path
+
+
+class DefaultProvider(EggProvider):
+    """Provides access to package resources in the filesystem"""
+
+    def _has(self, path) -> bool:
+        return os.path.exists(path)
+
+    def _isdir(self, path) -> bool:
+        return os.path.isdir(path)
+
+    def _listdir(self, path):
+        return os.listdir(path)
+
+    def get_resource_stream(self, manager: object, resource_name: str):
+        return open(self._fn(self.module_path, resource_name), 'rb')
+
+    def _get(self, path) -> bytes:
+        with open(path, 'rb') as stream:
+            return stream.read()
+
+    @classmethod
+    def _register(cls):
+        loader_names = (
+            'SourceFileLoader',
+            'SourcelessFileLoader',
+        )
+        for name in loader_names:
+            loader_cls = getattr(importlib.machinery, name, type(None))
+            register_loader_type(loader_cls, cls)
+
+
+DefaultProvider._register()
+
+
+class EmptyProvider(NullProvider):
+    """Provider that returns nothing for all requests"""
+
+    # A special case, we don't want all Providers inheriting from NullProvider to have a potentially None module_path
+    module_path: str | None = None  # type: ignore[assignment]
+
+    _isdir = _has = lambda self, path: False
+
+    def _get(self, path) -> bytes:
+        return b''
+
+    def _listdir(self, path):
+        return []
+
+    def __init__(self):
+        pass
+
+
+empty_provider = EmptyProvider()
+
+
+class ZipManifests(Dict[str, "MemoizedZipManifests.manifest_mod"]):
+    """
+    zip manifest builder
+    """
+
+    # `path` could be `StrPath | IO[bytes]` but that violates the LSP for `MemoizedZipManifests.load`
+    @classmethod
+    def build(cls, path: str):
+        """
+        Build a dictionary similar to the zipimport directory
+        caches, except instead of tuples, store ZipInfo objects.
+
+        Use a platform-specific path separator (os.sep) for the path keys
+        for compatibility with pypy on Windows.
+        """
+        with zipfile.ZipFile(path) as zfile:
+            items = (
+                (
+                    name.replace('/', os.sep),
+                    zfile.getinfo(name),
+                )
+                for name in zfile.namelist()
+            )
+            return dict(items)
+
+    load = build
+
+
+class MemoizedZipManifests(ZipManifests):
+    """
+    Memoized zipfile manifests.
+    """
+
+    class manifest_mod(NamedTuple):
+        manifest: dict[str, zipfile.ZipInfo]
+        mtime: float
+
+    def load(self, path: str) -> dict[str, zipfile.ZipInfo]:  # type: ignore[override] # ZipManifests.load is a classmethod
+        """
+        Load a manifest at path or return a suitable manifest already loaded.
+        """
+        path = os.path.normpath(path)
+        mtime = os.stat(path).st_mtime
+
+        if path not in self or self[path].mtime != mtime:
+            manifest = self.build(path)
+            self[path] = self.manifest_mod(manifest, mtime)
+
+        return self[path].manifest
+
+
+class ZipProvider(EggProvider):
+    """Resource support for zips and eggs"""
+
+    eagers: list[str] | None = None
+    _zip_manifests = MemoizedZipManifests()
+    # ZipProvider's loader should always be a zipimporter or equivalent
+    loader: zipimport.zipimporter
+
+    def __init__(self, module: _ZipLoaderModule):
+        super().__init__(module)
+        self.zip_pre = self.loader.archive + os.sep
+
+    def _zipinfo_name(self, fspath):
+        # Convert a virtual filename (full path to file) into a zipfile subpath
+        # usable with the zipimport directory cache for our target archive
+        fspath = fspath.rstrip(os.sep)
+        if fspath == self.loader.archive:
+            return ''
+        if fspath.startswith(self.zip_pre):
+            return fspath[len(self.zip_pre) :]
+        raise AssertionError("%s is not a subpath of %s" % (fspath, self.zip_pre))
+
+    def _parts(self, zip_path):
+        # Convert a zipfile subpath into an egg-relative path part list.
+        # pseudo-fs path
+        fspath = self.zip_pre + zip_path
+        if fspath.startswith(self.egg_root + os.sep):
+            return fspath[len(self.egg_root) + 1 :].split(os.sep)
+        raise AssertionError("%s is not a subpath of %s" % (fspath, self.egg_root))
+
+    @property
+    def zipinfo(self):
+        return self._zip_manifests.load(self.loader.archive)
+
+    def get_resource_filename(self, manager: ResourceManager, resource_name: str):
+        if not self.egg_name:
+            raise NotImplementedError(
+                "resource_filename() only supported for .egg, not .zip"
+            )
+        # no need to lock for extraction, since we use temp names
+        zip_path = self._resource_to_zip(resource_name)
+        eagers = self._get_eager_resources()
+        if '/'.join(self._parts(zip_path)) in eagers:
+            for name in eagers:
+                self._extract_resource(manager, self._eager_to_zip(name))
+        return self._extract_resource(manager, zip_path)
+
+    @staticmethod
+    def _get_date_and_size(zip_stat):
+        size = zip_stat.file_size
+        # ymdhms+wday, yday, dst
+        date_time = zip_stat.date_time + (0, 0, -1)
+        # 1980 offset already done
+        timestamp = time.mktime(date_time)
+        return timestamp, size
+
+    # FIXME: 'ZipProvider._extract_resource' is too complex (12)
+    def _extract_resource(self, manager: ResourceManager, zip_path) -> str:  # noqa: C901
+        if zip_path in self._index():
+            for name in self._index()[zip_path]:
+                last = self._extract_resource(manager, os.path.join(zip_path, name))
+            # return the extracted directory name
+            return os.path.dirname(last)
+
+        timestamp, size = self._get_date_and_size(self.zipinfo[zip_path])
+
+        if not WRITE_SUPPORT:
+            raise OSError(
+                '"os.rename" and "os.unlink" are not supported on this platform'
+            )
+        try:
+            if not self.egg_name:
+                raise OSError(
+                    '"egg_name" is empty. This likely means no egg could be found from the "module_path".'
+                )
+            real_path = manager.get_cache_path(self.egg_name, self._parts(zip_path))
+
+            if self._is_current(real_path, zip_path):
+                return real_path
+
+            outf, tmpnam = _mkstemp(
+                ".$extract",
+                dir=os.path.dirname(real_path),
+            )
+            os.write(outf, self.loader.get_data(zip_path))
+            os.close(outf)
+            utime(tmpnam, (timestamp, timestamp))
+            manager.postprocess(tmpnam, real_path)
+
+            try:
+                rename(tmpnam, real_path)
+
+            except OSError:
+                if os.path.isfile(real_path):
+                    if self._is_current(real_path, zip_path):
+                        # the file became current since it was checked above,
+                        #  so proceed.
+                        return real_path
+                    # Windows, del old file and retry
+                    elif os.name == 'nt':
+                        unlink(real_path)
+                        rename(tmpnam, real_path)
+                        return real_path
+                raise
+
+        except OSError:
+            # report a user-friendly error
+            manager.extraction_error()
+
+        return real_path
+
+    def _is_current(self, file_path, zip_path):
+        """
+        Return True if the file_path is current for this zip_path
+        """
+        timestamp, size = self._get_date_and_size(self.zipinfo[zip_path])
+        if not os.path.isfile(file_path):
+            return False
+        stat = os.stat(file_path)
+        if stat.st_size != size or stat.st_mtime != timestamp:
+            return False
+        # check that the contents match
+        zip_contents = self.loader.get_data(zip_path)
+        with open(file_path, 'rb') as f:
+            file_contents = f.read()
+        return zip_contents == file_contents
+
+    def _get_eager_resources(self):
+        if self.eagers is None:
+            eagers = []
+            for name in ('native_libs.txt', 'eager_resources.txt'):
+                if self.has_metadata(name):
+                    eagers.extend(self.get_metadata_lines(name))
+            self.eagers = eagers
+        return self.eagers
+
+    def _index(self):
+        try:
+            return self._dirindex
+        except AttributeError:
+            ind = {}
+            for path in self.zipinfo:
+                parts = path.split(os.sep)
+                while parts:
+                    parent = os.sep.join(parts[:-1])
+                    if parent in ind:
+                        ind[parent].append(parts[-1])
+                        break
+                    else:
+                        ind[parent] = [parts.pop()]
+            self._dirindex = ind
+            return ind
+
+    def _has(self, fspath) -> bool:
+        zip_path = self._zipinfo_name(fspath)
+        return zip_path in self.zipinfo or zip_path in self._index()
+
+    def _isdir(self, fspath) -> bool:
+        return self._zipinfo_name(fspath) in self._index()
+
+    def _listdir(self, fspath):
+        return list(self._index().get(self._zipinfo_name(fspath), ()))
+
+    def _eager_to_zip(self, resource_name: str):
+        return self._zipinfo_name(self._fn(self.egg_root, resource_name))
+
+    def _resource_to_zip(self, resource_name: str):
+        return self._zipinfo_name(self._fn(self.module_path, resource_name))
+
+
+register_loader_type(zipimport.zipimporter, ZipProvider)
+
+
+class FileMetadata(EmptyProvider):
+    """Metadata handler for standalone PKG-INFO files
+
+    Usage::
+
+        metadata = FileMetadata("/path/to/PKG-INFO")
+
+    This provider rejects all data and metadata requests except for PKG-INFO,
+    which is treated as existing, and will be the contents of the file at
+    the provided location.
+    """
+
+    def __init__(self, path: StrPath):
+        self.path = path
+
+    def _get_metadata_path(self, name):
+        return self.path
+
+    def has_metadata(self, name: str) -> bool:
+        return name == 'PKG-INFO' and os.path.isfile(self.path)
+
+    def get_metadata(self, name: str):
+        if name != 'PKG-INFO':
+            raise KeyError("No metadata except PKG-INFO is available")
+
+        with open(self.path, encoding='utf-8', errors="replace") as f:
+            metadata = f.read()
+        self._warn_on_replacement(metadata)
+        return metadata
+
+    def _warn_on_replacement(self, metadata):
+        replacement_char = '�'
+        if replacement_char in metadata:
+            tmpl = "{self.path} could not be properly decoded in UTF-8"
+            msg = tmpl.format(**locals())
+            warnings.warn(msg)
+
+    def get_metadata_lines(self, name: str) -> Iterator[str]:
+        return yield_lines(self.get_metadata(name))
+
+
+class PathMetadata(DefaultProvider):
+    """Metadata provider for egg directories
+
+    Usage::
+
+        # Development eggs:
+
+        egg_info = "/path/to/PackageName.egg-info"
+        base_dir = os.path.dirname(egg_info)
+        metadata = PathMetadata(base_dir, egg_info)
+        dist_name = os.path.splitext(os.path.basename(egg_info))[0]
+        dist = Distribution(basedir, project_name=dist_name, metadata=metadata)
+
+        # Unpacked egg directories:
+
+        egg_path = "/path/to/PackageName-ver-pyver-etc.egg"
+        metadata = PathMetadata(egg_path, os.path.join(egg_path,'EGG-INFO'))
+        dist = Distribution.from_filename(egg_path, metadata=metadata)
+    """
+
+    def __init__(self, path: str, egg_info: str):
+        self.module_path = path
+        self.egg_info = egg_info
+
+
+class EggMetadata(ZipProvider):
+    """Metadata provider for .egg files"""
+
+    def __init__(self, importer: zipimport.zipimporter):
+        """Create a metadata provider from a zipimporter"""
+
+        self.zip_pre = importer.archive + os.sep
+        self.loader = importer
+        if importer.prefix:
+            self.module_path = os.path.join(importer.archive, importer.prefix)
+        else:
+            self.module_path = importer.archive
+        self._setup_prefix()
+
+
+_distribution_finders: dict[type, _DistFinderType[Any]] = _declare_state(
+    'dict', '_distribution_finders', {}
+)
+
+
+def register_finder(importer_type: type[_T], distribution_finder: _DistFinderType[_T]):
+    """Register `distribution_finder` to find distributions in sys.path items
+
+    `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item
+    handler), and `distribution_finder` is a callable that, passed a path
+    item and the importer instance, yields ``Distribution`` instances found on
+    that path item.  See ``pkg_resources.find_on_path`` for an example."""
+    _distribution_finders[importer_type] = distribution_finder
+
+
+def find_distributions(path_item: str, only: bool = False):
+    """Yield distributions accessible via `path_item`"""
+    importer = get_importer(path_item)
+    finder = _find_adapter(_distribution_finders, importer)
+    return finder(importer, path_item, only)
+
+
+def find_eggs_in_zip(
+    importer: zipimport.zipimporter, path_item: str, only: bool = False
+) -> Iterator[Distribution]:
+    """
+    Find eggs in zip files; possibly multiple nested eggs.
+    """
+    if importer.archive.endswith('.whl'):
+        # wheels are not supported with this finder
+        # they don't have PKG-INFO metadata, and won't ever contain eggs
+        return
+    metadata = EggMetadata(importer)
+    if metadata.has_metadata('PKG-INFO'):
+        yield Distribution.from_filename(path_item, metadata=metadata)
+    if only:
+        # don't yield nested distros
+        return
+    for subitem in metadata.resource_listdir(''):
+        if _is_egg_path(subitem):
+            subpath = os.path.join(path_item, subitem)
+            dists = find_eggs_in_zip(zipimport.zipimporter(subpath), subpath)
+            yield from dists
+        elif subitem.lower().endswith(('.dist-info', '.egg-info')):
+            subpath = os.path.join(path_item, subitem)
+            submeta = EggMetadata(zipimport.zipimporter(subpath))
+            submeta.egg_info = subpath
+            yield Distribution.from_location(path_item, subitem, submeta)
+
+
+register_finder(zipimport.zipimporter, find_eggs_in_zip)
+
+
+def find_nothing(
+    importer: object | None, path_item: str | None, only: bool | None = False
+):
+    return ()
+
+
+register_finder(object, find_nothing)
+
+
+def find_on_path(importer: object | None, path_item, only=False):
+    """Yield distributions accessible on a sys.path directory"""
+    path_item = _normalize_cached(path_item)
+
+    if _is_unpacked_egg(path_item):
+        yield Distribution.from_filename(
+            path_item,
+            metadata=PathMetadata(path_item, os.path.join(path_item, 'EGG-INFO')),
+        )
+        return
+
+    entries = (os.path.join(path_item, child) for child in safe_listdir(path_item))
+
+    # scan for .egg and .egg-info in directory
+    for entry in sorted(entries):
+        fullpath = os.path.join(path_item, entry)
+        factory = dist_factory(path_item, entry, only)
+        yield from factory(fullpath)
+
+
+def dist_factory(path_item, entry, only):
+    """Return a dist_factory for the given entry."""
+    lower = entry.lower()
+    is_egg_info = lower.endswith('.egg-info')
+    is_dist_info = lower.endswith('.dist-info') and os.path.isdir(
+        os.path.join(path_item, entry)
+    )
+    is_meta = is_egg_info or is_dist_info
+    return (
+        distributions_from_metadata
+        if is_meta
+        else find_distributions
+        if not only and _is_egg_path(entry)
+        else resolve_egg_link
+        if not only and lower.endswith('.egg-link')
+        else NoDists()
+    )
+
+
+class NoDists:
+    """
+    >>> bool(NoDists())
+    False
+
+    >>> list(NoDists()('anything'))
+    []
+    """
+
+    def __bool__(self):
+        return False
+
+    def __call__(self, fullpath):
+        return iter(())
+
+
+def safe_listdir(path: StrOrBytesPath):
+    """
+    Attempt to list contents of path, but suppress some exceptions.
+    """
+    try:
+        return os.listdir(path)
+    except (PermissionError, NotADirectoryError):
+        pass
+    except OSError as e:
+        # Ignore the directory if does not exist, not a directory or
+        # permission denied
+        if e.errno not in (errno.ENOTDIR, errno.EACCES, errno.ENOENT):
+            raise
+    return ()
+
+
+def distributions_from_metadata(path: str):
+    root = os.path.dirname(path)
+    if os.path.isdir(path):
+        if len(os.listdir(path)) == 0:
+            # empty metadata dir; skip
+            return
+        metadata: _MetadataType = PathMetadata(root, path)
+    else:
+        metadata = FileMetadata(path)
+    entry = os.path.basename(path)
+    yield Distribution.from_location(
+        root,
+        entry,
+        metadata,
+        precedence=DEVELOP_DIST,
+    )
+
+
+def non_empty_lines(path):
+    """
+    Yield non-empty lines from file at path
+    """
+    for line in _read_utf8_with_fallback(path).splitlines():
+        line = line.strip()
+        if line:
+            yield line
+
+
+def resolve_egg_link(path):
+    """
+    Given a path to an .egg-link, resolve distributions
+    present in the referenced path.
+    """
+    referenced_paths = non_empty_lines(path)
+    resolved_paths = (
+        os.path.join(os.path.dirname(path), ref) for ref in referenced_paths
+    )
+    dist_groups = map(find_distributions, resolved_paths)
+    return next(dist_groups, ())
+
+
+if hasattr(pkgutil, 'ImpImporter'):
+    register_finder(pkgutil.ImpImporter, find_on_path)
+
+register_finder(importlib.machinery.FileFinder, find_on_path)
+
+_namespace_handlers: dict[type, _NSHandlerType[Any]] = _declare_state(
+    'dict', '_namespace_handlers', {}
+)
+_namespace_packages: dict[str | None, list[str]] = _declare_state(
+    'dict', '_namespace_packages', {}
+)
+
+
+def register_namespace_handler(
+    importer_type: type[_T], namespace_handler: _NSHandlerType[_T]
+):
+    """Register `namespace_handler` to declare namespace packages
+
+    `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item
+    handler), and `namespace_handler` is a callable like this::
+
+        def namespace_handler(importer, path_entry, moduleName, module):
+            # return a path_entry to use for child packages
+
+    Namespace handlers are only called if the importer object has already
+    agreed that it can handle the relevant path item, and they should only
+    return a subpath if the module __path__ does not already contain an
+    equivalent subpath.  For an example namespace handler, see
+    ``pkg_resources.file_ns_handler``.
+    """
+    _namespace_handlers[importer_type] = namespace_handler
+
+
+def _handle_ns(packageName, path_item):
+    """Ensure that named package includes a subpath of path_item (if needed)"""
+
+    importer = get_importer(path_item)
+    if importer is None:
+        return None
+
+    # use find_spec (PEP 451) and fall-back to find_module (PEP 302)
+    try:
+        spec = importer.find_spec(packageName)
+    except AttributeError:
+        # capture warnings due to #1111
+        with warnings.catch_warnings():
+            warnings.simplefilter("ignore")
+            loader = importer.find_module(packageName)
+    else:
+        loader = spec.loader if spec else None
+
+    if loader is None:
+        return None
+    module = sys.modules.get(packageName)
+    if module is None:
+        module = sys.modules[packageName] = types.ModuleType(packageName)
+        module.__path__ = []
+        _set_parent_ns(packageName)
+    elif not hasattr(module, '__path__'):
+        raise TypeError("Not a package:", packageName)
+    handler = _find_adapter(_namespace_handlers, importer)
+    subpath = handler(importer, path_item, packageName, module)
+    if subpath is not None:
+        path = module.__path__
+        path.append(subpath)
+        importlib.import_module(packageName)
+        _rebuild_mod_path(path, packageName, module)
+    return subpath
+
+
+def _rebuild_mod_path(orig_path, package_name, module: types.ModuleType):
+    """
+    Rebuild module.__path__ ensuring that all entries are ordered
+    corresponding to their sys.path order
+    """
+    sys_path = [_normalize_cached(p) for p in sys.path]
+
+    def safe_sys_path_index(entry):
+        """
+        Workaround for #520 and #513.
+        """
+        try:
+            return sys_path.index(entry)
+        except ValueError:
+            return float('inf')
+
+    def position_in_sys_path(path):
+        """
+        Return the ordinal of the path based on its position in sys.path
+        """
+        path_parts = path.split(os.sep)
+        module_parts = package_name.count('.') + 1
+        parts = path_parts[:-module_parts]
+        return safe_sys_path_index(_normalize_cached(os.sep.join(parts)))
+
+    new_path = sorted(orig_path, key=position_in_sys_path)
+    new_path = [_normalize_cached(p) for p in new_path]
+
+    if isinstance(module.__path__, list):
+        module.__path__[:] = new_path
+    else:
+        module.__path__ = new_path
+
+
+def declare_namespace(packageName: str):
+    """Declare that package 'packageName' is a namespace package"""
+
+    msg = (
+        f"Deprecated call to `pkg_resources.declare_namespace({packageName!r})`.\n"
+        "Implementing implicit namespace packages (as specified in PEP 420) "
+        "is preferred to `pkg_resources.declare_namespace`. "
+        "See https://setuptools.pypa.io/en/latest/references/"
+        "keywords.html#keyword-namespace-packages"
+    )
+    warnings.warn(msg, DeprecationWarning, stacklevel=2)
+
+    _imp.acquire_lock()
+    try:
+        if packageName in _namespace_packages:
+            return
+
+        path: MutableSequence[str] = sys.path
+        parent, _, _ = packageName.rpartition('.')
+
+        if parent:
+            declare_namespace(parent)
+            if parent not in _namespace_packages:
+                __import__(parent)
+            try:
+                path = sys.modules[parent].__path__
+            except AttributeError as e:
+                raise TypeError("Not a package:", parent) from e
+
+        # Track what packages are namespaces, so when new path items are added,
+        # they can be updated
+        _namespace_packages.setdefault(parent or None, []).append(packageName)
+        _namespace_packages.setdefault(packageName, [])
+
+        for path_item in path:
+            # Ensure all the parent's path items are reflected in the child,
+            # if they apply
+            _handle_ns(packageName, path_item)
+
+    finally:
+        _imp.release_lock()
+
+
+def fixup_namespace_packages(path_item: str, parent: str | None = None):
+    """Ensure that previously-declared namespace packages include path_item"""
+    _imp.acquire_lock()
+    try:
+        for package in _namespace_packages.get(parent, ()):
+            subpath = _handle_ns(package, path_item)
+            if subpath:
+                fixup_namespace_packages(subpath, package)
+    finally:
+        _imp.release_lock()
+
+
+def file_ns_handler(
+    importer: object,
+    path_item: StrPath,
+    packageName: str,
+    module: types.ModuleType,
+):
+    """Compute an ns-package subpath for a filesystem or zipfile importer"""
+
+    subpath = os.path.join(path_item, packageName.split('.')[-1])
+    normalized = _normalize_cached(subpath)
+    for item in module.__path__:
+        if _normalize_cached(item) == normalized:
+            break
+    else:
+        # Only return the path if it's not already there
+        return subpath
+
+
+if hasattr(pkgutil, 'ImpImporter'):
+    register_namespace_handler(pkgutil.ImpImporter, file_ns_handler)
+
+register_namespace_handler(zipimport.zipimporter, file_ns_handler)
+register_namespace_handler(importlib.machinery.FileFinder, file_ns_handler)
+
+
+def null_ns_handler(
+    importer: object,
+    path_item: str | None,
+    packageName: str | None,
+    module: _ModuleLike | None,
+):
+    return None
+
+
+register_namespace_handler(object, null_ns_handler)
+
+
+@overload
+def normalize_path(filename: StrPath) -> str: ...
+@overload
+def normalize_path(filename: BytesPath) -> bytes: ...
+def normalize_path(filename: StrOrBytesPath):
+    """Normalize a file/dir name for comparison purposes"""
+    return os.path.normcase(os.path.realpath(os.path.normpath(_cygwin_patch(filename))))
+
+
+def _cygwin_patch(filename: StrOrBytesPath):  # pragma: nocover
+    """
+    Contrary to POSIX 2008, on Cygwin, getcwd (3) contains
+    symlink components. Using
+    os.path.abspath() works around this limitation. A fix in os.getcwd()
+    would probably better, in Cygwin even more so, except
+    that this seems to be by design...
+    """
+    return os.path.abspath(filename) if sys.platform == 'cygwin' else filename
+
+
+if TYPE_CHECKING:
+    # https://github.com/python/mypy/issues/16261
+    # https://github.com/python/typeshed/issues/6347
+    @overload
+    def _normalize_cached(filename: StrPath) -> str: ...
+    @overload
+    def _normalize_cached(filename: BytesPath) -> bytes: ...
+    def _normalize_cached(filename: StrOrBytesPath) -> str | bytes: ...
+else:
+
+    @functools.lru_cache(maxsize=None)
+    def _normalize_cached(filename):
+        return normalize_path(filename)
+
+
+def _is_egg_path(path):
+    """
+    Determine if given path appears to be an egg.
+    """
+    return _is_zip_egg(path) or _is_unpacked_egg(path)
+
+
+def _is_zip_egg(path):
+    return (
+        path.lower().endswith('.egg')
+        and os.path.isfile(path)
+        and zipfile.is_zipfile(path)
+    )
+
+
+def _is_unpacked_egg(path):
+    """
+    Determine if given path appears to be an unpacked egg.
+    """
+    return path.lower().endswith('.egg') and os.path.isfile(
+        os.path.join(path, 'EGG-INFO', 'PKG-INFO')
+    )
+
+
+def _set_parent_ns(packageName):
+    parts = packageName.split('.')
+    name = parts.pop()
+    if parts:
+        parent = '.'.join(parts)
+        setattr(sys.modules[parent], name, sys.modules[packageName])
+
+
+MODULE = re.compile(r"\w+(\.\w+)*$").match
+EGG_NAME = re.compile(
+    r"""
+    (?P[^-]+) (
+        -(?P[^-]+) (
+            -py(?P[^-]+) (
+                -(?P.+)
+            )?
+        )?
+    )?
+    """,
+    re.VERBOSE | re.IGNORECASE,
+).match
+
+
+class EntryPoint:
+    """Object representing an advertised importable object"""
+
+    def __init__(
+        self,
+        name: str,
+        module_name: str,
+        attrs: Iterable[str] = (),
+        extras: Iterable[str] = (),
+        dist: Distribution | None = None,
+    ):
+        if not MODULE(module_name):
+            raise ValueError("Invalid module name", module_name)
+        self.name = name
+        self.module_name = module_name
+        self.attrs = tuple(attrs)
+        self.extras = tuple(extras)
+        self.dist = dist
+
+    def __str__(self):
+        s = "%s = %s" % (self.name, self.module_name)
+        if self.attrs:
+            s += ':' + '.'.join(self.attrs)
+        if self.extras:
+            s += ' [%s]' % ','.join(self.extras)
+        return s
+
+    def __repr__(self):
+        return "EntryPoint.parse(%r)" % str(self)
+
+    @overload
+    def load(
+        self,
+        require: Literal[True] = True,
+        env: Environment | None = None,
+        installer: _InstallerType | None = None,
+    ) -> _ResolvedEntryPoint: ...
+    @overload
+    def load(
+        self,
+        require: Literal[False],
+        *args: Any,
+        **kwargs: Any,
+    ) -> _ResolvedEntryPoint: ...
+    def load(
+        self,
+        require: bool = True,
+        *args: Environment | _InstallerType | None,
+        **kwargs: Environment | _InstallerType | None,
+    ) -> _ResolvedEntryPoint:
+        """
+        Require packages for this EntryPoint, then resolve it.
+        """
+        if not require or args or kwargs:
+            warnings.warn(
+                "Parameters to load are deprecated.  Call .resolve and "
+                ".require separately.",
+                PkgResourcesDeprecationWarning,
+                stacklevel=2,
+            )
+        if require:
+            # We could pass `env` and `installer` directly,
+            # but keeping `*args` and `**kwargs` for backwards compatibility
+            self.require(*args, **kwargs)  # type: ignore
+        return self.resolve()
+
+    def resolve(self) -> _ResolvedEntryPoint:
+        """
+        Resolve the entry point from its module and attrs.
+        """
+        module = __import__(self.module_name, fromlist=['__name__'], level=0)
+        try:
+            return functools.reduce(getattr, self.attrs, module)
+        except AttributeError as exc:
+            raise ImportError(str(exc)) from exc
+
+    def require(
+        self,
+        env: Environment | None = None,
+        installer: _InstallerType | None = None,
+    ):
+        if not self.dist:
+            error_cls = UnknownExtra if self.extras else AttributeError
+            raise error_cls("Can't require() without a distribution", self)
+
+        # Get the requirements for this entry point with all its extras and
+        # then resolve them. We have to pass `extras` along when resolving so
+        # that the working set knows what extras we want. Otherwise, for
+        # dist-info distributions, the working set will assume that the
+        # requirements for that extra are purely optional and skip over them.
+        reqs = self.dist.requires(self.extras)
+        items = working_set.resolve(reqs, env, installer, extras=self.extras)
+        list(map(working_set.add, items))
+
+    pattern = re.compile(
+        r'\s*'
+        r'(?P.+?)\s*'
+        r'=\s*'
+        r'(?P[\w.]+)\s*'
+        r'(:\s*(?P[\w.]+))?\s*'
+        r'(?P\[.*\])?\s*$'
+    )
+
+    @classmethod
+    def parse(cls, src: str, dist: Distribution | None = None):
+        """Parse a single entry point from string `src`
+
+        Entry point syntax follows the form::
+
+            name = some.module:some.attr [extra1, extra2]
+
+        The entry name and module name are required, but the ``:attrs`` and
+        ``[extras]`` parts are optional
+        """
+        m = cls.pattern.match(src)
+        if not m:
+            msg = "EntryPoint must be in 'name=module:attrs [extras]' format"
+            raise ValueError(msg, src)
+        res = m.groupdict()
+        extras = cls._parse_extras(res['extras'])
+        attrs = res['attr'].split('.') if res['attr'] else ()
+        return cls(res['name'], res['module'], attrs, extras, dist)
+
+    @classmethod
+    def _parse_extras(cls, extras_spec):
+        if not extras_spec:
+            return ()
+        req = Requirement.parse('x' + extras_spec)
+        if req.specs:
+            raise ValueError
+        return req.extras
+
+    @classmethod
+    def parse_group(
+        cls,
+        group: str,
+        lines: _NestedStr,
+        dist: Distribution | None = None,
+    ):
+        """Parse an entry point group"""
+        if not MODULE(group):
+            raise ValueError("Invalid group name", group)
+        this: dict[str, Self] = {}
+        for line in yield_lines(lines):
+            ep = cls.parse(line, dist)
+            if ep.name in this:
+                raise ValueError("Duplicate entry point", group, ep.name)
+            this[ep.name] = ep
+        return this
+
+    @classmethod
+    def parse_map(
+        cls,
+        data: str | Iterable[str] | dict[str, str | Iterable[str]],
+        dist: Distribution | None = None,
+    ):
+        """Parse a map of entry point groups"""
+        _data: Iterable[tuple[str | None, str | Iterable[str]]]
+        if isinstance(data, dict):
+            _data = data.items()
+        else:
+            _data = split_sections(data)
+        maps: dict[str, dict[str, Self]] = {}
+        for group, lines in _data:
+            if group is None:
+                if not lines:
+                    continue
+                raise ValueError("Entry points must be listed in groups")
+            group = group.strip()
+            if group in maps:
+                raise ValueError("Duplicate group name", group)
+            maps[group] = cls.parse_group(group, lines, dist)
+        return maps
+
+
+def _version_from_file(lines):
+    """
+    Given an iterable of lines from a Metadata file, return
+    the value of the Version field, if present, or None otherwise.
+    """
+
+    def is_version_line(line):
+        return line.lower().startswith('version:')
+
+    version_lines = filter(is_version_line, lines)
+    line = next(iter(version_lines), '')
+    _, _, value = line.partition(':')
+    return safe_version(value.strip()) or None
+
+
+class Distribution:
+    """Wrap an actual or potential sys.path entry w/metadata"""
+
+    PKG_INFO = 'PKG-INFO'
+
+    def __init__(
+        self,
+        location: str | None = None,
+        metadata: _MetadataType = None,
+        project_name: str | None = None,
+        version: str | None = None,
+        py_version: str | None = PY_MAJOR,
+        platform: str | None = None,
+        precedence: int = EGG_DIST,
+    ):
+        self.project_name = safe_name(project_name or 'Unknown')
+        if version is not None:
+            self._version = safe_version(version)
+        self.py_version = py_version
+        self.platform = platform
+        self.location = location
+        self.precedence = precedence
+        self._provider = metadata or empty_provider
+
+    @classmethod
+    def from_location(
+        cls,
+        location: str,
+        basename: StrPath,
+        metadata: _MetadataType = None,
+        **kw: int,  # We could set `precedence` explicitly, but keeping this as `**kw` for full backwards and subclassing compatibility
+    ) -> Distribution:
+        project_name, version, py_version, platform = [None] * 4
+        basename, ext = os.path.splitext(basename)
+        if ext.lower() in _distributionImpl:
+            cls = _distributionImpl[ext.lower()]
+
+            match = EGG_NAME(basename)
+            if match:
+                project_name, version, py_version, platform = match.group(
+                    'name', 'ver', 'pyver', 'plat'
+                )
+        return cls(
+            location,
+            metadata,
+            project_name=project_name,
+            version=version,
+            py_version=py_version,
+            platform=platform,
+            **kw,
+        )._reload_version()
+
+    def _reload_version(self):
+        return self
+
+    @property
+    def hashcmp(self):
+        return (
+            self._forgiving_parsed_version,
+            self.precedence,
+            self.key,
+            self.location,
+            self.py_version or '',
+            self.platform or '',
+        )
+
+    def __hash__(self):
+        return hash(self.hashcmp)
+
+    def __lt__(self, other: Distribution):
+        return self.hashcmp < other.hashcmp
+
+    def __le__(self, other: Distribution):
+        return self.hashcmp <= other.hashcmp
+
+    def __gt__(self, other: Distribution):
+        return self.hashcmp > other.hashcmp
+
+    def __ge__(self, other: Distribution):
+        return self.hashcmp >= other.hashcmp
+
+    def __eq__(self, other: object):
+        if not isinstance(other, self.__class__):
+            # It's not a Distribution, so they are not equal
+            return False
+        return self.hashcmp == other.hashcmp
+
+    def __ne__(self, other: object):
+        return not self == other
+
+    # These properties have to be lazy so that we don't have to load any
+    # metadata until/unless it's actually needed.  (i.e., some distributions
+    # may not know their name or version without loading PKG-INFO)
+
+    @property
+    def key(self):
+        try:
+            return self._key
+        except AttributeError:
+            self._key = key = self.project_name.lower()
+            return key
+
+    @property
+    def parsed_version(self):
+        if not hasattr(self, "_parsed_version"):
+            try:
+                self._parsed_version = parse_version(self.version)
+            except _packaging_version.InvalidVersion as ex:
+                info = f"(package: {self.project_name})"
+                if hasattr(ex, "add_note"):
+                    ex.add_note(info)  # PEP 678
+                    raise
+                raise _packaging_version.InvalidVersion(f"{str(ex)} {info}") from None
+
+        return self._parsed_version
+
+    @property
+    def _forgiving_parsed_version(self):
+        try:
+            return self.parsed_version
+        except _packaging_version.InvalidVersion as ex:
+            self._parsed_version = parse_version(_forgiving_version(self.version))
+
+            notes = "\n".join(getattr(ex, "__notes__", []))  # PEP 678
+            msg = f"""!!\n\n
+            *************************************************************************
+            {str(ex)}\n{notes}
+
+            This is a long overdue deprecation.
+            For the time being, `pkg_resources` will use `{self._parsed_version}`
+            as a replacement to avoid breaking existing environments,
+            but no future compatibility is guaranteed.
+
+            If you maintain package {self.project_name} you should implement
+            the relevant changes to adequate the project to PEP 440 immediately.
+            *************************************************************************
+            \n\n!!
+            """
+            warnings.warn(msg, DeprecationWarning)
+
+            return self._parsed_version
+
+    @property
+    def version(self):
+        try:
+            return self._version
+        except AttributeError as e:
+            version = self._get_version()
+            if version is None:
+                path = self._get_metadata_path_for_display(self.PKG_INFO)
+                msg = ("Missing 'Version:' header and/or {} file at path: {}").format(
+                    self.PKG_INFO, path
+                )
+                raise ValueError(msg, self) from e
+
+            return version
+
+    @property
+    def _dep_map(self):
+        """
+        A map of extra to its list of (direct) requirements
+        for this distribution, including the null extra.
+        """
+        try:
+            return self.__dep_map
+        except AttributeError:
+            self.__dep_map = self._filter_extras(self._build_dep_map())
+        return self.__dep_map
+
+    @staticmethod
+    def _filter_extras(dm: dict[str | None, list[Requirement]]):
+        """
+        Given a mapping of extras to dependencies, strip off
+        environment markers and filter out any dependencies
+        not matching the markers.
+        """
+        for extra in list(filter(None, dm)):
+            new_extra: str | None = extra
+            reqs = dm.pop(extra)
+            new_extra, _, marker = extra.partition(':')
+            fails_marker = marker and (
+                invalid_marker(marker) or not evaluate_marker(marker)
+            )
+            if fails_marker:
+                reqs = []
+            new_extra = safe_extra(new_extra) or None
+
+            dm.setdefault(new_extra, []).extend(reqs)
+        return dm
+
+    def _build_dep_map(self):
+        dm = {}
+        for name in 'requires.txt', 'depends.txt':
+            for extra, reqs in split_sections(self._get_metadata(name)):
+                dm.setdefault(extra, []).extend(parse_requirements(reqs))
+        return dm
+
+    def requires(self, extras: Iterable[str] = ()):
+        """List of Requirements needed for this distro if `extras` are used"""
+        dm = self._dep_map
+        deps: list[Requirement] = []
+        deps.extend(dm.get(None, ()))
+        for ext in extras:
+            try:
+                deps.extend(dm[safe_extra(ext)])
+            except KeyError as e:
+                raise UnknownExtra(
+                    "%s has no such extra feature %r" % (self, ext)
+                ) from e
+        return deps
+
+    def _get_metadata_path_for_display(self, name):
+        """
+        Return the path to the given metadata file, if available.
+        """
+        try:
+            # We need to access _get_metadata_path() on the provider object
+            # directly rather than through this class's __getattr__()
+            # since _get_metadata_path() is marked private.
+            path = self._provider._get_metadata_path(name)
+
+        # Handle exceptions e.g. in case the distribution's metadata
+        # provider doesn't support _get_metadata_path().
+        except Exception:
+            return '[could not detect]'
+
+        return path
+
+    def _get_metadata(self, name):
+        if self.has_metadata(name):
+            yield from self.get_metadata_lines(name)
+
+    def _get_version(self):
+        lines = self._get_metadata(self.PKG_INFO)
+        return _version_from_file(lines)
+
+    def activate(self, path: list[str] | None = None, replace: bool = False):
+        """Ensure distribution is importable on `path` (default=sys.path)"""
+        if path is None:
+            path = sys.path
+        self.insert_on(path, replace=replace)
+        if path is sys.path and self.location is not None:
+            fixup_namespace_packages(self.location)
+            for pkg in self._get_metadata('namespace_packages.txt'):
+                if pkg in sys.modules:
+                    declare_namespace(pkg)
+
+    def egg_name(self):
+        """Return what this distribution's standard .egg filename should be"""
+        filename = "%s-%s-py%s" % (
+            to_filename(self.project_name),
+            to_filename(self.version),
+            self.py_version or PY_MAJOR,
+        )
+
+        if self.platform:
+            filename += '-' + self.platform
+        return filename
+
+    def __repr__(self):
+        if self.location:
+            return "%s (%s)" % (self, self.location)
+        else:
+            return str(self)
+
+    def __str__(self):
+        try:
+            version = getattr(self, 'version', None)
+        except ValueError:
+            version = None
+        version = version or "[unknown version]"
+        return "%s %s" % (self.project_name, version)
+
+    def __getattr__(self, attr):
+        """Delegate all unrecognized public attributes to .metadata provider"""
+        if attr.startswith('_'):
+            raise AttributeError(attr)
+        return getattr(self._provider, attr)
+
+    def __dir__(self):
+        return list(
+            set(super().__dir__())
+            | set(attr for attr in self._provider.__dir__() if not attr.startswith('_'))
+        )
+
+    @classmethod
+    def from_filename(
+        cls,
+        filename: StrPath,
+        metadata: _MetadataType = None,
+        **kw: int,  # We could set `precedence` explicitly, but keeping this as `**kw` for full backwards and subclassing compatibility
+    ):
+        return cls.from_location(
+            _normalize_cached(filename), os.path.basename(filename), metadata, **kw
+        )
+
+    def as_requirement(self):
+        """Return a ``Requirement`` that matches this distribution exactly"""
+        if isinstance(self.parsed_version, _packaging_version.Version):
+            spec = "%s==%s" % (self.project_name, self.parsed_version)
+        else:
+            spec = "%s===%s" % (self.project_name, self.parsed_version)
+
+        return Requirement.parse(spec)
+
+    def load_entry_point(self, group: str, name: str) -> _ResolvedEntryPoint:
+        """Return the `name` entry point of `group` or raise ImportError"""
+        ep = self.get_entry_info(group, name)
+        if ep is None:
+            raise ImportError("Entry point %r not found" % ((group, name),))
+        return ep.load()
+
+    @overload
+    def get_entry_map(self, group: None = None) -> dict[str, dict[str, EntryPoint]]: ...
+    @overload
+    def get_entry_map(self, group: str) -> dict[str, EntryPoint]: ...
+    def get_entry_map(self, group: str | None = None):
+        """Return the entry point map for `group`, or the full entry map"""
+        if not hasattr(self, "_ep_map"):
+            self._ep_map = EntryPoint.parse_map(
+                self._get_metadata('entry_points.txt'), self
+            )
+        if group is not None:
+            return self._ep_map.get(group, {})
+        return self._ep_map
+
+    def get_entry_info(self, group: str, name: str):
+        """Return the EntryPoint object for `group`+`name`, or ``None``"""
+        return self.get_entry_map(group).get(name)
+
+    # FIXME: 'Distribution.insert_on' is too complex (13)
+    def insert_on(  # noqa: C901
+        self,
+        path: list[str],
+        loc=None,
+        replace: bool = False,
+    ):
+        """Ensure self.location is on path
+
+        If replace=False (default):
+            - If location is already in path anywhere, do nothing.
+            - Else:
+              - If it's an egg and its parent directory is on path,
+                insert just ahead of the parent.
+              - Else: add to the end of path.
+        If replace=True:
+            - If location is already on path anywhere (not eggs)
+              or higher priority than its parent (eggs)
+              do nothing.
+            - Else:
+              - If it's an egg and its parent directory is on path,
+                insert just ahead of the parent,
+                removing any lower-priority entries.
+              - Else: add it to the front of path.
+        """
+
+        loc = loc or self.location
+        if not loc:
+            return
+
+        nloc = _normalize_cached(loc)
+        bdir = os.path.dirname(nloc)
+        npath = [(p and _normalize_cached(p) or p) for p in path]
+
+        for p, item in enumerate(npath):
+            if item == nloc:
+                if replace:
+                    break
+                else:
+                    # don't modify path (even removing duplicates) if
+                    # found and not replace
+                    return
+            elif item == bdir and self.precedence == EGG_DIST:
+                # if it's an .egg, give it precedence over its directory
+                # UNLESS it's already been added to sys.path and replace=False
+                if (not replace) and nloc in npath[p:]:
+                    return
+                if path is sys.path:
+                    self.check_version_conflict()
+                path.insert(p, loc)
+                npath.insert(p, nloc)
+                break
+        else:
+            if path is sys.path:
+                self.check_version_conflict()
+            if replace:
+                path.insert(0, loc)
+            else:
+                path.append(loc)
+            return
+
+        # p is the spot where we found or inserted loc; now remove duplicates
+        while True:
+            try:
+                np = npath.index(nloc, p + 1)
+            except ValueError:
+                break
+            else:
+                del npath[np], path[np]
+                # ha!
+                p = np
+
+        return
+
+    def check_version_conflict(self):
+        if self.key == 'setuptools':
+            # ignore the inevitable setuptools self-conflicts  :(
+            return
+
+        nsp = dict.fromkeys(self._get_metadata('namespace_packages.txt'))
+        loc = normalize_path(self.location)
+        for modname in self._get_metadata('top_level.txt'):
+            if (
+                modname not in sys.modules
+                or modname in nsp
+                or modname in _namespace_packages
+            ):
+                continue
+            if modname in ('pkg_resources', 'setuptools', 'site'):
+                continue
+            fn = getattr(sys.modules[modname], '__file__', None)
+            if fn and (
+                normalize_path(fn).startswith(loc) or fn.startswith(self.location)
+            ):
+                continue
+            issue_warning(
+                "Module %s was already imported from %s, but %s is being added"
+                " to sys.path" % (modname, fn, self.location),
+            )
+
+    def has_version(self):
+        try:
+            self.version
+        except ValueError:
+            issue_warning("Unbuilt egg for " + repr(self))
+            return False
+        except SystemError:
+            # TODO: remove this except clause when python/cpython#103632 is fixed.
+            return False
+        return True
+
+    def clone(self, **kw: str | int | IResourceProvider | None):
+        """Copy this distribution, substituting in any changed keyword args"""
+        names = 'project_name version py_version platform location precedence'
+        for attr in names.split():
+            kw.setdefault(attr, getattr(self, attr, None))
+        kw.setdefault('metadata', self._provider)
+        # Unsafely unpacking. But keeping **kw for backwards and subclassing compatibility
+        return self.__class__(**kw)  # type:ignore[arg-type]
+
+    @property
+    def extras(self):
+        return [dep for dep in self._dep_map if dep]
+
+
+class EggInfoDistribution(Distribution):
+    def _reload_version(self):
+        """
+        Packages installed by distutils (e.g. numpy or scipy),
+        which uses an old safe_version, and so
+        their version numbers can get mangled when
+        converted to filenames (e.g., 1.11.0.dev0+2329eae to
+        1.11.0.dev0_2329eae). These distributions will not be
+        parsed properly
+        downstream by Distribution and safe_version, so
+        take an extra step and try to get the version number from
+        the metadata file itself instead of the filename.
+        """
+        md_version = self._get_version()
+        if md_version:
+            self._version = md_version
+        return self
+
+
+class DistInfoDistribution(Distribution):
+    """
+    Wrap an actual or potential sys.path entry
+    w/metadata, .dist-info style.
+    """
+
+    PKG_INFO = 'METADATA'
+    EQEQ = re.compile(r"([\(,])\s*(\d.*?)\s*([,\)])")
+
+    @property
+    def _parsed_pkg_info(self):
+        """Parse and cache metadata"""
+        try:
+            return self._pkg_info
+        except AttributeError:
+            metadata = self.get_metadata(self.PKG_INFO)
+            self._pkg_info = email.parser.Parser().parsestr(metadata)
+            return self._pkg_info
+
+    @property
+    def _dep_map(self):
+        try:
+            return self.__dep_map
+        except AttributeError:
+            self.__dep_map = self._compute_dependencies()
+            return self.__dep_map
+
+    def _compute_dependencies(self) -> dict[str | None, list[Requirement]]:
+        """Recompute this distribution's dependencies."""
+        self.__dep_map: dict[str | None, list[Requirement]] = {None: []}
+
+        reqs: list[Requirement] = []
+        # Including any condition expressions
+        for req in self._parsed_pkg_info.get_all('Requires-Dist') or []:
+            reqs.extend(parse_requirements(req))
+
+        def reqs_for_extra(extra):
+            for req in reqs:
+                if not req.marker or req.marker.evaluate({'extra': extra}):
+                    yield req
+
+        common = types.MappingProxyType(dict.fromkeys(reqs_for_extra(None)))
+        self.__dep_map[None].extend(common)
+
+        for extra in self._parsed_pkg_info.get_all('Provides-Extra') or []:
+            s_extra = safe_extra(extra.strip())
+            self.__dep_map[s_extra] = [
+                r for r in reqs_for_extra(extra) if r not in common
+            ]
+
+        return self.__dep_map
+
+
+_distributionImpl = {
+    '.egg': Distribution,
+    '.egg-info': EggInfoDistribution,
+    '.dist-info': DistInfoDistribution,
+}
+
+
+def issue_warning(*args, **kw):
+    level = 1
+    g = globals()
+    try:
+        # find the first stack frame that is *not* code in
+        # the pkg_resources module, to use for the warning
+        while sys._getframe(level).f_globals is g:
+            level += 1
+    except ValueError:
+        pass
+    warnings.warn(stacklevel=level + 1, *args, **kw)
+
+
+def parse_requirements(strs: _NestedStr):
+    """
+    Yield ``Requirement`` objects for each specification in `strs`.
+
+    `strs` must be a string, or a (possibly-nested) iterable thereof.
+    """
+    return map(Requirement, join_continuation(map(drop_comment, yield_lines(strs))))
+
+
+class RequirementParseError(_packaging_requirements.InvalidRequirement):
+    "Compatibility wrapper for InvalidRequirement"
+
+
+class Requirement(_packaging_requirements.Requirement):
+    def __init__(self, requirement_string: str):
+        """DO NOT CALL THIS UNDOCUMENTED METHOD; use Requirement.parse()!"""
+        super().__init__(requirement_string)
+        self.unsafe_name = self.name
+        project_name = safe_name(self.name)
+        self.project_name, self.key = project_name, project_name.lower()
+        self.specs = [(spec.operator, spec.version) for spec in self.specifier]
+        # packaging.requirements.Requirement uses a set for its extras. We use a variable-length tuple
+        self.extras: tuple[str] = tuple(map(safe_extra, self.extras))
+        self.hashCmp = (
+            self.key,
+            self.url,
+            self.specifier,
+            frozenset(self.extras),
+            str(self.marker) if self.marker else None,
+        )
+        self.__hash = hash(self.hashCmp)
+
+    def __eq__(self, other: object):
+        return isinstance(other, Requirement) and self.hashCmp == other.hashCmp
+
+    def __ne__(self, other):
+        return not self == other
+
+    def __contains__(self, item: Distribution | str | tuple[str, ...]) -> bool:
+        if isinstance(item, Distribution):
+            if item.key != self.key:
+                return False
+
+            item = item.version
+
+        # Allow prereleases always in order to match the previous behavior of
+        # this method. In the future this should be smarter and follow PEP 440
+        # more accurately.
+        return self.specifier.contains(item, prereleases=True)
+
+    def __hash__(self):
+        return self.__hash
+
+    def __repr__(self):
+        return "Requirement.parse(%r)" % str(self)
+
+    @staticmethod
+    def parse(s: str | Iterable[str]):
+        (req,) = parse_requirements(s)
+        return req
+
+
+def _always_object(classes):
+    """
+    Ensure object appears in the mro even
+    for old-style classes.
+    """
+    if object not in classes:
+        return classes + (object,)
+    return classes
+
+
+def _find_adapter(registry: Mapping[type, _AdapterT], ob: object) -> _AdapterT:
+    """Return an adapter factory for `ob` from `registry`"""
+    types = _always_object(inspect.getmro(getattr(ob, '__class__', type(ob))))
+    for t in types:
+        if t in registry:
+            return registry[t]
+    # _find_adapter would previously return None, and immediately be called.
+    # So we're raising a TypeError to keep backward compatibility if anyone depended on that behaviour.
+    raise TypeError(f"Could not find adapter for {registry} and {ob}")
+
+
+def ensure_directory(path: StrOrBytesPath):
+    """Ensure that the parent directory of `path` exists"""
+    dirname = os.path.dirname(path)
+    os.makedirs(dirname, exist_ok=True)
+
+
+def _bypass_ensure_directory(path):
+    """Sandbox-bypassing version of ensure_directory()"""
+    if not WRITE_SUPPORT:
+        raise OSError('"os.mkdir" not supported on this platform.')
+    dirname, filename = split(path)
+    if dirname and filename and not isdir(dirname):
+        _bypass_ensure_directory(dirname)
+        try:
+            mkdir(dirname, 0o755)
+        except FileExistsError:
+            pass
+
+
+def split_sections(s: _NestedStr) -> Iterator[tuple[str | None, list[str]]]:
+    """Split a string or iterable thereof into (section, content) pairs
+
+    Each ``section`` is a stripped version of the section header ("[section]")
+    and each ``content`` is a list of stripped lines excluding blank lines and
+    comment-only lines.  If there are any such lines before the first section
+    header, they're returned in a first ``section`` of ``None``.
+    """
+    section = None
+    content = []
+    for line in yield_lines(s):
+        if line.startswith("["):
+            if line.endswith("]"):
+                if section or content:
+                    yield section, content
+                section = line[1:-1].strip()
+                content = []
+            else:
+                raise ValueError("Invalid section heading", line)
+        else:
+            content.append(line)
+
+    # wrap up last segment
+    yield section, content
+
+
+def _mkstemp(*args, **kw):
+    old_open = os.open
+    try:
+        # temporarily bypass sandboxing
+        os.open = os_open
+        return tempfile.mkstemp(*args, **kw)
+    finally:
+        # and then put it back
+        os.open = old_open
+
+
+# Silence the PEP440Warning by default, so that end users don't get hit by it
+# randomly just because they use pkg_resources. We want to append the rule
+# because we want earlier uses of filterwarnings to take precedence over this
+# one.
+warnings.filterwarnings("ignore", category=PEP440Warning, append=True)
+
+
+class PkgResourcesDeprecationWarning(Warning):
+    """
+    Base class for warning about deprecations in ``pkg_resources``
+
+    This class is not derived from ``DeprecationWarning``, and as such is
+    visible by default.
+    """
+
+
+# Ported from ``setuptools`` to avoid introducing an import inter-dependency:
+_LOCALE_ENCODING = "locale" if sys.version_info >= (3, 10) else None
+
+
+def _read_utf8_with_fallback(file: str, fallback_encoding=_LOCALE_ENCODING) -> str:
+    """See setuptools.unicode_utils._read_utf8_with_fallback"""
+    try:
+        with open(file, "r", encoding="utf-8") as f:
+            return f.read()
+    except UnicodeDecodeError:  # pragma: no cover
+        msg = f"""\
+        ********************************************************************************
+        `encoding="utf-8"` fails with {file!r}, trying `encoding={fallback_encoding!r}`.
+
+        This fallback behaviour is considered **deprecated** and future versions of
+        `setuptools/pkg_resources` may not implement it.
+
+        Please encode {file!r} with "utf-8" to ensure future builds will succeed.
+
+        If this file was produced by `setuptools` itself, cleaning up the cached files
+        and re-building/re-installing the package with a newer version of `setuptools`
+        (e.g. by updating `build-system.requires` in its `pyproject.toml`)
+        might solve the problem.
+        ********************************************************************************
+        """
+        # TODO: Add a deadline?
+        #       See comment in setuptools.unicode_utils._Utf8EncodingNeeded
+        warnings.warn(msg, PkgResourcesDeprecationWarning, stacklevel=2)
+        with open(file, "r", encoding=fallback_encoding) as f:
+            return f.read()
+
+
+# from jaraco.functools 1.3
+def _call_aside(f, *args, **kwargs):
+    f(*args, **kwargs)
+    return f
+
+
+@_call_aside
+def _initialize(g=globals()):
+    "Set up global resource manager (deliberately not state-saved)"
+    manager = ResourceManager()
+    g['_manager'] = manager
+    g.update(
+        (name, getattr(manager, name))
+        for name in dir(manager)
+        if not name.startswith('_')
+    )
+
+
+@_call_aside
+def _initialize_master_working_set():
+    """
+    Prepare the master working set and make the ``require()``
+    API available.
+
+    This function has explicit effects on the global state
+    of pkg_resources. It is intended to be invoked once at
+    the initialization of this module.
+
+    Invocation by other packages is unsupported and done
+    at their own risk.
+    """
+    working_set = _declare_state('object', 'working_set', WorkingSet._build_master())
+
+    require = working_set.require
+    iter_entry_points = working_set.iter_entry_points
+    add_activation_listener = working_set.subscribe
+    run_script = working_set.run_script
+    # backward compatibility
+    run_main = run_script
+    # Activate all distributions already on sys.path with replace=False and
+    # ensure that all distributions added to the working set in the future
+    # (e.g. by calling ``require()``) will get activated as well,
+    # with higher priority (replace=True).
+    tuple(dist.activate(replace=False) for dist in working_set)
+    add_activation_listener(
+        lambda dist: dist.activate(replace=True),
+        existing=False,
+    )
+    working_set.entries = []
+    # match order
+    list(map(working_set.add_entry, sys.path))
+    globals().update(locals())
+
+
+if TYPE_CHECKING:
+    # All of these are set by the @_call_aside methods above
+    __resource_manager = ResourceManager()  # Won't exist at runtime
+    resource_exists = __resource_manager.resource_exists
+    resource_isdir = __resource_manager.resource_isdir
+    resource_filename = __resource_manager.resource_filename
+    resource_stream = __resource_manager.resource_stream
+    resource_string = __resource_manager.resource_string
+    resource_listdir = __resource_manager.resource_listdir
+    set_extraction_path = __resource_manager.set_extraction_path
+    cleanup_resources = __resource_manager.cleanup_resources
+
+    working_set = WorkingSet()
+    require = working_set.require
+    iter_entry_points = working_set.iter_entry_points
+    add_activation_listener = working_set.subscribe
+    run_script = working_set.run_script
+    run_main = run_script
diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7ea183017e2b157040f06e10d927562cf30d245a
GIT binary patch
literal 161264
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ⅇbc;*6FNT7&6#KKkRbc&X-sxhswEZH#Q
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
K-g`X for details and usage.
+
+"""
+
+from __future__ import annotations
+
+import os
+import sys
+from typing import TYPE_CHECKING
+
+from .api import PlatformDirsABC
+from .version import __version__
+from .version import __version_tuple__ as __version_info__
+
+if TYPE_CHECKING:
+    from pathlib import Path
+    from typing import Literal
+
+
+def _set_platform_dir_class() -> type[PlatformDirsABC]:
+    if sys.platform == "win32":
+        from pip._vendor.platformdirs.windows import Windows as Result  # noqa: PLC0415
+    elif sys.platform == "darwin":
+        from pip._vendor.platformdirs.macos import MacOS as Result  # noqa: PLC0415
+    else:
+        from pip._vendor.platformdirs.unix import Unix as Result  # noqa: PLC0415
+
+    if os.getenv("ANDROID_DATA") == "/data" and os.getenv("ANDROID_ROOT") == "/system":
+        if os.getenv("SHELL") or os.getenv("PREFIX"):
+            return Result
+
+        from pip._vendor.platformdirs.android import _android_folder  # noqa: PLC0415
+
+        if _android_folder() is not None:
+            from pip._vendor.platformdirs.android import Android  # noqa: PLC0415
+
+            return Android  # return to avoid redefinition of a result
+
+    return Result
+
+
+PlatformDirs = _set_platform_dir_class()  #: Currently active platform
+AppDirs = PlatformDirs  #: Backwards compatibility with appdirs
+
+
+def user_data_dir(
+    appname: str | None = None,
+    appauthor: str | None | Literal[False] = None,
+    version: str | None = None,
+    roaming: bool = False,  # noqa: FBT001, FBT002
+    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+) -> str:
+    """
+    :param appname: See `appname `.
+    :param appauthor: See `appauthor `.
+    :param version: See `version `.
+    :param roaming: See `roaming `.
+    :param ensure_exists: See `ensure_exists `.
+    :returns: data directory tied to the user
+    """
+    return PlatformDirs(
+        appname=appname,
+        appauthor=appauthor,
+        version=version,
+        roaming=roaming,
+        ensure_exists=ensure_exists,
+    ).user_data_dir
+
+
+def site_data_dir(
+    appname: str | None = None,
+    appauthor: str | None | Literal[False] = None,
+    version: str | None = None,
+    multipath: bool = False,  # noqa: FBT001, FBT002
+    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+) -> str:
+    """
+    :param appname: See `appname `.
+    :param appauthor: See `appauthor `.
+    :param version: See `version `.
+    :param multipath: See `roaming `.
+    :param ensure_exists: See `ensure_exists `.
+    :returns: data directory shared by users
+    """
+    return PlatformDirs(
+        appname=appname,
+        appauthor=appauthor,
+        version=version,
+        multipath=multipath,
+        ensure_exists=ensure_exists,
+    ).site_data_dir
+
+
+def user_config_dir(
+    appname: str | None = None,
+    appauthor: str | None | Literal[False] = None,
+    version: str | None = None,
+    roaming: bool = False,  # noqa: FBT001, FBT002
+    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+) -> str:
+    """
+    :param appname: See `appname `.
+    :param appauthor: See `appauthor `.
+    :param version: See `version `.
+    :param roaming: See `roaming `.
+    :param ensure_exists: See `ensure_exists `.
+    :returns: config directory tied to the user
+    """
+    return PlatformDirs(
+        appname=appname,
+        appauthor=appauthor,
+        version=version,
+        roaming=roaming,
+        ensure_exists=ensure_exists,
+    ).user_config_dir
+
+
+def site_config_dir(
+    appname: str | None = None,
+    appauthor: str | None | Literal[False] = None,
+    version: str | None = None,
+    multipath: bool = False,  # noqa: FBT001, FBT002
+    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+) -> str:
+    """
+    :param appname: See `appname `.
+    :param appauthor: See `appauthor `.
+    :param version: See `version `.
+    :param multipath: See `roaming `.
+    :param ensure_exists: See `ensure_exists `.
+    :returns: config directory shared by the users
+    """
+    return PlatformDirs(
+        appname=appname,
+        appauthor=appauthor,
+        version=version,
+        multipath=multipath,
+        ensure_exists=ensure_exists,
+    ).site_config_dir
+
+
+def user_cache_dir(
+    appname: str | None = None,
+    appauthor: str | None | Literal[False] = None,
+    version: str | None = None,
+    opinion: bool = True,  # noqa: FBT001, FBT002
+    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+) -> str:
+    """
+    :param appname: See `appname `.
+    :param appauthor: See `appauthor `.
+    :param version: See `version `.
+    :param opinion: See `roaming `.
+    :param ensure_exists: See `ensure_exists `.
+    :returns: cache directory tied to the user
+    """
+    return PlatformDirs(
+        appname=appname,
+        appauthor=appauthor,
+        version=version,
+        opinion=opinion,
+        ensure_exists=ensure_exists,
+    ).user_cache_dir
+
+
+def site_cache_dir(
+    appname: str | None = None,
+    appauthor: str | None | Literal[False] = None,
+    version: str | None = None,
+    opinion: bool = True,  # noqa: FBT001, FBT002
+    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+) -> str:
+    """
+    :param appname: See `appname `.
+    :param appauthor: See `appauthor `.
+    :param version: See `version `.
+    :param opinion: See `opinion `.
+    :param ensure_exists: See `ensure_exists `.
+    :returns: cache directory tied to the user
+    """
+    return PlatformDirs(
+        appname=appname,
+        appauthor=appauthor,
+        version=version,
+        opinion=opinion,
+        ensure_exists=ensure_exists,
+    ).site_cache_dir
+
+
+def user_state_dir(
+    appname: str | None = None,
+    appauthor: str | None | Literal[False] = None,
+    version: str | None = None,
+    roaming: bool = False,  # noqa: FBT001, FBT002
+    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+) -> str:
+    """
+    :param appname: See `appname `.
+    :param appauthor: See `appauthor `.
+    :param version: See `version `.
+    :param roaming: See `roaming `.
+    :param ensure_exists: See `ensure_exists `.
+    :returns: state directory tied to the user
+    """
+    return PlatformDirs(
+        appname=appname,
+        appauthor=appauthor,
+        version=version,
+        roaming=roaming,
+        ensure_exists=ensure_exists,
+    ).user_state_dir
+
+
+def user_log_dir(
+    appname: str | None = None,
+    appauthor: str | None | Literal[False] = None,
+    version: str | None = None,
+    opinion: bool = True,  # noqa: FBT001, FBT002
+    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+) -> str:
+    """
+    :param appname: See `appname `.
+    :param appauthor: See `appauthor `.
+    :param version: See `version `.
+    :param opinion: See `roaming `.
+    :param ensure_exists: See `ensure_exists `.
+    :returns: log directory tied to the user
+    """
+    return PlatformDirs(
+        appname=appname,
+        appauthor=appauthor,
+        version=version,
+        opinion=opinion,
+        ensure_exists=ensure_exists,
+    ).user_log_dir
+
+
+def user_documents_dir() -> str:
+    """:returns: documents directory tied to the user"""
+    return PlatformDirs().user_documents_dir
+
+
+def user_downloads_dir() -> str:
+    """:returns: downloads directory tied to the user"""
+    return PlatformDirs().user_downloads_dir
+
+
+def user_pictures_dir() -> str:
+    """:returns: pictures directory tied to the user"""
+    return PlatformDirs().user_pictures_dir
+
+
+def user_videos_dir() -> str:
+    """:returns: videos directory tied to the user"""
+    return PlatformDirs().user_videos_dir
+
+
+def user_music_dir() -> str:
+    """:returns: music directory tied to the user"""
+    return PlatformDirs().user_music_dir
+
+
+def user_desktop_dir() -> str:
+    """:returns: desktop directory tied to the user"""
+    return PlatformDirs().user_desktop_dir
+
+
+def user_runtime_dir(
+    appname: str | None = None,
+    appauthor: str | None | Literal[False] = None,
+    version: str | None = None,
+    opinion: bool = True,  # noqa: FBT001, FBT002
+    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+) -> str:
+    """
+    :param appname: See `appname `.
+    :param appauthor: See `appauthor `.
+    :param version: See `version `.
+    :param opinion: See `opinion `.
+    :param ensure_exists: See `ensure_exists `.
+    :returns: runtime directory tied to the user
+    """
+    return PlatformDirs(
+        appname=appname,
+        appauthor=appauthor,
+        version=version,
+        opinion=opinion,
+        ensure_exists=ensure_exists,
+    ).user_runtime_dir
+
+
+def site_runtime_dir(
+    appname: str | None = None,
+    appauthor: str | None | Literal[False] = None,
+    version: str | None = None,
+    opinion: bool = True,  # noqa: FBT001, FBT002
+    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+) -> str:
+    """
+    :param appname: See `appname `.
+    :param appauthor: See `appauthor `.
+    :param version: See `version `.
+    :param opinion: See `opinion `.
+    :param ensure_exists: See `ensure_exists `.
+    :returns: runtime directory shared by users
+    """
+    return PlatformDirs(
+        appname=appname,
+        appauthor=appauthor,
+        version=version,
+        opinion=opinion,
+        ensure_exists=ensure_exists,
+    ).site_runtime_dir
+
+
+def user_data_path(
+    appname: str | None = None,
+    appauthor: str | None | Literal[False] = None,
+    version: str | None = None,
+    roaming: bool = False,  # noqa: FBT001, FBT002
+    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+) -> Path:
+    """
+    :param appname: See `appname `.
+    :param appauthor: See `appauthor `.
+    :param version: See `version `.
+    :param roaming: See `roaming `.
+    :param ensure_exists: See `ensure_exists `.
+    :returns: data path tied to the user
+    """
+    return PlatformDirs(
+        appname=appname,
+        appauthor=appauthor,
+        version=version,
+        roaming=roaming,
+        ensure_exists=ensure_exists,
+    ).user_data_path
+
+
+def site_data_path(
+    appname: str | None = None,
+    appauthor: str | None | Literal[False] = None,
+    version: str | None = None,
+    multipath: bool = False,  # noqa: FBT001, FBT002
+    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+) -> Path:
+    """
+    :param appname: See `appname `.
+    :param appauthor: See `appauthor `.
+    :param version: See `version `.
+    :param multipath: See `multipath `.
+    :param ensure_exists: See `ensure_exists `.
+    :returns: data path shared by users
+    """
+    return PlatformDirs(
+        appname=appname,
+        appauthor=appauthor,
+        version=version,
+        multipath=multipath,
+        ensure_exists=ensure_exists,
+    ).site_data_path
+
+
+def user_config_path(
+    appname: str | None = None,
+    appauthor: str | None | Literal[False] = None,
+    version: str | None = None,
+    roaming: bool = False,  # noqa: FBT001, FBT002
+    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+) -> Path:
+    """
+    :param appname: See `appname `.
+    :param appauthor: See `appauthor `.
+    :param version: See `version `.
+    :param roaming: See `roaming `.
+    :param ensure_exists: See `ensure_exists `.
+    :returns: config path tied to the user
+    """
+    return PlatformDirs(
+        appname=appname,
+        appauthor=appauthor,
+        version=version,
+        roaming=roaming,
+        ensure_exists=ensure_exists,
+    ).user_config_path
+
+
+def site_config_path(
+    appname: str | None = None,
+    appauthor: str | None | Literal[False] = None,
+    version: str | None = None,
+    multipath: bool = False,  # noqa: FBT001, FBT002
+    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+) -> Path:
+    """
+    :param appname: See `appname `.
+    :param appauthor: See `appauthor `.
+    :param version: See `version `.
+    :param multipath: See `roaming `.
+    :param ensure_exists: See `ensure_exists `.
+    :returns: config path shared by the users
+    """
+    return PlatformDirs(
+        appname=appname,
+        appauthor=appauthor,
+        version=version,
+        multipath=multipath,
+        ensure_exists=ensure_exists,
+    ).site_config_path
+
+
+def site_cache_path(
+    appname: str | None = None,
+    appauthor: str | None | Literal[False] = None,
+    version: str | None = None,
+    opinion: bool = True,  # noqa: FBT001, FBT002
+    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+) -> Path:
+    """
+    :param appname: See `appname `.
+    :param appauthor: See `appauthor `.
+    :param version: See `version `.
+    :param opinion: See `opinion `.
+    :param ensure_exists: See `ensure_exists `.
+    :returns: cache directory tied to the user
+    """
+    return PlatformDirs(
+        appname=appname,
+        appauthor=appauthor,
+        version=version,
+        opinion=opinion,
+        ensure_exists=ensure_exists,
+    ).site_cache_path
+
+
+def user_cache_path(
+    appname: str | None = None,
+    appauthor: str | None | Literal[False] = None,
+    version: str | None = None,
+    opinion: bool = True,  # noqa: FBT001, FBT002
+    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+) -> Path:
+    """
+    :param appname: See `appname `.
+    :param appauthor: See `appauthor `.
+    :param version: See `version `.
+    :param opinion: See `roaming `.
+    :param ensure_exists: See `ensure_exists `.
+    :returns: cache path tied to the user
+    """
+    return PlatformDirs(
+        appname=appname,
+        appauthor=appauthor,
+        version=version,
+        opinion=opinion,
+        ensure_exists=ensure_exists,
+    ).user_cache_path
+
+
+def user_state_path(
+    appname: str | None = None,
+    appauthor: str | None | Literal[False] = None,
+    version: str | None = None,
+    roaming: bool = False,  # noqa: FBT001, FBT002
+    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+) -> Path:
+    """
+    :param appname: See `appname `.
+    :param appauthor: See `appauthor `.
+    :param version: See `version `.
+    :param roaming: See `roaming `.
+    :param ensure_exists: See `ensure_exists `.
+    :returns: state path tied to the user
+    """
+    return PlatformDirs(
+        appname=appname,
+        appauthor=appauthor,
+        version=version,
+        roaming=roaming,
+        ensure_exists=ensure_exists,
+    ).user_state_path
+
+
+def user_log_path(
+    appname: str | None = None,
+    appauthor: str | None | Literal[False] = None,
+    version: str | None = None,
+    opinion: bool = True,  # noqa: FBT001, FBT002
+    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+) -> Path:
+    """
+    :param appname: See `appname `.
+    :param appauthor: See `appauthor `.
+    :param version: See `version `.
+    :param opinion: See `roaming `.
+    :param ensure_exists: See `ensure_exists `.
+    :returns: log path tied to the user
+    """
+    return PlatformDirs(
+        appname=appname,
+        appauthor=appauthor,
+        version=version,
+        opinion=opinion,
+        ensure_exists=ensure_exists,
+    ).user_log_path
+
+
+def user_documents_path() -> Path:
+    """:returns: documents a path tied to the user"""
+    return PlatformDirs().user_documents_path
+
+
+def user_downloads_path() -> Path:
+    """:returns: downloads path tied to the user"""
+    return PlatformDirs().user_downloads_path
+
+
+def user_pictures_path() -> Path:
+    """:returns: pictures path tied to the user"""
+    return PlatformDirs().user_pictures_path
+
+
+def user_videos_path() -> Path:
+    """:returns: videos path tied to the user"""
+    return PlatformDirs().user_videos_path
+
+
+def user_music_path() -> Path:
+    """:returns: music path tied to the user"""
+    return PlatformDirs().user_music_path
+
+
+def user_desktop_path() -> Path:
+    """:returns: desktop path tied to the user"""
+    return PlatformDirs().user_desktop_path
+
+
+def user_runtime_path(
+    appname: str | None = None,
+    appauthor: str | None | Literal[False] = None,
+    version: str | None = None,
+    opinion: bool = True,  # noqa: FBT001, FBT002
+    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+) -> Path:
+    """
+    :param appname: See `appname `.
+    :param appauthor: See `appauthor `.
+    :param version: See `version `.
+    :param opinion: See `opinion `.
+    :param ensure_exists: See `ensure_exists `.
+    :returns: runtime path tied to the user
+    """
+    return PlatformDirs(
+        appname=appname,
+        appauthor=appauthor,
+        version=version,
+        opinion=opinion,
+        ensure_exists=ensure_exists,
+    ).user_runtime_path
+
+
+def site_runtime_path(
+    appname: str | None = None,
+    appauthor: str | None | Literal[False] = None,
+    version: str | None = None,
+    opinion: bool = True,  # noqa: FBT001, FBT002
+    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+) -> Path:
+    """
+    :param appname: See `appname `.
+    :param appauthor: See `appauthor `.
+    :param version: See `version `.
+    :param opinion: See `opinion `.
+    :param ensure_exists: See `ensure_exists `.
+    :returns: runtime path shared by users
+    """
+    return PlatformDirs(
+        appname=appname,
+        appauthor=appauthor,
+        version=version,
+        opinion=opinion,
+        ensure_exists=ensure_exists,
+    ).site_runtime_path
+
+
+__all__ = [
+    "AppDirs",
+    "PlatformDirs",
+    "PlatformDirsABC",
+    "__version__",
+    "__version_info__",
+    "site_cache_dir",
+    "site_cache_path",
+    "site_config_dir",
+    "site_config_path",
+    "site_data_dir",
+    "site_data_path",
+    "site_runtime_dir",
+    "site_runtime_path",
+    "user_cache_dir",
+    "user_cache_path",
+    "user_config_dir",
+    "user_config_path",
+    "user_data_dir",
+    "user_data_path",
+    "user_desktop_dir",
+    "user_desktop_path",
+    "user_documents_dir",
+    "user_documents_path",
+    "user_downloads_dir",
+    "user_downloads_path",
+    "user_log_dir",
+    "user_log_path",
+    "user_music_dir",
+    "user_music_path",
+    "user_pictures_dir",
+    "user_pictures_path",
+    "user_runtime_dir",
+    "user_runtime_path",
+    "user_state_dir",
+    "user_state_path",
+    "user_videos_dir",
+    "user_videos_path",
+]
diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/__main__.py b/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/__main__.py
new file mode 100644
index 0000000..fa8a677
--- /dev/null
+++ b/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/__main__.py
@@ -0,0 +1,55 @@
+"""Main entry point."""
+
+from __future__ import annotations
+
+from pip._vendor.platformdirs import PlatformDirs, __version__
+
+PROPS = (
+    "user_data_dir",
+    "user_config_dir",
+    "user_cache_dir",
+    "user_state_dir",
+    "user_log_dir",
+    "user_documents_dir",
+    "user_downloads_dir",
+    "user_pictures_dir",
+    "user_videos_dir",
+    "user_music_dir",
+    "user_runtime_dir",
+    "site_data_dir",
+    "site_config_dir",
+    "site_cache_dir",
+    "site_runtime_dir",
+)
+
+
+def main() -> None:
+    """Run the main entry point."""
+    app_name = "MyApp"
+    app_author = "MyCompany"
+
+    print(f"-- platformdirs {__version__} --")  # noqa: T201
+
+    print("-- app dirs (with optional 'version')")  # noqa: T201
+    dirs = PlatformDirs(app_name, app_author, version="1.0")
+    for prop in PROPS:
+        print(f"{prop}: {getattr(dirs, prop)}")  # noqa: T201
+
+    print("\n-- app dirs (without optional 'version')")  # noqa: T201
+    dirs = PlatformDirs(app_name, app_author)
+    for prop in PROPS:
+        print(f"{prop}: {getattr(dirs, prop)}")  # noqa: T201
+
+    print("\n-- app dirs (without optional 'appauthor')")  # noqa: T201
+    dirs = PlatformDirs(app_name)
+    for prop in PROPS:
+        print(f"{prop}: {getattr(dirs, prop)}")  # noqa: T201
+
+    print("\n-- app dirs (with disabled 'appauthor')")  # noqa: T201
+    dirs = PlatformDirs(app_name, appauthor=False)
+    for prop in PROPS:
+        print(f"{prop}: {getattr(dirs, prop)}")  # noqa: T201
+
+
+if __name__ == "__main__":
+    main()
diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9e86b6ffd6feb687ab79e414004f821a0a8f96e5
GIT binary patch
literal 19832
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

literal 0
HcmV?d00001

diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/android.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/android.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..970ff1b7ba0110a7abd679b15f27a1b57ece1299
GIT binary patch
literal 10700
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

literal 0
HcmV?d00001

diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/api.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/api.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..3a73d19663e8a42708263944e83f9d6c8414862c
GIT binary patch
literal 12914
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
H&N}=L55>>1

literal 0
HcmV?d00001

diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/unix.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/unix.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..51bd7d3c79ed6ecac2b78baec181cd72375705f8
GIT binary patch
literal 15040
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
WTfsKp+sXLr?|D7-o^J=~$o~ZhwetM{

literal 0
HcmV?d00001

diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/version.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/version.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..e224105876f58cfaf3890cf92e87491dbc76a311
GIT binary patch
literal 600
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.
+
+    Makes use of the `appname `, `version
+    `, `ensure_exists `.
+
+    """
+
+    @property
+    def user_data_dir(self) -> str:
+        """:return: data directory tied to the user, e.g. ``/data/user///files/``"""
+        return self._append_app_name_and_version(cast(str, _android_folder()), "files")
+
+    @property
+    def site_data_dir(self) -> str:
+        """:return: data directory shared by users, same as `user_data_dir`"""
+        return self.user_data_dir
+
+    @property
+    def user_config_dir(self) -> str:
+        """
+        :return: config directory tied to the user, e.g. \
+        ``/data/user///shared_prefs/``
+        """
+        return self._append_app_name_and_version(cast(str, _android_folder()), "shared_prefs")
+
+    @property
+    def site_config_dir(self) -> str:
+        """:return: config directory shared by the users, same as `user_config_dir`"""
+        return self.user_config_dir
+
+    @property
+    def user_cache_dir(self) -> str:
+        """:return: cache directory tied to the user, e.g.,``/data/user///cache/``"""
+        return self._append_app_name_and_version(cast(str, _android_folder()), "cache")
+
+    @property
+    def site_cache_dir(self) -> str:
+        """:return: cache directory shared by users, same as `user_cache_dir`"""
+        return self.user_cache_dir
+
+    @property
+    def user_state_dir(self) -> str:
+        """:return: state directory tied to the user, same as `user_data_dir`"""
+        return self.user_data_dir
+
+    @property
+    def user_log_dir(self) -> str:
+        """
+        :return: log directory tied to the user, same as `user_cache_dir` if not opinionated else ``log`` in it,
+          e.g. ``/data/user///cache//log``
+        """
+        path = self.user_cache_dir
+        if self.opinion:
+            path = os.path.join(path, "log")  # noqa: PTH118
+        return path
+
+    @property
+    def user_documents_dir(self) -> str:
+        """:return: documents directory tied to the user e.g. ``/storage/emulated/0/Documents``"""
+        return _android_documents_folder()
+
+    @property
+    def user_downloads_dir(self) -> str:
+        """:return: downloads directory tied to the user e.g. ``/storage/emulated/0/Downloads``"""
+        return _android_downloads_folder()
+
+    @property
+    def user_pictures_dir(self) -> str:
+        """:return: pictures directory tied to the user e.g. ``/storage/emulated/0/Pictures``"""
+        return _android_pictures_folder()
+
+    @property
+    def user_videos_dir(self) -> str:
+        """:return: videos directory tied to the user e.g. ``/storage/emulated/0/DCIM/Camera``"""
+        return _android_videos_folder()
+
+    @property
+    def user_music_dir(self) -> str:
+        """:return: music directory tied to the user e.g. ``/storage/emulated/0/Music``"""
+        return _android_music_folder()
+
+    @property
+    def user_desktop_dir(self) -> str:
+        """:return: desktop directory tied to the user e.g. ``/storage/emulated/0/Desktop``"""
+        return "/storage/emulated/0/Desktop"
+
+    @property
+    def user_runtime_dir(self) -> str:
+        """
+        :return: runtime directory tied to the user, same as `user_cache_dir` if not opinionated else ``tmp`` in it,
+          e.g. ``/data/user///cache//tmp``
+        """
+        path = self.user_cache_dir
+        if self.opinion:
+            path = os.path.join(path, "tmp")  # noqa: PTH118
+        return path
+
+    @property
+    def site_runtime_dir(self) -> str:
+        """:return: runtime directory shared by users, same as `user_runtime_dir`"""
+        return self.user_runtime_dir
+
+
+@lru_cache(maxsize=1)
+def _android_folder() -> str | None:  # noqa: C901, PLR0912
+    """:return: base folder for the Android OS or None if it cannot be found"""
+    result: str | None = None
+    # type checker isn't happy with our "import android", just don't do this when type checking see
+    # https://stackoverflow.com/a/61394121
+    if not TYPE_CHECKING:
+        try:
+            # First try to get a path to android app using python4android (if available)...
+            from android import mActivity  # noqa: PLC0415
+
+            context = cast("android.content.Context", mActivity.getApplicationContext())  # noqa: F821
+            result = context.getFilesDir().getParentFile().getAbsolutePath()
+        except Exception:  # noqa: BLE001
+            result = None
+    if result is None:
+        try:
+            # ...and fall back to using plain pyjnius, if python4android isn't available or doesn't deliver any useful
+            # result...
+            from jnius import autoclass  # noqa: PLC0415
+
+            context = autoclass("android.content.Context")
+            result = context.getFilesDir().getParentFile().getAbsolutePath()
+        except Exception:  # noqa: BLE001
+            result = None
+    if result is None:
+        # and if that fails, too, find an android folder looking at path on the sys.path
+        # warning: only works for apps installed under /data, not adopted storage etc.
+        pattern = re.compile(r"/data/(data|user/\d+)/(.+)/files")
+        for path in sys.path:
+            if pattern.match(path):
+                result = path.split("/files")[0]
+                break
+        else:
+            result = None
+    if result is None:
+        # one last try: find an android folder looking at path on the sys.path taking adopted storage paths into
+        # account
+        pattern = re.compile(r"/mnt/expand/[a-fA-F0-9-]{36}/(data|user/\d+)/(.+)/files")
+        for path in sys.path:
+            if pattern.match(path):
+                result = path.split("/files")[0]
+                break
+        else:
+            result = None
+    return result
+
+
+@lru_cache(maxsize=1)
+def _android_documents_folder() -> str:
+    """:return: documents folder for the Android OS"""
+    # Get directories with pyjnius
+    try:
+        from jnius import autoclass  # noqa: PLC0415
+
+        context = autoclass("android.content.Context")
+        environment = autoclass("android.os.Environment")
+        documents_dir: str = context.getExternalFilesDir(environment.DIRECTORY_DOCUMENTS).getAbsolutePath()
+    except Exception:  # noqa: BLE001
+        documents_dir = "/storage/emulated/0/Documents"
+
+    return documents_dir
+
+
+@lru_cache(maxsize=1)
+def _android_downloads_folder() -> str:
+    """:return: downloads folder for the Android OS"""
+    # Get directories with pyjnius
+    try:
+        from jnius import autoclass  # noqa: PLC0415
+
+        context = autoclass("android.content.Context")
+        environment = autoclass("android.os.Environment")
+        downloads_dir: str = context.getExternalFilesDir(environment.DIRECTORY_DOWNLOADS).getAbsolutePath()
+    except Exception:  # noqa: BLE001
+        downloads_dir = "/storage/emulated/0/Downloads"
+
+    return downloads_dir
+
+
+@lru_cache(maxsize=1)
+def _android_pictures_folder() -> str:
+    """:return: pictures folder for the Android OS"""
+    # Get directories with pyjnius
+    try:
+        from jnius import autoclass  # noqa: PLC0415
+
+        context = autoclass("android.content.Context")
+        environment = autoclass("android.os.Environment")
+        pictures_dir: str = context.getExternalFilesDir(environment.DIRECTORY_PICTURES).getAbsolutePath()
+    except Exception:  # noqa: BLE001
+        pictures_dir = "/storage/emulated/0/Pictures"
+
+    return pictures_dir
+
+
+@lru_cache(maxsize=1)
+def _android_videos_folder() -> str:
+    """:return: videos folder for the Android OS"""
+    # Get directories with pyjnius
+    try:
+        from jnius import autoclass  # noqa: PLC0415
+
+        context = autoclass("android.content.Context")
+        environment = autoclass("android.os.Environment")
+        videos_dir: str = context.getExternalFilesDir(environment.DIRECTORY_DCIM).getAbsolutePath()
+    except Exception:  # noqa: BLE001
+        videos_dir = "/storage/emulated/0/DCIM/Camera"
+
+    return videos_dir
+
+
+@lru_cache(maxsize=1)
+def _android_music_folder() -> str:
+    """:return: music folder for the Android OS"""
+    # Get directories with pyjnius
+    try:
+        from jnius import autoclass  # noqa: PLC0415
+
+        context = autoclass("android.content.Context")
+        environment = autoclass("android.os.Environment")
+        music_dir: str = context.getExternalFilesDir(environment.DIRECTORY_MUSIC).getAbsolutePath()
+    except Exception:  # noqa: BLE001
+        music_dir = "/storage/emulated/0/Music"
+
+    return music_dir
+
+
+__all__ = [
+    "Android",
+]
diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/api.py b/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/api.py
new file mode 100644
index 0000000..c50caa6
--- /dev/null
+++ b/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/api.py
@@ -0,0 +1,292 @@
+"""Base API."""
+
+from __future__ import annotations
+
+import os
+from abc import ABC, abstractmethod
+from pathlib import Path
+from typing import TYPE_CHECKING
+
+if TYPE_CHECKING:
+    from typing import Iterator, Literal
+
+
+class PlatformDirsABC(ABC):  # noqa: PLR0904
+    """Abstract base class for platform directories."""
+
+    def __init__(  # noqa: PLR0913, PLR0917
+        self,
+        appname: str | None = None,
+        appauthor: str | None | Literal[False] = None,
+        version: str | None = None,
+        roaming: bool = False,  # noqa: FBT001, FBT002
+        multipath: bool = False,  # noqa: FBT001, FBT002
+        opinion: bool = True,  # noqa: FBT001, FBT002
+        ensure_exists: bool = False,  # noqa: FBT001, FBT002
+    ) -> None:
+        """
+        Create a new platform directory.
+
+        :param appname: See `appname`.
+        :param appauthor: See `appauthor`.
+        :param version: See `version`.
+        :param roaming: See `roaming`.
+        :param multipath: See `multipath`.
+        :param opinion: See `opinion`.
+        :param ensure_exists: See `ensure_exists`.
+
+        """
+        self.appname = appname  #: The name of application.
+        self.appauthor = appauthor
+        """
+        The name of the app author or distributing body for this application.
+
+        Typically, it is the owning company name. Defaults to `appname`. You may pass ``False`` to disable it.
+
+        """
+        self.version = version
+        """
+        An optional version path element to append to the path.
+
+        You might want to use this if you want multiple versions of your app to be able to run independently. If used,
+        this would typically be ``.``.
+
+        """
+        self.roaming = roaming
+        """
+        Whether to use the roaming appdata directory on Windows.
+
+        That means that for users on a Windows network setup for roaming profiles, this user data will be synced on
+        login (see
+        `here `_).
+
+        """
+        self.multipath = multipath
+        """
+        An optional parameter which indicates that the entire list of data dirs should be returned.
+
+        By default, the first item would only be returned.
+
+        """
+        self.opinion = opinion  #: A flag to indicating to use opinionated values.
+        self.ensure_exists = ensure_exists
+        """
+        Optionally create the directory (and any missing parents) upon access if it does not exist.
+
+        By default, no directories are created.
+
+        """
+
+    def _append_app_name_and_version(self, *base: str) -> str:
+        params = list(base[1:])
+        if self.appname:
+            params.append(self.appname)
+            if self.version:
+                params.append(self.version)
+        path = os.path.join(base[0], *params)  # noqa: PTH118
+        self._optionally_create_directory(path)
+        return path
+
+    def _optionally_create_directory(self, path: str) -> None:
+        if self.ensure_exists:
+            Path(path).mkdir(parents=True, exist_ok=True)
+
+    @property
+    @abstractmethod
+    def user_data_dir(self) -> str:
+        """:return: data directory tied to the user"""
+
+    @property
+    @abstractmethod
+    def site_data_dir(self) -> str:
+        """:return: data directory shared by users"""
+
+    @property
+    @abstractmethod
+    def user_config_dir(self) -> str:
+        """:return: config directory tied to the user"""
+
+    @property
+    @abstractmethod
+    def site_config_dir(self) -> str:
+        """:return: config directory shared by the users"""
+
+    @property
+    @abstractmethod
+    def user_cache_dir(self) -> str:
+        """:return: cache directory tied to the user"""
+
+    @property
+    @abstractmethod
+    def site_cache_dir(self) -> str:
+        """:return: cache directory shared by users"""
+
+    @property
+    @abstractmethod
+    def user_state_dir(self) -> str:
+        """:return: state directory tied to the user"""
+
+    @property
+    @abstractmethod
+    def user_log_dir(self) -> str:
+        """:return: log directory tied to the user"""
+
+    @property
+    @abstractmethod
+    def user_documents_dir(self) -> str:
+        """:return: documents directory tied to the user"""
+
+    @property
+    @abstractmethod
+    def user_downloads_dir(self) -> str:
+        """:return: downloads directory tied to the user"""
+
+    @property
+    @abstractmethod
+    def user_pictures_dir(self) -> str:
+        """:return: pictures directory tied to the user"""
+
+    @property
+    @abstractmethod
+    def user_videos_dir(self) -> str:
+        """:return: videos directory tied to the user"""
+
+    @property
+    @abstractmethod
+    def user_music_dir(self) -> str:
+        """:return: music directory tied to the user"""
+
+    @property
+    @abstractmethod
+    def user_desktop_dir(self) -> str:
+        """:return: desktop directory tied to the user"""
+
+    @property
+    @abstractmethod
+    def user_runtime_dir(self) -> str:
+        """:return: runtime directory tied to the user"""
+
+    @property
+    @abstractmethod
+    def site_runtime_dir(self) -> str:
+        """:return: runtime directory shared by users"""
+
+    @property
+    def user_data_path(self) -> Path:
+        """:return: data path tied to the user"""
+        return Path(self.user_data_dir)
+
+    @property
+    def site_data_path(self) -> Path:
+        """:return: data path shared by users"""
+        return Path(self.site_data_dir)
+
+    @property
+    def user_config_path(self) -> Path:
+        """:return: config path tied to the user"""
+        return Path(self.user_config_dir)
+
+    @property
+    def site_config_path(self) -> Path:
+        """:return: config path shared by the users"""
+        return Path(self.site_config_dir)
+
+    @property
+    def user_cache_path(self) -> Path:
+        """:return: cache path tied to the user"""
+        return Path(self.user_cache_dir)
+
+    @property
+    def site_cache_path(self) -> Path:
+        """:return: cache path shared by users"""
+        return Path(self.site_cache_dir)
+
+    @property
+    def user_state_path(self) -> Path:
+        """:return: state path tied to the user"""
+        return Path(self.user_state_dir)
+
+    @property
+    def user_log_path(self) -> Path:
+        """:return: log path tied to the user"""
+        return Path(self.user_log_dir)
+
+    @property
+    def user_documents_path(self) -> Path:
+        """:return: documents a path tied to the user"""
+        return Path(self.user_documents_dir)
+
+    @property
+    def user_downloads_path(self) -> Path:
+        """:return: downloads path tied to the user"""
+        return Path(self.user_downloads_dir)
+
+    @property
+    def user_pictures_path(self) -> Path:
+        """:return: pictures path tied to the user"""
+        return Path(self.user_pictures_dir)
+
+    @property
+    def user_videos_path(self) -> Path:
+        """:return: videos path tied to the user"""
+        return Path(self.user_videos_dir)
+
+    @property
+    def user_music_path(self) -> Path:
+        """:return: music path tied to the user"""
+        return Path(self.user_music_dir)
+
+    @property
+    def user_desktop_path(self) -> Path:
+        """:return: desktop path tied to the user"""
+        return Path(self.user_desktop_dir)
+
+    @property
+    def user_runtime_path(self) -> Path:
+        """:return: runtime path tied to the user"""
+        return Path(self.user_runtime_dir)
+
+    @property
+    def site_runtime_path(self) -> Path:
+        """:return: runtime path shared by users"""
+        return Path(self.site_runtime_dir)
+
+    def iter_config_dirs(self) -> Iterator[str]:
+        """:yield: all user and site configuration directories."""
+        yield self.user_config_dir
+        yield self.site_config_dir
+
+    def iter_data_dirs(self) -> Iterator[str]:
+        """:yield: all user and site data directories."""
+        yield self.user_data_dir
+        yield self.site_data_dir
+
+    def iter_cache_dirs(self) -> Iterator[str]:
+        """:yield: all user and site cache directories."""
+        yield self.user_cache_dir
+        yield self.site_cache_dir
+
+    def iter_runtime_dirs(self) -> Iterator[str]:
+        """:yield: all user and site runtime directories."""
+        yield self.user_runtime_dir
+        yield self.site_runtime_dir
+
+    def iter_config_paths(self) -> Iterator[Path]:
+        """:yield: all user and site configuration paths."""
+        for path in self.iter_config_dirs():
+            yield Path(path)
+
+    def iter_data_paths(self) -> Iterator[Path]:
+        """:yield: all user and site data paths."""
+        for path in self.iter_data_dirs():
+            yield Path(path)
+
+    def iter_cache_paths(self) -> Iterator[Path]:
+        """:yield: all user and site cache paths."""
+        for path in self.iter_cache_dirs():
+            yield Path(path)
+
+    def iter_runtime_paths(self) -> Iterator[Path]:
+        """:yield: all user and site runtime paths."""
+        for path in self.iter_runtime_dirs():
+            yield Path(path)
diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/macos.py b/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/macos.py
new file mode 100644
index 0000000..eb1ba5d
--- /dev/null
+++ b/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/macos.py
@@ -0,0 +1,130 @@
+"""macOS."""
+
+from __future__ import annotations
+
+import os.path
+import sys
+
+from .api import PlatformDirsABC
+
+
+class MacOS(PlatformDirsABC):
+    """
+    Platform directories for the macOS operating system.
+
+    Follows the guidance from
+    `Apple documentation `_.
+    Makes use of the `appname `,
+    `version `,
+    `ensure_exists `.
+
+    """
+
+    @property
+    def user_data_dir(self) -> str:
+        """:return: data directory tied to the user, e.g. ``~/Library/Application Support/$appname/$version``"""
+        return self._append_app_name_and_version(os.path.expanduser("~/Library/Application Support"))  # noqa: PTH111
+
+    @property
+    def site_data_dir(self) -> str:
+        """
+        :return: data directory shared by users, e.g. ``/Library/Application Support/$appname/$version``.
+          If we're using a Python binary managed by `Homebrew `_, the directory
+          will be under the Homebrew prefix, e.g. ``/opt/homebrew/share/$appname/$version``.
+          If `multipath ` is enabled, and we're in Homebrew,
+          the response is a multi-path string separated by ":", e.g.
+          ``/opt/homebrew/share/$appname/$version:/Library/Application Support/$appname/$version``
+        """
+        is_homebrew = sys.prefix.startswith("/opt/homebrew")
+        path_list = [self._append_app_name_and_version("/opt/homebrew/share")] if is_homebrew else []
+        path_list.append(self._append_app_name_and_version("/Library/Application Support"))
+        if self.multipath:
+            return os.pathsep.join(path_list)
+        return path_list[0]
+
+    @property
+    def user_config_dir(self) -> str:
+        """:return: config directory tied to the user, same as `user_data_dir`"""
+        return self.user_data_dir
+
+    @property
+    def site_config_dir(self) -> str:
+        """:return: config directory shared by the users, same as `site_data_dir`"""
+        return self.site_data_dir
+
+    @property
+    def user_cache_dir(self) -> str:
+        """:return: cache directory tied to the user, e.g. ``~/Library/Caches/$appname/$version``"""
+        return self._append_app_name_and_version(os.path.expanduser("~/Library/Caches"))  # noqa: PTH111
+
+    @property
+    def site_cache_dir(self) -> str:
+        """
+        :return: cache directory shared by users, e.g. ``/Library/Caches/$appname/$version``.
+          If we're using a Python binary managed by `Homebrew `_, the directory
+          will be under the Homebrew prefix, e.g. ``/opt/homebrew/var/cache/$appname/$version``.
+          If `multipath ` is enabled, and we're in Homebrew,
+          the response is a multi-path string separated by ":", e.g.
+          ``/opt/homebrew/var/cache/$appname/$version:/Library/Caches/$appname/$version``
+        """
+        is_homebrew = sys.prefix.startswith("/opt/homebrew")
+        path_list = [self._append_app_name_and_version("/opt/homebrew/var/cache")] if is_homebrew else []
+        path_list.append(self._append_app_name_and_version("/Library/Caches"))
+        if self.multipath:
+            return os.pathsep.join(path_list)
+        return path_list[0]
+
+    @property
+    def user_state_dir(self) -> str:
+        """:return: state directory tied to the user, same as `user_data_dir`"""
+        return self.user_data_dir
+
+    @property
+    def user_log_dir(self) -> str:
+        """:return: log directory tied to the user, e.g. ``~/Library/Logs/$appname/$version``"""
+        return self._append_app_name_and_version(os.path.expanduser("~/Library/Logs"))  # noqa: PTH111
+
+    @property
+    def user_documents_dir(self) -> str:
+        """:return: documents directory tied to the user, e.g. ``~/Documents``"""
+        return os.path.expanduser("~/Documents")  # noqa: PTH111
+
+    @property
+    def user_downloads_dir(self) -> str:
+        """:return: downloads directory tied to the user, e.g. ``~/Downloads``"""
+        return os.path.expanduser("~/Downloads")  # noqa: PTH111
+
+    @property
+    def user_pictures_dir(self) -> str:
+        """:return: pictures directory tied to the user, e.g. ``~/Pictures``"""
+        return os.path.expanduser("~/Pictures")  # noqa: PTH111
+
+    @property
+    def user_videos_dir(self) -> str:
+        """:return: videos directory tied to the user, e.g. ``~/Movies``"""
+        return os.path.expanduser("~/Movies")  # noqa: PTH111
+
+    @property
+    def user_music_dir(self) -> str:
+        """:return: music directory tied to the user, e.g. ``~/Music``"""
+        return os.path.expanduser("~/Music")  # noqa: PTH111
+
+    @property
+    def user_desktop_dir(self) -> str:
+        """:return: desktop directory tied to the user, e.g. ``~/Desktop``"""
+        return os.path.expanduser("~/Desktop")  # noqa: PTH111
+
+    @property
+    def user_runtime_dir(self) -> str:
+        """:return: runtime directory tied to the user, e.g. ``~/Library/Caches/TemporaryItems/$appname/$version``"""
+        return self._append_app_name_and_version(os.path.expanduser("~/Library/Caches/TemporaryItems"))  # noqa: PTH111
+
+    @property
+    def site_runtime_dir(self) -> str:
+        """:return: runtime directory shared by users, same as `user_runtime_dir`"""
+        return self.user_runtime_dir
+
+
+__all__ = [
+    "MacOS",
+]
diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/py.typed b/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/py.typed
new file mode 100644
index 0000000..e69de29
diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/unix.py b/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/unix.py
new file mode 100644
index 0000000..9500ade
--- /dev/null
+++ b/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/unix.py
@@ -0,0 +1,275 @@
+"""Unix."""
+
+from __future__ import annotations
+
+import os
+import sys
+from configparser import ConfigParser
+from pathlib import Path
+from typing import Iterator, NoReturn
+
+from .api import PlatformDirsABC
+
+if sys.platform == "win32":
+
+    def getuid() -> NoReturn:
+        msg = "should only be used on Unix"
+        raise RuntimeError(msg)
+
+else:
+    from os import getuid
+
+
+class Unix(PlatformDirsABC):  # noqa: PLR0904
+    """
+    On Unix/Linux, we follow the `XDG Basedir Spec `_.
+
+    The spec allows overriding directories with environment variables. The examples shown are the default values,
+    alongside the name of the environment variable that overrides them. Makes use of the `appname
+    `, `version `, `multipath
+    `, `opinion `, `ensure_exists
+    `.
+
+    """
+
+    @property
+    def user_data_dir(self) -> str:
+        """
+        :return: data directory tied to the user, e.g. ``~/.local/share/$appname/$version`` or
+         ``$XDG_DATA_HOME/$appname/$version``
+        """
+        path = os.environ.get("XDG_DATA_HOME", "")
+        if not path.strip():
+            path = os.path.expanduser("~/.local/share")  # noqa: PTH111
+        return self._append_app_name_and_version(path)
+
+    @property
+    def _site_data_dirs(self) -> list[str]:
+        path = os.environ.get("XDG_DATA_DIRS", "")
+        if not path.strip():
+            path = f"/usr/local/share{os.pathsep}/usr/share"
+        return [self._append_app_name_and_version(p) for p in path.split(os.pathsep)]
+
+    @property
+    def site_data_dir(self) -> str:
+        """
+        :return: data directories shared by users (if `multipath ` is
+         enabled and ``XDG_DATA_DIRS`` is set and a multi path the response is also a multi path separated by the
+         OS path separator), e.g. ``/usr/local/share/$appname/$version`` or ``/usr/share/$appname/$version``
+        """
+        # XDG default for $XDG_DATA_DIRS; only first, if multipath is False
+        dirs = self._site_data_dirs
+        if not self.multipath:
+            return dirs[0]
+        return os.pathsep.join(dirs)
+
+    @property
+    def user_config_dir(self) -> str:
+        """
+        :return: config directory tied to the user, e.g. ``~/.config/$appname/$version`` or
+         ``$XDG_CONFIG_HOME/$appname/$version``
+        """
+        path = os.environ.get("XDG_CONFIG_HOME", "")
+        if not path.strip():
+            path = os.path.expanduser("~/.config")  # noqa: PTH111
+        return self._append_app_name_and_version(path)
+
+    @property
+    def _site_config_dirs(self) -> list[str]:
+        path = os.environ.get("XDG_CONFIG_DIRS", "")
+        if not path.strip():
+            path = "/etc/xdg"
+        return [self._append_app_name_and_version(p) for p in path.split(os.pathsep)]
+
+    @property
+    def site_config_dir(self) -> str:
+        """
+        :return: config directories shared by users (if `multipath `
+         is enabled and ``XDG_CONFIG_DIRS`` is set and a multi path the response is also a multi path separated by
+         the OS path separator), e.g. ``/etc/xdg/$appname/$version``
+        """
+        # XDG default for $XDG_CONFIG_DIRS only first, if multipath is False
+        dirs = self._site_config_dirs
+        if not self.multipath:
+            return dirs[0]
+        return os.pathsep.join(dirs)
+
+    @property
+    def user_cache_dir(self) -> str:
+        """
+        :return: cache directory tied to the user, e.g. ``~/.cache/$appname/$version`` or
+         ``~/$XDG_CACHE_HOME/$appname/$version``
+        """
+        path = os.environ.get("XDG_CACHE_HOME", "")
+        if not path.strip():
+            path = os.path.expanduser("~/.cache")  # noqa: PTH111
+        return self._append_app_name_and_version(path)
+
+    @property
+    def site_cache_dir(self) -> str:
+        """:return: cache directory shared by users, e.g. ``/var/cache/$appname/$version``"""
+        return self._append_app_name_and_version("/var/cache")
+
+    @property
+    def user_state_dir(self) -> str:
+        """
+        :return: state directory tied to the user, e.g. ``~/.local/state/$appname/$version`` or
+         ``$XDG_STATE_HOME/$appname/$version``
+        """
+        path = os.environ.get("XDG_STATE_HOME", "")
+        if not path.strip():
+            path = os.path.expanduser("~/.local/state")  # noqa: PTH111
+        return self._append_app_name_and_version(path)
+
+    @property
+    def user_log_dir(self) -> str:
+        """:return: log directory tied to the user, same as `user_state_dir` if not opinionated else ``log`` in it"""
+        path = self.user_state_dir
+        if self.opinion:
+            path = os.path.join(path, "log")  # noqa: PTH118
+            self._optionally_create_directory(path)
+        return path
+
+    @property
+    def user_documents_dir(self) -> str:
+        """:return: documents directory tied to the user, e.g. ``~/Documents``"""
+        return _get_user_media_dir("XDG_DOCUMENTS_DIR", "~/Documents")
+
+    @property
+    def user_downloads_dir(self) -> str:
+        """:return: downloads directory tied to the user, e.g. ``~/Downloads``"""
+        return _get_user_media_dir("XDG_DOWNLOAD_DIR", "~/Downloads")
+
+    @property
+    def user_pictures_dir(self) -> str:
+        """:return: pictures directory tied to the user, e.g. ``~/Pictures``"""
+        return _get_user_media_dir("XDG_PICTURES_DIR", "~/Pictures")
+
+    @property
+    def user_videos_dir(self) -> str:
+        """:return: videos directory tied to the user, e.g. ``~/Videos``"""
+        return _get_user_media_dir("XDG_VIDEOS_DIR", "~/Videos")
+
+    @property
+    def user_music_dir(self) -> str:
+        """:return: music directory tied to the user, e.g. ``~/Music``"""
+        return _get_user_media_dir("XDG_MUSIC_DIR", "~/Music")
+
+    @property
+    def user_desktop_dir(self) -> str:
+        """:return: desktop directory tied to the user, e.g. ``~/Desktop``"""
+        return _get_user_media_dir("XDG_DESKTOP_DIR", "~/Desktop")
+
+    @property
+    def user_runtime_dir(self) -> str:
+        """
+        :return: runtime directory tied to the user, e.g. ``/run/user/$(id -u)/$appname/$version`` or
+         ``$XDG_RUNTIME_DIR/$appname/$version``.
+
+         For FreeBSD/OpenBSD/NetBSD, it would return ``/var/run/user/$(id -u)/$appname/$version`` if
+         exists, otherwise ``/tmp/runtime-$(id -u)/$appname/$version``, if``$XDG_RUNTIME_DIR``
+         is not set.
+        """
+        path = os.environ.get("XDG_RUNTIME_DIR", "")
+        if not path.strip():
+            if sys.platform.startswith(("freebsd", "openbsd", "netbsd")):
+                path = f"/var/run/user/{getuid()}"
+                if not Path(path).exists():
+                    path = f"/tmp/runtime-{getuid()}"  # noqa: S108
+            else:
+                path = f"/run/user/{getuid()}"
+        return self._append_app_name_and_version(path)
+
+    @property
+    def site_runtime_dir(self) -> str:
+        """
+        :return: runtime directory shared by users, e.g. ``/run/$appname/$version`` or \
+        ``$XDG_RUNTIME_DIR/$appname/$version``.
+
+        Note that this behaves almost exactly like `user_runtime_dir` if ``$XDG_RUNTIME_DIR`` is set, but will
+        fall back to paths associated to the root user instead of a regular logged-in user if it's not set.
+
+        If you wish to ensure that a logged-in root user path is returned e.g. ``/run/user/0``, use `user_runtime_dir`
+        instead.
+
+        For FreeBSD/OpenBSD/NetBSD, it would return ``/var/run/$appname/$version`` if ``$XDG_RUNTIME_DIR`` is not set.
+        """
+        path = os.environ.get("XDG_RUNTIME_DIR", "")
+        if not path.strip():
+            if sys.platform.startswith(("freebsd", "openbsd", "netbsd")):
+                path = "/var/run"
+            else:
+                path = "/run"
+        return self._append_app_name_and_version(path)
+
+    @property
+    def site_data_path(self) -> Path:
+        """:return: data path shared by users. Only return the first item, even if ``multipath`` is set to ``True``"""
+        return self._first_item_as_path_if_multipath(self.site_data_dir)
+
+    @property
+    def site_config_path(self) -> Path:
+        """:return: config path shared by the users, returns the first item, even if ``multipath`` is set to ``True``"""
+        return self._first_item_as_path_if_multipath(self.site_config_dir)
+
+    @property
+    def site_cache_path(self) -> Path:
+        """:return: cache path shared by users. Only return the first item, even if ``multipath`` is set to ``True``"""
+        return self._first_item_as_path_if_multipath(self.site_cache_dir)
+
+    def _first_item_as_path_if_multipath(self, directory: str) -> Path:
+        if self.multipath:
+            # If multipath is True, the first path is returned.
+            directory = directory.split(os.pathsep)[0]
+        return Path(directory)
+
+    def iter_config_dirs(self) -> Iterator[str]:
+        """:yield: all user and site configuration directories."""
+        yield self.user_config_dir
+        yield from self._site_config_dirs
+
+    def iter_data_dirs(self) -> Iterator[str]:
+        """:yield: all user and site data directories."""
+        yield self.user_data_dir
+        yield from self._site_data_dirs
+
+
+def _get_user_media_dir(env_var: str, fallback_tilde_path: str) -> str:
+    media_dir = _get_user_dirs_folder(env_var)
+    if media_dir is None:
+        media_dir = os.environ.get(env_var, "").strip()
+        if not media_dir:
+            media_dir = os.path.expanduser(fallback_tilde_path)  # noqa: PTH111
+
+    return media_dir
+
+
+def _get_user_dirs_folder(key: str) -> str | None:
+    """
+    Return directory from user-dirs.dirs config file.
+
+    See https://freedesktop.org/wiki/Software/xdg-user-dirs/.
+
+    """
+    user_dirs_config_path = Path(Unix().user_config_dir) / "user-dirs.dirs"
+    if user_dirs_config_path.exists():
+        parser = ConfigParser()
+
+        with user_dirs_config_path.open() as stream:
+            # Add fake section header, so ConfigParser doesn't complain
+            parser.read_string(f"[top]\n{stream.read()}")
+
+        if key not in parser["top"]:
+            return None
+
+        path = parser["top"][key].strip('"')
+        # Handle relative home paths
+        return path.replace("$HOME", os.path.expanduser("~"))  # noqa: PTH111
+
+    return None
+
+
+__all__ = [
+    "Unix",
+]
diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/version.py b/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/version.py
new file mode 100644
index 0000000..6483ddc
--- /dev/null
+++ b/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/version.py
@@ -0,0 +1,16 @@
+# file generated by setuptools_scm
+# don't change, don't track in version control
+TYPE_CHECKING = False
+if TYPE_CHECKING:
+    from typing import Tuple, Union
+    VERSION_TUPLE = Tuple[Union[int, str], ...]
+else:
+    VERSION_TUPLE = object
+
+version: str
+__version__: str
+__version_tuple__: VERSION_TUPLE
+version_tuple: VERSION_TUPLE
+
+__version__ = version = '4.2.2'
+__version_tuple__ = version_tuple = (4, 2, 2)
diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/windows.py b/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/windows.py
new file mode 100644
index 0000000..d7bc960
--- /dev/null
+++ b/backend/.venv/Lib/site-packages/pip/_vendor/platformdirs/windows.py
@@ -0,0 +1,272 @@
+"""Windows."""
+
+from __future__ import annotations
+
+import os
+import sys
+from functools import lru_cache
+from typing import TYPE_CHECKING
+
+from .api import PlatformDirsABC
+
+if TYPE_CHECKING:
+    from collections.abc import Callable
+
+
+class Windows(PlatformDirsABC):
+    """
+    `MSDN on where to store app data files `_.
+
+    Makes use of the `appname `, `appauthor
+    `, `version `, `roaming
+    `, `opinion `, `ensure_exists
+    `.
+
+    """
+
+    @property
+    def user_data_dir(self) -> str:
+        """
+        :return: data directory tied to the user, e.g.
+         ``%USERPROFILE%\\AppData\\Local\\$appauthor\\$appname`` (not roaming) or
+         ``%USERPROFILE%\\AppData\\Roaming\\$appauthor\\$appname`` (roaming)
+        """
+        const = "CSIDL_APPDATA" if self.roaming else "CSIDL_LOCAL_APPDATA"
+        path = os.path.normpath(get_win_folder(const))
+        return self._append_parts(path)
+
+    def _append_parts(self, path: str, *, opinion_value: str | None = None) -> str:
+        params = []
+        if self.appname:
+            if self.appauthor is not False:
+                author = self.appauthor or self.appname
+                params.append(author)
+            params.append(self.appname)
+            if opinion_value is not None and self.opinion:
+                params.append(opinion_value)
+            if self.version:
+                params.append(self.version)
+        path = os.path.join(path, *params)  # noqa: PTH118
+        self._optionally_create_directory(path)
+        return path
+
+    @property
+    def site_data_dir(self) -> str:
+        """:return: data directory shared by users, e.g. ``C:\\ProgramData\\$appauthor\\$appname``"""
+        path = os.path.normpath(get_win_folder("CSIDL_COMMON_APPDATA"))
+        return self._append_parts(path)
+
+    @property
+    def user_config_dir(self) -> str:
+        """:return: config directory tied to the user, same as `user_data_dir`"""
+        return self.user_data_dir
+
+    @property
+    def site_config_dir(self) -> str:
+        """:return: config directory shared by the users, same as `site_data_dir`"""
+        return self.site_data_dir
+
+    @property
+    def user_cache_dir(self) -> str:
+        """
+        :return: cache directory tied to the user (if opinionated with ``Cache`` folder within ``$appname``) e.g.
+         ``%USERPROFILE%\\AppData\\Local\\$appauthor\\$appname\\Cache\\$version``
+        """
+        path = os.path.normpath(get_win_folder("CSIDL_LOCAL_APPDATA"))
+        return self._append_parts(path, opinion_value="Cache")
+
+    @property
+    def site_cache_dir(self) -> str:
+        """:return: cache directory shared by users, e.g. ``C:\\ProgramData\\$appauthor\\$appname\\Cache\\$version``"""
+        path = os.path.normpath(get_win_folder("CSIDL_COMMON_APPDATA"))
+        return self._append_parts(path, opinion_value="Cache")
+
+    @property
+    def user_state_dir(self) -> str:
+        """:return: state directory tied to the user, same as `user_data_dir`"""
+        return self.user_data_dir
+
+    @property
+    def user_log_dir(self) -> str:
+        """:return: log directory tied to the user, same as `user_data_dir` if not opinionated else ``Logs`` in it"""
+        path = self.user_data_dir
+        if self.opinion:
+            path = os.path.join(path, "Logs")  # noqa: PTH118
+            self._optionally_create_directory(path)
+        return path
+
+    @property
+    def user_documents_dir(self) -> str:
+        """:return: documents directory tied to the user e.g. ``%USERPROFILE%\\Documents``"""
+        return os.path.normpath(get_win_folder("CSIDL_PERSONAL"))
+
+    @property
+    def user_downloads_dir(self) -> str:
+        """:return: downloads directory tied to the user e.g. ``%USERPROFILE%\\Downloads``"""
+        return os.path.normpath(get_win_folder("CSIDL_DOWNLOADS"))
+
+    @property
+    def user_pictures_dir(self) -> str:
+        """:return: pictures directory tied to the user e.g. ``%USERPROFILE%\\Pictures``"""
+        return os.path.normpath(get_win_folder("CSIDL_MYPICTURES"))
+
+    @property
+    def user_videos_dir(self) -> str:
+        """:return: videos directory tied to the user e.g. ``%USERPROFILE%\\Videos``"""
+        return os.path.normpath(get_win_folder("CSIDL_MYVIDEO"))
+
+    @property
+    def user_music_dir(self) -> str:
+        """:return: music directory tied to the user e.g. ``%USERPROFILE%\\Music``"""
+        return os.path.normpath(get_win_folder("CSIDL_MYMUSIC"))
+
+    @property
+    def user_desktop_dir(self) -> str:
+        """:return: desktop directory tied to the user, e.g. ``%USERPROFILE%\\Desktop``"""
+        return os.path.normpath(get_win_folder("CSIDL_DESKTOPDIRECTORY"))
+
+    @property
+    def user_runtime_dir(self) -> str:
+        """
+        :return: runtime directory tied to the user, e.g.
+         ``%USERPROFILE%\\AppData\\Local\\Temp\\$appauthor\\$appname``
+        """
+        path = os.path.normpath(os.path.join(get_win_folder("CSIDL_LOCAL_APPDATA"), "Temp"))  # noqa: PTH118
+        return self._append_parts(path)
+
+    @property
+    def site_runtime_dir(self) -> str:
+        """:return: runtime directory shared by users, same as `user_runtime_dir`"""
+        return self.user_runtime_dir
+
+
+def get_win_folder_from_env_vars(csidl_name: str) -> str:
+    """Get folder from environment variables."""
+    result = get_win_folder_if_csidl_name_not_env_var(csidl_name)
+    if result is not None:
+        return result
+
+    env_var_name = {
+        "CSIDL_APPDATA": "APPDATA",
+        "CSIDL_COMMON_APPDATA": "ALLUSERSPROFILE",
+        "CSIDL_LOCAL_APPDATA": "LOCALAPPDATA",
+    }.get(csidl_name)
+    if env_var_name is None:
+        msg = f"Unknown CSIDL name: {csidl_name}"
+        raise ValueError(msg)
+    result = os.environ.get(env_var_name)
+    if result is None:
+        msg = f"Unset environment variable: {env_var_name}"
+        raise ValueError(msg)
+    return result
+
+
+def get_win_folder_if_csidl_name_not_env_var(csidl_name: str) -> str | None:
+    """Get a folder for a CSIDL name that does not exist as an environment variable."""
+    if csidl_name == "CSIDL_PERSONAL":
+        return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Documents")  # noqa: PTH118
+
+    if csidl_name == "CSIDL_DOWNLOADS":
+        return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Downloads")  # noqa: PTH118
+
+    if csidl_name == "CSIDL_MYPICTURES":
+        return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Pictures")  # noqa: PTH118
+
+    if csidl_name == "CSIDL_MYVIDEO":
+        return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Videos")  # noqa: PTH118
+
+    if csidl_name == "CSIDL_MYMUSIC":
+        return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Music")  # noqa: PTH118
+    return None
+
+
+def get_win_folder_from_registry(csidl_name: str) -> str:
+    """
+    Get folder from the registry.
+
+    This is a fallback technique at best. I'm not sure if using the registry for these guarantees us the correct answer
+    for all CSIDL_* names.
+
+    """
+    shell_folder_name = {
+        "CSIDL_APPDATA": "AppData",
+        "CSIDL_COMMON_APPDATA": "Common AppData",
+        "CSIDL_LOCAL_APPDATA": "Local AppData",
+        "CSIDL_PERSONAL": "Personal",
+        "CSIDL_DOWNLOADS": "{374DE290-123F-4565-9164-39C4925E467B}",
+        "CSIDL_MYPICTURES": "My Pictures",
+        "CSIDL_MYVIDEO": "My Video",
+        "CSIDL_MYMUSIC": "My Music",
+    }.get(csidl_name)
+    if shell_folder_name is None:
+        msg = f"Unknown CSIDL name: {csidl_name}"
+        raise ValueError(msg)
+    if sys.platform != "win32":  # only needed for mypy type checker to know that this code runs only on Windows
+        raise NotImplementedError
+    import winreg  # noqa: PLC0415
+
+    key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
+    directory, _ = winreg.QueryValueEx(key, shell_folder_name)
+    return str(directory)
+
+
+def get_win_folder_via_ctypes(csidl_name: str) -> str:
+    """Get folder with ctypes."""
+    # There is no 'CSIDL_DOWNLOADS'.
+    # Use 'CSIDL_PROFILE' (40) and append the default folder 'Downloads' instead.
+    # https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid
+
+    import ctypes  # noqa: PLC0415
+
+    csidl_const = {
+        "CSIDL_APPDATA": 26,
+        "CSIDL_COMMON_APPDATA": 35,
+        "CSIDL_LOCAL_APPDATA": 28,
+        "CSIDL_PERSONAL": 5,
+        "CSIDL_MYPICTURES": 39,
+        "CSIDL_MYVIDEO": 14,
+        "CSIDL_MYMUSIC": 13,
+        "CSIDL_DOWNLOADS": 40,
+        "CSIDL_DESKTOPDIRECTORY": 16,
+    }.get(csidl_name)
+    if csidl_const is None:
+        msg = f"Unknown CSIDL name: {csidl_name}"
+        raise ValueError(msg)
+
+    buf = ctypes.create_unicode_buffer(1024)
+    windll = getattr(ctypes, "windll")  # noqa: B009 # using getattr to avoid false positive with mypy type checker
+    windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf)
+
+    # Downgrade to short path name if it has high-bit chars.
+    if any(ord(c) > 255 for c in buf):  # noqa: PLR2004
+        buf2 = ctypes.create_unicode_buffer(1024)
+        if windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024):
+            buf = buf2
+
+    if csidl_name == "CSIDL_DOWNLOADS":
+        return os.path.join(buf.value, "Downloads")  # noqa: PTH118
+
+    return buf.value
+
+
+def _pick_get_win_folder() -> Callable[[str], str]:
+    try:
+        import ctypes  # noqa: PLC0415
+    except ImportError:
+        pass
+    else:
+        if hasattr(ctypes, "windll"):
+            return get_win_folder_via_ctypes
+    try:
+        import winreg  # noqa: PLC0415, F401
+    except ImportError:
+        return get_win_folder_from_env_vars
+    else:
+        return get_win_folder_from_registry
+
+
+get_win_folder = lru_cache(maxsize=None)(_pick_get_win_folder())
+
+__all__ = [
+    "Windows",
+]
diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__init__.py b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__init__.py
new file mode 100644
index 0000000..60ae9bb
--- /dev/null
+++ b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__init__.py
@@ -0,0 +1,82 @@
+"""
+    Pygments
+    ~~~~~~~~
+
+    Pygments is a syntax highlighting package written in Python.
+
+    It is a generic syntax highlighter for general use in all kinds of software
+    such as forum systems, wikis or other applications that need to prettify
+    source code. Highlights are:
+
+    * a wide range of common languages and markup formats is supported
+    * special attention is paid to details, increasing quality by a fair amount
+    * support for new languages and formats are added easily
+    * a number of output formats, presently HTML, LaTeX, RTF, SVG, all image
+      formats that PIL supports, and ANSI sequences
+    * it is usable as a command-line tool and as a library
+    * ... and it highlights even Brainfuck!
+
+    The `Pygments master branch`_ is installable with ``easy_install Pygments==dev``.
+
+    .. _Pygments master branch:
+       https://github.com/pygments/pygments/archive/master.zip#egg=Pygments-dev
+
+    :copyright: Copyright 2006-2024 by the Pygments team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+from io import StringIO, BytesIO
+
+__version__ = '2.18.0'
+__docformat__ = 'restructuredtext'
+
+__all__ = ['lex', 'format', 'highlight']
+
+
+def lex(code, lexer):
+    """
+    Lex `code` with the `lexer` (must be a `Lexer` instance)
+    and return an iterable of tokens. Currently, this only calls
+    `lexer.get_tokens()`.
+    """
+    try:
+        return lexer.get_tokens(code)
+    except TypeError:
+        # Heuristic to catch a common mistake.
+        from pip._vendor.pygments.lexer import RegexLexer
+        if isinstance(lexer, type) and issubclass(lexer, RegexLexer):
+            raise TypeError('lex() argument must be a lexer instance, '
+                            'not a class')
+        raise
+
+
+def format(tokens, formatter, outfile=None):  # pylint: disable=redefined-builtin
+    """
+    Format ``tokens`` (an iterable of tokens) with the formatter ``formatter``
+    (a `Formatter` instance).
+
+    If ``outfile`` is given and a valid file object (an object with a
+    ``write`` method), the result will be written to it, otherwise it
+    is returned as a string.
+    """
+    try:
+        if not outfile:
+            realoutfile = getattr(formatter, 'encoding', None) and BytesIO() or StringIO()
+            formatter.format(tokens, realoutfile)
+            return realoutfile.getvalue()
+        else:
+            formatter.format(tokens, outfile)
+    except TypeError:
+        # Heuristic to catch a common mistake.
+        from pip._vendor.pygments.formatter import Formatter
+        if isinstance(formatter, type) and issubclass(formatter, Formatter):
+            raise TypeError('format() argument must be a formatter instance, '
+                            'not a class')
+        raise
+
+
+def highlight(code, lexer, formatter, outfile=None):
+    """
+    This is the most high-level highlighting function. It combines `lex` and
+    `format` in one function.
+    """
+    return format(lex(code, lexer), formatter, outfile)
diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__main__.py b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__main__.py
new file mode 100644
index 0000000..dcc6e5a
--- /dev/null
+++ b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__main__.py
@@ -0,0 +1,17 @@
+"""
+    pygments.__main__
+    ~~~~~~~~~~~~~~~~~
+
+    Main entry point for ``python -m pygments``.
+
+    :copyright: Copyright 2006-2024 by the Pygments team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+import sys
+from pip._vendor.pygments.cmdline import main
+
+try:
+    sys.exit(main(sys.argv))
+except KeyboardInterrupt:
+    sys.exit(1)
diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..cae7446cca660912b5379ccec473f89e48235531
GIT binary patch
literal 3492
zcmaJ@O>7&-72YK&i6ZsmO16q9u06Kv*t8`|5scbVV*|G1#6sjBSZbOw0?6g=h+J#A
z%goH0q97NBkwcFuTEID^fKdc!3ips>jxE|-FLtED?!pJ7MGw8XQGgaX^?S2i(oNM4
zq~Yw$&YSn%e&09mkHf<`1MSLtXWd`r4dbu$khD~1uyYQBdxm3_499d*p4mv1QjK&e
zZ5mFxlyNepzMA3m{n9M;JN+LRr2!}BWIr%VS^N&-cd$KB$Xoj|hLK}v*W0xQ_m$KS
zKkl^Le=IRqGKzx5j-g
zT>HOlaKTms!Su4_u~2d{VR;@~bA3m$V3o;WRkbX^wMR0v>&%k0DQv)+RJ=<#1)W9>Q>aTX0KKV&4xf&sA+!ZNr6C%SBL)AoNvYFSf6f=kwM#{7D=^
zAk1YKAIteTot!;i1=NmzS?BPO(L6nZG;5ZY;k!#g^WA
zYf66`w}H^LCoI_+r}_HAViG#Sq12qey0pL~e?R2D&0~z6V6H|*D6Ogo2MJr0R=hs#
zxjx5t3Xmym)=QpS6_!YRFBXe>2`0Kgl#Jg3_AUs^^;biC?NI#jmg}5V5_IDm0V{&R
zmT%W9Wy-(nO9iNDFIujuvq}YdYL`3nU1pp;>+oBZN(a(#puD@)`A$k$U8$y=pP8w_
zXjm;GxS3{$WxatV?7Dl4&%}-uH{9kCUaOr=Oi$y?IF5NcXto70Zk}CChHP$j_IuNF
zvva2iB0zoDTc)_xm_p7uJO6{_%hzr!6}4aUpal0NpJx}A-iX&17cO49x^zjSr~|@c
z?(ZZsg;bPXQUXX^xE2juXe%xku5I+s6<~)E^@+
z8ti@>J5epN+K2x%{&zk`ch49!HqDzRhTmwL#)Ho6l5xaPT?^ke#0)f!G!J@rJ7pSb
zFxk3kDy^LK{GhW#d|M6o);Ck#`Me@8baT?lS$EC5M$1@F|Hx>Wh0Mk;bkY|2I;)UC
zRGPeTo?Q^6WOMUh<$
zh0tu9f@M-LAH=hP$(SkeNyQph<#@;O0#HbzEhxl-8Rc&98ei9^Z=8Z(#|u!eT1bM<
zdhTh5yUtB9KTyOu&yun*5aoLIqrv5NlV1`d5Yc4QZ5GQQmJ^6#0^g!GB`DQV&V^Ee
zL5MfXDD0yd8CGMv=_o^ai~4#yBxN1We_g#eztRfCn#A?NSNxkwPFuE3@&>?7+kxOK
zRa`7MdZh>lZmlf3)fI^ZPIvAbxdP{AI?nYdRR(okRW8F_(T}rqcLW1@1Kl0t`B1iR
zzEH`7qx9S`z&3?in|JcIJFOebuJ;lGerg9I&jho|12=
zF4{Lu!tsO7j&)PyfadQ02OTTxrlfhYrCTz8I}PRxB(uHWO=B~ipxngxW|tqmcM=;*
z#J=5abeUor?GzZ;WmboQX(!|LHwJEJ;M=zn%V6MGGERH|1NS9!o91SwJD*pmZsO+j
z?aIJ@Yd?~u!TzScSE0@^2`Zr8u6!!=I2!8^34W#09ak#a+;Q+VHi`8YIGdC#tJs5U
zan
z3Vx!(fpR2e6Dku|O~utq%cUYHzUXmyEFieT^<@az1w~>Fh_bj-0|(Dn6FC^{#dnc$7y4CR{r$E
z%;_DhBC4x}Tr^NFJAqv;M=3Xmfk$Sed>L{tBtpQ_uzn|Y7mwJ2JF{GlMPCDi&i%C^
z4&q0{Cd$6v2%OO4=fo?RBOR90=$@xd)BH#3B{TESQ-*oy*~rA5{F6P0?+pJXcl^%4
Vm;EE=$j;#jbL6YJKJ$z=_is+s&c6Tv

literal 0
HcmV?d00001

diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__main__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__main__.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..8f2c44cc3341cc6c6be812cc655af1cefa79a5b1
GIT binary patch
literal 738
zcmZ`$J8u&~5Z?7&uyF_k2?Rxo6`_bF?rbbXVF6Mwk!d<$S(d?2YesPrK_l
zM}eT>AtVG<8vX#H;wMm3BBbafDynn=Hz*Z*jxULjm||ykX1@8p+5I{-l?Td}AKfGl
z1mI_KNo`^r3_qw~8+f1zJm_V7*o4Y!ekRbG8U!an24J|6OJPS|$1I>;zYkz!=RxT&>-G&@e~D6`#163S2?A8+Q)sOZDo)N@HOp!NbxazA*E<
z$qTI%V5}$0>?TiE$i`XQ_Lytiu_huB&x9m2?M+NQ#?8a^-N5q+#avU6SjSsL#=65h
zoAKF29JQIly*ibc^L{8lf?-0l->z1y0pmRpIxe>8h7^Y5x~xwnp&i3z99wP2?I|M5
zRCJrx5@}n4NNgxT&*@-cDJjLVlwvBSnEr$k7w2vS%ob3LvKM~?c&z;D{)@$A#Pq&6
Uqo%#RbQOHQFh8k%$wPJi1#!K`@Bjb+

literal 0
HcmV?d00001

diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/cmdline.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/cmdline.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..48cce152fd18ed7e969b11f4fe0bbf4209a28da0
GIT binary patch
literal 26588
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

' : '\U0001d4ab', + '\\' : '\U0001d4ac', + '\\' : '\U0000211b', + '\\' : '\U0001d4ae', + '\\' : '\U0001d4af', + '\\' : '\U0001d4b0', + '\\' : '\U0001d4b1', + '\\' : '\U0001d4b2', + '\\' : '\U0001d4b3', + '\\' : '\U0001d4b4', + '\\' : '\U0001d4b5', + '\\' : '\U0001d5ba', + '\\' : '\U0001d5bb', + '\\' : '\U0001d5bc', + '\\' : '\U0001d5bd', + '\\' : '\U0001d5be', + '\\' : '\U0001d5bf', + '\\' : '\U0001d5c0', + '\\' : '\U0001d5c1', + '\\' : '\U0001d5c2', + '\\' : '\U0001d5c3', + '\\' : '\U0001d5c4', + '\\' : '\U0001d5c5', + '\\' : '\U0001d5c6', + '\\' : '\U0001d5c7', + '\\' : '\U0001d5c8', + '\\

' : '\U0001d5c9', + '\\' : '\U0001d5ca', + '\\' : '\U0001d5cb', + '\\' : '\U0001d5cc', + '\\' : '\U0001d5cd', + '\\' : '\U0001d5ce', + '\\' : '\U0001d5cf', + '\\' : '\U0001d5d0', + '\\' : '\U0001d5d1', + '\\' : '\U0001d5d2', + '\\' : '\U0001d5d3', + '\\' : '\U0001d504', + '\\' : '\U0001d505', + '\\' : '\U0000212d', + '\\

' : '\U0001d507', + '\\' : '\U0001d508', + '\\' : '\U0001d509', + '\\' : '\U0001d50a', + '\\' : '\U0000210c', + '\\' : '\U00002111', + '\\' : '\U0001d50d', + '\\' : '\U0001d50e', + '\\' : '\U0001d50f', + '\\' : '\U0001d510', + '\\' : '\U0001d511', + '\\' : '\U0001d512', + '\\' : '\U0001d513', + '\\' : '\U0001d514', + '\\' : '\U0000211c', + '\\' : '\U0001d516', + '\\' : '\U0001d517', + '\\' : '\U0001d518', + '\\' : '\U0001d519', + '\\' : '\U0001d51a', + '\\' : '\U0001d51b', + '\\' : '\U0001d51c', + '\\' : '\U00002128', + '\\' : '\U0001d51e', + '\\' : '\U0001d51f', + '\\' : '\U0001d520', + '\\

!Kv1)KCaZ@nor#2+$q_lZs80yj8l*5fGIDNcbYyf~i01@-5ex6wQ3V}~>C=LS zu`qe-{Wsr!Z!T4QnG>p zp9R%8(91xd166g!5{2B9FD8Hwxf^_vV5}I<98RUwRS1;IV#AddlW>%x!6kB{VsJ?! z=D^MuH_yYe_E>=Wu=$oJzs0xxc^f9+HDJ*V-?qq%z^^XKI^H=>>%tL~(>wIGci;se z@-j>b`1S{_HwS!s?Jzw=`o2J7Xsyhl$LuVj3Xd6sPpA^s9-}>~^qY8XBD$)QWi2Bn za8y~+wIMN)P_v3IE6Je*)Iu~42ZI$U8eYN5N_0k!M>W{k5Ev}Ok!aD3oEeUROj5~k zqu_?^`Uz)phR?jTm|0n50D_)^PxHf6KtKDM%U$=bY;xU%aufE$0n$pyOezfEU{dRd zCbiDcCv!Me%9}%^9~KgXDa0BcGjePh=L}BAYq~~*2m%SgVz^DAoX3PlISrrI3zN08 z?wYT+D%E^_U)}op{G$(RzOhYi?C%@pz`)$-rrDp8=q|es9ZF(*5UdV~>4C)7*k#C& z@DgXPg2FOLIkwI&(HlK9^!;Oyc$(@HTZf_kSjo|Y?o#Sm5u7g+!Sz2PxL+uO=a~_n zlf8A(2eSW1{dMMf8VAnP``5ilzNNWZjcKLw1yTIgjHEz z6hy0G3ea+fp>=6$8VjPX6FHvMu{JSb^-XGS))^&WD74q6ESBk;G6zhJ0ZIzAwH*>$ z?$``j>CpH{ExK7mFP4@%$0uONYjf%464%Uyfl_$&b zQoh9f2b-x%dduDaVm8yY&Qn|N&_N^4`{~W%%?H6MR~g*mj@K<*?%(3NY#L;)N_dNV zrS1#dKY#Ch`P^r(Z*o0mW0(#34Oc8Csfk$3a9}NA9iC4T$+C5Yn&D5;UuXj{Ylb5) zXAF+27`!Pn+oai%%p)YP!tt5z?WT1(txDMxzCtEJK%0a1J50L{hGBkX-3+(ej$BOz z$F|#B;OqXT0$+$1J@uCM@|{{sAE0EhX}h_tj4M6>w~GNP%2s+UNxi+R8mvqMSgN6x zddJb~*~&bib7Y|4gQfXG!N2Q7ysN^yp-*J5*~60XtZnsdId(r8rfb+;yS$(Ooa%J*8l| eWxJ)byiz%4?enRVVS1jr8D@OX-O2Qt=kq75p_82e literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/filter.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/filter.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5b2d61aeb390a40d22654d8cf71d071f0e77baa8 GIT binary patch literal 3225 zcmaJ@-)|g89iQ3Ty}Mk`c49jYI8Hoiity3+Vgdxk)TSjr+Ng~|IBBKBuwL)(IqR%% zkC{E2J1&tGEJ&mP$pf5Qim*f;8by`bC;kY8H<5S}#MRK^#&bPTJAdX@NS4byCnY z@+xukb>bLzH8r=8kbOz$OSy@=iKthv(%i1v-!cqJxw^RQmO_y)dVc6~*>|P8WMt>L zz^V8y3olwB^OnoLE6w2BWsY04Dt^e+5_vU$(hka1?k!#nC)vrk$&O7-93MY6aqOFH zp(<^E5be)G*IGWpgzK_bE}Vbu`#+q`%WWrp&vr|~on+seJ*CFqID7K+%>{pppVjhIcT7ZxQ#mI93DxBIMvto}Dc+ z-~E}(8LYABt+;6RRe?uewYcNT6(NMuN`>zT3!sCqdU9(wTAFd!cEMh-`I(^P&a2?q z(LGC_b*R6AKA(Z=cl32a0VQ>^MCE8#bzQ5|*z41Pq@P2qey=sOUm6BjRmr!>4dea9 zD!oHza{LZ9o64S9-?W8OO3C8GBA8C^^ZOKHd32I+k3{YCm$uq;Qo)F+p~7A1=EP#c{{kBMC}qZ8YFCw z!7X;)G#Ww)@y2B-(hv_WOPx6Fy9GO3b4P(0+PiHv0JJA+|C9hc<-!$NA<#;)+zv`B zE)NB>Sg}&FLoWdImXHDwC?_Ws)j>ws%R-8Rx)8Y<_JT4nKUj6SZ3%ZwxPI}7;sY>Q zG6c|G#)U<0vTcNh$n7w!mfa(4#qujIY#dp1&%?P@&-H;w9kcUt&#|0bvY9c>Whq{! znM?595RGQaG@ZaU&1O3GEN3)zT%nmZ&62h3!dUN_$m=sw8k?y_5SuXMd=D%Eyr4ya zHx!{E+Zh1`9m0cn5~beRT>st&#+)tPI4 zbg^9m&1NeLwr>g0E7UgCgn(Bf$(iqTWnQk}JcUNUY|yq4bZ@m33tuEh@d@$B2w0F= z(n2zV5Yaj@p`}Wda0D*|F%{ka9j&P&J~%oj&^V?UT!>flLes4EDW~#r$5EV$R0N9e zJ9th1byfupITROM3BOxIP<3+ZZZzX6jgK-g6NG2u%;q|$IS=@q1V0E9l@cJwBCS)G z&QTF+J<+j>5+;~&1UkM(9`+vE?mfJfJ}i$llS}eJ=vN5Ln&wX{mam{D5yeMw5Le`A zE^VaH@L~MKDhEG-=vya`wSbG>~3seLX6O$Fe6Q4PQ~b8ARPEkDEierI}eQ=i?qQdt*uHJ zEL))mf)0sRtuB~|APX4~@@)rhK`FX66|4-%R+-fc6)PJgLBDd>Y^o3iJH64gJemdHg}n(B(iBLlu6J?NF9JBI~gT` zR@>LDZf#P17iWJ5D!^~w(9Lk8@b|v4hyD9E!arSk`^x>%hO-$eY{! zZ*67YdYJD0ZQu324gFqvY%{f;9{XP!V$2W2uT_BRi=HN+6WX)WUHp9gq6dqjvL>S_ zm4rVJ`#poRdv|!RxO)mGGpOXV;p2gQjj3Bxn|t3&exUy)`(bu_VCsH)>ZA0OdOTb` z^dkK;&FQz3FVbA`W1BNBnBr~>lIAybW#2sz%Z9nJJhD)&wEuYm;uQ()s!f>QceOH;iyl%f4khI?r0 ZKP*FEcub)Bba*$NzWL_A3H-^e{|n_3{q_I= literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/formatter.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/formatter.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ddf8db0491332a80810b6cd2cd8511eb1934a44c GIT binary patch literal 4724 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/lexer.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/lexer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4f6fe9b7a73b7376530ab05809604d9a8a770e35 GIT binary patch literal 38365 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/modeline.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/modeline.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..158063c9a306b984cd1d2bf46f7ce5d4c3d09597 GIT binary patch literal 1563 zcmZV;&rc&&_`R8FJGAAui%Wyai^`^hQjn;L%>rRr5;fR0Tl7%MHq)8cGG#h5J8ufx zW-v8bBgiHYFN-&hyWvmqf?`&ja4_-2!KB(fdC~W#9oXQP%=fQn{#E?(UO>X_?LxsV!q z402&LqJ|&CT%^uPV&g>=QLyUeDmEOFs+ua+H3R#vUtNc&|Ga>RR<(4D0%2syHo-PZ z7G;7}WE#|7z>`uPrL6!OYv5uT|j6UxMf*dSY-$evt zwD85s$M^1MQ@-!Ct|{0cIF0UP?{@ghpDZqAvP-CB+DOHYtmz~byM9hqs*q9j^AuDm$hP^XbzsF3LA16lf0!_ zQw7RXO?xUBrKuo-lvVde{@({SWp)_#D<3t>7@j&cpQ(2&NhnmrVRfg5D{WC>RfeR|H)}6jFIPM%^n{zpp)-(oG zu0hvOh2QX_ly?`b4Fj;vJD1&X`JlSnf-4aCWY8594uUKYfOFXm7t-~F$6YOIWt>_G zxgjUgbqHK8u(LsfM_WCh?^Y`g;sbUs z^)A5+maZgvkwQT=l|sSe=wi@|tn2g=QOv4Ee-mEh%cc8w?q!#3mXTi$KaJ3_D|hzI}x literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/plugin.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/plugin.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..483eb6e00f449da545837ae69c8cc0e49cd34add GIT binary patch literal 2612 zcmd5;%}*Og6rZsTHs;$24pFPJZB-?vU?_@G#Xu^;hl1)rgk32(PPfbMU^c9Gt(oP+ z2%4zs0n|$AsYy@G7190+{Reun8WpKZG#;|d(24t_U+7@_vZcH z?~VOyYikg}xO0D0SN#b6&Oa){Q&vj1KzWKZltLQTJO<8sQXY&nZ_2CrQa-IA)u1(| z8a4mdDCO4zAOl(x$R;faGN?6!Y|ghtT9seGWl(~V%V)C0v{^J~tYmak%zarqf@1P+ z*-&x~CEc_MT~t&Ob=M8DPH1_N#bWLxk8r;lLYS}z!X019TPxJvHY)V2rL7nwHV@Nr z?#=bFXwj@*;*6shW6~<$XA6ilsQ(}blRX;Sc zsGCFrFT`ZJWikmuO7;@rZ#NUMe@(ZSBtWw5%+OT;j>M!}i3xW-K0Q7;lb94ZYQ$D_ zgGGaX@}7ubrv=zc^K#AtLb8qaIi3S&?bJ^P+2*7Z=#<(du1;P1UAs{^ru#7B8l$G@a7Xb?(yB*&W}cEsZZg^6q`S>iMboiTnYN&4rD@mPAz zqRT7?-J3Qa+N@tuRcpnxfrtI7MM-)=QJ0CSrK79FTusOIg*4M`(hnP!l?-9&oSqwy zVNJ8>Kn1!1_hN|V@=hlhQ~7jZXbZ&t5FT~|#AEcb_3}5LKc0H&Z`)q|ZvBN{I&4H8 z;U`-=ThC+LTgCQhArL(b@TrZRjc2{j7mDqXLLgFt%}C{SLGd zfKUbP3H0D1)C+B*v+7c*=lA$2#^~Fy59QI%-Zi|7XChvag3}qFyf--~PtGLg=Hox3xZOx7dA=|?-kf`&k_Q>cVbqjJ)kv>WV3xNRSZ6J$pB z!#AtQJlpv3(GQP`J%fd|!D3*LL-fgUNkDY%`kM+-XCgTtpFB+*dI?fI8=V@?xOWtN z8?47(N2Z1|XCO0tOfSQ(HT(PtR{L?TOZ*lPs7o7N_kp*W(dBjL>%i5!t`tz{sIdw6 T9(8-LbQJX9kAx_3O@#OtoG61W literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/regexopt.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/regexopt.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..75348faa2d88b6ba881f43f061e0e45716f5808d GIT binary patch literal 4081 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/sphinxext.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/sphinxext.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b01e0dc96cb739fcd35a83e2963b73688d678a19 GIT binary patch literal 12102 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/token.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/token.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4d8c062f8371d52b0123f04416fdc29b8d4b505d GIT binary patch literal 8193 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 A=Kufz literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/unistring.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/unistring.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1bc206902731ed76fc6d028641481559e810bce4 GIT binary patch literal 32976 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/util.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/util.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..74c22118b557c8c3f502d51c71ff54bbd2b93a12 GIT binary patch literal 14073 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 DP^k;r literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/cmdline.py b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/cmdline.py new file mode 100644 index 0000000..0a7072e --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/cmdline.py @@ -0,0 +1,668 @@ +""" + pygments.cmdline + ~~~~~~~~~~~~~~~~ + + Command line interface. + + :copyright: Copyright 2006-2024 by the Pygments team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import os +import sys +import shutil +import argparse +from textwrap import dedent + +from pip._vendor.pygments import __version__, highlight +from pip._vendor.pygments.util import ClassNotFound, OptionError, docstring_headline, \ + guess_decode, guess_decode_from_terminal, terminal_encoding, \ + UnclosingTextIOWrapper +from pip._vendor.pygments.lexers import get_all_lexers, get_lexer_by_name, guess_lexer, \ + load_lexer_from_file, get_lexer_for_filename, find_lexer_class_for_filename +from pip._vendor.pygments.lexers.special import TextLexer +from pip._vendor.pygments.formatters.latex import LatexEmbeddedLexer, LatexFormatter +from pip._vendor.pygments.formatters import get_all_formatters, get_formatter_by_name, \ + load_formatter_from_file, get_formatter_for_filename, find_formatter_class +from pip._vendor.pygments.formatters.terminal import TerminalFormatter +from pip._vendor.pygments.formatters.terminal256 import Terminal256Formatter, TerminalTrueColorFormatter +from pip._vendor.pygments.filters import get_all_filters, find_filter_class +from pip._vendor.pygments.styles import get_all_styles, get_style_by_name + + +def _parse_options(o_strs): + opts = {} + if not o_strs: + return opts + for o_str in o_strs: + if not o_str.strip(): + continue + o_args = o_str.split(',') + for o_arg in o_args: + o_arg = o_arg.strip() + try: + o_key, o_val = o_arg.split('=', 1) + o_key = o_key.strip() + o_val = o_val.strip() + except ValueError: + opts[o_arg] = True + else: + opts[o_key] = o_val + return opts + + +def _parse_filters(f_strs): + filters = [] + if not f_strs: + return filters + for f_str in f_strs: + if ':' in f_str: + fname, fopts = f_str.split(':', 1) + filters.append((fname, _parse_options([fopts]))) + else: + filters.append((f_str, {})) + return filters + + +def _print_help(what, name): + try: + if what == 'lexer': + cls = get_lexer_by_name(name) + print(f"Help on the {cls.name} lexer:") + print(dedent(cls.__doc__)) + elif what == 'formatter': + cls = find_formatter_class(name) + print(f"Help on the {cls.name} formatter:") + print(dedent(cls.__doc__)) + elif what == 'filter': + cls = find_filter_class(name) + print(f"Help on the {name} filter:") + print(dedent(cls.__doc__)) + return 0 + except (AttributeError, ValueError): + print(f"{what} not found!", file=sys.stderr) + return 1 + + +def _print_list(what): + if what == 'lexer': + print() + print("Lexers:") + print("~~~~~~~") + + info = [] + for fullname, names, exts, _ in get_all_lexers(): + tup = (', '.join(names)+':', fullname, + exts and '(filenames ' + ', '.join(exts) + ')' or '') + info.append(tup) + info.sort() + for i in info: + print(('* {}\n {} {}').format(*i)) + + elif what == 'formatter': + print() + print("Formatters:") + print("~~~~~~~~~~~") + + info = [] + for cls in get_all_formatters(): + doc = docstring_headline(cls) + tup = (', '.join(cls.aliases) + ':', doc, cls.filenames and + '(filenames ' + ', '.join(cls.filenames) + ')' or '') + info.append(tup) + info.sort() + for i in info: + print(('* {}\n {} {}').format(*i)) + + elif what == 'filter': + print() + print("Filters:") + print("~~~~~~~~") + + for name in get_all_filters(): + cls = find_filter_class(name) + print("* " + name + ':') + print(f" {docstring_headline(cls)}") + + elif what == 'style': + print() + print("Styles:") + print("~~~~~~~") + + for name in get_all_styles(): + cls = get_style_by_name(name) + print("* " + name + ':') + print(f" {docstring_headline(cls)}") + + +def _print_list_as_json(requested_items): + import json + result = {} + if 'lexer' in requested_items: + info = {} + for fullname, names, filenames, mimetypes in get_all_lexers(): + info[fullname] = { + 'aliases': names, + 'filenames': filenames, + 'mimetypes': mimetypes + } + result['lexers'] = info + + if 'formatter' in requested_items: + info = {} + for cls in get_all_formatters(): + doc = docstring_headline(cls) + info[cls.name] = { + 'aliases': cls.aliases, + 'filenames': cls.filenames, + 'doc': doc + } + result['formatters'] = info + + if 'filter' in requested_items: + info = {} + for name in get_all_filters(): + cls = find_filter_class(name) + info[name] = { + 'doc': docstring_headline(cls) + } + result['filters'] = info + + if 'style' in requested_items: + info = {} + for name in get_all_styles(): + cls = get_style_by_name(name) + info[name] = { + 'doc': docstring_headline(cls) + } + result['styles'] = info + + json.dump(result, sys.stdout) + +def main_inner(parser, argns): + if argns.help: + parser.print_help() + return 0 + + if argns.V: + print(f'Pygments version {__version__}, (c) 2006-2024 by Georg Brandl, Matthäus ' + 'Chajdas and contributors.') + return 0 + + def is_only_option(opt): + return not any(v for (k, v) in vars(argns).items() if k != opt) + + # handle ``pygmentize -L`` + if argns.L is not None: + arg_set = set() + for k, v in vars(argns).items(): + if v: + arg_set.add(k) + + arg_set.discard('L') + arg_set.discard('json') + + if arg_set: + parser.print_help(sys.stderr) + return 2 + + # print version + if not argns.json: + main(['', '-V']) + allowed_types = {'lexer', 'formatter', 'filter', 'style'} + largs = [arg.rstrip('s') for arg in argns.L] + if any(arg not in allowed_types for arg in largs): + parser.print_help(sys.stderr) + return 0 + if not largs: + largs = allowed_types + if not argns.json: + for arg in largs: + _print_list(arg) + else: + _print_list_as_json(largs) + return 0 + + # handle ``pygmentize -H`` + if argns.H: + if not is_only_option('H'): + parser.print_help(sys.stderr) + return 2 + what, name = argns.H + if what not in ('lexer', 'formatter', 'filter'): + parser.print_help(sys.stderr) + return 2 + return _print_help(what, name) + + # parse -O options + parsed_opts = _parse_options(argns.O or []) + + # parse -P options + for p_opt in argns.P or []: + try: + name, value = p_opt.split('=', 1) + except ValueError: + parsed_opts[p_opt] = True + else: + parsed_opts[name] = value + + # encodings + inencoding = parsed_opts.get('inencoding', parsed_opts.get('encoding')) + outencoding = parsed_opts.get('outencoding', parsed_opts.get('encoding')) + + # handle ``pygmentize -N`` + if argns.N: + lexer = find_lexer_class_for_filename(argns.N) + if lexer is None: + lexer = TextLexer + + print(lexer.aliases[0]) + return 0 + + # handle ``pygmentize -C`` + if argns.C: + inp = sys.stdin.buffer.read() + try: + lexer = guess_lexer(inp, inencoding=inencoding) + except ClassNotFound: + lexer = TextLexer + + print(lexer.aliases[0]) + return 0 + + # handle ``pygmentize -S`` + S_opt = argns.S + a_opt = argns.a + if S_opt is not None: + f_opt = argns.f + if not f_opt: + parser.print_help(sys.stderr) + return 2 + if argns.l or argns.INPUTFILE: + parser.print_help(sys.stderr) + return 2 + + try: + parsed_opts['style'] = S_opt + fmter = get_formatter_by_name(f_opt, **parsed_opts) + except ClassNotFound as err: + print(err, file=sys.stderr) + return 1 + + print(fmter.get_style_defs(a_opt or '')) + return 0 + + # if no -S is given, -a is not allowed + if argns.a is not None: + parser.print_help(sys.stderr) + return 2 + + # parse -F options + F_opts = _parse_filters(argns.F or []) + + # -x: allow custom (eXternal) lexers and formatters + allow_custom_lexer_formatter = bool(argns.x) + + # select lexer + lexer = None + + # given by name? + lexername = argns.l + if lexername: + # custom lexer, located relative to user's cwd + if allow_custom_lexer_formatter and '.py' in lexername: + try: + filename = None + name = None + if ':' in lexername: + filename, name = lexername.rsplit(':', 1) + + if '.py' in name: + # This can happen on Windows: If the lexername is + # C:\lexer.py -- return to normal load path in that case + name = None + + if filename and name: + lexer = load_lexer_from_file(filename, name, + **parsed_opts) + else: + lexer = load_lexer_from_file(lexername, **parsed_opts) + except ClassNotFound as err: + print('Error:', err, file=sys.stderr) + return 1 + else: + try: + lexer = get_lexer_by_name(lexername, **parsed_opts) + except (OptionError, ClassNotFound) as err: + print('Error:', err, file=sys.stderr) + return 1 + + # read input code + code = None + + if argns.INPUTFILE: + if argns.s: + print('Error: -s option not usable when input file specified', + file=sys.stderr) + return 2 + + infn = argns.INPUTFILE + try: + with open(infn, 'rb') as infp: + code = infp.read() + except Exception as err: + print('Error: cannot read infile:', err, file=sys.stderr) + return 1 + if not inencoding: + code, inencoding = guess_decode(code) + + # do we have to guess the lexer? + if not lexer: + try: + lexer = get_lexer_for_filename(infn, code, **parsed_opts) + except ClassNotFound as err: + if argns.g: + try: + lexer = guess_lexer(code, **parsed_opts) + except ClassNotFound: + lexer = TextLexer(**parsed_opts) + else: + print('Error:', err, file=sys.stderr) + return 1 + except OptionError as err: + print('Error:', err, file=sys.stderr) + return 1 + + elif not argns.s: # treat stdin as full file (-s support is later) + # read code from terminal, always in binary mode since we want to + # decode ourselves and be tolerant with it + code = sys.stdin.buffer.read() # use .buffer to get a binary stream + if not inencoding: + code, inencoding = guess_decode_from_terminal(code, sys.stdin) + # else the lexer will do the decoding + if not lexer: + try: + lexer = guess_lexer(code, **parsed_opts) + except ClassNotFound: + lexer = TextLexer(**parsed_opts) + + else: # -s option needs a lexer with -l + if not lexer: + print('Error: when using -s a lexer has to be selected with -l', + file=sys.stderr) + return 2 + + # process filters + for fname, fopts in F_opts: + try: + lexer.add_filter(fname, **fopts) + except ClassNotFound as err: + print('Error:', err, file=sys.stderr) + return 1 + + # select formatter + outfn = argns.o + fmter = argns.f + if fmter: + # custom formatter, located relative to user's cwd + if allow_custom_lexer_formatter and '.py' in fmter: + try: + filename = None + name = None + if ':' in fmter: + # Same logic as above for custom lexer + filename, name = fmter.rsplit(':', 1) + + if '.py' in name: + name = None + + if filename and name: + fmter = load_formatter_from_file(filename, name, + **parsed_opts) + else: + fmter = load_formatter_from_file(fmter, **parsed_opts) + except ClassNotFound as err: + print('Error:', err, file=sys.stderr) + return 1 + else: + try: + fmter = get_formatter_by_name(fmter, **parsed_opts) + except (OptionError, ClassNotFound) as err: + print('Error:', err, file=sys.stderr) + return 1 + + if outfn: + if not fmter: + try: + fmter = get_formatter_for_filename(outfn, **parsed_opts) + except (OptionError, ClassNotFound) as err: + print('Error:', err, file=sys.stderr) + return 1 + try: + outfile = open(outfn, 'wb') + except Exception as err: + print('Error: cannot open outfile:', err, file=sys.stderr) + return 1 + else: + if not fmter: + if os.environ.get('COLORTERM','') in ('truecolor', '24bit'): + fmter = TerminalTrueColorFormatter(**parsed_opts) + elif '256' in os.environ.get('TERM', ''): + fmter = Terminal256Formatter(**parsed_opts) + else: + fmter = TerminalFormatter(**parsed_opts) + outfile = sys.stdout.buffer + + # determine output encoding if not explicitly selected + if not outencoding: + if outfn: + # output file? use lexer encoding for now (can still be None) + fmter.encoding = inencoding + else: + # else use terminal encoding + fmter.encoding = terminal_encoding(sys.stdout) + + # provide coloring under Windows, if possible + if not outfn and sys.platform in ('win32', 'cygwin') and \ + fmter.name in ('Terminal', 'Terminal256'): # pragma: no cover + # unfortunately colorama doesn't support binary streams on Py3 + outfile = UnclosingTextIOWrapper(outfile, encoding=fmter.encoding) + fmter.encoding = None + try: + import colorama.initialise + except ImportError: + pass + else: + outfile = colorama.initialise.wrap_stream( + outfile, convert=None, strip=None, autoreset=False, wrap=True) + + # When using the LaTeX formatter and the option `escapeinside` is + # specified, we need a special lexer which collects escaped text + # before running the chosen language lexer. + escapeinside = parsed_opts.get('escapeinside', '') + if len(escapeinside) == 2 and isinstance(fmter, LatexFormatter): + left = escapeinside[0] + right = escapeinside[1] + lexer = LatexEmbeddedLexer(left, right, lexer) + + # ... and do it! + if not argns.s: + # process whole input as per normal... + try: + highlight(code, lexer, fmter, outfile) + finally: + if outfn: + outfile.close() + return 0 + else: + # line by line processing of stdin (eg: for 'tail -f')... + try: + while 1: + line = sys.stdin.buffer.readline() + if not line: + break + if not inencoding: + line = guess_decode_from_terminal(line, sys.stdin)[0] + highlight(line, lexer, fmter, outfile) + if hasattr(outfile, 'flush'): + outfile.flush() + return 0 + except KeyboardInterrupt: # pragma: no cover + return 0 + finally: + if outfn: + outfile.close() + + +class HelpFormatter(argparse.HelpFormatter): + def __init__(self, prog, indent_increment=2, max_help_position=16, width=None): + if width is None: + try: + width = shutil.get_terminal_size().columns - 2 + except Exception: + pass + argparse.HelpFormatter.__init__(self, prog, indent_increment, + max_help_position, width) + + +def main(args=sys.argv): + """ + Main command line entry point. + """ + desc = "Highlight an input file and write the result to an output file." + parser = argparse.ArgumentParser(description=desc, add_help=False, + formatter_class=HelpFormatter) + + operation = parser.add_argument_group('Main operation') + lexersel = operation.add_mutually_exclusive_group() + lexersel.add_argument( + '-l', metavar='LEXER', + help='Specify the lexer to use. (Query names with -L.) If not ' + 'given and -g is not present, the lexer is guessed from the filename.') + lexersel.add_argument( + '-g', action='store_true', + help='Guess the lexer from the file contents, or pass through ' + 'as plain text if nothing can be guessed.') + operation.add_argument( + '-F', metavar='FILTER[:options]', action='append', + help='Add a filter to the token stream. (Query names with -L.) ' + 'Filter options are given after a colon if necessary.') + operation.add_argument( + '-f', metavar='FORMATTER', + help='Specify the formatter to use. (Query names with -L.) ' + 'If not given, the formatter is guessed from the output filename, ' + 'and defaults to the terminal formatter if the output is to the ' + 'terminal or an unknown file extension.') + operation.add_argument( + '-O', metavar='OPTION=value[,OPTION=value,...]', action='append', + help='Give options to the lexer and formatter as a comma-separated ' + 'list of key-value pairs. ' + 'Example: `-O bg=light,python=cool`.') + operation.add_argument( + '-P', metavar='OPTION=value', action='append', + help='Give a single option to the lexer and formatter - with this ' + 'you can pass options whose value contains commas and equal signs. ' + 'Example: `-P "heading=Pygments, the Python highlighter"`.') + operation.add_argument( + '-o', metavar='OUTPUTFILE', + help='Where to write the output. Defaults to standard output.') + + operation.add_argument( + 'INPUTFILE', nargs='?', + help='Where to read the input. Defaults to standard input.') + + flags = parser.add_argument_group('Operation flags') + flags.add_argument( + '-v', action='store_true', + help='Print a detailed traceback on unhandled exceptions, which ' + 'is useful for debugging and bug reports.') + flags.add_argument( + '-s', action='store_true', + help='Process lines one at a time until EOF, rather than waiting to ' + 'process the entire file. This only works for stdin, only for lexers ' + 'with no line-spanning constructs, and is intended for streaming ' + 'input such as you get from `tail -f`. ' + 'Example usage: `tail -f sql.log | pygmentize -s -l sql`.') + flags.add_argument( + '-x', action='store_true', + help='Allow custom lexers and formatters to be loaded from a .py file ' + 'relative to the current working directory. For example, ' + '`-l ./customlexer.py -x`. By default, this option expects a file ' + 'with a class named CustomLexer or CustomFormatter; you can also ' + 'specify your own class name with a colon (`-l ./lexer.py:MyLexer`). ' + 'Users should be very careful not to use this option with untrusted ' + 'files, because it will import and run them.') + flags.add_argument('--json', help='Output as JSON. This can ' + 'be only used in conjunction with -L.', + default=False, + action='store_true') + + special_modes_group = parser.add_argument_group( + 'Special modes - do not do any highlighting') + special_modes = special_modes_group.add_mutually_exclusive_group() + special_modes.add_argument( + '-S', metavar='STYLE -f formatter', + help='Print style definitions for STYLE for a formatter ' + 'given with -f. The argument given by -a is formatter ' + 'dependent.') + special_modes.add_argument( + '-L', nargs='*', metavar='WHAT', + help='List lexers, formatters, styles or filters -- ' + 'give additional arguments for the thing(s) you want to list ' + '(e.g. "styles"), or omit them to list everything.') + special_modes.add_argument( + '-N', metavar='FILENAME', + help='Guess and print out a lexer name based solely on the given ' + 'filename. Does not take input or highlight anything. If no specific ' + 'lexer can be determined, "text" is printed.') + special_modes.add_argument( + '-C', action='store_true', + help='Like -N, but print out a lexer name based solely on ' + 'a given content from standard input.') + special_modes.add_argument( + '-H', action='store', nargs=2, metavar=('NAME', 'TYPE'), + help='Print detailed help for the object of type , ' + 'where is one of "lexer", "formatter" or "filter".') + special_modes.add_argument( + '-V', action='store_true', + help='Print the package version.') + special_modes.add_argument( + '-h', '--help', action='store_true', + help='Print this help.') + special_modes_group.add_argument( + '-a', metavar='ARG', + help='Formatter-specific additional argument for the -S (print ' + 'style sheet) mode.') + + argns = parser.parse_args(args[1:]) + + try: + return main_inner(parser, argns) + except BrokenPipeError: + # someone closed our stdout, e.g. by quitting a pager. + return 0 + except Exception: + if argns.v: + print(file=sys.stderr) + print('*' * 65, file=sys.stderr) + print('An unhandled exception occurred while highlighting.', + file=sys.stderr) + print('Please report the whole traceback to the issue tracker at', + file=sys.stderr) + print('.', + file=sys.stderr) + print('*' * 65, file=sys.stderr) + print(file=sys.stderr) + raise + import traceback + info = traceback.format_exception(*sys.exc_info()) + msg = info[-1].strip() + if len(info) >= 3: + # extract relevant file and position info + msg += '\n (f{})'.format(info[-2].split('\n')[0].strip()[1:]) + print(file=sys.stderr) + print('*** Error while highlighting:', file=sys.stderr) + print(msg, file=sys.stderr) + print('*** If this is a bug you want to report, please rerun with -v.', + file=sys.stderr) + return 1 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/console.py b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/console.py new file mode 100644 index 0000000..4c1a062 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/console.py @@ -0,0 +1,70 @@ +""" + pygments.console + ~~~~~~~~~~~~~~~~ + + Format colored console output. + + :copyright: Copyright 2006-2024 by the Pygments team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +esc = "\x1b[" + +codes = {} +codes[""] = "" +codes["reset"] = esc + "39;49;00m" + +codes["bold"] = esc + "01m" +codes["faint"] = esc + "02m" +codes["standout"] = esc + "03m" +codes["underline"] = esc + "04m" +codes["blink"] = esc + "05m" +codes["overline"] = esc + "06m" + +dark_colors = ["black", "red", "green", "yellow", "blue", + "magenta", "cyan", "gray"] +light_colors = ["brightblack", "brightred", "brightgreen", "brightyellow", "brightblue", + "brightmagenta", "brightcyan", "white"] + +x = 30 +for dark, light in zip(dark_colors, light_colors): + codes[dark] = esc + "%im" % x + codes[light] = esc + "%im" % (60 + x) + x += 1 + +del dark, light, x + +codes["white"] = codes["bold"] + + +def reset_color(): + return codes["reset"] + + +def colorize(color_key, text): + return codes[color_key] + text + codes["reset"] + + +def ansiformat(attr, text): + """ + Format ``text`` with a color and/or some attributes:: + + color normal color + *color* bold color + _color_ underlined color + +color+ blinking color + """ + result = [] + if attr[:1] == attr[-1:] == '+': + result.append(codes['blink']) + attr = attr[1:-1] + if attr[:1] == attr[-1:] == '*': + result.append(codes['bold']) + attr = attr[1:-1] + if attr[:1] == attr[-1:] == '_': + result.append(codes['underline']) + attr = attr[1:-1] + result.append(codes[attr]) + result.append(text) + result.append(codes['reset']) + return ''.join(result) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/filter.py b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/filter.py new file mode 100644 index 0000000..aa6f760 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/filter.py @@ -0,0 +1,70 @@ +""" + pygments.filter + ~~~~~~~~~~~~~~~ + + Module that implements the default filter. + + :copyright: Copyright 2006-2024 by the Pygments team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + + +def apply_filters(stream, filters, lexer=None): + """ + Use this method to apply an iterable of filters to + a stream. If lexer is given it's forwarded to the + filter, otherwise the filter receives `None`. + """ + def _apply(filter_, stream): + yield from filter_.filter(lexer, stream) + for filter_ in filters: + stream = _apply(filter_, stream) + return stream + + +def simplefilter(f): + """ + Decorator that converts a function into a filter:: + + @simplefilter + def lowercase(self, lexer, stream, options): + for ttype, value in stream: + yield ttype, value.lower() + """ + return type(f.__name__, (FunctionFilter,), { + '__module__': getattr(f, '__module__'), + '__doc__': f.__doc__, + 'function': f, + }) + + +class Filter: + """ + Default filter. Subclass this class or use the `simplefilter` + decorator to create own filters. + """ + + def __init__(self, **options): + self.options = options + + def filter(self, lexer, stream): + raise NotImplementedError() + + +class FunctionFilter(Filter): + """ + Abstract class used by `simplefilter` to create simple + function filters on the fly. The `simplefilter` decorator + automatically creates subclasses of this class for + functions passed to it. + """ + function = None + + def __init__(self, **options): + if not hasattr(self, 'function'): + raise TypeError(f'{self.__class__.__name__!r} used without bound function') + Filter.__init__(self, **options) + + def filter(self, lexer, stream): + # pylint: disable=not-callable + yield from self.function(lexer, stream, self.options) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/filters/__init__.py b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/filters/__init__.py new file mode 100644 index 0000000..9255ca2 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/filters/__init__.py @@ -0,0 +1,940 @@ +""" + pygments.filters + ~~~~~~~~~~~~~~~~ + + Module containing filter lookup functions and default + filters. + + :copyright: Copyright 2006-2024 by the Pygments team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import re + +from pip._vendor.pygments.token import String, Comment, Keyword, Name, Error, Whitespace, \ + string_to_tokentype +from pip._vendor.pygments.filter import Filter +from pip._vendor.pygments.util import get_list_opt, get_int_opt, get_bool_opt, \ + get_choice_opt, ClassNotFound, OptionError +from pip._vendor.pygments.plugin import find_plugin_filters + + +def find_filter_class(filtername): + """Lookup a filter by name. Return None if not found.""" + if filtername in FILTERS: + return FILTERS[filtername] + for name, cls in find_plugin_filters(): + if name == filtername: + return cls + return None + + +def get_filter_by_name(filtername, **options): + """Return an instantiated filter. + + Options are passed to the filter initializer if wanted. + Raise a ClassNotFound if not found. + """ + cls = find_filter_class(filtername) + if cls: + return cls(**options) + else: + raise ClassNotFound(f'filter {filtername!r} not found') + + +def get_all_filters(): + """Return a generator of all filter names.""" + yield from FILTERS + for name, _ in find_plugin_filters(): + yield name + + +def _replace_special(ttype, value, regex, specialttype, + replacefunc=lambda x: x): + last = 0 + for match in regex.finditer(value): + start, end = match.start(), match.end() + if start != last: + yield ttype, value[last:start] + yield specialttype, replacefunc(value[start:end]) + last = end + if last != len(value): + yield ttype, value[last:] + + +class CodeTagFilter(Filter): + """Highlight special code tags in comments and docstrings. + + Options accepted: + + `codetags` : list of strings + A list of strings that are flagged as code tags. The default is to + highlight ``XXX``, ``TODO``, ``FIXME``, ``BUG`` and ``NOTE``. + + .. versionchanged:: 2.13 + Now recognizes ``FIXME`` by default. + """ + + def __init__(self, **options): + Filter.__init__(self, **options) + tags = get_list_opt(options, 'codetags', + ['XXX', 'TODO', 'FIXME', 'BUG', 'NOTE']) + self.tag_re = re.compile(r'\b({})\b'.format('|'.join([ + re.escape(tag) for tag in tags if tag + ]))) + + def filter(self, lexer, stream): + regex = self.tag_re + for ttype, value in stream: + if ttype in String.Doc or \ + ttype in Comment and \ + ttype not in Comment.Preproc: + yield from _replace_special(ttype, value, regex, Comment.Special) + else: + yield ttype, value + + +class SymbolFilter(Filter): + """Convert mathematical symbols such as \\ in Isabelle + or \\longrightarrow in LaTeX into Unicode characters. + + This is mostly useful for HTML or console output when you want to + approximate the source rendering you'd see in an IDE. + + Options accepted: + + `lang` : string + The symbol language. Must be one of ``'isabelle'`` or + ``'latex'``. The default is ``'isabelle'``. + """ + + latex_symbols = { + '\\alpha' : '\U000003b1', + '\\beta' : '\U000003b2', + '\\gamma' : '\U000003b3', + '\\delta' : '\U000003b4', + '\\varepsilon' : '\U000003b5', + '\\zeta' : '\U000003b6', + '\\eta' : '\U000003b7', + '\\vartheta' : '\U000003b8', + '\\iota' : '\U000003b9', + '\\kappa' : '\U000003ba', + '\\lambda' : '\U000003bb', + '\\mu' : '\U000003bc', + '\\nu' : '\U000003bd', + '\\xi' : '\U000003be', + '\\pi' : '\U000003c0', + '\\varrho' : '\U000003c1', + '\\sigma' : '\U000003c3', + '\\tau' : '\U000003c4', + '\\upsilon' : '\U000003c5', + '\\varphi' : '\U000003c6', + '\\chi' : '\U000003c7', + '\\psi' : '\U000003c8', + '\\omega' : '\U000003c9', + '\\Gamma' : '\U00000393', + '\\Delta' : '\U00000394', + '\\Theta' : '\U00000398', + '\\Lambda' : '\U0000039b', + '\\Xi' : '\U0000039e', + '\\Pi' : '\U000003a0', + '\\Sigma' : '\U000003a3', + '\\Upsilon' : '\U000003a5', + '\\Phi' : '\U000003a6', + '\\Psi' : '\U000003a8', + '\\Omega' : '\U000003a9', + '\\leftarrow' : '\U00002190', + '\\longleftarrow' : '\U000027f5', + '\\rightarrow' : '\U00002192', + '\\longrightarrow' : '\U000027f6', + '\\Leftarrow' : '\U000021d0', + '\\Longleftarrow' : '\U000027f8', + '\\Rightarrow' : '\U000021d2', + '\\Longrightarrow' : '\U000027f9', + '\\leftrightarrow' : '\U00002194', + '\\longleftrightarrow' : '\U000027f7', + '\\Leftrightarrow' : '\U000021d4', + '\\Longleftrightarrow' : '\U000027fa', + '\\mapsto' : '\U000021a6', + '\\longmapsto' : '\U000027fc', + '\\relbar' : '\U00002500', + '\\Relbar' : '\U00002550', + '\\hookleftarrow' : '\U000021a9', + '\\hookrightarrow' : '\U000021aa', + '\\leftharpoondown' : '\U000021bd', + '\\rightharpoondown' : '\U000021c1', + '\\leftharpoonup' : '\U000021bc', + '\\rightharpoonup' : '\U000021c0', + '\\rightleftharpoons' : '\U000021cc', + '\\leadsto' : '\U0000219d', + '\\downharpoonleft' : '\U000021c3', + '\\downharpoonright' : '\U000021c2', + '\\upharpoonleft' : '\U000021bf', + '\\upharpoonright' : '\U000021be', + '\\restriction' : '\U000021be', + '\\uparrow' : '\U00002191', + '\\Uparrow' : '\U000021d1', + '\\downarrow' : '\U00002193', + '\\Downarrow' : '\U000021d3', + '\\updownarrow' : '\U00002195', + '\\Updownarrow' : '\U000021d5', + '\\langle' : '\U000027e8', + '\\rangle' : '\U000027e9', + '\\lceil' : '\U00002308', + '\\rceil' : '\U00002309', + '\\lfloor' : '\U0000230a', + '\\rfloor' : '\U0000230b', + '\\flqq' : '\U000000ab', + '\\frqq' : '\U000000bb', + '\\bot' : '\U000022a5', + '\\top' : '\U000022a4', + '\\wedge' : '\U00002227', + '\\bigwedge' : '\U000022c0', + '\\vee' : '\U00002228', + '\\bigvee' : '\U000022c1', + '\\forall' : '\U00002200', + '\\exists' : '\U00002203', + '\\nexists' : '\U00002204', + '\\neg' : '\U000000ac', + '\\Box' : '\U000025a1', + '\\Diamond' : '\U000025c7', + '\\vdash' : '\U000022a2', + '\\models' : '\U000022a8', + '\\dashv' : '\U000022a3', + '\\surd' : '\U0000221a', + '\\le' : '\U00002264', + '\\ge' : '\U00002265', + '\\ll' : '\U0000226a', + '\\gg' : '\U0000226b', + '\\lesssim' : '\U00002272', + '\\gtrsim' : '\U00002273', + '\\lessapprox' : '\U00002a85', + '\\gtrapprox' : '\U00002a86', + '\\in' : '\U00002208', + '\\notin' : '\U00002209', + '\\subset' : '\U00002282', + '\\supset' : '\U00002283', + '\\subseteq' : '\U00002286', + '\\supseteq' : '\U00002287', + '\\sqsubset' : '\U0000228f', + '\\sqsupset' : '\U00002290', + '\\sqsubseteq' : '\U00002291', + '\\sqsupseteq' : '\U00002292', + '\\cap' : '\U00002229', + '\\bigcap' : '\U000022c2', + '\\cup' : '\U0000222a', + '\\bigcup' : '\U000022c3', + '\\sqcup' : '\U00002294', + '\\bigsqcup' : '\U00002a06', + '\\sqcap' : '\U00002293', + '\\Bigsqcap' : '\U00002a05', + '\\setminus' : '\U00002216', + '\\propto' : '\U0000221d', + '\\uplus' : '\U0000228e', + '\\bigplus' : '\U00002a04', + '\\sim' : '\U0000223c', + '\\doteq' : '\U00002250', + '\\simeq' : '\U00002243', + '\\approx' : '\U00002248', + '\\asymp' : '\U0000224d', + '\\cong' : '\U00002245', + '\\equiv' : '\U00002261', + '\\Join' : '\U000022c8', + '\\bowtie' : '\U00002a1d', + '\\prec' : '\U0000227a', + '\\succ' : '\U0000227b', + '\\preceq' : '\U0000227c', + '\\succeq' : '\U0000227d', + '\\parallel' : '\U00002225', + '\\mid' : '\U000000a6', + '\\pm' : '\U000000b1', + '\\mp' : '\U00002213', + '\\times' : '\U000000d7', + '\\div' : '\U000000f7', + '\\cdot' : '\U000022c5', + '\\star' : '\U000022c6', + '\\circ' : '\U00002218', + '\\dagger' : '\U00002020', + '\\ddagger' : '\U00002021', + '\\lhd' : '\U000022b2', + '\\rhd' : '\U000022b3', + '\\unlhd' : '\U000022b4', + '\\unrhd' : '\U000022b5', + '\\triangleleft' : '\U000025c3', + '\\triangleright' : '\U000025b9', + '\\triangle' : '\U000025b3', + '\\triangleq' : '\U0000225c', + '\\oplus' : '\U00002295', + '\\bigoplus' : '\U00002a01', + '\\otimes' : '\U00002297', + '\\bigotimes' : '\U00002a02', + '\\odot' : '\U00002299', + '\\bigodot' : '\U00002a00', + '\\ominus' : '\U00002296', + '\\oslash' : '\U00002298', + '\\dots' : '\U00002026', + '\\cdots' : '\U000022ef', + '\\sum' : '\U00002211', + '\\prod' : '\U0000220f', + '\\coprod' : '\U00002210', + '\\infty' : '\U0000221e', + '\\int' : '\U0000222b', + '\\oint' : '\U0000222e', + '\\clubsuit' : '\U00002663', + '\\diamondsuit' : '\U00002662', + '\\heartsuit' : '\U00002661', + '\\spadesuit' : '\U00002660', + '\\aleph' : '\U00002135', + '\\emptyset' : '\U00002205', + '\\nabla' : '\U00002207', + '\\partial' : '\U00002202', + '\\flat' : '\U0000266d', + '\\natural' : '\U0000266e', + '\\sharp' : '\U0000266f', + '\\angle' : '\U00002220', + '\\copyright' : '\U000000a9', + '\\textregistered' : '\U000000ae', + '\\textonequarter' : '\U000000bc', + '\\textonehalf' : '\U000000bd', + '\\textthreequarters' : '\U000000be', + '\\textordfeminine' : '\U000000aa', + '\\textordmasculine' : '\U000000ba', + '\\euro' : '\U000020ac', + '\\pounds' : '\U000000a3', + '\\yen' : '\U000000a5', + '\\textcent' : '\U000000a2', + '\\textcurrency' : '\U000000a4', + '\\textdegree' : '\U000000b0', + } + + isabelle_symbols = { + '\\' : '\U0001d7ec', + '\\' : '\U0001d7ed', + '\\' : '\U0001d7ee', + '\\' : '\U0001d7ef', + '\\' : '\U0001d7f0', + '\\' : '\U0001d7f1', + '\\' : '\U0001d7f2', + '\\' : '\U0001d7f3', + '\\' : '\U0001d7f4', + '\\' : '\U0001d7f5', + '\\' : '\U0001d49c', + '\\' : '\U0000212c', + '\\' : '\U0001d49e', + '\\' : '\U0001d49f', + '\\' : '\U00002130', + '\\' : '\U00002131', + '\\' : '\U0001d4a2', + '\\' : '\U0000210b', + '\\' : '\U00002110', + '\\' : '\U0001d4a5', + '\\' : '\U0001d4a6', + '\\' : '\U00002112', + '\\' : '\U00002133', + '\\' : '\U0001d4a9', + '\\' : '\U0001d4aa', + '\\

' : '\U0001d521', + '\\' : '\U0001d522', + '\\' : '\U0001d523', + '\\' : '\U0001d524', + '\\' : '\U0001d525', + '\\' : '\U0001d526', + '\\' : '\U0001d527', + '\\' : '\U0001d528', + '\\' : '\U0001d529', + '\\' : '\U0001d52a', + '\\' : '\U0001d52b', + '\\' : '\U0001d52c', + '\\' : '\U0001d52d', + '\\' : '\U0001d52e', + '\\' : '\U0001d52f', + '\\' : '\U0001d530', + '\\' : '\U0001d531', + '\\' : '\U0001d532', + '\\' : '\U0001d533', + '\\' : '\U0001d534', + '\\' : '\U0001d535', + '\\' : '\U0001d536', + '\\' : '\U0001d537', + '\\' : '\U000003b1', + '\\' : '\U000003b2', + '\\' : '\U000003b3', + '\\' : '\U000003b4', + '\\' : '\U000003b5', + '\\' : '\U000003b6', + '\\' : '\U000003b7', + '\\' : '\U000003b8', + '\\' : '\U000003b9', + '\\' : '\U000003ba', + '\\' : '\U000003bb', + '\\' : '\U000003bc', + '\\' : '\U000003bd', + '\\' : '\U000003be', + '\\' : '\U000003c0', + '\\' : '\U000003c1', + '\\' : '\U000003c3', + '\\' : '\U000003c4', + '\\' : '\U000003c5', + '\\' : '\U000003c6', + '\\' : '\U000003c7', + '\\' : '\U000003c8', + '\\' : '\U000003c9', + '\\' : '\U00000393', + '\\' : '\U00000394', + '\\' : '\U00000398', + '\\' : '\U0000039b', + '\\' : '\U0000039e', + '\\' : '\U000003a0', + '\\' : '\U000003a3', + '\\' : '\U000003a5', + '\\' : '\U000003a6', + '\\' : '\U000003a8', + '\\' : '\U000003a9', + '\\' : '\U0001d539', + '\\' : '\U00002102', + '\\' : '\U00002115', + '\\' : '\U0000211a', + '\\' : '\U0000211d', + '\\' : '\U00002124', + '\\' : '\U00002190', + '\\' : '\U000027f5', + '\\' : '\U00002192', + '\\' : '\U000027f6', + '\\' : '\U000021d0', + '\\' : '\U000027f8', + '\\' : '\U000021d2', + '\\' : '\U000027f9', + '\\' : '\U00002194', + '\\' : '\U000027f7', + '\\' : '\U000021d4', + '\\' : '\U000027fa', + '\\' : '\U000021a6', + '\\' : '\U000027fc', + '\\' : '\U00002500', + '\\' : '\U00002550', + '\\' : '\U000021a9', + '\\' : '\U000021aa', + '\\' : '\U000021bd', + '\\' : '\U000021c1', + '\\' : '\U000021bc', + '\\' : '\U000021c0', + '\\' : '\U000021cc', + '\\' : '\U0000219d', + '\\' : '\U000021c3', + '\\' : '\U000021c2', + '\\' : '\U000021bf', + '\\' : '\U000021be', + '\\' : '\U000021be', + '\\' : '\U00002237', + '\\' : '\U00002191', + '\\' : '\U000021d1', + '\\' : '\U00002193', + '\\' : '\U000021d3', + '\\' : '\U00002195', + '\\' : '\U000021d5', + '\\' : '\U000027e8', + '\\' : '\U000027e9', + '\\' : '\U00002308', + '\\' : '\U00002309', + '\\' : '\U0000230a', + '\\' : '\U0000230b', + '\\' : '\U00002987', + '\\' : '\U00002988', + '\\' : '\U000027e6', + '\\' : '\U000027e7', + '\\' : '\U00002983', + '\\' : '\U00002984', + '\\' : '\U000000ab', + '\\' : '\U000000bb', + '\\' : '\U000022a5', + '\\' : '\U000022a4', + '\\' : '\U00002227', + '\\' : '\U000022c0', + '\\' : '\U00002228', + '\\' : '\U000022c1', + '\\' : '\U00002200', + '\\' : '\U00002203', + '\\' : '\U00002204', + '\\' : '\U000000ac', + '\\' : '\U000025a1', + '\\' : '\U000025c7', + '\\' : '\U000022a2', + '\\' : '\U000022a8', + '\\' : '\U000022a9', + '\\' : '\U000022ab', + '\\' : '\U000022a3', + '\\' : '\U0000221a', + '\\' : '\U00002264', + '\\' : '\U00002265', + '\\' : '\U0000226a', + '\\' : '\U0000226b', + '\\' : '\U00002272', + '\\' : '\U00002273', + '\\' : '\U00002a85', + '\\' : '\U00002a86', + '\\' : '\U00002208', + '\\' : '\U00002209', + '\\' : '\U00002282', + '\\' : '\U00002283', + '\\' : '\U00002286', + '\\' : '\U00002287', + '\\' : '\U0000228f', + '\\' : '\U00002290', + '\\' : '\U00002291', + '\\' : '\U00002292', + '\\' : '\U00002229', + '\\' : '\U000022c2', + '\\' : '\U0000222a', + '\\' : '\U000022c3', + '\\' : '\U00002294', + '\\' : '\U00002a06', + '\\' : '\U00002293', + '\\' : '\U00002a05', + '\\' : '\U00002216', + '\\' : '\U0000221d', + '\\' : '\U0000228e', + '\\' : '\U00002a04', + '\\' : '\U00002260', + '\\' : '\U0000223c', + '\\' : '\U00002250', + '\\' : '\U00002243', + '\\' : '\U00002248', + '\\' : '\U0000224d', + '\\' : '\U00002245', + '\\' : '\U00002323', + '\\' : '\U00002261', + '\\' : '\U00002322', + '\\' : '\U000022c8', + '\\' : '\U00002a1d', + '\\' : '\U0000227a', + '\\' : '\U0000227b', + '\\' : '\U0000227c', + '\\' : '\U0000227d', + '\\' : '\U00002225', + '\\' : '\U000000a6', + '\\' : '\U000000b1', + '\\' : '\U00002213', + '\\' : '\U000000d7', + '\\
' : '\U000000f7', + '\\' : '\U000022c5', + '\\' : '\U000022c6', + '\\' : '\U00002219', + '\\' : '\U00002218', + '\\' : '\U00002020', + '\\' : '\U00002021', + '\\' : '\U000022b2', + '\\' : '\U000022b3', + '\\' : '\U000022b4', + '\\' : '\U000022b5', + '\\' : '\U000025c3', + '\\' : '\U000025b9', + '\\' : '\U000025b3', + '\\' : '\U0000225c', + '\\' : '\U00002295', + '\\' : '\U00002a01', + '\\' : '\U00002297', + '\\' : '\U00002a02', + '\\' : '\U00002299', + '\\' : '\U00002a00', + '\\' : '\U00002296', + '\\' : '\U00002298', + '\\' : '\U00002026', + '\\' : '\U000022ef', + '\\' : '\U00002211', + '\\' : '\U0000220f', + '\\' : '\U00002210', + '\\' : '\U0000221e', + '\\' : '\U0000222b', + '\\' : '\U0000222e', + '\\' : '\U00002663', + '\\' : '\U00002662', + '\\' : '\U00002661', + '\\' : '\U00002660', + '\\' : '\U00002135', + '\\' : '\U00002205', + '\\' : '\U00002207', + '\\' : '\U00002202', + '\\' : '\U0000266d', + '\\' : '\U0000266e', + '\\' : '\U0000266f', + '\\' : '\U00002220', + '\\' : '\U000000a9', + '\\' : '\U000000ae', + '\\' : '\U000000ad', + '\\' : '\U000000af', + '\\' : '\U000000bc', + '\\' : '\U000000bd', + '\\' : '\U000000be', + '\\' : '\U000000aa', + '\\' : '\U000000ba', + '\\
' : '\U000000a7', + '\\' : '\U000000b6', + '\\' : '\U000000a1', + '\\' : '\U000000bf', + '\\' : '\U000020ac', + '\\' : '\U000000a3', + '\\' : '\U000000a5', + '\\' : '\U000000a2', + '\\' : '\U000000a4', + '\\' : '\U000000b0', + '\\' : '\U00002a3f', + '\\' : '\U00002127', + '\\' : '\U000025ca', + '\\' : '\U00002118', + '\\' : '\U00002240', + '\\' : '\U000022c4', + '\\' : '\U000000b4', + '\\' : '\U00000131', + '\\' : '\U000000a8', + '\\' : '\U000000b8', + '\\' : '\U000002dd', + '\\' : '\U000003f5', + '\\' : '\U000023ce', + '\\' : '\U00002039', + '\\' : '\U0000203a', + '\\' : '\U00002302', + '\\<^sub>' : '\U000021e9', + '\\<^sup>' : '\U000021e7', + '\\<^bold>' : '\U00002759', + '\\<^bsub>' : '\U000021d8', + '\\<^esub>' : '\U000021d9', + '\\<^bsup>' : '\U000021d7', + '\\<^esup>' : '\U000021d6', + } + + lang_map = {'isabelle' : isabelle_symbols, 'latex' : latex_symbols} + + def __init__(self, **options): + Filter.__init__(self, **options) + lang = get_choice_opt(options, 'lang', + ['isabelle', 'latex'], 'isabelle') + self.symbols = self.lang_map[lang] + + def filter(self, lexer, stream): + for ttype, value in stream: + if value in self.symbols: + yield ttype, self.symbols[value] + else: + yield ttype, value + + +class KeywordCaseFilter(Filter): + """Convert keywords to lowercase or uppercase or capitalize them, which + means first letter uppercase, rest lowercase. + + This can be useful e.g. if you highlight Pascal code and want to adapt the + code to your styleguide. + + Options accepted: + + `case` : string + The casing to convert keywords to. Must be one of ``'lower'``, + ``'upper'`` or ``'capitalize'``. The default is ``'lower'``. + """ + + def __init__(self, **options): + Filter.__init__(self, **options) + case = get_choice_opt(options, 'case', + ['lower', 'upper', 'capitalize'], 'lower') + self.convert = getattr(str, case) + + def filter(self, lexer, stream): + for ttype, value in stream: + if ttype in Keyword: + yield ttype, self.convert(value) + else: + yield ttype, value + + +class NameHighlightFilter(Filter): + """Highlight a normal Name (and Name.*) token with a different token type. + + Example:: + + filter = NameHighlightFilter( + names=['foo', 'bar', 'baz'], + tokentype=Name.Function, + ) + + This would highlight the names "foo", "bar" and "baz" + as functions. `Name.Function` is the default token type. + + Options accepted: + + `names` : list of strings + A list of names that should be given the different token type. + There is no default. + `tokentype` : TokenType or string + A token type or a string containing a token type name that is + used for highlighting the strings in `names`. The default is + `Name.Function`. + """ + + def __init__(self, **options): + Filter.__init__(self, **options) + self.names = set(get_list_opt(options, 'names', [])) + tokentype = options.get('tokentype') + if tokentype: + self.tokentype = string_to_tokentype(tokentype) + else: + self.tokentype = Name.Function + + def filter(self, lexer, stream): + for ttype, value in stream: + if ttype in Name and value in self.names: + yield self.tokentype, value + else: + yield ttype, value + + +class ErrorToken(Exception): + pass + + +class RaiseOnErrorTokenFilter(Filter): + """Raise an exception when the lexer generates an error token. + + Options accepted: + + `excclass` : Exception class + The exception class to raise. + The default is `pygments.filters.ErrorToken`. + + .. versionadded:: 0.8 + """ + + def __init__(self, **options): + Filter.__init__(self, **options) + self.exception = options.get('excclass', ErrorToken) + try: + # issubclass() will raise TypeError if first argument is not a class + if not issubclass(self.exception, Exception): + raise TypeError + except TypeError: + raise OptionError('excclass option is not an exception class') + + def filter(self, lexer, stream): + for ttype, value in stream: + if ttype is Error: + raise self.exception(value) + yield ttype, value + + +class VisibleWhitespaceFilter(Filter): + """Convert tabs, newlines and/or spaces to visible characters. + + Options accepted: + + `spaces` : string or bool + If this is a one-character string, spaces will be replaces by this string. + If it is another true value, spaces will be replaced by ``·`` (unicode + MIDDLE DOT). If it is a false value, spaces will not be replaced. The + default is ``False``. + `tabs` : string or bool + The same as for `spaces`, but the default replacement character is ``»`` + (unicode RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK). The default value + is ``False``. Note: this will not work if the `tabsize` option for the + lexer is nonzero, as tabs will already have been expanded then. + `tabsize` : int + If tabs are to be replaced by this filter (see the `tabs` option), this + is the total number of characters that a tab should be expanded to. + The default is ``8``. + `newlines` : string or bool + The same as for `spaces`, but the default replacement character is ``¶`` + (unicode PILCROW SIGN). The default value is ``False``. + `wstokentype` : bool + If true, give whitespace the special `Whitespace` token type. This allows + styling the visible whitespace differently (e.g. greyed out), but it can + disrupt background colors. The default is ``True``. + + .. versionadded:: 0.8 + """ + + def __init__(self, **options): + Filter.__init__(self, **options) + for name, default in [('spaces', '·'), + ('tabs', '»'), + ('newlines', '¶')]: + opt = options.get(name, False) + if isinstance(opt, str) and len(opt) == 1: + setattr(self, name, opt) + else: + setattr(self, name, (opt and default or '')) + tabsize = get_int_opt(options, 'tabsize', 8) + if self.tabs: + self.tabs += ' ' * (tabsize - 1) + if self.newlines: + self.newlines += '\n' + self.wstt = get_bool_opt(options, 'wstokentype', True) + + def filter(self, lexer, stream): + if self.wstt: + spaces = self.spaces or ' ' + tabs = self.tabs or '\t' + newlines = self.newlines or '\n' + regex = re.compile(r'\s') + + def replacefunc(wschar): + if wschar == ' ': + return spaces + elif wschar == '\t': + return tabs + elif wschar == '\n': + return newlines + return wschar + + for ttype, value in stream: + yield from _replace_special(ttype, value, regex, Whitespace, + replacefunc) + else: + spaces, tabs, newlines = self.spaces, self.tabs, self.newlines + # simpler processing + for ttype, value in stream: + if spaces: + value = value.replace(' ', spaces) + if tabs: + value = value.replace('\t', tabs) + if newlines: + value = value.replace('\n', newlines) + yield ttype, value + + +class GobbleFilter(Filter): + """Gobbles source code lines (eats initial characters). + + This filter drops the first ``n`` characters off every line of code. This + may be useful when the source code fed to the lexer is indented by a fixed + amount of space that isn't desired in the output. + + Options accepted: + + `n` : int + The number of characters to gobble. + + .. versionadded:: 1.2 + """ + def __init__(self, **options): + Filter.__init__(self, **options) + self.n = get_int_opt(options, 'n', 0) + + def gobble(self, value, left): + if left < len(value): + return value[left:], 0 + else: + return '', left - len(value) + + def filter(self, lexer, stream): + n = self.n + left = n # How many characters left to gobble. + for ttype, value in stream: + # Remove ``left`` tokens from first line, ``n`` from all others. + parts = value.split('\n') + (parts[0], left) = self.gobble(parts[0], left) + for i in range(1, len(parts)): + (parts[i], left) = self.gobble(parts[i], n) + value = '\n'.join(parts) + + if value != '': + yield ttype, value + + +class TokenMergeFilter(Filter): + """Merges consecutive tokens with the same token type in the output + stream of a lexer. + + .. versionadded:: 1.2 + """ + def __init__(self, **options): + Filter.__init__(self, **options) + + def filter(self, lexer, stream): + current_type = None + current_value = None + for ttype, value in stream: + if ttype is current_type: + current_value += value + else: + if current_type is not None: + yield current_type, current_value + current_type = ttype + current_value = value + if current_type is not None: + yield current_type, current_value + + +FILTERS = { + 'codetagify': CodeTagFilter, + 'keywordcase': KeywordCaseFilter, + 'highlight': NameHighlightFilter, + 'raiseonerror': RaiseOnErrorTokenFilter, + 'whitespace': VisibleWhitespaceFilter, + 'gobble': GobbleFilter, + 'tokenmerge': TokenMergeFilter, + 'symbols': SymbolFilter, +} diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/filters/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/filters/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bc691352dcf423d6102c035496bfc1056b023927 GIT binary patch literal 37915 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, + the `arg` is then given by the ``-a`` option. + """ + return '' + + def format(self, tokensource, outfile): + """ + This method must format the tokens from the `tokensource` iterable and + write the formatted version to the file object `outfile`. + + Formatter options can control how exactly the tokens are converted. + """ + if self.encoding: + # wrap the outfile in a StreamWriter + outfile = codecs.lookup(self.encoding)[3](outfile) + return self.format_unencoded(tokensource, outfile) + + # Allow writing Formatter[str] or Formatter[bytes]. That's equivalent to + # Formatter. This helps when using third-party type stubs from typeshed. + def __class_getitem__(cls, name): + return cls diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__init__.py b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__init__.py new file mode 100644 index 0000000..f19e993 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__init__.py @@ -0,0 +1,157 @@ +""" + pygments.formatters + ~~~~~~~~~~~~~~~~~~~ + + Pygments formatters. + + :copyright: Copyright 2006-2024 by the Pygments team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import re +import sys +import types +import fnmatch +from os.path import basename + +from pip._vendor.pygments.formatters._mapping import FORMATTERS +from pip._vendor.pygments.plugin import find_plugin_formatters +from pip._vendor.pygments.util import ClassNotFound + +__all__ = ['get_formatter_by_name', 'get_formatter_for_filename', + 'get_all_formatters', 'load_formatter_from_file'] + list(FORMATTERS) + +_formatter_cache = {} # classes by name +_pattern_cache = {} + + +def _fn_matches(fn, glob): + """Return whether the supplied file name fn matches pattern filename.""" + if glob not in _pattern_cache: + pattern = _pattern_cache[glob] = re.compile(fnmatch.translate(glob)) + return pattern.match(fn) + return _pattern_cache[glob].match(fn) + + +def _load_formatters(module_name): + """Load a formatter (and all others in the module too).""" + mod = __import__(module_name, None, None, ['__all__']) + for formatter_name in mod.__all__: + cls = getattr(mod, formatter_name) + _formatter_cache[cls.name] = cls + + +def get_all_formatters(): + """Return a generator for all formatter classes.""" + # NB: this returns formatter classes, not info like get_all_lexers(). + for info in FORMATTERS.values(): + if info[1] not in _formatter_cache: + _load_formatters(info[0]) + yield _formatter_cache[info[1]] + for _, formatter in find_plugin_formatters(): + yield formatter + + +def find_formatter_class(alias): + """Lookup a formatter by alias. + + Returns None if not found. + """ + for module_name, name, aliases, _, _ in FORMATTERS.values(): + if alias in aliases: + if name not in _formatter_cache: + _load_formatters(module_name) + return _formatter_cache[name] + for _, cls in find_plugin_formatters(): + if alias in cls.aliases: + return cls + + +def get_formatter_by_name(_alias, **options): + """ + Return an instance of a :class:`.Formatter` subclass that has `alias` in its + aliases list. The formatter is given the `options` at its instantiation. + + Will raise :exc:`pygments.util.ClassNotFound` if no formatter with that + alias is found. + """ + cls = find_formatter_class(_alias) + if cls is None: + raise ClassNotFound(f"no formatter found for name {_alias!r}") + return cls(**options) + + +def load_formatter_from_file(filename, formattername="CustomFormatter", **options): + """ + Return a `Formatter` subclass instance loaded from the provided file, relative + to the current directory. + + The file is expected to contain a Formatter class named ``formattername`` + (by default, CustomFormatter). Users should be very careful with the input, because + this method is equivalent to running ``eval()`` on the input file. The formatter is + given the `options` at its instantiation. + + :exc:`pygments.util.ClassNotFound` is raised if there are any errors loading + the formatter. + + .. versionadded:: 2.2 + """ + try: + # This empty dict will contain the namespace for the exec'd file + custom_namespace = {} + with open(filename, 'rb') as f: + exec(f.read(), custom_namespace) + # Retrieve the class `formattername` from that namespace + if formattername not in custom_namespace: + raise ClassNotFound(f'no valid {formattername} class found in {filename}') + formatter_class = custom_namespace[formattername] + # And finally instantiate it with the options + return formatter_class(**options) + except OSError as err: + raise ClassNotFound(f'cannot read {filename}: {err}') + except ClassNotFound: + raise + except Exception as err: + raise ClassNotFound(f'error when loading custom formatter: {err}') + + +def get_formatter_for_filename(fn, **options): + """ + Return a :class:`.Formatter` subclass instance that has a filename pattern + matching `fn`. The formatter is given the `options` at its instantiation. + + Will raise :exc:`pygments.util.ClassNotFound` if no formatter for that filename + is found. + """ + fn = basename(fn) + for modname, name, _, filenames, _ in FORMATTERS.values(): + for filename in filenames: + if _fn_matches(fn, filename): + if name not in _formatter_cache: + _load_formatters(modname) + return _formatter_cache[name](**options) + for _name, cls in find_plugin_formatters(): + for filename in cls.filenames: + if _fn_matches(fn, filename): + return cls(**options) + raise ClassNotFound(f"no formatter found for file name {fn!r}") + + +class _automodule(types.ModuleType): + """Automatically import formatters.""" + + def __getattr__(self, name): + info = FORMATTERS.get(name) + if info: + _load_formatters(info[0]) + cls = _formatter_cache[info[1]] + setattr(self, name, cls) + return cls + raise AttributeError(name) + + +oldmod = sys.modules[__name__] +newmod = _automodule(__name__) +newmod.__dict__.update(oldmod.__dict__) +sys.modules[__name__] = newmod +del newmod.newmod, newmod.oldmod, newmod.sys, newmod.types diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dbb9c93086f30ee1122d1f8f87eecd8f589afb4c GIT binary patch literal 6906 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 a0X1(iu9b_KXEP(Y{kh;q?7cWa$v*&S)4WOm literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8baa7cf5ab8509cb9b45b76341ef40a36088eacc GIT binary patch literal 4219 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 W9#{zc!=GSTw5a?D|9M%*+Ia literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/groff.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/groff.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d10f29d579ebb4f2b7b646a66dcc8547c71437ad GIT binary patch literal 7297 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 D-B@SN literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/html.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/html.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dcb2462d8517498aa6c1c8a78fa28ba1775d5f96 GIT binary patch literal 41030 zcmd753wT@CogauN34$O9zTf2K`ymn(CCZX0k~Sq$Z^^PGN49K-1bIOU5(&^3peVv% zqVZ&>lt*2Wws%A&_L|;iKT~zOW;$($`L^vS$?U{!r!62TLm1KQC_8DtX21P*Dan~; zJo9z;_dn-801&dAnXljWN<6stp7;Np|MUFMx&J07$Ew41;*~zni@&SW{RKTJSGIif z*s0g)Zt6tcd7Y>i4U_uwdiHBLZ(zU1^G5b-V$a4&^Hj$93_YbaO=eD6&Rf{Mc`|Ft zdfqyfeLj22cHYL`WlZKw+0Waja?j^ZInF!ux-4Ep-uXN+b3%W=~>G=w=?0ls`cSt9ee@iE3x-B0YsU?W5nlsev-1!YU$&9`j&gZ?XyZ*|o z?uzkc-K@T~BKYsE0y!Y9m{Xar0Tb&gs zUVinsXY^ISC*bZthD)vqxBt~?&vfT7;zXa+sm!rX%oBNzbDO^AKFsJ;=_z(SNOfxiOk8giXR@ywr^)f=313S;RaEc%lkCe_ndOD^DXy;v^sN4XOA7dBJ%I~&GLQKteUhJAB}hdG;~BH= zQP23CRE>vi`17|TxT=d~+BPyvBAF%28TT@4R(5UF?~K&%TpPMq-xJF%T(CXJ&0l=+ z+8bd@xm1D->HGOz#N5;cR2W=LoJxqJE2L9;Gp`Tn(IY*2q@Ty{)lL!p6OCm^Mg0pI zC`63zq6s%C*Zgl(&sF{P&XAs$$l<1o>pOn=|Ke&jN|`7-ZUjcfGp1b<=nY|GATT%W zj+@85t||Pu=*LeZ3aZ2*=@=#)WXXodCS88N)Pm?8`16kkFGo*+>Nc=gv0kgxl+ufG{FaEtO*RUI+xH{XL!P z40rmZiOzoOSEY7N>v2xoL}A7&x+O*rLFELQ>#Jp-OlY@ot;A`>xjbEQ7_Pm+1Xj= z>`vB&v!@w?c6a(gO2-0DF(B6UTYGCeI{w>(L`Mf&M%|?!w@d6tpLzqHz@)psv4#D% z`g=S13yPWo!vJ^!(;e>DXFQkt>c)KD0H$OIO~*Pxe(I|uy2zlgPZ+!4lKk#KUt^2g zJLVHX1Y7-p2MS{&AW%*@!t*%}F)kp9D zKOjwdyq5&YJ=s^s0OG&kb_eQ&3zB=hudcBL5F7VQx&hIxaQq683p#o`Ww^4@>bH)8 zHmDa76uKUl1Hdq7hP@Su}~}3B&meF$0oTrkIJ)B3ck;iCGA( zq7`Ab*eKc{mD%u{gWnwd+VN`_a}k>>IuJVCd1BtTbRY9Nb?5W(oS*PqfM>{bYJ4G+ z?TW-A#etQ0E|RzYg4zSu8UlJFx|eXsgsnK_6x z3H1n~fPA%LEy6mn4q?4mkFY^(K-f5!-P$CPH0}By!K^TK1%Znr$zUvl7 zMtUI?c>702gn(ED$&dpM6XgX_1q-`GfD8C0 zAdxagqZEd|vFN@!5~75bzy%NV50B&z9Jt__6rGGpw5oNh+34mCLG<{iCtY(wpU|S- z_6g0+t-`ZHvlk#~7JBd~%rgqDWo9$4E2-2Sy`3~26W)PQFb1MzOXwj1E?tof9~3Yg zLlU3^(SE{`q_~r=gEMvg<367p*)r;qT6+>Ir%ID@P-)YUd*lpBNuSbmbVTY$Kw>?9 z2|M_3w_x@`At1?Kz?22rVURpi(~|EpCex%#@&x99S*)%B2qOM~;2X!U7fOVJP}A-) z&$tI!XGq`RsB>X*m?cti2gOdgF1abz?`FmELe%+%{4In77|yCOI6x@EQ$NyZ$jMnX zr)up2^jSuX{BDS=5c>q;P=aS%EsO{Wy;GV+RZn=J@5qolcfsuyMuIDgDCgx z1-Y#0xxfXVw}W+HM40l4Gk_3l)~UHuM|j;JzJPH66p>Fe^oo}^?sf%cB=C?3Bm|z25iiR(QSW=OPc5d2|z>KXqL!< zJ8~FOp{l2kKmGuJn{4}ndTw&7AfI!HY!CH|zU$mKmsVzYf za06AQ045J*1pLQ6R}$s{7lWPvC5{OiptQ-6GCr>~gA6dxvMr1^lGszOho{0l;@~)QR zl3>ze;KfuSIhU{*)DB_=vxb4H5%&Z5C0XS3L+0SZZV&1>h^dFF6^1p!_>@}uS(4*q zl#|U~G$ZAabqRHpybjIg%nOv?>2{*63U^ZrA{iM*Hzo>#Bq$lav?)vq<3xZE5b)xy zBi<4Kz_<*{QZdpa_%E=j23o6-ESMOHO;QikrlhUAxj6v_j3#Rp(_H3^7hOlm?FwO3 zXfR>4OE^P{vf!T?<$}8kWVPavk!Bh2tTH}Me6}z_+UpbCq5rGpT;{TcwYnJR;w zCK}DpL@kQRL5c~Nq$F9&7r-8vbzT#O8AtT`0tC!N3f?Y|rsVOm+zjH%Y{rOFdI^&M z6bb`ZQTsvs9TMLJ=J&M6JqCgYp@bL+*^wb1k}TpKliV(JNtw8QPtZ;36l^Dui(JB} zhx09(X6m@5K@K*uoUm%pIm4>K4C4sM3;>MNqPeh7L!g2#g{dh8I1A(=51YJmkS^!g z+Y4%cm=NRlO@V%n6Mq2O&O*Q;(;?646pqk@21v%xCzXW|EEA{sNMd7U)F<4f`GGET z>49FLKg6i%me{hwsyY;rO#`*cY-Op9K+lK{?=x4~2!IdAJ?oHAFrldw9lSZ;xmDo9=Q!DAh)FvLx2(i{w zPFZARMI;w+*!siPmL`lG7xehp(16LEpo*ZoUWUp`x-}^*&|bGY_o`VFTSAr5NTN5* zO!YyFneL*f&AfGLr&$^%WhNHK#15B+T{N3m!{mXVo}BR~){xv~*&IL($3^QV66qnB z$Y_)bN~LuPW5uyn8>}N7nQ6>;6aymlPHq2}3>qIR)~yjt)308*#yg>#Bu|8dGO2Ir z#-*!EriBW9RRN3X!bT=hn^V}4OmnsQjypz-nLfny7;vUU6eZnyTV93HSyD)+c z4CnO_^=64gABY!GK&}!3fgv-F`hAl#0gbVdM#hJc^1+J4R5V5Xz;uLc&(NHd5t%d* z)>DtBV4{(!quSYoQqTq7A`mn*RAGSQBzrLRK^|SQiZXbRv^NVi97buiJXRHe!gvzt zR4{b&X(?;L6!8?4c_x8NCG$YF8o*BDZORy^3{m5StQnm5aj0RmdD{qNYHi}EjPNFMhA$7qbN-M5hm7etp%#x>x#%Zi|3B2CV z0m-FJhU6D~D2%um872u;7Zh&@nD~z=kI0xD>z`ql*CRf+5e#Oe3)G zplwrFDJHWD@kq6oqp&~%n&34O)9N5N5E5xU=TZfbpEohF(TsLtjMc)hV(y;cD`m36 znM_X@XOo3lJ^`4#0UIDV9;&1jX00&4(B^f|0&`W?3evx)O_8{X2pvSLNo2{7z{)K&)5vaD1wfx#8bm~R>rtTM!1ra*zU8S9153Y?MRxj?Xr=W7Xs-v3FrV7 zFeqVGx3!Vj(9_l?Prih*TV%U+Yhn>-9M-hF9zPr|Xs%J|D%2A#%xrK-%Vs=L^gsfk zA)@Bf zFdakk92ucjb?{0?G^8Ych}jHN7{Z1*a_!o&t1&@$ zQB9a?*$eGNZ4_AxnRy7~K=L1@1KA?4gpq_f@ul23F^^hsN*7ddBcWM| z5`I?#=#=u@)7n63G{mLoGhTSBbb)|+Aq{an^nx0(j&iUO5=_H32i;%piqbtA3D@LP zOW&>_c$$K_dPji998!DD)dQ^WF!tt}#0pQ6)U!RIn_eIJy-YB>LAs_Wh|aMJGB$U2 zfgOiz6EfeR257~AcmZM5)@+f>WfhRGk_fJufDdJQ$O@<~yn#T`0+nozP>Y%+K?0Rw z9s;VMA*$G@l=+H#qK6_>+ofE)S_GHanZb(LSylTg1LbS2Nq|Z*htPyiHwP6lghpMq zufx=*D5toxlyc!wth&1`Rr3CzLq?HjEs;PsT$#HZ9RE7qZE;d@SGzT-m96|LGkzK%K z3>2C~W6Jq7VC+o*23bbZ3Sl54{}n(1DH4580|%n5ze(50XbDb-p0gecmpv}wqU*BD zKPGvm6{ko7+E%RSaw=HChlK(A36dxiB_JQD15Jq){g!xfudAQB12OJJT185*TWyh} zN0f>flVMNFR8+_>l|+@W-4Wea7Kee*I6XdN(A*t zRsfk35QD7n;@N{8d%l$EYD0?>XQWAvsv0y06k;diFd+|MO5&7iidD=>G_kPwr?fa> z#Si$!n=S|gm*Ee~6cM;AdblB*jGH5kEi_iGeu(k7XKr_R;3JP`sL^=T%8?Z*Rvi!| znFR4QC2A{%_adz`j?{DGUWZI1cw4_BXlT;VY)Jzas4-0OR$<^`= zg(bWr)~EsU9AP5Oc_zwl;ddNTm}xQqDHX(VV3mXjBA`pwtvcHWIp*4L)qJ6u^o}sK@~cPQwaF_WP1ClgrpzlTkV)#;OE2KakZa ziBD)Wi$MEhAIMrBFwZW;ivTOhj@X5RlP1R@6x9xIqF$HRv6X5snvdHdkf_0T-6jL}z6x zmRlbA$l=+`M^?@>CAcO?Op_I5j4&G`Ho9Q5otO=%hs_1b!8=ARXN_Z2Wz-FTq4j|G zIGH$EozxT(Q$WKoZ=jcvk1k5(sxnA0Og&@Fq$dmatUQ?>^NtXg=k>8_$ejq*hJY~b z^ZPwyY6IA46j+5StkrdVRv>wkDAe;TV4)ZZM&!{X-zUDx#_fw39Ga%!CGv6zH6n3E z8EjmhF>uCUm?@+>nkZ-tnoH~VUuo$+)r)|ur3XNcle}13lAho`#yY9+esqoj1cJ`w zIK0Q1$6ve91{*ZZD)rZI95`Cv>HcrX=;49I)MML`EYnRQZ;w zDGyx%VH-RMNuAr;Jc{R?phj*fBB6hsatB!&rWkRG!wh5u)M*7xwPx{o&X9!7F;)br zlrAs;mA0}HlQ9G62D>fsLzQ)-`8=mG-3J&l5(T4*l?l)3W&(+mU8eXFBh7w7-#TiU zqE&G3O_>-lzXjC`p^nWr7~{}OPOZ^t*lK9)R&|;n@e{HX!+bA93weovkv|4NM(kL< z3{H5|usMNF(^$k!lr3%|Y7)$7W1H22X7)QKyFN3IXxef@F3peM&G;&NX2$g%T}c03 z{eQ35(E5EQ{8jgtFMSO={b3)UK?wWzjgY z>o+RPnzk&PQdZIkWG9V4j*{j#s?V0TKKtLQtemuEsk7lXYL`82Sq`OLNpQ$bf&*>C zV;68kH=M6LCFO7=I1FH+l#bwF6ByJ zu96$Aq|I~edII+3qrEcrVCS1bEVzUgNfxmXc}tbN-n@_j?~0P%Ws1d#&w-sv>cB4L z4)|Uo7Ad%#(5eb0#S?O2dvBUtDg>X93mbydBZ((qX?mM4u9ZBAs@6QEQfRw__J zpKG3yx=Nd2NG&`ib#+qeS|xSTtg1UDurN({DP z8}&MD!9J*N!LB_S&)}NP!FU!qroqbO_Q$i?4L7Dp0`kW#iX%@vOI>n`XW=Dx>WF8l z{vGj5yd`5wJa3DqTiik>Ef#4@G)2WNiuEOKA?`~eNIY+gnjSn&(sLa%mDRyQ#rFAf zH*ZMcSPe_^^u{wYK_QCPp_xRXR9`2^?%&RMCP^7syNYMcO%FB^0oAE5l%PcJMoFsE=+@h=iwzf&MBQ|as z#uji-V0bv5i}eqJjAz{I#+FMF+gE9$i$v^K>Y%_$K|KYX6l|w}_Nq!mC!}r)h)zh) zP_UbVJrwLk5HF)Yv9o=?I>J#YtL=Q-SJtFw*{ifsw{mUQ6DF zr95IOU+#`rwyo^GYuOenD%&V(jTE)6Hhj`{yDeI@Yr%BgdcU}CW%uggHFvbQ7th)E z%NkcER^M13ik9uivprT(_rbnf`&Q=HMxzyb7fkmorLoe=jnei=Y5VHAPhPqG%6j>o zSE3y+L`zR2eNL>bYNMHFU5`?G>l z0C7{NZ+Kq+Sf?*JrN@2VDg7_XYd+X^Yuk$W(bR`i(emzv!RyB!Wwm6@d8aX2d6@UT zs^NoIZoRTvv)&M`dX}Y0H^gPa2Nky}R$f`FiPI?#PSIzM!c8N7zwnb_^e3i<~)-BISas5amm`lzsJc`c^~m#nW6{C!$JzPux<#Y@K8SV@e@eRE)EUc;khCC$lLO{;-zv1b$v+xE|)8B!yHxRvd~XEi17(YLcb`e+8#(q z{vIzQc+zAZyGQuWu{LxwAQzk!Zf!Py7K z;PVM1q`KU46Dso~ebN{`X>8(pfe(*SdKGPF$0d2sjv3M%;B{$TZ& z4UgM@j|S)r3dZ3Z_WTWdZNy%?(ipY3EEr?{Nf6u}J;7xAfd;NFqt(zG-N5NZji=$x+KTIJ#QoM&6*>K`F^}0v{ zo^mA(vEgdlmkeu4PI~+bCF-xYsY8n6Gk|nm2}8P5GJL%PXkFJECw>KXd|ySl2^Nt*BHs8(aLLI$cWhs z7rfe7602>D6gA2Ww=r6@9i$QCSai)xgIN4lXgNP@sn~ip2?;<9Cu#10vJr&YCF(u; zD|*7MVZ`vuqr)4VH!`eZB`{C5cPOcJI!Nq4)ahPDs(ItQ329VKMoXi~<@08oZ;}x* zi3U2^L=r+7qVZz3mQuM3XnMVzR*~qH-yl-3l1!{5GfFb6?=sYPnd&=>`Yua-XH{E~ z{nS>lv`X#DuUe8#Eh*=zC9$+h3CgcrQiflD{dUNV^I43Ji?U-v?71?fVNBq}d7xfgamFJ!8Q_7Rk`0 z2i947hm2Y5xD%2WgOzm7Mh6MkShj(KZx25Th2oGfb991L7%bL2rmz=^?K5Oe$QXrt zy<0*&`|T0Brmw(^Jn0cx6My+%=l~jvM0Pi66oIT>?O-j6o7oQ|s__hNm1XDl#En>w zZp~y2Fm4R&!1+I8JN%p#ny}nF9yiefqcnvQ{bXrmoK+EdzlIk&@SPE$TcFEgOtD1{ckg=-^u+Bnp=~BMv8jbNH=q zus59%M<;)C>~5~WUhR%JcJo(9-ufnc)3s5yCsMZOpBLXT-Ff+kxzW9+qGc~c94{mn zm6+_yWeeF4ECq_bx>4~=q~e)q z#h!bXy|KjCdm|Nl*XyGd{r4=-CPj2dD!SLsKs~)@>3NV_aAWS;+;T-Uw=ryK+$!`E z(_)kUC>rsVgx<6&M7kvn1tA7?H;gw-H_SIO#>^ACF~e&G3iEvxHP4&o&0vZ~$r3V2 z8KDd?5@X0TZdx*2FEZ)oGZAY7o6ZPjUQ9FXl{$cInW!fNwV*D!o(9xoB9@CXz~~J? zNR6$32gjC$Ob87Lra`lUe4t2|Rn z@pcyT?_|)3&FH}lVP5EL6Mjiz2;Q`HVrH_*L2@(Kk)%n)#m#UnnDWE)f$fNK6L$Vd ztyx?}BIN)ln=y4u8pZ=-44hq9<2Hk4e!t6*I+*GMp}+3F6-R6;p~q%`!}3}5$E7N=fS@;oARwccOHy5 z+7^wGqBb0d_TtLWXSw-HGm!7>1&c$=J6FtiZA~#J34B?(k9EkfX~o@*>}%QAa~`75 zU4Lmd=Ao2sDy3-IyzE~YdT4}LxH$H^Z!AnLcdwY2XICb^C$8=K_|kgqdfloo+|j>2 zcGtE)=Io|o?T>XR0mV9s7Hog@t1{H_SHH63m7fH)@0ac`vi`8Kb$^vLiQuck<-h#9 z&3(+V)N3Ax{H0U1(}|<=Ca@ZaPtxniLv2dA{O*wPx5h{a4J0mmsY^{-^2<7@i4Nhr zs4fd>ad?|1hgKp9gY>5z;0K&DUsM-qw32`uri;Mg)Qj*-I}Q<8oS~S=6=OfJ)bv{| zPb}5^#8NX9ybPI?vXozxX$B+9l*P!eqgBkh8!UTc{*5;hT;Z8i`Nq63KOd~ZPg0yF z^dUNKyf8W0YL&i8MUe~^cOefN ztaQs~O%85!4@SBN|LAO_`)H*8*rx-L`je5WlZ)1vE$_zhYsX`byl{bYqhMF0VAp4b z<;y$XIl5w5ZF_7q6y|?!H09WVzP7?}c1>dX9UBFEBL#bZ&~&Hhf9?3RG+J=_bE5%C zEezAQ>Wjo87&}|R4G!%k+Y9beFCzQz8|fs@bVw@4l4b}1re1Qa8L?>)UyjZAve*eT zot?=hZII|X@d<-4A1n%pPFYY9oL=&`o1~~*GT*Bacu|~~PTp5S2}=?aI<*KKhiN5V z!{=1oo-7T;i?wII;K9?uTE{GOG$-YwTe;2sGG3(G35bA&F?++x*^S0Mk;XmYhP~?rVOw9!UcDUHsM!&z*%7YZxwbQG+a0qvu812= z1CgeIaO3_v^%O-I74NE|sDCpIg-jhnw` zgqWkhTK}ZEaT!(wDVMBm>BpZiShmL*=k)|4eKBMxIWeak|c2IhnLBwN^t>$!O+$>W6TA)@>ETL}IKJ&9@(EED`J*?H1d^w*5A zY}7*F!D*~%^%mF>>9}T)X?8ZN(hFXOLSnK0SZ{*hlTOFcv<%+bchMG!kz4_HK|{NM zGk-Jaygjcd&EZw6iAgNba&ZP26J$&foc(?p5lARk`HUiZ7;N84)HE5%*$ba*_z?9w zxg0b^GwT?#{raj7(nhSfZ27>FXVDnTFI+hAvyuwjISOuCm#oVN?pAiJ99XUY@W|cD zooo4P{zyg7PaXRYt7X)r)hxY)V)-~&J#bvc);FA1f#s}# z6gQEcf<7_CP)WH&24kg5&+#r1^GGN4YhCK2E|3uoU5I7d7xu*ps#Xd=s{F7rT+ng1 z;J{k_n)nA(-=B)?IB>V%$Q^0n!2Rr^#j*Ex-UEp&EWshNgTE*!SvJ12cVX~zQ$|)D zP5{Z-%8^=Ght|c5eEG;5WurzsWG-C2R zb%LfQFg&+@Yt2ILXQhWQQznRQnt zzDnT1tmfPD8V8xSq-zM0bVO+hZ&Ig7G7&vP(CtAoKo@IBn9duH_K2e$=M0n8=2p)} z#r{aeewe>wd8Nxm%bDSto#F1m@Xn#|&{R0r8@71=8yXVn1N20JWmzKNWL71^v>{zo zDr}|yX$w5xCU~aWuc<7!01PWtFyZLsG;oFT(VYO-qmhcEPls#b#3kfnQ=N!n@*r6wL-GbfT5+!rD(?#50ucK1nIhk*2T@Eb8w=MTa*Kb;~Cul z;5O&^aWmU9p2YQ!5_GFl=s>d90@>aDyO9nyN02J_doSM0u7_dp#yqTtC6zZrOQDs) zk4}7eB3iN|?AQ@2D81Rc)XQiuJ6M~~Rf3^%kv3G1zsIG3?lGPIi6mrEFZF9sPDdot z!3R)PYD)N3pep60kDoVsML7Ey(&=ij4w%T2A?lefWnk`K33?kG(9}7Twv}X$Nx7bq zLp8E%*`Ossqopf-50qI*PD@WIy@Z#O7-}{Y$%gVv6XW>3|G9wbk`^+GW-;S?nTjsB zi*#M{Mb(W=%No9iCId&Jo+GnE#(Qq8vCd83(xvMlagC=`9rB~%3JL> zJ&f?ST}z|feJ@+-2h~4r_&xniy+GT-(cr4v#^rAj21zp{8#+TAaGi%Q_4jv%I7mgYbfJlgYr)MCFv@Zp}B>= ziGI#!d?RC4uhg+ycm2vgGU96^IVYLMFA?qpzs}C85DvJ!bUqBe-+^@$@Bn42H+iG6 zt)uO-YrAZ?#;!e_VFt@HPSNy3T7X*_tj%o6oDAY>Hhh%9#Jt?}vqAGrV7y}wWTxAw zIG)8=3t4+<@Gts_E zmX~H7y5nBzyHJ~>)ac?zuS91H}A&mwb>i<*XEbc ze(>t8SMTMvJ*ckxVDi@FQud}PJFhcV)AT{;R%r3?XBG7;SJw0&zOgoTw|Va`s@ub* z?f2^%K5G83`J?s^+rKA$GJAXWlW*Ss=K7Ur=iylA&QC(OLywL6`o6_un~uz!;`=3K zH)oe-Z+>Ix8!MOYmF!q=*yuTRx98OTva01vt2@_Aep)tg=X9*J`~%A^%e~sJSY5|z zV54(?q;vnBXQG`)!?njA8ufL@^`GnXWheCi*{Cbuuiv!m3JUKPx8E-=hmuhKVR@{+ z`J>(sdt(hP#8E#t8%lOQG#X2GZt9E$-7tsdbi z;)~5nT~^r_elnH4Ibb?$)&DSap#ETu?nm499;(y*xS{P(vGI@W7To_)@xWfh|8cJV zu*LMpj$FF0*?y?N_>){C?thZ6r~3kSUu-^9llha1Ol12>UDjc<@h97g4(p7c>dd(R z)J*jxS%gV}XY$5=P*g5&XrDt-q$yH2VBgh4*#;M5ZUk7v0N=;T1r%#gA;cQes?X~B z0w`h)bMhsrG3A1tSCs%0%m%Qh5=}%6pyLYXQ-0?&L6=qft`#^>oHUKycRma6(^!dN z62P~q5a-a!Q10ffc(3vapav4g--*5SCHQxvWK#W zpNe{tm*#Ur78ok<-7LJfB)oToa;1D2?J`65aRa>v)UzeKXbM@8(mZbD@4RNw9Lfwr z^+dc)Y6v-`Jdq4?X(Sb>i<$2m=kvU!EJeB2E9Fj2k%@AQq6KLUV%B_KC{M})@5)1b zcF2s-_P!bQ<)o8rLW$!ZgmES3VvSP1_8ZDkM>Aiv&ljM@f)=aX0RrU4mnMeI4hMzv z1^D_HeU3=wwMuRst!d@IZwwW%)GQ3;v-?5{6?s7{;*t#%Ys1AxEw^%~;DVaISWaKU zf9G_JGndMoxgYtyFgCV{UzGIX^C;}w9QBRAD(z4(?#P_SoytkNj9XyxWm;lu zAvcHp5xupEGgDJI+lKS@%t?IE21l;P^;puRzQ+yYlX1h;Y~0|V#vi_e#$DuxndD-0 zO+qfAtp$GRcc?VICvIiZ3^R+wZHf|4MRAjiVG>&!lo1;aNPeP2Ff4Alm{kt$=1fdr zV3`*Zt))YsXK2w7qVmIIw?f#0=y<+6tXYb7tCzE<`;Rz zi_-Fr<%wH8f11~{fc2X4<kKj+cE)LqA92N+%*KI~IqKIaY?RXf02yys#2j8DBjVF6mx0J>cs? z%Y{F+Rd4Rp}l| zZx{VOv#B%W?uJ~FwHv}qZrNQX?krYrkv5SXBmPB8As-AA*0Of zAwDI%&jIVUfZ1aaT4wfkFm@A!AY$wg7{J(bz}RUWE{*U3HkSd$o(slKDT);sX}@ZU zOq633Gm+K+_MQtN!zyNlauE-)0%0~7yTfY;+2dSx`L}e(m|v;FV`M_b&qKipavEEdW9p=T zN4aRUq<>GrpCD+pN#CJ+jnt>`fHag}Bl)d)2}C`csceh}`=uBa`Wb?_5teXigC64) z{EUM86rmrETeU3G|4tEqPQgzpn4*C86tV9xK7mjda6-+!julE>n__)rlsYL%lt}g0 z6y5I^#pTPp-nj${l8&?z8Lf`ks~3!nBENeEPEtjUtMFpkw(5!$bw=~HM{~NqIt~7d zs+Mafzzl-1vdU%YR_V$Mx2j~i+qqJ|YWT2a)%9UV0^L2ZJQpcxSu*|Ii0m^&WSyMI zR>GZrrDRpV+OS%@IvXzEy_ET&ym~S7=d?mr5-#7l_Qst9pO%E5c_C8%Lae+2WU-6!gyjGKwB za7w5Mtk=6i7eHCKxO#n`ikBHDC5D#*x)QV}%c{XzNUt6d-<4ycE3+dh4~>3Eh>&A3 z1IeDlu!~_FO?AclgULvGzw~E#C*7lfPy)vdKqB61?#SavK+|8|T^OuMhXM%+{tF?% zJj&$851V7dRvEEXE`ayRx67|bY{G&*S#-%;d|@eLQ4jao4_^KDt4mV2^VvIHcU*Ux zBAtg9O*D7Pdhh7z)u(x%4u+q7AyW22`0PuOvX{ceFGU?MJt!_&E?k^=C+A@f#2tB_ z3{(tMCC?M$WQc(ZyTx~R|ME{n>6h_WyELpS_!n^-v zl&g&7jg!|-F6d)lX&h<5cCF{F53C2)ZIQCUaPeT&F{q7FcETv>2aL(11pdlL=^ulT z@=<~!Pm&8FQZMN!-qV~B{(y?tN9}VFnD)lhg}~ zYia92Eoo9K$~bv~TqM(S%B9IzFbKgV4yB}#mmu3XPy)#yX=1qyLh=J`2$JZt;hAg= z8?pvY~r$5~7bgztyiKD*T}OR`oqw3l);Jl!b3TI|OJ=_T0s$<-re5+&Xc$^2nNH zz3>mKeo(cZd*}7A^GGEBC>AL17VLnNTG49e>g(a^E>a`9W6$iR-yZPI+_fK-Pg0{g1Qt2Z~HTwpnqXWNuV3?aEidG@88tQ|g78mHGINK*u7A)a>V2hoIN!LLWnQl1RFhSkU?MGn$j8iCR1PcwB zc)EYPNPbVa??fd3MA&}vuH_^UNI{IUsHH3sG4{9b@6rFrso%fH^rKEI?voIM zrg=U79(N<)EJ)PzflEsSWif6}rxHQqNo^e1u~*6?s2h8h-bc}Rc@94k5iUOsy}Zdv zS!tq_=~tR4W+%a4KrRk{ZYR*XTpqQQ%U!04|E9H6e_dZ}`uq6(rHB_;O3a*cU7=4N zZRtD#;PFue(2Fn@GHhcjmV+}I{8uqtQHi>M(Nx*Z!5C;JV=K{Ki=>rB^ zHwLG~?;$`!oYP?g47P(7-T3CUZ{DlvistUv$lVjk-Lqa8&Fv3c`niKhqO_5PO!fGC z{B_XMzl}usWXp@FpT~9;IKg9~XHoy!_he}^bKb&EdPzeiLz!i03R_xH7d`MozCspd zq~>$5So9A=nE`b{;$pdyO8bQ~|1xMMmY7m6tt7ViWM?*uH#PT(i$ZD+Y)d96rCcGq z(jr!l16CCW7O@;6-)-u6N{Njr#o;lfL_3yAbQhb_q;p`wCQr1!$CqsKv4oP3lvw;p zy+XO69Fgsp9cNY}dg?_Y{IWf%Vh&M!dXnGTMO!)T@V!dQAfXKDYp~R0F&ruzj0jM>x%MVElPLF8n#A&vQGOZ78o<6XB9|EJt`!=3KV4cCiW(jHE)KK z$KL}KI(X|7L!}<2XL@o7d0%{+X>ky*af$fcb}*s2Wm1E*1G8CmuhFt;Iba9P zmMW2osB6j<$|gF(XZ?IObcbxx6GB#mnXpA>dFxP1mbV7Ei&C=UF`*6{Y^YW^Q`u7T z(*kxD#v-k4Ih0A51a}_8b+_Vb!}N;0p!UJJqjV@Y-_p!{WY}g&`9M~z{(z~-UnwWg z7do0r+n@O|o%<`$Nxqjo;taMpaBgE&EP;ICE?fE3_Z#zd(z|F7*I;tEWX4==xki z#j@7@H6^hyK8hCdgPVpZc7_6y8Rg|Q9P~g(ukd3!xtZ03?}JXWwqf5NiJsiPN@Q6A zx1z(H*xO@tPX~I*`#;z%0~CCPh&{7aJ^27E_WgG_Fu?&Tp2c?1(wFh#Mw~5Ao=8Yd z#&%__5`VdsBPZ!N;b29IzQ?BwHzoHG*S8>G;uF@$@{0Is7FieyeHDUXT2!e{A|S0uxMFs`>deqeq-}T=RQ35(Q6;R zwzenQ*t>Lcad5fivyuu_uwuNGy==PQ*8WNJ?dFZPo=98I`krXpV5G2l@$j-IR$jeP zzAaL|Z7p!;LTvYQ&<;EI>mR~HX1{*%z=N7SWDpiNs-2N)=bCkW=uYhq4u?yz!%;6B z)MJBW?b6`~LL(ODvQ`g9gdKQOw{!$@5SGlwmZk4lX=$zm&!tr>=C{9by8$iwAp2JK ziu-QU-nA^0*Bxux#_tDlW>DjP{jcCSbU;rNaT0OFEUZ1&h`Ui7i z;mEzhqp`}`w}&3c3Cz^xKSkBFZuu^bp{iP*Svh@cE?m+In`3F!+vd$Vy{@X|;WzX; zn}f^&$F3b)ZoFIGv2tY16fWI$&-M&7l*Q9G&n=x>KKssV;rzO&tq%J^ZH`}mj;w{1 zk94`1A_GGk1Ly7zoLkP359&Je$xF9iT62Fqe6O@G{MzuM`Llx3n9#5x?28EdaMqWw zfAPp?B?4TeHX6Dk4c%)mM;e~JqmMM~U(Slvb*^RMM6lZRq4nK&YQw_dE%O7Rjsg_0 zDP07cTh^uHkB1nDFr zNZ7D)5(d{3^xA^M>4v-kX-+ytkMPFCCjSin)ePw$;uR=ADRnqQk0@r`jAIF;xg_P9 zL_J-wJcTwTQ0U)9C;X&-!IRy=s1h?6kyUBmwS61e6_M-ZbEqTDU`x-5B$1_+2+}#a|5iD(c&5>U z(xry{Va94Kt;@g(jN};RGG%#Rv&K&#E=zu^$*>Y^z*?F)SnQ45#u0CXfp<9hn@+A6QI206Q9gSspMXzH3}?OvI&h{1ePf4-EXcs751mor zc1^*52wub!!nov{5|WS1Pxz>bwsLebSgyD-X{K0Z=MlHN{yU6_wq_g5PqH~-2Xb9M z_M#m|BJg3Xw6gCGaG8YJV&6iHvaDpn1fpHbi3>|40dQL^%`=%%a~|y&)^;y5U~M_L zD<%GILWl387==?~Psh}?sRiRNs+v~b_|vMLwD5T?xTs&;6@yu5;H}G8GFmQLyzsW2 zp1ZEiEE}(dh?n<+KU7vP4#i3;ZU&cv8zo(llCE$`U#z}wUHrp~Ke)Kj|5Bv?rEuTN z;g`>cYhMAW1iP78d2!{?YS-$EtB2NhhpYC5%lAbK_kj_GYryx{O4c*ORnLXXpNkeg zM{69Y_#OMhGF^4Iyb`s)V1H3Ep(K2wzsKVU$j0)-^$pTsRqR7z`AW3@BLxxOlq)F( z?e5eEKUU}LIUI$`XXOYN>G;HEs30@QQO{Z8Qw zzD9&Es$>2p<|e0h`E+)CD*;~ebhs*g%tG?u>&ISAOa~R+iyldTNx|m`6tbGZ8ywHz z-?vC2tZ@@9Vg>V)DJ#AE2r%?_p%|EW?7I9?oDs&&jW~z%=J3++%Gc}K^+ z^-4xGuX!QkL2i+zwy6;FKlRcGB{T6P8ja+nejz<6M z?C9WM=IIey$kvVTIv{&1`v7(wy{IEXg|E2~Yo#c)cDyD%QT_@KKHK7%z}J;0IXjg< zGcoEWW~y=-x5z$YO`q3Li`lLf%|6M4Zwd>nFH|t~j=pz6-+VxQ=|0_}7DOjRE5oOK zVwROa-<4qBB2vbhI-@q2w^c2NIOVLz4@j^tB+{eu;ZbcmX!KL+!*pi?!O2z!tpUpi zIg>kx^q(jo-Y!*81k?EcFM2#k!T(J`4MqGPboU4W#9VB8k!XdKIrJ*t2gLcM|Bc>O z(cL{tYUV>uq8VrVGS`=N?-^`}r2!OExqfQ=KO>U;|DY6*>`EQZ0o&Ylq>k zH50QH+&FRV#B$?LZ30dmDyw0Vy7Un`-r7WGbdzr~&gixd594!4Gm~_08yz7dJOf zu^CBv5TAlmR*pFe9(Mz+CgFEyrB^xVq6S9~4n7H50hDQ9$apw2lD#+WbzoVb9?4G5`B`^|WW& zIeZx>V)!KI^xOn}Fx~Hz84ctv;;ixVw27Do!cUhZY-T6(#>>(soe6j*`El{2owFm? zxw@QvWNI2miZP>Q95WT4$H4?P;yg>~3rY#bsbi;7^0S%$1wHGcl{7QN|lAzTW7rpx-7&iXT*{m*nI|3TON=eqq7-Tpt< zorvg8Y?|Q1{WFsTE6KKsu(jf9CXNC#TNaGJeRyHwGgBtJ8Q*eqL3uNQLtlywVO{=a zzOJhCvCg2cePlK1D<0Xi^kti+nT4jX&as)FV>fM<>oQ9oR^-@AHp?^0O%E#y?53;M z&98plos=Ok+;d$N(|WM;hC-AuPy9@@{GjI!&TUGJXVU`exa zoSc*WZoPi*HBI9gXHT*zTh;aIzi!>Sb?>cP#edAn$>!ired$=>Z+bZHztV^5%*num zU*b9LCMR+|oXCrY5x$3KzlI(IevKo>QB#kJr!>=udDPNl8MXFUM{PZ}(X5^<7H=5I z?#a%g9Oe=GsH4X*n$wdrn%k3$R7;POr5Hx?dh!N2(e_QgrvSfM-{i$?(LQJp9fQ1> zBjzIHeA(3F7F|7sVqQ;?nBU_uaGji3@KsK9`(1AsmHze=v)Dq!7WqrG*ishjL2U6G zhGfnyEUpA`rGAr^vy8=VL2Q}7OpD#hVz(l;JSDcA#a19zNQteOG*okbR}CkbF+yvP z^8$AxbcMTWyue-IlPN_!mmGI~Pu^HgN`6C6-UV*Vq~=H28*12F8Tnzh05?84IO-n@ zhw2A{(x@*S_DiAqz~~@Ldp@(vW{DkYegP$gGl8q4zHuQq5gwli*DE=i`h(+>Qebc> z+$6NBL1EvXJqLI1+q17x=$jP6Lw?~*vIj!g?;G7Eg#3P?`N{K-oj!Z6o;B1o66p7j zh5SuI%egis{bW~bd-u6^*0Sgi`vN1O`s|NrF1o$EoTYWmYmyy<{%~(!FgVg191qKO z`U;GN*#}D+351ldTuSO63ZgMe^%`Y!*QjsMFK4lzHpzD-8SDs-h0k}O?p&6lwI=6v z1_sijPK*zxN41QOuaELtWKK4p4UYQ8WK&Bp_?&F%Cg_gH*0cV>i4mV9TTc1Kz{IF* zJ>54F`0|8bwseJk01V|H5hD)rg=AX9&c2ik=%%In^x0F*CsE{lGa!c|r%$%Y+2kuR z5m%dk*!R?gaLzXt5>5rjf)RUba6$_BC867YMK+)EkBtQT6$xbSn6^K)3r z94+G>zwbDjx|bO*!DmoYcKz7c<9*V9A(G0b&%C^#kr0NB9TpfD2XlYG*o5C{ol z!LZ;{b9cXPl5M@cW4=*;Z?Bx)+dCQ*Cq^jj=!{@>s*$D6~WM z4kMs-ZJ&~Z64!MtNx`@WPa$RfM2fkh;j4U)Ni=?y>oJQa_!iL&-zr+*+eD{mMS7NK z!&kPL1>Y`a!*_^w_&K5je(q$B*CpF&fTw(80I?J~&X%?E6%u?{@nIo2pbV}Fqb1DW zB?K6L?-Kfe*}DXPxWB$$p$Gj&^i*{w1nB$0Sq$VRH^onJy=odaWx$t;sa$}=mpWW* zLio~Z5~&>3#a!5~hNiGhsYE_h5q7BY!?|im{~gZL!)j=XepNdKjt z4{N>Cj{BWrn(tn4y z>R~k`nzRv=Pw^ppm@uC?^hON=mcy0WhZcAv8RGwOEt}I?u2L&bYnf0#&84=?dQB^X zxwNugHD3QsE$g*(cgQBm?-S3<#w&p_*&_NR{CW%JELx0=L?wfvK*TSb*%Fm){;~d` z2%;m~F8ibaEne9=F)ZXo@Xp@)oYebA^*sL)PP<}d#I}>8l`Lwg(pY+jKUBn zAxH#dqT7M7K)AOz;!aug^=fQ0@`U~Z-Zd^!QZ-|`k*od`dhnHz;3yzh1tab=TXnT2Qu9P#Y_#T?j0>-!6ZvJYMkVOk1K%m}$Fl z>c=G&v*tw2j#<;q?78gu19x1NYeueAShH|B1s~dTUp#vK=!(56X0KW}aM$jAzo2Zj z^5CrLrQC$Wwc;p?Im+I1l&|KvUc7ky;z~|UET?ASi+6MCGw1uujHMa1T}P=b7&D_( z&w?V{_&WCuto%V^7{wKrX^o5An;P3WZJaU=Th-k9uZq_f zL1m^*(`Mwd>8WZ+G(U$uLV9M(G;CMn^k21(Y0H!abf*(FS*NVSIeHE?BwDo9%ikzO z9;ce3|EjfRqMVyB6l`gap=7qK=mG(85S z#ZvPcWJ@S4f=^|?eo2yu=!S?k6T0>X#|8p}!WEx1hSl37^G)6?EWC-naVgmE4~1m& znc%n|Y}%QwGwrgyKR7x%F&5~@l9RI~e|SQob&qgpd?XMa35@we5>a2!4L?i3nvnwI z-Ylt=Vok)yNbM|04M<%S>eeP!>G4%Jh|%-%BhjR%kCR$6lf+k@9tG zZbSM-s_Hd(*SJ+@$%?Zg=B!vKSqv`@EOjooFCU8TYQ6nbR5-c1eeY{O_v+6rhaVbw zS35sry5}xlao5D$HF5X0>sd3FSw3NRzWB)XN9KKZ>=g-j>598H=B|yqx6ibHP`q{4 zlqm4rd}QvCX!Vi11x*QeS;DjB=2zyv@@vy8p1PQ)F7Da2;@KDT>|5F&_Z*rv$pxOo zmWp3}e9g|4l&?8Bckx;t=Ma=-q%9S6Tw6xFFmG5!h*F%$mmmP7JPo9z%~adm)g0Ig zGjEW*w#j0_UE^<5g|+3AX^9Y9G0dc0y=DrjwIEev6!aV-Pl&*CW2Gi8tStsC@r-@K z;x~T7sG|7`kccs|uVZ8>gkZ{;GGY_z`PoNoQu{jnPdMT!qcY+f&zQI=W0J6J-2^%o z8cXIhrJfttGN&r@o;fX9@*6}Jyw+}sxSvmpyVLk-T7+VgP$lzKuNx)mheXVgv_&Qk;}US)-6F*-zzrEQr~3-Uxf>sD@Z z8^_`vMq=o1;bFelLo_LrZT&BD@M@zlpW^^4(eKmYpk%ad_W7hB-5g6h>BdslWe#db6; zH{N#tp!}Wk_>MEPZ8uNMotU2hJ$T<;g2u{s(uyvbKY6EMM`FjWZ)d-ry>t*|)QorB zwfBJn&0S&x=#nr{>QuwBG7jtc`7LSSdRgD?1o3JG@eMJXUr*UiN6**&MYsZzP*U z&=|xl@c)(NCZwThUMHTJB#+??P)Xrhh!CeaQImFbsYx`7rU4^}7naP|ESM?U$kN=5 zWdI7jui8>-&p=+UYaB%zmp(f@cVjQesz!E2Mo!S`8IVjOu^PeEn`ROhsV~ypltES1 z5hsQ1p!%msZX|bU(wJVEN@9_!NnLuXXi3=)h|(}8T9G?LpRgU+)@=t_7~9Jjn@Jz@ zl!-`Ja?Iw>IcD=e$CwpK6m#_~HUyKH%{Wck5Hi8XPNT`3mXv6JK69!v_nFg@C4ZA` z2##*q^w{ZB?U7ulfk+S4KqNTS5OFr7MHDrhn+%2hqiON|sZ@v7!+!jG@b~b3oqrr# zJt!0ROo*`~87Y*C#hGZ6$f=Y^Ivdt#-*ARimuW@mdIx2D%tRm6)_+Rvb_^%YT{ob9 zVw>Rx48OtO^$?qYRwVqln1Nd;pL?Peq;vnge8sg2EZw zYRQ&YJhwcrl-(-(R^MxZR|89y__jmf9^xe@5+!xfU2PAHd`SmC^VmIy`^D4OPd^|) ze~410w@MctyIZpRff*4$;fy(l*36XiVJ=s=WdmDtcXd?B5h@L4V7h&r+ zG^O1O{3KV+g*AeOGb|&|;S8!@JA<-ydkqrp%n`e=<2bUUUob&;g=?#@{LUR+pps2 zQ*1_D^?R01*>C)=Rlmm4Pnn;vw<7WA1z)egWvr;u|8WO5?l2q_3;GVLG!_W{qC6&bK z3_PgLZHY|yhITyJpJ}r$)Mw)0ridfU*IQ6S>Y_ucTaD9yMJ7UvW-R@eXzBlBdppJW zVU5Q#Pno6qe~SK2F|PK;(^D4FqH%Yb#$`=%cNx->bxdvsk)K-fH%vGXPmv`u@a9w6 zsRj=|ZIT0N<0Wu4FYsZio;lH`a$qm;AY>Yk3PR=}t>-j`Mtucr0w&x zKURv`HBK^ zsi3wvK*U@n*#c;yofJ>GtyxAn=hXWMa}@#MMovvNL*I(fRa`D8E7EgtLY zZU+rVZIAmWrE4gputP^EL`yYI6(iePM}i?gWhSMJbQKTDW77r(7$Fix`+4~+d~^yEX;JS8QeLA$Z|6{ z7hJd!EozuGt{Gf;bx@$LY}pyxvU9OjITQKQqIYev<|m@(o{n$%;%wXM&c>CU$6`B= zEsM9?e$f3+cYNo$q^{*^%)R4-%I0}^)G#>Y~kq3Nw^;n(uP2V#VUWs0JC;oOhh-nH!*@yAV^ zYfGZ2GU}>a%`cBubj0&JqmIr`9#(M0HMECqOH|eV`s05`+t{{G6Yh!+-CNW;-gA3D zd8sqy>(dxwRtri|E~ij-xlt&m@YB#~OxHWE{7&BRPIc?f_JfA+IScXey@OdDcJuch zF?3kW-{;L8wTACo%!v8E-AG|)5%PS$*3)s+{QaXwgnz(ib>^CXki)}Yw{z02$#%{f z1V}E-#K7tL6Vf(CyxA(gb>f7aOlA6qe3GvpHaY?wHY&&Alt<=I!R{r8)cs)yQoWS= zI?r%DM3g0YG{-Vf9V|nnBvpE%vRcv|lnE8WgP>#sL$Ttlj5#Y8s^iXWQQI~}yOfmw zkck8NOpfja1lZ^(Hq9xL=(Is+M4_S6PS+*(lp&MGDMgZnCaDx>Jjkc1=k+G^e1M%f z(zpS31Q-T3VaJt#7#`Xs4Ef16$*Y5r(J|QyQ1tZ$uYN=${D_7I1s_xHHX09KZ1$9wJ-My69sH0Yy6T&dnX&5H~14u_I)lV6uUBEmwN6N31hxpXe z$+T3AL=FN*np0*Kv%-Jwx((|7iqe_uHqd5FGyb{j){ag#t()<0EH!OJ^tmZKG`?Ze zdYKlE;hVM7#P1x1!Ef{(-)X6hmgjQ9p&$3_Ln>AC{tOoA8?;2Y_f z45 zrh~iZ=bm2}iF@`(UHb{|n&z73M`8s#qmG^L=j5g38;E;$M_s$sd;>V62Y$Yv<4(&r z6!$blT@7l!p;*E8sAK!R^^IoEw2=Uj1WoAs;9KxEBS2H^gb)NsBV9@im}`$BGHgPE zG-Tp|imE(3WjL2vzTF-sR)IM%Wmcuk1x_iav1WW^TAOJVJv75EflVzLMG@6!SQ8ik znvkKKPf#sNSb~l(T?4vgybDYg9Y(YAibYjgZX8lEnnvuCTnH1aURG@wTwrhCq+-{S zt%%M{XlCq_a?rt;B1Y`UBn9#^%f0@nL;4NW8!1fRVOaLRLsIAxJW#!C>@JMz)yA9x zs9veCQ26rhnGhb^ef~Mg_mxTMF#w)<|6dB=l&PP3aKKdZAJ zb!tw<=?C+OO0(lL^q61=ZG=5EtoR0bvf?8fK3MQsVWF2LmcoLM-`s*v%t0=vmHW!uNoWZxISuQTj# zW!6f-=`-D(%qkSvE(J%05Ufx8!SBG9qFy*Z1hk(B`9lnwlP08OK}#m2Nlm>F4zdbK zH7r4UiYmtylVnyOEu+*r6$9n^df~Dn`1nK-N5DWX0+SNhRCROWI;?R?J&z*-`>Jmb8kdPxvLkioG4Z3M7_KGSt_ z7mY3CheoS^WJ2^Oo1kr=PN)KKs)QY)f50~}64tpwq?|a@-dUwJjfj?0XV!gpc6C%G zyGyntFcJ~(A)uy8sO$133-J+fB1?YvYX%6KLktNF+Zb6$e%Rt zrp~n~eQFZ+B^x1H#mK?>Ru~B*A&Y>}=cn1k)~8G;?S~4DV^eiyD1i2Y0EZNUwf6)* zd?9U!8}>}J7ZR=nMnu+ldAMM9wv z@{Of1)}X0Af$WA@-(lyje8IBlIe?>Y*x%2lQzP7L8fkQrFgg(mYmLFU=W;;w3u0hk z0A{@qf*B%HpAt^}j5~`R@Hj6vu>laR++eNH|)*wv|b5-f4-K@yP zI#?E@P8l(?8K#V)Ny|EpgBieCpS(<+-P^csVQfG(M36}&OnX%%OQ}%6!eE%@7Y7wg z19D3K5HOw)ldZLkjV9OYC5GN(6Qg~=8+{}&r6x>L@Hd&7f(}58D`QOp>7E-paA4$D zMnI6$P@58y150TG+!u^7^@eCIu|=XZqD?GLufi-LW9Kv0>mOfVElwWCl@)V^Z0N@& z%mu+Dr8%&T+SF?u-OVJ4$8{g@0^oA^$j3 z7~!C_u|b~#GIdBIF5EyyN^U}F5T$z&J|;UMK?85f4$m_D6o_oHus6`Hp`a9qV4ndi zkR)Ll_sR4wDwDmQEK{EJUS>jvgUO{kG}23Rm4c1u*yWE&Y(#WCtfHYxnunm#7$L2O zUrecXBcHRkK8bMaD4l+12-A$=3k>y&S#E+W43K^x@6 zRGU#;XD}k3IbGF(LjdhWHj}}{6gR-*G70}J{#SV1%7b}P#;YS4tw7%(bsQYZXi6+7 zKO9PIs-Ni)>6#5^u3WDsUyg10*~_Mu(+!$%!Nm;O!17J9n9Xn)BU<0Iy^(|lYS4^9 z^kWj#kR@iTM@z_~8H2COV;3DMd9>>@>+;}krkV#*I^Atz4n|`noTWM3K5}V?XPO!j z?b9(Pa~KiHb7^k4HZ205q^u`LC*P={K>1=}4JMoPB2UcMdcpOQ&Xl=Lau)I+2OH=ZYamvPew!qvz zxk}JhS;jnN>+)#Vh}N~WRV+`br(CN?>pjL*u`Z8}0o?FmHNXBVHDHFf>ECJyvGrA%CBdRPsGyVQ_=*r(D87*~1efHLDMsKS^sQIC^qefqD8c~|)mE=!2j7!UfX zI5s*uCu45Xh@-_5>KC+FMrOG&qG_*cBJJ670Hqt4yK|PIilmil8@jilpDBy0GXt>37I`le{|e zeB=?OW7;+4Ivp+`lm1{x`dy0uJ@URyo{79A^4=ov_sRPM^8S##e@osny!8NJXFt++ zD3L+d;v2`2vIv%9EG)fD*_|3Ak{rh$QEV3Rqr~5blIHzTvnzTb#ZHkVW!a&E6w;w2 zeG%nCG)T5glr!TFd`3K7q&ezf`XOMmb~o-9F<&9lPG94Gf@8O>tNE1)S0@bW3cC0; zoL6@7AKLO(Y^5<<>3n0%wsYao9oxdsv)u3qR|>{-r>7k`1ZT~I!MWzoKLHePTT zCW3{+g6Fj@uWniV(sEV2^4Rj#c;REnmYt}qeXaD>(v`|1vC1Ry$}hxhJ_R@)a z<+ZOock8)mUDI+$yu6j#-IB-8`E(LxDv;a=Q?bm5;H= ztshp^FJ4JBwBCLak<}+zWW|RSb&H3hjqSI;9Ixo2vSq7fI~F}l^|x!{Wu0uatF?QV zwkP&=z1xU#+n!+Msy-BUE_Ox_biSJx7apf=5khCHMqd>t#ga+-@5Rgt6|N|6;?unULw3=zhz%I zfg6v?)E%qP}^h8N(TeAnpsh@YOV@Qci( z4`zg|=#gxMd>x_=tCvyPqYkW|UeKXXWNX^W(~i+t@*mUsBZdoCZE`EI;;NtEA8@?$ zEUmt*v%GTdL_}3})D{B>9Sv`K?v(M0C-ECNCgdYKwVhNw2T~5EX~R@xVtv2FKyRa* zLNI?Bq15Aj7rPJ0_6DVfNJZLk(=)uI515_vvy+&%S5DnJ6?1x{Ht)uRHX1A&a0>!- zstooc6(EQur!v$@rYjYPlnjjBV#7bYVfYsy00t$f3Q3Qz0U@b_SqF`DoPk z=tevs5HPS1o4pwxu;Dgr7%tn9lyMTL!0bCxM#)QmLZeKdY$qEPv)Eu2M9MRbOi%yM zG&&NyQcMk^wvvrAtf6$1G8CF&gwh?MFH$~hW*^xw)GuzBS#88nG2;n_67P{$93hcZku8}8N2ldPo02@E8AC}1ds@lyA#?wGS~@%+l}))@YGwnlBO z3Rq}HRcAtg%`olYY=&vh)0}RE0??$EPUgeaqGYK7oE~HCpWFZ`Ksy%OeQbFkzPml@Y>(R7HzJeO+6Uv zNx+h#1fW!!QJ~R`q%M}ARFw%zjNq_ShhF6Q@jCR%E4-OIm%CtE5%$D{JxfJ#;c(P> zBx*ad5lDnA482GOBf6^C)%<)m)Jw@QtvIrAK8K@R<=1OU5yRBY1FziRbTOQwog;9B zgLw5uIa^hrgJXLgb7V8)*k!&N62P84d)P6yibCyZmtCG8S&u^s1!7pD2oD)4ke>cm z1RD~k7#=zDWG!LGPV*}ab$`{x0cF$1s+8nDi6 zz#bJ?y6p1#;AZU`WMl7^{sIHr2sT^apdv)92c2?rpMgfr5UI?BUF)*^H35)hBNc!p zG5eONeS5-FI{)Otk=WMVG0*Oq#|VVQGfsdIPiZ`cOQSQ+jUXhkWIZ`UM7qmJ!jjks zKr`zsRjB}SW{e!z6u|5NSP|r*0Vkso9s8u4Xc%vyFe@k!dM5snNkx+AGa+-`@>Eby z;p?d8%$uK{{ z^D~kDO?E{PIjSqosrQuMKqtvLQ`fxYPpV1+Bv_^yhcam&i<#{W8qG_t zZaHVvcU9k0<*ei-hCuIiq1I zm+1|Nl*!6QPtshb2T?Gs#D1kY#JbX=@To2;q>@yY=0yHYgQ}CqTB2 zD3cNT4cROW!^T0;#b|3bMIl4#8WqjV*c_pJ+sKKyl&bY@bfeJ1+SW5zu)0FTk}}lF z%6ZXw-N_UeH8Drc!jo~w&Q*tV*7C0(UvX@WIkwJ=E9H%`^2WI1Kmr?b>0IebUQG=5 zInS@uHpOb261Coy+M}`BqmY>MkF$49w#VGt6L^6nhs!Gd31`j9R%in0i&RItErx;w zv(1>A%=8o2^o&!cDf56?MIttdhDeJx87Y$(VnVZ^&))<@-_2(cB=dXdk@Q`7xOCf! z9~_PaL()qWOP!VeH+g>zFGK^v3WrmaQ)~E+lys#jr?jarAi!55j|%wQ>$xkotufoy z`Ore!V$G6u*%K{qeov*L$gVj$IAZX67qN7$@hU%Uz(3=(iG|I$+k~r*xV?2uIfj|G z;%y(g4X;(92QKr{7Q85wT7NQ;?&WM+hQC3_WqLJQXo}rNq6?3i=re58la!fW8_Gl? zM9n~SI$OUUIhC!J!-2pLlcTavJEk1N+A*5e1x|lwZ8~QvM|v4O&CyfU5MrHbSpS`} zfP^KXF_nWnd3u@}n#xjpgLLhHOHIYDlbWs_V`WNz)2tI8)TJF_>3N5>BON_%Do1Uf zT`$d@cB0q05sY!#64nl$a7)gjj)bnfhP9(4y*w*pOeuqx@3b-|Kvz39(p%S|i`Sxl zAo9}|{4-+bwXoU@H)1BbIrS)xS#VFUS0l+-r>O^ubkwU6j zRo8MUtT!H(!tHL@&Z+s?wk-WB`gmUEv!(xqfb=%JZf}9a6zUdON}zIoyg>Ip9=1Ytr{_-NWxJK)x>zx+nU^ldi;v@*-L~2vtJuHP9x?^#Hx-g*T$uyhmd-N0-mXYg*<` z&7N4`6Ylbbx|n;{?1|Ny?Ta}}5v0tX!rNRg_b=3ZJ%CMZwqsSOUg%o992XAGcG1O> zV{^wA-0u}^yH{B?dm^#5e6|Dm=Y4aJ&vo42&Xw(2E9AEBSUZX*d`QV%s=n1%QbB5D zWm`-VN6ab5X{_=e;bXIHF~m>uy4?jxh>4Y5=c&X3q!TB$c+ZQ}P^lYmGPf!eBUQ7C z&?}0dglM3Ps95&3$diHaqGpYF;-vL3p0OZ~N>@v6y0D2QNopliu5ENH{I-Q1MS(~1 zjp5BxT3zfgN;#H#h);>TrvY(2A`uk%DnTd>eZ@sMrH)CDz5Gp&QCP%~QxbZJYt z;}jB({MEdo*)ZMV_)*@rndXEmZ?gqIz@O-8TR%B36@{G5&5u4#?JgK?N zz>G(->DV5ZKr-x~czqT74DOj@56HxnOy7)EN3dAKt8V>Rq` zC}*j}#7lHTUN*JS6WAs?=+yPH?9^4xB8?Le9Z#A59_42Tuyp*Xo|PH`qc||8@@C39 zr2Je7(e$$&Kq3Eyuuq3@#LMW+R22d!_PF4F9_hE!V6xb;t0(s~gES$BSTj z=Pe6`i{^#gsHXw%jjoh6#L615e`I+ca(vd_dvpv~dk1s|Ba`7h5#7TOmN zEF6y(?OS%Q961>~a&o5YuH)4E4wtg3h%;6l!J2W(tMGriwt-<=YWZY6>In?befAoo zmya{Pfbcn1l#2PNDZ{EtF^$R0nQGiK`l@lJnT*lE=c$}Hz0Z(=^OSBOo(?C|9AZn; zqVSod1e!^co`WcXXkeQQz1xt1qg3Gwxy3jv=q1&V@;=0rnb8!INiy^no7*FxI5wnK ztL60HDI0o#erRLP!ketMdb%0{$C?HDVV<(G@nk7aza%NuHZ_<2n@US=G=t;ihOt4W zJM`@Z$Shc()7jIITBdWRbEk5p{_svUC($i+=5c%1G`w3)(SN7xQ;s)vj@~)u27gXE z;50X7S4SyYMO!Hc=^*o1vy*UzUYvxCDfQc_#4`w}X-*{%#SNOKa#P2R+KDqxb5q&W z->IB8v))LuBwz@>3J4j8_orpWCwm5z&VAF|@S(H_e5%-@!V40=&718LfX*5jSL{KA zOP5l(?@O1+ei%3Z!0yBLgw8WAUE0Ai5a*5SCZyLV8DMPCd+Cx^SD3T}FiOW^(G>}$ z+10S!<7p-yS;uX6JGbW@|Lwk^>sZ8F^Vi!!Pn^dQA9|+wYP2s0x6(o>K$@NuYQrzv$-HHB{}S(YkVpKXY#j4nk^U#8lK`afWq(W|4`m_R zE4e829SZ#pdGC<-`{eyOd3lt2heG)j`XdT`k37Nzsg&YoDMY=(X6eHPv)`tmc>;Du zQc}W_IOKx?kunuh0hMx76n|AJq!0W}4^C!hor?ZW<|n29L)F3%FI|lzXEBW(K_j%O zWF<|YbfhqCBUKFQo}r!dho~4krwe8xE4Ff&=FETPE{uz8jul%)%vN#NR=Jv!|Kf$~ z7ZQ#M;lA2j5#VFSWUUvGX_|vP<>S~Th+q8yS8oXH(%_P zFCP2avCrIgqfeZTxz2)3r3Z+KNsYUA&a@}oMK?R=I_I0`PAufjbt9s@>Xp%#M`yEH zJ|?U6ELFbxY~0<5r;3yNdfr0wf@Lvp@yXXqmYSE%Z*@g?9FJB!LUuE!UOk09Jg?#> zcurzJ3~MTOLG0Uq=HE7JXO%ORI&_y9K)vLd|PAujVWr zSPn1b#D%uGu6u}ayy{qdGA`_2YF=uI3Wp$PC7U-cG{0(DG%hy3Zo%ss&2L$jOK$J| zPFZYE`|Z%Xd*8VnJ#!)2^QG9Ci?Pm&(TZoH;&ZdPcU>b%Mq;*q{=h$XjiNvZ}Uq#E)V&JZ{hkP$1whRnQQBBDchNHc53#O892!fSZx&pk7! z&1_^!q$d*b7nE>wvA0)wWVD$|-~fh`AeShA z-$>4Cze?BMVVR}8qg6*Kj6lGhaTE^e*f$d3h)0LTep#Sf6S5pu+I`Q^Nq6?9>Q>&Z+s}(?R@2Y?n4eg56kR) zl@hL^Fyeng@t>?c?dEI+u(ah%p%{Jvd;~&&2hN8gO}qydyk^g;P52~XFG4P}Cy`(D zH7jzNJ%7JuMTSp9w6T8E(NfHP+tgCaeYe=!Qf2&ZB~N~>xs@}1cc-akkKwxwJcajI WTbj(@J!GKp5uUha(uU8vK(%=mP^il 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
    #P%_(8%#J&HIOEnK=;J%)In5bmf1o4z^$gZ0o? VLv3R8kAoM*{?f%i3D9x>{41(R&36C* literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/latex.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/latex.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..282b20de6b6b69aa61c903e354f84edb94bf2da9 GIT binary patch literal 20129 zcmdsfYj7M#l3w?`Fc=Jg!5hT0@gguJ2nygsB>0dh0(_GaMQZN|K>`NT4RFB04Ak8q z31DWIw;|i0fhx{bluIX29Wc*Wq7o2{qMKSy@?CSy`D`+5GRt#U2jN$+!1~CXaL6-_eWtIE~EH z?;&%86S*Nyu;XvVIB5|LqRE`Nd3ZVX9o286GsmYo;owgC=ewz5DF_j zo?p`V{k-NrqspPk#L?H0FSMxj+cf71>9Qni#bR_M1bng@ibfPFKO4OuMYNJLXAhhj zIPm7c$k}sm44y%ScS2G}#-h>iNOW4&is&sAQQ1q$37Rhpd(fs&K1*FlX)&JuXO!OH zV%#L3RcmC4IX*L5<*m1ij^9}C6kWfu-X`)f{v)u)_wBzC&SAj0UjXMa;0j*==P}@l zUI6Dc;EG=WS7N}Gz5vc=z?HoKuH1mDcmZ6c0ax_`xM~Bg<^^!I2Hb`hz||RW^)G;H zFyInV*N)_6|i=QW;S-^;VI`zWThQP_U_w%c zr$f_QM^Gn5<*lX=-3l>i2+^%fi1tj+Y92`m2BxJEkR!LD`)d3t=OG5JaOtAb5BFZ( zyX06JPZf3i!dG*>V9CDpjg+tb*}N;!n|LSj`pV0z!k(0GuMY6r7upkiVoRcVrC_yj zSIW2B!2kby;p4V4Xa7?YvvYsp85X0#89MBO;eevdcXZ*MW&KLrGd!b6#@f!CM_6uY zFdB}^IYn=GbV-q5R0PlXm3QVt5uA4@hI-0vDtJVCl%l(4_HUG??}) zuga1lsq@3AF-t<~zF}Dk2QCZQrDNkpX-5Y;TeItC!ueXL!RNOaGwX8t7&rUCyk(K7 zMlZDW&JPEbNMK4547ySHYFjT2Rxf|1iPF})d44!Fepw$3!A?!9v%^wYk<2k% z#)qZL)7blgam{mCA5 zTW?#R1;p0KY)lkkX!@u&o26oOzO66L_<*sG&O4b&B)K~rJRguphlg_pL*mw`7|E@G zh&C$bb1NXUjS6&_wNNC(jf!`3D7tF#Qr|$#g&sjfKJ? zbym0(QqK!gKn{l_S-1$rnRLjU=?kdyujXP6kIlcGTOyCmzk?EeJ4c}e%bsAij!4=g z(;)vCnH!vH)lFvWnIz)y#JJCl`ZzQ`*%sr^z}$%A_eyt+6Kxv^#x{o(W!$8L+T=d* z->HWy{I%{FuVaLUU_YgCzx>~L{C3$5yqX<)vgVo&$dI~zyXI8Y*=b30j?=!^oB{e# zXmBt@IzpN?0~?`Qc?(Ma75j|;dW-_8=S-q@i69~O%K^c+mJ(qUOr(Pa*9qEWiHVL zGps-?KJzJhL9ZS1tmIz?EW%ZVXn?tpx#FALfh@Pz>XVBz})@_IyYY zB9bI3%qSW)&!bTR!b})t2hk`)qo^d_WKl5H62sj3J+LP1FQfTPI6NxAYyp3E3)F=G z{HCfRQt#1-B#e%JLz2h9-czGGa_BuFIU1o8vs(yZJaj9GITQ87%|@5n)Uc#E=re(JTrx3YC)G zIU0#x0+cyR#w?yijWR6-LxC`+jj54ngNE3olF&6e3gSjb{cKeN;V{F*cCauN2+C1K z2&wuqGV-tq44c@rc1MZVnQ$M$(3MePO2V>&)4U>Z}CpjFk4?rtFz z35I7#F=1WP5X}Lgr%)us>|H>y4oqbwYuM{Z>++k#3DI#OAdKdkyrY6FsWUQhvY;@F zn{^wEMqrOeXp%8k=y-J0BtsE&I*j=@=8Je9(+i6{1SSR53{5s;3Rz4EJD=4b5Jff~ ztdh>;AR`!*rd3HanAKcf22Q+lbR50~Y>y}iJ1fsfqodt|7>#tQ0j~I-3~eTBy1(DS??Vd?cfzhXPP* zz+J{5M;V{!8%PG=F*f?#!M8K(I;6 z>6>#yY8f)8iTNFq=6FulW%kBZ&=8%<5PdF5jB2guWoM(2B!4L#1L}sSOpc3U^T+h-5 zQWfLRASTAn!oc({n$Pi&jD5puvZ?IN;#w1*G@U`0+35j;CLtp17kayK=7nczOUtuD z1d3dCpIE|a_zfXI%-sjDF=Mx8aOV*`6CsijSZpHM6bRYUK~-kM&K~nt*56 z!7NNi6(xi-O1KyZ&q#_tXBu<3)DY`fXt*~rq|q$u{#XM*v3A3>92IARbRfW<#V$0r zF^(r}O^ENAAO>#HWFC@iPN)-h+$m8QZo2WAyT+YwoXg@H+G)@fFngpN2SiAB=n60O zylkP*)Iv3gOc?dOFIfPhfNhVg^aL!CpWgp_VJotJU4%NJ&*E$VQB8l7O#nJ&i`_dJ|dJP zEH*G0ivbx8U0B4{gl=H*v4!p#v7dhedwcryqi+=6rt^ANzsne@70w}?v3grl1kAaj z<0_z96w$~rvF$xQJ?)rW>-aO_VFi)q1K0ip29-hl|6pu7ZMrg$Z*-ZHZXB!_nZTI( zx(#6rp-chr_gEb0cBC zpl(|j$d(})NS;HPbgl4gk8o5K&O@P&LHcrp(G!m^o1E77I=2&y3jsW_Hy{P-^~Gp1iGS_So~Bu@+@+tz>bycb=Q&{MDy4mu@#7(%h!DtQ8pAtmZbAPkAF+X$6LMrWKiL8UTMuJf?Zf5@}j1 zg05g{TADW!rE8c888d1&pyHVao308xXw^Oo{l9!Qa_Q04T(>9QIQPNMz9!khF#3+;ZQ|=W? zUPYqWaU^Muur#h}PImDvzedI7BS9Q1s-)Zf%6Umr>8^?_Bdx&DFpXO(<`I(z&}y#c zM9vj+k4ZI$`BP3HfoIHJw&t!&y6cvepua_czOBAij=C}yWqH1l&)>Q zU39Z3acre9Rojn};!KGxRlAK!9@exa4lkd(>rB<`$Gi7oebcS^<(F4Z-s?>@52or5 zEjYe#*FLOkymeu@b7k+nvQ*Q-RNVkTOVjnOxA)xKlZda3rRsO z*u&5~EGk)0*Gh$CsgNpaNu0i4v@u=VuvY6&*7}!QlC|9n1J{nGH#Dwo*p%F`X}LGK zVavk6zdrUzXk8fi!rPdxX}U3geLk^!c`{W4O0RhzxxH)d=A^s%=k6BW4@jJ8KExX& zL!b76o#2Bt%i&uM@t1k{TDcJmKE$B}-qjIeJ@#NPS+dzIg9jEq#P_+l1GVHUUH1%d z@B9tN4FgBq8F#4}S?V<9M!W!?U3bhS+G*#@&X`+t%t1o3GN)DMvdRjqGPhO6qy}s2 zvC4`pIImS!oTsdWl{KQ@(n(7)XNFeE@*p4!1^M5 zNX_UG&?IOkVx((0$g@vx^eZ~eSrJ`x;Ga40;C0)zRtNCJd2{B@aI*zL1SL_~CC=~0 z9e+2x_r$yM0VKa9F*)bx=;<4mchftah7UymWHc1f>@b?~Vux+1 z@u6%vrn%*bF=lekZCfwQo{@+>d&AKnH0Aw0W}^lyjq(mUy}~^xEl=0f-MD=H@`Fv= zp4$1A9r#V0er)GjyMDNBSy}1*^x|Fn-2?adpAP=ilid2+z1LEk5C26+a`Wq{mN(Ly zwmqRXPdUDJ=VOj9+xghV)i(e7s{#}%G}!NSyyDgzW6`iUSI+K4+uL8IyHXrF>e#sE z3aJ4^A!X|5c9rTvs#b_&O2U0mM4GEIo6=RPRg9w`ifDvPW4a)v#_|--fIvifwniD( z98=LqRCDUHw}su$fhINBhD*zN)|^$njmdgvetsTzkMr}WqdQ2=H3r*6lIJGPW@CCY zG=$Nhn@z}%k3}!z0-Rb78|KOuRw&PerFeXJob>>poKEzvr~&R8j2_Wv!PtaO>)GGB z)0d`I^pdxe_2}np?d^WIOq#6bVK+s6WP)e~!6~s1ZUS9Ta58@>yFSufy4zB2MiYOb ze2iM!)jqImuus%%!D;y|6v>;Y+<_Iuj5Ca`;1su^AV2^$(A4Snz%L^H~hS>HG zkl=i7*|=;=6s@{9FW48vYteLL^Qya<<-_UXvbEyoWO4I??JI|~u=#Nb*C5>Pztw;B z_`=}g_Jq41_UiEHYT$fwIFvdwnX12#^o6sDz_w~Q!T;jK zn?E~b!iJK=lc_To9yGKk&My1!jHDWNVC$abUw&e@mF>Fj!X_-QUJQMw8RSv(LH-wm z$N%d$es*N_t#hkG!Q@+F>V%XU9LL@*JI^n=9+g%tmD3#5rmO02ynFrK#K3ZEs%i^n zXG7z{!A0lQW9ix^WE>wHeX^Tt*r*@s){%_mBW;cy>VJz23(dpt`X>&t8@J<#&TeS{ zOiB+vDVTYVM73(E2B0C+ z)XIs@NlP`b3OO80;5m9k*DV_feq7EL%-!@DJS@D)u4|YZlKc&Ht*A)v%^-M1(r+H& z7J*3)<|kh+TujW}1F($C!E~Ob4!^D-GP8t?JjWQlSvwy71rOV_wZsmuwl%9NtHaK{J7 z8bxlNJ25zNcJSmICk~t)lurW&@cNzy0Su8GMyX7vnC4+))bGPcNz-SDZE~$7_kM1! zaov8;tv*0|{Sr`I;U0Uql5%rLr^_l9Txp^G6Ym}Gn$VXN`o0vlC%p{|1B;u|-trGm zUOl<=_Hy~MV|j3;eWiLuy?gBL-h1+D-Lap0kKI&v$>i zd*vIc&3ow_+y8{)efzOv3isq4tF!fl+MF-kL-=v;!f4# zXOrVuK!L@rnMTUr#%%d`6x`2ET1I~co~bS@M8V`?9?H$6Wz1(FVdOu7-h7<(eylKFB08~dCGw}Sl6=k`wCu@XHFGA_ z!;mEL(zq{P67$K&o{Qlnvt8yl2SZuB92m;w3am_K{!6n)T}E@yRYwM}A4J`Pa#nQdYfCRXz|UKy*Dr=P>E zr503GtV-lWUmXYT#2Ut{W7Tr~b7V>x(^$%5mC#r!V%111v-Otew6gkwX48kAStT;F zUa>9OuJt^pO>R#{i}n4X{i*!zGg5?y^tu*6uX&vwPoG>-<8nH&K#eW-a*(VRI1Hx;pX7b>(rDB~}Z_343jhTzrd@HXus1BGI z)Wc>DR2?z%nO~HWqO|To>4|kkc#YMd{PkzcO??0}O1js&$E^Kf!)K&z;h{4%GmEou zm$Y#zIbPY*&dE)f+r0ZoC4U5aVr~$gW*Gc8~PR^@M;5N*zLH$x5t`NHKmk&`jo%@&f%fsEZP^|26Nx>jy3KKy!$p zpqiNvnfA0S6Pz2`J&V5Z*Xq_ok$%C?f*#?j$5e;Hk{qN4%s456Uq5UVV=NTa0-p|; zMRzPX88Z1S;dauH6s-V@M7I~3gWhFPa^BtT=vB`lHfCbrCVTH8+Z{7cWKA&F%M_Ut9I}-+e3Tf9-zrk$YpX zahi|ukDA-=H@~vlwd?NoWY;VAn+NapJ#pHa5A$Dhwz4BUoCm(j55M)nw-W7Zt$p`f z`&PuYormx5JZxZwdDOh?Yxw$hgUq$k=KG~^Gw6K=69a4Q+mraeY5Nzx9VY!9UwDPT zZ|J;w0`8X`2r$0oyj^^=_8h^^ezr!NWeOH^W=91(^VU8jC^MV9kN>xd#a&(aWLJ~ws`nqTlex? zU$$+#S+K+}ZGX_b@nL80N;_^zI`=FMCR%PDNpIYe*nG19{k3mLq;sQi`^e2BiMKv_ z{W@V?tJ-+KY9pv!97s1bEe<}YYf5)@e_rxw$%^`u*&ofOx(?hdCd`S-2ldVA?w3A4 z_35d*+y6`dPy18dhi;x+IC`mkB3(HmA+KR&Sb;RrNO5aTz&J`)m&qzF@BI&R((sl9ljY( zmTh`i3-=eiJGEQDE6f2_UUO?ES>FEG<|yk=SJvG)dHrMpGkIsz7nKyzy`ky0_ojEz z`M8*?sJ%6FACM(nZ9Tb+KXxxyr-YYMHN6W*9+cLktLtxExPBqgo~rI#w5J=I6ZS;; zM@JS19@Ny+-53^q*|yxb+`c@vQoG{0+kRKQJAUuA)s2V0s6CRdtYt}m%jGLmw2wR z>+u{P&JUGp|3y^XiR4}F!1 z%1;{aG^SfR%%8eDb?FvA3f5Y-CtJ3sT6U&ey4G5HlP$femTg}bIm>oDvAddg{EBlG z?|fXwd8_{E>rSp#_zL^6|B=2TA8%dhNVV=-tK9wAiPC>o$SD8I{>sx;wq#Y?>AlY6 z9vpTSQfqd>4NT9b4~nPizys)BX4jJLj#qGLSB< zUUIIMG+jBIE~{NEymIs_N0qbntDY`r^V74u$GQJ$t;9Qb>JAsQw;qU1_BD z_!0nL3?Oxi4x}#8i4=GANZqpqez#W6r1Bu*CMiyieV`mj0;PupJNqUeOdl-^D!%;E zL-zG|gwMdS#lCFQgJJbz2zBPU3*(rb!6%Ch&6q?nI=Z|^>{B-j<|CgSsXXk3-BrW$ zr$Q-kAO<)4U)4vU3^O`dOy2mq^Z74XwD#VRXhZxV`4v`~;OMh^Wn02!Z!!het zIpc!McYhq?SVWRTk4T#3KIKpOommQ$gH}eS&e?`R9clg<0QnPoJ&r^nAf{XB`-iNF zx%y{$)e1_uN7@4^T=>AXvKF`Nh3Tp~{CJGFhwkDJORknIs!4a}(xsHU^I6|K*#@L$ zK7AFq@GmIfLY@5Z_@nD`bDIIcd}7vxChS+}qs&`@i}QFv%yngB%po_y2TvH+Jz1ea zw$BW_F~_)-=W*AGK5?DPya={yTVsxVcw$a?jS9vszdLN)0a%+3x#9n|-^}vTvgcdk zd|uUo*vOR7E`2kU7Y5gt-e-G4sN|3$|K^2 zaXSEw8kcX3R|EiR?y(ufIl`F_W5fD~6trS1KZ1H)>E%_8zo@v;h%plqouB?aO6L4| z_$hzye@@)>AJ7JFb{AJ!z2GLDz>}`6TPRM~)UVZSPu6T-Is0Wz|JB0_2NvF2Y)O~; z7G@t*2TC0~|%x*t!S)Fr$C8foDBy7ujOEH=J?#_xKw;IK14!k>`ePu*U61 z*-ivJ*#5*0i`zc83qku3?K-33K8eLgGZ9LXmt?3F9EA%m?W;^AgW3GAiGRsoeuY~M+}d$_-_3oi)m`_i_bngzan(;6e$=qq zje>oQUrzZQP=%n{z!t_v)MYa57p+3?FlP^E?@PAj*cjx`3Emd!(`+jKF81Zwf}a9p zZu9RjtOqm*n&1Dy{S$0ND5KxH{;jmv_u*|-rZf;DpCdQU}Qk7j#>|EP^Z1I}f zrOKuE7AI3a;Yk^g{aPUj_3Z;42Riv+wn(Q%W*h2XBBO6892|(U0?Xt2;+;*|42>uv zTg=3hvz7a34TlhSS{bL|7t}=6U&7KUS{R1uU6yWsbE%CwpFDYHH|5eQfb15Gn z-_+D$SyAMxSbXog`?~#c z1y@`5q>}TNrpv1q)ul6wJt?n%TTXB3ubHCp?N<))2zEl>=3~jpWl&`;D?VwK{}Lgs zC|mzPwq>_Bs!hqpWE!L(g7)lk6_Z}plE-XW`hazo>nA_X@;`iTf5egNo}B(j6X9bn z`AAL=mb4|WQ|6|B(z6Z~USm#^E%Rf@qT31(WLRnT*pp#)D%Zz^`xRSOzj-{}8Off% zUt?~Z>~nMe+RtWfmh|64s`Gm3Pv6W#=#w(t&2(>lKkPe2Um!EKzZAlk7&@=}3*`4f ztFDwDq8$1DbZPxBkkg#Z>j$u7R4%Y0^of6H<&UV~-%#>BN^T%gNXi?khpu`2DGKH` zK3DAJ2-kn4E%9e)pl=C?G3SGl@-)J9PTf4UyqzxP5z}(@BvcM{@$7?AA6yGdXA`}P zk^8=Oe1(3iV(Iip)z?cGo!B`P4N!8YWLf=u?$f!H(0{#nkzd@tRQaHyCSBJIr;zvq zf3j}#58wKH_|xILy{mP5?^o_kS8lj-z3j_E`;*l^fwPs&7~v_`04et@yP<3;peb#RtpzKl9m;oum@C0`xm3;7LS*N!;&or~wb=IHn9fx^=~-?&uu KD~^6y@Bar9`}mIl literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/other.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/other.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..06c804e5a741660f3ffe62b748741c56dd95af47 GIT binary patch literal 6881 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8e7ae7b4e29565beef0a3f23144bd67d429985e5 GIT binary patch literal 2962 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/svg.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/svg.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..30e7f5740c327ad1a4a4ec652d28478499cab6ce GIT binary patch literal 9143 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/_mapping.py b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/_mapping.py new file mode 100644 index 0000000..72ca840 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/_mapping.py @@ -0,0 +1,23 @@ +# Automatically generated by scripts/gen_mapfiles.py. +# DO NOT EDIT BY HAND; run `tox -e mapfiles` instead. + +FORMATTERS = { + 'BBCodeFormatter': ('pygments.formatters.bbcode', 'BBCode', ('bbcode', 'bb'), (), 'Format tokens with BBcodes. These formatting codes are used by many bulletin boards, so you can highlight your sourcecode with pygments before posting it there.'), + 'BmpImageFormatter': ('pygments.formatters.img', 'img_bmp', ('bmp', 'bitmap'), ('*.bmp',), 'Create a bitmap image from source code. This uses the Python Imaging Library to generate a pixmap from the source code.'), + 'GifImageFormatter': ('pygments.formatters.img', 'img_gif', ('gif',), ('*.gif',), 'Create a GIF image from source code. This uses the Python Imaging Library to generate a pixmap from the source code.'), + 'GroffFormatter': ('pygments.formatters.groff', 'groff', ('groff', 'troff', 'roff'), (), 'Format tokens with groff escapes to change their color and font style.'), + 'HtmlFormatter': ('pygments.formatters.html', 'HTML', ('html',), ('*.html', '*.htm'), "Format tokens as HTML 4 ```` tags. By default, the content is enclosed in a ``
    `` tag, itself wrapped in a ``
    `` tag (but see the `nowrap` option). The ``
    ``'s CSS class can be set by the `cssclass` option."), + 'IRCFormatter': ('pygments.formatters.irc', 'IRC', ('irc', 'IRC'), (), 'Format tokens with IRC color sequences'), + 'ImageFormatter': ('pygments.formatters.img', 'img', ('img', 'IMG', 'png'), ('*.png',), 'Create a PNG image from source code. This uses the Python Imaging Library to generate a pixmap from the source code.'), + 'JpgImageFormatter': ('pygments.formatters.img', 'img_jpg', ('jpg', 'jpeg'), ('*.jpg',), 'Create a JPEG image from source code. This uses the Python Imaging Library to generate a pixmap from the source code.'), + 'LatexFormatter': ('pygments.formatters.latex', 'LaTeX', ('latex', 'tex'), ('*.tex',), 'Format tokens as LaTeX code. This needs the `fancyvrb` and `color` standard packages.'), + 'NullFormatter': ('pygments.formatters.other', 'Text only', ('text', 'null'), ('*.txt',), 'Output the text unchanged without any formatting.'), + 'PangoMarkupFormatter': ('pygments.formatters.pangomarkup', 'Pango Markup', ('pango', 'pangomarkup'), (), 'Format tokens as Pango Markup code. It can then be rendered to an SVG.'), + 'RawTokenFormatter': ('pygments.formatters.other', 'Raw tokens', ('raw', 'tokens'), ('*.raw',), 'Format tokens as a raw representation for storing token streams.'), + 'RtfFormatter': ('pygments.formatters.rtf', 'RTF', ('rtf',), ('*.rtf',), 'Format tokens as RTF markup. This formatter automatically outputs full RTF documents with color information and other useful stuff. Perfect for Copy and Paste into Microsoft(R) Word(R) documents.'), + 'SvgFormatter': ('pygments.formatters.svg', 'SVG', ('svg',), ('*.svg',), 'Format tokens as an SVG graphics file. This formatter is still experimental. Each line of code is a ```` element with explicit ``x`` and ``y`` coordinates containing ```` elements with the individual token styles.'), + 'Terminal256Formatter': ('pygments.formatters.terminal256', 'Terminal256', ('terminal256', 'console256', '256'), (), 'Format tokens with ANSI color sequences, for output in a 256-color terminal or console. Like in `TerminalFormatter` color sequences are terminated at newlines, so that paging the output works correctly.'), + 'TerminalFormatter': ('pygments.formatters.terminal', 'Terminal', ('terminal', 'console'), (), 'Format tokens with ANSI color sequences, for output in a text console. Color sequences are terminated at newlines, so that paging the output works correctly.'), + 'TerminalTrueColorFormatter': ('pygments.formatters.terminal256', 'TerminalTrueColor', ('terminal16m', 'console16m', '16m'), (), 'Format tokens with ANSI color sequences, for output in a true-color terminal or console. Like in `TerminalFormatter` color sequences are terminated at newlines, so that paging the output works correctly.'), + 'TestcaseFormatter': ('pygments.formatters.other', 'Testcase', ('testcase',), (), 'Format tokens as appropriate for a new testcase.'), +} diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/bbcode.py b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/bbcode.py new file mode 100644 index 0000000..5a05bd9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/bbcode.py @@ -0,0 +1,108 @@ +""" + pygments.formatters.bbcode + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + BBcode formatter. + + :copyright: Copyright 2006-2024 by the Pygments team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + + +from pip._vendor.pygments.formatter import Formatter +from pip._vendor.pygments.util import get_bool_opt + +__all__ = ['BBCodeFormatter'] + + +class BBCodeFormatter(Formatter): + """ + Format tokens with BBcodes. These formatting codes are used by many + bulletin boards, so you can highlight your sourcecode with pygments before + posting it there. + + This formatter has no support for background colors and borders, as there + are no common BBcode tags for that. + + Some board systems (e.g. phpBB) don't support colors in their [code] tag, + so you can't use the highlighting together with that tag. + Text in a [code] tag usually is shown with a monospace font (which this + formatter can do with the ``monofont`` option) and no spaces (which you + need for indentation) are removed. + + Additional options accepted: + + `style` + The style to use, can be a string or a Style subclass (default: + ``'default'``). + + `codetag` + If set to true, put the output into ``[code]`` tags (default: + ``false``) + + `monofont` + If set to true, add a tag to show the code with a monospace font + (default: ``false``). + """ + name = 'BBCode' + aliases = ['bbcode', 'bb'] + filenames = [] + + def __init__(self, **options): + Formatter.__init__(self, **options) + self._code = get_bool_opt(options, 'codetag', False) + self._mono = get_bool_opt(options, 'monofont', False) + + self.styles = {} + self._make_styles() + + def _make_styles(self): + for ttype, ndef in self.style: + start = end = '' + if ndef['color']: + start += '[color=#{}]'.format(ndef['color']) + end = '[/color]' + end + if ndef['bold']: + start += '[b]' + end = '[/b]' + end + if ndef['italic']: + start += '[i]' + end = '[/i]' + end + if ndef['underline']: + start += '[u]' + end = '[/u]' + end + # there are no common BBcodes for background-color and border + + self.styles[ttype] = start, end + + def format_unencoded(self, tokensource, outfile): + if self._code: + outfile.write('[code]') + if self._mono: + outfile.write('[font=monospace]') + + lastval = '' + lasttype = None + + for ttype, value in tokensource: + while ttype not in self.styles: + ttype = ttype.parent + if ttype == lasttype: + lastval += value + else: + if lastval: + start, end = self.styles[lasttype] + outfile.write(''.join((start, lastval, end))) + lastval = value + lasttype = ttype + + if lastval: + start, end = self.styles[lasttype] + outfile.write(''.join((start, lastval, end))) + + if self._mono: + outfile.write('[/font]') + if self._code: + outfile.write('[/code]') + if self._code or self._mono: + outfile.write('\n') diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/groff.py b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/groff.py new file mode 100644 index 0000000..5c8a958 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/groff.py @@ -0,0 +1,170 @@ +""" + pygments.formatters.groff + ~~~~~~~~~~~~~~~~~~~~~~~~~ + + Formatter for groff output. + + :copyright: Copyright 2006-2024 by the Pygments team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import math +from pip._vendor.pygments.formatter import Formatter +from pip._vendor.pygments.util import get_bool_opt, get_int_opt + +__all__ = ['GroffFormatter'] + + +class GroffFormatter(Formatter): + """ + Format tokens with groff escapes to change their color and font style. + + .. versionadded:: 2.11 + + Additional options accepted: + + `style` + The style to use, can be a string or a Style subclass (default: + ``'default'``). + + `monospaced` + If set to true, monospace font will be used (default: ``true``). + + `linenos` + If set to true, print the line numbers (default: ``false``). + + `wrap` + Wrap lines to the specified number of characters. Disabled if set to 0 + (default: ``0``). + """ + + name = 'groff' + aliases = ['groff','troff','roff'] + filenames = [] + + def __init__(self, **options): + Formatter.__init__(self, **options) + + self.monospaced = get_bool_opt(options, 'monospaced', True) + self.linenos = get_bool_opt(options, 'linenos', False) + self._lineno = 0 + self.wrap = get_int_opt(options, 'wrap', 0) + self._linelen = 0 + + self.styles = {} + self._make_styles() + + + def _make_styles(self): + regular = '\\f[CR]' if self.monospaced else '\\f[R]' + bold = '\\f[CB]' if self.monospaced else '\\f[B]' + italic = '\\f[CI]' if self.monospaced else '\\f[I]' + + for ttype, ndef in self.style: + start = end = '' + if ndef['color']: + start += '\\m[{}]'.format(ndef['color']) + end = '\\m[]' + end + if ndef['bold']: + start += bold + end = regular + end + if ndef['italic']: + start += italic + end = regular + end + if ndef['bgcolor']: + start += '\\M[{}]'.format(ndef['bgcolor']) + end = '\\M[]' + end + + self.styles[ttype] = start, end + + + def _define_colors(self, outfile): + colors = set() + for _, ndef in self.style: + if ndef['color'] is not None: + colors.add(ndef['color']) + + for color in sorted(colors): + outfile.write('.defcolor ' + color + ' rgb #' + color + '\n') + + + def _write_lineno(self, outfile): + self._lineno += 1 + outfile.write("%s% 4d " % (self._lineno != 1 and '\n' or '', self._lineno)) + + + def _wrap_line(self, line): + length = len(line.rstrip('\n')) + space = ' ' if self.linenos else '' + newline = '' + + if length > self.wrap: + for i in range(0, math.floor(length / self.wrap)): + chunk = line[i*self.wrap:i*self.wrap+self.wrap] + newline += (chunk + '\n' + space) + remainder = length % self.wrap + if remainder > 0: + newline += line[-remainder-1:] + self._linelen = remainder + elif self._linelen + length > self.wrap: + newline = ('\n' + space) + line + self._linelen = length + else: + newline = line + self._linelen += length + + return newline + + + def _escape_chars(self, text): + text = text.replace('\\', '\\[u005C]'). \ + replace('.', '\\[char46]'). \ + replace('\'', '\\[u0027]'). \ + replace('`', '\\[u0060]'). \ + replace('~', '\\[u007E]') + copy = text + + for char in copy: + if len(char) != len(char.encode()): + uni = char.encode('unicode_escape') \ + .decode()[1:] \ + .replace('x', 'u00') \ + .upper() + text = text.replace(char, '\\[u' + uni[1:] + ']') + + return text + + + def format_unencoded(self, tokensource, outfile): + self._define_colors(outfile) + + outfile.write('.nf\n\\f[CR]\n') + + if self.linenos: + self._write_lineno(outfile) + + for ttype, value in tokensource: + while ttype not in self.styles: + ttype = ttype.parent + start, end = self.styles[ttype] + + for line in value.splitlines(True): + if self.wrap > 0: + line = self._wrap_line(line) + + if start and end: + text = self._escape_chars(line.rstrip('\n')) + if text != '': + outfile.write(''.join((start, text, end))) + else: + outfile.write(self._escape_chars(line.rstrip('\n'))) + + if line.endswith('\n'): + if self.linenos: + self._write_lineno(outfile) + self._linelen = 0 + else: + outfile.write('\n') + self._linelen = 0 + + outfile.write('\n.fi') diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/html.py b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/html.py new file mode 100644 index 0000000..7aa938f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/html.py @@ -0,0 +1,987 @@ +""" + pygments.formatters.html + ~~~~~~~~~~~~~~~~~~~~~~~~ + + Formatter for HTML output. + + :copyright: Copyright 2006-2024 by the Pygments team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import functools +import os +import sys +import os.path +from io import StringIO + +from pip._vendor.pygments.formatter import Formatter +from pip._vendor.pygments.token import Token, Text, STANDARD_TYPES +from pip._vendor.pygments.util import get_bool_opt, get_int_opt, get_list_opt + +try: + import ctags +except ImportError: + ctags = None + +__all__ = ['HtmlFormatter'] + + +_escape_html_table = { + ord('&'): '&', + ord('<'): '<', + ord('>'): '>', + ord('"'): '"', + ord("'"): ''', +} + + +def escape_html(text, table=_escape_html_table): + """Escape &, <, > as well as single and double quotes for HTML.""" + return text.translate(table) + + +def webify(color): + if color.startswith('calc') or color.startswith('var'): + return color + else: + return '#' + color + + +def _get_ttype_class(ttype): + fname = STANDARD_TYPES.get(ttype) + if fname: + return fname + aname = '' + while fname is None: + aname = '-' + ttype[-1] + aname + ttype = ttype.parent + fname = STANDARD_TYPES.get(ttype) + return fname + aname + + +CSSFILE_TEMPLATE = '''\ +/* +generated by Pygments +Copyright 2006-2024 by the Pygments team. +Licensed under the BSD license, see LICENSE for details. +*/ +%(styledefs)s +''' + +DOC_HEADER = '''\ + + + + + %(title)s + + + + +

    %(title)s

    + +''' + +DOC_HEADER_EXTERNALCSS = '''\ + + + + + %(title)s + + + + +

    %(title)s

    + +''' + +DOC_FOOTER = '''\ + + +''' + + +class HtmlFormatter(Formatter): + r""" + Format tokens as HTML 4 ```` tags. By default, the content is enclosed + in a ``
    `` tag, itself wrapped in a ``
    `` tag (but see the `nowrap` option). + The ``
    ``'s CSS class can be set by the `cssclass` option. + + If the `linenos` option is set to ``"table"``, the ``
    `` is
    +    additionally wrapped inside a ```` which has one row and two
    +    cells: one containing the line numbers and one containing the code.
    +    Example:
    +
    +    .. sourcecode:: html
    +
    +        
    +
    + + +
    +
    1
    +            2
    +
    +
    def foo(bar):
    +              pass
    +            
    +
    + + (whitespace added to improve clarity). + + A list of lines can be specified using the `hl_lines` option to make these + lines highlighted (as of Pygments 0.11). + + With the `full` option, a complete HTML 4 document is output, including + the style definitions inside a `` + + +
    {code}
    + + +""" + +CONSOLE_SVG_FORMAT = """\ + + + + + + + + + {lines} + + + {chrome} + + {backgrounds} + + {matrix} + + + +""" + +_SVG_FONT_FAMILY = "Rich Fira Code" +_SVG_CLASSES_PREFIX = "rich-svg" diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/_extension.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_extension.py new file mode 100644 index 0000000..cbd6da9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_extension.py @@ -0,0 +1,10 @@ +from typing import Any + + +def load_ipython_extension(ip: Any) -> None: # pragma: no cover + # prevent circular import + from pip._vendor.rich.pretty import install + from pip._vendor.rich.traceback import install as tr_install + + install() + tr_install() diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/_fileno.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_fileno.py new file mode 100644 index 0000000..b17ee65 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_fileno.py @@ -0,0 +1,24 @@ +from __future__ import annotations + +from typing import IO, Callable + + +def get_fileno(file_like: IO[str]) -> int | None: + """Get fileno() from a file, accounting for poorly implemented file-like objects. + + Args: + file_like (IO): A file-like object. + + Returns: + int | None: The result of fileno if available, or None if operation failed. + """ + fileno: Callable[[], int] | None = getattr(file_like, "fileno", None) + if fileno is not None: + try: + return fileno() + except Exception: + # `fileno` is documented as potentially raising a OSError + # Alas, from the issues, there are so many poorly implemented file-like objects, + # that `fileno()` can raise just about anything. + return None + return None diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/_inspect.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_inspect.py new file mode 100644 index 0000000..30446ce --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_inspect.py @@ -0,0 +1,270 @@ +from __future__ import absolute_import + +import inspect +from inspect import cleandoc, getdoc, getfile, isclass, ismodule, signature +from typing import Any, Collection, Iterable, Optional, Tuple, Type, Union + +from .console import Group, RenderableType +from .control import escape_control_codes +from .highlighter import ReprHighlighter +from .jupyter import JupyterMixin +from .panel import Panel +from .pretty import Pretty +from .table import Table +from .text import Text, TextType + + +def _first_paragraph(doc: str) -> str: + """Get the first paragraph from a docstring.""" + paragraph, _, _ = doc.partition("\n\n") + return paragraph + + +class Inspect(JupyterMixin): + """A renderable to inspect any Python Object. + + Args: + obj (Any): An object to inspect. + title (str, optional): Title to display over inspect result, or None use type. Defaults to None. + help (bool, optional): Show full help text rather than just first paragraph. Defaults to False. + methods (bool, optional): Enable inspection of callables. Defaults to False. + docs (bool, optional): Also render doc strings. Defaults to True. + private (bool, optional): Show private attributes (beginning with underscore). Defaults to False. + dunder (bool, optional): Show attributes starting with double underscore. Defaults to False. + sort (bool, optional): Sort attributes alphabetically. Defaults to True. + all (bool, optional): Show all attributes. Defaults to False. + value (bool, optional): Pretty print value of object. Defaults to True. + """ + + def __init__( + self, + obj: Any, + *, + title: Optional[TextType] = None, + help: bool = False, + methods: bool = False, + docs: bool = True, + private: bool = False, + dunder: bool = False, + sort: bool = True, + all: bool = True, + value: bool = True, + ) -> None: + self.highlighter = ReprHighlighter() + self.obj = obj + self.title = title or self._make_title(obj) + if all: + methods = private = dunder = True + self.help = help + self.methods = methods + self.docs = docs or help + self.private = private or dunder + self.dunder = dunder + self.sort = sort + self.value = value + + def _make_title(self, obj: Any) -> Text: + """Make a default title.""" + title_str = ( + str(obj) + if (isclass(obj) or callable(obj) or ismodule(obj)) + else str(type(obj)) + ) + title_text = self.highlighter(title_str) + return title_text + + def __rich__(self) -> Panel: + return Panel.fit( + Group(*self._render()), + title=self.title, + border_style="scope.border", + padding=(0, 1), + ) + + def _get_signature(self, name: str, obj: Any) -> Optional[Text]: + """Get a signature for a callable.""" + try: + _signature = str(signature(obj)) + ":" + except ValueError: + _signature = "(...)" + except TypeError: + return None + + source_filename: Optional[str] = None + try: + source_filename = getfile(obj) + except (OSError, TypeError): + # OSError is raised if obj has no source file, e.g. when defined in REPL. + pass + + callable_name = Text(name, style="inspect.callable") + if source_filename: + callable_name.stylize(f"link file://{source_filename}") + signature_text = self.highlighter(_signature) + + qualname = name or getattr(obj, "__qualname__", name) + + # If obj is a module, there may be classes (which are callable) to display + if inspect.isclass(obj): + prefix = "class" + elif inspect.iscoroutinefunction(obj): + prefix = "async def" + else: + prefix = "def" + + qual_signature = Text.assemble( + (f"{prefix} ", f"inspect.{prefix.replace(' ', '_')}"), + (qualname, "inspect.callable"), + signature_text, + ) + + return qual_signature + + def _render(self) -> Iterable[RenderableType]: + """Render object.""" + + def sort_items(item: Tuple[str, Any]) -> Tuple[bool, str]: + key, (_error, value) = item + return (callable(value), key.strip("_").lower()) + + def safe_getattr(attr_name: str) -> Tuple[Any, Any]: + """Get attribute or any exception.""" + try: + return (None, getattr(obj, attr_name)) + except Exception as error: + return (error, None) + + obj = self.obj + keys = dir(obj) + total_items = len(keys) + if not self.dunder: + keys = [key for key in keys if not key.startswith("__")] + if not self.private: + keys = [key for key in keys if not key.startswith("_")] + not_shown_count = total_items - len(keys) + items = [(key, safe_getattr(key)) for key in keys] + if self.sort: + items.sort(key=sort_items) + + items_table = Table.grid(padding=(0, 1), expand=False) + items_table.add_column(justify="right") + add_row = items_table.add_row + highlighter = self.highlighter + + if callable(obj): + signature = self._get_signature("", obj) + if signature is not None: + yield signature + yield "" + + if self.docs: + _doc = self._get_formatted_doc(obj) + if _doc is not None: + doc_text = Text(_doc, style="inspect.help") + doc_text = highlighter(doc_text) + yield doc_text + yield "" + + if self.value and not (isclass(obj) or callable(obj) or ismodule(obj)): + yield Panel( + Pretty(obj, indent_guides=True, max_length=10, max_string=60), + border_style="inspect.value.border", + ) + yield "" + + for key, (error, value) in items: + key_text = Text.assemble( + ( + key, + "inspect.attr.dunder" if key.startswith("__") else "inspect.attr", + ), + (" =", "inspect.equals"), + ) + if error is not None: + warning = key_text.copy() + warning.stylize("inspect.error") + add_row(warning, highlighter(repr(error))) + continue + + if callable(value): + if not self.methods: + continue + + _signature_text = self._get_signature(key, value) + if _signature_text is None: + add_row(key_text, Pretty(value, highlighter=highlighter)) + else: + if self.docs: + docs = self._get_formatted_doc(value) + if docs is not None: + _signature_text.append("\n" if "\n" in docs else " ") + doc = highlighter(docs) + doc.stylize("inspect.doc") + _signature_text.append(doc) + + add_row(key_text, _signature_text) + else: + add_row(key_text, Pretty(value, highlighter=highlighter)) + if items_table.row_count: + yield items_table + elif not_shown_count: + yield Text.from_markup( + f"[b cyan]{not_shown_count}[/][i] attribute(s) not shown.[/i] " + f"Run [b][magenta]inspect[/]([not b]inspect[/])[/b] for options." + ) + + def _get_formatted_doc(self, object_: Any) -> Optional[str]: + """ + Extract the docstring of an object, process it and returns it. + The processing consists in cleaning up the doctring's indentation, + taking only its 1st paragraph if `self.help` is not True, + and escape its control codes. + + Args: + object_ (Any): the object to get the docstring from. + + Returns: + Optional[str]: the processed docstring, or None if no docstring was found. + """ + docs = getdoc(object_) + if docs is None: + return None + docs = cleandoc(docs).strip() + if not self.help: + docs = _first_paragraph(docs) + return escape_control_codes(docs) + + +def get_object_types_mro(obj: Union[object, Type[Any]]) -> Tuple[type, ...]: + """Returns the MRO of an object's class, or of the object itself if it's a class.""" + if not hasattr(obj, "__mro__"): + # N.B. we cannot use `if type(obj) is type` here because it doesn't work with + # some types of classes, such as the ones that use abc.ABCMeta. + obj = type(obj) + return getattr(obj, "__mro__", ()) + + +def get_object_types_mro_as_strings(obj: object) -> Collection[str]: + """ + Returns the MRO of an object's class as full qualified names, or of the object itself if it's a class. + + Examples: + `object_types_mro_as_strings(JSONDecoder)` will return `['json.decoder.JSONDecoder', 'builtins.object']` + """ + return [ + f'{getattr(type_, "__module__", "")}.{getattr(type_, "__qualname__", "")}' + for type_ in get_object_types_mro(obj) + ] + + +def is_object_one_of_types( + obj: object, fully_qualified_types_names: Collection[str] +) -> bool: + """ + Returns `True` if the given object's class (or the object itself, if it's a class) has one of the + fully qualified names in its MRO. + """ + for type_name in get_object_types_mro_as_strings(obj): + if type_name in fully_qualified_types_names: + return True + return False diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/_log_render.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_log_render.py new file mode 100644 index 0000000..fc16c84 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_log_render.py @@ -0,0 +1,94 @@ +from datetime import datetime +from typing import Iterable, List, Optional, TYPE_CHECKING, Union, Callable + + +from .text import Text, TextType + +if TYPE_CHECKING: + from .console import Console, ConsoleRenderable, RenderableType + from .table import Table + +FormatTimeCallable = Callable[[datetime], Text] + + +class LogRender: + def __init__( + self, + show_time: bool = True, + show_level: bool = False, + show_path: bool = True, + time_format: Union[str, FormatTimeCallable] = "[%x %X]", + omit_repeated_times: bool = True, + level_width: Optional[int] = 8, + ) -> None: + self.show_time = show_time + self.show_level = show_level + self.show_path = show_path + self.time_format = time_format + self.omit_repeated_times = omit_repeated_times + self.level_width = level_width + self._last_time: Optional[Text] = None + + def __call__( + self, + console: "Console", + renderables: Iterable["ConsoleRenderable"], + log_time: Optional[datetime] = None, + time_format: Optional[Union[str, FormatTimeCallable]] = None, + level: TextType = "", + path: Optional[str] = None, + line_no: Optional[int] = None, + link_path: Optional[str] = None, + ) -> "Table": + from .containers import Renderables + from .table import Table + + output = Table.grid(padding=(0, 1)) + output.expand = True + if self.show_time: + output.add_column(style="log.time") + if self.show_level: + output.add_column(style="log.level", width=self.level_width) + output.add_column(ratio=1, style="log.message", overflow="fold") + if self.show_path and path: + output.add_column(style="log.path") + row: List["RenderableType"] = [] + if self.show_time: + log_time = log_time or console.get_datetime() + time_format = time_format or self.time_format + if callable(time_format): + log_time_display = time_format(log_time) + else: + log_time_display = Text(log_time.strftime(time_format)) + if log_time_display == self._last_time and self.omit_repeated_times: + row.append(Text(" " * len(log_time_display))) + else: + row.append(log_time_display) + self._last_time = log_time_display + if self.show_level: + row.append(level) + + row.append(Renderables(renderables)) + if self.show_path and path: + path_text = Text() + path_text.append( + path, style=f"link file://{link_path}" if link_path else "" + ) + if line_no: + path_text.append(":") + path_text.append( + f"{line_no}", + style=f"link file://{link_path}#{line_no}" if link_path else "", + ) + row.append(path_text) + + output.add_row(*row) + return output + + +if __name__ == "__main__": # pragma: no cover + from pip._vendor.rich.console import Console + + c = Console() + c.print("[on blue]Hello", justify="right") + c.log("[on blue]hello", justify="right") diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/_loop.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_loop.py new file mode 100644 index 0000000..01c6caf --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_loop.py @@ -0,0 +1,43 @@ +from typing import Iterable, Tuple, TypeVar + +T = TypeVar("T") + + +def loop_first(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: + """Iterate and generate a tuple with a flag for first value.""" + iter_values = iter(values) + try: + value = next(iter_values) + except StopIteration: + return + yield True, value + for value in iter_values: + yield False, value + + +def loop_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: + """Iterate and generate a tuple with a flag for last value.""" + iter_values = iter(values) + try: + previous_value = next(iter_values) + except StopIteration: + return + for value in iter_values: + yield False, previous_value + previous_value = value + yield True, previous_value + + +def loop_first_last(values: Iterable[T]) -> Iterable[Tuple[bool, bool, T]]: + """Iterate and generate a tuple with a flag for first and last value.""" + iter_values = iter(values) + try: + previous_value = next(iter_values) + except StopIteration: + return + first = True + for value in iter_values: + yield first, False, previous_value + first = False + previous_value = value + yield first, True, previous_value diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/_null_file.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_null_file.py new file mode 100644 index 0000000..b659673 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_null_file.py @@ -0,0 +1,69 @@ +from types import TracebackType +from typing import IO, Iterable, Iterator, List, Optional, Type + + +class NullFile(IO[str]): + def close(self) -> None: + pass + + def isatty(self) -> bool: + return False + + def read(self, __n: int = 1) -> str: + return "" + + def readable(self) -> bool: + return False + + def readline(self, __limit: int = 1) -> str: + return "" + + def readlines(self, __hint: int = 1) -> List[str]: + return [] + + def seek(self, __offset: int, __whence: int = 1) -> int: + return 0 + + def seekable(self) -> bool: + return False + + def tell(self) -> int: + return 0 + + def truncate(self, __size: Optional[int] = 1) -> int: + return 0 + + def writable(self) -> bool: + return False + + def writelines(self, __lines: Iterable[str]) -> None: + pass + + def __next__(self) -> str: + return "" + + def __iter__(self) -> Iterator[str]: + return iter([""]) + + def __enter__(self) -> IO[str]: + pass + + def __exit__( + self, + __t: Optional[Type[BaseException]], + __value: Optional[BaseException], + __traceback: Optional[TracebackType], + ) -> None: + pass + + def write(self, text: str) -> int: + return 0 + + def flush(self) -> None: + pass + + def fileno(self) -> int: + return -1 + + +NULL_FILE = NullFile() diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/_palettes.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_palettes.py new file mode 100644 index 0000000..3c748d3 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_palettes.py @@ -0,0 +1,309 @@ +from .palette import Palette + + +# Taken from https://en.wikipedia.org/wiki/ANSI_escape_code (Windows 10 column) +WINDOWS_PALETTE = Palette( + [ + (12, 12, 12), + (197, 15, 31), + (19, 161, 14), + (193, 156, 0), + (0, 55, 218), + (136, 23, 152), + (58, 150, 221), + (204, 204, 204), + (118, 118, 118), + (231, 72, 86), + (22, 198, 12), + (249, 241, 165), + (59, 120, 255), + (180, 0, 158), + (97, 214, 214), + (242, 242, 242), + ] +) + +# # The standard ansi colors (including bright variants) +STANDARD_PALETTE = Palette( + [ + (0, 0, 0), + (170, 0, 0), + (0, 170, 0), + (170, 85, 0), + (0, 0, 170), + (170, 0, 170), + (0, 170, 170), + (170, 170, 170), + (85, 85, 85), + (255, 85, 85), + (85, 255, 85), + (255, 255, 85), + (85, 85, 255), + (255, 85, 255), + (85, 255, 255), + (255, 255, 255), + ] +) + + +# The 256 color palette +EIGHT_BIT_PALETTE = Palette( + [ + (0, 0, 0), + (128, 0, 0), + (0, 128, 0), + (128, 128, 0), + (0, 0, 128), + (128, 0, 128), + (0, 128, 128), + (192, 192, 192), + (128, 128, 128), + (255, 0, 0), + (0, 255, 0), + (255, 255, 0), + (0, 0, 255), + (255, 0, 255), + (0, 255, 255), + (255, 255, 255), + (0, 0, 0), + (0, 0, 95), + (0, 0, 135), + (0, 0, 175), + (0, 0, 215), + (0, 0, 255), + (0, 95, 0), + (0, 95, 95), + (0, 95, 135), + (0, 95, 175), + (0, 95, 215), + (0, 95, 255), + (0, 135, 0), + (0, 135, 95), + (0, 135, 135), + (0, 135, 175), + (0, 135, 215), + (0, 135, 255), + (0, 175, 0), + (0, 175, 95), + (0, 175, 135), + (0, 175, 175), + (0, 175, 215), + (0, 175, 255), + (0, 215, 0), + (0, 215, 95), + (0, 215, 135), + (0, 215, 175), + (0, 215, 215), + (0, 215, 255), + (0, 255, 0), + (0, 255, 95), + (0, 255, 135), + (0, 255, 175), + (0, 255, 215), + (0, 255, 255), + (95, 0, 0), + (95, 0, 95), + (95, 0, 135), + (95, 0, 175), + (95, 0, 215), + (95, 0, 255), + (95, 95, 0), + (95, 95, 95), + (95, 95, 135), + (95, 95, 175), + (95, 95, 215), + (95, 95, 255), + (95, 135, 0), + (95, 135, 95), + (95, 135, 135), + (95, 135, 175), + (95, 135, 215), + (95, 135, 255), + (95, 175, 0), + (95, 175, 95), + (95, 175, 135), + (95, 175, 175), + (95, 175, 215), + (95, 175, 255), + (95, 215, 0), + (95, 215, 95), + (95, 215, 135), + (95, 215, 175), + (95, 215, 215), + (95, 215, 255), + (95, 255, 0), + (95, 255, 95), + (95, 255, 135), + (95, 255, 175), + (95, 255, 215), + (95, 255, 255), + (135, 0, 0), + (135, 0, 95), + (135, 0, 135), + (135, 0, 175), + (135, 0, 215), + (135, 0, 255), + (135, 95, 0), + (135, 95, 95), + (135, 95, 135), + (135, 95, 175), + (135, 95, 215), + (135, 95, 255), + (135, 135, 0), + (135, 135, 95), + (135, 135, 135), + (135, 135, 175), + (135, 135, 215), + (135, 135, 255), + (135, 175, 0), + (135, 175, 95), + (135, 175, 135), + (135, 175, 175), + (135, 175, 215), + (135, 175, 255), + (135, 215, 0), + (135, 215, 95), + (135, 215, 135), + (135, 215, 175), + (135, 215, 215), + (135, 215, 255), + (135, 255, 0), + (135, 255, 95), + (135, 255, 135), + (135, 255, 175), + (135, 255, 215), + (135, 255, 255), + (175, 0, 0), + (175, 0, 95), + (175, 0, 135), + (175, 0, 175), + (175, 0, 215), + (175, 0, 255), + (175, 95, 0), + (175, 95, 95), + (175, 95, 135), + (175, 95, 175), + (175, 95, 215), + (175, 95, 255), + (175, 135, 0), + (175, 135, 95), + (175, 135, 135), + (175, 135, 175), + (175, 135, 215), + (175, 135, 255), + (175, 175, 0), + (175, 175, 95), + (175, 175, 135), + (175, 175, 175), + (175, 175, 215), + (175, 175, 255), + (175, 215, 0), + (175, 215, 95), + (175, 215, 135), + (175, 215, 175), + (175, 215, 215), + (175, 215, 255), + (175, 255, 0), + (175, 255, 95), + (175, 255, 135), + (175, 255, 175), + (175, 255, 215), + (175, 255, 255), + (215, 0, 0), + (215, 0, 95), + (215, 0, 135), + (215, 0, 175), + (215, 0, 215), + (215, 0, 255), + (215, 95, 0), + (215, 95, 95), + (215, 95, 135), + (215, 95, 175), + (215, 95, 215), + (215, 95, 255), + (215, 135, 0), + (215, 135, 95), + (215, 135, 135), + (215, 135, 175), + (215, 135, 215), + (215, 135, 255), + (215, 175, 0), + (215, 175, 95), + (215, 175, 135), + (215, 175, 175), + (215, 175, 215), + (215, 175, 255), + (215, 215, 0), + (215, 215, 95), + (215, 215, 135), + (215, 215, 175), + (215, 215, 215), + (215, 215, 255), + (215, 255, 0), + (215, 255, 95), + (215, 255, 135), + (215, 255, 175), + (215, 255, 215), + (215, 255, 255), + (255, 0, 0), + (255, 0, 95), + (255, 0, 135), + (255, 0, 175), + (255, 0, 215), + (255, 0, 255), + (255, 95, 0), + (255, 95, 95), + (255, 95, 135), + (255, 95, 175), + (255, 95, 215), + (255, 95, 255), + (255, 135, 0), + (255, 135, 95), + (255, 135, 135), + (255, 135, 175), + (255, 135, 215), + (255, 135, 255), + (255, 175, 0), + (255, 175, 95), + (255, 175, 135), + (255, 175, 175), + (255, 175, 215), + (255, 175, 255), + (255, 215, 0), + (255, 215, 95), + (255, 215, 135), + (255, 215, 175), + (255, 215, 215), + (255, 215, 255), + (255, 255, 0), + (255, 255, 95), + (255, 255, 135), + (255, 255, 175), + (255, 255, 215), + (255, 255, 255), + (8, 8, 8), + (18, 18, 18), + (28, 28, 28), + (38, 38, 38), + (48, 48, 48), + (58, 58, 58), + (68, 68, 68), + (78, 78, 78), + (88, 88, 88), + (98, 98, 98), + (108, 108, 108), + (118, 118, 118), + (128, 128, 128), + (138, 138, 138), + (148, 148, 148), + (158, 158, 158), + (168, 168, 168), + (178, 178, 178), + (188, 188, 188), + (198, 198, 198), + (208, 208, 208), + (218, 218, 218), + (228, 228, 228), + (238, 238, 238), + ] +) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/_pick.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_pick.py new file mode 100644 index 0000000..4f6d8b2 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_pick.py @@ -0,0 +1,17 @@ +from typing import Optional + + +def pick_bool(*values: Optional[bool]) -> bool: + """Pick the first non-none bool or return the last value. + + Args: + *values (bool): Any number of boolean or None values. + + Returns: + bool: First non-none boolean. + """ + assert values, "1 or more values required" + for value in values: + if value is not None: + return value + return bool(value) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/_ratio.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_ratio.py new file mode 100644 index 0000000..95267b0 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_ratio.py @@ -0,0 +1,159 @@ +import sys +from fractions import Fraction +from math import ceil +from typing import cast, List, Optional, Sequence + +if sys.version_info >= (3, 8): + from typing import Protocol +else: + from pip._vendor.typing_extensions import Protocol # pragma: no cover + + +class Edge(Protocol): + """Any object that defines an edge (such as Layout).""" + + size: Optional[int] = None + ratio: int = 1 + minimum_size: int = 1 + + +def ratio_resolve(total: int, edges: Sequence[Edge]) -> List[int]: + """Divide total space to satisfy size, ratio, and minimum_size, constraints. + + The returned list of integers should add up to total in most cases, unless it is + impossible to satisfy all the constraints. For instance, if there are two edges + with a minimum size of 20 each and `total` is 30 then the returned list will be + greater than total. In practice, this would mean that a Layout object would + clip the rows that would overflow the screen height. + + Args: + total (int): Total number of characters. + edges (List[Edge]): Edges within total space. + + Returns: + List[int]: Number of characters for each edge. + """ + # Size of edge or None for yet to be determined + sizes = [(edge.size or None) for edge in edges] + + _Fraction = Fraction + + # While any edges haven't been calculated + while None in sizes: + # Get flexible edges and index to map these back on to sizes list + flexible_edges = [ + (index, edge) + for index, (size, edge) in enumerate(zip(sizes, edges)) + if size is None + ] + # Remaining space in total + remaining = total - sum(size or 0 for size in sizes) + if remaining <= 0: + # No room for flexible edges + return [ + ((edge.minimum_size or 1) if size is None else size) + for size, edge in zip(sizes, edges) + ] + # Calculate number of characters in a ratio portion + portion = _Fraction( + remaining, sum((edge.ratio or 1) for _, edge in flexible_edges) + ) + + # If any edges will be less than their minimum, replace size with the minimum + for index, edge in flexible_edges: + if portion * edge.ratio <= edge.minimum_size: + sizes[index] = edge.minimum_size + # New fixed size will invalidate calculations, so we need to repeat the process + break + else: + # Distribute flexible space and compensate for rounding error + # Since edge sizes can only be integers we need to add the remainder + # to the following line + remainder = _Fraction(0) + for index, edge in flexible_edges: + size, remainder = divmod(portion * edge.ratio + remainder, 1) + sizes[index] = size + break + # Sizes now contains integers only + return cast(List[int], sizes) + + +def ratio_reduce( + total: int, ratios: List[int], maximums: List[int], values: List[int] +) -> List[int]: + """Divide an integer total in to parts based on ratios. + + Args: + total (int): The total to divide. + ratios (List[int]): A list of integer ratios. + maximums (List[int]): List of maximums values for each slot. + values (List[int]): List of values + + Returns: + List[int]: A list of integers guaranteed to sum to total. + """ + ratios = [ratio if _max else 0 for ratio, _max in zip(ratios, maximums)] + total_ratio = sum(ratios) + if not total_ratio: + return values[:] + total_remaining = total + result: List[int] = [] + append = result.append + for ratio, maximum, value in zip(ratios, maximums, values): + if ratio and total_ratio > 0: + distributed = min(maximum, round(ratio * total_remaining / total_ratio)) + append(value - distributed) + total_remaining -= distributed + total_ratio -= ratio + else: + append(value) + return result + + +def ratio_distribute( + total: int, ratios: List[int], minimums: Optional[List[int]] = None +) -> List[int]: + """Distribute an integer total in to parts based on ratios. + + Args: + total (int): The total to divide. + ratios (List[int]): A list of integer ratios. + minimums (List[int]): List of minimum values for each slot. + + Returns: + List[int]: A list of integers guaranteed to sum to total. + """ + if minimums: + ratios = [ratio if _min else 0 for ratio, _min in zip(ratios, minimums)] + total_ratio = sum(ratios) + assert total_ratio > 0, "Sum of ratios must be > 0" + + total_remaining = total + distributed_total: List[int] = [] + append = distributed_total.append + if minimums is None: + _minimums = [0] * len(ratios) + else: + _minimums = minimums + for ratio, minimum in zip(ratios, _minimums): + if total_ratio > 0: + distributed = max(minimum, ceil(ratio * total_remaining / total_ratio)) + else: + distributed = total_remaining + append(distributed) + total_ratio -= ratio + total_remaining -= distributed + return distributed_total + + +if __name__ == "__main__": + from dataclasses import dataclass + + @dataclass + class E: + size: Optional[int] = None + ratio: int = 1 + minimum_size: int = 1 + + resolved = ratio_resolve(110, [E(None, 1, 1), E(None, 1, 1), E(None, 1, 1)]) + print(sum(resolved)) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/_spinners.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_spinners.py new file mode 100644 index 0000000..d0bb1fe --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_spinners.py @@ -0,0 +1,482 @@ +""" +Spinners are from: +* cli-spinners: + MIT License + Copyright (c) Sindre Sorhus (sindresorhus.com) + 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. +""" + +SPINNERS = { + "dots": { + "interval": 80, + "frames": "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏", + }, + "dots2": {"interval": 80, "frames": "⣾⣽⣻⢿⡿⣟⣯⣷"}, + "dots3": { + "interval": 80, + "frames": "⠋⠙⠚⠞⠖⠦⠴⠲⠳⠓", + }, + "dots4": { + "interval": 80, + "frames": "⠄⠆⠇⠋⠙⠸⠰⠠⠰⠸⠙⠋⠇⠆", + }, + "dots5": { + "interval": 80, + "frames": "⠋⠙⠚⠒⠂⠂⠒⠲⠴⠦⠖⠒⠐⠐⠒⠓⠋", + }, + "dots6": { + "interval": 80, + "frames": "⠁⠉⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄⠄⠤⠴⠲⠒⠂⠂⠒⠚⠙⠉⠁", + }, + "dots7": { + "interval": 80, + "frames": "⠈⠉⠋⠓⠒⠐⠐⠒⠖⠦⠤⠠⠠⠤⠦⠖⠒⠐⠐⠒⠓⠋⠉⠈", + }, + "dots8": { + "interval": 80, + "frames": "⠁⠁⠉⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄⠄⠤⠠⠠⠤⠦⠖⠒⠐⠐⠒⠓⠋⠉⠈⠈", + }, + "dots9": {"interval": 80, "frames": "⢹⢺⢼⣸⣇⡧⡗⡏"}, + "dots10": {"interval": 80, "frames": "⢄⢂⢁⡁⡈⡐⡠"}, + "dots11": {"interval": 100, "frames": "⠁⠂⠄⡀⢀⠠⠐⠈"}, + "dots12": { + "interval": 80, + "frames": [ + "⢀⠀", + "⡀⠀", + "⠄⠀", + "⢂⠀", + "⡂⠀", + "⠅⠀", + "⢃⠀", + "⡃⠀", + "⠍⠀", + "⢋⠀", + "⡋⠀", + "⠍⠁", + "⢋⠁", + "⡋⠁", + "⠍⠉", + "⠋⠉", + "⠋⠉", + "⠉⠙", + "⠉⠙", + "⠉⠩", + "⠈⢙", + "⠈⡙", + "⢈⠩", + "⡀⢙", + "⠄⡙", + "⢂⠩", + "⡂⢘", + "⠅⡘", + "⢃⠨", + "⡃⢐", + "⠍⡐", + "⢋⠠", + "⡋⢀", + "⠍⡁", + "⢋⠁", + "⡋⠁", + "⠍⠉", + "⠋⠉", + "⠋⠉", + "⠉⠙", + "⠉⠙", + "⠉⠩", + "⠈⢙", + "⠈⡙", + "⠈⠩", + "⠀⢙", + "⠀⡙", + "⠀⠩", + "⠀⢘", + "⠀⡘", + "⠀⠨", + "⠀⢐", + "⠀⡐", + "⠀⠠", + "⠀⢀", + "⠀⡀", + ], + }, + "dots8Bit": { + "interval": 80, + "frames": "⠀⠁⠂⠃⠄⠅⠆⠇⡀⡁⡂⡃⡄⡅⡆⡇⠈⠉⠊⠋⠌⠍⠎⠏⡈⡉⡊⡋⡌⡍⡎⡏⠐⠑⠒⠓⠔⠕⠖⠗⡐⡑⡒⡓⡔⡕⡖⡗⠘⠙⠚⠛⠜⠝⠞⠟⡘⡙" + "⡚⡛⡜⡝⡞⡟⠠⠡⠢⠣⠤⠥⠦⠧⡠⡡⡢⡣⡤⡥⡦⡧⠨⠩⠪⠫⠬⠭⠮⠯⡨⡩⡪⡫⡬⡭⡮⡯⠰⠱⠲⠳⠴⠵⠶⠷⡰⡱⡲⡳⡴⡵⡶⡷⠸⠹⠺⠻" + "⠼⠽⠾⠿⡸⡹⡺⡻⡼⡽⡾⡿⢀⢁⢂⢃⢄⢅⢆⢇⣀⣁⣂⣃⣄⣅⣆⣇⢈⢉⢊⢋⢌⢍⢎⢏⣈⣉⣊⣋⣌⣍⣎⣏⢐⢑⢒⢓⢔⢕⢖⢗⣐⣑⣒⣓⣔⣕" + "⣖⣗⢘⢙⢚⢛⢜⢝⢞⢟⣘⣙⣚⣛⣜⣝⣞⣟⢠⢡⢢⢣⢤⢥⢦⢧⣠⣡⣢⣣⣤⣥⣦⣧⢨⢩⢪⢫⢬⢭⢮⢯⣨⣩⣪⣫⣬⣭⣮⣯⢰⢱⢲⢳⢴⢵⢶⢷" + "⣰⣱⣲⣳⣴⣵⣶⣷⢸⢹⢺⢻⢼⢽⢾⢿⣸⣹⣺⣻⣼⣽⣾⣿", + }, + "line": {"interval": 130, "frames": ["-", "\\", "|", "/"]}, + "line2": {"interval": 100, "frames": "⠂-–—–-"}, + "pipe": {"interval": 100, "frames": "┤┘┴└├┌┬┐"}, + "simpleDots": {"interval": 400, "frames": [". ", ".. ", "...", " "]}, + "simpleDotsScrolling": { + "interval": 200, + "frames": [". ", ".. ", "...", " ..", " .", " "], + }, + "star": {"interval": 70, "frames": "✶✸✹✺✹✷"}, + "star2": {"interval": 80, "frames": "+x*"}, + "flip": { + "interval": 70, + "frames": "___-``'´-___", + }, + "hamburger": {"interval": 100, "frames": "☱☲☴"}, + "growVertical": { + "interval": 120, + "frames": "▁▃▄▅▆▇▆▅▄▃", + }, + "growHorizontal": { + "interval": 120, + "frames": "▏▎▍▌▋▊▉▊▋▌▍▎", + }, + "balloon": {"interval": 140, "frames": " .oO@* "}, + "balloon2": {"interval": 120, "frames": ".oO°Oo."}, + "noise": {"interval": 100, "frames": "▓▒░"}, + "bounce": {"interval": 120, "frames": "⠁⠂⠄⠂"}, + "boxBounce": {"interval": 120, "frames": "▖▘▝▗"}, + "boxBounce2": {"interval": 100, "frames": "▌▀▐▄"}, + "triangle": {"interval": 50, "frames": "◢◣◤◥"}, + "arc": {"interval": 100, "frames": "◜◠◝◞◡◟"}, + "circle": {"interval": 120, "frames": "◡⊙◠"}, + "squareCorners": {"interval": 180, "frames": "◰◳◲◱"}, + "circleQuarters": {"interval": 120, "frames": "◴◷◶◵"}, + "circleHalves": {"interval": 50, "frames": "◐◓◑◒"}, + "squish": {"interval": 100, "frames": "╫╪"}, + "toggle": {"interval": 250, "frames": "⊶⊷"}, + "toggle2": {"interval": 80, "frames": "▫▪"}, + "toggle3": {"interval": 120, "frames": "□■"}, + "toggle4": {"interval": 100, "frames": "■□▪▫"}, + "toggle5": {"interval": 100, "frames": "▮▯"}, + "toggle6": {"interval": 300, "frames": "ဝ၀"}, + "toggle7": {"interval": 80, "frames": "⦾⦿"}, + "toggle8": {"interval": 100, "frames": "◍◌"}, + "toggle9": {"interval": 100, "frames": "◉◎"}, + "toggle10": {"interval": 100, "frames": "㊂㊀㊁"}, + "toggle11": {"interval": 50, "frames": "⧇⧆"}, + "toggle12": {"interval": 120, "frames": "☗☖"}, + "toggle13": {"interval": 80, "frames": "=*-"}, + "arrow": {"interval": 100, "frames": "←↖↑↗→↘↓↙"}, + "arrow2": { + "interval": 80, + "frames": ["⬆️ ", "↗️ ", "➡️ ", "↘️ ", "⬇️ ", "↙️ ", "⬅️ ", "↖️ "], + }, + "arrow3": { + "interval": 120, + "frames": ["▹▹▹▹▹", "▸▹▹▹▹", "▹▸▹▹▹", "▹▹▸▹▹", "▹▹▹▸▹", "▹▹▹▹▸"], + }, + "bouncingBar": { + "interval": 80, + "frames": [ + "[ ]", + "[= ]", + "[== ]", + "[=== ]", + "[ ===]", + "[ ==]", + "[ =]", + "[ ]", + "[ =]", + "[ ==]", + "[ ===]", + "[====]", + "[=== ]", + "[== ]", + "[= ]", + ], + }, + "bouncingBall": { + "interval": 80, + "frames": [ + "( ● )", + "( ● )", + "( ● )", + "( ● )", + "( ●)", + "( ● )", + "( ● )", + "( ● )", + "( ● )", + "(● )", + ], + }, + "smiley": {"interval": 200, "frames": ["😄 ", "😝 "]}, + "monkey": {"interval": 300, "frames": ["🙈 ", "🙈 ", "🙉 ", "🙊 "]}, + "hearts": {"interval": 100, "frames": ["💛 ", "💙 ", "💜 ", "💚 ", "❤️ "]}, + "clock": { + "interval": 100, + "frames": [ + "🕛 ", + "🕐 ", + "🕑 ", + "🕒 ", + "🕓 ", + "🕔 ", + "🕕 ", + "🕖 ", + "🕗 ", + "🕘 ", + "🕙 ", + "🕚 ", + ], + }, + "earth": {"interval": 180, "frames": ["🌍 ", "🌎 ", "🌏 "]}, + "material": { + "interval": 17, + "frames": [ + "█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "███▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "████▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "███████▁▁▁▁▁▁▁▁▁▁▁▁▁", + "████████▁▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "██████████▁▁▁▁▁▁▁▁▁▁", + "███████████▁▁▁▁▁▁▁▁▁", + "█████████████▁▁▁▁▁▁▁", + "██████████████▁▁▁▁▁▁", + "██████████████▁▁▁▁▁▁", + "▁██████████████▁▁▁▁▁", + "▁██████████████▁▁▁▁▁", + "▁██████████████▁▁▁▁▁", + "▁▁██████████████▁▁▁▁", + "▁▁▁██████████████▁▁▁", + "▁▁▁▁█████████████▁▁▁", + "▁▁▁▁██████████████▁▁", + "▁▁▁▁██████████████▁▁", + "▁▁▁▁▁██████████████▁", + "▁▁▁▁▁██████████████▁", + "▁▁▁▁▁██████████████▁", + "▁▁▁▁▁▁██████████████", + "▁▁▁▁▁▁██████████████", + "▁▁▁▁▁▁▁█████████████", + "▁▁▁▁▁▁▁█████████████", + "▁▁▁▁▁▁▁▁████████████", + "▁▁▁▁▁▁▁▁████████████", + "▁▁▁▁▁▁▁▁▁███████████", + "▁▁▁▁▁▁▁▁▁███████████", + "▁▁▁▁▁▁▁▁▁▁██████████", + "▁▁▁▁▁▁▁▁▁▁██████████", + "▁▁▁▁▁▁▁▁▁▁▁▁████████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁███████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁██████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████", + "█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████", + "██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", + "██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", + "███▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", + "████▁▁▁▁▁▁▁▁▁▁▁▁▁▁██", + "█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "██████▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "████████▁▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "███████████▁▁▁▁▁▁▁▁▁", + "████████████▁▁▁▁▁▁▁▁", + "████████████▁▁▁▁▁▁▁▁", + "██████████████▁▁▁▁▁▁", + "██████████████▁▁▁▁▁▁", + "▁██████████████▁▁▁▁▁", + "▁██████████████▁▁▁▁▁", + "▁▁▁█████████████▁▁▁▁", + "▁▁▁▁▁████████████▁▁▁", + "▁▁▁▁▁████████████▁▁▁", + "▁▁▁▁▁▁███████████▁▁▁", + "▁▁▁▁▁▁▁▁█████████▁▁▁", + "▁▁▁▁▁▁▁▁█████████▁▁▁", + "▁▁▁▁▁▁▁▁▁█████████▁▁", + "▁▁▁▁▁▁▁▁▁█████████▁▁", + "▁▁▁▁▁▁▁▁▁▁█████████▁", + "▁▁▁▁▁▁▁▁▁▁▁████████▁", + "▁▁▁▁▁▁▁▁▁▁▁████████▁", + "▁▁▁▁▁▁▁▁▁▁▁▁███████▁", + "▁▁▁▁▁▁▁▁▁▁▁▁███████▁", + "▁▁▁▁▁▁▁▁▁▁▁▁▁███████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁███████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + ], + }, + "moon": { + "interval": 80, + "frames": ["🌑 ", "🌒 ", "🌓 ", "🌔 ", "🌕 ", "🌖 ", "🌗 ", "🌘 "], + }, + "runner": {"interval": 140, "frames": ["🚶 ", "🏃 "]}, + "pong": { + "interval": 80, + "frames": [ + "▐⠂ ▌", + "▐⠈ ▌", + "▐ ⠂ ▌", + "▐ ⠠ ▌", + "▐ ⡀ ▌", + "▐ ⠠ ▌", + "▐ ⠂ ▌", + "▐ ⠈ ▌", + "▐ ⠂ ▌", + "▐ ⠠ ▌", + "▐ ⡀ ▌", + "▐ ⠠ ▌", + "▐ ⠂ ▌", + "▐ ⠈ ▌", + "▐ ⠂▌", + "▐ ⠠▌", + "▐ ⡀▌", + "▐ ⠠ ▌", + "▐ ⠂ ▌", + "▐ ⠈ ▌", + "▐ ⠂ ▌", + "▐ ⠠ ▌", + "▐ ⡀ ▌", + "▐ ⠠ ▌", + "▐ ⠂ ▌", + "▐ ⠈ ▌", + "▐ ⠂ ▌", + "▐ ⠠ ▌", + "▐ ⡀ ▌", + "▐⠠ ▌", + ], + }, + "shark": { + "interval": 120, + "frames": [ + "▐|\\____________▌", + "▐_|\\___________▌", + "▐__|\\__________▌", + "▐___|\\_________▌", + "▐____|\\________▌", + "▐_____|\\_______▌", + "▐______|\\______▌", + "▐_______|\\_____▌", + "▐________|\\____▌", + "▐_________|\\___▌", + "▐__________|\\__▌", + "▐___________|\\_▌", + "▐____________|\\▌", + "▐____________/|▌", + "▐___________/|_▌", + "▐__________/|__▌", + "▐_________/|___▌", + "▐________/|____▌", + "▐_______/|_____▌", + "▐______/|______▌", + "▐_____/|_______▌", + "▐____/|________▌", + "▐___/|_________▌", + "▐__/|__________▌", + "▐_/|___________▌", + "▐/|____________▌", + ], + }, + "dqpb": {"interval": 100, "frames": "dqpb"}, + "weather": { + "interval": 100, + "frames": [ + "☀️ ", + "☀️ ", + "☀️ ", + "🌤 ", + "⛅️ ", + "🌥 ", + "☁️ ", + "🌧 ", + "🌨 ", + "🌧 ", + "🌨 ", + "🌧 ", + "🌨 ", + "⛈ ", + "🌨 ", + "🌧 ", + "🌨 ", + "☁️ ", + "🌥 ", + "⛅️ ", + "🌤 ", + "☀️ ", + "☀️ ", + ], + }, + "christmas": {"interval": 400, "frames": "🌲🎄"}, + "grenade": { + "interval": 80, + "frames": [ + "، ", + "′ ", + " ´ ", + " ‾ ", + " ⸌", + " ⸊", + " |", + " ⁎", + " ⁕", + " ෴ ", + " ⁓", + " ", + " ", + " ", + ], + }, + "point": {"interval": 125, "frames": ["∙∙∙", "●∙∙", "∙●∙", "∙∙●", "∙∙∙"]}, + "layer": {"interval": 150, "frames": "-=≡"}, + "betaWave": { + "interval": 80, + "frames": [ + "ρββββββ", + "βρβββββ", + "ββρββββ", + "βββρβββ", + "ββββρββ", + "βββββρβ", + "ββββββρ", + ], + }, + "aesthetic": { + "interval": 80, + "frames": [ + "▰▱▱▱▱▱▱", + "▰▰▱▱▱▱▱", + "▰▰▰▱▱▱▱", + "▰▰▰▰▱▱▱", + "▰▰▰▰▰▱▱", + "▰▰▰▰▰▰▱", + "▰▰▰▰▰▰▰", + "▰▱▱▱▱▱▱", + ], + }, +} diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/_stack.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_stack.py new file mode 100644 index 0000000..194564e --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_stack.py @@ -0,0 +1,16 @@ +from typing import List, TypeVar + +T = TypeVar("T") + + +class Stack(List[T]): + """A small shim over builtin list.""" + + @property + def top(self) -> T: + """Get top of stack.""" + return self[-1] + + def push(self, item: T) -> None: + """Push an item on to the stack (append in stack nomenclature).""" + self.append(item) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/_timer.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_timer.py new file mode 100644 index 0000000..a2ca6be --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_timer.py @@ -0,0 +1,19 @@ +""" +Timer context manager, only used in debug. + +""" + +from time import time + +import contextlib +from typing import Generator + + +@contextlib.contextmanager +def timer(subject: str = "time") -> Generator[None, None, None]: + """print the elapsed time. (only used in debugging)""" + start = time() + yield + elapsed = time() - start + elapsed_ms = elapsed * 1000 + print(f"{subject} elapsed {elapsed_ms:.1f}ms") diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/_win32_console.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_win32_console.py new file mode 100644 index 0000000..81b1082 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_win32_console.py @@ -0,0 +1,662 @@ +"""Light wrapper around the Win32 Console API - this module should only be imported on Windows + +The API that this module wraps is documented at https://docs.microsoft.com/en-us/windows/console/console-functions +""" +import ctypes +import sys +from typing import Any + +windll: Any = None +if sys.platform == "win32": + windll = ctypes.LibraryLoader(ctypes.WinDLL) +else: + raise ImportError(f"{__name__} can only be imported on Windows") + +import time +from ctypes import Structure, byref, wintypes +from typing import IO, NamedTuple, Type, cast + +from pip._vendor.rich.color import ColorSystem +from pip._vendor.rich.style import Style + +STDOUT = -11 +ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4 + +COORD = wintypes._COORD + + +class LegacyWindowsError(Exception): + pass + + +class WindowsCoordinates(NamedTuple): + """Coordinates in the Windows Console API are (y, x), not (x, y). + This class is intended to prevent that confusion. + Rows and columns are indexed from 0. + This class can be used in place of wintypes._COORD in arguments and argtypes. + """ + + row: int + col: int + + @classmethod + def from_param(cls, value: "WindowsCoordinates") -> COORD: + """Converts a WindowsCoordinates into a wintypes _COORD structure. + This classmethod is internally called by ctypes to perform the conversion. + + Args: + value (WindowsCoordinates): The input coordinates to convert. + + Returns: + wintypes._COORD: The converted coordinates struct. + """ + return COORD(value.col, value.row) + + +class CONSOLE_SCREEN_BUFFER_INFO(Structure): + _fields_ = [ + ("dwSize", COORD), + ("dwCursorPosition", COORD), + ("wAttributes", wintypes.WORD), + ("srWindow", wintypes.SMALL_RECT), + ("dwMaximumWindowSize", COORD), + ] + + +class CONSOLE_CURSOR_INFO(ctypes.Structure): + _fields_ = [("dwSize", wintypes.DWORD), ("bVisible", wintypes.BOOL)] + + +_GetStdHandle = windll.kernel32.GetStdHandle +_GetStdHandle.argtypes = [ + wintypes.DWORD, +] +_GetStdHandle.restype = wintypes.HANDLE + + +def GetStdHandle(handle: int = STDOUT) -> wintypes.HANDLE: + """Retrieves a handle to the specified standard device (standard input, standard output, or standard error). + + Args: + handle (int): Integer identifier for the handle. Defaults to -11 (stdout). + + Returns: + wintypes.HANDLE: The handle + """ + return cast(wintypes.HANDLE, _GetStdHandle(handle)) + + +_GetConsoleMode = windll.kernel32.GetConsoleMode +_GetConsoleMode.argtypes = [wintypes.HANDLE, wintypes.LPDWORD] +_GetConsoleMode.restype = wintypes.BOOL + + +def GetConsoleMode(std_handle: wintypes.HANDLE) -> int: + """Retrieves the current input mode of a console's input buffer + or the current output mode of a console screen buffer. + + Args: + std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. + + Raises: + LegacyWindowsError: If any error occurs while calling the Windows console API. + + Returns: + int: Value representing the current console mode as documented at + https://docs.microsoft.com/en-us/windows/console/getconsolemode#parameters + """ + + console_mode = wintypes.DWORD() + success = bool(_GetConsoleMode(std_handle, console_mode)) + if not success: + raise LegacyWindowsError("Unable to get legacy Windows Console Mode") + return console_mode.value + + +_FillConsoleOutputCharacterW = windll.kernel32.FillConsoleOutputCharacterW +_FillConsoleOutputCharacterW.argtypes = [ + wintypes.HANDLE, + ctypes.c_char, + wintypes.DWORD, + cast(Type[COORD], WindowsCoordinates), + ctypes.POINTER(wintypes.DWORD), +] +_FillConsoleOutputCharacterW.restype = wintypes.BOOL + + +def FillConsoleOutputCharacter( + std_handle: wintypes.HANDLE, + char: str, + length: int, + start: WindowsCoordinates, +) -> int: + """Writes a character to the console screen buffer a specified number of times, beginning at the specified coordinates. + + Args: + std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. + char (str): The character to write. Must be a string of length 1. + length (int): The number of times to write the character. + start (WindowsCoordinates): The coordinates to start writing at. + + Returns: + int: The number of characters written. + """ + character = ctypes.c_char(char.encode()) + num_characters = wintypes.DWORD(length) + num_written = wintypes.DWORD(0) + _FillConsoleOutputCharacterW( + std_handle, + character, + num_characters, + start, + byref(num_written), + ) + return num_written.value + + +_FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute +_FillConsoleOutputAttribute.argtypes = [ + wintypes.HANDLE, + wintypes.WORD, + wintypes.DWORD, + cast(Type[COORD], WindowsCoordinates), + ctypes.POINTER(wintypes.DWORD), +] +_FillConsoleOutputAttribute.restype = wintypes.BOOL + + +def FillConsoleOutputAttribute( + std_handle: wintypes.HANDLE, + attributes: int, + length: int, + start: WindowsCoordinates, +) -> int: + """Sets the character attributes for a specified number of character cells, + beginning at the specified coordinates in a screen buffer. + + Args: + std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. + attributes (int): Integer value representing the foreground and background colours of the cells. + length (int): The number of cells to set the output attribute of. + start (WindowsCoordinates): The coordinates of the first cell whose attributes are to be set. + + Returns: + int: The number of cells whose attributes were actually set. + """ + num_cells = wintypes.DWORD(length) + style_attrs = wintypes.WORD(attributes) + num_written = wintypes.DWORD(0) + _FillConsoleOutputAttribute( + std_handle, style_attrs, num_cells, start, byref(num_written) + ) + return num_written.value + + +_SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute +_SetConsoleTextAttribute.argtypes = [ + wintypes.HANDLE, + wintypes.WORD, +] +_SetConsoleTextAttribute.restype = wintypes.BOOL + + +def SetConsoleTextAttribute( + std_handle: wintypes.HANDLE, attributes: wintypes.WORD +) -> bool: + """Set the colour attributes for all text written after this function is called. + + Args: + std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. + attributes (int): Integer value representing the foreground and background colours. + + + Returns: + bool: True if the attribute was set successfully, otherwise False. + """ + return bool(_SetConsoleTextAttribute(std_handle, attributes)) + + +_GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo +_GetConsoleScreenBufferInfo.argtypes = [ + wintypes.HANDLE, + ctypes.POINTER(CONSOLE_SCREEN_BUFFER_INFO), +] +_GetConsoleScreenBufferInfo.restype = wintypes.BOOL + + +def GetConsoleScreenBufferInfo( + std_handle: wintypes.HANDLE, +) -> CONSOLE_SCREEN_BUFFER_INFO: + """Retrieves information about the specified console screen buffer. + + Args: + std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. + + Returns: + CONSOLE_SCREEN_BUFFER_INFO: A CONSOLE_SCREEN_BUFFER_INFO ctype struct contain information about + screen size, cursor position, colour attributes, and more.""" + console_screen_buffer_info = CONSOLE_SCREEN_BUFFER_INFO() + _GetConsoleScreenBufferInfo(std_handle, byref(console_screen_buffer_info)) + return console_screen_buffer_info + + +_SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition +_SetConsoleCursorPosition.argtypes = [ + wintypes.HANDLE, + cast(Type[COORD], WindowsCoordinates), +] +_SetConsoleCursorPosition.restype = wintypes.BOOL + + +def SetConsoleCursorPosition( + std_handle: wintypes.HANDLE, coords: WindowsCoordinates +) -> bool: + """Set the position of the cursor in the console screen + + Args: + std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. + coords (WindowsCoordinates): The coordinates to move the cursor to. + + Returns: + bool: True if the function succeeds, otherwise False. + """ + return bool(_SetConsoleCursorPosition(std_handle, coords)) + + +_GetConsoleCursorInfo = windll.kernel32.GetConsoleCursorInfo +_GetConsoleCursorInfo.argtypes = [ + wintypes.HANDLE, + ctypes.POINTER(CONSOLE_CURSOR_INFO), +] +_GetConsoleCursorInfo.restype = wintypes.BOOL + + +def GetConsoleCursorInfo( + std_handle: wintypes.HANDLE, cursor_info: CONSOLE_CURSOR_INFO +) -> bool: + """Get the cursor info - used to get cursor visibility and width + + Args: + std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. + cursor_info (CONSOLE_CURSOR_INFO): CONSOLE_CURSOR_INFO ctype struct that receives information + about the console's cursor. + + Returns: + bool: True if the function succeeds, otherwise False. + """ + return bool(_GetConsoleCursorInfo(std_handle, byref(cursor_info))) + + +_SetConsoleCursorInfo = windll.kernel32.SetConsoleCursorInfo +_SetConsoleCursorInfo.argtypes = [ + wintypes.HANDLE, + ctypes.POINTER(CONSOLE_CURSOR_INFO), +] +_SetConsoleCursorInfo.restype = wintypes.BOOL + + +def SetConsoleCursorInfo( + std_handle: wintypes.HANDLE, cursor_info: CONSOLE_CURSOR_INFO +) -> bool: + """Set the cursor info - used for adjusting cursor visibility and width + + Args: + std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. + cursor_info (CONSOLE_CURSOR_INFO): CONSOLE_CURSOR_INFO ctype struct containing the new cursor info. + + Returns: + bool: True if the function succeeds, otherwise False. + """ + return bool(_SetConsoleCursorInfo(std_handle, byref(cursor_info))) + + +_SetConsoleTitle = windll.kernel32.SetConsoleTitleW +_SetConsoleTitle.argtypes = [wintypes.LPCWSTR] +_SetConsoleTitle.restype = wintypes.BOOL + + +def SetConsoleTitle(title: str) -> bool: + """Sets the title of the current console window + + Args: + title (str): The new title of the console window. + + Returns: + bool: True if the function succeeds, otherwise False. + """ + return bool(_SetConsoleTitle(title)) + + +class LegacyWindowsTerm: + """This class allows interaction with the legacy Windows Console API. It should only be used in the context + of environments where virtual terminal processing is not available. However, if it is used in a Windows environment, + the entire API should work. + + Args: + file (IO[str]): The file which the Windows Console API HANDLE is retrieved from, defaults to sys.stdout. + """ + + BRIGHT_BIT = 8 + + # Indices are ANSI color numbers, values are the corresponding Windows Console API color numbers + ANSI_TO_WINDOWS = [ + 0, # black The Windows colours are defined in wincon.h as follows: + 4, # red define FOREGROUND_BLUE 0x0001 -- 0000 0001 + 2, # green define FOREGROUND_GREEN 0x0002 -- 0000 0010 + 6, # yellow define FOREGROUND_RED 0x0004 -- 0000 0100 + 1, # blue define FOREGROUND_INTENSITY 0x0008 -- 0000 1000 + 5, # magenta define BACKGROUND_BLUE 0x0010 -- 0001 0000 + 3, # cyan define BACKGROUND_GREEN 0x0020 -- 0010 0000 + 7, # white define BACKGROUND_RED 0x0040 -- 0100 0000 + 8, # bright black (grey) define BACKGROUND_INTENSITY 0x0080 -- 1000 0000 + 12, # bright red + 10, # bright green + 14, # bright yellow + 9, # bright blue + 13, # bright magenta + 11, # bright cyan + 15, # bright white + ] + + def __init__(self, file: "IO[str]") -> None: + handle = GetStdHandle(STDOUT) + self._handle = handle + default_text = GetConsoleScreenBufferInfo(handle).wAttributes + self._default_text = default_text + + self._default_fore = default_text & 7 + self._default_back = (default_text >> 4) & 7 + self._default_attrs = self._default_fore | (self._default_back << 4) + + self._file = file + self.write = file.write + self.flush = file.flush + + @property + def cursor_position(self) -> WindowsCoordinates: + """Returns the current position of the cursor (0-based) + + Returns: + WindowsCoordinates: The current cursor position. + """ + coord: COORD = GetConsoleScreenBufferInfo(self._handle).dwCursorPosition + return WindowsCoordinates(row=cast(int, coord.Y), col=cast(int, coord.X)) + + @property + def screen_size(self) -> WindowsCoordinates: + """Returns the current size of the console screen buffer, in character columns and rows + + Returns: + WindowsCoordinates: The width and height of the screen as WindowsCoordinates. + """ + screen_size: COORD = GetConsoleScreenBufferInfo(self._handle).dwSize + return WindowsCoordinates( + row=cast(int, screen_size.Y), col=cast(int, screen_size.X) + ) + + def write_text(self, text: str) -> None: + """Write text directly to the terminal without any modification of styles + + Args: + text (str): The text to write to the console + """ + self.write(text) + self.flush() + + def write_styled(self, text: str, style: Style) -> None: + """Write styled text to the terminal. + + Args: + text (str): The text to write + style (Style): The style of the text + """ + color = style.color + bgcolor = style.bgcolor + if style.reverse: + color, bgcolor = bgcolor, color + + if color: + fore = color.downgrade(ColorSystem.WINDOWS).number + fore = fore if fore is not None else 7 # Default to ANSI 7: White + if style.bold: + fore = fore | self.BRIGHT_BIT + if style.dim: + fore = fore & ~self.BRIGHT_BIT + fore = self.ANSI_TO_WINDOWS[fore] + else: + fore = self._default_fore + + if bgcolor: + back = bgcolor.downgrade(ColorSystem.WINDOWS).number + back = back if back is not None else 0 # Default to ANSI 0: Black + back = self.ANSI_TO_WINDOWS[back] + else: + back = self._default_back + + assert fore is not None + assert back is not None + + SetConsoleTextAttribute( + self._handle, attributes=ctypes.c_ushort(fore | (back << 4)) + ) + self.write_text(text) + SetConsoleTextAttribute(self._handle, attributes=self._default_text) + + def move_cursor_to(self, new_position: WindowsCoordinates) -> None: + """Set the position of the cursor + + Args: + new_position (WindowsCoordinates): The WindowsCoordinates representing the new position of the cursor. + """ + if new_position.col < 0 or new_position.row < 0: + return + SetConsoleCursorPosition(self._handle, coords=new_position) + + def erase_line(self) -> None: + """Erase all content on the line the cursor is currently located at""" + screen_size = self.screen_size + cursor_position = self.cursor_position + cells_to_erase = screen_size.col + start_coordinates = WindowsCoordinates(row=cursor_position.row, col=0) + FillConsoleOutputCharacter( + self._handle, " ", length=cells_to_erase, start=start_coordinates + ) + FillConsoleOutputAttribute( + self._handle, + self._default_attrs, + length=cells_to_erase, + start=start_coordinates, + ) + + def erase_end_of_line(self) -> None: + """Erase all content from the cursor position to the end of that line""" + cursor_position = self.cursor_position + cells_to_erase = self.screen_size.col - cursor_position.col + FillConsoleOutputCharacter( + self._handle, " ", length=cells_to_erase, start=cursor_position + ) + FillConsoleOutputAttribute( + self._handle, + self._default_attrs, + length=cells_to_erase, + start=cursor_position, + ) + + def erase_start_of_line(self) -> None: + """Erase all content from the cursor position to the start of that line""" + row, col = self.cursor_position + start = WindowsCoordinates(row, 0) + FillConsoleOutputCharacter(self._handle, " ", length=col, start=start) + FillConsoleOutputAttribute( + self._handle, self._default_attrs, length=col, start=start + ) + + def move_cursor_up(self) -> None: + """Move the cursor up a single cell""" + cursor_position = self.cursor_position + SetConsoleCursorPosition( + self._handle, + coords=WindowsCoordinates( + row=cursor_position.row - 1, col=cursor_position.col + ), + ) + + def move_cursor_down(self) -> None: + """Move the cursor down a single cell""" + cursor_position = self.cursor_position + SetConsoleCursorPosition( + self._handle, + coords=WindowsCoordinates( + row=cursor_position.row + 1, + col=cursor_position.col, + ), + ) + + def move_cursor_forward(self) -> None: + """Move the cursor forward a single cell. Wrap to the next line if required.""" + row, col = self.cursor_position + if col == self.screen_size.col - 1: + row += 1 + col = 0 + else: + col += 1 + SetConsoleCursorPosition( + self._handle, coords=WindowsCoordinates(row=row, col=col) + ) + + def move_cursor_to_column(self, column: int) -> None: + """Move cursor to the column specified by the zero-based column index, staying on the same row + + Args: + column (int): The zero-based column index to move the cursor to. + """ + row, _ = self.cursor_position + SetConsoleCursorPosition(self._handle, coords=WindowsCoordinates(row, column)) + + def move_cursor_backward(self) -> None: + """Move the cursor backward a single cell. Wrap to the previous line if required.""" + row, col = self.cursor_position + if col == 0: + row -= 1 + col = self.screen_size.col - 1 + else: + col -= 1 + SetConsoleCursorPosition( + self._handle, coords=WindowsCoordinates(row=row, col=col) + ) + + def hide_cursor(self) -> None: + """Hide the cursor""" + current_cursor_size = self._get_cursor_size() + invisible_cursor = CONSOLE_CURSOR_INFO(dwSize=current_cursor_size, bVisible=0) + SetConsoleCursorInfo(self._handle, cursor_info=invisible_cursor) + + def show_cursor(self) -> None: + """Show the cursor""" + current_cursor_size = self._get_cursor_size() + visible_cursor = CONSOLE_CURSOR_INFO(dwSize=current_cursor_size, bVisible=1) + SetConsoleCursorInfo(self._handle, cursor_info=visible_cursor) + + def set_title(self, title: str) -> None: + """Set the title of the terminal window + + Args: + title (str): The new title of the console window + """ + assert len(title) < 255, "Console title must be less than 255 characters" + SetConsoleTitle(title) + + def _get_cursor_size(self) -> int: + """Get the percentage of the character cell that is filled by the cursor""" + cursor_info = CONSOLE_CURSOR_INFO() + GetConsoleCursorInfo(self._handle, cursor_info=cursor_info) + return int(cursor_info.dwSize) + + +if __name__ == "__main__": + handle = GetStdHandle() + + from pip._vendor.rich.console import Console + + console = Console() + + term = LegacyWindowsTerm(sys.stdout) + term.set_title("Win32 Console Examples") + + style = Style(color="black", bgcolor="red") + + heading = Style.parse("black on green") + + # Check colour output + console.rule("Checking colour output") + console.print("[on red]on red!") + console.print("[blue]blue!") + console.print("[yellow]yellow!") + console.print("[bold yellow]bold yellow!") + console.print("[bright_yellow]bright_yellow!") + console.print("[dim bright_yellow]dim bright_yellow!") + console.print("[italic cyan]italic cyan!") + console.print("[bold white on blue]bold white on blue!") + console.print("[reverse bold white on blue]reverse bold white on blue!") + console.print("[bold black on cyan]bold black on cyan!") + console.print("[black on green]black on green!") + console.print("[blue on green]blue on green!") + console.print("[white on black]white on black!") + console.print("[black on white]black on white!") + console.print("[#1BB152 on #DA812D]#1BB152 on #DA812D!") + + # Check cursor movement + console.rule("Checking cursor movement") + console.print() + term.move_cursor_backward() + term.move_cursor_backward() + term.write_text("went back and wrapped to prev line") + time.sleep(1) + term.move_cursor_up() + term.write_text("we go up") + time.sleep(1) + term.move_cursor_down() + term.write_text("and down") + time.sleep(1) + term.move_cursor_up() + term.move_cursor_backward() + term.move_cursor_backward() + term.write_text("we went up and back 2") + time.sleep(1) + term.move_cursor_down() + term.move_cursor_backward() + term.move_cursor_backward() + term.write_text("we went down and back 2") + time.sleep(1) + + # Check erasing of lines + term.hide_cursor() + console.print() + console.rule("Checking line erasing") + console.print("\n...Deleting to the start of the line...") + term.write_text("The red arrow shows the cursor location, and direction of erase") + time.sleep(1) + term.move_cursor_to_column(16) + term.write_styled("<", Style.parse("black on red")) + term.move_cursor_backward() + time.sleep(1) + term.erase_start_of_line() + time.sleep(1) + + console.print("\n\n...And to the end of the line...") + term.write_text("The red arrow shows the cursor location, and direction of erase") + time.sleep(1) + + term.move_cursor_to_column(16) + term.write_styled(">", Style.parse("black on red")) + time.sleep(1) + term.erase_end_of_line() + time.sleep(1) + + console.print("\n\n...Now the whole line will be erased...") + term.write_styled("I'm going to disappear!", style=Style.parse("black on cyan")) + time.sleep(1) + term.erase_line() + + term.show_cursor() + print("\n") diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/_windows.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_windows.py new file mode 100644 index 0000000..7520a9f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_windows.py @@ -0,0 +1,71 @@ +import sys +from dataclasses import dataclass + + +@dataclass +class WindowsConsoleFeatures: + """Windows features available.""" + + vt: bool = False + """The console supports VT codes.""" + truecolor: bool = False + """The console supports truecolor.""" + + +try: + import ctypes + from ctypes import LibraryLoader + + if sys.platform == "win32": + windll = LibraryLoader(ctypes.WinDLL) + else: + windll = None + raise ImportError("Not windows") + + from pip._vendor.rich._win32_console import ( + ENABLE_VIRTUAL_TERMINAL_PROCESSING, + GetConsoleMode, + GetStdHandle, + LegacyWindowsError, + ) + +except (AttributeError, ImportError, ValueError): + # Fallback if we can't load the Windows DLL + def get_windows_console_features() -> WindowsConsoleFeatures: + features = WindowsConsoleFeatures() + return features + +else: + + def get_windows_console_features() -> WindowsConsoleFeatures: + """Get windows console features. + + Returns: + WindowsConsoleFeatures: An instance of WindowsConsoleFeatures. + """ + handle = GetStdHandle() + try: + console_mode = GetConsoleMode(handle) + success = True + except LegacyWindowsError: + console_mode = 0 + success = False + vt = bool(success and console_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) + truecolor = False + if vt: + win_version = sys.getwindowsversion() + truecolor = win_version.major > 10 or ( + win_version.major == 10 and win_version.build >= 15063 + ) + features = WindowsConsoleFeatures(vt=vt, truecolor=truecolor) + return features + + +if __name__ == "__main__": + import platform + + features = get_windows_console_features() + from pip._vendor.rich import print + + print(f'platform="{platform.system()}"') + print(repr(features)) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/_windows_renderer.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_windows_renderer.py new file mode 100644 index 0000000..5ece056 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_windows_renderer.py @@ -0,0 +1,56 @@ +from typing import Iterable, Sequence, Tuple, cast + +from pip._vendor.rich._win32_console import LegacyWindowsTerm, WindowsCoordinates +from pip._vendor.rich.segment import ControlCode, ControlType, Segment + + +def legacy_windows_render(buffer: Iterable[Segment], term: LegacyWindowsTerm) -> None: + """Makes appropriate Windows Console API calls based on the segments in the buffer. + + Args: + buffer (Iterable[Segment]): Iterable of Segments to convert to Win32 API calls. + term (LegacyWindowsTerm): Used to call the Windows Console API. + """ + for text, style, control in buffer: + if not control: + if style: + term.write_styled(text, style) + else: + term.write_text(text) + else: + control_codes: Sequence[ControlCode] = control + for control_code in control_codes: + control_type = control_code[0] + if control_type == ControlType.CURSOR_MOVE_TO: + _, x, y = cast(Tuple[ControlType, int, int], control_code) + term.move_cursor_to(WindowsCoordinates(row=y - 1, col=x - 1)) + elif control_type == ControlType.CARRIAGE_RETURN: + term.write_text("\r") + elif control_type == ControlType.HOME: + term.move_cursor_to(WindowsCoordinates(0, 0)) + elif control_type == ControlType.CURSOR_UP: + term.move_cursor_up() + elif control_type == ControlType.CURSOR_DOWN: + term.move_cursor_down() + elif control_type == ControlType.CURSOR_FORWARD: + term.move_cursor_forward() + elif control_type == ControlType.CURSOR_BACKWARD: + term.move_cursor_backward() + elif control_type == ControlType.CURSOR_MOVE_TO_COLUMN: + _, column = cast(Tuple[ControlType, int], control_code) + term.move_cursor_to_column(column - 1) + elif control_type == ControlType.HIDE_CURSOR: + term.hide_cursor() + elif control_type == ControlType.SHOW_CURSOR: + term.show_cursor() + elif control_type == ControlType.ERASE_IN_LINE: + _, mode = cast(Tuple[ControlType, int], control_code) + if mode == 0: + term.erase_end_of_line() + elif mode == 1: + term.erase_start_of_line() + elif mode == 2: + term.erase_line() + elif control_type == ControlType.SET_WINDOW_TITLE: + _, title = cast(Tuple[ControlType, str], control_code) + term.set_title(title) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/_wrap.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_wrap.py new file mode 100644 index 0000000..2e94ff6 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/_wrap.py @@ -0,0 +1,93 @@ +from __future__ import annotations + +import re +from typing import Iterable + +from ._loop import loop_last +from .cells import cell_len, chop_cells + +re_word = re.compile(r"\s*\S+\s*") + + +def words(text: str) -> Iterable[tuple[int, int, str]]: + """Yields each word from the text as a tuple + containing (start_index, end_index, word). A "word" in this context may + include the actual word and any whitespace to the right. + """ + position = 0 + word_match = re_word.match(text, position) + while word_match is not None: + start, end = word_match.span() + word = word_match.group(0) + yield start, end, word + word_match = re_word.match(text, end) + + +def divide_line(text: str, width: int, fold: bool = True) -> list[int]: + """Given a string of text, and a width (measured in cells), return a list + of cell offsets which the string should be split at in order for it to fit + within the given width. + + Args: + text: The text to examine. + width: The available cell width. + fold: If True, words longer than `width` will be folded onto a new line. + + Returns: + A list of indices to break the line at. + """ + break_positions: list[int] = [] # offsets to insert the breaks at + append = break_positions.append + cell_offset = 0 + _cell_len = cell_len + + for start, _end, word in words(text): + word_length = _cell_len(word.rstrip()) + remaining_space = width - cell_offset + word_fits_remaining_space = remaining_space >= word_length + + if word_fits_remaining_space: + # Simplest case - the word fits within the remaining width for this line. + cell_offset += _cell_len(word) + else: + # Not enough space remaining for this word on the current line. + if word_length > width: + # The word doesn't fit on any line, so we can't simply + # place it on the next line... + if fold: + # Fold the word across multiple lines. + folded_word = chop_cells(word, width=width) + for last, line in loop_last(folded_word): + if start: + append(start) + if last: + cell_offset = _cell_len(line) + else: + start += len(line) + else: + # Folding isn't allowed, so crop the word. + if start: + append(start) + cell_offset = _cell_len(word) + elif cell_offset and start: + # The word doesn't fit within the remaining space on the current + # line, but it *can* fit on to the next (empty) line. + append(start) + cell_offset = _cell_len(word) + + return break_positions + + +if __name__ == "__main__": # pragma: no cover + from .console import Console + + console = Console(width=10) + console.print("12345 abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ 12345") + print(chop_cells("abcdefghijklmnopqrstuvwxyz", 10)) + + console = Console(width=20) + console.rule() + console.print("TextualはPythonの高速アプリケーション開発フレームワークです") + + console.rule() + console.print("アプリケーションは1670万色を使用でき") diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/abc.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/abc.py new file mode 100644 index 0000000..e6e498e --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/abc.py @@ -0,0 +1,33 @@ +from abc import ABC + + +class RichRenderable(ABC): + """An abstract base class for Rich renderables. + + Note that there is no need to extend this class, the intended use is to check if an + object supports the Rich renderable protocol. For example:: + + if isinstance(my_object, RichRenderable): + console.print(my_object) + + """ + + @classmethod + def __subclasshook__(cls, other: type) -> bool: + """Check if this class supports the rich render protocol.""" + return hasattr(other, "__rich_console__") or hasattr(other, "__rich__") + + +if __name__ == "__main__": # pragma: no cover + from pip._vendor.rich.text import Text + + t = Text() + print(isinstance(Text, RichRenderable)) + print(isinstance(t, RichRenderable)) + + class Foo: + pass + + f = Foo() + print(isinstance(f, RichRenderable)) + print(isinstance("", RichRenderable)) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/align.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/align.py new file mode 100644 index 0000000..f7b734f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/align.py @@ -0,0 +1,311 @@ +import sys +from itertools import chain +from typing import TYPE_CHECKING, Iterable, Optional + +if sys.version_info >= (3, 8): + from typing import Literal +else: + from pip._vendor.typing_extensions import Literal # pragma: no cover + +from .constrain import Constrain +from .jupyter import JupyterMixin +from .measure import Measurement +from .segment import Segment +from .style import StyleType + +if TYPE_CHECKING: + from .console import Console, ConsoleOptions, RenderableType, RenderResult + +AlignMethod = Literal["left", "center", "right"] +VerticalAlignMethod = Literal["top", "middle", "bottom"] + + +class Align(JupyterMixin): + """Align a renderable by adding spaces if necessary. + + Args: + renderable (RenderableType): A console renderable. + align (AlignMethod): One of "left", "center", or "right"" + style (StyleType, optional): An optional style to apply to the background. + vertical (Optional[VerticalAlignMethod], optional): Optional vertical align, one of "top", "middle", or "bottom". Defaults to None. + pad (bool, optional): Pad the right with spaces. Defaults to True. + width (int, optional): Restrict contents to given width, or None to use default width. Defaults to None. + height (int, optional): Set height of align renderable, or None to fit to contents. Defaults to None. + + Raises: + ValueError: if ``align`` is not one of the expected values. + """ + + def __init__( + self, + renderable: "RenderableType", + align: AlignMethod = "left", + style: Optional[StyleType] = None, + *, + vertical: Optional[VerticalAlignMethod] = None, + pad: bool = True, + width: Optional[int] = None, + height: Optional[int] = None, + ) -> None: + if align not in ("left", "center", "right"): + raise ValueError( + f'invalid value for align, expected "left", "center", or "right" (not {align!r})' + ) + if vertical is not None and vertical not in ("top", "middle", "bottom"): + raise ValueError( + f'invalid value for vertical, expected "top", "middle", or "bottom" (not {vertical!r})' + ) + self.renderable = renderable + self.align = align + self.style = style + self.vertical = vertical + self.pad = pad + self.width = width + self.height = height + + def __repr__(self) -> str: + return f"Align({self.renderable!r}, {self.align!r})" + + @classmethod + def left( + cls, + renderable: "RenderableType", + style: Optional[StyleType] = None, + *, + vertical: Optional[VerticalAlignMethod] = None, + pad: bool = True, + width: Optional[int] = None, + height: Optional[int] = None, + ) -> "Align": + """Align a renderable to the left.""" + return cls( + renderable, + "left", + style=style, + vertical=vertical, + pad=pad, + width=width, + height=height, + ) + + @classmethod + def center( + cls, + renderable: "RenderableType", + style: Optional[StyleType] = None, + *, + vertical: Optional[VerticalAlignMethod] = None, + pad: bool = True, + width: Optional[int] = None, + height: Optional[int] = None, + ) -> "Align": + """Align a renderable to the center.""" + return cls( + renderable, + "center", + style=style, + vertical=vertical, + pad=pad, + width=width, + height=height, + ) + + @classmethod + def right( + cls, + renderable: "RenderableType", + style: Optional[StyleType] = None, + *, + vertical: Optional[VerticalAlignMethod] = None, + pad: bool = True, + width: Optional[int] = None, + height: Optional[int] = None, + ) -> "Align": + """Align a renderable to the right.""" + return cls( + renderable, + "right", + style=style, + vertical=vertical, + pad=pad, + width=width, + height=height, + ) + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + align = self.align + width = console.measure(self.renderable, options=options).maximum + rendered = console.render( + Constrain( + self.renderable, width if self.width is None else min(width, self.width) + ), + options.update(height=None), + ) + lines = list(Segment.split_lines(rendered)) + width, height = Segment.get_shape(lines) + lines = Segment.set_shape(lines, width, height) + new_line = Segment.line() + excess_space = options.max_width - width + style = console.get_style(self.style) if self.style is not None else None + + def generate_segments() -> Iterable[Segment]: + if excess_space <= 0: + # Exact fit + for line in lines: + yield from line + yield new_line + + elif align == "left": + # Pad on the right + pad = Segment(" " * excess_space, style) if self.pad else None + for line in lines: + yield from line + if pad: + yield pad + yield new_line + + elif align == "center": + # Pad left and right + left = excess_space // 2 + pad = Segment(" " * left, style) + pad_right = ( + Segment(" " * (excess_space - left), style) if self.pad else None + ) + for line in lines: + if left: + yield pad + yield from line + if pad_right: + yield pad_right + yield new_line + + elif align == "right": + # Padding on left + pad = Segment(" " * excess_space, style) + for line in lines: + yield pad + yield from line + yield new_line + + blank_line = ( + Segment(f"{' ' * (self.width or options.max_width)}\n", style) + if self.pad + else Segment("\n") + ) + + def blank_lines(count: int) -> Iterable[Segment]: + if count > 0: + for _ in range(count): + yield blank_line + + vertical_height = self.height or options.height + iter_segments: Iterable[Segment] + if self.vertical and vertical_height is not None: + if self.vertical == "top": + bottom_space = vertical_height - height + iter_segments = chain(generate_segments(), blank_lines(bottom_space)) + elif self.vertical == "middle": + top_space = (vertical_height - height) // 2 + bottom_space = vertical_height - top_space - height + iter_segments = chain( + blank_lines(top_space), + generate_segments(), + blank_lines(bottom_space), + ) + else: # self.vertical == "bottom": + top_space = vertical_height - height + iter_segments = chain(blank_lines(top_space), generate_segments()) + else: + iter_segments = generate_segments() + if self.style: + style = console.get_style(self.style) + iter_segments = Segment.apply_style(iter_segments, style) + yield from iter_segments + + def __rich_measure__( + self, console: "Console", options: "ConsoleOptions" + ) -> Measurement: + measurement = Measurement.get(console, options, self.renderable) + return measurement + + +class VerticalCenter(JupyterMixin): + """Vertically aligns a renderable. + + Warn: + This class is deprecated and may be removed in a future version. Use Align class with + `vertical="middle"`. + + Args: + renderable (RenderableType): A renderable object. + """ + + def __init__( + self, + renderable: "RenderableType", + style: Optional[StyleType] = None, + ) -> None: + self.renderable = renderable + self.style = style + + def __repr__(self) -> str: + return f"VerticalCenter({self.renderable!r})" + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + style = console.get_style(self.style) if self.style is not None else None + lines = console.render_lines( + self.renderable, options.update(height=None), pad=False + ) + width, _height = Segment.get_shape(lines) + new_line = Segment.line() + height = options.height or options.size.height + top_space = (height - len(lines)) // 2 + bottom_space = height - top_space - len(lines) + blank_line = Segment(f"{' ' * width}", style) + + def blank_lines(count: int) -> Iterable[Segment]: + for _ in range(count): + yield blank_line + yield new_line + + if top_space > 0: + yield from blank_lines(top_space) + for line in lines: + yield from line + yield new_line + if bottom_space > 0: + yield from blank_lines(bottom_space) + + def __rich_measure__( + self, console: "Console", options: "ConsoleOptions" + ) -> Measurement: + measurement = Measurement.get(console, options, self.renderable) + return measurement + + +if __name__ == "__main__": # pragma: no cover + from pip._vendor.rich.console import Console, Group + from pip._vendor.rich.highlighter import ReprHighlighter + from pip._vendor.rich.panel import Panel + + highlighter = ReprHighlighter() + console = Console() + + panel = Panel( + Group( + Align.left(highlighter("align='left'")), + Align.center(highlighter("align='center'")), + Align.right(highlighter("align='right'")), + ), + width=60, + style="on dark_blue", + title="Align", + ) + + console.print( + Align.center(panel, vertical="middle", style="on red", height=console.height) + ) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/ansi.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/ansi.py new file mode 100644 index 0000000..66365e6 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/ansi.py @@ -0,0 +1,240 @@ +import re +import sys +from contextlib import suppress +from typing import Iterable, NamedTuple, Optional + +from .color import Color +from .style import Style +from .text import Text + +re_ansi = re.compile( + r""" +(?:\x1b\](.*?)\x1b\\)| +(?:\x1b([(@-Z\\-_]|\[[0-?]*[ -/]*[@-~])) +""", + re.VERBOSE, +) + + +class _AnsiToken(NamedTuple): + """Result of ansi tokenized string.""" + + plain: str = "" + sgr: Optional[str] = "" + osc: Optional[str] = "" + + +def _ansi_tokenize(ansi_text: str) -> Iterable[_AnsiToken]: + """Tokenize a string in to plain text and ANSI codes. + + Args: + ansi_text (str): A String containing ANSI codes. + + Yields: + AnsiToken: A named tuple of (plain, sgr, osc) + """ + + position = 0 + sgr: Optional[str] + osc: Optional[str] + for match in re_ansi.finditer(ansi_text): + start, end = match.span(0) + osc, sgr = match.groups() + if start > position: + yield _AnsiToken(ansi_text[position:start]) + if sgr: + if sgr == "(": + position = end + 1 + continue + if sgr.endswith("m"): + yield _AnsiToken("", sgr[1:-1], osc) + else: + yield _AnsiToken("", sgr, osc) + position = end + if position < len(ansi_text): + yield _AnsiToken(ansi_text[position:]) + + +SGR_STYLE_MAP = { + 1: "bold", + 2: "dim", + 3: "italic", + 4: "underline", + 5: "blink", + 6: "blink2", + 7: "reverse", + 8: "conceal", + 9: "strike", + 21: "underline2", + 22: "not dim not bold", + 23: "not italic", + 24: "not underline", + 25: "not blink", + 26: "not blink2", + 27: "not reverse", + 28: "not conceal", + 29: "not strike", + 30: "color(0)", + 31: "color(1)", + 32: "color(2)", + 33: "color(3)", + 34: "color(4)", + 35: "color(5)", + 36: "color(6)", + 37: "color(7)", + 39: "default", + 40: "on color(0)", + 41: "on color(1)", + 42: "on color(2)", + 43: "on color(3)", + 44: "on color(4)", + 45: "on color(5)", + 46: "on color(6)", + 47: "on color(7)", + 49: "on default", + 51: "frame", + 52: "encircle", + 53: "overline", + 54: "not frame not encircle", + 55: "not overline", + 90: "color(8)", + 91: "color(9)", + 92: "color(10)", + 93: "color(11)", + 94: "color(12)", + 95: "color(13)", + 96: "color(14)", + 97: "color(15)", + 100: "on color(8)", + 101: "on color(9)", + 102: "on color(10)", + 103: "on color(11)", + 104: "on color(12)", + 105: "on color(13)", + 106: "on color(14)", + 107: "on color(15)", +} + + +class AnsiDecoder: + """Translate ANSI code in to styled Text.""" + + def __init__(self) -> None: + self.style = Style.null() + + def decode(self, terminal_text: str) -> Iterable[Text]: + """Decode ANSI codes in an iterable of lines. + + Args: + lines (Iterable[str]): An iterable of lines of terminal output. + + Yields: + Text: Marked up Text. + """ + for line in terminal_text.splitlines(): + yield self.decode_line(line) + + def decode_line(self, line: str) -> Text: + """Decode a line containing ansi codes. + + Args: + line (str): A line of terminal output. + + Returns: + Text: A Text instance marked up according to ansi codes. + """ + from_ansi = Color.from_ansi + from_rgb = Color.from_rgb + _Style = Style + text = Text() + append = text.append + line = line.rsplit("\r", 1)[-1] + for plain_text, sgr, osc in _ansi_tokenize(line): + if plain_text: + append(plain_text, self.style or None) + elif osc is not None: + if osc.startswith("8;"): + _params, semicolon, link = osc[2:].partition(";") + if semicolon: + self.style = self.style.update_link(link or None) + elif sgr is not None: + # Translate in to semi-colon separated codes + # Ignore invalid codes, because we want to be lenient + codes = [ + min(255, int(_code) if _code else 0) + for _code in sgr.split(";") + if _code.isdigit() or _code == "" + ] + iter_codes = iter(codes) + for code in iter_codes: + if code == 0: + # reset + self.style = _Style.null() + elif code in SGR_STYLE_MAP: + # styles + self.style += _Style.parse(SGR_STYLE_MAP[code]) + elif code == 38: + #  Foreground + with suppress(StopIteration): + color_type = next(iter_codes) + if color_type == 5: + self.style += _Style.from_color( + from_ansi(next(iter_codes)) + ) + elif color_type == 2: + self.style += _Style.from_color( + from_rgb( + next(iter_codes), + next(iter_codes), + next(iter_codes), + ) + ) + elif code == 48: + # Background + with suppress(StopIteration): + color_type = next(iter_codes) + if color_type == 5: + self.style += _Style.from_color( + None, from_ansi(next(iter_codes)) + ) + elif color_type == 2: + self.style += _Style.from_color( + None, + from_rgb( + next(iter_codes), + next(iter_codes), + next(iter_codes), + ), + ) + + return text + + +if sys.platform != "win32" and __name__ == "__main__": # pragma: no cover + import io + import os + import pty + import sys + + decoder = AnsiDecoder() + + stdout = io.BytesIO() + + def read(fd: int) -> bytes: + data = os.read(fd, 1024) + stdout.write(data) + return data + + pty.spawn(sys.argv[1:], read) + + from .console import Console + + console = Console(record=True) + + stdout_result = stdout.getvalue().decode("utf-8") + print(stdout_result) + + for line in decoder.decode(stdout_result): + console.print(line) + + console.save_html("stdout.html") diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/bar.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/bar.py new file mode 100644 index 0000000..022284b --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/bar.py @@ -0,0 +1,93 @@ +from typing import Optional, Union + +from .color import Color +from .console import Console, ConsoleOptions, RenderResult +from .jupyter import JupyterMixin +from .measure import Measurement +from .segment import Segment +from .style import Style + +# There are left-aligned characters for 1/8 to 7/8, but +# the right-aligned characters exist only for 1/8 and 4/8. +BEGIN_BLOCK_ELEMENTS = ["█", "█", "█", "▐", "▐", "▐", "▕", "▕"] +END_BLOCK_ELEMENTS = [" ", "▏", "▎", "▍", "▌", "▋", "▊", "▉"] +FULL_BLOCK = "█" + + +class Bar(JupyterMixin): + """Renders a solid block bar. + + Args: + size (float): Value for the end of the bar. + begin (float): Begin point (between 0 and size, inclusive). + end (float): End point (between 0 and size, inclusive). + width (int, optional): Width of the bar, or ``None`` for maximum width. Defaults to None. + color (Union[Color, str], optional): Color of the bar. Defaults to "default". + bgcolor (Union[Color, str], optional): Color of bar background. Defaults to "default". + """ + + def __init__( + self, + size: float, + begin: float, + end: float, + *, + width: Optional[int] = None, + color: Union[Color, str] = "default", + bgcolor: Union[Color, str] = "default", + ): + self.size = size + self.begin = max(begin, 0) + self.end = min(end, size) + self.width = width + self.style = Style(color=color, bgcolor=bgcolor) + + def __repr__(self) -> str: + return f"Bar({self.size}, {self.begin}, {self.end})" + + def __rich_console__( + self, console: Console, options: ConsoleOptions + ) -> RenderResult: + width = min( + self.width if self.width is not None else options.max_width, + options.max_width, + ) + + if self.begin >= self.end: + yield Segment(" " * width, self.style) + yield Segment.line() + return + + prefix_complete_eights = int(width * 8 * self.begin / self.size) + prefix_bar_count = prefix_complete_eights // 8 + prefix_eights_count = prefix_complete_eights % 8 + + body_complete_eights = int(width * 8 * self.end / self.size) + body_bar_count = body_complete_eights // 8 + body_eights_count = body_complete_eights % 8 + + # When start and end fall into the same cell, we ideally should render + # a symbol that's "center-aligned", but there is no good symbol in Unicode. + # In this case, we fall back to right-aligned block symbol for simplicity. + + prefix = " " * prefix_bar_count + if prefix_eights_count: + prefix += BEGIN_BLOCK_ELEMENTS[prefix_eights_count] + + body = FULL_BLOCK * body_bar_count + if body_eights_count: + body += END_BLOCK_ELEMENTS[body_eights_count] + + suffix = " " * (width - len(body)) + + yield Segment(prefix + body[len(prefix) :] + suffix, self.style) + yield Segment.line() + + def __rich_measure__( + self, console: Console, options: ConsoleOptions + ) -> Measurement: + return ( + Measurement(self.width, self.width) + if self.width is not None + else Measurement(4, options.max_width) + ) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/box.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/box.py new file mode 100644 index 0000000..0511a9e --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/box.py @@ -0,0 +1,480 @@ +import sys +from typing import TYPE_CHECKING, Iterable, List + +if sys.version_info >= (3, 8): + from typing import Literal +else: + from pip._vendor.typing_extensions import Literal # pragma: no cover + + +from ._loop import loop_last + +if TYPE_CHECKING: + from pip._vendor.rich.console import ConsoleOptions + + +class Box: + """Defines characters to render boxes. + + ┌─┬┐ top + │ ││ head + ├─┼┤ head_row + │ ││ mid + ├─┼┤ row + ├─┼┤ foot_row + │ ││ foot + └─┴┘ bottom + + Args: + box (str): Characters making up box. + ascii (bool, optional): True if this box uses ascii characters only. Default is False. + """ + + def __init__(self, box: str, *, ascii: bool = False) -> None: + self._box = box + self.ascii = ascii + line1, line2, line3, line4, line5, line6, line7, line8 = box.splitlines() + # top + self.top_left, self.top, self.top_divider, self.top_right = iter(line1) + # head + self.head_left, _, self.head_vertical, self.head_right = iter(line2) + # head_row + ( + self.head_row_left, + self.head_row_horizontal, + self.head_row_cross, + self.head_row_right, + ) = iter(line3) + + # mid + self.mid_left, _, self.mid_vertical, self.mid_right = iter(line4) + # row + self.row_left, self.row_horizontal, self.row_cross, self.row_right = iter(line5) + # foot_row + ( + self.foot_row_left, + self.foot_row_horizontal, + self.foot_row_cross, + self.foot_row_right, + ) = iter(line6) + # foot + self.foot_left, _, self.foot_vertical, self.foot_right = iter(line7) + # bottom + self.bottom_left, self.bottom, self.bottom_divider, self.bottom_right = iter( + line8 + ) + + def __repr__(self) -> str: + return "Box(...)" + + def __str__(self) -> str: + return self._box + + def substitute(self, options: "ConsoleOptions", safe: bool = True) -> "Box": + """Substitute this box for another if it won't render due to platform issues. + + Args: + options (ConsoleOptions): Console options used in rendering. + safe (bool, optional): Substitute this for another Box if there are known problems + displaying on the platform (currently only relevant on Windows). Default is True. + + Returns: + Box: A different Box or the same Box. + """ + box = self + if options.legacy_windows and safe: + box = LEGACY_WINDOWS_SUBSTITUTIONS.get(box, box) + if options.ascii_only and not box.ascii: + box = ASCII + return box + + def get_plain_headed_box(self) -> "Box": + """If this box uses special characters for the borders of the header, then + return the equivalent box that does not. + + Returns: + Box: The most similar Box that doesn't use header-specific box characters. + If the current Box already satisfies this criterion, then it's returned. + """ + return PLAIN_HEADED_SUBSTITUTIONS.get(self, self) + + def get_top(self, widths: Iterable[int]) -> str: + """Get the top of a simple box. + + Args: + widths (List[int]): Widths of columns. + + Returns: + str: A string of box characters. + """ + + parts: List[str] = [] + append = parts.append + append(self.top_left) + for last, width in loop_last(widths): + append(self.top * width) + if not last: + append(self.top_divider) + append(self.top_right) + return "".join(parts) + + def get_row( + self, + widths: Iterable[int], + level: Literal["head", "row", "foot", "mid"] = "row", + edge: bool = True, + ) -> str: + """Get the top of a simple box. + + Args: + width (List[int]): Widths of columns. + + Returns: + str: A string of box characters. + """ + if level == "head": + left = self.head_row_left + horizontal = self.head_row_horizontal + cross = self.head_row_cross + right = self.head_row_right + elif level == "row": + left = self.row_left + horizontal = self.row_horizontal + cross = self.row_cross + right = self.row_right + elif level == "mid": + left = self.mid_left + horizontal = " " + cross = self.mid_vertical + right = self.mid_right + elif level == "foot": + left = self.foot_row_left + horizontal = self.foot_row_horizontal + cross = self.foot_row_cross + right = self.foot_row_right + else: + raise ValueError("level must be 'head', 'row' or 'foot'") + + parts: List[str] = [] + append = parts.append + if edge: + append(left) + for last, width in loop_last(widths): + append(horizontal * width) + if not last: + append(cross) + if edge: + append(right) + return "".join(parts) + + def get_bottom(self, widths: Iterable[int]) -> str: + """Get the bottom of a simple box. + + Args: + widths (List[int]): Widths of columns. + + Returns: + str: A string of box characters. + """ + + parts: List[str] = [] + append = parts.append + append(self.bottom_left) + for last, width in loop_last(widths): + append(self.bottom * width) + if not last: + append(self.bottom_divider) + append(self.bottom_right) + return "".join(parts) + + +# fmt: off +ASCII: Box = Box( + "+--+\n" + "| ||\n" + "|-+|\n" + "| ||\n" + "|-+|\n" + "|-+|\n" + "| ||\n" + "+--+\n", + ascii=True, +) + +ASCII2: Box = Box( + "+-++\n" + "| ||\n" + "+-++\n" + "| ||\n" + "+-++\n" + "+-++\n" + "| ||\n" + "+-++\n", + ascii=True, +) + +ASCII_DOUBLE_HEAD: Box = Box( + "+-++\n" + "| ||\n" + "+=++\n" + "| ||\n" + "+-++\n" + "+-++\n" + "| ||\n" + "+-++\n", + ascii=True, +) + +SQUARE: Box = Box( + "┌─┬┐\n" + "│ ││\n" + "├─┼┤\n" + "│ ││\n" + "├─┼┤\n" + "├─┼┤\n" + "│ ││\n" + "└─┴┘\n" +) + +SQUARE_DOUBLE_HEAD: Box = Box( + "┌─┬┐\n" + "│ ││\n" + "╞═╪╡\n" + "│ ││\n" + "├─┼┤\n" + "├─┼┤\n" + "│ ││\n" + "└─┴┘\n" +) + +MINIMAL: Box = Box( + " ╷ \n" + " │ \n" + "╶─┼╴\n" + " │ \n" + "╶─┼╴\n" + "╶─┼╴\n" + " │ \n" + " ╵ \n" +) + + +MINIMAL_HEAVY_HEAD: Box = Box( + " ╷ \n" + " │ \n" + "╺━┿╸\n" + " │ \n" + "╶─┼╴\n" + "╶─┼╴\n" + " │ \n" + " ╵ \n" +) + +MINIMAL_DOUBLE_HEAD: Box = Box( + " ╷ \n" + " │ \n" + " ═╪ \n" + " │ \n" + " ─┼ \n" + " ─┼ \n" + " │ \n" + " ╵ \n" +) + + +SIMPLE: Box = Box( + " \n" + " \n" + " ── \n" + " \n" + " \n" + " ── \n" + " \n" + " \n" +) + +SIMPLE_HEAD: Box = Box( + " \n" + " \n" + " ── \n" + " \n" + " \n" + " \n" + " \n" + " \n" +) + + +SIMPLE_HEAVY: Box = Box( + " \n" + " \n" + " ━━ \n" + " \n" + " \n" + " ━━ \n" + " \n" + " \n" +) + + +HORIZONTALS: Box = Box( + " ── \n" + " \n" + " ── \n" + " \n" + " ── \n" + " ── \n" + " \n" + " ── \n" +) + +ROUNDED: Box = Box( + "╭─┬╮\n" + "│ ││\n" + "├─┼┤\n" + "│ ││\n" + "├─┼┤\n" + "├─┼┤\n" + "│ ││\n" + "╰─┴╯\n" +) + +HEAVY: Box = Box( + "┏━┳┓\n" + "┃ ┃┃\n" + "┣━╋┫\n" + "┃ ┃┃\n" + "┣━╋┫\n" + "┣━╋┫\n" + "┃ ┃┃\n" + "┗━┻┛\n" +) + +HEAVY_EDGE: Box = Box( + "┏━┯┓\n" + "┃ │┃\n" + "┠─┼┨\n" + "┃ │┃\n" + "┠─┼┨\n" + "┠─┼┨\n" + "┃ │┃\n" + "┗━┷┛\n" +) + +HEAVY_HEAD: Box = Box( + "┏━┳┓\n" + "┃ ┃┃\n" + "┡━╇┩\n" + "│ ││\n" + "├─┼┤\n" + "├─┼┤\n" + "│ ││\n" + "└─┴┘\n" +) + +DOUBLE: Box = Box( + "╔═╦╗\n" + "║ ║║\n" + "╠═╬╣\n" + "║ ║║\n" + "╠═╬╣\n" + "╠═╬╣\n" + "║ ║║\n" + "╚═╩╝\n" +) + +DOUBLE_EDGE: Box = Box( + "╔═╤╗\n" + "║ │║\n" + "╟─┼╢\n" + "║ │║\n" + "╟─┼╢\n" + "╟─┼╢\n" + "║ │║\n" + "╚═╧╝\n" +) + +MARKDOWN: Box = Box( + " \n" + "| ||\n" + "|-||\n" + "| ||\n" + "|-||\n" + "|-||\n" + "| ||\n" + " \n", + ascii=True, +) +# fmt: on + +# Map Boxes that don't render with raster fonts on to equivalent that do +LEGACY_WINDOWS_SUBSTITUTIONS = { + ROUNDED: SQUARE, + MINIMAL_HEAVY_HEAD: MINIMAL, + SIMPLE_HEAVY: SIMPLE, + HEAVY: SQUARE, + HEAVY_EDGE: SQUARE, + HEAVY_HEAD: SQUARE, +} + +# Map headed boxes to their headerless equivalents +PLAIN_HEADED_SUBSTITUTIONS = { + HEAVY_HEAD: SQUARE, + SQUARE_DOUBLE_HEAD: SQUARE, + MINIMAL_DOUBLE_HEAD: MINIMAL, + MINIMAL_HEAVY_HEAD: MINIMAL, + ASCII_DOUBLE_HEAD: ASCII2, +} + + +if __name__ == "__main__": # pragma: no cover + from pip._vendor.rich.columns import Columns + from pip._vendor.rich.panel import Panel + + from . import box as box + from .console import Console + from .table import Table + from .text import Text + + console = Console(record=True) + + BOXES = [ + "ASCII", + "ASCII2", + "ASCII_DOUBLE_HEAD", + "SQUARE", + "SQUARE_DOUBLE_HEAD", + "MINIMAL", + "MINIMAL_HEAVY_HEAD", + "MINIMAL_DOUBLE_HEAD", + "SIMPLE", + "SIMPLE_HEAD", + "SIMPLE_HEAVY", + "HORIZONTALS", + "ROUNDED", + "HEAVY", + "HEAVY_EDGE", + "HEAVY_HEAD", + "DOUBLE", + "DOUBLE_EDGE", + "MARKDOWN", + ] + + console.print(Panel("[bold green]Box Constants", style="green"), justify="center") + console.print() + + columns = Columns(expand=True, padding=2) + for box_name in sorted(BOXES): + table = Table( + show_footer=True, style="dim", border_style="not dim", expand=True + ) + table.add_column("Header 1", "Footer 1") + table.add_column("Header 2", "Footer 2") + table.add_row("Cell", "Cell") + table.add_row("Cell", "Cell") + table.box = getattr(box, box_name) + table.title = Text(f"box.{box_name}", style="magenta") + columns.add_renderable(table) + console.print(columns) + + # console.save_svg("box.svg") diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/cells.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/cells.py new file mode 100644 index 0000000..f85f928 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/cells.py @@ -0,0 +1,167 @@ +from __future__ import annotations + +import re +from functools import lru_cache +from typing import Callable + +from ._cell_widths import CELL_WIDTHS + +# Regex to match sequence of the most common character ranges +_is_single_cell_widths = re.compile("^[\u0020-\u006f\u00a0\u02ff\u0370-\u0482]*$").match + + +@lru_cache(4096) +def cached_cell_len(text: str) -> int: + """Get the number of cells required to display text. + + This method always caches, which may use up a lot of memory. It is recommended to use + `cell_len` over this method. + + Args: + text (str): Text to display. + + Returns: + int: Get the number of cells required to display text. + """ + _get_size = get_character_cell_size + total_size = sum(_get_size(character) for character in text) + return total_size + + +def cell_len(text: str, _cell_len: Callable[[str], int] = cached_cell_len) -> int: + """Get the number of cells required to display text. + + Args: + text (str): Text to display. + + Returns: + int: Get the number of cells required to display text. + """ + if len(text) < 512: + return _cell_len(text) + _get_size = get_character_cell_size + total_size = sum(_get_size(character) for character in text) + return total_size + + +@lru_cache(maxsize=4096) +def get_character_cell_size(character: str) -> int: + """Get the cell size of a character. + + Args: + character (str): A single character. + + Returns: + int: Number of cells (0, 1 or 2) occupied by that character. + """ + return _get_codepoint_cell_size(ord(character)) + + +@lru_cache(maxsize=4096) +def _get_codepoint_cell_size(codepoint: int) -> int: + """Get the cell size of a character. + + Args: + codepoint (int): Codepoint of a character. + + Returns: + int: Number of cells (0, 1 or 2) occupied by that character. + """ + + _table = CELL_WIDTHS + lower_bound = 0 + upper_bound = len(_table) - 1 + index = (lower_bound + upper_bound) // 2 + while True: + start, end, width = _table[index] + if codepoint < start: + upper_bound = index - 1 + elif codepoint > end: + lower_bound = index + 1 + else: + return 0 if width == -1 else width + if upper_bound < lower_bound: + break + index = (lower_bound + upper_bound) // 2 + return 1 + + +def set_cell_size(text: str, total: int) -> str: + """Set the length of a string to fit within given number of cells.""" + + if _is_single_cell_widths(text): + size = len(text) + if size < total: + return text + " " * (total - size) + return text[:total] + + if total <= 0: + return "" + cell_size = cell_len(text) + if cell_size == total: + return text + if cell_size < total: + return text + " " * (total - cell_size) + + start = 0 + end = len(text) + + # Binary search until we find the right size + while True: + pos = (start + end) // 2 + before = text[: pos + 1] + before_len = cell_len(before) + if before_len == total + 1 and cell_len(before[-1]) == 2: + return before[:-1] + " " + if before_len == total: + return before + if before_len > total: + end = pos + else: + start = pos + + +def chop_cells( + text: str, + width: int, +) -> list[str]: + """Split text into lines such that each line fits within the available (cell) width. + + Args: + text: The text to fold such that it fits in the given width. + width: The width available (number of cells). + + Returns: + A list of strings such that each string in the list has cell width + less than or equal to the available width. + """ + _get_character_cell_size = get_character_cell_size + lines: list[list[str]] = [[]] + + append_new_line = lines.append + append_to_last_line = lines[-1].append + + total_width = 0 + + for character in text: + cell_width = _get_character_cell_size(character) + char_doesnt_fit = total_width + cell_width > width + + if char_doesnt_fit: + append_new_line([character]) + append_to_last_line = lines[-1].append + total_width = cell_width + else: + append_to_last_line(character) + total_width += cell_width + + return ["".join(line) for line in lines] + + +if __name__ == "__main__": # pragma: no cover + print(get_character_cell_size("😽")) + for line in chop_cells("""这是对亚洲语言支持的测试。面对模棱两可的想法,拒绝猜测的诱惑。""", 8): + print(line) + for n in range(80, 1, -1): + print(set_cell_size("""这是对亚洲语言支持的测试。面对模棱两可的想法,拒绝猜测的诱惑。""", n) + "|") + print("x" * n) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/color.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/color.py new file mode 100644 index 0000000..4270a27 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/color.py @@ -0,0 +1,621 @@ +import platform +import re +from colorsys import rgb_to_hls +from enum import IntEnum +from functools import lru_cache +from typing import TYPE_CHECKING, NamedTuple, Optional, Tuple + +from ._palettes import EIGHT_BIT_PALETTE, STANDARD_PALETTE, WINDOWS_PALETTE +from .color_triplet import ColorTriplet +from .repr import Result, rich_repr +from .terminal_theme import DEFAULT_TERMINAL_THEME + +if TYPE_CHECKING: # pragma: no cover + from .terminal_theme import TerminalTheme + from .text import Text + + +WINDOWS = platform.system() == "Windows" + + +class ColorSystem(IntEnum): + """One of the 3 color system supported by terminals.""" + + STANDARD = 1 + EIGHT_BIT = 2 + TRUECOLOR = 3 + WINDOWS = 4 + + def __repr__(self) -> str: + return f"ColorSystem.{self.name}" + + def __str__(self) -> str: + return repr(self) + + +class ColorType(IntEnum): + """Type of color stored in Color class.""" + + DEFAULT = 0 + STANDARD = 1 + EIGHT_BIT = 2 + TRUECOLOR = 3 + WINDOWS = 4 + + def __repr__(self) -> str: + return f"ColorType.{self.name}" + + +ANSI_COLOR_NAMES = { + "black": 0, + "red": 1, + "green": 2, + "yellow": 3, + "blue": 4, + "magenta": 5, + "cyan": 6, + "white": 7, + "bright_black": 8, + "bright_red": 9, + "bright_green": 10, + "bright_yellow": 11, + "bright_blue": 12, + "bright_magenta": 13, + "bright_cyan": 14, + "bright_white": 15, + "grey0": 16, + "gray0": 16, + "navy_blue": 17, + "dark_blue": 18, + "blue3": 20, + "blue1": 21, + "dark_green": 22, + "deep_sky_blue4": 25, + "dodger_blue3": 26, + "dodger_blue2": 27, + "green4": 28, + "spring_green4": 29, + "turquoise4": 30, + "deep_sky_blue3": 32, + "dodger_blue1": 33, + "green3": 40, + "spring_green3": 41, + "dark_cyan": 36, + "light_sea_green": 37, + "deep_sky_blue2": 38, + "deep_sky_blue1": 39, + "spring_green2": 47, + "cyan3": 43, + "dark_turquoise": 44, + "turquoise2": 45, + "green1": 46, + "spring_green1": 48, + "medium_spring_green": 49, + "cyan2": 50, + "cyan1": 51, + "dark_red": 88, + "deep_pink4": 125, + "purple4": 55, + "purple3": 56, + "blue_violet": 57, + "orange4": 94, + "grey37": 59, + "gray37": 59, + "medium_purple4": 60, + "slate_blue3": 62, + "royal_blue1": 63, + "chartreuse4": 64, + "dark_sea_green4": 71, + "pale_turquoise4": 66, + "steel_blue": 67, + "steel_blue3": 68, + "cornflower_blue": 69, + "chartreuse3": 76, + "cadet_blue": 73, + "sky_blue3": 74, + "steel_blue1": 81, + "pale_green3": 114, + "sea_green3": 78, + "aquamarine3": 79, + "medium_turquoise": 80, + "chartreuse2": 112, + "sea_green2": 83, + "sea_green1": 85, + "aquamarine1": 122, + "dark_slate_gray2": 87, + "dark_magenta": 91, + "dark_violet": 128, + "purple": 129, + "light_pink4": 95, + "plum4": 96, + "medium_purple3": 98, + "slate_blue1": 99, + "yellow4": 106, + "wheat4": 101, + "grey53": 102, + "gray53": 102, + "light_slate_grey": 103, + "light_slate_gray": 103, + "medium_purple": 104, + "light_slate_blue": 105, + "dark_olive_green3": 149, + "dark_sea_green": 108, + "light_sky_blue3": 110, + "sky_blue2": 111, + "dark_sea_green3": 150, + "dark_slate_gray3": 116, + "sky_blue1": 117, + "chartreuse1": 118, + "light_green": 120, + "pale_green1": 156, + "dark_slate_gray1": 123, + "red3": 160, + "medium_violet_red": 126, + "magenta3": 164, + "dark_orange3": 166, + "indian_red": 167, + "hot_pink3": 168, + "medium_orchid3": 133, + "medium_orchid": 134, + "medium_purple2": 140, + "dark_goldenrod": 136, + "light_salmon3": 173, + "rosy_brown": 138, + "grey63": 139, + "gray63": 139, + "medium_purple1": 141, + "gold3": 178, + "dark_khaki": 143, + "navajo_white3": 144, + "grey69": 145, + "gray69": 145, + "light_steel_blue3": 146, + "light_steel_blue": 147, + "yellow3": 184, + "dark_sea_green2": 157, + "light_cyan3": 152, + "light_sky_blue1": 153, + "green_yellow": 154, + "dark_olive_green2": 155, + "dark_sea_green1": 193, + "pale_turquoise1": 159, + "deep_pink3": 162, + "magenta2": 200, + "hot_pink2": 169, + "orchid": 170, + "medium_orchid1": 207, + "orange3": 172, + "light_pink3": 174, + "pink3": 175, + "plum3": 176, + "violet": 177, + "light_goldenrod3": 179, + "tan": 180, + "misty_rose3": 181, + "thistle3": 182, + "plum2": 183, + "khaki3": 185, + "light_goldenrod2": 222, + "light_yellow3": 187, + "grey84": 188, + "gray84": 188, + "light_steel_blue1": 189, + "yellow2": 190, + "dark_olive_green1": 192, + "honeydew2": 194, + "light_cyan1": 195, + "red1": 196, + "deep_pink2": 197, + "deep_pink1": 199, + "magenta1": 201, + "orange_red1": 202, + "indian_red1": 204, + "hot_pink": 206, + "dark_orange": 208, + "salmon1": 209, + "light_coral": 210, + "pale_violet_red1": 211, + "orchid2": 212, + "orchid1": 213, + "orange1": 214, + "sandy_brown": 215, + "light_salmon1": 216, + "light_pink1": 217, + "pink1": 218, + "plum1": 219, + "gold1": 220, + "navajo_white1": 223, + "misty_rose1": 224, + "thistle1": 225, + "yellow1": 226, + "light_goldenrod1": 227, + "khaki1": 228, + "wheat1": 229, + "cornsilk1": 230, + "grey100": 231, + "gray100": 231, + "grey3": 232, + "gray3": 232, + "grey7": 233, + "gray7": 233, + "grey11": 234, + "gray11": 234, + "grey15": 235, + "gray15": 235, + "grey19": 236, + "gray19": 236, + "grey23": 237, + "gray23": 237, + "grey27": 238, + "gray27": 238, + "grey30": 239, + "gray30": 239, + "grey35": 240, + "gray35": 240, + "grey39": 241, + "gray39": 241, + "grey42": 242, + "gray42": 242, + "grey46": 243, + "gray46": 243, + "grey50": 244, + "gray50": 244, + "grey54": 245, + "gray54": 245, + "grey58": 246, + "gray58": 246, + "grey62": 247, + "gray62": 247, + "grey66": 248, + "gray66": 248, + "grey70": 249, + "gray70": 249, + "grey74": 250, + "gray74": 250, + "grey78": 251, + "gray78": 251, + "grey82": 252, + "gray82": 252, + "grey85": 253, + "gray85": 253, + "grey89": 254, + "gray89": 254, + "grey93": 255, + "gray93": 255, +} + + +class ColorParseError(Exception): + """The color could not be parsed.""" + + +RE_COLOR = re.compile( + r"""^ +\#([0-9a-f]{6})$| +color\(([0-9]{1,3})\)$| +rgb\(([\d\s,]+)\)$ +""", + re.VERBOSE, +) + + +@rich_repr +class Color(NamedTuple): + """Terminal color definition.""" + + name: str + """The name of the color (typically the input to Color.parse).""" + type: ColorType + """The type of the color.""" + number: Optional[int] = None + """The color number, if a standard color, or None.""" + triplet: Optional[ColorTriplet] = None + """A triplet of color components, if an RGB color.""" + + def __rich__(self) -> "Text": + """Displays the actual color if Rich printed.""" + from .style import Style + from .text import Text + + return Text.assemble( + f"", + ) + + def __rich_repr__(self) -> Result: + yield self.name + yield self.type + yield "number", self.number, None + yield "triplet", self.triplet, None + + @property + def system(self) -> ColorSystem: + """Get the native color system for this color.""" + if self.type == ColorType.DEFAULT: + return ColorSystem.STANDARD + return ColorSystem(int(self.type)) + + @property + def is_system_defined(self) -> bool: + """Check if the color is ultimately defined by the system.""" + return self.system not in (ColorSystem.EIGHT_BIT, ColorSystem.TRUECOLOR) + + @property + def is_default(self) -> bool: + """Check if the color is a default color.""" + return self.type == ColorType.DEFAULT + + def get_truecolor( + self, theme: Optional["TerminalTheme"] = None, foreground: bool = True + ) -> ColorTriplet: + """Get an equivalent color triplet for this color. + + Args: + theme (TerminalTheme, optional): Optional terminal theme, or None to use default. Defaults to None. + foreground (bool, optional): True for a foreground color, or False for background. Defaults to True. + + Returns: + ColorTriplet: A color triplet containing RGB components. + """ + + if theme is None: + theme = DEFAULT_TERMINAL_THEME + if self.type == ColorType.TRUECOLOR: + assert self.triplet is not None + return self.triplet + elif self.type == ColorType.EIGHT_BIT: + assert self.number is not None + return EIGHT_BIT_PALETTE[self.number] + elif self.type == ColorType.STANDARD: + assert self.number is not None + return theme.ansi_colors[self.number] + elif self.type == ColorType.WINDOWS: + assert self.number is not None + return WINDOWS_PALETTE[self.number] + else: # self.type == ColorType.DEFAULT: + assert self.number is None + return theme.foreground_color if foreground else theme.background_color + + @classmethod + def from_ansi(cls, number: int) -> "Color": + """Create a Color number from it's 8-bit ansi number. + + Args: + number (int): A number between 0-255 inclusive. + + Returns: + Color: A new Color instance. + """ + return cls( + name=f"color({number})", + type=(ColorType.STANDARD if number < 16 else ColorType.EIGHT_BIT), + number=number, + ) + + @classmethod + def from_triplet(cls, triplet: "ColorTriplet") -> "Color": + """Create a truecolor RGB color from a triplet of values. + + Args: + triplet (ColorTriplet): A color triplet containing red, green and blue components. + + Returns: + Color: A new color object. + """ + return cls(name=triplet.hex, type=ColorType.TRUECOLOR, triplet=triplet) + + @classmethod + def from_rgb(cls, red: float, green: float, blue: float) -> "Color": + """Create a truecolor from three color components in the range(0->255). + + Args: + red (float): Red component in range 0-255. + green (float): Green component in range 0-255. + blue (float): Blue component in range 0-255. + + Returns: + Color: A new color object. + """ + return cls.from_triplet(ColorTriplet(int(red), int(green), int(blue))) + + @classmethod + def default(cls) -> "Color": + """Get a Color instance representing the default color. + + Returns: + Color: Default color. + """ + return cls(name="default", type=ColorType.DEFAULT) + + @classmethod + @lru_cache(maxsize=1024) + def parse(cls, color: str) -> "Color": + """Parse a color definition.""" + original_color = color + color = color.lower().strip() + + if color == "default": + return cls(color, type=ColorType.DEFAULT) + + color_number = ANSI_COLOR_NAMES.get(color) + if color_number is not None: + return cls( + color, + type=(ColorType.STANDARD if color_number < 16 else ColorType.EIGHT_BIT), + number=color_number, + ) + + color_match = RE_COLOR.match(color) + if color_match is None: + raise ColorParseError(f"{original_color!r} is not a valid color") + + color_24, color_8, color_rgb = color_match.groups() + if color_24: + triplet = ColorTriplet( + int(color_24[0:2], 16), int(color_24[2:4], 16), int(color_24[4:6], 16) + ) + return cls(color, ColorType.TRUECOLOR, triplet=triplet) + + elif color_8: + number = int(color_8) + if number > 255: + raise ColorParseError(f"color number must be <= 255 in {color!r}") + return cls( + color, + type=(ColorType.STANDARD if number < 16 else ColorType.EIGHT_BIT), + number=number, + ) + + else: # color_rgb: + components = color_rgb.split(",") + if len(components) != 3: + raise ColorParseError( + f"expected three components in {original_color!r}" + ) + red, green, blue = components + triplet = ColorTriplet(int(red), int(green), int(blue)) + if not all(component <= 255 for component in triplet): + raise ColorParseError( + f"color components must be <= 255 in {original_color!r}" + ) + return cls(color, ColorType.TRUECOLOR, triplet=triplet) + + @lru_cache(maxsize=1024) + def get_ansi_codes(self, foreground: bool = True) -> Tuple[str, ...]: + """Get the ANSI escape codes for this color.""" + _type = self.type + if _type == ColorType.DEFAULT: + return ("39" if foreground else "49",) + + elif _type == ColorType.WINDOWS: + number = self.number + assert number is not None + fore, back = (30, 40) if number < 8 else (82, 92) + return (str(fore + number if foreground else back + number),) + + elif _type == ColorType.STANDARD: + number = self.number + assert number is not None + fore, back = (30, 40) if number < 8 else (82, 92) + return (str(fore + number if foreground else back + number),) + + elif _type == ColorType.EIGHT_BIT: + assert self.number is not None + return ("38" if foreground else "48", "5", str(self.number)) + + else: # self.standard == ColorStandard.TRUECOLOR: + assert self.triplet is not None + red, green, blue = self.triplet + return ("38" if foreground else "48", "2", str(red), str(green), str(blue)) + + @lru_cache(maxsize=1024) + def downgrade(self, system: ColorSystem) -> "Color": + """Downgrade a color system to a system with fewer colors.""" + + if self.type in (ColorType.DEFAULT, system): + return self + # Convert to 8-bit color from truecolor color + if system == ColorSystem.EIGHT_BIT and self.system == ColorSystem.TRUECOLOR: + assert self.triplet is not None + _h, l, s = rgb_to_hls(*self.triplet.normalized) + # If saturation is under 15% assume it is grayscale + if s < 0.15: + gray = round(l * 25.0) + if gray == 0: + color_number = 16 + elif gray == 25: + color_number = 231 + else: + color_number = 231 + gray + return Color(self.name, ColorType.EIGHT_BIT, number=color_number) + + red, green, blue = self.triplet + six_red = red / 95 if red < 95 else 1 + (red - 95) / 40 + six_green = green / 95 if green < 95 else 1 + (green - 95) / 40 + six_blue = blue / 95 if blue < 95 else 1 + (blue - 95) / 40 + + color_number = ( + 16 + 36 * round(six_red) + 6 * round(six_green) + round(six_blue) + ) + return Color(self.name, ColorType.EIGHT_BIT, number=color_number) + + # Convert to standard from truecolor or 8-bit + elif system == ColorSystem.STANDARD: + if self.system == ColorSystem.TRUECOLOR: + assert self.triplet is not None + triplet = self.triplet + else: # self.system == ColorSystem.EIGHT_BIT + assert self.number is not None + triplet = ColorTriplet(*EIGHT_BIT_PALETTE[self.number]) + + color_number = STANDARD_PALETTE.match(triplet) + return Color(self.name, ColorType.STANDARD, number=color_number) + + elif system == ColorSystem.WINDOWS: + if self.system == ColorSystem.TRUECOLOR: + assert self.triplet is not None + triplet = self.triplet + else: # self.system == ColorSystem.EIGHT_BIT + assert self.number is not None + if self.number < 16: + return Color(self.name, ColorType.WINDOWS, number=self.number) + triplet = ColorTriplet(*EIGHT_BIT_PALETTE[self.number]) + + color_number = WINDOWS_PALETTE.match(triplet) + return Color(self.name, ColorType.WINDOWS, number=color_number) + + return self + + +def parse_rgb_hex(hex_color: str) -> ColorTriplet: + """Parse six hex characters in to RGB triplet.""" + assert len(hex_color) == 6, "must be 6 characters" + color = ColorTriplet( + int(hex_color[0:2], 16), int(hex_color[2:4], 16), int(hex_color[4:6], 16) + ) + return color + + +def blend_rgb( + color1: ColorTriplet, color2: ColorTriplet, cross_fade: float = 0.5 +) -> ColorTriplet: + """Blend one RGB color in to another.""" + r1, g1, b1 = color1 + r2, g2, b2 = color2 + new_color = ColorTriplet( + int(r1 + (r2 - r1) * cross_fade), + int(g1 + (g2 - g1) * cross_fade), + int(b1 + (b2 - b1) * cross_fade), + ) + return new_color + + +if __name__ == "__main__": # pragma: no cover + from .console import Console + from .table import Table + from .text import Text + + console = Console() + + table = Table(show_footer=False, show_edge=True) + table.add_column("Color", width=10, overflow="ellipsis") + table.add_column("Number", justify="right", style="yellow") + table.add_column("Name", style="green") + table.add_column("Hex", style="blue") + table.add_column("RGB", style="magenta") + + colors = sorted((v, k) for k, v in ANSI_COLOR_NAMES.items()) + for color_number, name in colors: + if "grey" in name: + continue + color_cell = Text(" " * 10, style=f"on {name}") + if color_number < 16: + table.add_row(color_cell, f"{color_number}", Text(f'"{name}"')) + else: + color = EIGHT_BIT_PALETTE[color_number] # type: ignore[has-type] + table.add_row( + color_cell, str(color_number), Text(f'"{name}"'), color.hex, color.rgb + ) + + console.print(table) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/color_triplet.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/color_triplet.py new file mode 100644 index 0000000..02cab32 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/color_triplet.py @@ -0,0 +1,38 @@ +from typing import NamedTuple, Tuple + + +class ColorTriplet(NamedTuple): + """The red, green, and blue components of a color.""" + + red: int + """Red component in 0 to 255 range.""" + green: int + """Green component in 0 to 255 range.""" + blue: int + """Blue component in 0 to 255 range.""" + + @property + def hex(self) -> str: + """get the color triplet in CSS style.""" + red, green, blue = self + return f"#{red:02x}{green:02x}{blue:02x}" + + @property + def rgb(self) -> str: + """The color in RGB format. + + Returns: + str: An rgb color, e.g. ``"rgb(100,23,255)"``. + """ + red, green, blue = self + return f"rgb({red},{green},{blue})" + + @property + def normalized(self) -> Tuple[float, float, float]: + """Convert components into floats between 0 and 1. + + Returns: + Tuple[float, float, float]: A tuple of three normalized colour components. + """ + red, green, blue = self + return red / 255.0, green / 255.0, blue / 255.0 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/columns.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/columns.py new file mode 100644 index 0000000..669a3a7 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/columns.py @@ -0,0 +1,187 @@ +from collections import defaultdict +from itertools import chain +from operator import itemgetter +from typing import Dict, Iterable, List, Optional, Tuple + +from .align import Align, AlignMethod +from .console import Console, ConsoleOptions, RenderableType, RenderResult +from .constrain import Constrain +from .measure import Measurement +from .padding import Padding, PaddingDimensions +from .table import Table +from .text import TextType +from .jupyter import JupyterMixin + + +class Columns(JupyterMixin): + """Display renderables in neat columns. + + Args: + renderables (Iterable[RenderableType]): Any number of Rich renderables (including str). + width (int, optional): The desired width of the columns, or None to auto detect. Defaults to None. + padding (PaddingDimensions, optional): Optional padding around cells. Defaults to (0, 1). + expand (bool, optional): Expand columns to full width. Defaults to False. + equal (bool, optional): Arrange in to equal sized columns. Defaults to False. + column_first (bool, optional): Align items from top to bottom (rather than left to right). Defaults to False. + right_to_left (bool, optional): Start column from right hand side. Defaults to False. + align (str, optional): Align value ("left", "right", or "center") or None for default. Defaults to None. + title (TextType, optional): Optional title for Columns. + """ + + def __init__( + self, + renderables: Optional[Iterable[RenderableType]] = None, + padding: PaddingDimensions = (0, 1), + *, + width: Optional[int] = None, + expand: bool = False, + equal: bool = False, + column_first: bool = False, + right_to_left: bool = False, + align: Optional[AlignMethod] = None, + title: Optional[TextType] = None, + ) -> None: + self.renderables = list(renderables or []) + self.width = width + self.padding = padding + self.expand = expand + self.equal = equal + self.column_first = column_first + self.right_to_left = right_to_left + self.align: Optional[AlignMethod] = align + self.title = title + + def add_renderable(self, renderable: RenderableType) -> None: + """Add a renderable to the columns. + + Args: + renderable (RenderableType): Any renderable object. + """ + self.renderables.append(renderable) + + def __rich_console__( + self, console: Console, options: ConsoleOptions + ) -> RenderResult: + render_str = console.render_str + renderables = [ + render_str(renderable) if isinstance(renderable, str) else renderable + for renderable in self.renderables + ] + if not renderables: + return + _top, right, _bottom, left = Padding.unpack(self.padding) + width_padding = max(left, right) + max_width = options.max_width + widths: Dict[int, int] = defaultdict(int) + column_count = len(renderables) + + get_measurement = Measurement.get + renderable_widths = [ + get_measurement(console, options, renderable).maximum + for renderable in renderables + ] + if self.equal: + renderable_widths = [max(renderable_widths)] * len(renderable_widths) + + def iter_renderables( + column_count: int, + ) -> Iterable[Tuple[int, Optional[RenderableType]]]: + item_count = len(renderables) + if self.column_first: + width_renderables = list(zip(renderable_widths, renderables)) + + column_lengths: List[int] = [item_count // column_count] * column_count + for col_no in range(item_count % column_count): + column_lengths[col_no] += 1 + + row_count = (item_count + column_count - 1) // column_count + cells = [[-1] * column_count for _ in range(row_count)] + row = col = 0 + for index in range(item_count): + cells[row][col] = index + column_lengths[col] -= 1 + if column_lengths[col]: + row += 1 + else: + col += 1 + row = 0 + for index in chain.from_iterable(cells): + if index == -1: + break + yield width_renderables[index] + else: + yield from zip(renderable_widths, renderables) + # Pad odd elements with spaces + if item_count % column_count: + for _ in range(column_count - (item_count % column_count)): + yield 0, None + + table = Table.grid(padding=self.padding, collapse_padding=True, pad_edge=False) + table.expand = self.expand + table.title = self.title + + if self.width is not None: + column_count = (max_width) // (self.width + width_padding) + for _ in range(column_count): + table.add_column(width=self.width) + else: + while column_count > 1: + widths.clear() + column_no = 0 + for renderable_width, _ in iter_renderables(column_count): + widths[column_no] = max(widths[column_no], renderable_width) + total_width = sum(widths.values()) + width_padding * ( + len(widths) - 1 + ) + if total_width > max_width: + column_count = len(widths) - 1 + break + else: + column_no = (column_no + 1) % column_count + else: + break + + get_renderable = itemgetter(1) + _renderables = [ + get_renderable(_renderable) + for _renderable in iter_renderables(column_count) + ] + if self.equal: + _renderables = [ + None + if renderable is None + else Constrain(renderable, renderable_widths[0]) + for renderable in _renderables + ] + if self.align: + align = self.align + _Align = Align + _renderables = [ + None if renderable is None else _Align(renderable, align) + for renderable in _renderables + ] + + right_to_left = self.right_to_left + add_row = table.add_row + for start in range(0, len(_renderables), column_count): + row = _renderables[start : start + column_count] + if right_to_left: + row = row[::-1] + add_row(*row) + yield table + + +if __name__ == "__main__": # pragma: no cover + import os + + console = Console() + + files = [f"{i} {s}" for i, s in enumerate(sorted(os.listdir()))] + columns = Columns(files, padding=(0, 1), expand=False, equal=False) + console.print(columns) + console.rule() + columns.column_first = True + console.print(columns) + columns.right_to_left = True + console.rule() + console.print(columns) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/console.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/console.py new file mode 100644 index 0000000..a11c7c1 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/console.py @@ -0,0 +1,2633 @@ +import inspect +import os +import platform +import sys +import threading +import zlib +from abc import ABC, abstractmethod +from dataclasses import dataclass, field +from datetime import datetime +from functools import wraps +from getpass import getpass +from html import escape +from inspect import isclass +from itertools import islice +from math import ceil +from time import monotonic +from types import FrameType, ModuleType, TracebackType +from typing import ( + IO, + TYPE_CHECKING, + Any, + Callable, + Dict, + Iterable, + List, + Mapping, + NamedTuple, + Optional, + TextIO, + Tuple, + Type, + Union, + cast, +) + +from pip._vendor.rich._null_file import NULL_FILE + +if sys.version_info >= (3, 8): + from typing import Literal, Protocol, runtime_checkable +else: + from pip._vendor.typing_extensions import ( + Literal, + Protocol, + runtime_checkable, + ) # pragma: no cover + +from . import errors, themes +from ._emoji_replace import _emoji_replace +from ._export_format import CONSOLE_HTML_FORMAT, CONSOLE_SVG_FORMAT +from ._fileno import get_fileno +from ._log_render import FormatTimeCallable, LogRender +from .align import Align, AlignMethod +from .color import ColorSystem, blend_rgb +from .control import Control +from .emoji import EmojiVariant +from .highlighter import NullHighlighter, ReprHighlighter +from .markup import render as render_markup +from .measure import Measurement, measure_renderables +from .pager import Pager, SystemPager +from .pretty import Pretty, is_expandable +from .protocol import rich_cast +from .region import Region +from .scope import render_scope +from .screen import Screen +from .segment import Segment +from .style import Style, StyleType +from .styled import Styled +from .terminal_theme import DEFAULT_TERMINAL_THEME, SVG_EXPORT_THEME, TerminalTheme +from .text import Text, TextType +from .theme import Theme, ThemeStack + +if TYPE_CHECKING: + from ._windows import WindowsConsoleFeatures + from .live import Live + from .status import Status + +JUPYTER_DEFAULT_COLUMNS = 115 +JUPYTER_DEFAULT_LINES = 100 +WINDOWS = platform.system() == "Windows" + +HighlighterType = Callable[[Union[str, "Text"]], "Text"] +JustifyMethod = Literal["default", "left", "center", "right", "full"] +OverflowMethod = Literal["fold", "crop", "ellipsis", "ignore"] + + +class NoChange: + pass + + +NO_CHANGE = NoChange() + +try: + _STDIN_FILENO = sys.__stdin__.fileno() +except Exception: + _STDIN_FILENO = 0 +try: + _STDOUT_FILENO = sys.__stdout__.fileno() +except Exception: + _STDOUT_FILENO = 1 +try: + _STDERR_FILENO = sys.__stderr__.fileno() +except Exception: + _STDERR_FILENO = 2 + +_STD_STREAMS = (_STDIN_FILENO, _STDOUT_FILENO, _STDERR_FILENO) +_STD_STREAMS_OUTPUT = (_STDOUT_FILENO, _STDERR_FILENO) + + +_TERM_COLORS = { + "kitty": ColorSystem.EIGHT_BIT, + "256color": ColorSystem.EIGHT_BIT, + "16color": ColorSystem.STANDARD, +} + + +class ConsoleDimensions(NamedTuple): + """Size of the terminal.""" + + width: int + """The width of the console in 'cells'.""" + height: int + """The height of the console in lines.""" + + +@dataclass +class ConsoleOptions: + """Options for __rich_console__ method.""" + + size: ConsoleDimensions + """Size of console.""" + legacy_windows: bool + """legacy_windows: flag for legacy windows.""" + min_width: int + """Minimum width of renderable.""" + max_width: int + """Maximum width of renderable.""" + is_terminal: bool + """True if the target is a terminal, otherwise False.""" + encoding: str + """Encoding of terminal.""" + max_height: int + """Height of container (starts as terminal)""" + justify: Optional[JustifyMethod] = None + """Justify value override for renderable.""" + overflow: Optional[OverflowMethod] = None + """Overflow value override for renderable.""" + no_wrap: Optional[bool] = False + """Disable wrapping for text.""" + highlight: Optional[bool] = None + """Highlight override for render_str.""" + markup: Optional[bool] = None + """Enable markup when rendering strings.""" + height: Optional[int] = None + + @property + def ascii_only(self) -> bool: + """Check if renderables should use ascii only.""" + return not self.encoding.startswith("utf") + + def copy(self) -> "ConsoleOptions": + """Return a copy of the options. + + Returns: + ConsoleOptions: a copy of self. + """ + options: ConsoleOptions = ConsoleOptions.__new__(ConsoleOptions) + options.__dict__ = self.__dict__.copy() + return options + + def update( + self, + *, + width: Union[int, NoChange] = NO_CHANGE, + min_width: Union[int, NoChange] = NO_CHANGE, + max_width: Union[int, NoChange] = NO_CHANGE, + justify: Union[Optional[JustifyMethod], NoChange] = NO_CHANGE, + overflow: Union[Optional[OverflowMethod], NoChange] = NO_CHANGE, + no_wrap: Union[Optional[bool], NoChange] = NO_CHANGE, + highlight: Union[Optional[bool], NoChange] = NO_CHANGE, + markup: Union[Optional[bool], NoChange] = NO_CHANGE, + height: Union[Optional[int], NoChange] = NO_CHANGE, + ) -> "ConsoleOptions": + """Update values, return a copy.""" + options = self.copy() + if not isinstance(width, NoChange): + options.min_width = options.max_width = max(0, width) + if not isinstance(min_width, NoChange): + options.min_width = min_width + if not isinstance(max_width, NoChange): + options.max_width = max_width + if not isinstance(justify, NoChange): + options.justify = justify + if not isinstance(overflow, NoChange): + options.overflow = overflow + if not isinstance(no_wrap, NoChange): + options.no_wrap = no_wrap + if not isinstance(highlight, NoChange): + options.highlight = highlight + if not isinstance(markup, NoChange): + options.markup = markup + if not isinstance(height, NoChange): + if height is not None: + options.max_height = height + options.height = None if height is None else max(0, height) + return options + + def update_width(self, width: int) -> "ConsoleOptions": + """Update just the width, return a copy. + + Args: + width (int): New width (sets both min_width and max_width) + + Returns: + ~ConsoleOptions: New console options instance. + """ + options = self.copy() + options.min_width = options.max_width = max(0, width) + return options + + def update_height(self, height: int) -> "ConsoleOptions": + """Update the height, and return a copy. + + Args: + height (int): New height + + Returns: + ~ConsoleOptions: New Console options instance. + """ + options = self.copy() + options.max_height = options.height = height + return options + + def reset_height(self) -> "ConsoleOptions": + """Return a copy of the options with height set to ``None``. + + Returns: + ~ConsoleOptions: New console options instance. + """ + options = self.copy() + options.height = None + return options + + def update_dimensions(self, width: int, height: int) -> "ConsoleOptions": + """Update the width and height, and return a copy. + + Args: + width (int): New width (sets both min_width and max_width). + height (int): New height. + + Returns: + ~ConsoleOptions: New console options instance. + """ + options = self.copy() + options.min_width = options.max_width = max(0, width) + options.height = options.max_height = height + return options + + +@runtime_checkable +class RichCast(Protocol): + """An object that may be 'cast' to a console renderable.""" + + def __rich__( + self, + ) -> Union["ConsoleRenderable", "RichCast", str]: # pragma: no cover + ... + + +@runtime_checkable +class ConsoleRenderable(Protocol): + """An object that supports the console protocol.""" + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": # pragma: no cover + ... + + +# A type that may be rendered by Console. +RenderableType = Union[ConsoleRenderable, RichCast, str] +"""A string or any object that may be rendered by Rich.""" + +# The result of calling a __rich_console__ method. +RenderResult = Iterable[Union[RenderableType, Segment]] + +_null_highlighter = NullHighlighter() + + +class CaptureError(Exception): + """An error in the Capture context manager.""" + + +class NewLine: + """A renderable to generate new line(s)""" + + def __init__(self, count: int = 1) -> None: + self.count = count + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> Iterable[Segment]: + yield Segment("\n" * self.count) + + +class ScreenUpdate: + """Render a list of lines at a given offset.""" + + def __init__(self, lines: List[List[Segment]], x: int, y: int) -> None: + self._lines = lines + self.x = x + self.y = y + + def __rich_console__( + self, console: "Console", options: ConsoleOptions + ) -> RenderResult: + x = self.x + move_to = Control.move_to + for offset, line in enumerate(self._lines, self.y): + yield move_to(x, offset) + yield from line + + +class Capture: + """Context manager to capture the result of printing to the console. + See :meth:`~rich.console.Console.capture` for how to use. + + Args: + console (Console): A console instance to capture output. + """ + + def __init__(self, console: "Console") -> None: + self._console = console + self._result: Optional[str] = None + + def __enter__(self) -> "Capture": + self._console.begin_capture() + return self + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + self._result = self._console.end_capture() + + def get(self) -> str: + """Get the result of the capture.""" + if self._result is None: + raise CaptureError( + "Capture result is not available until context manager exits." + ) + return self._result + + +class ThemeContext: + """A context manager to use a temporary theme. See :meth:`~rich.console.Console.use_theme` for usage.""" + + def __init__(self, console: "Console", theme: Theme, inherit: bool = True) -> None: + self.console = console + self.theme = theme + self.inherit = inherit + + def __enter__(self) -> "ThemeContext": + self.console.push_theme(self.theme) + return self + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + self.console.pop_theme() + + +class PagerContext: + """A context manager that 'pages' content. See :meth:`~rich.console.Console.pager` for usage.""" + + def __init__( + self, + console: "Console", + pager: Optional[Pager] = None, + styles: bool = False, + links: bool = False, + ) -> None: + self._console = console + self.pager = SystemPager() if pager is None else pager + self.styles = styles + self.links = links + + def __enter__(self) -> "PagerContext": + self._console._enter_buffer() + return self + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + if exc_type is None: + with self._console._lock: + buffer: List[Segment] = self._console._buffer[:] + del self._console._buffer[:] + segments: Iterable[Segment] = buffer + if not self.styles: + segments = Segment.strip_styles(segments) + elif not self.links: + segments = Segment.strip_links(segments) + content = self._console._render_buffer(segments) + self.pager.show(content) + self._console._exit_buffer() + + +class ScreenContext: + """A context manager that enables an alternative screen. See :meth:`~rich.console.Console.screen` for usage.""" + + def __init__( + self, console: "Console", hide_cursor: bool, style: StyleType = "" + ) -> None: + self.console = console + self.hide_cursor = hide_cursor + self.screen = Screen(style=style) + self._changed = False + + def update( + self, *renderables: RenderableType, style: Optional[StyleType] = None + ) -> None: + """Update the screen. + + Args: + renderable (RenderableType, optional): Optional renderable to replace current renderable, + or None for no change. Defaults to None. + style: (Style, optional): Replacement style, or None for no change. Defaults to None. + """ + if renderables: + self.screen.renderable = ( + Group(*renderables) if len(renderables) > 1 else renderables[0] + ) + if style is not None: + self.screen.style = style + self.console.print(self.screen, end="") + + def __enter__(self) -> "ScreenContext": + self._changed = self.console.set_alt_screen(True) + if self._changed and self.hide_cursor: + self.console.show_cursor(False) + return self + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + if self._changed: + self.console.set_alt_screen(False) + if self.hide_cursor: + self.console.show_cursor(True) + + +class Group: + """Takes a group of renderables and returns a renderable object that renders the group. + + Args: + renderables (Iterable[RenderableType]): An iterable of renderable objects. + fit (bool, optional): Fit dimension of group to contents, or fill available space. Defaults to True. + """ + + def __init__(self, *renderables: "RenderableType", fit: bool = True) -> None: + self._renderables = renderables + self.fit = fit + self._render: Optional[List[RenderableType]] = None + + @property + def renderables(self) -> List["RenderableType"]: + if self._render is None: + self._render = list(self._renderables) + return self._render + + def __rich_measure__( + self, console: "Console", options: "ConsoleOptions" + ) -> "Measurement": + if self.fit: + return measure_renderables(console, options, self.renderables) + else: + return Measurement(options.max_width, options.max_width) + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> RenderResult: + yield from self.renderables + + +def group(fit: bool = True) -> Callable[..., Callable[..., Group]]: + """A decorator that turns an iterable of renderables in to a group. + + Args: + fit (bool, optional): Fit dimension of group to contents, or fill available space. Defaults to True. + """ + + def decorator( + method: Callable[..., Iterable[RenderableType]] + ) -> Callable[..., Group]: + """Convert a method that returns an iterable of renderables in to a Group.""" + + @wraps(method) + def _replace(*args: Any, **kwargs: Any) -> Group: + renderables = method(*args, **kwargs) + return Group(*renderables, fit=fit) + + return _replace + + return decorator + + +def _is_jupyter() -> bool: # pragma: no cover + """Check if we're running in a Jupyter notebook.""" + try: + get_ipython # type: ignore[name-defined] + except NameError: + return False + ipython = get_ipython() # type: ignore[name-defined] + shell = ipython.__class__.__name__ + if ( + "google.colab" in str(ipython.__class__) + or os.getenv("DATABRICKS_RUNTIME_VERSION") + or shell == "ZMQInteractiveShell" + ): + return True # Jupyter notebook or qtconsole + elif shell == "TerminalInteractiveShell": + return False # Terminal running IPython + else: + return False # Other type (?) + + +COLOR_SYSTEMS = { + "standard": ColorSystem.STANDARD, + "256": ColorSystem.EIGHT_BIT, + "truecolor": ColorSystem.TRUECOLOR, + "windows": ColorSystem.WINDOWS, +} + +_COLOR_SYSTEMS_NAMES = {system: name for name, system in COLOR_SYSTEMS.items()} + + +@dataclass +class ConsoleThreadLocals(threading.local): + """Thread local values for Console context.""" + + theme_stack: ThemeStack + buffer: List[Segment] = field(default_factory=list) + buffer_index: int = 0 + + +class RenderHook(ABC): + """Provides hooks in to the render process.""" + + @abstractmethod + def process_renderables( + self, renderables: List[ConsoleRenderable] + ) -> List[ConsoleRenderable]: + """Called with a list of objects to render. + + This method can return a new list of renderables, or modify and return the same list. + + Args: + renderables (List[ConsoleRenderable]): A number of renderable objects. + + Returns: + List[ConsoleRenderable]: A replacement list of renderables. + """ + + +_windows_console_features: Optional["WindowsConsoleFeatures"] = None + + +def get_windows_console_features() -> "WindowsConsoleFeatures": # pragma: no cover + global _windows_console_features + if _windows_console_features is not None: + return _windows_console_features + from ._windows import get_windows_console_features + + _windows_console_features = get_windows_console_features() + return _windows_console_features + + +def detect_legacy_windows() -> bool: + """Detect legacy Windows.""" + return WINDOWS and not get_windows_console_features().vt + + +class Console: + """A high level console interface. + + Args: + color_system (str, optional): The color system supported by your terminal, + either ``"standard"``, ``"256"`` or ``"truecolor"``. Leave as ``"auto"`` to autodetect. + force_terminal (Optional[bool], optional): Enable/disable terminal control codes, or None to auto-detect terminal. Defaults to None. + force_jupyter (Optional[bool], optional): Enable/disable Jupyter rendering, or None to auto-detect Jupyter. Defaults to None. + force_interactive (Optional[bool], optional): Enable/disable interactive mode, or None to auto detect. Defaults to None. + soft_wrap (Optional[bool], optional): Set soft wrap default on print method. Defaults to False. + theme (Theme, optional): An optional style theme object, or ``None`` for default theme. + stderr (bool, optional): Use stderr rather than stdout if ``file`` is not specified. Defaults to False. + file (IO, optional): A file object where the console should write to. Defaults to stdout. + quiet (bool, Optional): Boolean to suppress all output. Defaults to False. + width (int, optional): The width of the terminal. Leave as default to auto-detect width. + height (int, optional): The height of the terminal. Leave as default to auto-detect height. + style (StyleType, optional): Style to apply to all output, or None for no style. Defaults to None. + no_color (Optional[bool], optional): Enabled no color mode, or None to auto detect. Defaults to None. + tab_size (int, optional): Number of spaces used to replace a tab character. Defaults to 8. + record (bool, optional): Boolean to enable recording of terminal output, + required to call :meth:`export_html`, :meth:`export_svg`, and :meth:`export_text`. Defaults to False. + markup (bool, optional): Boolean to enable :ref:`console_markup`. Defaults to True. + emoji (bool, optional): Enable emoji code. Defaults to True. + emoji_variant (str, optional): Optional emoji variant, either "text" or "emoji". Defaults to None. + highlight (bool, optional): Enable automatic highlighting. Defaults to True. + log_time (bool, optional): Boolean to enable logging of time by :meth:`log` methods. Defaults to True. + log_path (bool, optional): Boolean to enable the logging of the caller by :meth:`log`. Defaults to True. + log_time_format (Union[str, TimeFormatterCallable], optional): If ``log_time`` is enabled, either string for strftime or callable that formats the time. Defaults to "[%X] ". + highlighter (HighlighterType, optional): Default highlighter. + legacy_windows (bool, optional): Enable legacy Windows mode, or ``None`` to auto detect. Defaults to ``None``. + safe_box (bool, optional): Restrict box options that don't render on legacy Windows. + get_datetime (Callable[[], datetime], optional): Callable that gets the current time as a datetime.datetime object (used by Console.log), + or None for datetime.now. + get_time (Callable[[], time], optional): Callable that gets the current time in seconds, default uses time.monotonic. + """ + + _environ: Mapping[str, str] = os.environ + + def __init__( + self, + *, + color_system: Optional[ + Literal["auto", "standard", "256", "truecolor", "windows"] + ] = "auto", + force_terminal: Optional[bool] = None, + force_jupyter: Optional[bool] = None, + force_interactive: Optional[bool] = None, + soft_wrap: bool = False, + theme: Optional[Theme] = None, + stderr: bool = False, + file: Optional[IO[str]] = None, + quiet: bool = False, + width: Optional[int] = None, + height: Optional[int] = None, + style: Optional[StyleType] = None, + no_color: Optional[bool] = None, + tab_size: int = 8, + record: bool = False, + markup: bool = True, + emoji: bool = True, + emoji_variant: Optional[EmojiVariant] = None, + highlight: bool = True, + log_time: bool = True, + log_path: bool = True, + log_time_format: Union[str, FormatTimeCallable] = "[%X]", + highlighter: Optional["HighlighterType"] = ReprHighlighter(), + legacy_windows: Optional[bool] = None, + safe_box: bool = True, + get_datetime: Optional[Callable[[], datetime]] = None, + get_time: Optional[Callable[[], float]] = None, + _environ: Optional[Mapping[str, str]] = None, + ): + # Copy of os.environ allows us to replace it for testing + if _environ is not None: + self._environ = _environ + + self.is_jupyter = _is_jupyter() if force_jupyter is None else force_jupyter + if self.is_jupyter: + if width is None: + jupyter_columns = self._environ.get("JUPYTER_COLUMNS") + if jupyter_columns is not None and jupyter_columns.isdigit(): + width = int(jupyter_columns) + else: + width = JUPYTER_DEFAULT_COLUMNS + if height is None: + jupyter_lines = self._environ.get("JUPYTER_LINES") + if jupyter_lines is not None and jupyter_lines.isdigit(): + height = int(jupyter_lines) + else: + height = JUPYTER_DEFAULT_LINES + + self.tab_size = tab_size + self.record = record + self._markup = markup + self._emoji = emoji + self._emoji_variant: Optional[EmojiVariant] = emoji_variant + self._highlight = highlight + self.legacy_windows: bool = ( + (detect_legacy_windows() and not self.is_jupyter) + if legacy_windows is None + else legacy_windows + ) + + if width is None: + columns = self._environ.get("COLUMNS") + if columns is not None and columns.isdigit(): + width = int(columns) - self.legacy_windows + if height is None: + lines = self._environ.get("LINES") + if lines is not None and lines.isdigit(): + height = int(lines) + + self.soft_wrap = soft_wrap + self._width = width + self._height = height + + self._color_system: Optional[ColorSystem] + + self._force_terminal = None + if force_terminal is not None: + self._force_terminal = force_terminal + + self._file = file + self.quiet = quiet + self.stderr = stderr + + if color_system is None: + self._color_system = None + elif color_system == "auto": + self._color_system = self._detect_color_system() + else: + self._color_system = COLOR_SYSTEMS[color_system] + + self._lock = threading.RLock() + self._log_render = LogRender( + show_time=log_time, + show_path=log_path, + time_format=log_time_format, + ) + self.highlighter: HighlighterType = highlighter or _null_highlighter + self.safe_box = safe_box + self.get_datetime = get_datetime or datetime.now + self.get_time = get_time or monotonic + self.style = style + self.no_color = ( + no_color if no_color is not None else "NO_COLOR" in self._environ + ) + self.is_interactive = ( + (self.is_terminal and not self.is_dumb_terminal) + if force_interactive is None + else force_interactive + ) + + self._record_buffer_lock = threading.RLock() + self._thread_locals = ConsoleThreadLocals( + theme_stack=ThemeStack(themes.DEFAULT if theme is None else theme) + ) + self._record_buffer: List[Segment] = [] + self._render_hooks: List[RenderHook] = [] + self._live: Optional["Live"] = None + self._is_alt_screen = False + + def __repr__(self) -> str: + return f"" + + @property + def file(self) -> IO[str]: + """Get the file object to write to.""" + file = self._file or (sys.stderr if self.stderr else sys.stdout) + file = getattr(file, "rich_proxied_file", file) + if file is None: + file = NULL_FILE + return file + + @file.setter + def file(self, new_file: IO[str]) -> None: + """Set a new file object.""" + self._file = new_file + + @property + def _buffer(self) -> List[Segment]: + """Get a thread local buffer.""" + return self._thread_locals.buffer + + @property + def _buffer_index(self) -> int: + """Get a thread local buffer.""" + return self._thread_locals.buffer_index + + @_buffer_index.setter + def _buffer_index(self, value: int) -> None: + self._thread_locals.buffer_index = value + + @property + def _theme_stack(self) -> ThemeStack: + """Get the thread local theme stack.""" + return self._thread_locals.theme_stack + + def _detect_color_system(self) -> Optional[ColorSystem]: + """Detect color system from env vars.""" + if self.is_jupyter: + return ColorSystem.TRUECOLOR + if not self.is_terminal or self.is_dumb_terminal: + return None + if WINDOWS: # pragma: no cover + if self.legacy_windows: # pragma: no cover + return ColorSystem.WINDOWS + windows_console_features = get_windows_console_features() + return ( + ColorSystem.TRUECOLOR + if windows_console_features.truecolor + else ColorSystem.EIGHT_BIT + ) + else: + color_term = self._environ.get("COLORTERM", "").strip().lower() + if color_term in ("truecolor", "24bit"): + return ColorSystem.TRUECOLOR + term = self._environ.get("TERM", "").strip().lower() + _term_name, _hyphen, colors = term.rpartition("-") + color_system = _TERM_COLORS.get(colors, ColorSystem.STANDARD) + return color_system + + def _enter_buffer(self) -> None: + """Enter in to a buffer context, and buffer all output.""" + self._buffer_index += 1 + + def _exit_buffer(self) -> None: + """Leave buffer context, and render content if required.""" + self._buffer_index -= 1 + self._check_buffer() + + def set_live(self, live: "Live") -> None: + """Set Live instance. Used by Live context manager. + + Args: + live (Live): Live instance using this Console. + + Raises: + errors.LiveError: If this Console has a Live context currently active. + """ + with self._lock: + if self._live is not None: + raise errors.LiveError("Only one live display may be active at once") + self._live = live + + def clear_live(self) -> None: + """Clear the Live instance.""" + with self._lock: + self._live = None + + def push_render_hook(self, hook: RenderHook) -> None: + """Add a new render hook to the stack. + + Args: + hook (RenderHook): Render hook instance. + """ + with self._lock: + self._render_hooks.append(hook) + + def pop_render_hook(self) -> None: + """Pop the last renderhook from the stack.""" + with self._lock: + self._render_hooks.pop() + + def __enter__(self) -> "Console": + """Own context manager to enter buffer context.""" + self._enter_buffer() + return self + + def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None: + """Exit buffer context.""" + self._exit_buffer() + + def begin_capture(self) -> None: + """Begin capturing console output. Call :meth:`end_capture` to exit capture mode and return output.""" + self._enter_buffer() + + def end_capture(self) -> str: + """End capture mode and return captured string. + + Returns: + str: Console output. + """ + render_result = self._render_buffer(self._buffer) + del self._buffer[:] + self._exit_buffer() + return render_result + + def push_theme(self, theme: Theme, *, inherit: bool = True) -> None: + """Push a new theme on to the top of the stack, replacing the styles from the previous theme. + Generally speaking, you should call :meth:`~rich.console.Console.use_theme` to get a context manager, rather + than calling this method directly. + + Args: + theme (Theme): A theme instance. + inherit (bool, optional): Inherit existing styles. Defaults to True. + """ + self._theme_stack.push_theme(theme, inherit=inherit) + + def pop_theme(self) -> None: + """Remove theme from top of stack, restoring previous theme.""" + self._theme_stack.pop_theme() + + def use_theme(self, theme: Theme, *, inherit: bool = True) -> ThemeContext: + """Use a different theme for the duration of the context manager. + + Args: + theme (Theme): Theme instance to user. + inherit (bool, optional): Inherit existing console styles. Defaults to True. + + Returns: + ThemeContext: [description] + """ + return ThemeContext(self, theme, inherit) + + @property + def color_system(self) -> Optional[str]: + """Get color system string. + + Returns: + Optional[str]: "standard", "256" or "truecolor". + """ + + if self._color_system is not None: + return _COLOR_SYSTEMS_NAMES[self._color_system] + else: + return None + + @property + def encoding(self) -> str: + """Get the encoding of the console file, e.g. ``"utf-8"``. + + Returns: + str: A standard encoding string. + """ + return (getattr(self.file, "encoding", "utf-8") or "utf-8").lower() + + @property + def is_terminal(self) -> bool: + """Check if the console is writing to a terminal. + + Returns: + bool: True if the console writing to a device capable of + understanding terminal codes, otherwise False. + """ + if self._force_terminal is not None: + return self._force_terminal + + if hasattr(sys.stdin, "__module__") and sys.stdin.__module__.startswith( + "idlelib" + ): + # Return False for Idle which claims to be a tty but can't handle ansi codes + return False + + if self.is_jupyter: + # return False for Jupyter, which may have FORCE_COLOR set + return False + + # If FORCE_COLOR env var has any value at all, we assume a terminal. + force_color = self._environ.get("FORCE_COLOR") + if force_color is not None: + self._force_terminal = True + return True + + isatty: Optional[Callable[[], bool]] = getattr(self.file, "isatty", None) + try: + return False if isatty is None else isatty() + except ValueError: + # in some situation (at the end of a pytest run for example) isatty() can raise + # ValueError: I/O operation on closed file + # return False because we aren't in a terminal anymore + return False + + @property + def is_dumb_terminal(self) -> bool: + """Detect dumb terminal. + + Returns: + bool: True if writing to a dumb terminal, otherwise False. + + """ + _term = self._environ.get("TERM", "") + is_dumb = _term.lower() in ("dumb", "unknown") + return self.is_terminal and is_dumb + + @property + def options(self) -> ConsoleOptions: + """Get default console options.""" + return ConsoleOptions( + max_height=self.size.height, + size=self.size, + legacy_windows=self.legacy_windows, + min_width=1, + max_width=self.width, + encoding=self.encoding, + is_terminal=self.is_terminal, + ) + + @property + def size(self) -> ConsoleDimensions: + """Get the size of the console. + + Returns: + ConsoleDimensions: A named tuple containing the dimensions. + """ + + if self._width is not None and self._height is not None: + return ConsoleDimensions(self._width - self.legacy_windows, self._height) + + if self.is_dumb_terminal: + return ConsoleDimensions(80, 25) + + width: Optional[int] = None + height: Optional[int] = None + + if WINDOWS: # pragma: no cover + try: + width, height = os.get_terminal_size() + except (AttributeError, ValueError, OSError): # Probably not a terminal + pass + else: + for file_descriptor in _STD_STREAMS: + try: + width, height = os.get_terminal_size(file_descriptor) + except (AttributeError, ValueError, OSError): + pass + else: + break + + columns = self._environ.get("COLUMNS") + if columns is not None and columns.isdigit(): + width = int(columns) + lines = self._environ.get("LINES") + if lines is not None and lines.isdigit(): + height = int(lines) + + # get_terminal_size can report 0, 0 if run from pseudo-terminal + width = width or 80 + height = height or 25 + return ConsoleDimensions( + width - self.legacy_windows if self._width is None else self._width, + height if self._height is None else self._height, + ) + + @size.setter + def size(self, new_size: Tuple[int, int]) -> None: + """Set a new size for the terminal. + + Args: + new_size (Tuple[int, int]): New width and height. + """ + width, height = new_size + self._width = width + self._height = height + + @property + def width(self) -> int: + """Get the width of the console. + + Returns: + int: The width (in characters) of the console. + """ + return self.size.width + + @width.setter + def width(self, width: int) -> None: + """Set width. + + Args: + width (int): New width. + """ + self._width = width + + @property + def height(self) -> int: + """Get the height of the console. + + Returns: + int: The height (in lines) of the console. + """ + return self.size.height + + @height.setter + def height(self, height: int) -> None: + """Set height. + + Args: + height (int): new height. + """ + self._height = height + + def bell(self) -> None: + """Play a 'bell' sound (if supported by the terminal).""" + self.control(Control.bell()) + + def capture(self) -> Capture: + """A context manager to *capture* the result of print() or log() in a string, + rather than writing it to the console. + + Example: + >>> from rich.console import Console + >>> console = Console() + >>> with console.capture() as capture: + ... console.print("[bold magenta]Hello World[/]") + >>> print(capture.get()) + + Returns: + Capture: Context manager with disables writing to the terminal. + """ + capture = Capture(self) + return capture + + def pager( + self, pager: Optional[Pager] = None, styles: bool = False, links: bool = False + ) -> PagerContext: + """A context manager to display anything printed within a "pager". The pager application + is defined by the system and will typically support at least pressing a key to scroll. + + Args: + pager (Pager, optional): A pager object, or None to use :class:`~rich.pager.SystemPager`. Defaults to None. + styles (bool, optional): Show styles in pager. Defaults to False. + links (bool, optional): Show links in pager. Defaults to False. + + Example: + >>> from rich.console import Console + >>> from rich.__main__ import make_test_card + >>> console = Console() + >>> with console.pager(): + console.print(make_test_card()) + + Returns: + PagerContext: A context manager. + """ + return PagerContext(self, pager=pager, styles=styles, links=links) + + def line(self, count: int = 1) -> None: + """Write new line(s). + + Args: + count (int, optional): Number of new lines. Defaults to 1. + """ + + assert count >= 0, "count must be >= 0" + self.print(NewLine(count)) + + def clear(self, home: bool = True) -> None: + """Clear the screen. + + Args: + home (bool, optional): Also move the cursor to 'home' position. Defaults to True. + """ + if home: + self.control(Control.clear(), Control.home()) + else: + self.control(Control.clear()) + + def status( + self, + status: RenderableType, + *, + spinner: str = "dots", + spinner_style: StyleType = "status.spinner", + speed: float = 1.0, + refresh_per_second: float = 12.5, + ) -> "Status": + """Display a status and spinner. + + Args: + status (RenderableType): A status renderable (str or Text typically). + spinner (str, optional): Name of spinner animation (see python -m rich.spinner). Defaults to "dots". + spinner_style (StyleType, optional): Style of spinner. Defaults to "status.spinner". + speed (float, optional): Speed factor for spinner animation. Defaults to 1.0. + refresh_per_second (float, optional): Number of refreshes per second. Defaults to 12.5. + + Returns: + Status: A Status object that may be used as a context manager. + """ + from .status import Status + + status_renderable = Status( + status, + console=self, + spinner=spinner, + spinner_style=spinner_style, + speed=speed, + refresh_per_second=refresh_per_second, + ) + return status_renderable + + def show_cursor(self, show: bool = True) -> bool: + """Show or hide the cursor. + + Args: + show (bool, optional): Set visibility of the cursor. + """ + if self.is_terminal: + self.control(Control.show_cursor(show)) + return True + return False + + def set_alt_screen(self, enable: bool = True) -> bool: + """Enables alternative screen mode. + + Note, if you enable this mode, you should ensure that is disabled before + the application exits. See :meth:`~rich.Console.screen` for a context manager + that handles this for you. + + Args: + enable (bool, optional): Enable (True) or disable (False) alternate screen. Defaults to True. + + Returns: + bool: True if the control codes were written. + + """ + changed = False + if self.is_terminal and not self.legacy_windows: + self.control(Control.alt_screen(enable)) + changed = True + self._is_alt_screen = enable + return changed + + @property + def is_alt_screen(self) -> bool: + """Check if the alt screen was enabled. + + Returns: + bool: True if the alt screen was enabled, otherwise False. + """ + return self._is_alt_screen + + def set_window_title(self, title: str) -> bool: + """Set the title of the console terminal window. + + Warning: There is no means within Rich of "resetting" the window title to its + previous value, meaning the title you set will persist even after your application + exits. + + ``fish`` shell resets the window title before and after each command by default, + negating this issue. Windows Terminal and command prompt will also reset the title for you. + Most other shells and terminals, however, do not do this. + + Some terminals may require configuration changes before you can set the title. + Some terminals may not support setting the title at all. + + Other software (including the terminal itself, the shell, custom prompts, plugins, etc.) + may also set the terminal window title. This could result in whatever value you write + using this method being overwritten. + + Args: + title (str): The new title of the terminal window. + + Returns: + bool: True if the control code to change the terminal title was + written, otherwise False. Note that a return value of True + does not guarantee that the window title has actually changed, + since the feature may be unsupported/disabled in some terminals. + """ + if self.is_terminal: + self.control(Control.title(title)) + return True + return False + + def screen( + self, hide_cursor: bool = True, style: Optional[StyleType] = None + ) -> "ScreenContext": + """Context manager to enable and disable 'alternative screen' mode. + + Args: + hide_cursor (bool, optional): Also hide the cursor. Defaults to False. + style (Style, optional): Optional style for screen. Defaults to None. + + Returns: + ~ScreenContext: Context which enables alternate screen on enter, and disables it on exit. + """ + return ScreenContext(self, hide_cursor=hide_cursor, style=style or "") + + def measure( + self, renderable: RenderableType, *, options: Optional[ConsoleOptions] = None + ) -> Measurement: + """Measure a renderable. Returns a :class:`~rich.measure.Measurement` object which contains + information regarding the number of characters required to print the renderable. + + Args: + renderable (RenderableType): Any renderable or string. + options (Optional[ConsoleOptions], optional): Options to use when measuring, or None + to use default options. Defaults to None. + + Returns: + Measurement: A measurement of the renderable. + """ + measurement = Measurement.get(self, options or self.options, renderable) + return measurement + + def render( + self, renderable: RenderableType, options: Optional[ConsoleOptions] = None + ) -> Iterable[Segment]: + """Render an object in to an iterable of `Segment` instances. + + This method contains the logic for rendering objects with the console protocol. + You are unlikely to need to use it directly, unless you are extending the library. + + Args: + renderable (RenderableType): An object supporting the console protocol, or + an object that may be converted to a string. + options (ConsoleOptions, optional): An options object, or None to use self.options. Defaults to None. + + Returns: + Iterable[Segment]: An iterable of segments that may be rendered. + """ + + _options = options or self.options + if _options.max_width < 1: + # No space to render anything. This prevents potential recursion errors. + return + render_iterable: RenderResult + + renderable = rich_cast(renderable) + if hasattr(renderable, "__rich_console__") and not isclass(renderable): + render_iterable = renderable.__rich_console__(self, _options) # type: ignore[union-attr] + elif isinstance(renderable, str): + text_renderable = self.render_str( + renderable, highlight=_options.highlight, markup=_options.markup + ) + render_iterable = text_renderable.__rich_console__(self, _options) + else: + raise errors.NotRenderableError( + f"Unable to render {renderable!r}; " + "A str, Segment or object with __rich_console__ method is required" + ) + + try: + iter_render = iter(render_iterable) + except TypeError: + raise errors.NotRenderableError( + f"object {render_iterable!r} is not renderable" + ) + _Segment = Segment + _options = _options.reset_height() + for render_output in iter_render: + if isinstance(render_output, _Segment): + yield render_output + else: + yield from self.render(render_output, _options) + + def render_lines( + self, + renderable: RenderableType, + options: Optional[ConsoleOptions] = None, + *, + style: Optional[Style] = None, + pad: bool = True, + new_lines: bool = False, + ) -> List[List[Segment]]: + """Render objects in to a list of lines. + + The output of render_lines is useful when further formatting of rendered console text + is required, such as the Panel class which draws a border around any renderable object. + + Args: + renderable (RenderableType): Any object renderable in the console. + options (Optional[ConsoleOptions], optional): Console options, or None to use self.options. Default to ``None``. + style (Style, optional): Optional style to apply to renderables. Defaults to ``None``. + pad (bool, optional): Pad lines shorter than render width. Defaults to ``True``. + new_lines (bool, optional): Include "\n" characters at end of lines. + + Returns: + List[List[Segment]]: A list of lines, where a line is a list of Segment objects. + """ + with self._lock: + render_options = options or self.options + _rendered = self.render(renderable, render_options) + if style: + _rendered = Segment.apply_style(_rendered, style) + + render_height = render_options.height + if render_height is not None: + render_height = max(0, render_height) + + lines = list( + islice( + Segment.split_and_crop_lines( + _rendered, + render_options.max_width, + include_new_lines=new_lines, + pad=pad, + style=style, + ), + None, + render_height, + ) + ) + if render_options.height is not None: + extra_lines = render_options.height - len(lines) + if extra_lines > 0: + pad_line = [ + [Segment(" " * render_options.max_width, style), Segment("\n")] + if new_lines + else [Segment(" " * render_options.max_width, style)] + ] + lines.extend(pad_line * extra_lines) + + return lines + + def render_str( + self, + text: str, + *, + style: Union[str, Style] = "", + justify: Optional[JustifyMethod] = None, + overflow: Optional[OverflowMethod] = None, + emoji: Optional[bool] = None, + markup: Optional[bool] = None, + highlight: Optional[bool] = None, + highlighter: Optional[HighlighterType] = None, + ) -> "Text": + """Convert a string to a Text instance. This is called automatically if + you print or log a string. + + Args: + text (str): Text to render. + style (Union[str, Style], optional): Style to apply to rendered text. + justify (str, optional): Justify method: "default", "left", "center", "full", or "right". Defaults to ``None``. + overflow (str, optional): Overflow method: "crop", "fold", or "ellipsis". Defaults to ``None``. + emoji (Optional[bool], optional): Enable emoji, or ``None`` to use Console default. + markup (Optional[bool], optional): Enable markup, or ``None`` to use Console default. + highlight (Optional[bool], optional): Enable highlighting, or ``None`` to use Console default. + highlighter (HighlighterType, optional): Optional highlighter to apply. + Returns: + ConsoleRenderable: Renderable object. + + """ + emoji_enabled = emoji or (emoji is None and self._emoji) + markup_enabled = markup or (markup is None and self._markup) + highlight_enabled = highlight or (highlight is None and self._highlight) + + if markup_enabled: + rich_text = render_markup( + text, + style=style, + emoji=emoji_enabled, + emoji_variant=self._emoji_variant, + ) + rich_text.justify = justify + rich_text.overflow = overflow + else: + rich_text = Text( + _emoji_replace(text, default_variant=self._emoji_variant) + if emoji_enabled + else text, + justify=justify, + overflow=overflow, + style=style, + ) + + _highlighter = (highlighter or self.highlighter) if highlight_enabled else None + if _highlighter is not None: + highlight_text = _highlighter(str(rich_text)) + highlight_text.copy_styles(rich_text) + return highlight_text + + return rich_text + + def get_style( + self, name: Union[str, Style], *, default: Optional[Union[Style, str]] = None + ) -> Style: + """Get a Style instance by its theme name or parse a definition. + + Args: + name (str): The name of a style or a style definition. + + Returns: + Style: A Style object. + + Raises: + MissingStyle: If no style could be parsed from name. + + """ + if isinstance(name, Style): + return name + + try: + style = self._theme_stack.get(name) + if style is None: + style = Style.parse(name) + return style.copy() if style.link else style + except errors.StyleSyntaxError as error: + if default is not None: + return self.get_style(default) + raise errors.MissingStyle( + f"Failed to get style {name!r}; {error}" + ) from None + + def _collect_renderables( + self, + objects: Iterable[Any], + sep: str, + end: str, + *, + justify: Optional[JustifyMethod] = None, + emoji: Optional[bool] = None, + markup: Optional[bool] = None, + highlight: Optional[bool] = None, + ) -> List[ConsoleRenderable]: + """Combine a number of renderables and text into one renderable. + + Args: + objects (Iterable[Any]): Anything that Rich can render. + sep (str): String to write between print data. + end (str): String to write at end of print data. + justify (str, optional): One of "left", "right", "center", or "full". Defaults to ``None``. + emoji (Optional[bool], optional): Enable emoji code, or ``None`` to use console default. + markup (Optional[bool], optional): Enable markup, or ``None`` to use console default. + highlight (Optional[bool], optional): Enable automatic highlighting, or ``None`` to use console default. + + Returns: + List[ConsoleRenderable]: A list of things to render. + """ + renderables: List[ConsoleRenderable] = [] + _append = renderables.append + text: List[Text] = [] + append_text = text.append + + append = _append + if justify in ("left", "center", "right"): + + def align_append(renderable: RenderableType) -> None: + _append(Align(renderable, cast(AlignMethod, justify))) + + append = align_append + + _highlighter: HighlighterType = _null_highlighter + if highlight or (highlight is None and self._highlight): + _highlighter = self.highlighter + + def check_text() -> None: + if text: + sep_text = Text(sep, justify=justify, end=end) + append(sep_text.join(text)) + text.clear() + + for renderable in objects: + renderable = rich_cast(renderable) + if isinstance(renderable, str): + append_text( + self.render_str( + renderable, emoji=emoji, markup=markup, highlighter=_highlighter + ) + ) + elif isinstance(renderable, Text): + append_text(renderable) + elif isinstance(renderable, ConsoleRenderable): + check_text() + append(renderable) + elif is_expandable(renderable): + check_text() + append(Pretty(renderable, highlighter=_highlighter)) + else: + append_text(_highlighter(str(renderable))) + + check_text() + + if self.style is not None: + style = self.get_style(self.style) + renderables = [Styled(renderable, style) for renderable in renderables] + + return renderables + + def rule( + self, + title: TextType = "", + *, + characters: str = "─", + style: Union[str, Style] = "rule.line", + align: AlignMethod = "center", + ) -> None: + """Draw a line with optional centered title. + + Args: + title (str, optional): Text to render over the rule. Defaults to "". + characters (str, optional): Character(s) to form the line. Defaults to "─". + style (str, optional): Style of line. Defaults to "rule.line". + align (str, optional): How to align the title, one of "left", "center", or "right". Defaults to "center". + """ + from .rule import Rule + + rule = Rule(title=title, characters=characters, style=style, align=align) + self.print(rule) + + def control(self, *control: Control) -> None: + """Insert non-printing control codes. + + Args: + control_codes (str): Control codes, such as those that may move the cursor. + """ + if not self.is_dumb_terminal: + with self: + self._buffer.extend(_control.segment for _control in control) + + def out( + self, + *objects: Any, + sep: str = " ", + end: str = "\n", + style: Optional[Union[str, Style]] = None, + highlight: Optional[bool] = None, + ) -> None: + """Output to the terminal. This is a low-level way of writing to the terminal which unlike + :meth:`~rich.console.Console.print` won't pretty print, wrap text, or apply markup, but will + optionally apply highlighting and a basic style. + + Args: + sep (str, optional): String to write between print data. Defaults to " ". + end (str, optional): String to write at end of print data. Defaults to "\\\\n". + style (Union[str, Style], optional): A style to apply to output. Defaults to None. + highlight (Optional[bool], optional): Enable automatic highlighting, or ``None`` to use + console default. Defaults to ``None``. + """ + raw_output: str = sep.join(str(_object) for _object in objects) + self.print( + raw_output, + style=style, + highlight=highlight, + emoji=False, + markup=False, + no_wrap=True, + overflow="ignore", + crop=False, + end=end, + ) + + def print( + self, + *objects: Any, + sep: str = " ", + end: str = "\n", + style: Optional[Union[str, Style]] = None, + justify: Optional[JustifyMethod] = None, + overflow: Optional[OverflowMethod] = None, + no_wrap: Optional[bool] = None, + emoji: Optional[bool] = None, + markup: Optional[bool] = None, + highlight: Optional[bool] = None, + width: Optional[int] = None, + height: Optional[int] = None, + crop: bool = True, + soft_wrap: Optional[bool] = None, + new_line_start: bool = False, + ) -> None: + """Print to the console. + + Args: + objects (positional args): Objects to log to the terminal. + sep (str, optional): String to write between print data. Defaults to " ". + end (str, optional): String to write at end of print data. Defaults to "\\\\n". + style (Union[str, Style], optional): A style to apply to output. Defaults to None. + justify (str, optional): Justify method: "default", "left", "right", "center", or "full". Defaults to ``None``. + overflow (str, optional): Overflow method: "ignore", "crop", "fold", or "ellipsis". Defaults to None. + no_wrap (Optional[bool], optional): Disable word wrapping. Defaults to None. + emoji (Optional[bool], optional): Enable emoji code, or ``None`` to use console default. Defaults to ``None``. + markup (Optional[bool], optional): Enable markup, or ``None`` to use console default. Defaults to ``None``. + highlight (Optional[bool], optional): Enable automatic highlighting, or ``None`` to use console default. Defaults to ``None``. + width (Optional[int], optional): Width of output, or ``None`` to auto-detect. Defaults to ``None``. + crop (Optional[bool], optional): Crop output to width of terminal. Defaults to True. + soft_wrap (bool, optional): Enable soft wrap mode which disables word wrapping and cropping of text or ``None`` for + Console default. Defaults to ``None``. + new_line_start (bool, False): Insert a new line at the start if the output contains more than one line. Defaults to ``False``. + """ + if not objects: + objects = (NewLine(),) + + if soft_wrap is None: + soft_wrap = self.soft_wrap + if soft_wrap: + if no_wrap is None: + no_wrap = True + if overflow is None: + overflow = "ignore" + crop = False + render_hooks = self._render_hooks[:] + with self: + renderables = self._collect_renderables( + objects, + sep, + end, + justify=justify, + emoji=emoji, + markup=markup, + highlight=highlight, + ) + for hook in render_hooks: + renderables = hook.process_renderables(renderables) + render_options = self.options.update( + justify=justify, + overflow=overflow, + width=min(width, self.width) if width is not None else NO_CHANGE, + height=height, + no_wrap=no_wrap, + markup=markup, + highlight=highlight, + ) + + new_segments: List[Segment] = [] + extend = new_segments.extend + render = self.render + if style is None: + for renderable in renderables: + extend(render(renderable, render_options)) + else: + for renderable in renderables: + extend( + Segment.apply_style( + render(renderable, render_options), self.get_style(style) + ) + ) + if new_line_start: + if ( + len("".join(segment.text for segment in new_segments).splitlines()) + > 1 + ): + new_segments.insert(0, Segment.line()) + if crop: + buffer_extend = self._buffer.extend + for line in Segment.split_and_crop_lines( + new_segments, self.width, pad=False + ): + buffer_extend(line) + else: + self._buffer.extend(new_segments) + + def print_json( + self, + json: Optional[str] = None, + *, + data: Any = None, + indent: Union[None, int, str] = 2, + highlight: bool = True, + skip_keys: bool = False, + ensure_ascii: bool = False, + check_circular: bool = True, + allow_nan: bool = True, + default: Optional[Callable[[Any], Any]] = None, + sort_keys: bool = False, + ) -> None: + """Pretty prints JSON. Output will be valid JSON. + + Args: + json (Optional[str]): A string containing JSON. + data (Any): If json is not supplied, then encode this data. + indent (Union[None, int, str], optional): Number of spaces to indent. Defaults to 2. + highlight (bool, optional): Enable highlighting of output: Defaults to True. + skip_keys (bool, optional): Skip keys not of a basic type. Defaults to False. + ensure_ascii (bool, optional): Escape all non-ascii characters. Defaults to False. + check_circular (bool, optional): Check for circular references. Defaults to True. + allow_nan (bool, optional): Allow NaN and Infinity values. Defaults to True. + default (Callable, optional): A callable that converts values that can not be encoded + in to something that can be JSON encoded. Defaults to None. + sort_keys (bool, optional): Sort dictionary keys. Defaults to False. + """ + from pip._vendor.rich.json import JSON + + if json is None: + json_renderable = JSON.from_data( + data, + indent=indent, + highlight=highlight, + skip_keys=skip_keys, + ensure_ascii=ensure_ascii, + check_circular=check_circular, + allow_nan=allow_nan, + default=default, + sort_keys=sort_keys, + ) + else: + if not isinstance(json, str): + raise TypeError( + f"json must be str. Did you mean print_json(data={json!r}) ?" + ) + json_renderable = JSON( + json, + indent=indent, + highlight=highlight, + skip_keys=skip_keys, + ensure_ascii=ensure_ascii, + check_circular=check_circular, + allow_nan=allow_nan, + default=default, + sort_keys=sort_keys, + ) + self.print(json_renderable, soft_wrap=True) + + def update_screen( + self, + renderable: RenderableType, + *, + region: Optional[Region] = None, + options: Optional[ConsoleOptions] = None, + ) -> None: + """Update the screen at a given offset. + + Args: + renderable (RenderableType): A Rich renderable. + region (Region, optional): Region of screen to update, or None for entire screen. Defaults to None. + x (int, optional): x offset. Defaults to 0. + y (int, optional): y offset. Defaults to 0. + + Raises: + errors.NoAltScreen: If the Console isn't in alt screen mode. + + """ + if not self.is_alt_screen: + raise errors.NoAltScreen("Alt screen must be enabled to call update_screen") + render_options = options or self.options + if region is None: + x = y = 0 + render_options = render_options.update_dimensions( + render_options.max_width, render_options.height or self.height + ) + else: + x, y, width, height = region + render_options = render_options.update_dimensions(width, height) + + lines = self.render_lines(renderable, options=render_options) + self.update_screen_lines(lines, x, y) + + def update_screen_lines( + self, lines: List[List[Segment]], x: int = 0, y: int = 0 + ) -> None: + """Update lines of the screen at a given offset. + + Args: + lines (List[List[Segment]]): Rendered lines (as produced by :meth:`~rich.Console.render_lines`). + x (int, optional): x offset (column no). Defaults to 0. + y (int, optional): y offset (column no). Defaults to 0. + + Raises: + errors.NoAltScreen: If the Console isn't in alt screen mode. + """ + if not self.is_alt_screen: + raise errors.NoAltScreen("Alt screen must be enabled to call update_screen") + screen_update = ScreenUpdate(lines, x, y) + segments = self.render(screen_update) + self._buffer.extend(segments) + self._check_buffer() + + def print_exception( + self, + *, + width: Optional[int] = 100, + extra_lines: int = 3, + theme: Optional[str] = None, + word_wrap: bool = False, + show_locals: bool = False, + suppress: Iterable[Union[str, ModuleType]] = (), + max_frames: int = 100, + ) -> None: + """Prints a rich render of the last exception and traceback. + + Args: + width (Optional[int], optional): Number of characters used to render code. Defaults to 100. + extra_lines (int, optional): Additional lines of code to render. Defaults to 3. + theme (str, optional): Override pygments theme used in traceback + word_wrap (bool, optional): Enable word wrapping of long lines. Defaults to False. + show_locals (bool, optional): Enable display of local variables. Defaults to False. + suppress (Iterable[Union[str, ModuleType]]): Optional sequence of modules or paths to exclude from traceback. + max_frames (int): Maximum number of frames to show in a traceback, 0 for no maximum. Defaults to 100. + """ + from .traceback import Traceback + + traceback = Traceback( + width=width, + extra_lines=extra_lines, + theme=theme, + word_wrap=word_wrap, + show_locals=show_locals, + suppress=suppress, + max_frames=max_frames, + ) + self.print(traceback) + + @staticmethod + def _caller_frame_info( + offset: int, + currentframe: Callable[[], Optional[FrameType]] = inspect.currentframe, + ) -> Tuple[str, int, Dict[str, Any]]: + """Get caller frame information. + + Args: + offset (int): the caller offset within the current frame stack. + currentframe (Callable[[], Optional[FrameType]], optional): the callable to use to + retrieve the current frame. Defaults to ``inspect.currentframe``. + + Returns: + Tuple[str, int, Dict[str, Any]]: A tuple containing the filename, the line number and + the dictionary of local variables associated with the caller frame. + + Raises: + RuntimeError: If the stack offset is invalid. + """ + # Ignore the frame of this local helper + offset += 1 + + frame = currentframe() + if frame is not None: + # Use the faster currentframe where implemented + while offset and frame is not None: + frame = frame.f_back + offset -= 1 + assert frame is not None + return frame.f_code.co_filename, frame.f_lineno, frame.f_locals + else: + # Fallback to the slower stack + frame_info = inspect.stack()[offset] + return frame_info.filename, frame_info.lineno, frame_info.frame.f_locals + + def log( + self, + *objects: Any, + sep: str = " ", + end: str = "\n", + style: Optional[Union[str, Style]] = None, + justify: Optional[JustifyMethod] = None, + emoji: Optional[bool] = None, + markup: Optional[bool] = None, + highlight: Optional[bool] = None, + log_locals: bool = False, + _stack_offset: int = 1, + ) -> None: + """Log rich content to the terminal. + + Args: + objects (positional args): Objects to log to the terminal. + sep (str, optional): String to write between print data. Defaults to " ". + end (str, optional): String to write at end of print data. Defaults to "\\\\n". + style (Union[str, Style], optional): A style to apply to output. Defaults to None. + justify (str, optional): One of "left", "right", "center", or "full". Defaults to ``None``. + emoji (Optional[bool], optional): Enable emoji code, or ``None`` to use console default. Defaults to None. + markup (Optional[bool], optional): Enable markup, or ``None`` to use console default. Defaults to None. + highlight (Optional[bool], optional): Enable automatic highlighting, or ``None`` to use console default. Defaults to None. + log_locals (bool, optional): Boolean to enable logging of locals where ``log()`` + was called. Defaults to False. + _stack_offset (int, optional): Offset of caller from end of call stack. Defaults to 1. + """ + if not objects: + objects = (NewLine(),) + + render_hooks = self._render_hooks[:] + + with self: + renderables = self._collect_renderables( + objects, + sep, + end, + justify=justify, + emoji=emoji, + markup=markup, + highlight=highlight, + ) + if style is not None: + renderables = [Styled(renderable, style) for renderable in renderables] + + filename, line_no, locals = self._caller_frame_info(_stack_offset) + link_path = None if filename.startswith("<") else os.path.abspath(filename) + path = filename.rpartition(os.sep)[-1] + if log_locals: + locals_map = { + key: value + for key, value in locals.items() + if not key.startswith("__") + } + renderables.append(render_scope(locals_map, title="[i]locals")) + + renderables = [ + self._log_render( + self, + renderables, + log_time=self.get_datetime(), + path=path, + line_no=line_no, + link_path=link_path, + ) + ] + for hook in render_hooks: + renderables = hook.process_renderables(renderables) + new_segments: List[Segment] = [] + extend = new_segments.extend + render = self.render + render_options = self.options + for renderable in renderables: + extend(render(renderable, render_options)) + buffer_extend = self._buffer.extend + for line in Segment.split_and_crop_lines( + new_segments, self.width, pad=False + ): + buffer_extend(line) + + def _check_buffer(self) -> None: + """Check if the buffer may be rendered. Render it if it can (e.g. Console.quiet is False) + Rendering is supported on Windows, Unix and Jupyter environments. For + legacy Windows consoles, the win32 API is called directly. + This method will also record what it renders if recording is enabled via Console.record. + """ + if self.quiet: + del self._buffer[:] + return + with self._lock: + if self.record: + with self._record_buffer_lock: + self._record_buffer.extend(self._buffer[:]) + + if self._buffer_index == 0: + if self.is_jupyter: # pragma: no cover + from .jupyter import display + + display(self._buffer, self._render_buffer(self._buffer[:])) + del self._buffer[:] + else: + if WINDOWS: + use_legacy_windows_render = False + if self.legacy_windows: + fileno = get_fileno(self.file) + if fileno is not None: + use_legacy_windows_render = ( + fileno in _STD_STREAMS_OUTPUT + ) + + if use_legacy_windows_render: + from pip._vendor.rich._win32_console import LegacyWindowsTerm + from pip._vendor.rich._windows_renderer import legacy_windows_render + + buffer = self._buffer[:] + if self.no_color and self._color_system: + buffer = list(Segment.remove_color(buffer)) + + legacy_windows_render(buffer, LegacyWindowsTerm(self.file)) + else: + # Either a non-std stream on legacy Windows, or modern Windows. + text = self._render_buffer(self._buffer[:]) + # https://bugs.python.org/issue37871 + # https://github.com/python/cpython/issues/82052 + # We need to avoid writing more than 32Kb in a single write, due to the above bug + write = self.file.write + # Worse case scenario, every character is 4 bytes of utf-8 + MAX_WRITE = 32 * 1024 // 4 + try: + if len(text) <= MAX_WRITE: + write(text) + else: + batch: List[str] = [] + batch_append = batch.append + size = 0 + for line in text.splitlines(True): + if size + len(line) > MAX_WRITE and batch: + write("".join(batch)) + batch.clear() + size = 0 + batch_append(line) + size += len(line) + if batch: + write("".join(batch)) + batch.clear() + except UnicodeEncodeError as error: + error.reason = f"{error.reason}\n*** You may need to add PYTHONIOENCODING=utf-8 to your environment ***" + raise + else: + text = self._render_buffer(self._buffer[:]) + try: + self.file.write(text) + except UnicodeEncodeError as error: + error.reason = f"{error.reason}\n*** You may need to add PYTHONIOENCODING=utf-8 to your environment ***" + raise + + self.file.flush() + del self._buffer[:] + + def _render_buffer(self, buffer: Iterable[Segment]) -> str: + """Render buffered output, and clear buffer.""" + output: List[str] = [] + append = output.append + color_system = self._color_system + legacy_windows = self.legacy_windows + not_terminal = not self.is_terminal + if self.no_color and color_system: + buffer = Segment.remove_color(buffer) + for text, style, control in buffer: + if style: + append( + style.render( + text, + color_system=color_system, + legacy_windows=legacy_windows, + ) + ) + elif not (not_terminal and control): + append(text) + + rendered = "".join(output) + return rendered + + def input( + self, + prompt: TextType = "", + *, + markup: bool = True, + emoji: bool = True, + password: bool = False, + stream: Optional[TextIO] = None, + ) -> str: + """Displays a prompt and waits for input from the user. The prompt may contain color / style. + + It works in the same way as Python's builtin :func:`input` function and provides elaborate line editing and history features if Python's builtin :mod:`readline` module is previously loaded. + + Args: + prompt (Union[str, Text]): Text to render in the prompt. + markup (bool, optional): Enable console markup (requires a str prompt). Defaults to True. + emoji (bool, optional): Enable emoji (requires a str prompt). Defaults to True. + password: (bool, optional): Hide typed text. Defaults to False. + stream: (TextIO, optional): Optional file to read input from (rather than stdin). Defaults to None. + + Returns: + str: Text read from stdin. + """ + if prompt: + self.print(prompt, markup=markup, emoji=emoji, end="") + if password: + result = getpass("", stream=stream) + else: + if stream: + result = stream.readline() + else: + result = input() + return result + + def export_text(self, *, clear: bool = True, styles: bool = False) -> str: + """Generate text from console contents (requires record=True argument in constructor). + + Args: + clear (bool, optional): Clear record buffer after exporting. Defaults to ``True``. + styles (bool, optional): If ``True``, ansi escape codes will be included. ``False`` for plain text. + Defaults to ``False``. + + Returns: + str: String containing console contents. + + """ + assert ( + self.record + ), "To export console contents set record=True in the constructor or instance" + + with self._record_buffer_lock: + if styles: + text = "".join( + (style.render(text) if style else text) + for text, style, _ in self._record_buffer + ) + else: + text = "".join( + segment.text + for segment in self._record_buffer + if not segment.control + ) + if clear: + del self._record_buffer[:] + return text + + def save_text(self, path: str, *, clear: bool = True, styles: bool = False) -> None: + """Generate text from console and save to a given location (requires record=True argument in constructor). + + Args: + path (str): Path to write text files. + clear (bool, optional): Clear record buffer after exporting. Defaults to ``True``. + styles (bool, optional): If ``True``, ansi style codes will be included. ``False`` for plain text. + Defaults to ``False``. + + """ + text = self.export_text(clear=clear, styles=styles) + with open(path, "wt", encoding="utf-8") as write_file: + write_file.write(text) + + def export_html( + self, + *, + theme: Optional[TerminalTheme] = None, + clear: bool = True, + code_format: Optional[str] = None, + inline_styles: bool = False, + ) -> str: + """Generate HTML from console contents (requires record=True argument in constructor). + + Args: + theme (TerminalTheme, optional): TerminalTheme object containing console colors. + clear (bool, optional): Clear record buffer after exporting. Defaults to ``True``. + code_format (str, optional): Format string to render HTML. In addition to '{foreground}', + '{background}', and '{code}', should contain '{stylesheet}' if inline_styles is ``False``. + inline_styles (bool, optional): If ``True`` styles will be inlined in to spans, which makes files + larger but easier to cut and paste markup. If ``False``, styles will be embedded in a style tag. + Defaults to False. + + Returns: + str: String containing console contents as HTML. + """ + assert ( + self.record + ), "To export console contents set record=True in the constructor or instance" + fragments: List[str] = [] + append = fragments.append + _theme = theme or DEFAULT_TERMINAL_THEME + stylesheet = "" + + render_code_format = CONSOLE_HTML_FORMAT if code_format is None else code_format + + with self._record_buffer_lock: + if inline_styles: + for text, style, _ in Segment.filter_control( + Segment.simplify(self._record_buffer) + ): + text = escape(text) + if style: + rule = style.get_html_style(_theme) + if style.link: + text = f'
    {text}' + text = f'{text}' if rule else text + append(text) + else: + styles: Dict[str, int] = {} + for text, style, _ in Segment.filter_control( + Segment.simplify(self._record_buffer) + ): + text = escape(text) + if style: + rule = style.get_html_style(_theme) + style_number = styles.setdefault(rule, len(styles) + 1) + if style.link: + text = f'{text}' + else: + text = f'{text}' + append(text) + stylesheet_rules: List[str] = [] + stylesheet_append = stylesheet_rules.append + for style_rule, style_number in styles.items(): + if style_rule: + stylesheet_append(f".r{style_number} {{{style_rule}}}") + stylesheet = "\n".join(stylesheet_rules) + + rendered_code = render_code_format.format( + code="".join(fragments), + stylesheet=stylesheet, + foreground=_theme.foreground_color.hex, + background=_theme.background_color.hex, + ) + if clear: + del self._record_buffer[:] + return rendered_code + + def save_html( + self, + path: str, + *, + theme: Optional[TerminalTheme] = None, + clear: bool = True, + code_format: str = CONSOLE_HTML_FORMAT, + inline_styles: bool = False, + ) -> None: + """Generate HTML from console contents and write to a file (requires record=True argument in constructor). + + Args: + path (str): Path to write html file. + theme (TerminalTheme, optional): TerminalTheme object containing console colors. + clear (bool, optional): Clear record buffer after exporting. Defaults to ``True``. + code_format (str, optional): Format string to render HTML. In addition to '{foreground}', + '{background}', and '{code}', should contain '{stylesheet}' if inline_styles is ``False``. + inline_styles (bool, optional): If ``True`` styles will be inlined in to spans, which makes files + larger but easier to cut and paste markup. If ``False``, styles will be embedded in a style tag. + Defaults to False. + + """ + html = self.export_html( + theme=theme, + clear=clear, + code_format=code_format, + inline_styles=inline_styles, + ) + with open(path, "wt", encoding="utf-8") as write_file: + write_file.write(html) + + def export_svg( + self, + *, + title: str = "Rich", + theme: Optional[TerminalTheme] = None, + clear: bool = True, + code_format: str = CONSOLE_SVG_FORMAT, + font_aspect_ratio: float = 0.61, + unique_id: Optional[str] = None, + ) -> str: + """ + Generate an SVG from the console contents (requires record=True in Console constructor). + + Args: + title (str, optional): The title of the tab in the output image + theme (TerminalTheme, optional): The ``TerminalTheme`` object to use to style the terminal + clear (bool, optional): Clear record buffer after exporting. Defaults to ``True`` + code_format (str, optional): Format string used to generate the SVG. Rich will inject a number of variables + into the string in order to form the final SVG output. The default template used and the variables + injected by Rich can be found by inspecting the ``console.CONSOLE_SVG_FORMAT`` variable. + font_aspect_ratio (float, optional): The width to height ratio of the font used in the ``code_format`` + string. Defaults to 0.61, which is the width to height ratio of Fira Code (the default font). + If you aren't specifying a different font inside ``code_format``, you probably don't need this. + unique_id (str, optional): unique id that is used as the prefix for various elements (CSS styles, node + ids). If not set, this defaults to a computed value based on the recorded content. + """ + + from pip._vendor.rich.cells import cell_len + + style_cache: Dict[Style, str] = {} + + def get_svg_style(style: Style) -> str: + """Convert a Style to CSS rules for SVG.""" + if style in style_cache: + return style_cache[style] + css_rules = [] + color = ( + _theme.foreground_color + if (style.color is None or style.color.is_default) + else style.color.get_truecolor(_theme) + ) + bgcolor = ( + _theme.background_color + if (style.bgcolor is None or style.bgcolor.is_default) + else style.bgcolor.get_truecolor(_theme) + ) + if style.reverse: + color, bgcolor = bgcolor, color + if style.dim: + color = blend_rgb(color, bgcolor, 0.4) + css_rules.append(f"fill: {color.hex}") + if style.bold: + css_rules.append("font-weight: bold") + if style.italic: + css_rules.append("font-style: italic;") + if style.underline: + css_rules.append("text-decoration: underline;") + if style.strike: + css_rules.append("text-decoration: line-through;") + + css = ";".join(css_rules) + style_cache[style] = css + return css + + _theme = theme or SVG_EXPORT_THEME + + width = self.width + char_height = 20 + char_width = char_height * font_aspect_ratio + line_height = char_height * 1.22 + + margin_top = 1 + margin_right = 1 + margin_bottom = 1 + margin_left = 1 + + padding_top = 40 + padding_right = 8 + padding_bottom = 8 + padding_left = 8 + + padding_width = padding_left + padding_right + padding_height = padding_top + padding_bottom + margin_width = margin_left + margin_right + margin_height = margin_top + margin_bottom + + text_backgrounds: List[str] = [] + text_group: List[str] = [] + classes: Dict[str, int] = {} + style_no = 1 + + def escape_text(text: str) -> str: + """HTML escape text and replace spaces with nbsp.""" + return escape(text).replace(" ", " ") + + def make_tag( + name: str, content: Optional[str] = None, **attribs: object + ) -> str: + """Make a tag from name, content, and attributes.""" + + def stringify(value: object) -> str: + if isinstance(value, (float)): + return format(value, "g") + return str(value) + + tag_attribs = " ".join( + f'{k.lstrip("_").replace("_", "-")}="{stringify(v)}"' + for k, v in attribs.items() + ) + return ( + f"<{name} {tag_attribs}>{content}" + if content + else f"<{name} {tag_attribs}/>" + ) + + with self._record_buffer_lock: + segments = list(Segment.filter_control(self._record_buffer)) + if clear: + self._record_buffer.clear() + + if unique_id is None: + unique_id = "terminal-" + str( + zlib.adler32( + ("".join(repr(segment) for segment in segments)).encode( + "utf-8", + "ignore", + ) + + title.encode("utf-8", "ignore") + ) + ) + y = 0 + for y, line in enumerate(Segment.split_and_crop_lines(segments, length=width)): + x = 0 + for text, style, _control in line: + style = style or Style() + rules = get_svg_style(style) + if rules not in classes: + classes[rules] = style_no + style_no += 1 + class_name = f"r{classes[rules]}" + + if style.reverse: + has_background = True + background = ( + _theme.foreground_color.hex + if style.color is None + else style.color.get_truecolor(_theme).hex + ) + else: + bgcolor = style.bgcolor + has_background = bgcolor is not None and not bgcolor.is_default + background = ( + _theme.background_color.hex + if style.bgcolor is None + else style.bgcolor.get_truecolor(_theme).hex + ) + + text_length = cell_len(text) + if has_background: + text_backgrounds.append( + make_tag( + "rect", + fill=background, + x=x * char_width, + y=y * line_height + 1.5, + width=char_width * text_length, + height=line_height + 0.25, + shape_rendering="crispEdges", + ) + ) + + if text != " " * len(text): + text_group.append( + make_tag( + "text", + escape_text(text), + _class=f"{unique_id}-{class_name}", + x=x * char_width, + y=y * line_height + char_height, + textLength=char_width * len(text), + clip_path=f"url(#{unique_id}-line-{y})", + ) + ) + x += cell_len(text) + + line_offsets = [line_no * line_height + 1.5 for line_no in range(y)] + lines = "\n".join( + f""" + {make_tag("rect", x=0, y=offset, width=char_width * width, height=line_height + 0.25)} + """ + for line_no, offset in enumerate(line_offsets) + ) + + styles = "\n".join( + f".{unique_id}-r{rule_no} {{ {css} }}" for css, rule_no in classes.items() + ) + backgrounds = "".join(text_backgrounds) + matrix = "".join(text_group) + + terminal_width = ceil(width * char_width + padding_width) + terminal_height = (y + 1) * line_height + padding_height + chrome = make_tag( + "rect", + fill=_theme.background_color.hex, + stroke="rgba(255,255,255,0.35)", + stroke_width="1", + x=margin_left, + y=margin_top, + width=terminal_width, + height=terminal_height, + rx=8, + ) + + title_color = _theme.foreground_color.hex + if title: + chrome += make_tag( + "text", + escape_text(title), + _class=f"{unique_id}-title", + fill=title_color, + text_anchor="middle", + x=terminal_width // 2, + y=margin_top + char_height + 6, + ) + chrome += f""" + + + + + + """ + + svg = code_format.format( + unique_id=unique_id, + char_width=char_width, + char_height=char_height, + line_height=line_height, + terminal_width=char_width * width - 1, + terminal_height=(y + 1) * line_height - 1, + width=terminal_width + margin_width, + height=terminal_height + margin_height, + terminal_x=margin_left + padding_left, + terminal_y=margin_top + padding_top, + styles=styles, + chrome=chrome, + backgrounds=backgrounds, + matrix=matrix, + lines=lines, + ) + return svg + + def save_svg( + self, + path: str, + *, + title: str = "Rich", + theme: Optional[TerminalTheme] = None, + clear: bool = True, + code_format: str = CONSOLE_SVG_FORMAT, + font_aspect_ratio: float = 0.61, + unique_id: Optional[str] = None, + ) -> None: + """Generate an SVG file from the console contents (requires record=True in Console constructor). + + Args: + path (str): The path to write the SVG to. + title (str, optional): The title of the tab in the output image + theme (TerminalTheme, optional): The ``TerminalTheme`` object to use to style the terminal + clear (bool, optional): Clear record buffer after exporting. Defaults to ``True`` + code_format (str, optional): Format string used to generate the SVG. Rich will inject a number of variables + into the string in order to form the final SVG output. The default template used and the variables + injected by Rich can be found by inspecting the ``console.CONSOLE_SVG_FORMAT`` variable. + font_aspect_ratio (float, optional): The width to height ratio of the font used in the ``code_format`` + string. Defaults to 0.61, which is the width to height ratio of Fira Code (the default font). + If you aren't specifying a different font inside ``code_format``, you probably don't need this. + unique_id (str, optional): unique id that is used as the prefix for various elements (CSS styles, node + ids). If not set, this defaults to a computed value based on the recorded content. + """ + svg = self.export_svg( + title=title, + theme=theme, + clear=clear, + code_format=code_format, + font_aspect_ratio=font_aspect_ratio, + unique_id=unique_id, + ) + with open(path, "wt", encoding="utf-8") as write_file: + write_file.write(svg) + + +def _svg_hash(svg_main_code: str) -> str: + """Returns a unique hash for the given SVG main code. + + Args: + svg_main_code (str): The content we're going to inject in the SVG envelope. + + Returns: + str: a hash of the given content + """ + return str(zlib.adler32(svg_main_code.encode())) + + +if __name__ == "__main__": # pragma: no cover + console = Console(record=True) + + console.log( + "JSONRPC [i]request[/i]", + 5, + 1.3, + True, + False, + None, + { + "jsonrpc": "2.0", + "method": "subtract", + "params": {"minuend": 42, "subtrahend": 23}, + "id": 3, + }, + ) + + console.log("Hello, World!", "{'a': 1}", repr(console)) + + console.print( + { + "name": None, + "empty": [], + "quiz": { + "sport": { + "answered": True, + "q1": { + "question": "Which one is correct team name in NBA?", + "options": [ + "New York Bulls", + "Los Angeles Kings", + "Golden State Warriors", + "Huston Rocket", + ], + "answer": "Huston Rocket", + }, + }, + "maths": { + "answered": False, + "q1": { + "question": "5 + 7 = ?", + "options": [10, 11, 12, 13], + "answer": 12, + }, + "q2": { + "question": "12 - 8 = ?", + "options": [1, 2, 3, 4], + "answer": 4, + }, + }, + }, + } + ) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/constrain.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/constrain.py new file mode 100644 index 0000000..65fdf56 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/constrain.py @@ -0,0 +1,37 @@ +from typing import Optional, TYPE_CHECKING + +from .jupyter import JupyterMixin +from .measure import Measurement + +if TYPE_CHECKING: + from .console import Console, ConsoleOptions, RenderableType, RenderResult + + +class Constrain(JupyterMixin): + """Constrain the width of a renderable to a given number of characters. + + Args: + renderable (RenderableType): A renderable object. + width (int, optional): The maximum width (in characters) to render. Defaults to 80. + """ + + def __init__(self, renderable: "RenderableType", width: Optional[int] = 80) -> None: + self.renderable = renderable + self.width = width + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + if self.width is None: + yield self.renderable + else: + child_options = options.update_width(min(self.width, options.max_width)) + yield from console.render(self.renderable, child_options) + + def __rich_measure__( + self, console: "Console", options: "ConsoleOptions" + ) -> "Measurement": + if self.width is not None: + options = options.update_width(self.width) + measurement = Measurement.get(console, options, self.renderable) + return measurement diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/containers.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/containers.py new file mode 100644 index 0000000..901ff8b --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/containers.py @@ -0,0 +1,167 @@ +from itertools import zip_longest +from typing import ( + TYPE_CHECKING, + Iterable, + Iterator, + List, + Optional, + TypeVar, + Union, + overload, +) + +if TYPE_CHECKING: + from .console import ( + Console, + ConsoleOptions, + JustifyMethod, + OverflowMethod, + RenderResult, + RenderableType, + ) + from .text import Text + +from .cells import cell_len +from .measure import Measurement + +T = TypeVar("T") + + +class Renderables: + """A list subclass which renders its contents to the console.""" + + def __init__( + self, renderables: Optional[Iterable["RenderableType"]] = None + ) -> None: + self._renderables: List["RenderableType"] = ( + list(renderables) if renderables is not None else [] + ) + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + """Console render method to insert line-breaks.""" + yield from self._renderables + + def __rich_measure__( + self, console: "Console", options: "ConsoleOptions" + ) -> "Measurement": + dimensions = [ + Measurement.get(console, options, renderable) + for renderable in self._renderables + ] + if not dimensions: + return Measurement(1, 1) + _min = max(dimension.minimum for dimension in dimensions) + _max = max(dimension.maximum for dimension in dimensions) + return Measurement(_min, _max) + + def append(self, renderable: "RenderableType") -> None: + self._renderables.append(renderable) + + def __iter__(self) -> Iterable["RenderableType"]: + return iter(self._renderables) + + +class Lines: + """A list subclass which can render to the console.""" + + def __init__(self, lines: Iterable["Text"] = ()) -> None: + self._lines: List["Text"] = list(lines) + + def __repr__(self) -> str: + return f"Lines({self._lines!r})" + + def __iter__(self) -> Iterator["Text"]: + return iter(self._lines) + + @overload + def __getitem__(self, index: int) -> "Text": + ... + + @overload + def __getitem__(self, index: slice) -> List["Text"]: + ... + + def __getitem__(self, index: Union[slice, int]) -> Union["Text", List["Text"]]: + return self._lines[index] + + def __setitem__(self, index: int, value: "Text") -> "Lines": + self._lines[index] = value + return self + + def __len__(self) -> int: + return self._lines.__len__() + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + """Console render method to insert line-breaks.""" + yield from self._lines + + def append(self, line: "Text") -> None: + self._lines.append(line) + + def extend(self, lines: Iterable["Text"]) -> None: + self._lines.extend(lines) + + def pop(self, index: int = -1) -> "Text": + return self._lines.pop(index) + + def justify( + self, + console: "Console", + width: int, + justify: "JustifyMethod" = "left", + overflow: "OverflowMethod" = "fold", + ) -> None: + """Justify and overflow text to a given width. + + Args: + console (Console): Console instance. + width (int): Number of cells available per line. + justify (str, optional): Default justify method for text: "left", "center", "full" or "right". Defaults to "left". + overflow (str, optional): Default overflow for text: "crop", "fold", or "ellipsis". Defaults to "fold". + + """ + from .text import Text + + if justify == "left": + for line in self._lines: + line.truncate(width, overflow=overflow, pad=True) + elif justify == "center": + for line in self._lines: + line.rstrip() + line.truncate(width, overflow=overflow) + line.pad_left((width - cell_len(line.plain)) // 2) + line.pad_right(width - cell_len(line.plain)) + elif justify == "right": + for line in self._lines: + line.rstrip() + line.truncate(width, overflow=overflow) + line.pad_left(width - cell_len(line.plain)) + elif justify == "full": + for line_index, line in enumerate(self._lines): + if line_index == len(self._lines) - 1: + break + words = line.split(" ") + words_size = sum(cell_len(word.plain) for word in words) + num_spaces = len(words) - 1 + spaces = [1 for _ in range(num_spaces)] + index = 0 + if spaces: + while words_size + num_spaces < width: + spaces[len(spaces) - index - 1] += 1 + num_spaces += 1 + index = (index + 1) % len(spaces) + tokens: List[Text] = [] + for index, (word, next_word) in enumerate( + zip_longest(words, words[1:]) + ): + tokens.append(word) + if index < len(spaces): + style = word.get_style_at_offset(console, -1) + next_style = next_word.get_style_at_offset(console, 0) + space_style = style if style == next_style else line.style + tokens.append(Text(" " * spaces[index], style=space_style)) + self[line_index] = Text("").join(tokens) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/control.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/control.py new file mode 100644 index 0000000..88fcb92 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/control.py @@ -0,0 +1,225 @@ +import sys +import time +from typing import TYPE_CHECKING, Callable, Dict, Iterable, List, Union + +if sys.version_info >= (3, 8): + from typing import Final +else: + from pip._vendor.typing_extensions import Final # pragma: no cover + +from .segment import ControlCode, ControlType, Segment + +if TYPE_CHECKING: + from .console import Console, ConsoleOptions, RenderResult + +STRIP_CONTROL_CODES: Final = [ + 7, # Bell + 8, # Backspace + 11, # Vertical tab + 12, # Form feed + 13, # Carriage return +] +_CONTROL_STRIP_TRANSLATE: Final = { + _codepoint: None for _codepoint in STRIP_CONTROL_CODES +} + +CONTROL_ESCAPE: Final = { + 7: "\\a", + 8: "\\b", + 11: "\\v", + 12: "\\f", + 13: "\\r", +} + +CONTROL_CODES_FORMAT: Dict[int, Callable[..., str]] = { + ControlType.BELL: lambda: "\x07", + ControlType.CARRIAGE_RETURN: lambda: "\r", + ControlType.HOME: lambda: "\x1b[H", + ControlType.CLEAR: lambda: "\x1b[2J", + ControlType.ENABLE_ALT_SCREEN: lambda: "\x1b[?1049h", + ControlType.DISABLE_ALT_SCREEN: lambda: "\x1b[?1049l", + ControlType.SHOW_CURSOR: lambda: "\x1b[?25h", + ControlType.HIDE_CURSOR: lambda: "\x1b[?25l", + ControlType.CURSOR_UP: lambda param: f"\x1b[{param}A", + ControlType.CURSOR_DOWN: lambda param: f"\x1b[{param}B", + ControlType.CURSOR_FORWARD: lambda param: f"\x1b[{param}C", + ControlType.CURSOR_BACKWARD: lambda param: f"\x1b[{param}D", + ControlType.CURSOR_MOVE_TO_COLUMN: lambda param: f"\x1b[{param+1}G", + ControlType.ERASE_IN_LINE: lambda param: f"\x1b[{param}K", + ControlType.CURSOR_MOVE_TO: lambda x, y: f"\x1b[{y+1};{x+1}H", + ControlType.SET_WINDOW_TITLE: lambda title: f"\x1b]0;{title}\x07", +} + + +class Control: + """A renderable that inserts a control code (non printable but may move cursor). + + Args: + *codes (str): Positional arguments are either a :class:`~rich.segment.ControlType` enum or a + tuple of ControlType and an integer parameter + """ + + __slots__ = ["segment"] + + def __init__(self, *codes: Union[ControlType, ControlCode]) -> None: + control_codes: List[ControlCode] = [ + (code,) if isinstance(code, ControlType) else code for code in codes + ] + _format_map = CONTROL_CODES_FORMAT + rendered_codes = "".join( + _format_map[code](*parameters) for code, *parameters in control_codes + ) + self.segment = Segment(rendered_codes, None, control_codes) + + @classmethod + def bell(cls) -> "Control": + """Ring the 'bell'.""" + return cls(ControlType.BELL) + + @classmethod + def home(cls) -> "Control": + """Move cursor to 'home' position.""" + return cls(ControlType.HOME) + + @classmethod + def move(cls, x: int = 0, y: int = 0) -> "Control": + """Move cursor relative to current position. + + Args: + x (int): X offset. + y (int): Y offset. + + Returns: + ~Control: Control object. + + """ + + def get_codes() -> Iterable[ControlCode]: + control = ControlType + if x: + yield ( + control.CURSOR_FORWARD if x > 0 else control.CURSOR_BACKWARD, + abs(x), + ) + if y: + yield ( + control.CURSOR_DOWN if y > 0 else control.CURSOR_UP, + abs(y), + ) + + control = cls(*get_codes()) + return control + + @classmethod + def move_to_column(cls, x: int, y: int = 0) -> "Control": + """Move to the given column, optionally add offset to row. + + Returns: + x (int): absolute x (column) + y (int): optional y offset (row) + + Returns: + ~Control: Control object. + """ + + return ( + cls( + (ControlType.CURSOR_MOVE_TO_COLUMN, x), + ( + ControlType.CURSOR_DOWN if y > 0 else ControlType.CURSOR_UP, + abs(y), + ), + ) + if y + else cls((ControlType.CURSOR_MOVE_TO_COLUMN, x)) + ) + + @classmethod + def move_to(cls, x: int, y: int) -> "Control": + """Move cursor to absolute position. + + Args: + x (int): x offset (column) + y (int): y offset (row) + + Returns: + ~Control: Control object. + """ + return cls((ControlType.CURSOR_MOVE_TO, x, y)) + + @classmethod + def clear(cls) -> "Control": + """Clear the screen.""" + return cls(ControlType.CLEAR) + + @classmethod + def show_cursor(cls, show: bool) -> "Control": + """Show or hide the cursor.""" + return cls(ControlType.SHOW_CURSOR if show else ControlType.HIDE_CURSOR) + + @classmethod + def alt_screen(cls, enable: bool) -> "Control": + """Enable or disable alt screen.""" + if enable: + return cls(ControlType.ENABLE_ALT_SCREEN, ControlType.HOME) + else: + return cls(ControlType.DISABLE_ALT_SCREEN) + + @classmethod + def title(cls, title: str) -> "Control": + """Set the terminal window title + + Args: + title (str): The new terminal window title + """ + return cls((ControlType.SET_WINDOW_TITLE, title)) + + def __str__(self) -> str: + return self.segment.text + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + if self.segment.text: + yield self.segment + + +def strip_control_codes( + text: str, _translate_table: Dict[int, None] = _CONTROL_STRIP_TRANSLATE +) -> str: + """Remove control codes from text. + + Args: + text (str): A string possibly contain control codes. + + Returns: + str: String with control codes removed. + """ + return text.translate(_translate_table) + + +def escape_control_codes( + text: str, + _translate_table: Dict[int, str] = CONTROL_ESCAPE, +) -> str: + """Replace control codes with their "escaped" equivalent in the given text. + (e.g. "\b" becomes "\\b") + + Args: + text (str): A string possibly containing control codes. + + Returns: + str: String with control codes replaced with their escaped version. + """ + return text.translate(_translate_table) + + +if __name__ == "__main__": # pragma: no cover + from pip._vendor.rich.console import Console + + console = Console() + console.print("Look at the title of your terminal window ^") + # console.print(Control((ControlType.SET_WINDOW_TITLE, "Hello, world!"))) + for i in range(10): + console.set_window_title("🚀 Loading" + "." * i) + time.sleep(0.5) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/default_styles.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/default_styles.py new file mode 100644 index 0000000..dca3719 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/default_styles.py @@ -0,0 +1,190 @@ +from typing import Dict + +from .style import Style + +DEFAULT_STYLES: Dict[str, Style] = { + "none": Style.null(), + "reset": Style( + color="default", + bgcolor="default", + dim=False, + bold=False, + italic=False, + underline=False, + blink=False, + blink2=False, + reverse=False, + conceal=False, + strike=False, + ), + "dim": Style(dim=True), + "bright": Style(dim=False), + "bold": Style(bold=True), + "strong": Style(bold=True), + "code": Style(reverse=True, bold=True), + "italic": Style(italic=True), + "emphasize": Style(italic=True), + "underline": Style(underline=True), + "blink": Style(blink=True), + "blink2": Style(blink2=True), + "reverse": Style(reverse=True), + "strike": Style(strike=True), + "black": Style(color="black"), + "red": Style(color="red"), + "green": Style(color="green"), + "yellow": Style(color="yellow"), + "magenta": Style(color="magenta"), + "cyan": Style(color="cyan"), + "white": Style(color="white"), + "inspect.attr": Style(color="yellow", italic=True), + "inspect.attr.dunder": Style(color="yellow", italic=True, dim=True), + "inspect.callable": Style(bold=True, color="red"), + "inspect.async_def": Style(italic=True, color="bright_cyan"), + "inspect.def": Style(italic=True, color="bright_cyan"), + "inspect.class": Style(italic=True, color="bright_cyan"), + "inspect.error": Style(bold=True, color="red"), + "inspect.equals": Style(), + "inspect.help": Style(color="cyan"), + "inspect.doc": Style(dim=True), + "inspect.value.border": Style(color="green"), + "live.ellipsis": Style(bold=True, color="red"), + "layout.tree.row": Style(dim=False, color="red"), + "layout.tree.column": Style(dim=False, color="blue"), + "logging.keyword": Style(bold=True, color="yellow"), + "logging.level.notset": Style(dim=True), + "logging.level.debug": Style(color="green"), + "logging.level.info": Style(color="blue"), + "logging.level.warning": Style(color="red"), + "logging.level.error": Style(color="red", bold=True), + "logging.level.critical": Style(color="red", bold=True, reverse=True), + "log.level": Style.null(), + "log.time": Style(color="cyan", dim=True), + "log.message": Style.null(), + "log.path": Style(dim=True), + "repr.ellipsis": Style(color="yellow"), + "repr.indent": Style(color="green", dim=True), + "repr.error": Style(color="red", bold=True), + "repr.str": Style(color="green", italic=False, bold=False), + "repr.brace": Style(bold=True), + "repr.comma": Style(bold=True), + "repr.ipv4": Style(bold=True, color="bright_green"), + "repr.ipv6": Style(bold=True, color="bright_green"), + "repr.eui48": Style(bold=True, color="bright_green"), + "repr.eui64": Style(bold=True, color="bright_green"), + "repr.tag_start": Style(bold=True), + "repr.tag_name": Style(color="bright_magenta", bold=True), + "repr.tag_contents": Style(color="default"), + "repr.tag_end": Style(bold=True), + "repr.attrib_name": Style(color="yellow", italic=False), + "repr.attrib_equal": Style(bold=True), + "repr.attrib_value": Style(color="magenta", italic=False), + "repr.number": Style(color="cyan", bold=True, italic=False), + "repr.number_complex": Style(color="cyan", bold=True, italic=False), # same + "repr.bool_true": Style(color="bright_green", italic=True), + "repr.bool_false": Style(color="bright_red", italic=True), + "repr.none": Style(color="magenta", italic=True), + "repr.url": Style(underline=True, color="bright_blue", italic=False, bold=False), + "repr.uuid": Style(color="bright_yellow", bold=False), + "repr.call": Style(color="magenta", bold=True), + "repr.path": Style(color="magenta"), + "repr.filename": Style(color="bright_magenta"), + "rule.line": Style(color="bright_green"), + "rule.text": Style.null(), + "json.brace": Style(bold=True), + "json.bool_true": Style(color="bright_green", italic=True), + "json.bool_false": Style(color="bright_red", italic=True), + "json.null": Style(color="magenta", italic=True), + "json.number": Style(color="cyan", bold=True, italic=False), + "json.str": Style(color="green", italic=False, bold=False), + "json.key": Style(color="blue", bold=True), + "prompt": Style.null(), + "prompt.choices": Style(color="magenta", bold=True), + "prompt.default": Style(color="cyan", bold=True), + "prompt.invalid": Style(color="red"), + "prompt.invalid.choice": Style(color="red"), + "pretty": Style.null(), + "scope.border": Style(color="blue"), + "scope.key": Style(color="yellow", italic=True), + "scope.key.special": Style(color="yellow", italic=True, dim=True), + "scope.equals": Style(color="red"), + "table.header": Style(bold=True), + "table.footer": Style(bold=True), + "table.cell": Style.null(), + "table.title": Style(italic=True), + "table.caption": Style(italic=True, dim=True), + "traceback.error": Style(color="red", italic=True), + "traceback.border.syntax_error": Style(color="bright_red"), + "traceback.border": Style(color="red"), + "traceback.text": Style.null(), + "traceback.title": Style(color="red", bold=True), + "traceback.exc_type": Style(color="bright_red", bold=True), + "traceback.exc_value": Style.null(), + "traceback.offset": Style(color="bright_red", bold=True), + "bar.back": Style(color="grey23"), + "bar.complete": Style(color="rgb(249,38,114)"), + "bar.finished": Style(color="rgb(114,156,31)"), + "bar.pulse": Style(color="rgb(249,38,114)"), + "progress.description": Style.null(), + "progress.filesize": Style(color="green"), + "progress.filesize.total": Style(color="green"), + "progress.download": Style(color="green"), + "progress.elapsed": Style(color="yellow"), + "progress.percentage": Style(color="magenta"), + "progress.remaining": Style(color="cyan"), + "progress.data.speed": Style(color="red"), + "progress.spinner": Style(color="green"), + "status.spinner": Style(color="green"), + "tree": Style(), + "tree.line": Style(), + "markdown.paragraph": Style(), + "markdown.text": Style(), + "markdown.em": Style(italic=True), + "markdown.emph": Style(italic=True), # For commonmark backwards compatibility + "markdown.strong": Style(bold=True), + "markdown.code": Style(bold=True, color="cyan", bgcolor="black"), + "markdown.code_block": Style(color="cyan", bgcolor="black"), + "markdown.block_quote": Style(color="magenta"), + "markdown.list": Style(color="cyan"), + "markdown.item": Style(), + "markdown.item.bullet": Style(color="yellow", bold=True), + "markdown.item.number": Style(color="yellow", bold=True), + "markdown.hr": Style(color="yellow"), + "markdown.h1.border": Style(), + "markdown.h1": Style(bold=True), + "markdown.h2": Style(bold=True, underline=True), + "markdown.h3": Style(bold=True), + "markdown.h4": Style(bold=True, dim=True), + "markdown.h5": Style(underline=True), + "markdown.h6": Style(italic=True), + "markdown.h7": Style(italic=True, dim=True), + "markdown.link": Style(color="bright_blue"), + "markdown.link_url": Style(color="blue", underline=True), + "markdown.s": Style(strike=True), + "iso8601.date": Style(color="blue"), + "iso8601.time": Style(color="magenta"), + "iso8601.timezone": Style(color="yellow"), +} + + +if __name__ == "__main__": # pragma: no cover + import argparse + import io + + from pip._vendor.rich.console import Console + from pip._vendor.rich.table import Table + from pip._vendor.rich.text import Text + + parser = argparse.ArgumentParser() + parser.add_argument("--html", action="store_true", help="Export as HTML table") + args = parser.parse_args() + html: bool = args.html + console = Console(record=True, width=70, file=io.StringIO()) if html else Console() + + table = Table("Name", "Styling") + + for style_name, style in DEFAULT_STYLES.items(): + table.add_row(Text(style_name, style=style), str(style)) + + console.print(table) + if html: + print(console.export_html(inline_styles=True)) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/diagnose.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/diagnose.py new file mode 100644 index 0000000..ad36183 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/diagnose.py @@ -0,0 +1,37 @@ +import os +import platform + +from pip._vendor.rich import inspect +from pip._vendor.rich.console import Console, get_windows_console_features +from pip._vendor.rich.panel import Panel +from pip._vendor.rich.pretty import Pretty + + +def report() -> None: # pragma: no cover + """Print a report to the terminal with debugging information""" + console = Console() + inspect(console) + features = get_windows_console_features() + inspect(features) + + env_names = ( + "TERM", + "COLORTERM", + "CLICOLOR", + "NO_COLOR", + "TERM_PROGRAM", + "COLUMNS", + "LINES", + "JUPYTER_COLUMNS", + "JUPYTER_LINES", + "JPY_PARENT_PID", + "VSCODE_VERBOSE_LOGGING", + ) + env = {name: os.getenv(name) for name in env_names} + console.print(Panel.fit((Pretty(env)), title="[b]Environment Variables")) + + console.print(f'platform="{platform.system()}"') + + +if __name__ == "__main__": # pragma: no cover + report() diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/emoji.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/emoji.py new file mode 100644 index 0000000..791f046 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/emoji.py @@ -0,0 +1,96 @@ +import sys +from typing import TYPE_CHECKING, Optional, Union + +from .jupyter import JupyterMixin +from .segment import Segment +from .style import Style +from ._emoji_codes import EMOJI +from ._emoji_replace import _emoji_replace + +if sys.version_info >= (3, 8): + from typing import Literal +else: + from pip._vendor.typing_extensions import Literal # pragma: no cover + + +if TYPE_CHECKING: + from .console import Console, ConsoleOptions, RenderResult + + +EmojiVariant = Literal["emoji", "text"] + + +class NoEmoji(Exception): + """No emoji by that name.""" + + +class Emoji(JupyterMixin): + __slots__ = ["name", "style", "_char", "variant"] + + VARIANTS = {"text": "\uFE0E", "emoji": "\uFE0F"} + + def __init__( + self, + name: str, + style: Union[str, Style] = "none", + variant: Optional[EmojiVariant] = None, + ) -> None: + """A single emoji character. + + Args: + name (str): Name of emoji. + style (Union[str, Style], optional): Optional style. Defaults to None. + + Raises: + NoEmoji: If the emoji doesn't exist. + """ + self.name = name + self.style = style + self.variant = variant + try: + self._char = EMOJI[name] + except KeyError: + raise NoEmoji(f"No emoji called {name!r}") + if variant is not None: + self._char += self.VARIANTS.get(variant, "") + + @classmethod + def replace(cls, text: str) -> str: + """Replace emoji markup with corresponding unicode characters. + + Args: + text (str): A string with emojis codes, e.g. "Hello :smiley:!" + + Returns: + str: A string with emoji codes replaces with actual emoji. + """ + return _emoji_replace(text) + + def __repr__(self) -> str: + return f"" + + def __str__(self) -> str: + return self._char + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + yield Segment(self._char, console.get_style(self.style)) + + +if __name__ == "__main__": # pragma: no cover + import sys + + from pip._vendor.rich.columns import Columns + from pip._vendor.rich.console import Console + + console = Console(record=True) + + columns = Columns( + (f":{name}: {name}" for name in sorted(EMOJI.keys()) if "\u200D" not in name), + column_first=True, + ) + + console.print(columns) + if len(sys.argv) > 1: + console.save_html(sys.argv[1]) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/errors.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/errors.py new file mode 100644 index 0000000..0bcbe53 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/errors.py @@ -0,0 +1,34 @@ +class ConsoleError(Exception): + """An error in console operation.""" + + +class StyleError(Exception): + """An error in styles.""" + + +class StyleSyntaxError(ConsoleError): + """Style was badly formatted.""" + + +class MissingStyle(StyleError): + """No such style.""" + + +class StyleStackError(ConsoleError): + """Style stack is invalid.""" + + +class NotRenderableError(ConsoleError): + """Object is not renderable.""" + + +class MarkupError(ConsoleError): + """Markup was badly formatted.""" + + +class LiveError(ConsoleError): + """Error related to Live display.""" + + +class NoAltScreen(ConsoleError): + """Alt screen mode was required.""" diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/file_proxy.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/file_proxy.py new file mode 100644 index 0000000..4b0b0da --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/file_proxy.py @@ -0,0 +1,57 @@ +import io +from typing import IO, TYPE_CHECKING, Any, List + +from .ansi import AnsiDecoder +from .text import Text + +if TYPE_CHECKING: + from .console import Console + + +class FileProxy(io.TextIOBase): + """Wraps a file (e.g. sys.stdout) and redirects writes to a console.""" + + def __init__(self, console: "Console", file: IO[str]) -> None: + self.__console = console + self.__file = file + self.__buffer: List[str] = [] + self.__ansi_decoder = AnsiDecoder() + + @property + def rich_proxied_file(self) -> IO[str]: + """Get proxied file.""" + return self.__file + + def __getattr__(self, name: str) -> Any: + return getattr(self.__file, name) + + def write(self, text: str) -> int: + if not isinstance(text, str): + raise TypeError(f"write() argument must be str, not {type(text).__name__}") + buffer = self.__buffer + lines: List[str] = [] + while text: + line, new_line, text = text.partition("\n") + if new_line: + lines.append("".join(buffer) + line) + buffer.clear() + else: + buffer.append(line) + break + if lines: + console = self.__console + with console: + output = Text("\n").join( + self.__ansi_decoder.decode_line(line) for line in lines + ) + console.print(output) + return len(text) + + def flush(self) -> None: + output = "".join(self.__buffer) + if output: + self.__console.print(output) + del self.__buffer[:] + + def fileno(self) -> int: + return self.__file.fileno() diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/filesize.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/filesize.py new file mode 100644 index 0000000..99f118e --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/filesize.py @@ -0,0 +1,89 @@ +# coding: utf-8 +"""Functions for reporting filesizes. Borrowed from https://github.com/PyFilesystem/pyfilesystem2 + +The functions declared in this module should cover the different +use cases needed to generate a string representation of a file size +using several different units. Since there are many standards regarding +file size units, three different functions have been implemented. + +See Also: + * `Wikipedia: Binary prefix `_ + +""" + +__all__ = ["decimal"] + +from typing import Iterable, List, Optional, Tuple + + +def _to_str( + size: int, + suffixes: Iterable[str], + base: int, + *, + precision: Optional[int] = 1, + separator: Optional[str] = " ", +) -> str: + if size == 1: + return "1 byte" + elif size < base: + return "{:,} bytes".format(size) + + for i, suffix in enumerate(suffixes, 2): # noqa: B007 + unit = base**i + if size < unit: + break + return "{:,.{precision}f}{separator}{}".format( + (base * size / unit), + suffix, + precision=precision, + separator=separator, + ) + + +def pick_unit_and_suffix(size: int, suffixes: List[str], base: int) -> Tuple[int, str]: + """Pick a suffix and base for the given size.""" + for i, suffix in enumerate(suffixes): + unit = base**i + if size < unit * base: + break + return unit, suffix + + +def decimal( + size: int, + *, + precision: Optional[int] = 1, + separator: Optional[str] = " ", +) -> str: + """Convert a filesize in to a string (powers of 1000, SI prefixes). + + In this convention, ``1000 B = 1 kB``. + + This is typically the format used to advertise the storage + capacity of USB flash drives and the like (*256 MB* meaning + actually a storage capacity of more than *256 000 000 B*), + or used by **Mac OS X** since v10.6 to report file sizes. + + Arguments: + int (size): A file size. + int (precision): The number of decimal places to include (default = 1). + str (separator): The string to separate the value from the units (default = " "). + + Returns: + `str`: A string containing a abbreviated file size and units. + + Example: + >>> filesize.decimal(30000) + '30.0 kB' + >>> filesize.decimal(30000, precision=2, separator="") + '30.00kB' + + """ + return _to_str( + size, + ("kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"), + 1000, + precision=precision, + separator=separator, + ) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/highlighter.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/highlighter.py new file mode 100644 index 0000000..27714b2 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/highlighter.py @@ -0,0 +1,232 @@ +import re +from abc import ABC, abstractmethod +from typing import List, Union + +from .text import Span, Text + + +def _combine_regex(*regexes: str) -> str: + """Combine a number of regexes in to a single regex. + + Returns: + str: New regex with all regexes ORed together. + """ + return "|".join(regexes) + + +class Highlighter(ABC): + """Abstract base class for highlighters.""" + + def __call__(self, text: Union[str, Text]) -> Text: + """Highlight a str or Text instance. + + Args: + text (Union[str, ~Text]): Text to highlight. + + Raises: + TypeError: If not called with text or str. + + Returns: + Text: A test instance with highlighting applied. + """ + if isinstance(text, str): + highlight_text = Text(text) + elif isinstance(text, Text): + highlight_text = text.copy() + else: + raise TypeError(f"str or Text instance required, not {text!r}") + self.highlight(highlight_text) + return highlight_text + + @abstractmethod + def highlight(self, text: Text) -> None: + """Apply highlighting in place to text. + + Args: + text (~Text): A text object highlight. + """ + + +class NullHighlighter(Highlighter): + """A highlighter object that doesn't highlight. + + May be used to disable highlighting entirely. + + """ + + def highlight(self, text: Text) -> None: + """Nothing to do""" + + +class RegexHighlighter(Highlighter): + """Applies highlighting from a list of regular expressions.""" + + highlights: List[str] = [] + base_style: str = "" + + def highlight(self, text: Text) -> None: + """Highlight :class:`rich.text.Text` using regular expressions. + + Args: + text (~Text): Text to highlighted. + + """ + + highlight_regex = text.highlight_regex + for re_highlight in self.highlights: + highlight_regex(re_highlight, style_prefix=self.base_style) + + +class ReprHighlighter(RegexHighlighter): + """Highlights the text typically produced from ``__repr__`` methods.""" + + base_style = "repr." + highlights = [ + r"(?P<)(?P[-\w.:|]*)(?P[\w\W]*)(?P>)", + r'(?P[\w_]{1,50})=(?P"?[\w_]+"?)?', + r"(?P[][{}()])", + _combine_regex( + r"(?P[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})", + r"(?P([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4})", + r"(?P(?:[0-9A-Fa-f]{1,2}-){7}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{1,2}:){7}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{4}\.){3}[0-9A-Fa-f]{4})", + r"(?P(?:[0-9A-Fa-f]{1,2}-){5}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{1,2}:){5}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{4}\.){2}[0-9A-Fa-f]{4})", + r"(?P[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12})", + r"(?P[\w.]*?)\(", + r"\b(?PTrue)\b|\b(?PFalse)\b|\b(?PNone)\b", + r"(?P\.\.\.)", + r"(?P(?(?\B(/[-\w._+]+)*\/)(?P[-\w._+]*)?", + r"(?b?'''.*?(?(file|https|http|ws|wss)://[-0-9a-zA-Z$_+!`(),.?/;:&=%#~]*)", + ), + ] + + +class JSONHighlighter(RegexHighlighter): + """Highlights JSON""" + + # Captures the start and end of JSON strings, handling escaped quotes + JSON_STR = r"(?b?\".*?(?[\{\[\(\)\]\}])", + r"\b(?Ptrue)\b|\b(?Pfalse)\b|\b(?Pnull)\b", + r"(?P(? None: + super().highlight(text) + + # Additional work to handle highlighting JSON keys + plain = text.plain + append = text.spans.append + whitespace = self.JSON_WHITESPACE + for match in re.finditer(self.JSON_STR, plain): + start, end = match.span() + cursor = end + while cursor < len(plain): + char = plain[cursor] + cursor += 1 + if char == ":": + append(Span(start, end, "json.key")) + elif char in whitespace: + continue + break + + +class ISO8601Highlighter(RegexHighlighter): + """Highlights the ISO8601 date time strings. + Regex reference: https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch04s07.html + """ + + base_style = "iso8601." + highlights = [ + # + # Dates + # + # Calendar month (e.g. 2008-08). The hyphen is required + r"^(?P[0-9]{4})-(?P1[0-2]|0[1-9])$", + # Calendar date w/o hyphens (e.g. 20080830) + r"^(?P(?P[0-9]{4})(?P1[0-2]|0[1-9])(?P3[01]|0[1-9]|[12][0-9]))$", + # Ordinal date (e.g. 2008-243). The hyphen is optional + r"^(?P(?P[0-9]{4})-?(?P36[0-6]|3[0-5][0-9]|[12][0-9]{2}|0[1-9][0-9]|00[1-9]))$", + # + # Weeks + # + # Week of the year (e.g., 2008-W35). The hyphen is optional + r"^(?P(?P[0-9]{4})-?W(?P5[0-3]|[1-4][0-9]|0[1-9]))$", + # Week date (e.g., 2008-W35-6). The hyphens are optional + r"^(?P(?P[0-9]{4})-?W(?P5[0-3]|[1-4][0-9]|0[1-9])-?(?P[1-7]))$", + # + # Times + # + # Hours and minutes (e.g., 17:21). The colon is optional + r"^(?P
    {text}' + append_fragment(text) + + code = "".join(fragments) + html = JUPYTER_HTML_FORMAT.format(code=code) + + return html + + +def display(segments: Iterable[Segment], text: str) -> None: + """Render segments to Jupyter.""" + html = _render_segments(segments) + jupyter_renderable = JupyterRenderable(html, text) + try: + from IPython.display import display as ipython_display + + ipython_display(jupyter_renderable) + except ModuleNotFoundError: + # Handle the case where the Console has force_jupyter=True, + # but IPython is not installed. + pass + + +def print(*args: Any, **kwargs: Any) -> None: + """Proxy for Console print.""" + console = get_console() + return console.print(*args, **kwargs) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/layout.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/layout.py new file mode 100644 index 0000000..a6f1a31 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/layout.py @@ -0,0 +1,442 @@ +from abc import ABC, abstractmethod +from itertools import islice +from operator import itemgetter +from threading import RLock +from typing import ( + TYPE_CHECKING, + Dict, + Iterable, + List, + NamedTuple, + Optional, + Sequence, + Tuple, + Union, +) + +from ._ratio import ratio_resolve +from .align import Align +from .console import Console, ConsoleOptions, RenderableType, RenderResult +from .highlighter import ReprHighlighter +from .panel import Panel +from .pretty import Pretty +from .region import Region +from .repr import Result, rich_repr +from .segment import Segment +from .style import StyleType + +if TYPE_CHECKING: + from pip._vendor.rich.tree import Tree + + +class LayoutRender(NamedTuple): + """An individual layout render.""" + + region: Region + render: List[List[Segment]] + + +RegionMap = Dict["Layout", Region] +RenderMap = Dict["Layout", LayoutRender] + + +class LayoutError(Exception): + """Layout related error.""" + + +class NoSplitter(LayoutError): + """Requested splitter does not exist.""" + + +class _Placeholder: + """An internal renderable used as a Layout placeholder.""" + + highlighter = ReprHighlighter() + + def __init__(self, layout: "Layout", style: StyleType = "") -> None: + self.layout = layout + self.style = style + + def __rich_console__( + self, console: Console, options: ConsoleOptions + ) -> RenderResult: + width = options.max_width + height = options.height or options.size.height + layout = self.layout + title = ( + f"{layout.name!r} ({width} x {height})" + if layout.name + else f"({width} x {height})" + ) + yield Panel( + Align.center(Pretty(layout), vertical="middle"), + style=self.style, + title=self.highlighter(title), + border_style="blue", + height=height, + ) + + +class Splitter(ABC): + """Base class for a splitter.""" + + name: str = "" + + @abstractmethod + def get_tree_icon(self) -> str: + """Get the icon (emoji) used in layout.tree""" + + @abstractmethod + def divide( + self, children: Sequence["Layout"], region: Region + ) -> Iterable[Tuple["Layout", Region]]: + """Divide a region amongst several child layouts. + + Args: + children (Sequence(Layout)): A number of child layouts. + region (Region): A rectangular region to divide. + """ + + +class RowSplitter(Splitter): + """Split a layout region in to rows.""" + + name = "row" + + def get_tree_icon(self) -> str: + return "[layout.tree.row]⬌" + + def divide( + self, children: Sequence["Layout"], region: Region + ) -> Iterable[Tuple["Layout", Region]]: + x, y, width, height = region + render_widths = ratio_resolve(width, children) + offset = 0 + _Region = Region + for child, child_width in zip(children, render_widths): + yield child, _Region(x + offset, y, child_width, height) + offset += child_width + + +class ColumnSplitter(Splitter): + """Split a layout region in to columns.""" + + name = "column" + + def get_tree_icon(self) -> str: + return "[layout.tree.column]⬍" + + def divide( + self, children: Sequence["Layout"], region: Region + ) -> Iterable[Tuple["Layout", Region]]: + x, y, width, height = region + render_heights = ratio_resolve(height, children) + offset = 0 + _Region = Region + for child, child_height in zip(children, render_heights): + yield child, _Region(x, y + offset, width, child_height) + offset += child_height + + +@rich_repr +class Layout: + """A renderable to divide a fixed height in to rows or columns. + + Args: + renderable (RenderableType, optional): Renderable content, or None for placeholder. Defaults to None. + name (str, optional): Optional identifier for Layout. Defaults to None. + size (int, optional): Optional fixed size of layout. Defaults to None. + minimum_size (int, optional): Minimum size of layout. Defaults to 1. + ratio (int, optional): Optional ratio for flexible layout. Defaults to 1. + visible (bool, optional): Visibility of layout. Defaults to True. + """ + + splitters = {"row": RowSplitter, "column": ColumnSplitter} + + def __init__( + self, + renderable: Optional[RenderableType] = None, + *, + name: Optional[str] = None, + size: Optional[int] = None, + minimum_size: int = 1, + ratio: int = 1, + visible: bool = True, + ) -> None: + self._renderable = renderable or _Placeholder(self) + self.size = size + self.minimum_size = minimum_size + self.ratio = ratio + self.name = name + self.visible = visible + self.splitter: Splitter = self.splitters["column"]() + self._children: List[Layout] = [] + self._render_map: RenderMap = {} + self._lock = RLock() + + def __rich_repr__(self) -> Result: + yield "name", self.name, None + yield "size", self.size, None + yield "minimum_size", self.minimum_size, 1 + yield "ratio", self.ratio, 1 + + @property + def renderable(self) -> RenderableType: + """Layout renderable.""" + return self if self._children else self._renderable + + @property + def children(self) -> List["Layout"]: + """Gets (visible) layout children.""" + return [child for child in self._children if child.visible] + + @property + def map(self) -> RenderMap: + """Get a map of the last render.""" + return self._render_map + + def get(self, name: str) -> Optional["Layout"]: + """Get a named layout, or None if it doesn't exist. + + Args: + name (str): Name of layout. + + Returns: + Optional[Layout]: Layout instance or None if no layout was found. + """ + if self.name == name: + return self + else: + for child in self._children: + named_layout = child.get(name) + if named_layout is not None: + return named_layout + return None + + def __getitem__(self, name: str) -> "Layout": + layout = self.get(name) + if layout is None: + raise KeyError(f"No layout with name {name!r}") + return layout + + @property + def tree(self) -> "Tree": + """Get a tree renderable to show layout structure.""" + from pip._vendor.rich.styled import Styled + from pip._vendor.rich.table import Table + from pip._vendor.rich.tree import Tree + + def summary(layout: "Layout") -> Table: + icon = layout.splitter.get_tree_icon() + + table = Table.grid(padding=(0, 1, 0, 0)) + + text: RenderableType = ( + Pretty(layout) if layout.visible else Styled(Pretty(layout), "dim") + ) + table.add_row(icon, text) + _summary = table + return _summary + + layout = self + tree = Tree( + summary(layout), + guide_style=f"layout.tree.{layout.splitter.name}", + highlight=True, + ) + + def recurse(tree: "Tree", layout: "Layout") -> None: + for child in layout._children: + recurse( + tree.add( + summary(child), + guide_style=f"layout.tree.{child.splitter.name}", + ), + child, + ) + + recurse(tree, self) + return tree + + def split( + self, + *layouts: Union["Layout", RenderableType], + splitter: Union[Splitter, str] = "column", + ) -> None: + """Split the layout in to multiple sub-layouts. + + Args: + *layouts (Layout): Positional arguments should be (sub) Layout instances. + splitter (Union[Splitter, str]): Splitter instance or name of splitter. + """ + _layouts = [ + layout if isinstance(layout, Layout) else Layout(layout) + for layout in layouts + ] + try: + self.splitter = ( + splitter + if isinstance(splitter, Splitter) + else self.splitters[splitter]() + ) + except KeyError: + raise NoSplitter(f"No splitter called {splitter!r}") + self._children[:] = _layouts + + def add_split(self, *layouts: Union["Layout", RenderableType]) -> None: + """Add a new layout(s) to existing split. + + Args: + *layouts (Union[Layout, RenderableType]): Positional arguments should be renderables or (sub) Layout instances. + + """ + _layouts = ( + layout if isinstance(layout, Layout) else Layout(layout) + for layout in layouts + ) + self._children.extend(_layouts) + + def split_row(self, *layouts: Union["Layout", RenderableType]) -> None: + """Split the layout in to a row (layouts side by side). + + Args: + *layouts (Layout): Positional arguments should be (sub) Layout instances. + """ + self.split(*layouts, splitter="row") + + def split_column(self, *layouts: Union["Layout", RenderableType]) -> None: + """Split the layout in to a column (layouts stacked on top of each other). + + Args: + *layouts (Layout): Positional arguments should be (sub) Layout instances. + """ + self.split(*layouts, splitter="column") + + def unsplit(self) -> None: + """Reset splits to initial state.""" + del self._children[:] + + def update(self, renderable: RenderableType) -> None: + """Update renderable. + + Args: + renderable (RenderableType): New renderable object. + """ + with self._lock: + self._renderable = renderable + + def refresh_screen(self, console: "Console", layout_name: str) -> None: + """Refresh a sub-layout. + + Args: + console (Console): Console instance where Layout is to be rendered. + layout_name (str): Name of layout. + """ + with self._lock: + layout = self[layout_name] + region, _lines = self._render_map[layout] + (x, y, width, height) = region + lines = console.render_lines( + layout, console.options.update_dimensions(width, height) + ) + self._render_map[layout] = LayoutRender(region, lines) + console.update_screen_lines(lines, x, y) + + def _make_region_map(self, width: int, height: int) -> RegionMap: + """Create a dict that maps layout on to Region.""" + stack: List[Tuple[Layout, Region]] = [(self, Region(0, 0, width, height))] + push = stack.append + pop = stack.pop + layout_regions: List[Tuple[Layout, Region]] = [] + append_layout_region = layout_regions.append + while stack: + append_layout_region(pop()) + layout, region = layout_regions[-1] + children = layout.children + if children: + for child_and_region in layout.splitter.divide(children, region): + push(child_and_region) + + region_map = { + layout: region + for layout, region in sorted(layout_regions, key=itemgetter(1)) + } + return region_map + + def render(self, console: Console, options: ConsoleOptions) -> RenderMap: + """Render the sub_layouts. + + Args: + console (Console): Console instance. + options (ConsoleOptions): Console options. + + Returns: + RenderMap: A dict that maps Layout on to a tuple of Region, lines + """ + render_width = options.max_width + render_height = options.height or console.height + region_map = self._make_region_map(render_width, render_height) + layout_regions = [ + (layout, region) + for layout, region in region_map.items() + if not layout.children + ] + render_map: Dict["Layout", "LayoutRender"] = {} + render_lines = console.render_lines + update_dimensions = options.update_dimensions + + for layout, region in layout_regions: + lines = render_lines( + layout.renderable, update_dimensions(region.width, region.height) + ) + render_map[layout] = LayoutRender(region, lines) + return render_map + + def __rich_console__( + self, console: Console, options: ConsoleOptions + ) -> RenderResult: + with self._lock: + width = options.max_width or console.width + height = options.height or console.height + render_map = self.render(console, options.update_dimensions(width, height)) + self._render_map = render_map + layout_lines: List[List[Segment]] = [[] for _ in range(height)] + _islice = islice + for region, lines in render_map.values(): + _x, y, _layout_width, layout_height = region + for row, line in zip( + _islice(layout_lines, y, y + layout_height), lines + ): + row.extend(line) + + new_line = Segment.line() + for layout_row in layout_lines: + yield from layout_row + yield new_line + + +if __name__ == "__main__": + from pip._vendor.rich.console import Console + + console = Console() + layout = Layout() + + layout.split_column( + Layout(name="header", size=3), + Layout(ratio=1, name="main"), + Layout(size=10, name="footer"), + ) + + layout["main"].split_row(Layout(name="side"), Layout(name="body", ratio=2)) + + layout["body"].split_row(Layout(name="content", ratio=2), Layout(name="s2")) + + layout["s2"].split_column( + Layout(name="top"), Layout(name="middle"), Layout(name="bottom") + ) + + layout["side"].split_column(Layout(layout.tree, name="left1"), Layout(name="left2")) + + layout["content"].update("foo") + + console.print(layout) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/live.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/live.py new file mode 100644 index 0000000..f0529a7 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/live.py @@ -0,0 +1,375 @@ +import sys +from threading import Event, RLock, Thread +from types import TracebackType +from typing import IO, Any, Callable, List, Optional, TextIO, Type, cast + +from . import get_console +from .console import Console, ConsoleRenderable, RenderableType, RenderHook +from .control import Control +from .file_proxy import FileProxy +from .jupyter import JupyterMixin +from .live_render import LiveRender, VerticalOverflowMethod +from .screen import Screen +from .text import Text + + +class _RefreshThread(Thread): + """A thread that calls refresh() at regular intervals.""" + + def __init__(self, live: "Live", refresh_per_second: float) -> None: + self.live = live + self.refresh_per_second = refresh_per_second + self.done = Event() + super().__init__(daemon=True) + + def stop(self) -> None: + self.done.set() + + def run(self) -> None: + while not self.done.wait(1 / self.refresh_per_second): + with self.live._lock: + if not self.done.is_set(): + self.live.refresh() + + +class Live(JupyterMixin, RenderHook): + """Renders an auto-updating live display of any given renderable. + + Args: + renderable (RenderableType, optional): The renderable to live display. Defaults to displaying nothing. + console (Console, optional): Optional Console instance. Default will an internal Console instance writing to stdout. + screen (bool, optional): Enable alternate screen mode. Defaults to False. + auto_refresh (bool, optional): Enable auto refresh. If disabled, you will need to call `refresh()` or `update()` with refresh flag. Defaults to True + refresh_per_second (float, optional): Number of times per second to refresh the live display. Defaults to 4. + transient (bool, optional): Clear the renderable on exit (has no effect when screen=True). Defaults to False. + redirect_stdout (bool, optional): Enable redirection of stdout, so ``print`` may be used. Defaults to True. + redirect_stderr (bool, optional): Enable redirection of stderr. Defaults to True. + vertical_overflow (VerticalOverflowMethod, optional): How to handle renderable when it is too tall for the console. Defaults to "ellipsis". + get_renderable (Callable[[], RenderableType], optional): Optional callable to get renderable. Defaults to None. + """ + + def __init__( + self, + renderable: Optional[RenderableType] = None, + *, + console: Optional[Console] = None, + screen: bool = False, + auto_refresh: bool = True, + refresh_per_second: float = 4, + transient: bool = False, + redirect_stdout: bool = True, + redirect_stderr: bool = True, + vertical_overflow: VerticalOverflowMethod = "ellipsis", + get_renderable: Optional[Callable[[], RenderableType]] = None, + ) -> None: + assert refresh_per_second > 0, "refresh_per_second must be > 0" + self._renderable = renderable + self.console = console if console is not None else get_console() + self._screen = screen + self._alt_screen = False + + self._redirect_stdout = redirect_stdout + self._redirect_stderr = redirect_stderr + self._restore_stdout: Optional[IO[str]] = None + self._restore_stderr: Optional[IO[str]] = None + + self._lock = RLock() + self.ipy_widget: Optional[Any] = None + self.auto_refresh = auto_refresh + self._started: bool = False + self.transient = True if screen else transient + + self._refresh_thread: Optional[_RefreshThread] = None + self.refresh_per_second = refresh_per_second + + self.vertical_overflow = vertical_overflow + self._get_renderable = get_renderable + self._live_render = LiveRender( + self.get_renderable(), vertical_overflow=vertical_overflow + ) + + @property + def is_started(self) -> bool: + """Check if live display has been started.""" + return self._started + + def get_renderable(self) -> RenderableType: + renderable = ( + self._get_renderable() + if self._get_renderable is not None + else self._renderable + ) + return renderable or "" + + def start(self, refresh: bool = False) -> None: + """Start live rendering display. + + Args: + refresh (bool, optional): Also refresh. Defaults to False. + """ + with self._lock: + if self._started: + return + self.console.set_live(self) + self._started = True + if self._screen: + self._alt_screen = self.console.set_alt_screen(True) + self.console.show_cursor(False) + self._enable_redirect_io() + self.console.push_render_hook(self) + if refresh: + try: + self.refresh() + except Exception: + # If refresh fails, we want to stop the redirection of sys.stderr, + # so the error stacktrace is properly displayed in the terminal. + # (or, if the code that calls Rich captures the exception and wants to display something, + # let this be displayed in the terminal). + self.stop() + raise + if self.auto_refresh: + self._refresh_thread = _RefreshThread(self, self.refresh_per_second) + self._refresh_thread.start() + + def stop(self) -> None: + """Stop live rendering display.""" + with self._lock: + if not self._started: + return + self.console.clear_live() + self._started = False + + if self.auto_refresh and self._refresh_thread is not None: + self._refresh_thread.stop() + self._refresh_thread = None + # allow it to fully render on the last even if overflow + self.vertical_overflow = "visible" + with self.console: + try: + if not self._alt_screen and not self.console.is_jupyter: + self.refresh() + finally: + self._disable_redirect_io() + self.console.pop_render_hook() + if not self._alt_screen and self.console.is_terminal: + self.console.line() + self.console.show_cursor(True) + if self._alt_screen: + self.console.set_alt_screen(False) + + if self.transient and not self._alt_screen: + self.console.control(self._live_render.restore_cursor()) + if self.ipy_widget is not None and self.transient: + self.ipy_widget.close() # pragma: no cover + + def __enter__(self) -> "Live": + self.start(refresh=self._renderable is not None) + return self + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + self.stop() + + def _enable_redirect_io(self) -> None: + """Enable redirecting of stdout / stderr.""" + if self.console.is_terminal or self.console.is_jupyter: + if self._redirect_stdout and not isinstance(sys.stdout, FileProxy): + self._restore_stdout = sys.stdout + sys.stdout = cast("TextIO", FileProxy(self.console, sys.stdout)) + if self._redirect_stderr and not isinstance(sys.stderr, FileProxy): + self._restore_stderr = sys.stderr + sys.stderr = cast("TextIO", FileProxy(self.console, sys.stderr)) + + def _disable_redirect_io(self) -> None: + """Disable redirecting of stdout / stderr.""" + if self._restore_stdout: + sys.stdout = cast("TextIO", self._restore_stdout) + self._restore_stdout = None + if self._restore_stderr: + sys.stderr = cast("TextIO", self._restore_stderr) + self._restore_stderr = None + + @property + def renderable(self) -> RenderableType: + """Get the renderable that is being displayed + + Returns: + RenderableType: Displayed renderable. + """ + renderable = self.get_renderable() + return Screen(renderable) if self._alt_screen else renderable + + def update(self, renderable: RenderableType, *, refresh: bool = False) -> None: + """Update the renderable that is being displayed + + Args: + renderable (RenderableType): New renderable to use. + refresh (bool, optional): Refresh the display. Defaults to False. + """ + if isinstance(renderable, str): + renderable = self.console.render_str(renderable) + with self._lock: + self._renderable = renderable + if refresh: + self.refresh() + + def refresh(self) -> None: + """Update the display of the Live Render.""" + with self._lock: + self._live_render.set_renderable(self.renderable) + if self.console.is_jupyter: # pragma: no cover + try: + from IPython.display import display + from ipywidgets import Output + except ImportError: + import warnings + + warnings.warn('install "ipywidgets" for Jupyter support') + else: + if self.ipy_widget is None: + self.ipy_widget = Output() + display(self.ipy_widget) + + with self.ipy_widget: + self.ipy_widget.clear_output(wait=True) + self.console.print(self._live_render.renderable) + elif self.console.is_terminal and not self.console.is_dumb_terminal: + with self.console: + self.console.print(Control()) + elif ( + not self._started and not self.transient + ): # if it is finished allow files or dumb-terminals to see final result + with self.console: + self.console.print(Control()) + + def process_renderables( + self, renderables: List[ConsoleRenderable] + ) -> List[ConsoleRenderable]: + """Process renderables to restore cursor and display progress.""" + self._live_render.vertical_overflow = self.vertical_overflow + if self.console.is_interactive: + # lock needs acquiring as user can modify live_render renderable at any time unlike in Progress. + with self._lock: + reset = ( + Control.home() + if self._alt_screen + else self._live_render.position_cursor() + ) + renderables = [reset, *renderables, self._live_render] + elif ( + not self._started and not self.transient + ): # if it is finished render the final output for files or dumb_terminals + renderables = [*renderables, self._live_render] + + return renderables + + +if __name__ == "__main__": # pragma: no cover + import random + import time + from itertools import cycle + from typing import Dict, List, Tuple + + from .align import Align + from .console import Console + from .live import Live as Live + from .panel import Panel + from .rule import Rule + from .syntax import Syntax + from .table import Table + + console = Console() + + syntax = Syntax( + '''def loop_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: + """Iterate and generate a tuple with a flag for last value.""" + iter_values = iter(values) + try: + previous_value = next(iter_values) + except StopIteration: + return + for value in iter_values: + yield False, previous_value + previous_value = value + yield True, previous_value''', + "python", + line_numbers=True, + ) + + table = Table("foo", "bar", "baz") + table.add_row("1", "2", "3") + + progress_renderables = [ + "You can make the terminal shorter and taller to see the live table hide" + "Text may be printed while the progress bars are rendering.", + Panel("In fact, [i]any[/i] renderable will work"), + "Such as [magenta]tables[/]...", + table, + "Pretty printed structures...", + {"type": "example", "text": "Pretty printed"}, + "Syntax...", + syntax, + Rule("Give it a try!"), + ] + + examples = cycle(progress_renderables) + + exchanges = [ + "SGD", + "MYR", + "EUR", + "USD", + "AUD", + "JPY", + "CNH", + "HKD", + "CAD", + "INR", + "DKK", + "GBP", + "RUB", + "NZD", + "MXN", + "IDR", + "TWD", + "THB", + "VND", + ] + with Live(console=console) as live_table: + exchange_rate_dict: Dict[Tuple[str, str], float] = {} + + for index in range(100): + select_exchange = exchanges[index % len(exchanges)] + + for exchange in exchanges: + if exchange == select_exchange: + continue + time.sleep(0.4) + if random.randint(0, 10) < 1: + console.log(next(examples)) + exchange_rate_dict[(select_exchange, exchange)] = 200 / ( + (random.random() * 320) + 1 + ) + if len(exchange_rate_dict) > len(exchanges) - 1: + exchange_rate_dict.pop(list(exchange_rate_dict.keys())[0]) + table = Table(title="Exchange Rates") + + table.add_column("Source Currency") + table.add_column("Destination Currency") + table.add_column("Exchange Rate") + + for (source, dest), exchange_rate in exchange_rate_dict.items(): + table.add_row( + source, + dest, + Text( + f"{exchange_rate:.4f}", + style="red" if exchange_rate < 1.0 else "green", + ), + ) + + live_table.update(Align.center(table)) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/live_render.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/live_render.py new file mode 100644 index 0000000..e20745d --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/live_render.py @@ -0,0 +1,112 @@ +import sys +from typing import Optional, Tuple + +if sys.version_info >= (3, 8): + from typing import Literal +else: + from pip._vendor.typing_extensions import Literal # pragma: no cover + + +from ._loop import loop_last +from .console import Console, ConsoleOptions, RenderableType, RenderResult +from .control import Control +from .segment import ControlType, Segment +from .style import StyleType +from .text import Text + +VerticalOverflowMethod = Literal["crop", "ellipsis", "visible"] + + +class LiveRender: + """Creates a renderable that may be updated. + + Args: + renderable (RenderableType): Any renderable object. + style (StyleType, optional): An optional style to apply to the renderable. Defaults to "". + """ + + def __init__( + self, + renderable: RenderableType, + style: StyleType = "", + vertical_overflow: VerticalOverflowMethod = "ellipsis", + ) -> None: + self.renderable = renderable + self.style = style + self.vertical_overflow = vertical_overflow + self._shape: Optional[Tuple[int, int]] = None + + def set_renderable(self, renderable: RenderableType) -> None: + """Set a new renderable. + + Args: + renderable (RenderableType): Any renderable object, including str. + """ + self.renderable = renderable + + def position_cursor(self) -> Control: + """Get control codes to move cursor to beginning of live render. + + Returns: + Control: A control instance that may be printed. + """ + if self._shape is not None: + _, height = self._shape + return Control( + ControlType.CARRIAGE_RETURN, + (ControlType.ERASE_IN_LINE, 2), + *( + ( + (ControlType.CURSOR_UP, 1), + (ControlType.ERASE_IN_LINE, 2), + ) + * (height - 1) + ) + ) + return Control() + + def restore_cursor(self) -> Control: + """Get control codes to clear the render and restore the cursor to its previous position. + + Returns: + Control: A Control instance that may be printed. + """ + if self._shape is not None: + _, height = self._shape + return Control( + ControlType.CARRIAGE_RETURN, + *((ControlType.CURSOR_UP, 1), (ControlType.ERASE_IN_LINE, 2)) * height + ) + return Control() + + def __rich_console__( + self, console: Console, options: ConsoleOptions + ) -> RenderResult: + renderable = self.renderable + style = console.get_style(self.style) + lines = console.render_lines(renderable, options, style=style, pad=False) + shape = Segment.get_shape(lines) + + _, height = shape + if height > options.size.height: + if self.vertical_overflow == "crop": + lines = lines[: options.size.height] + shape = Segment.get_shape(lines) + elif self.vertical_overflow == "ellipsis": + lines = lines[: (options.size.height - 1)] + overflow_text = Text( + "...", + overflow="crop", + justify="center", + end="", + style="live.ellipsis", + ) + lines.append(list(console.render(overflow_text))) + shape = Segment.get_shape(lines) + self._shape = shape + + new_line = Segment.line() + for last, line in loop_last(lines): + yield from line + if not last: + yield new_line diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/logging.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/logging.py new file mode 100644 index 0000000..91368dd --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/logging.py @@ -0,0 +1,289 @@ +import logging +from datetime import datetime +from logging import Handler, LogRecord +from pathlib import Path +from types import ModuleType +from typing import ClassVar, Iterable, List, Optional, Type, Union + +from pip._vendor.rich._null_file import NullFile + +from . import get_console +from ._log_render import FormatTimeCallable, LogRender +from .console import Console, ConsoleRenderable +from .highlighter import Highlighter, ReprHighlighter +from .text import Text +from .traceback import Traceback + + +class RichHandler(Handler): + """A logging handler that renders output with Rich. The time / level / message and file are displayed in columns. + The level is color coded, and the message is syntax highlighted. + + Note: + Be careful when enabling console markup in log messages if you have configured logging for libraries not + under your control. If a dependency writes messages containing square brackets, it may not produce the intended output. + + Args: + level (Union[int, str], optional): Log level. Defaults to logging.NOTSET. + console (:class:`~rich.console.Console`, optional): Optional console instance to write logs. + Default will use a global console instance writing to stdout. + show_time (bool, optional): Show a column for the time. Defaults to True. + omit_repeated_times (bool, optional): Omit repetition of the same time. Defaults to True. + show_level (bool, optional): Show a column for the level. Defaults to True. + show_path (bool, optional): Show the path to the original log call. Defaults to True. + enable_link_path (bool, optional): Enable terminal link of path column to file. Defaults to True. + highlighter (Highlighter, optional): Highlighter to style log messages, or None to use ReprHighlighter. Defaults to None. + markup (bool, optional): Enable console markup in log messages. Defaults to False. + rich_tracebacks (bool, optional): Enable rich tracebacks with syntax highlighting and formatting. Defaults to False. + tracebacks_width (Optional[int], optional): Number of characters used to render tracebacks, or None for full width. Defaults to None. + tracebacks_extra_lines (int, optional): Additional lines of code to render tracebacks, or None for full width. Defaults to None. + tracebacks_theme (str, optional): Override pygments theme used in traceback. + tracebacks_word_wrap (bool, optional): Enable word wrapping of long tracebacks lines. Defaults to True. + tracebacks_show_locals (bool, optional): Enable display of locals in tracebacks. Defaults to False. + tracebacks_suppress (Sequence[Union[str, ModuleType]]): Optional sequence of modules or paths to exclude from traceback. + locals_max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation. + Defaults to 10. + locals_max_string (int, optional): Maximum length of string before truncating, or None to disable. Defaults to 80. + log_time_format (Union[str, TimeFormatterCallable], optional): If ``log_time`` is enabled, either string for strftime or callable that formats the time. Defaults to "[%x %X] ". + keywords (List[str], optional): List of words to highlight instead of ``RichHandler.KEYWORDS``. + """ + + KEYWORDS: ClassVar[Optional[List[str]]] = [ + "GET", + "POST", + "HEAD", + "PUT", + "DELETE", + "OPTIONS", + "TRACE", + "PATCH", + ] + HIGHLIGHTER_CLASS: ClassVar[Type[Highlighter]] = ReprHighlighter + + def __init__( + self, + level: Union[int, str] = logging.NOTSET, + console: Optional[Console] = None, + *, + show_time: bool = True, + omit_repeated_times: bool = True, + show_level: bool = True, + show_path: bool = True, + enable_link_path: bool = True, + highlighter: Optional[Highlighter] = None, + markup: bool = False, + rich_tracebacks: bool = False, + tracebacks_width: Optional[int] = None, + tracebacks_extra_lines: int = 3, + tracebacks_theme: Optional[str] = None, + tracebacks_word_wrap: bool = True, + tracebacks_show_locals: bool = False, + tracebacks_suppress: Iterable[Union[str, ModuleType]] = (), + locals_max_length: int = 10, + locals_max_string: int = 80, + log_time_format: Union[str, FormatTimeCallable] = "[%x %X]", + keywords: Optional[List[str]] = None, + ) -> None: + super().__init__(level=level) + self.console = console or get_console() + self.highlighter = highlighter or self.HIGHLIGHTER_CLASS() + self._log_render = LogRender( + show_time=show_time, + show_level=show_level, + show_path=show_path, + time_format=log_time_format, + omit_repeated_times=omit_repeated_times, + level_width=None, + ) + self.enable_link_path = enable_link_path + self.markup = markup + self.rich_tracebacks = rich_tracebacks + self.tracebacks_width = tracebacks_width + self.tracebacks_extra_lines = tracebacks_extra_lines + self.tracebacks_theme = tracebacks_theme + self.tracebacks_word_wrap = tracebacks_word_wrap + self.tracebacks_show_locals = tracebacks_show_locals + self.tracebacks_suppress = tracebacks_suppress + self.locals_max_length = locals_max_length + self.locals_max_string = locals_max_string + self.keywords = keywords + + def get_level_text(self, record: LogRecord) -> Text: + """Get the level name from the record. + + Args: + record (LogRecord): LogRecord instance. + + Returns: + Text: A tuple of the style and level name. + """ + level_name = record.levelname + level_text = Text.styled( + level_name.ljust(8), f"logging.level.{level_name.lower()}" + ) + return level_text + + def emit(self, record: LogRecord) -> None: + """Invoked by logging.""" + message = self.format(record) + traceback = None + if ( + self.rich_tracebacks + and record.exc_info + and record.exc_info != (None, None, None) + ): + exc_type, exc_value, exc_traceback = record.exc_info + assert exc_type is not None + assert exc_value is not None + traceback = Traceback.from_exception( + exc_type, + exc_value, + exc_traceback, + width=self.tracebacks_width, + extra_lines=self.tracebacks_extra_lines, + theme=self.tracebacks_theme, + word_wrap=self.tracebacks_word_wrap, + show_locals=self.tracebacks_show_locals, + locals_max_length=self.locals_max_length, + locals_max_string=self.locals_max_string, + suppress=self.tracebacks_suppress, + ) + message = record.getMessage() + if self.formatter: + record.message = record.getMessage() + formatter = self.formatter + if hasattr(formatter, "usesTime") and formatter.usesTime(): + record.asctime = formatter.formatTime(record, formatter.datefmt) + message = formatter.formatMessage(record) + + message_renderable = self.render_message(record, message) + log_renderable = self.render( + record=record, traceback=traceback, message_renderable=message_renderable + ) + if isinstance(self.console.file, NullFile): + # Handles pythonw, where stdout/stderr are null, and we return NullFile + # instance from Console.file. In this case, we still want to make a log record + # even though we won't be writing anything to a file. + self.handleError(record) + else: + try: + self.console.print(log_renderable) + except Exception: + self.handleError(record) + + def render_message(self, record: LogRecord, message: str) -> "ConsoleRenderable": + """Render message text in to Text. + + Args: + record (LogRecord): logging Record. + message (str): String containing log message. + + Returns: + ConsoleRenderable: Renderable to display log message. + """ + use_markup = getattr(record, "markup", self.markup) + message_text = Text.from_markup(message) if use_markup else Text(message) + + highlighter = getattr(record, "highlighter", self.highlighter) + if highlighter: + message_text = highlighter(message_text) + + if self.keywords is None: + self.keywords = self.KEYWORDS + + if self.keywords: + message_text.highlight_words(self.keywords, "logging.keyword") + + return message_text + + def render( + self, + *, + record: LogRecord, + traceback: Optional[Traceback], + message_renderable: "ConsoleRenderable", + ) -> "ConsoleRenderable": + """Render log for display. + + Args: + record (LogRecord): logging Record. + traceback (Optional[Traceback]): Traceback instance or None for no Traceback. + message_renderable (ConsoleRenderable): Renderable (typically Text) containing log message contents. + + Returns: + ConsoleRenderable: Renderable to display log. + """ + path = Path(record.pathname).name + level = self.get_level_text(record) + time_format = None if self.formatter is None else self.formatter.datefmt + log_time = datetime.fromtimestamp(record.created) + + log_renderable = self._log_render( + self.console, + [message_renderable] if not traceback else [message_renderable, traceback], + log_time=log_time, + time_format=time_format, + level=level, + path=path, + line_no=record.lineno, + link_path=record.pathname if self.enable_link_path else None, + ) + return log_renderable + + +if __name__ == "__main__": # pragma: no cover + from time import sleep + + FORMAT = "%(message)s" + # FORMAT = "%(asctime)-15s - %(levelname)s - %(message)s" + logging.basicConfig( + level="NOTSET", + format=FORMAT, + datefmt="[%X]", + handlers=[RichHandler(rich_tracebacks=True, tracebacks_show_locals=True)], + ) + log = logging.getLogger("rich") + + log.info("Server starting...") + log.info("Listening on http://127.0.0.1:8080") + sleep(1) + + log.info("GET /index.html 200 1298") + log.info("GET /imgs/backgrounds/back1.jpg 200 54386") + log.info("GET /css/styles.css 200 54386") + log.warning("GET /favicon.ico 404 242") + sleep(1) + + log.debug( + "JSONRPC request\n--> %r\n<-- %r", + { + "version": "1.1", + "method": "confirmFruitPurchase", + "params": [["apple", "orange", "mangoes", "pomelo"], 1.123], + "id": "194521489", + }, + {"version": "1.1", "result": True, "error": None, "id": "194521489"}, + ) + log.debug( + "Loading configuration file /adasd/asdasd/qeqwe/qwrqwrqwr/sdgsdgsdg/werwerwer/dfgerert/ertertert/ertetert/werwerwer" + ) + log.error("Unable to find 'pomelo' in database!") + log.info("POST /jsonrpc/ 200 65532") + log.info("POST /admin/ 401 42234") + log.warning("password was rejected for admin site.") + + def divide() -> None: + number = 1 + divisor = 0 + foos = ["foo"] * 100 + log.debug("in divide") + try: + number / divisor + except: + log.exception("An error of some kind occurred!") + + divide() + sleep(1) + log.critical("Out of memory!") + log.info("Server exited with code=-1") + log.info("[bold]EXITING...[/bold]", extra=dict(markup=True)) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/markup.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/markup.py new file mode 100644 index 0000000..f617187 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/markup.py @@ -0,0 +1,251 @@ +import re +from ast import literal_eval +from operator import attrgetter +from typing import Callable, Iterable, List, Match, NamedTuple, Optional, Tuple, Union + +from ._emoji_replace import _emoji_replace +from .emoji import EmojiVariant +from .errors import MarkupError +from .style import Style +from .text import Span, Text + +RE_TAGS = re.compile( + r"""((\\*)\[([a-z#/@][^[]*?)])""", + re.VERBOSE, +) + +RE_HANDLER = re.compile(r"^([\w.]*?)(\(.*?\))?$") + + +class Tag(NamedTuple): + """A tag in console markup.""" + + name: str + """The tag name. e.g. 'bold'.""" + parameters: Optional[str] + """Any additional parameters after the name.""" + + def __str__(self) -> str: + return ( + self.name if self.parameters is None else f"{self.name} {self.parameters}" + ) + + @property + def markup(self) -> str: + """Get the string representation of this tag.""" + return ( + f"[{self.name}]" + if self.parameters is None + else f"[{self.name}={self.parameters}]" + ) + + +_ReStringMatch = Match[str] # regex match object +_ReSubCallable = Callable[[_ReStringMatch], str] # Callable invoked by re.sub +_EscapeSubMethod = Callable[[_ReSubCallable, str], str] # Sub method of a compiled re + + +def escape( + markup: str, + _escape: _EscapeSubMethod = re.compile(r"(\\*)(\[[a-z#/@][^[]*?])").sub, +) -> str: + """Escapes text so that it won't be interpreted as markup. + + Args: + markup (str): Content to be inserted in to markup. + + Returns: + str: Markup with square brackets escaped. + """ + + def escape_backslashes(match: Match[str]) -> str: + """Called by re.sub replace matches.""" + backslashes, text = match.groups() + return f"{backslashes}{backslashes}\\{text}" + + markup = _escape(escape_backslashes, markup) + if markup.endswith("\\") and not markup.endswith("\\\\"): + return markup + "\\" + + return markup + + +def _parse(markup: str) -> Iterable[Tuple[int, Optional[str], Optional[Tag]]]: + """Parse markup in to an iterable of tuples of (position, text, tag). + + Args: + markup (str): A string containing console markup + + """ + position = 0 + _divmod = divmod + _Tag = Tag + for match in RE_TAGS.finditer(markup): + full_text, escapes, tag_text = match.groups() + start, end = match.span() + if start > position: + yield start, markup[position:start], None + if escapes: + backslashes, escaped = _divmod(len(escapes), 2) + if backslashes: + # Literal backslashes + yield start, "\\" * backslashes, None + start += backslashes * 2 + if escaped: + # Escape of tag + yield start, full_text[len(escapes) :], None + position = end + continue + text, equals, parameters = tag_text.partition("=") + yield start, None, _Tag(text, parameters if equals else None) + position = end + if position < len(markup): + yield position, markup[position:], None + + +def render( + markup: str, + style: Union[str, Style] = "", + emoji: bool = True, + emoji_variant: Optional[EmojiVariant] = None, +) -> Text: + """Render console markup in to a Text instance. + + Args: + markup (str): A string containing console markup. + style: (Union[str, Style]): The style to use. + emoji (bool, optional): Also render emoji code. Defaults to True. + emoji_variant (str, optional): Optional emoji variant, either "text" or "emoji". Defaults to None. + + + Raises: + MarkupError: If there is a syntax error in the markup. + + Returns: + Text: A test instance. + """ + emoji_replace = _emoji_replace + if "[" not in markup: + return Text( + emoji_replace(markup, default_variant=emoji_variant) if emoji else markup, + style=style, + ) + text = Text(style=style) + append = text.append + normalize = Style.normalize + + style_stack: List[Tuple[int, Tag]] = [] + pop = style_stack.pop + + spans: List[Span] = [] + append_span = spans.append + + _Span = Span + _Tag = Tag + + def pop_style(style_name: str) -> Tuple[int, Tag]: + """Pop tag matching given style name.""" + for index, (_, tag) in enumerate(reversed(style_stack), 1): + if tag.name == style_name: + return pop(-index) + raise KeyError(style_name) + + for position, plain_text, tag in _parse(markup): + if plain_text is not None: + # Handle open brace escapes, where the brace is not part of a tag. + plain_text = plain_text.replace("\\[", "[") + append(emoji_replace(plain_text) if emoji else plain_text) + elif tag is not None: + if tag.name.startswith("/"): # Closing tag + style_name = tag.name[1:].strip() + + if style_name: # explicit close + style_name = normalize(style_name) + try: + start, open_tag = pop_style(style_name) + except KeyError: + raise MarkupError( + f"closing tag '{tag.markup}' at position {position} doesn't match any open tag" + ) from None + else: # implicit close + try: + start, open_tag = pop() + except IndexError: + raise MarkupError( + f"closing tag '[/]' at position {position} has nothing to close" + ) from None + + if open_tag.name.startswith("@"): + if open_tag.parameters: + handler_name = "" + parameters = open_tag.parameters.strip() + handler_match = RE_HANDLER.match(parameters) + if handler_match is not None: + handler_name, match_parameters = handler_match.groups() + parameters = ( + "()" if match_parameters is None else match_parameters + ) + + try: + meta_params = literal_eval(parameters) + except SyntaxError as error: + raise MarkupError( + f"error parsing {parameters!r} in {open_tag.parameters!r}; {error.msg}" + ) + except Exception as error: + raise MarkupError( + f"error parsing {open_tag.parameters!r}; {error}" + ) from None + + if handler_name: + meta_params = ( + handler_name, + meta_params + if isinstance(meta_params, tuple) + else (meta_params,), + ) + + else: + meta_params = () + + append_span( + _Span( + start, len(text), Style(meta={open_tag.name: meta_params}) + ) + ) + else: + append_span(_Span(start, len(text), str(open_tag))) + + else: # Opening tag + normalized_tag = _Tag(normalize(tag.name), tag.parameters) + style_stack.append((len(text), normalized_tag)) + + text_length = len(text) + while style_stack: + start, tag = style_stack.pop() + style = str(tag) + if style: + append_span(_Span(start, text_length, style)) + + text.spans = sorted(spans[::-1], key=attrgetter("start")) + return text + + +if __name__ == "__main__": # pragma: no cover + MARKUP = [ + "[red]Hello World[/red]", + "[magenta]Hello [b]World[/b]", + "[bold]Bold[italic] bold and italic [/bold]italic[/italic]", + "Click [link=https://www.willmcgugan.com]here[/link] to visit my Blog", + ":warning-emoji: [bold red blink] DANGER![/]", + ] + + from pip._vendor.rich import print + from pip._vendor.rich.table import Table + + grid = Table("Markup", "Result", padding=(0, 1)) + + for markup in MARKUP: + grid.add_row(Text(markup), markup) + + print(grid) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/measure.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/measure.py new file mode 100644 index 0000000..a508ffa --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/measure.py @@ -0,0 +1,151 @@ +from operator import itemgetter +from typing import TYPE_CHECKING, Callable, NamedTuple, Optional, Sequence + +from . import errors +from .protocol import is_renderable, rich_cast + +if TYPE_CHECKING: + from .console import Console, ConsoleOptions, RenderableType + + +class Measurement(NamedTuple): + """Stores the minimum and maximum widths (in characters) required to render an object.""" + + minimum: int + """Minimum number of cells required to render.""" + maximum: int + """Maximum number of cells required to render.""" + + @property + def span(self) -> int: + """Get difference between maximum and minimum.""" + return self.maximum - self.minimum + + def normalize(self) -> "Measurement": + """Get measurement that ensures that minimum <= maximum and minimum >= 0 + + Returns: + Measurement: A normalized measurement. + """ + minimum, maximum = self + minimum = min(max(0, minimum), maximum) + return Measurement(max(0, minimum), max(0, max(minimum, maximum))) + + def with_maximum(self, width: int) -> "Measurement": + """Get a RenderableWith where the widths are <= width. + + Args: + width (int): Maximum desired width. + + Returns: + Measurement: New Measurement object. + """ + minimum, maximum = self + return Measurement(min(minimum, width), min(maximum, width)) + + def with_minimum(self, width: int) -> "Measurement": + """Get a RenderableWith where the widths are >= width. + + Args: + width (int): Minimum desired width. + + Returns: + Measurement: New Measurement object. + """ + minimum, maximum = self + width = max(0, width) + return Measurement(max(minimum, width), max(maximum, width)) + + def clamp( + self, min_width: Optional[int] = None, max_width: Optional[int] = None + ) -> "Measurement": + """Clamp a measurement within the specified range. + + Args: + min_width (int): Minimum desired width, or ``None`` for no minimum. Defaults to None. + max_width (int): Maximum desired width, or ``None`` for no maximum. Defaults to None. + + Returns: + Measurement: New Measurement object. + """ + measurement = self + if min_width is not None: + measurement = measurement.with_minimum(min_width) + if max_width is not None: + measurement = measurement.with_maximum(max_width) + return measurement + + @classmethod + def get( + cls, console: "Console", options: "ConsoleOptions", renderable: "RenderableType" + ) -> "Measurement": + """Get a measurement for a renderable. + + Args: + console (~rich.console.Console): Console instance. + options (~rich.console.ConsoleOptions): Console options. + renderable (RenderableType): An object that may be rendered with Rich. + + Raises: + errors.NotRenderableError: If the object is not renderable. + + Returns: + Measurement: Measurement object containing range of character widths required to render the object. + """ + _max_width = options.max_width + if _max_width < 1: + return Measurement(0, 0) + if isinstance(renderable, str): + renderable = console.render_str( + renderable, markup=options.markup, highlight=False + ) + renderable = rich_cast(renderable) + if is_renderable(renderable): + get_console_width: Optional[ + Callable[["Console", "ConsoleOptions"], "Measurement"] + ] = getattr(renderable, "__rich_measure__", None) + if get_console_width is not None: + render_width = ( + get_console_width(console, options) + .normalize() + .with_maximum(_max_width) + ) + if render_width.maximum < 1: + return Measurement(0, 0) + return render_width.normalize() + else: + return Measurement(0, _max_width) + else: + raise errors.NotRenderableError( + f"Unable to get render width for {renderable!r}; " + "a str, Segment, or object with __rich_console__ method is required" + ) + + +def measure_renderables( + console: "Console", + options: "ConsoleOptions", + renderables: Sequence["RenderableType"], +) -> "Measurement": + """Get a measurement that would fit a number of renderables. + + Args: + console (~rich.console.Console): Console instance. + options (~rich.console.ConsoleOptions): Console options. + renderables (Iterable[RenderableType]): One or more renderable objects. + + Returns: + Measurement: Measurement object containing range of character widths required to + contain all given renderables. + """ + if not renderables: + return Measurement(0, 0) + get_measurement = Measurement.get + measurements = [ + get_measurement(console, options, renderable) for renderable in renderables + ] + measured_width = Measurement( + max(measurements, key=itemgetter(0)).minimum, + max(measurements, key=itemgetter(1)).maximum, + ) + return measured_width diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/padding.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/padding.py new file mode 100644 index 0000000..1b2204f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/padding.py @@ -0,0 +1,141 @@ +from typing import cast, List, Optional, Tuple, TYPE_CHECKING, Union + +if TYPE_CHECKING: + from .console import ( + Console, + ConsoleOptions, + RenderableType, + RenderResult, + ) +from .jupyter import JupyterMixin +from .measure import Measurement +from .style import Style +from .segment import Segment + + +PaddingDimensions = Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int, int]] + + +class Padding(JupyterMixin): + """Draw space around content. + + Example: + >>> print(Padding("Hello", (2, 4), style="on blue")) + + Args: + renderable (RenderableType): String or other renderable. + pad (Union[int, Tuple[int]]): Padding for top, right, bottom, and left borders. + May be specified with 1, 2, or 4 integers (CSS style). + style (Union[str, Style], optional): Style for padding characters. Defaults to "none". + expand (bool, optional): Expand padding to fit available width. Defaults to True. + """ + + def __init__( + self, + renderable: "RenderableType", + pad: "PaddingDimensions" = (0, 0, 0, 0), + *, + style: Union[str, Style] = "none", + expand: bool = True, + ): + self.renderable = renderable + self.top, self.right, self.bottom, self.left = self.unpack(pad) + self.style = style + self.expand = expand + + @classmethod + def indent(cls, renderable: "RenderableType", level: int) -> "Padding": + """Make padding instance to render an indent. + + Args: + renderable (RenderableType): String or other renderable. + level (int): Number of characters to indent. + + Returns: + Padding: A Padding instance. + """ + + return Padding(renderable, pad=(0, 0, 0, level), expand=False) + + @staticmethod + def unpack(pad: "PaddingDimensions") -> Tuple[int, int, int, int]: + """Unpack padding specified in CSS style.""" + if isinstance(pad, int): + return (pad, pad, pad, pad) + if len(pad) == 1: + _pad = pad[0] + return (_pad, _pad, _pad, _pad) + if len(pad) == 2: + pad_top, pad_right = cast(Tuple[int, int], pad) + return (pad_top, pad_right, pad_top, pad_right) + if len(pad) == 4: + top, right, bottom, left = cast(Tuple[int, int, int, int], pad) + return (top, right, bottom, left) + raise ValueError(f"1, 2 or 4 integers required for padding; {len(pad)} given") + + def __repr__(self) -> str: + return f"Padding({self.renderable!r}, ({self.top},{self.right},{self.bottom},{self.left}))" + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + style = console.get_style(self.style) + if self.expand: + width = options.max_width + else: + width = min( + Measurement.get(console, options, self.renderable).maximum + + self.left + + self.right, + options.max_width, + ) + render_options = options.update_width(width - self.left - self.right) + if render_options.height is not None: + render_options = render_options.update_height( + height=render_options.height - self.top - self.bottom + ) + lines = console.render_lines( + self.renderable, render_options, style=style, pad=True + ) + _Segment = Segment + + left = _Segment(" " * self.left, style) if self.left else None + right = ( + [_Segment(f'{" " * self.right}', style), _Segment.line()] + if self.right + else [_Segment.line()] + ) + blank_line: Optional[List[Segment]] = None + if self.top: + blank_line = [_Segment(f'{" " * width}\n', style)] + yield from blank_line * self.top + if left: + for line in lines: + yield left + yield from line + yield from right + else: + for line in lines: + yield from line + yield from right + if self.bottom: + blank_line = blank_line or [_Segment(f'{" " * width}\n', style)] + yield from blank_line * self.bottom + + def __rich_measure__( + self, console: "Console", options: "ConsoleOptions" + ) -> "Measurement": + max_width = options.max_width + extra_width = self.left + self.right + if max_width - extra_width < 1: + return Measurement(max_width, max_width) + measure_min, measure_max = Measurement.get(console, options, self.renderable) + measurement = Measurement(measure_min + extra_width, measure_max + extra_width) + measurement = measurement.with_maximum(max_width) + return measurement + + +if __name__ == "__main__": # pragma: no cover + from pip._vendor.rich import print + + print(Padding("Hello, World", (2, 4), style="on blue")) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/pager.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/pager.py new file mode 100644 index 0000000..a3f7aa6 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/pager.py @@ -0,0 +1,34 @@ +from abc import ABC, abstractmethod +from typing import Any + + +class Pager(ABC): + """Base class for a pager.""" + + @abstractmethod + def show(self, content: str) -> None: + """Show content in pager. + + Args: + content (str): Content to be displayed. + """ + + +class SystemPager(Pager): + """Uses the pager installed on the system.""" + + def _pager(self, content: str) -> Any: #  pragma: no cover + return __import__("pydoc").pager(content) + + def show(self, content: str) -> None: + """Use the same pager used by pydoc.""" + self._pager(content) + + +if __name__ == "__main__": # pragma: no cover + from .__main__ import make_test_card + from .console import Console + + console = Console() + with console.pager(styles=True): + console.print(make_test_card()) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/palette.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/palette.py new file mode 100644 index 0000000..fa0c4dd --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/palette.py @@ -0,0 +1,100 @@ +from math import sqrt +from functools import lru_cache +from typing import Sequence, Tuple, TYPE_CHECKING + +from .color_triplet import ColorTriplet + +if TYPE_CHECKING: + from pip._vendor.rich.table import Table + + +class Palette: + """A palette of available colors.""" + + def __init__(self, colors: Sequence[Tuple[int, int, int]]): + self._colors = colors + + def __getitem__(self, number: int) -> ColorTriplet: + return ColorTriplet(*self._colors[number]) + + def __rich__(self) -> "Table": + from pip._vendor.rich.color import Color + from pip._vendor.rich.style import Style + from pip._vendor.rich.text import Text + from pip._vendor.rich.table import Table + + table = Table( + "index", + "RGB", + "Color", + title="Palette", + caption=f"{len(self._colors)} colors", + highlight=True, + caption_justify="right", + ) + for index, color in enumerate(self._colors): + table.add_row( + str(index), + repr(color), + Text(" " * 16, style=Style(bgcolor=Color.from_rgb(*color))), + ) + return table + + # This is somewhat inefficient and needs caching + @lru_cache(maxsize=1024) + def match(self, color: Tuple[int, int, int]) -> int: + """Find a color from a palette that most closely matches a given color. + + Args: + color (Tuple[int, int, int]): RGB components in range 0 > 255. + + Returns: + int: Index of closes matching color. + """ + red1, green1, blue1 = color + _sqrt = sqrt + get_color = self._colors.__getitem__ + + def get_color_distance(index: int) -> float: + """Get the distance to a color.""" + red2, green2, blue2 = get_color(index) + red_mean = (red1 + red2) // 2 + red = red1 - red2 + green = green1 - green2 + blue = blue1 - blue2 + return _sqrt( + (((512 + red_mean) * red * red) >> 8) + + 4 * green * green + + (((767 - red_mean) * blue * blue) >> 8) + ) + + min_index = min(range(len(self._colors)), key=get_color_distance) + return min_index + + +if __name__ == "__main__": # pragma: no cover + import colorsys + from typing import Iterable + from pip._vendor.rich.color import Color + from pip._vendor.rich.console import Console, ConsoleOptions + from pip._vendor.rich.segment import Segment + from pip._vendor.rich.style import Style + + class ColorBox: + def __rich_console__( + self, console: Console, options: ConsoleOptions + ) -> Iterable[Segment]: + height = console.size.height - 3 + for y in range(0, height): + for x in range(options.max_width): + h = x / options.max_width + l = y / (height + 1) + r1, g1, b1 = colorsys.hls_to_rgb(h, l, 1.0) + r2, g2, b2 = colorsys.hls_to_rgb(h, l + (1 / height / 2), 1.0) + bgcolor = Color.from_rgb(r1 * 255, g1 * 255, b1 * 255) + color = Color.from_rgb(r2 * 255, g2 * 255, b2 * 255) + yield Segment("▄", Style(color=color, bgcolor=bgcolor)) + yield Segment.line() + + console = Console() + console.print(ColorBox()) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/panel.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/panel.py new file mode 100644 index 0000000..95f4c84 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/panel.py @@ -0,0 +1,312 @@ +from typing import TYPE_CHECKING, Optional + +from .align import AlignMethod +from .box import ROUNDED, Box +from .cells import cell_len +from .jupyter import JupyterMixin +from .measure import Measurement, measure_renderables +from .padding import Padding, PaddingDimensions +from .segment import Segment +from .style import Style, StyleType +from .text import Text, TextType + +if TYPE_CHECKING: + from .console import Console, ConsoleOptions, RenderableType, RenderResult + + +class Panel(JupyterMixin): + """A console renderable that draws a border around its contents. + + Example: + >>> console.print(Panel("Hello, World!")) + + Args: + renderable (RenderableType): A console renderable object. + box (Box, optional): A Box instance that defines the look of the border (see :ref:`appendix_box`. + Defaults to box.ROUNDED. + safe_box (bool, optional): Disable box characters that don't display on windows legacy terminal with *raster* fonts. Defaults to True. + expand (bool, optional): If True the panel will stretch to fill the console + width, otherwise it will be sized to fit the contents. Defaults to True. + style (str, optional): The style of the panel (border and contents). Defaults to "none". + border_style (str, optional): The style of the border. Defaults to "none". + width (Optional[int], optional): Optional width of panel. Defaults to None to auto-detect. + height (Optional[int], optional): Optional height of panel. Defaults to None to auto-detect. + padding (Optional[PaddingDimensions]): Optional padding around renderable. Defaults to 0. + highlight (bool, optional): Enable automatic highlighting of panel title (if str). Defaults to False. + """ + + def __init__( + self, + renderable: "RenderableType", + box: Box = ROUNDED, + *, + title: Optional[TextType] = None, + title_align: AlignMethod = "center", + subtitle: Optional[TextType] = None, + subtitle_align: AlignMethod = "center", + safe_box: Optional[bool] = None, + expand: bool = True, + style: StyleType = "none", + border_style: StyleType = "none", + width: Optional[int] = None, + height: Optional[int] = None, + padding: PaddingDimensions = (0, 1), + highlight: bool = False, + ) -> None: + self.renderable = renderable + self.box = box + self.title = title + self.title_align: AlignMethod = title_align + self.subtitle = subtitle + self.subtitle_align = subtitle_align + self.safe_box = safe_box + self.expand = expand + self.style = style + self.border_style = border_style + self.width = width + self.height = height + self.padding = padding + self.highlight = highlight + + @classmethod + def fit( + cls, + renderable: "RenderableType", + box: Box = ROUNDED, + *, + title: Optional[TextType] = None, + title_align: AlignMethod = "center", + subtitle: Optional[TextType] = None, + subtitle_align: AlignMethod = "center", + safe_box: Optional[bool] = None, + style: StyleType = "none", + border_style: StyleType = "none", + width: Optional[int] = None, + height: Optional[int] = None, + padding: PaddingDimensions = (0, 1), + highlight: bool = False, + ) -> "Panel": + """An alternative constructor that sets expand=False.""" + return cls( + renderable, + box, + title=title, + title_align=title_align, + subtitle=subtitle, + subtitle_align=subtitle_align, + safe_box=safe_box, + style=style, + border_style=border_style, + width=width, + height=height, + padding=padding, + highlight=highlight, + expand=False, + ) + + @property + def _title(self) -> Optional[Text]: + if self.title: + title_text = ( + Text.from_markup(self.title) + if isinstance(self.title, str) + else self.title.copy() + ) + title_text.end = "" + title_text.plain = title_text.plain.replace("\n", " ") + title_text.no_wrap = True + title_text.expand_tabs() + title_text.pad(1) + return title_text + return None + + @property + def _subtitle(self) -> Optional[Text]: + if self.subtitle: + subtitle_text = ( + Text.from_markup(self.subtitle) + if isinstance(self.subtitle, str) + else self.subtitle.copy() + ) + subtitle_text.end = "" + subtitle_text.plain = subtitle_text.plain.replace("\n", " ") + subtitle_text.no_wrap = True + subtitle_text.expand_tabs() + subtitle_text.pad(1) + return subtitle_text + return None + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + _padding = Padding.unpack(self.padding) + renderable = ( + Padding(self.renderable, _padding) if any(_padding) else self.renderable + ) + style = console.get_style(self.style) + border_style = style + console.get_style(self.border_style) + width = ( + options.max_width + if self.width is None + else min(options.max_width, self.width) + ) + + safe_box: bool = console.safe_box if self.safe_box is None else self.safe_box + box = self.box.substitute(options, safe=safe_box) + + def align_text( + text: Text, width: int, align: str, character: str, style: Style + ) -> Text: + """Gets new aligned text. + + Args: + text (Text): Title or subtitle text. + width (int): Desired width. + align (str): Alignment. + character (str): Character for alignment. + style (Style): Border style + + Returns: + Text: New text instance + """ + text = text.copy() + text.truncate(width) + excess_space = width - cell_len(text.plain) + if excess_space: + if align == "left": + return Text.assemble( + text, + (character * excess_space, style), + no_wrap=True, + end="", + ) + elif align == "center": + left = excess_space // 2 + return Text.assemble( + (character * left, style), + text, + (character * (excess_space - left), style), + no_wrap=True, + end="", + ) + else: + return Text.assemble( + (character * excess_space, style), + text, + no_wrap=True, + end="", + ) + return text + + title_text = self._title + if title_text is not None: + title_text.stylize_before(border_style) + + child_width = ( + width - 2 + if self.expand + else console.measure( + renderable, options=options.update_width(width - 2) + ).maximum + ) + child_height = self.height or options.height or None + if child_height: + child_height -= 2 + if title_text is not None: + child_width = min( + options.max_width - 2, max(child_width, title_text.cell_len + 2) + ) + + width = child_width + 2 + child_options = options.update( + width=child_width, height=child_height, highlight=self.highlight + ) + lines = console.render_lines(renderable, child_options, style=style) + + line_start = Segment(box.mid_left, border_style) + line_end = Segment(f"{box.mid_right}", border_style) + new_line = Segment.line() + if title_text is None or width <= 4: + yield Segment(box.get_top([width - 2]), border_style) + else: + title_text = align_text( + title_text, + width - 4, + self.title_align, + box.top, + border_style, + ) + yield Segment(box.top_left + box.top, border_style) + yield from console.render(title_text, child_options.update_width(width - 4)) + yield Segment(box.top + box.top_right, border_style) + + yield new_line + for line in lines: + yield line_start + yield from line + yield line_end + yield new_line + + subtitle_text = self._subtitle + if subtitle_text is not None: + subtitle_text.stylize_before(border_style) + + if subtitle_text is None or width <= 4: + yield Segment(box.get_bottom([width - 2]), border_style) + else: + subtitle_text = align_text( + subtitle_text, + width - 4, + self.subtitle_align, + box.bottom, + border_style, + ) + yield Segment(box.bottom_left + box.bottom, border_style) + yield from console.render( + subtitle_text, child_options.update_width(width - 4) + ) + yield Segment(box.bottom + box.bottom_right, border_style) + + yield new_line + + def __rich_measure__( + self, console: "Console", options: "ConsoleOptions" + ) -> "Measurement": + _title = self._title + _, right, _, left = Padding.unpack(self.padding) + padding = left + right + renderables = [self.renderable, _title] if _title else [self.renderable] + + if self.width is None: + width = ( + measure_renderables( + console, + options.update_width(options.max_width - padding - 2), + renderables, + ).maximum + + padding + + 2 + ) + else: + width = self.width + return Measurement(width, width) + + +if __name__ == "__main__": # pragma: no cover + from .console import Console + + c = Console() + + from .box import DOUBLE, ROUNDED + from .padding import Padding + + p = Panel( + "Hello, World!", + title="rich.Panel", + style="white on blue", + box=DOUBLE, + padding=1, + ) + + c.print() + c.print(p) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/pretty.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/pretty.py new file mode 100644 index 0000000..9b9e3ba --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/pretty.py @@ -0,0 +1,995 @@ +import builtins +import collections +import dataclasses +import inspect +import os +import sys +from array import array +from collections import Counter, UserDict, UserList, defaultdict, deque +from dataclasses import dataclass, fields, is_dataclass +from inspect import isclass +from itertools import islice +from types import MappingProxyType +from typing import ( + TYPE_CHECKING, + Any, + Callable, + DefaultDict, + Dict, + Iterable, + List, + Optional, + Sequence, + Set, + Tuple, + Union, +) + +from pip._vendor.rich.repr import RichReprResult + +try: + import attr as _attr_module + + _has_attrs = hasattr(_attr_module, "ib") +except ImportError: # pragma: no cover + _has_attrs = False + +from . import get_console +from ._loop import loop_last +from ._pick import pick_bool +from .abc import RichRenderable +from .cells import cell_len +from .highlighter import ReprHighlighter +from .jupyter import JupyterMixin, JupyterRenderable +from .measure import Measurement +from .text import Text + +if TYPE_CHECKING: + from .console import ( + Console, + ConsoleOptions, + HighlighterType, + JustifyMethod, + OverflowMethod, + RenderResult, + ) + + +def _is_attr_object(obj: Any) -> bool: + """Check if an object was created with attrs module.""" + return _has_attrs and _attr_module.has(type(obj)) + + +def _get_attr_fields(obj: Any) -> Sequence["_attr_module.Attribute[Any]"]: + """Get fields for an attrs object.""" + return _attr_module.fields(type(obj)) if _has_attrs else [] + + +def _is_dataclass_repr(obj: object) -> bool: + """Check if an instance of a dataclass contains the default repr. + + Args: + obj (object): A dataclass instance. + + Returns: + bool: True if the default repr is used, False if there is a custom repr. + """ + # Digging in to a lot of internals here + # Catching all exceptions in case something is missing on a non CPython implementation + try: + return obj.__repr__.__code__.co_filename == dataclasses.__file__ + except Exception: # pragma: no coverage + return False + + +_dummy_namedtuple = collections.namedtuple("_dummy_namedtuple", []) + + +def _has_default_namedtuple_repr(obj: object) -> bool: + """Check if an instance of namedtuple contains the default repr + + Args: + obj (object): A namedtuple + + Returns: + bool: True if the default repr is used, False if there's a custom repr. + """ + obj_file = None + try: + obj_file = inspect.getfile(obj.__repr__) + except (OSError, TypeError): + # OSError handles case where object is defined in __main__ scope, e.g. REPL - no filename available. + # TypeError trapped defensively, in case of object without filename slips through. + pass + default_repr_file = inspect.getfile(_dummy_namedtuple.__repr__) + return obj_file == default_repr_file + + +def _ipy_display_hook( + value: Any, + console: Optional["Console"] = None, + overflow: "OverflowMethod" = "ignore", + crop: bool = False, + indent_guides: bool = False, + max_length: Optional[int] = None, + max_string: Optional[int] = None, + max_depth: Optional[int] = None, + expand_all: bool = False, +) -> Union[str, None]: + # needed here to prevent circular import: + from .console import ConsoleRenderable + + # always skip rich generated jupyter renderables or None values + if _safe_isinstance(value, JupyterRenderable) or value is None: + return None + + console = console or get_console() + + with console.capture() as capture: + # certain renderables should start on a new line + if _safe_isinstance(value, ConsoleRenderable): + console.line() + console.print( + value + if _safe_isinstance(value, RichRenderable) + else Pretty( + value, + overflow=overflow, + indent_guides=indent_guides, + max_length=max_length, + max_string=max_string, + max_depth=max_depth, + expand_all=expand_all, + margin=12, + ), + crop=crop, + new_line_start=True, + end="", + ) + # strip trailing newline, not usually part of a text repr + # I'm not sure if this should be prevented at a lower level + return capture.get().rstrip("\n") + + +def _safe_isinstance( + obj: object, class_or_tuple: Union[type, Tuple[type, ...]] +) -> bool: + """isinstance can fail in rare cases, for example types with no __class__""" + try: + return isinstance(obj, class_or_tuple) + except Exception: + return False + + +def install( + console: Optional["Console"] = None, + overflow: "OverflowMethod" = "ignore", + crop: bool = False, + indent_guides: bool = False, + max_length: Optional[int] = None, + max_string: Optional[int] = None, + max_depth: Optional[int] = None, + expand_all: bool = False, +) -> None: + """Install automatic pretty printing in the Python REPL. + + Args: + console (Console, optional): Console instance or ``None`` to use global console. Defaults to None. + overflow (Optional[OverflowMethod], optional): Overflow method. Defaults to "ignore". + crop (Optional[bool], optional): Enable cropping of long lines. Defaults to False. + indent_guides (bool, optional): Enable indentation guides. Defaults to False. + max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation. + Defaults to None. + max_string (int, optional): Maximum length of string before truncating, or None to disable. Defaults to None. + max_depth (int, optional): Maximum depth of nested data structures, or None for no maximum. Defaults to None. + expand_all (bool, optional): Expand all containers. Defaults to False. + max_frames (int): Maximum number of frames to show in a traceback, 0 for no maximum. Defaults to 100. + """ + from pip._vendor.rich import get_console + + console = console or get_console() + assert console is not None + + def display_hook(value: Any) -> None: + """Replacement sys.displayhook which prettifies objects with Rich.""" + if value is not None: + assert console is not None + builtins._ = None # type: ignore[attr-defined] + console.print( + value + if _safe_isinstance(value, RichRenderable) + else Pretty( + value, + overflow=overflow, + indent_guides=indent_guides, + max_length=max_length, + max_string=max_string, + max_depth=max_depth, + expand_all=expand_all, + ), + crop=crop, + ) + builtins._ = value # type: ignore[attr-defined] + + try: + ip = get_ipython() # type: ignore[name-defined] + except NameError: + sys.displayhook = display_hook + else: + from IPython.core.formatters import BaseFormatter + + class RichFormatter(BaseFormatter): # type: ignore[misc] + pprint: bool = True + + def __call__(self, value: Any) -> Any: + if self.pprint: + return _ipy_display_hook( + value, + console=get_console(), + overflow=overflow, + indent_guides=indent_guides, + max_length=max_length, + max_string=max_string, + max_depth=max_depth, + expand_all=expand_all, + ) + else: + return repr(value) + + # replace plain text formatter with rich formatter + rich_formatter = RichFormatter() + ip.display_formatter.formatters["text/plain"] = rich_formatter + + +class Pretty(JupyterMixin): + """A rich renderable that pretty prints an object. + + Args: + _object (Any): An object to pretty print. + highlighter (HighlighterType, optional): Highlighter object to apply to result, or None for ReprHighlighter. Defaults to None. + indent_size (int, optional): Number of spaces in indent. Defaults to 4. + justify (JustifyMethod, optional): Justify method, or None for default. Defaults to None. + overflow (OverflowMethod, optional): Overflow method, or None for default. Defaults to None. + no_wrap (Optional[bool], optional): Disable word wrapping. Defaults to False. + indent_guides (bool, optional): Enable indentation guides. Defaults to False. + max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation. + Defaults to None. + max_string (int, optional): Maximum length of string before truncating, or None to disable. Defaults to None. + max_depth (int, optional): Maximum depth of nested data structures, or None for no maximum. Defaults to None. + expand_all (bool, optional): Expand all containers. Defaults to False. + margin (int, optional): Subtrace a margin from width to force containers to expand earlier. Defaults to 0. + insert_line (bool, optional): Insert a new line if the output has multiple new lines. Defaults to False. + """ + + def __init__( + self, + _object: Any, + highlighter: Optional["HighlighterType"] = None, + *, + indent_size: int = 4, + justify: Optional["JustifyMethod"] = None, + overflow: Optional["OverflowMethod"] = None, + no_wrap: Optional[bool] = False, + indent_guides: bool = False, + max_length: Optional[int] = None, + max_string: Optional[int] = None, + max_depth: Optional[int] = None, + expand_all: bool = False, + margin: int = 0, + insert_line: bool = False, + ) -> None: + self._object = _object + self.highlighter = highlighter or ReprHighlighter() + self.indent_size = indent_size + self.justify: Optional["JustifyMethod"] = justify + self.overflow: Optional["OverflowMethod"] = overflow + self.no_wrap = no_wrap + self.indent_guides = indent_guides + self.max_length = max_length + self.max_string = max_string + self.max_depth = max_depth + self.expand_all = expand_all + self.margin = margin + self.insert_line = insert_line + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + pretty_str = pretty_repr( + self._object, + max_width=options.max_width - self.margin, + indent_size=self.indent_size, + max_length=self.max_length, + max_string=self.max_string, + max_depth=self.max_depth, + expand_all=self.expand_all, + ) + pretty_text = Text.from_ansi( + pretty_str, + justify=self.justify or options.justify, + overflow=self.overflow or options.overflow, + no_wrap=pick_bool(self.no_wrap, options.no_wrap), + style="pretty", + ) + pretty_text = ( + self.highlighter(pretty_text) + if pretty_text + else Text( + f"{type(self._object)}.__repr__ returned empty string", + style="dim italic", + ) + ) + if self.indent_guides and not options.ascii_only: + pretty_text = pretty_text.with_indent_guides( + self.indent_size, style="repr.indent" + ) + if self.insert_line and "\n" in pretty_text: + yield "" + yield pretty_text + + def __rich_measure__( + self, console: "Console", options: "ConsoleOptions" + ) -> "Measurement": + pretty_str = pretty_repr( + self._object, + max_width=options.max_width, + indent_size=self.indent_size, + max_length=self.max_length, + max_string=self.max_string, + max_depth=self.max_depth, + expand_all=self.expand_all, + ) + text_width = ( + max(cell_len(line) for line in pretty_str.splitlines()) if pretty_str else 0 + ) + return Measurement(text_width, text_width) + + +def _get_braces_for_defaultdict(_object: DefaultDict[Any, Any]) -> Tuple[str, str, str]: + return ( + f"defaultdict({_object.default_factory!r}, {{", + "})", + f"defaultdict({_object.default_factory!r}, {{}})", + ) + + +def _get_braces_for_array(_object: "array[Any]") -> Tuple[str, str, str]: + return (f"array({_object.typecode!r}, [", "])", f"array({_object.typecode!r})") + + +_BRACES: Dict[type, Callable[[Any], Tuple[str, str, str]]] = { + os._Environ: lambda _object: ("environ({", "})", "environ({})"), + array: _get_braces_for_array, + defaultdict: _get_braces_for_defaultdict, + Counter: lambda _object: ("Counter({", "})", "Counter()"), + deque: lambda _object: ("deque([", "])", "deque()"), + dict: lambda _object: ("{", "}", "{}"), + UserDict: lambda _object: ("{", "}", "{}"), + frozenset: lambda _object: ("frozenset({", "})", "frozenset()"), + list: lambda _object: ("[", "]", "[]"), + UserList: lambda _object: ("[", "]", "[]"), + set: lambda _object: ("{", "}", "set()"), + tuple: lambda _object: ("(", ")", "()"), + MappingProxyType: lambda _object: ("mappingproxy({", "})", "mappingproxy({})"), +} +_CONTAINERS = tuple(_BRACES.keys()) +_MAPPING_CONTAINERS = (dict, os._Environ, MappingProxyType, UserDict) + + +def is_expandable(obj: Any) -> bool: + """Check if an object may be expanded by pretty print.""" + return ( + _safe_isinstance(obj, _CONTAINERS) + or (is_dataclass(obj)) + or (hasattr(obj, "__rich_repr__")) + or _is_attr_object(obj) + ) and not isclass(obj) + + +@dataclass +class Node: + """A node in a repr tree. May be atomic or a container.""" + + key_repr: str = "" + value_repr: str = "" + open_brace: str = "" + close_brace: str = "" + empty: str = "" + last: bool = False + is_tuple: bool = False + is_namedtuple: bool = False + children: Optional[List["Node"]] = None + key_separator: str = ": " + separator: str = ", " + + def iter_tokens(self) -> Iterable[str]: + """Generate tokens for this node.""" + if self.key_repr: + yield self.key_repr + yield self.key_separator + if self.value_repr: + yield self.value_repr + elif self.children is not None: + if self.children: + yield self.open_brace + if self.is_tuple and not self.is_namedtuple and len(self.children) == 1: + yield from self.children[0].iter_tokens() + yield "," + else: + for child in self.children: + yield from child.iter_tokens() + if not child.last: + yield self.separator + yield self.close_brace + else: + yield self.empty + + def check_length(self, start_length: int, max_length: int) -> bool: + """Check the length fits within a limit. + + Args: + start_length (int): Starting length of the line (indent, prefix, suffix). + max_length (int): Maximum length. + + Returns: + bool: True if the node can be rendered within max length, otherwise False. + """ + total_length = start_length + for token in self.iter_tokens(): + total_length += cell_len(token) + if total_length > max_length: + return False + return True + + def __str__(self) -> str: + repr_text = "".join(self.iter_tokens()) + return repr_text + + def render( + self, max_width: int = 80, indent_size: int = 4, expand_all: bool = False + ) -> str: + """Render the node to a pretty repr. + + Args: + max_width (int, optional): Maximum width of the repr. Defaults to 80. + indent_size (int, optional): Size of indents. Defaults to 4. + expand_all (bool, optional): Expand all levels. Defaults to False. + + Returns: + str: A repr string of the original object. + """ + lines = [_Line(node=self, is_root=True)] + line_no = 0 + while line_no < len(lines): + line = lines[line_no] + if line.expandable and not line.expanded: + if expand_all or not line.check_length(max_width): + lines[line_no : line_no + 1] = line.expand(indent_size) + line_no += 1 + + repr_str = "\n".join(str(line) for line in lines) + return repr_str + + +@dataclass +class _Line: + """A line in repr output.""" + + parent: Optional["_Line"] = None + is_root: bool = False + node: Optional[Node] = None + text: str = "" + suffix: str = "" + whitespace: str = "" + expanded: bool = False + last: bool = False + + @property + def expandable(self) -> bool: + """Check if the line may be expanded.""" + return bool(self.node is not None and self.node.children) + + def check_length(self, max_length: int) -> bool: + """Check this line fits within a given number of cells.""" + start_length = ( + len(self.whitespace) + cell_len(self.text) + cell_len(self.suffix) + ) + assert self.node is not None + return self.node.check_length(start_length, max_length) + + def expand(self, indent_size: int) -> Iterable["_Line"]: + """Expand this line by adding children on their own line.""" + node = self.node + assert node is not None + whitespace = self.whitespace + assert node.children + if node.key_repr: + new_line = yield _Line( + text=f"{node.key_repr}{node.key_separator}{node.open_brace}", + whitespace=whitespace, + ) + else: + new_line = yield _Line(text=node.open_brace, whitespace=whitespace) + child_whitespace = self.whitespace + " " * indent_size + tuple_of_one = node.is_tuple and len(node.children) == 1 + for last, child in loop_last(node.children): + separator = "," if tuple_of_one else node.separator + line = _Line( + parent=new_line, + node=child, + whitespace=child_whitespace, + suffix=separator, + last=last and not tuple_of_one, + ) + yield line + + yield _Line( + text=node.close_brace, + whitespace=whitespace, + suffix=self.suffix, + last=self.last, + ) + + def __str__(self) -> str: + if self.last: + return f"{self.whitespace}{self.text}{self.node or ''}" + else: + return ( + f"{self.whitespace}{self.text}{self.node or ''}{self.suffix.rstrip()}" + ) + + +def _is_namedtuple(obj: Any) -> bool: + """Checks if an object is most likely a namedtuple. It is possible + to craft an object that passes this check and isn't a namedtuple, but + there is only a minuscule chance of this happening unintentionally. + + Args: + obj (Any): The object to test + + Returns: + bool: True if the object is a namedtuple. False otherwise. + """ + try: + fields = getattr(obj, "_fields", None) + except Exception: + # Being very defensive - if we cannot get the attr then its not a namedtuple + return False + return isinstance(obj, tuple) and isinstance(fields, tuple) + + +def traverse( + _object: Any, + max_length: Optional[int] = None, + max_string: Optional[int] = None, + max_depth: Optional[int] = None, +) -> Node: + """Traverse object and generate a tree. + + Args: + _object (Any): Object to be traversed. + max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation. + Defaults to None. + max_string (int, optional): Maximum length of string before truncating, or None to disable truncating. + Defaults to None. + max_depth (int, optional): Maximum depth of data structures, or None for no maximum. + Defaults to None. + + Returns: + Node: The root of a tree structure which can be used to render a pretty repr. + """ + + def to_repr(obj: Any) -> str: + """Get repr string for an object, but catch errors.""" + if ( + max_string is not None + and _safe_isinstance(obj, (bytes, str)) + and len(obj) > max_string + ): + truncated = len(obj) - max_string + obj_repr = f"{obj[:max_string]!r}+{truncated}" + else: + try: + obj_repr = repr(obj) + except Exception as error: + obj_repr = f"" + return obj_repr + + visited_ids: Set[int] = set() + push_visited = visited_ids.add + pop_visited = visited_ids.remove + + def _traverse(obj: Any, root: bool = False, depth: int = 0) -> Node: + """Walk the object depth first.""" + + obj_id = id(obj) + if obj_id in visited_ids: + # Recursion detected + return Node(value_repr="...") + + obj_type = type(obj) + children: List[Node] + reached_max_depth = max_depth is not None and depth >= max_depth + + def iter_rich_args(rich_args: Any) -> Iterable[Union[Any, Tuple[str, Any]]]: + for arg in rich_args: + if _safe_isinstance(arg, tuple): + if len(arg) == 3: + key, child, default = arg + if default == child: + continue + yield key, child + elif len(arg) == 2: + key, child = arg + yield key, child + elif len(arg) == 1: + yield arg[0] + else: + yield arg + + try: + fake_attributes = hasattr( + obj, "awehoi234_wdfjwljet234_234wdfoijsdfmmnxpi492" + ) + except Exception: + fake_attributes = False + + rich_repr_result: Optional[RichReprResult] = None + if not fake_attributes: + try: + if hasattr(obj, "__rich_repr__") and not isclass(obj): + rich_repr_result = obj.__rich_repr__() + except Exception: + pass + + if rich_repr_result is not None: + push_visited(obj_id) + angular = getattr(obj.__rich_repr__, "angular", False) + args = list(iter_rich_args(rich_repr_result)) + class_name = obj.__class__.__name__ + + if args: + children = [] + append = children.append + + if reached_max_depth: + if angular: + node = Node(value_repr=f"<{class_name}...>") + else: + node = Node(value_repr=f"{class_name}(...)") + else: + if angular: + node = Node( + open_brace=f"<{class_name} ", + close_brace=">", + children=children, + last=root, + separator=" ", + ) + else: + node = Node( + open_brace=f"{class_name}(", + close_brace=")", + children=children, + last=root, + ) + for last, arg in loop_last(args): + if _safe_isinstance(arg, tuple): + key, child = arg + child_node = _traverse(child, depth=depth + 1) + child_node.last = last + child_node.key_repr = key + child_node.key_separator = "=" + append(child_node) + else: + child_node = _traverse(arg, depth=depth + 1) + child_node.last = last + append(child_node) + else: + node = Node( + value_repr=f"<{class_name}>" if angular else f"{class_name}()", + children=[], + last=root, + ) + pop_visited(obj_id) + elif _is_attr_object(obj) and not fake_attributes: + push_visited(obj_id) + children = [] + append = children.append + + attr_fields = _get_attr_fields(obj) + if attr_fields: + if reached_max_depth: + node = Node(value_repr=f"{obj.__class__.__name__}(...)") + else: + node = Node( + open_brace=f"{obj.__class__.__name__}(", + close_brace=")", + children=children, + last=root, + ) + + def iter_attrs() -> ( + Iterable[Tuple[str, Any, Optional[Callable[[Any], str]]]] + ): + """Iterate over attr fields and values.""" + for attr in attr_fields: + if attr.repr: + try: + value = getattr(obj, attr.name) + except Exception as error: + # Can happen, albeit rarely + yield (attr.name, error, None) + else: + yield ( + attr.name, + value, + attr.repr if callable(attr.repr) else None, + ) + + for last, (name, value, repr_callable) in loop_last(iter_attrs()): + if repr_callable: + child_node = Node(value_repr=str(repr_callable(value))) + else: + child_node = _traverse(value, depth=depth + 1) + child_node.last = last + child_node.key_repr = name + child_node.key_separator = "=" + append(child_node) + else: + node = Node( + value_repr=f"{obj.__class__.__name__}()", children=[], last=root + ) + pop_visited(obj_id) + elif ( + is_dataclass(obj) + and not _safe_isinstance(obj, type) + and not fake_attributes + and _is_dataclass_repr(obj) + ): + push_visited(obj_id) + children = [] + append = children.append + if reached_max_depth: + node = Node(value_repr=f"{obj.__class__.__name__}(...)") + else: + node = Node( + open_brace=f"{obj.__class__.__name__}(", + close_brace=")", + children=children, + last=root, + empty=f"{obj.__class__.__name__}()", + ) + + for last, field in loop_last( + field for field in fields(obj) if field.repr + ): + child_node = _traverse(getattr(obj, field.name), depth=depth + 1) + child_node.key_repr = field.name + child_node.last = last + child_node.key_separator = "=" + append(child_node) + + pop_visited(obj_id) + elif _is_namedtuple(obj) and _has_default_namedtuple_repr(obj): + push_visited(obj_id) + class_name = obj.__class__.__name__ + if reached_max_depth: + # If we've reached the max depth, we still show the class name, but not its contents + node = Node( + value_repr=f"{class_name}(...)", + ) + else: + children = [] + append = children.append + node = Node( + open_brace=f"{class_name}(", + close_brace=")", + children=children, + empty=f"{class_name}()", + ) + for last, (key, value) in loop_last(obj._asdict().items()): + child_node = _traverse(value, depth=depth + 1) + child_node.key_repr = key + child_node.last = last + child_node.key_separator = "=" + append(child_node) + pop_visited(obj_id) + elif _safe_isinstance(obj, _CONTAINERS): + for container_type in _CONTAINERS: + if _safe_isinstance(obj, container_type): + obj_type = container_type + break + + push_visited(obj_id) + + open_brace, close_brace, empty = _BRACES[obj_type](obj) + + if reached_max_depth: + node = Node(value_repr=f"{open_brace}...{close_brace}") + elif obj_type.__repr__ != type(obj).__repr__: + node = Node(value_repr=to_repr(obj), last=root) + elif obj: + children = [] + node = Node( + open_brace=open_brace, + close_brace=close_brace, + children=children, + last=root, + ) + append = children.append + num_items = len(obj) + last_item_index = num_items - 1 + + if _safe_isinstance(obj, _MAPPING_CONTAINERS): + iter_items = iter(obj.items()) + if max_length is not None: + iter_items = islice(iter_items, max_length) + for index, (key, child) in enumerate(iter_items): + child_node = _traverse(child, depth=depth + 1) + child_node.key_repr = to_repr(key) + child_node.last = index == last_item_index + append(child_node) + else: + iter_values = iter(obj) + if max_length is not None: + iter_values = islice(iter_values, max_length) + for index, child in enumerate(iter_values): + child_node = _traverse(child, depth=depth + 1) + child_node.last = index == last_item_index + append(child_node) + if max_length is not None and num_items > max_length: + append(Node(value_repr=f"... +{num_items - max_length}", last=True)) + else: + node = Node(empty=empty, children=[], last=root) + + pop_visited(obj_id) + else: + node = Node(value_repr=to_repr(obj), last=root) + node.is_tuple = _safe_isinstance(obj, tuple) + node.is_namedtuple = _is_namedtuple(obj) + return node + + node = _traverse(_object, root=True) + return node + + +def pretty_repr( + _object: Any, + *, + max_width: int = 80, + indent_size: int = 4, + max_length: Optional[int] = None, + max_string: Optional[int] = None, + max_depth: Optional[int] = None, + expand_all: bool = False, +) -> str: + """Prettify repr string by expanding on to new lines to fit within a given width. + + Args: + _object (Any): Object to repr. + max_width (int, optional): Desired maximum width of repr string. Defaults to 80. + indent_size (int, optional): Number of spaces to indent. Defaults to 4. + max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation. + Defaults to None. + max_string (int, optional): Maximum length of string before truncating, or None to disable truncating. + Defaults to None. + max_depth (int, optional): Maximum depth of nested data structure, or None for no depth. + Defaults to None. + expand_all (bool, optional): Expand all containers regardless of available width. Defaults to False. + + Returns: + str: A possibly multi-line representation of the object. + """ + + if _safe_isinstance(_object, Node): + node = _object + else: + node = traverse( + _object, max_length=max_length, max_string=max_string, max_depth=max_depth + ) + repr_str: str = node.render( + max_width=max_width, indent_size=indent_size, expand_all=expand_all + ) + return repr_str + + +def pprint( + _object: Any, + *, + console: Optional["Console"] = None, + indent_guides: bool = True, + max_length: Optional[int] = None, + max_string: Optional[int] = None, + max_depth: Optional[int] = None, + expand_all: bool = False, +) -> None: + """A convenience function for pretty printing. + + Args: + _object (Any): Object to pretty print. + console (Console, optional): Console instance, or None to use default. Defaults to None. + max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation. + Defaults to None. + max_string (int, optional): Maximum length of strings before truncating, or None to disable. Defaults to None. + max_depth (int, optional): Maximum depth for nested data structures, or None for unlimited depth. Defaults to None. + indent_guides (bool, optional): Enable indentation guides. Defaults to True. + expand_all (bool, optional): Expand all containers. Defaults to False. + """ + _console = get_console() if console is None else console + _console.print( + Pretty( + _object, + max_length=max_length, + max_string=max_string, + max_depth=max_depth, + indent_guides=indent_guides, + expand_all=expand_all, + overflow="ignore", + ), + soft_wrap=True, + ) + + +if __name__ == "__main__": # pragma: no cover + + class BrokenRepr: + def __repr__(self) -> str: + 1 / 0 + return "this will fail" + + from typing import NamedTuple + + class StockKeepingUnit(NamedTuple): + name: str + description: str + price: float + category: str + reviews: List[str] + + d = defaultdict(int) + d["foo"] = 5 + data = { + "foo": [ + 1, + "Hello World!", + 100.123, + 323.232, + 432324.0, + {5, 6, 7, (1, 2, 3, 4), 8}, + ], + "bar": frozenset({1, 2, 3}), + "defaultdict": defaultdict( + list, {"crumble": ["apple", "rhubarb", "butter", "sugar", "flour"]} + ), + "counter": Counter( + [ + "apple", + "orange", + "pear", + "kumquat", + "kumquat", + "durian" * 100, + ] + ), + "atomic": (False, True, None), + "namedtuple": StockKeepingUnit( + "Sparkling British Spring Water", + "Carbonated spring water", + 0.9, + "water", + ["its amazing!", "its terrible!"], + ), + "Broken": BrokenRepr(), + } + data["foo"].append(data) # type: ignore[attr-defined] + + from pip._vendor.rich import print + + print(Pretty(data, indent_guides=True, max_string=20)) + + class Thing: + def __repr__(self) -> str: + return "Hello\x1b[38;5;239m World!" + + print(Pretty(Thing())) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/progress.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/progress.py new file mode 100644 index 0000000..2420c24 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/progress.py @@ -0,0 +1,1699 @@ +import io +import sys +import typing +import warnings +from abc import ABC, abstractmethod +from collections import deque +from dataclasses import dataclass, field +from datetime import timedelta +from io import RawIOBase, UnsupportedOperation +from math import ceil +from mmap import mmap +from operator import length_hint +from os import PathLike, stat +from threading import Event, RLock, Thread +from types import TracebackType +from typing import ( + Any, + BinaryIO, + Callable, + ContextManager, + Deque, + Dict, + Generic, + Iterable, + List, + NamedTuple, + NewType, + Optional, + Sequence, + TextIO, + Tuple, + Type, + TypeVar, + Union, +) + +if sys.version_info >= (3, 8): + from typing import Literal +else: + from pip._vendor.typing_extensions import Literal # pragma: no cover + +from . import filesize, get_console +from .console import Console, Group, JustifyMethod, RenderableType +from .highlighter import Highlighter +from .jupyter import JupyterMixin +from .live import Live +from .progress_bar import ProgressBar +from .spinner import Spinner +from .style import StyleType +from .table import Column, Table +from .text import Text, TextType + +TaskID = NewType("TaskID", int) + +ProgressType = TypeVar("ProgressType") + +GetTimeCallable = Callable[[], float] + + +_I = typing.TypeVar("_I", TextIO, BinaryIO) + + +class _TrackThread(Thread): + """A thread to periodically update progress.""" + + def __init__(self, progress: "Progress", task_id: "TaskID", update_period: float): + self.progress = progress + self.task_id = task_id + self.update_period = update_period + self.done = Event() + + self.completed = 0 + super().__init__() + + def run(self) -> None: + task_id = self.task_id + advance = self.progress.advance + update_period = self.update_period + last_completed = 0 + wait = self.done.wait + while not wait(update_period): + completed = self.completed + if last_completed != completed: + advance(task_id, completed - last_completed) + last_completed = completed + + self.progress.update(self.task_id, completed=self.completed, refresh=True) + + def __enter__(self) -> "_TrackThread": + self.start() + return self + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + self.done.set() + self.join() + + +def track( + sequence: Union[Sequence[ProgressType], Iterable[ProgressType]], + description: str = "Working...", + total: Optional[float] = None, + auto_refresh: bool = True, + console: Optional[Console] = None, + transient: bool = False, + get_time: Optional[Callable[[], float]] = None, + refresh_per_second: float = 10, + style: StyleType = "bar.back", + complete_style: StyleType = "bar.complete", + finished_style: StyleType = "bar.finished", + pulse_style: StyleType = "bar.pulse", + update_period: float = 0.1, + disable: bool = False, + show_speed: bool = True, +) -> Iterable[ProgressType]: + """Track progress by iterating over a sequence. + + Args: + sequence (Iterable[ProgressType]): A sequence (must support "len") you wish to iterate over. + description (str, optional): Description of task show next to progress bar. Defaults to "Working". + total: (float, optional): Total number of steps. Default is len(sequence). + auto_refresh (bool, optional): Automatic refresh, disable to force a refresh after each iteration. Default is True. + transient: (bool, optional): Clear the progress on exit. Defaults to False. + console (Console, optional): Console to write to. Default creates internal Console instance. + refresh_per_second (float): Number of times per second to refresh the progress information. Defaults to 10. + style (StyleType, optional): Style for the bar background. Defaults to "bar.back". + complete_style (StyleType, optional): Style for the completed bar. Defaults to "bar.complete". + finished_style (StyleType, optional): Style for a finished bar. Defaults to "bar.finished". + pulse_style (StyleType, optional): Style for pulsing bars. Defaults to "bar.pulse". + update_period (float, optional): Minimum time (in seconds) between calls to update(). Defaults to 0.1. + disable (bool, optional): Disable display of progress. + show_speed (bool, optional): Show speed if total isn't known. Defaults to True. + Returns: + Iterable[ProgressType]: An iterable of the values in the sequence. + + """ + + columns: List["ProgressColumn"] = ( + [TextColumn("[progress.description]{task.description}")] if description else [] + ) + columns.extend( + ( + BarColumn( + style=style, + complete_style=complete_style, + finished_style=finished_style, + pulse_style=pulse_style, + ), + TaskProgressColumn(show_speed=show_speed), + TimeRemainingColumn(elapsed_when_finished=True), + ) + ) + progress = Progress( + *columns, + auto_refresh=auto_refresh, + console=console, + transient=transient, + get_time=get_time, + refresh_per_second=refresh_per_second or 10, + disable=disable, + ) + + with progress: + yield from progress.track( + sequence, total=total, description=description, update_period=update_period + ) + + +class _Reader(RawIOBase, BinaryIO): + """A reader that tracks progress while it's being read from.""" + + def __init__( + self, + handle: BinaryIO, + progress: "Progress", + task: TaskID, + close_handle: bool = True, + ) -> None: + self.handle = handle + self.progress = progress + self.task = task + self.close_handle = close_handle + self._closed = False + + def __enter__(self) -> "_Reader": + self.handle.__enter__() + return self + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + self.close() + + def __iter__(self) -> BinaryIO: + return self + + def __next__(self) -> bytes: + line = next(self.handle) + self.progress.advance(self.task, advance=len(line)) + return line + + @property + def closed(self) -> bool: + return self._closed + + def fileno(self) -> int: + return self.handle.fileno() + + def isatty(self) -> bool: + return self.handle.isatty() + + @property + def mode(self) -> str: + return self.handle.mode + + @property + def name(self) -> str: + return self.handle.name + + def readable(self) -> bool: + return self.handle.readable() + + def seekable(self) -> bool: + return self.handle.seekable() + + def writable(self) -> bool: + return False + + def read(self, size: int = -1) -> bytes: + block = self.handle.read(size) + self.progress.advance(self.task, advance=len(block)) + return block + + def readinto(self, b: Union[bytearray, memoryview, mmap]): # type: ignore[no-untyped-def, override] + n = self.handle.readinto(b) # type: ignore[attr-defined] + self.progress.advance(self.task, advance=n) + return n + + def readline(self, size: int = -1) -> bytes: # type: ignore[override] + line = self.handle.readline(size) + self.progress.advance(self.task, advance=len(line)) + return line + + def readlines(self, hint: int = -1) -> List[bytes]: + lines = self.handle.readlines(hint) + self.progress.advance(self.task, advance=sum(map(len, lines))) + return lines + + def close(self) -> None: + if self.close_handle: + self.handle.close() + self._closed = True + + def seek(self, offset: int, whence: int = 0) -> int: + pos = self.handle.seek(offset, whence) + self.progress.update(self.task, completed=pos) + return pos + + def tell(self) -> int: + return self.handle.tell() + + def write(self, s: Any) -> int: + raise UnsupportedOperation("write") + + +class _ReadContext(ContextManager[_I], Generic[_I]): + """A utility class to handle a context for both a reader and a progress.""" + + def __init__(self, progress: "Progress", reader: _I) -> None: + self.progress = progress + self.reader: _I = reader + + def __enter__(self) -> _I: + self.progress.start() + return self.reader.__enter__() + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + self.progress.stop() + self.reader.__exit__(exc_type, exc_val, exc_tb) + + +def wrap_file( + file: BinaryIO, + total: int, + *, + description: str = "Reading...", + auto_refresh: bool = True, + console: Optional[Console] = None, + transient: bool = False, + get_time: Optional[Callable[[], float]] = None, + refresh_per_second: float = 10, + style: StyleType = "bar.back", + complete_style: StyleType = "bar.complete", + finished_style: StyleType = "bar.finished", + pulse_style: StyleType = "bar.pulse", + disable: bool = False, +) -> ContextManager[BinaryIO]: + """Read bytes from a file while tracking progress. + + Args: + file (Union[str, PathLike[str], BinaryIO]): The path to the file to read, or a file-like object in binary mode. + total (int): Total number of bytes to read. + description (str, optional): Description of task show next to progress bar. Defaults to "Reading". + auto_refresh (bool, optional): Automatic refresh, disable to force a refresh after each iteration. Default is True. + transient: (bool, optional): Clear the progress on exit. Defaults to False. + console (Console, optional): Console to write to. Default creates internal Console instance. + refresh_per_second (float): Number of times per second to refresh the progress information. Defaults to 10. + style (StyleType, optional): Style for the bar background. Defaults to "bar.back". + complete_style (StyleType, optional): Style for the completed bar. Defaults to "bar.complete". + finished_style (StyleType, optional): Style for a finished bar. Defaults to "bar.finished". + pulse_style (StyleType, optional): Style for pulsing bars. Defaults to "bar.pulse". + disable (bool, optional): Disable display of progress. + Returns: + ContextManager[BinaryIO]: A context manager yielding a progress reader. + + """ + + columns: List["ProgressColumn"] = ( + [TextColumn("[progress.description]{task.description}")] if description else [] + ) + columns.extend( + ( + BarColumn( + style=style, + complete_style=complete_style, + finished_style=finished_style, + pulse_style=pulse_style, + ), + DownloadColumn(), + TimeRemainingColumn(), + ) + ) + progress = Progress( + *columns, + auto_refresh=auto_refresh, + console=console, + transient=transient, + get_time=get_time, + refresh_per_second=refresh_per_second or 10, + disable=disable, + ) + + reader = progress.wrap_file(file, total=total, description=description) + return _ReadContext(progress, reader) + + +@typing.overload +def open( + file: Union[str, "PathLike[str]", bytes], + mode: Union[Literal["rt"], Literal["r"]], + buffering: int = -1, + encoding: Optional[str] = None, + errors: Optional[str] = None, + newline: Optional[str] = None, + *, + total: Optional[int] = None, + description: str = "Reading...", + auto_refresh: bool = True, + console: Optional[Console] = None, + transient: bool = False, + get_time: Optional[Callable[[], float]] = None, + refresh_per_second: float = 10, + style: StyleType = "bar.back", + complete_style: StyleType = "bar.complete", + finished_style: StyleType = "bar.finished", + pulse_style: StyleType = "bar.pulse", + disable: bool = False, +) -> ContextManager[TextIO]: + pass + + +@typing.overload +def open( + file: Union[str, "PathLike[str]", bytes], + mode: Literal["rb"], + buffering: int = -1, + encoding: Optional[str] = None, + errors: Optional[str] = None, + newline: Optional[str] = None, + *, + total: Optional[int] = None, + description: str = "Reading...", + auto_refresh: bool = True, + console: Optional[Console] = None, + transient: bool = False, + get_time: Optional[Callable[[], float]] = None, + refresh_per_second: float = 10, + style: StyleType = "bar.back", + complete_style: StyleType = "bar.complete", + finished_style: StyleType = "bar.finished", + pulse_style: StyleType = "bar.pulse", + disable: bool = False, +) -> ContextManager[BinaryIO]: + pass + + +def open( + file: Union[str, "PathLike[str]", bytes], + mode: Union[Literal["rb"], Literal["rt"], Literal["r"]] = "r", + buffering: int = -1, + encoding: Optional[str] = None, + errors: Optional[str] = None, + newline: Optional[str] = None, + *, + total: Optional[int] = None, + description: str = "Reading...", + auto_refresh: bool = True, + console: Optional[Console] = None, + transient: bool = False, + get_time: Optional[Callable[[], float]] = None, + refresh_per_second: float = 10, + style: StyleType = "bar.back", + complete_style: StyleType = "bar.complete", + finished_style: StyleType = "bar.finished", + pulse_style: StyleType = "bar.pulse", + disable: bool = False, +) -> Union[ContextManager[BinaryIO], ContextManager[TextIO]]: + """Read bytes from a file while tracking progress. + + Args: + path (Union[str, PathLike[str], BinaryIO]): The path to the file to read, or a file-like object in binary mode. + mode (str): The mode to use to open the file. Only supports "r", "rb" or "rt". + buffering (int): The buffering strategy to use, see :func:`io.open`. + encoding (str, optional): The encoding to use when reading in text mode, see :func:`io.open`. + errors (str, optional): The error handling strategy for decoding errors, see :func:`io.open`. + newline (str, optional): The strategy for handling newlines in text mode, see :func:`io.open` + total: (int, optional): Total number of bytes to read. Must be provided if reading from a file handle. Default for a path is os.stat(file).st_size. + description (str, optional): Description of task show next to progress bar. Defaults to "Reading". + auto_refresh (bool, optional): Automatic refresh, disable to force a refresh after each iteration. Default is True. + transient: (bool, optional): Clear the progress on exit. Defaults to False. + console (Console, optional): Console to write to. Default creates internal Console instance. + refresh_per_second (float): Number of times per second to refresh the progress information. Defaults to 10. + style (StyleType, optional): Style for the bar background. Defaults to "bar.back". + complete_style (StyleType, optional): Style for the completed bar. Defaults to "bar.complete". + finished_style (StyleType, optional): Style for a finished bar. Defaults to "bar.finished". + pulse_style (StyleType, optional): Style for pulsing bars. Defaults to "bar.pulse". + disable (bool, optional): Disable display of progress. + encoding (str, optional): The encoding to use when reading in text mode. + + Returns: + ContextManager[BinaryIO]: A context manager yielding a progress reader. + + """ + + columns: List["ProgressColumn"] = ( + [TextColumn("[progress.description]{task.description}")] if description else [] + ) + columns.extend( + ( + BarColumn( + style=style, + complete_style=complete_style, + finished_style=finished_style, + pulse_style=pulse_style, + ), + DownloadColumn(), + TimeRemainingColumn(), + ) + ) + progress = Progress( + *columns, + auto_refresh=auto_refresh, + console=console, + transient=transient, + get_time=get_time, + refresh_per_second=refresh_per_second or 10, + disable=disable, + ) + + reader = progress.open( + file, + mode=mode, + buffering=buffering, + encoding=encoding, + errors=errors, + newline=newline, + total=total, + description=description, + ) + return _ReadContext(progress, reader) # type: ignore[return-value, type-var] + + +class ProgressColumn(ABC): + """Base class for a widget to use in progress display.""" + + max_refresh: Optional[float] = None + + def __init__(self, table_column: Optional[Column] = None) -> None: + self._table_column = table_column + self._renderable_cache: Dict[TaskID, Tuple[float, RenderableType]] = {} + self._update_time: Optional[float] = None + + def get_table_column(self) -> Column: + """Get a table column, used to build tasks table.""" + return self._table_column or Column() + + def __call__(self, task: "Task") -> RenderableType: + """Called by the Progress object to return a renderable for the given task. + + Args: + task (Task): An object containing information regarding the task. + + Returns: + RenderableType: Anything renderable (including str). + """ + current_time = task.get_time() + if self.max_refresh is not None and not task.completed: + try: + timestamp, renderable = self._renderable_cache[task.id] + except KeyError: + pass + else: + if timestamp + self.max_refresh > current_time: + return renderable + + renderable = self.render(task) + self._renderable_cache[task.id] = (current_time, renderable) + return renderable + + @abstractmethod + def render(self, task: "Task") -> RenderableType: + """Should return a renderable object.""" + + +class RenderableColumn(ProgressColumn): + """A column to insert an arbitrary column. + + Args: + renderable (RenderableType, optional): Any renderable. Defaults to empty string. + """ + + def __init__( + self, renderable: RenderableType = "", *, table_column: Optional[Column] = None + ): + self.renderable = renderable + super().__init__(table_column=table_column) + + def render(self, task: "Task") -> RenderableType: + return self.renderable + + +class SpinnerColumn(ProgressColumn): + """A column with a 'spinner' animation. + + Args: + spinner_name (str, optional): Name of spinner animation. Defaults to "dots". + style (StyleType, optional): Style of spinner. Defaults to "progress.spinner". + speed (float, optional): Speed factor of spinner. Defaults to 1.0. + finished_text (TextType, optional): Text used when task is finished. Defaults to " ". + """ + + def __init__( + self, + spinner_name: str = "dots", + style: Optional[StyleType] = "progress.spinner", + speed: float = 1.0, + finished_text: TextType = " ", + table_column: Optional[Column] = None, + ): + self.spinner = Spinner(spinner_name, style=style, speed=speed) + self.finished_text = ( + Text.from_markup(finished_text) + if isinstance(finished_text, str) + else finished_text + ) + super().__init__(table_column=table_column) + + def set_spinner( + self, + spinner_name: str, + spinner_style: Optional[StyleType] = "progress.spinner", + speed: float = 1.0, + ) -> None: + """Set a new spinner. + + Args: + spinner_name (str): Spinner name, see python -m rich.spinner. + spinner_style (Optional[StyleType], optional): Spinner style. Defaults to "progress.spinner". + speed (float, optional): Speed factor of spinner. Defaults to 1.0. + """ + self.spinner = Spinner(spinner_name, style=spinner_style, speed=speed) + + def render(self, task: "Task") -> RenderableType: + text = ( + self.finished_text + if task.finished + else self.spinner.render(task.get_time()) + ) + return text + + +class TextColumn(ProgressColumn): + """A column containing text.""" + + def __init__( + self, + text_format: str, + style: StyleType = "none", + justify: JustifyMethod = "left", + markup: bool = True, + highlighter: Optional[Highlighter] = None, + table_column: Optional[Column] = None, + ) -> None: + self.text_format = text_format + self.justify: JustifyMethod = justify + self.style = style + self.markup = markup + self.highlighter = highlighter + super().__init__(table_column=table_column or Column(no_wrap=True)) + + def render(self, task: "Task") -> Text: + _text = self.text_format.format(task=task) + if self.markup: + text = Text.from_markup(_text, style=self.style, justify=self.justify) + else: + text = Text(_text, style=self.style, justify=self.justify) + if self.highlighter: + self.highlighter.highlight(text) + return text + + +class BarColumn(ProgressColumn): + """Renders a visual progress bar. + + Args: + bar_width (Optional[int], optional): Width of bar or None for full width. Defaults to 40. + style (StyleType, optional): Style for the bar background. Defaults to "bar.back". + complete_style (StyleType, optional): Style for the completed bar. Defaults to "bar.complete". + finished_style (StyleType, optional): Style for a finished bar. Defaults to "bar.finished". + pulse_style (StyleType, optional): Style for pulsing bars. Defaults to "bar.pulse". + """ + + def __init__( + self, + bar_width: Optional[int] = 40, + style: StyleType = "bar.back", + complete_style: StyleType = "bar.complete", + finished_style: StyleType = "bar.finished", + pulse_style: StyleType = "bar.pulse", + table_column: Optional[Column] = None, + ) -> None: + self.bar_width = bar_width + self.style = style + self.complete_style = complete_style + self.finished_style = finished_style + self.pulse_style = pulse_style + super().__init__(table_column=table_column) + + def render(self, task: "Task") -> ProgressBar: + """Gets a progress bar widget for a task.""" + return ProgressBar( + total=max(0, task.total) if task.total is not None else None, + completed=max(0, task.completed), + width=None if self.bar_width is None else max(1, self.bar_width), + pulse=not task.started, + animation_time=task.get_time(), + style=self.style, + complete_style=self.complete_style, + finished_style=self.finished_style, + pulse_style=self.pulse_style, + ) + + +class TimeElapsedColumn(ProgressColumn): + """Renders time elapsed.""" + + def render(self, task: "Task") -> Text: + """Show time elapsed.""" + elapsed = task.finished_time if task.finished else task.elapsed + if elapsed is None: + return Text("-:--:--", style="progress.elapsed") + delta = timedelta(seconds=max(0, int(elapsed))) + return Text(str(delta), style="progress.elapsed") + + +class TaskProgressColumn(TextColumn): + """Show task progress as a percentage. + + Args: + text_format (str, optional): Format for percentage display. Defaults to "[progress.percentage]{task.percentage:>3.0f}%". + text_format_no_percentage (str, optional): Format if percentage is unknown. Defaults to "". + style (StyleType, optional): Style of output. Defaults to "none". + justify (JustifyMethod, optional): Text justification. Defaults to "left". + markup (bool, optional): Enable markup. Defaults to True. + highlighter (Optional[Highlighter], optional): Highlighter to apply to output. Defaults to None. + table_column (Optional[Column], optional): Table Column to use. Defaults to None. + show_speed (bool, optional): Show speed if total is unknown. Defaults to False. + """ + + def __init__( + self, + text_format: str = "[progress.percentage]{task.percentage:>3.0f}%", + text_format_no_percentage: str = "", + style: StyleType = "none", + justify: JustifyMethod = "left", + markup: bool = True, + highlighter: Optional[Highlighter] = None, + table_column: Optional[Column] = None, + show_speed: bool = False, + ) -> None: + self.text_format_no_percentage = text_format_no_percentage + self.show_speed = show_speed + super().__init__( + text_format=text_format, + style=style, + justify=justify, + markup=markup, + highlighter=highlighter, + table_column=table_column, + ) + + @classmethod + def render_speed(cls, speed: Optional[float]) -> Text: + """Render the speed in iterations per second. + + Args: + task (Task): A Task object. + + Returns: + Text: Text object containing the task speed. + """ + if speed is None: + return Text("", style="progress.percentage") + unit, suffix = filesize.pick_unit_and_suffix( + int(speed), + ["", "×10³", "×10⁶", "×10⁹", "×10¹²"], + 1000, + ) + data_speed = speed / unit + return Text(f"{data_speed:.1f}{suffix} it/s", style="progress.percentage") + + def render(self, task: "Task") -> Text: + if task.total is None and self.show_speed: + return self.render_speed(task.finished_speed or task.speed) + text_format = ( + self.text_format_no_percentage if task.total is None else self.text_format + ) + _text = text_format.format(task=task) + if self.markup: + text = Text.from_markup(_text, style=self.style, justify=self.justify) + else: + text = Text(_text, style=self.style, justify=self.justify) + if self.highlighter: + self.highlighter.highlight(text) + return text + + +class TimeRemainingColumn(ProgressColumn): + """Renders estimated time remaining. + + Args: + compact (bool, optional): Render MM:SS when time remaining is less than an hour. Defaults to False. + elapsed_when_finished (bool, optional): Render time elapsed when the task is finished. Defaults to False. + """ + + # Only refresh twice a second to prevent jitter + max_refresh = 0.5 + + def __init__( + self, + compact: bool = False, + elapsed_when_finished: bool = False, + table_column: Optional[Column] = None, + ): + self.compact = compact + self.elapsed_when_finished = elapsed_when_finished + super().__init__(table_column=table_column) + + def render(self, task: "Task") -> Text: + """Show time remaining.""" + if self.elapsed_when_finished and task.finished: + task_time = task.finished_time + style = "progress.elapsed" + else: + task_time = task.time_remaining + style = "progress.remaining" + + if task.total is None: + return Text("", style=style) + + if task_time is None: + return Text("--:--" if self.compact else "-:--:--", style=style) + + # Based on https://github.com/tqdm/tqdm/blob/master/tqdm/std.py + minutes, seconds = divmod(int(task_time), 60) + hours, minutes = divmod(minutes, 60) + + if self.compact and not hours: + formatted = f"{minutes:02d}:{seconds:02d}" + else: + formatted = f"{hours:d}:{minutes:02d}:{seconds:02d}" + + return Text(formatted, style=style) + + +class FileSizeColumn(ProgressColumn): + """Renders completed filesize.""" + + def render(self, task: "Task") -> Text: + """Show data completed.""" + data_size = filesize.decimal(int(task.completed)) + return Text(data_size, style="progress.filesize") + + +class TotalFileSizeColumn(ProgressColumn): + """Renders total filesize.""" + + def render(self, task: "Task") -> Text: + """Show data completed.""" + data_size = filesize.decimal(int(task.total)) if task.total is not None else "" + return Text(data_size, style="progress.filesize.total") + + +class MofNCompleteColumn(ProgressColumn): + """Renders completed count/total, e.g. ' 10/1000'. + + Best for bounded tasks with int quantities. + + Space pads the completed count so that progress length does not change as task progresses + past powers of 10. + + Args: + separator (str, optional): Text to separate completed and total values. Defaults to "/". + """ + + def __init__(self, separator: str = "/", table_column: Optional[Column] = None): + self.separator = separator + super().__init__(table_column=table_column) + + def render(self, task: "Task") -> Text: + """Show completed/total.""" + completed = int(task.completed) + total = int(task.total) if task.total is not None else "?" + total_width = len(str(total)) + return Text( + f"{completed:{total_width}d}{self.separator}{total}", + style="progress.download", + ) + + +class DownloadColumn(ProgressColumn): + """Renders file size downloaded and total, e.g. '0.5/2.3 GB'. + + Args: + binary_units (bool, optional): Use binary units, KiB, MiB etc. Defaults to False. + """ + + def __init__( + self, binary_units: bool = False, table_column: Optional[Column] = None + ) -> None: + self.binary_units = binary_units + super().__init__(table_column=table_column) + + def render(self, task: "Task") -> Text: + """Calculate common unit for completed and total.""" + completed = int(task.completed) + + unit_and_suffix_calculation_base = ( + int(task.total) if task.total is not None else completed + ) + if self.binary_units: + unit, suffix = filesize.pick_unit_and_suffix( + unit_and_suffix_calculation_base, + ["bytes", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"], + 1024, + ) + else: + unit, suffix = filesize.pick_unit_and_suffix( + unit_and_suffix_calculation_base, + ["bytes", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"], + 1000, + ) + precision = 0 if unit == 1 else 1 + + completed_ratio = completed / unit + completed_str = f"{completed_ratio:,.{precision}f}" + + if task.total is not None: + total = int(task.total) + total_ratio = total / unit + total_str = f"{total_ratio:,.{precision}f}" + else: + total_str = "?" + + download_status = f"{completed_str}/{total_str} {suffix}" + download_text = Text(download_status, style="progress.download") + return download_text + + +class TransferSpeedColumn(ProgressColumn): + """Renders human readable transfer speed.""" + + def render(self, task: "Task") -> Text: + """Show data transfer speed.""" + speed = task.finished_speed or task.speed + if speed is None: + return Text("?", style="progress.data.speed") + data_speed = filesize.decimal(int(speed)) + return Text(f"{data_speed}/s", style="progress.data.speed") + + +class ProgressSample(NamedTuple): + """Sample of progress for a given time.""" + + timestamp: float + """Timestamp of sample.""" + completed: float + """Number of steps completed.""" + + +@dataclass +class Task: + """Information regarding a progress task. + + This object should be considered read-only outside of the :class:`~Progress` class. + + """ + + id: TaskID + """Task ID associated with this task (used in Progress methods).""" + + description: str + """str: Description of the task.""" + + total: Optional[float] + """Optional[float]: Total number of steps in this task.""" + + completed: float + """float: Number of steps completed""" + + _get_time: GetTimeCallable + """Callable to get the current time.""" + + finished_time: Optional[float] = None + """float: Time task was finished.""" + + visible: bool = True + """bool: Indicates if this task is visible in the progress display.""" + + fields: Dict[str, Any] = field(default_factory=dict) + """dict: Arbitrary fields passed in via Progress.update.""" + + start_time: Optional[float] = field(default=None, init=False, repr=False) + """Optional[float]: Time this task was started, or None if not started.""" + + stop_time: Optional[float] = field(default=None, init=False, repr=False) + """Optional[float]: Time this task was stopped, or None if not stopped.""" + + finished_speed: Optional[float] = None + """Optional[float]: The last speed for a finished task.""" + + _progress: Deque[ProgressSample] = field( + default_factory=lambda: deque(maxlen=1000), init=False, repr=False + ) + + _lock: RLock = field(repr=False, default_factory=RLock) + """Thread lock.""" + + def get_time(self) -> float: + """float: Get the current time, in seconds.""" + return self._get_time() + + @property + def started(self) -> bool: + """bool: Check if the task as started.""" + return self.start_time is not None + + @property + def remaining(self) -> Optional[float]: + """Optional[float]: Get the number of steps remaining, if a non-None total was set.""" + if self.total is None: + return None + return self.total - self.completed + + @property + def elapsed(self) -> Optional[float]: + """Optional[float]: Time elapsed since task was started, or ``None`` if the task hasn't started.""" + if self.start_time is None: + return None + if self.stop_time is not None: + return self.stop_time - self.start_time + return self.get_time() - self.start_time + + @property + def finished(self) -> bool: + """Check if the task has finished.""" + return self.finished_time is not None + + @property + def percentage(self) -> float: + """float: Get progress of task as a percentage. If a None total was set, returns 0""" + if not self.total: + return 0.0 + completed = (self.completed / self.total) * 100.0 + completed = min(100.0, max(0.0, completed)) + return completed + + @property + def speed(self) -> Optional[float]: + """Optional[float]: Get the estimated speed in steps per second.""" + if self.start_time is None: + return None + with self._lock: + progress = self._progress + if not progress: + return None + total_time = progress[-1].timestamp - progress[0].timestamp + if total_time == 0: + return None + iter_progress = iter(progress) + next(iter_progress) + total_completed = sum(sample.completed for sample in iter_progress) + speed = total_completed / total_time + return speed + + @property + def time_remaining(self) -> Optional[float]: + """Optional[float]: Get estimated time to completion, or ``None`` if no data.""" + if self.finished: + return 0.0 + speed = self.speed + if not speed: + return None + remaining = self.remaining + if remaining is None: + return None + estimate = ceil(remaining / speed) + return estimate + + def _reset(self) -> None: + """Reset progress.""" + self._progress.clear() + self.finished_time = None + self.finished_speed = None + + +class Progress(JupyterMixin): + """Renders an auto-updating progress bar(s). + + Args: + console (Console, optional): Optional Console instance. Default will an internal Console instance writing to stdout. + auto_refresh (bool, optional): Enable auto refresh. If disabled, you will need to call `refresh()`. + refresh_per_second (Optional[float], optional): Number of times per second to refresh the progress information or None to use default (10). Defaults to None. + speed_estimate_period: (float, optional): Period (in seconds) used to calculate the speed estimate. Defaults to 30. + transient: (bool, optional): Clear the progress on exit. Defaults to False. + redirect_stdout: (bool, optional): Enable redirection of stdout, so ``print`` may be used. Defaults to True. + redirect_stderr: (bool, optional): Enable redirection of stderr. Defaults to True. + get_time: (Callable, optional): A callable that gets the current time, or None to use Console.get_time. Defaults to None. + disable (bool, optional): Disable progress display. Defaults to False + expand (bool, optional): Expand tasks table to fit width. Defaults to False. + """ + + def __init__( + self, + *columns: Union[str, ProgressColumn], + console: Optional[Console] = None, + auto_refresh: bool = True, + refresh_per_second: float = 10, + speed_estimate_period: float = 30.0, + transient: bool = False, + redirect_stdout: bool = True, + redirect_stderr: bool = True, + get_time: Optional[GetTimeCallable] = None, + disable: bool = False, + expand: bool = False, + ) -> None: + assert refresh_per_second > 0, "refresh_per_second must be > 0" + self._lock = RLock() + self.columns = columns or self.get_default_columns() + self.speed_estimate_period = speed_estimate_period + + self.disable = disable + self.expand = expand + self._tasks: Dict[TaskID, Task] = {} + self._task_index: TaskID = TaskID(0) + self.live = Live( + console=console or get_console(), + auto_refresh=auto_refresh, + refresh_per_second=refresh_per_second, + transient=transient, + redirect_stdout=redirect_stdout, + redirect_stderr=redirect_stderr, + get_renderable=self.get_renderable, + ) + self.get_time = get_time or self.console.get_time + self.print = self.console.print + self.log = self.console.log + + @classmethod + def get_default_columns(cls) -> Tuple[ProgressColumn, ...]: + """Get the default columns used for a new Progress instance: + - a text column for the description (TextColumn) + - the bar itself (BarColumn) + - a text column showing completion percentage (TextColumn) + - an estimated-time-remaining column (TimeRemainingColumn) + If the Progress instance is created without passing a columns argument, + the default columns defined here will be used. + + You can also create a Progress instance using custom columns before + and/or after the defaults, as in this example: + + progress = Progress( + SpinnerColumn(), + *Progress.get_default_columns(), + "Elapsed:", + TimeElapsedColumn(), + ) + + This code shows the creation of a Progress display, containing + a spinner to the left, the default columns, and a labeled elapsed + time column. + """ + return ( + TextColumn("[progress.description]{task.description}"), + BarColumn(), + TaskProgressColumn(), + TimeRemainingColumn(), + ) + + @property + def console(self) -> Console: + return self.live.console + + @property + def tasks(self) -> List[Task]: + """Get a list of Task instances.""" + with self._lock: + return list(self._tasks.values()) + + @property + def task_ids(self) -> List[TaskID]: + """A list of task IDs.""" + with self._lock: + return list(self._tasks.keys()) + + @property + def finished(self) -> bool: + """Check if all tasks have been completed.""" + with self._lock: + if not self._tasks: + return True + return all(task.finished for task in self._tasks.values()) + + def start(self) -> None: + """Start the progress display.""" + if not self.disable: + self.live.start(refresh=True) + + def stop(self) -> None: + """Stop the progress display.""" + self.live.stop() + if not self.console.is_interactive: + self.console.print() + + def __enter__(self) -> "Progress": + self.start() + return self + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + self.stop() + + def track( + self, + sequence: Union[Iterable[ProgressType], Sequence[ProgressType]], + total: Optional[float] = None, + task_id: Optional[TaskID] = None, + description: str = "Working...", + update_period: float = 0.1, + ) -> Iterable[ProgressType]: + """Track progress by iterating over a sequence. + + Args: + sequence (Sequence[ProgressType]): A sequence of values you want to iterate over and track progress. + total: (float, optional): Total number of steps. Default is len(sequence). + task_id: (TaskID): Task to track. Default is new task. + description: (str, optional): Description of task, if new task is created. + update_period (float, optional): Minimum time (in seconds) between calls to update(). Defaults to 0.1. + + Returns: + Iterable[ProgressType]: An iterable of values taken from the provided sequence. + """ + if total is None: + total = float(length_hint(sequence)) or None + + if task_id is None: + task_id = self.add_task(description, total=total) + else: + self.update(task_id, total=total) + + if self.live.auto_refresh: + with _TrackThread(self, task_id, update_period) as track_thread: + for value in sequence: + yield value + track_thread.completed += 1 + else: + advance = self.advance + refresh = self.refresh + for value in sequence: + yield value + advance(task_id, 1) + refresh() + + def wrap_file( + self, + file: BinaryIO, + total: Optional[int] = None, + *, + task_id: Optional[TaskID] = None, + description: str = "Reading...", + ) -> BinaryIO: + """Track progress file reading from a binary file. + + Args: + file (BinaryIO): A file-like object opened in binary mode. + total (int, optional): Total number of bytes to read. This must be provided unless a task with a total is also given. + task_id (TaskID): Task to track. Default is new task. + description (str, optional): Description of task, if new task is created. + + Returns: + BinaryIO: A readable file-like object in binary mode. + + Raises: + ValueError: When no total value can be extracted from the arguments or the task. + """ + # attempt to recover the total from the task + total_bytes: Optional[float] = None + if total is not None: + total_bytes = total + elif task_id is not None: + with self._lock: + total_bytes = self._tasks[task_id].total + if total_bytes is None: + raise ValueError( + f"unable to get the total number of bytes, please specify 'total'" + ) + + # update total of task or create new task + if task_id is None: + task_id = self.add_task(description, total=total_bytes) + else: + self.update(task_id, total=total_bytes) + + return _Reader(file, self, task_id, close_handle=False) + + @typing.overload + def open( + self, + file: Union[str, "PathLike[str]", bytes], + mode: Literal["rb"], + buffering: int = -1, + encoding: Optional[str] = None, + errors: Optional[str] = None, + newline: Optional[str] = None, + *, + total: Optional[int] = None, + task_id: Optional[TaskID] = None, + description: str = "Reading...", + ) -> BinaryIO: + pass + + @typing.overload + def open( + self, + file: Union[str, "PathLike[str]", bytes], + mode: Union[Literal["r"], Literal["rt"]], + buffering: int = -1, + encoding: Optional[str] = None, + errors: Optional[str] = None, + newline: Optional[str] = None, + *, + total: Optional[int] = None, + task_id: Optional[TaskID] = None, + description: str = "Reading...", + ) -> TextIO: + pass + + def open( + self, + file: Union[str, "PathLike[str]", bytes], + mode: Union[Literal["rb"], Literal["rt"], Literal["r"]] = "r", + buffering: int = -1, + encoding: Optional[str] = None, + errors: Optional[str] = None, + newline: Optional[str] = None, + *, + total: Optional[int] = None, + task_id: Optional[TaskID] = None, + description: str = "Reading...", + ) -> Union[BinaryIO, TextIO]: + """Track progress while reading from a binary file. + + Args: + path (Union[str, PathLike[str]]): The path to the file to read. + mode (str): The mode to use to open the file. Only supports "r", "rb" or "rt". + buffering (int): The buffering strategy to use, see :func:`io.open`. + encoding (str, optional): The encoding to use when reading in text mode, see :func:`io.open`. + errors (str, optional): The error handling strategy for decoding errors, see :func:`io.open`. + newline (str, optional): The strategy for handling newlines in text mode, see :func:`io.open`. + total (int, optional): Total number of bytes to read. If none given, os.stat(path).st_size is used. + task_id (TaskID): Task to track. Default is new task. + description (str, optional): Description of task, if new task is created. + + Returns: + BinaryIO: A readable file-like object in binary mode. + + Raises: + ValueError: When an invalid mode is given. + """ + # normalize the mode (always rb, rt) + _mode = "".join(sorted(mode, reverse=False)) + if _mode not in ("br", "rt", "r"): + raise ValueError("invalid mode {!r}".format(mode)) + + # patch buffering to provide the same behaviour as the builtin `open` + line_buffering = buffering == 1 + if _mode == "br" and buffering == 1: + warnings.warn( + "line buffering (buffering=1) isn't supported in binary mode, the default buffer size will be used", + RuntimeWarning, + ) + buffering = -1 + elif _mode in ("rt", "r"): + if buffering == 0: + raise ValueError("can't have unbuffered text I/O") + elif buffering == 1: + buffering = -1 + + # attempt to get the total with `os.stat` + if total is None: + total = stat(file).st_size + + # update total of task or create new task + if task_id is None: + task_id = self.add_task(description, total=total) + else: + self.update(task_id, total=total) + + # open the file in binary mode, + handle = io.open(file, "rb", buffering=buffering) + reader = _Reader(handle, self, task_id, close_handle=True) + + # wrap the reader in a `TextIOWrapper` if text mode + if mode in ("r", "rt"): + return io.TextIOWrapper( + reader, + encoding=encoding, + errors=errors, + newline=newline, + line_buffering=line_buffering, + ) + + return reader + + def start_task(self, task_id: TaskID) -> None: + """Start a task. + + Starts a task (used when calculating elapsed time). You may need to call this manually, + if you called ``add_task`` with ``start=False``. + + Args: + task_id (TaskID): ID of task. + """ + with self._lock: + task = self._tasks[task_id] + if task.start_time is None: + task.start_time = self.get_time() + + def stop_task(self, task_id: TaskID) -> None: + """Stop a task. + + This will freeze the elapsed time on the task. + + Args: + task_id (TaskID): ID of task. + """ + with self._lock: + task = self._tasks[task_id] + current_time = self.get_time() + if task.start_time is None: + task.start_time = current_time + task.stop_time = current_time + + def update( + self, + task_id: TaskID, + *, + total: Optional[float] = None, + completed: Optional[float] = None, + advance: Optional[float] = None, + description: Optional[str] = None, + visible: Optional[bool] = None, + refresh: bool = False, + **fields: Any, + ) -> None: + """Update information associated with a task. + + Args: + task_id (TaskID): Task id (returned by add_task). + total (float, optional): Updates task.total if not None. + completed (float, optional): Updates task.completed if not None. + advance (float, optional): Add a value to task.completed if not None. + description (str, optional): Change task description if not None. + visible (bool, optional): Set visible flag if not None. + refresh (bool): Force a refresh of progress information. Default is False. + **fields (Any): Additional data fields required for rendering. + """ + with self._lock: + task = self._tasks[task_id] + completed_start = task.completed + + if total is not None and total != task.total: + task.total = total + task._reset() + if advance is not None: + task.completed += advance + if completed is not None: + task.completed = completed + if description is not None: + task.description = description + if visible is not None: + task.visible = visible + task.fields.update(fields) + update_completed = task.completed - completed_start + + current_time = self.get_time() + old_sample_time = current_time - self.speed_estimate_period + _progress = task._progress + + popleft = _progress.popleft + while _progress and _progress[0].timestamp < old_sample_time: + popleft() + if update_completed > 0: + _progress.append(ProgressSample(current_time, update_completed)) + if ( + task.total is not None + and task.completed >= task.total + and task.finished_time is None + ): + task.finished_time = task.elapsed + + if refresh: + self.refresh() + + def reset( + self, + task_id: TaskID, + *, + start: bool = True, + total: Optional[float] = None, + completed: int = 0, + visible: Optional[bool] = None, + description: Optional[str] = None, + **fields: Any, + ) -> None: + """Reset a task so completed is 0 and the clock is reset. + + Args: + task_id (TaskID): ID of task. + start (bool, optional): Start the task after reset. Defaults to True. + total (float, optional): New total steps in task, or None to use current total. Defaults to None. + completed (int, optional): Number of steps completed. Defaults to 0. + visible (bool, optional): Enable display of the task. Defaults to True. + description (str, optional): Change task description if not None. Defaults to None. + **fields (str): Additional data fields required for rendering. + """ + current_time = self.get_time() + with self._lock: + task = self._tasks[task_id] + task._reset() + task.start_time = current_time if start else None + if total is not None: + task.total = total + task.completed = completed + if visible is not None: + task.visible = visible + if fields: + task.fields = fields + if description is not None: + task.description = description + task.finished_time = None + self.refresh() + + def advance(self, task_id: TaskID, advance: float = 1) -> None: + """Advance task by a number of steps. + + Args: + task_id (TaskID): ID of task. + advance (float): Number of steps to advance. Default is 1. + """ + current_time = self.get_time() + with self._lock: + task = self._tasks[task_id] + completed_start = task.completed + task.completed += advance + update_completed = task.completed - completed_start + old_sample_time = current_time - self.speed_estimate_period + _progress = task._progress + + popleft = _progress.popleft + while _progress and _progress[0].timestamp < old_sample_time: + popleft() + while len(_progress) > 1000: + popleft() + _progress.append(ProgressSample(current_time, update_completed)) + if ( + task.total is not None + and task.completed >= task.total + and task.finished_time is None + ): + task.finished_time = task.elapsed + task.finished_speed = task.speed + + def refresh(self) -> None: + """Refresh (render) the progress information.""" + if not self.disable and self.live.is_started: + self.live.refresh() + + def get_renderable(self) -> RenderableType: + """Get a renderable for the progress display.""" + renderable = Group(*self.get_renderables()) + return renderable + + def get_renderables(self) -> Iterable[RenderableType]: + """Get a number of renderables for the progress display.""" + table = self.make_tasks_table(self.tasks) + yield table + + def make_tasks_table(self, tasks: Iterable[Task]) -> Table: + """Get a table to render the Progress display. + + Args: + tasks (Iterable[Task]): An iterable of Task instances, one per row of the table. + + Returns: + Table: A table instance. + """ + table_columns = ( + ( + Column(no_wrap=True) + if isinstance(_column, str) + else _column.get_table_column().copy() + ) + for _column in self.columns + ) + table = Table.grid(*table_columns, padding=(0, 1), expand=self.expand) + + for task in tasks: + if task.visible: + table.add_row( + *( + ( + column.format(task=task) + if isinstance(column, str) + else column(task) + ) + for column in self.columns + ) + ) + return table + + def __rich__(self) -> RenderableType: + """Makes the Progress class itself renderable.""" + with self._lock: + return self.get_renderable() + + def add_task( + self, + description: str, + start: bool = True, + total: Optional[float] = 100.0, + completed: int = 0, + visible: bool = True, + **fields: Any, + ) -> TaskID: + """Add a new 'task' to the Progress display. + + Args: + description (str): A description of the task. + start (bool, optional): Start the task immediately (to calculate elapsed time). If set to False, + you will need to call `start` manually. Defaults to True. + total (float, optional): Number of total steps in the progress if known. + Set to None to render a pulsing animation. Defaults to 100. + completed (int, optional): Number of steps completed so far. Defaults to 0. + visible (bool, optional): Enable display of the task. Defaults to True. + **fields (str): Additional data fields required for rendering. + + Returns: + TaskID: An ID you can use when calling `update`. + """ + with self._lock: + task = Task( + self._task_index, + description, + total, + completed, + visible=visible, + fields=fields, + _get_time=self.get_time, + _lock=self._lock, + ) + self._tasks[self._task_index] = task + if start: + self.start_task(self._task_index) + new_task_index = self._task_index + self._task_index = TaskID(int(self._task_index) + 1) + self.refresh() + return new_task_index + + def remove_task(self, task_id: TaskID) -> None: + """Delete a task if it exists. + + Args: + task_id (TaskID): A task ID. + + """ + with self._lock: + del self._tasks[task_id] + + +if __name__ == "__main__": # pragma: no coverage + import random + import time + + from .panel import Panel + from .rule import Rule + from .syntax import Syntax + from .table import Table + + syntax = Syntax( + '''def loop_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: + """Iterate and generate a tuple with a flag for last value.""" + iter_values = iter(values) + try: + previous_value = next(iter_values) + except StopIteration: + return + for value in iter_values: + yield False, previous_value + previous_value = value + yield True, previous_value''', + "python", + line_numbers=True, + ) + + table = Table("foo", "bar", "baz") + table.add_row("1", "2", "3") + + progress_renderables = [ + "Text may be printed while the progress bars are rendering.", + Panel("In fact, [i]any[/i] renderable will work"), + "Such as [magenta]tables[/]...", + table, + "Pretty printed structures...", + {"type": "example", "text": "Pretty printed"}, + "Syntax...", + syntax, + Rule("Give it a try!"), + ] + + from itertools import cycle + + examples = cycle(progress_renderables) + + console = Console(record=True) + + with Progress( + SpinnerColumn(), + *Progress.get_default_columns(), + TimeElapsedColumn(), + console=console, + transient=False, + ) as progress: + task1 = progress.add_task("[red]Downloading", total=1000) + task2 = progress.add_task("[green]Processing", total=1000) + task3 = progress.add_task("[yellow]Thinking", total=None) + + while not progress.finished: + progress.update(task1, advance=0.5) + progress.update(task2, advance=0.3) + time.sleep(0.01) + if random.randint(0, 100) < 1: + progress.log(next(examples)) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/progress_bar.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/progress_bar.py new file mode 100644 index 0000000..a2bf326 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/progress_bar.py @@ -0,0 +1,223 @@ +import math +from functools import lru_cache +from time import monotonic +from typing import Iterable, List, Optional + +from .color import Color, blend_rgb +from .color_triplet import ColorTriplet +from .console import Console, ConsoleOptions, RenderResult +from .jupyter import JupyterMixin +from .measure import Measurement +from .segment import Segment +from .style import Style, StyleType + +# Number of characters before 'pulse' animation repeats +PULSE_SIZE = 20 + + +class ProgressBar(JupyterMixin): + """Renders a (progress) bar. Used by rich.progress. + + Args: + total (float, optional): Number of steps in the bar. Defaults to 100. Set to None to render a pulsing animation. + completed (float, optional): Number of steps completed. Defaults to 0. + width (int, optional): Width of the bar, or ``None`` for maximum width. Defaults to None. + pulse (bool, optional): Enable pulse effect. Defaults to False. Will pulse if a None total was passed. + style (StyleType, optional): Style for the bar background. Defaults to "bar.back". + complete_style (StyleType, optional): Style for the completed bar. Defaults to "bar.complete". + finished_style (StyleType, optional): Style for a finished bar. Defaults to "bar.finished". + pulse_style (StyleType, optional): Style for pulsing bars. Defaults to "bar.pulse". + animation_time (Optional[float], optional): Time in seconds to use for animation, or None to use system time. + """ + + def __init__( + self, + total: Optional[float] = 100.0, + completed: float = 0, + width: Optional[int] = None, + pulse: bool = False, + style: StyleType = "bar.back", + complete_style: StyleType = "bar.complete", + finished_style: StyleType = "bar.finished", + pulse_style: StyleType = "bar.pulse", + animation_time: Optional[float] = None, + ): + self.total = total + self.completed = completed + self.width = width + self.pulse = pulse + self.style = style + self.complete_style = complete_style + self.finished_style = finished_style + self.pulse_style = pulse_style + self.animation_time = animation_time + + self._pulse_segments: Optional[List[Segment]] = None + + def __repr__(self) -> str: + return f"" + + @property + def percentage_completed(self) -> Optional[float]: + """Calculate percentage complete.""" + if self.total is None: + return None + completed = (self.completed / self.total) * 100.0 + completed = min(100, max(0.0, completed)) + return completed + + @lru_cache(maxsize=16) + def _get_pulse_segments( + self, + fore_style: Style, + back_style: Style, + color_system: str, + no_color: bool, + ascii: bool = False, + ) -> List[Segment]: + """Get a list of segments to render a pulse animation. + + Returns: + List[Segment]: A list of segments, one segment per character. + """ + bar = "-" if ascii else "━" + segments: List[Segment] = [] + if color_system not in ("standard", "eight_bit", "truecolor") or no_color: + segments += [Segment(bar, fore_style)] * (PULSE_SIZE // 2) + segments += [Segment(" " if no_color else bar, back_style)] * ( + PULSE_SIZE - (PULSE_SIZE // 2) + ) + return segments + + append = segments.append + fore_color = ( + fore_style.color.get_truecolor() + if fore_style.color + else ColorTriplet(255, 0, 255) + ) + back_color = ( + back_style.color.get_truecolor() + if back_style.color + else ColorTriplet(0, 0, 0) + ) + cos = math.cos + pi = math.pi + _Segment = Segment + _Style = Style + from_triplet = Color.from_triplet + + for index in range(PULSE_SIZE): + position = index / PULSE_SIZE + fade = 0.5 + cos((position * pi * 2)) / 2.0 + color = blend_rgb(fore_color, back_color, cross_fade=fade) + append(_Segment(bar, _Style(color=from_triplet(color)))) + return segments + + def update(self, completed: float, total: Optional[float] = None) -> None: + """Update progress with new values. + + Args: + completed (float): Number of steps completed. + total (float, optional): Total number of steps, or ``None`` to not change. Defaults to None. + """ + self.completed = completed + self.total = total if total is not None else self.total + + def _render_pulse( + self, console: Console, width: int, ascii: bool = False + ) -> Iterable[Segment]: + """Renders the pulse animation. + + Args: + console (Console): Console instance. + width (int): Width in characters of pulse animation. + + Returns: + RenderResult: [description] + + Yields: + Iterator[Segment]: Segments to render pulse + """ + fore_style = console.get_style(self.pulse_style, default="white") + back_style = console.get_style(self.style, default="black") + + pulse_segments = self._get_pulse_segments( + fore_style, back_style, console.color_system, console.no_color, ascii=ascii + ) + segment_count = len(pulse_segments) + current_time = ( + monotonic() if self.animation_time is None else self.animation_time + ) + segments = pulse_segments * (int(width / segment_count) + 2) + offset = int(-current_time * 15) % segment_count + segments = segments[offset : offset + width] + yield from segments + + def __rich_console__( + self, console: Console, options: ConsoleOptions + ) -> RenderResult: + width = min(self.width or options.max_width, options.max_width) + ascii = options.legacy_windows or options.ascii_only + should_pulse = self.pulse or self.total is None + if should_pulse: + yield from self._render_pulse(console, width, ascii=ascii) + return + + completed: Optional[float] = ( + min(self.total, max(0, self.completed)) if self.total is not None else None + ) + + bar = "-" if ascii else "━" + half_bar_right = " " if ascii else "╸" + half_bar_left = " " if ascii else "╺" + complete_halves = ( + int(width * 2 * completed / self.total) + if self.total and completed is not None + else width * 2 + ) + bar_count = complete_halves // 2 + half_bar_count = complete_halves % 2 + style = console.get_style(self.style) + is_finished = self.total is None or self.completed >= self.total + complete_style = console.get_style( + self.finished_style if is_finished else self.complete_style + ) + _Segment = Segment + if bar_count: + yield _Segment(bar * bar_count, complete_style) + if half_bar_count: + yield _Segment(half_bar_right * half_bar_count, complete_style) + + if not console.no_color: + remaining_bars = width - bar_count - half_bar_count + if remaining_bars and console.color_system is not None: + if not half_bar_count and bar_count: + yield _Segment(half_bar_left, style) + remaining_bars -= 1 + if remaining_bars: + yield _Segment(bar * remaining_bars, style) + + def __rich_measure__( + self, console: Console, options: ConsoleOptions + ) -> Measurement: + return ( + Measurement(self.width, self.width) + if self.width is not None + else Measurement(4, options.max_width) + ) + + +if __name__ == "__main__": # pragma: no cover + console = Console() + bar = ProgressBar(width=50, total=100) + + import time + + console.show_cursor(False) + for n in range(0, 101, 1): + bar.update(n) + console.print(bar) + console.file.write("\r") + time.sleep(0.05) + console.show_cursor(True) + console.print() diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/prompt.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/prompt.py new file mode 100644 index 0000000..75ff048 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/prompt.py @@ -0,0 +1,375 @@ +from typing import Any, Generic, List, Optional, TextIO, TypeVar, Union, overload + +from . import get_console +from .console import Console +from .text import Text, TextType + +PromptType = TypeVar("PromptType") +DefaultType = TypeVar("DefaultType") + + +class PromptError(Exception): + """Exception base class for prompt related errors.""" + + +class InvalidResponse(PromptError): + """Exception to indicate a response was invalid. Raise this within process_response() to indicate an error + and provide an error message. + + Args: + message (Union[str, Text]): Error message. + """ + + def __init__(self, message: TextType) -> None: + self.message = message + + def __rich__(self) -> TextType: + return self.message + + +class PromptBase(Generic[PromptType]): + """Ask the user for input until a valid response is received. This is the base class, see one of + the concrete classes for examples. + + Args: + prompt (TextType, optional): Prompt text. Defaults to "". + console (Console, optional): A Console instance or None to use global console. Defaults to None. + password (bool, optional): Enable password input. Defaults to False. + choices (List[str], optional): A list of valid choices. Defaults to None. + show_default (bool, optional): Show default in prompt. Defaults to True. + show_choices (bool, optional): Show choices in prompt. Defaults to True. + """ + + response_type: type = str + + validate_error_message = "[prompt.invalid]Please enter a valid value" + illegal_choice_message = ( + "[prompt.invalid.choice]Please select one of the available options" + ) + prompt_suffix = ": " + + choices: Optional[List[str]] = None + + def __init__( + self, + prompt: TextType = "", + *, + console: Optional[Console] = None, + password: bool = False, + choices: Optional[List[str]] = None, + show_default: bool = True, + show_choices: bool = True, + ) -> None: + self.console = console or get_console() + self.prompt = ( + Text.from_markup(prompt, style="prompt") + if isinstance(prompt, str) + else prompt + ) + self.password = password + if choices is not None: + self.choices = choices + self.show_default = show_default + self.show_choices = show_choices + + @classmethod + @overload + def ask( + cls, + prompt: TextType = "", + *, + console: Optional[Console] = None, + password: bool = False, + choices: Optional[List[str]] = None, + show_default: bool = True, + show_choices: bool = True, + default: DefaultType, + stream: Optional[TextIO] = None, + ) -> Union[DefaultType, PromptType]: + ... + + @classmethod + @overload + def ask( + cls, + prompt: TextType = "", + *, + console: Optional[Console] = None, + password: bool = False, + choices: Optional[List[str]] = None, + show_default: bool = True, + show_choices: bool = True, + stream: Optional[TextIO] = None, + ) -> PromptType: + ... + + @classmethod + def ask( + cls, + prompt: TextType = "", + *, + console: Optional[Console] = None, + password: bool = False, + choices: Optional[List[str]] = None, + show_default: bool = True, + show_choices: bool = True, + default: Any = ..., + stream: Optional[TextIO] = None, + ) -> Any: + """Shortcut to construct and run a prompt loop and return the result. + + Example: + >>> filename = Prompt.ask("Enter a filename") + + Args: + prompt (TextType, optional): Prompt text. Defaults to "". + console (Console, optional): A Console instance or None to use global console. Defaults to None. + password (bool, optional): Enable password input. Defaults to False. + choices (List[str], optional): A list of valid choices. Defaults to None. + show_default (bool, optional): Show default in prompt. Defaults to True. + show_choices (bool, optional): Show choices in prompt. Defaults to True. + stream (TextIO, optional): Optional text file open for reading to get input. Defaults to None. + """ + _prompt = cls( + prompt, + console=console, + password=password, + choices=choices, + show_default=show_default, + show_choices=show_choices, + ) + return _prompt(default=default, stream=stream) + + def render_default(self, default: DefaultType) -> Text: + """Turn the supplied default in to a Text instance. + + Args: + default (DefaultType): Default value. + + Returns: + Text: Text containing rendering of default value. + """ + return Text(f"({default})", "prompt.default") + + def make_prompt(self, default: DefaultType) -> Text: + """Make prompt text. + + Args: + default (DefaultType): Default value. + + Returns: + Text: Text to display in prompt. + """ + prompt = self.prompt.copy() + prompt.end = "" + + if self.show_choices and self.choices: + _choices = "/".join(self.choices) + choices = f"[{_choices}]" + prompt.append(" ") + prompt.append(choices, "prompt.choices") + + if ( + default != ... + and self.show_default + and isinstance(default, (str, self.response_type)) + ): + prompt.append(" ") + _default = self.render_default(default) + prompt.append(_default) + + prompt.append(self.prompt_suffix) + + return prompt + + @classmethod + def get_input( + cls, + console: Console, + prompt: TextType, + password: bool, + stream: Optional[TextIO] = None, + ) -> str: + """Get input from user. + + Args: + console (Console): Console instance. + prompt (TextType): Prompt text. + password (bool): Enable password entry. + + Returns: + str: String from user. + """ + return console.input(prompt, password=password, stream=stream) + + def check_choice(self, value: str) -> bool: + """Check value is in the list of valid choices. + + Args: + value (str): Value entered by user. + + Returns: + bool: True if choice was valid, otherwise False. + """ + assert self.choices is not None + return value.strip() in self.choices + + def process_response(self, value: str) -> PromptType: + """Process response from user, convert to prompt type. + + Args: + value (str): String typed by user. + + Raises: + InvalidResponse: If ``value`` is invalid. + + Returns: + PromptType: The value to be returned from ask method. + """ + value = value.strip() + try: + return_value: PromptType = self.response_type(value) + except ValueError: + raise InvalidResponse(self.validate_error_message) + + if self.choices is not None and not self.check_choice(value): + raise InvalidResponse(self.illegal_choice_message) + + return return_value + + def on_validate_error(self, value: str, error: InvalidResponse) -> None: + """Called to handle validation error. + + Args: + value (str): String entered by user. + error (InvalidResponse): Exception instance the initiated the error. + """ + self.console.print(error) + + def pre_prompt(self) -> None: + """Hook to display something before the prompt.""" + + @overload + def __call__(self, *, stream: Optional[TextIO] = None) -> PromptType: + ... + + @overload + def __call__( + self, *, default: DefaultType, stream: Optional[TextIO] = None + ) -> Union[PromptType, DefaultType]: + ... + + def __call__(self, *, default: Any = ..., stream: Optional[TextIO] = None) -> Any: + """Run the prompt loop. + + Args: + default (Any, optional): Optional default value. + + Returns: + PromptType: Processed value. + """ + while True: + self.pre_prompt() + prompt = self.make_prompt(default) + value = self.get_input(self.console, prompt, self.password, stream=stream) + if value == "" and default != ...: + return default + try: + return_value = self.process_response(value) + except InvalidResponse as error: + self.on_validate_error(value, error) + continue + else: + return return_value + + +class Prompt(PromptBase[str]): + """A prompt that returns a str. + + Example: + >>> name = Prompt.ask("Enter your name") + + + """ + + response_type = str + + +class IntPrompt(PromptBase[int]): + """A prompt that returns an integer. + + Example: + >>> burrito_count = IntPrompt.ask("How many burritos do you want to order") + + """ + + response_type = int + validate_error_message = "[prompt.invalid]Please enter a valid integer number" + + +class FloatPrompt(PromptBase[float]): + """A prompt that returns a float. + + Example: + >>> temperature = FloatPrompt.ask("Enter desired temperature") + + """ + + response_type = float + validate_error_message = "[prompt.invalid]Please enter a number" + + +class Confirm(PromptBase[bool]): + """A yes / no confirmation prompt. + + Example: + >>> if Confirm.ask("Continue"): + run_job() + + """ + + response_type = bool + validate_error_message = "[prompt.invalid]Please enter Y or N" + choices: List[str] = ["y", "n"] + + def render_default(self, default: DefaultType) -> Text: + """Render the default as (y) or (n) rather than True/False.""" + yes, no = self.choices + return Text(f"({yes})" if default else f"({no})", style="prompt.default") + + def process_response(self, value: str) -> bool: + """Convert choices to a bool.""" + value = value.strip().lower() + if value not in self.choices: + raise InvalidResponse(self.validate_error_message) + return value == self.choices[0] + + +if __name__ == "__main__": # pragma: no cover + from pip._vendor.rich import print + + if Confirm.ask("Run [i]prompt[/i] tests?", default=True): + while True: + result = IntPrompt.ask( + ":rocket: Enter a number between [b]1[/b] and [b]10[/b]", default=5 + ) + if result >= 1 and result <= 10: + break + print(":pile_of_poo: [prompt.invalid]Number must be between 1 and 10") + print(f"number={result}") + + while True: + password = Prompt.ask( + "Please enter a password [cyan](must be at least 5 characters)", + password=True, + ) + if len(password) >= 5: + break + print("[prompt.invalid]password too short") + print(f"password={password!r}") + + fruit = Prompt.ask("Enter a fruit", choices=["apple", "orange", "pear"]) + print(f"fruit={fruit!r}") + + else: + print("[b]OK :loudly_crying_face:") diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/protocol.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/protocol.py new file mode 100644 index 0000000..12ab237 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/protocol.py @@ -0,0 +1,42 @@ +from typing import Any, cast, Set, TYPE_CHECKING +from inspect import isclass + +if TYPE_CHECKING: + from pip._vendor.rich.console import RenderableType + +_GIBBERISH = """aihwerij235234ljsdnp34ksodfipwoe234234jlskjdf""" + + +def is_renderable(check_object: Any) -> bool: + """Check if an object may be rendered by Rich.""" + return ( + isinstance(check_object, str) + or hasattr(check_object, "__rich__") + or hasattr(check_object, "__rich_console__") + ) + + +def rich_cast(renderable: object) -> "RenderableType": + """Cast an object to a renderable by calling __rich__ if present. + + Args: + renderable (object): A potentially renderable object + + Returns: + object: The result of recursively calling __rich__. + """ + from pip._vendor.rich.console import RenderableType + + rich_visited_set: Set[type] = set() # Prevent potential infinite loop + while hasattr(renderable, "__rich__") and not isclass(renderable): + # Detect object which claim to have all the attributes + if hasattr(renderable, _GIBBERISH): + return repr(renderable) + cast_method = getattr(renderable, "__rich__") + renderable = cast_method() + renderable_type = type(renderable) + if renderable_type in rich_visited_set: + break + rich_visited_set.add(renderable_type) + + return cast(RenderableType, renderable) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/py.typed b/backend/.venv/Lib/site-packages/pip/_vendor/rich/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/region.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/region.py new file mode 100644 index 0000000..75b3631 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/region.py @@ -0,0 +1,10 @@ +from typing import NamedTuple + + +class Region(NamedTuple): + """Defines a rectangular region of the screen.""" + + x: int + y: int + width: int + height: int diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/repr.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/repr.py new file mode 100644 index 0000000..10efc42 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/repr.py @@ -0,0 +1,149 @@ +import inspect +from functools import partial +from typing import ( + Any, + Callable, + Iterable, + List, + Optional, + Tuple, + Type, + TypeVar, + Union, + overload, +) + +T = TypeVar("T") + + +Result = Iterable[Union[Any, Tuple[Any], Tuple[str, Any], Tuple[str, Any, Any]]] +RichReprResult = Result + + +class ReprError(Exception): + """An error occurred when attempting to build a repr.""" + + +@overload +def auto(cls: Optional[Type[T]]) -> Type[T]: + ... + + +@overload +def auto(*, angular: bool = False) -> Callable[[Type[T]], Type[T]]: + ... + + +def auto( + cls: Optional[Type[T]] = None, *, angular: Optional[bool] = None +) -> Union[Type[T], Callable[[Type[T]], Type[T]]]: + """Class decorator to create __repr__ from __rich_repr__""" + + def do_replace(cls: Type[T], angular: Optional[bool] = None) -> Type[T]: + def auto_repr(self: T) -> str: + """Create repr string from __rich_repr__""" + repr_str: List[str] = [] + append = repr_str.append + + angular: bool = getattr(self.__rich_repr__, "angular", False) # type: ignore[attr-defined] + for arg in self.__rich_repr__(): # type: ignore[attr-defined] + if isinstance(arg, tuple): + if len(arg) == 1: + append(repr(arg[0])) + else: + key, value, *default = arg + if key is None: + append(repr(value)) + else: + if default and default[0] == value: + continue + append(f"{key}={value!r}") + else: + append(repr(arg)) + if angular: + return f"<{self.__class__.__name__} {' '.join(repr_str)}>" + else: + return f"{self.__class__.__name__}({', '.join(repr_str)})" + + def auto_rich_repr(self: Type[T]) -> Result: + """Auto generate __rich_rep__ from signature of __init__""" + try: + signature = inspect.signature(self.__init__) + for name, param in signature.parameters.items(): + if param.kind == param.POSITIONAL_ONLY: + yield getattr(self, name) + elif param.kind in ( + param.POSITIONAL_OR_KEYWORD, + param.KEYWORD_ONLY, + ): + if param.default is param.empty: + yield getattr(self, param.name) + else: + yield param.name, getattr(self, param.name), param.default + except Exception as error: + raise ReprError( + f"Failed to auto generate __rich_repr__; {error}" + ) from None + + if not hasattr(cls, "__rich_repr__"): + auto_rich_repr.__doc__ = "Build a rich repr" + cls.__rich_repr__ = auto_rich_repr # type: ignore[attr-defined] + + auto_repr.__doc__ = "Return repr(self)" + cls.__repr__ = auto_repr # type: ignore[assignment] + if angular is not None: + cls.__rich_repr__.angular = angular # type: ignore[attr-defined] + return cls + + if cls is None: + return partial(do_replace, angular=angular) + else: + return do_replace(cls, angular=angular) + + +@overload +def rich_repr(cls: Optional[Type[T]]) -> Type[T]: + ... + + +@overload +def rich_repr(*, angular: bool = False) -> Callable[[Type[T]], Type[T]]: + ... + + +def rich_repr( + cls: Optional[Type[T]] = None, *, angular: bool = False +) -> Union[Type[T], Callable[[Type[T]], Type[T]]]: + if cls is None: + return auto(angular=angular) + else: + return auto(cls) + + +if __name__ == "__main__": + + @auto + class Foo: + def __rich_repr__(self) -> Result: + yield "foo" + yield "bar", {"shopping": ["eggs", "ham", "pineapple"]} + yield "buy", "hand sanitizer" + + foo = Foo() + from pip._vendor.rich.console import Console + + console = Console() + + console.rule("Standard repr") + console.print(foo) + + console.print(foo, width=60) + console.print(foo, width=30) + + console.rule("Angular repr") + Foo.__rich_repr__.angular = True # type: ignore[attr-defined] + + console.print(foo) + + console.print(foo, width=60) + console.print(foo, width=30) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/rule.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/rule.py new file mode 100644 index 0000000..fd00ce6 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/rule.py @@ -0,0 +1,130 @@ +from typing import Union + +from .align import AlignMethod +from .cells import cell_len, set_cell_size +from .console import Console, ConsoleOptions, RenderResult +from .jupyter import JupyterMixin +from .measure import Measurement +from .style import Style +from .text import Text + + +class Rule(JupyterMixin): + """A console renderable to draw a horizontal rule (line). + + Args: + title (Union[str, Text], optional): Text to render in the rule. Defaults to "". + characters (str, optional): Character(s) used to draw the line. Defaults to "─". + style (StyleType, optional): Style of Rule. Defaults to "rule.line". + end (str, optional): Character at end of Rule. defaults to "\\\\n" + align (str, optional): How to align the title, one of "left", "center", or "right". Defaults to "center". + """ + + def __init__( + self, + title: Union[str, Text] = "", + *, + characters: str = "─", + style: Union[str, Style] = "rule.line", + end: str = "\n", + align: AlignMethod = "center", + ) -> None: + if cell_len(characters) < 1: + raise ValueError( + "'characters' argument must have a cell width of at least 1" + ) + if align not in ("left", "center", "right"): + raise ValueError( + f'invalid value for align, expected "left", "center", "right" (not {align!r})' + ) + self.title = title + self.characters = characters + self.style = style + self.end = end + self.align = align + + def __repr__(self) -> str: + return f"Rule({self.title!r}, {self.characters!r})" + + def __rich_console__( + self, console: Console, options: ConsoleOptions + ) -> RenderResult: + width = options.max_width + + characters = ( + "-" + if (options.ascii_only and not self.characters.isascii()) + else self.characters + ) + + chars_len = cell_len(characters) + if not self.title: + yield self._rule_line(chars_len, width) + return + + if isinstance(self.title, Text): + title_text = self.title + else: + title_text = console.render_str(self.title, style="rule.text") + + title_text.plain = title_text.plain.replace("\n", " ") + title_text.expand_tabs() + + required_space = 4 if self.align == "center" else 2 + truncate_width = max(0, width - required_space) + if not truncate_width: + yield self._rule_line(chars_len, width) + return + + rule_text = Text(end=self.end) + if self.align == "center": + title_text.truncate(truncate_width, overflow="ellipsis") + side_width = (width - cell_len(title_text.plain)) // 2 + left = Text(characters * (side_width // chars_len + 1)) + left.truncate(side_width - 1) + right_length = width - cell_len(left.plain) - cell_len(title_text.plain) + right = Text(characters * (side_width // chars_len + 1)) + right.truncate(right_length) + rule_text.append(left.plain + " ", self.style) + rule_text.append(title_text) + rule_text.append(" " + right.plain, self.style) + elif self.align == "left": + title_text.truncate(truncate_width, overflow="ellipsis") + rule_text.append(title_text) + rule_text.append(" ") + rule_text.append(characters * (width - rule_text.cell_len), self.style) + elif self.align == "right": + title_text.truncate(truncate_width, overflow="ellipsis") + rule_text.append(characters * (width - title_text.cell_len - 1), self.style) + rule_text.append(" ") + rule_text.append(title_text) + + rule_text.plain = set_cell_size(rule_text.plain, width) + yield rule_text + + def _rule_line(self, chars_len: int, width: int) -> Text: + rule_text = Text(self.characters * ((width // chars_len) + 1), self.style) + rule_text.truncate(width) + rule_text.plain = set_cell_size(rule_text.plain, width) + return rule_text + + def __rich_measure__( + self, console: Console, options: ConsoleOptions + ) -> Measurement: + return Measurement(1, 1) + + +if __name__ == "__main__": # pragma: no cover + import sys + + from pip._vendor.rich.console import Console + + try: + text = sys.argv[1] + except IndexError: + text = "Hello, World" + console = Console() + console.print(Rule(title=text)) + + console = Console() + console.print(Rule("foo"), width=4) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/scope.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/scope.py new file mode 100644 index 0000000..c9d134c --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/scope.py @@ -0,0 +1,86 @@ +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, Optional, Tuple + +from .highlighter import ReprHighlighter +from .panel import Panel +from .pretty import Pretty +from .table import Table +from .text import Text, TextType + +if TYPE_CHECKING: + from .console import ConsoleRenderable + + +def render_scope( + scope: "Mapping[str, Any]", + *, + title: Optional[TextType] = None, + sort_keys: bool = True, + indent_guides: bool = False, + max_length: Optional[int] = None, + max_string: Optional[int] = None, +) -> "ConsoleRenderable": + """Render python variables in a given scope. + + Args: + scope (Mapping): A mapping containing variable names and values. + title (str, optional): Optional title. Defaults to None. + sort_keys (bool, optional): Enable sorting of items. Defaults to True. + indent_guides (bool, optional): Enable indentation guides. Defaults to False. + max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation. + Defaults to None. + max_string (int, optional): Maximum length of string before truncating, or None to disable. Defaults to None. + + Returns: + ConsoleRenderable: A renderable object. + """ + highlighter = ReprHighlighter() + items_table = Table.grid(padding=(0, 1), expand=False) + items_table.add_column(justify="right") + + def sort_items(item: Tuple[str, Any]) -> Tuple[bool, str]: + """Sort special variables first, then alphabetically.""" + key, _ = item + return (not key.startswith("__"), key.lower()) + + items = sorted(scope.items(), key=sort_items) if sort_keys else scope.items() + for key, value in items: + key_text = Text.assemble( + (key, "scope.key.special" if key.startswith("__") else "scope.key"), + (" =", "scope.equals"), + ) + items_table.add_row( + key_text, + Pretty( + value, + highlighter=highlighter, + indent_guides=indent_guides, + max_length=max_length, + max_string=max_string, + ), + ) + return Panel.fit( + items_table, + title=title, + border_style="scope.border", + padding=(0, 1), + ) + + +if __name__ == "__main__": # pragma: no cover + from pip._vendor.rich import print + + print() + + def test(foo: float, bar: float) -> None: + list_of_things = [1, 2, 3, None, 4, True, False, "Hello World"] + dict_of_things = { + "version": "1.1", + "method": "confirmFruitPurchase", + "params": [["apple", "orange", "mangoes", "pomelo"], 1.123], + "id": "194521489", + } + print(render_scope(locals(), title="[i]locals", sort_keys=False)) + + test(20.3423, 3.1427) + print() diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/screen.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/screen.py new file mode 100644 index 0000000..7f416e1 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/screen.py @@ -0,0 +1,54 @@ +from typing import Optional, TYPE_CHECKING + +from .segment import Segment +from .style import StyleType +from ._loop import loop_last + + +if TYPE_CHECKING: + from .console import ( + Console, + ConsoleOptions, + RenderResult, + RenderableType, + Group, + ) + + +class Screen: + """A renderable that fills the terminal screen and crops excess. + + Args: + renderable (RenderableType): Child renderable. + style (StyleType, optional): Optional background style. Defaults to None. + """ + + renderable: "RenderableType" + + def __init__( + self, + *renderables: "RenderableType", + style: Optional[StyleType] = None, + application_mode: bool = False, + ) -> None: + from pip._vendor.rich.console import Group + + self.renderable = Group(*renderables) + self.style = style + self.application_mode = application_mode + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + width, height = options.size + style = console.get_style(self.style) if self.style else None + render_options = options.update(width=width, height=height) + lines = console.render_lines( + self.renderable or "", render_options, style=style, pad=True + ) + lines = Segment.set_shape(lines, width, height, style=style) + new_line = Segment("\n\r") if self.application_mode else Segment.line() + for last, line in loop_last(lines): + yield from line + if not last: + yield new_line diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/segment.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/segment.py new file mode 100644 index 0000000..93edbbd --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/segment.py @@ -0,0 +1,738 @@ +from enum import IntEnum +from functools import lru_cache +from itertools import filterfalse +from logging import getLogger +from operator import attrgetter +from typing import ( + TYPE_CHECKING, + Dict, + Iterable, + List, + NamedTuple, + Optional, + Sequence, + Tuple, + Type, + Union, +) + +from .cells import ( + _is_single_cell_widths, + cached_cell_len, + cell_len, + get_character_cell_size, + set_cell_size, +) +from .repr import Result, rich_repr +from .style import Style + +if TYPE_CHECKING: + from .console import Console, ConsoleOptions, RenderResult + +log = getLogger("rich") + + +class ControlType(IntEnum): + """Non-printable control codes which typically translate to ANSI codes.""" + + BELL = 1 + CARRIAGE_RETURN = 2 + HOME = 3 + CLEAR = 4 + SHOW_CURSOR = 5 + HIDE_CURSOR = 6 + ENABLE_ALT_SCREEN = 7 + DISABLE_ALT_SCREEN = 8 + CURSOR_UP = 9 + CURSOR_DOWN = 10 + CURSOR_FORWARD = 11 + CURSOR_BACKWARD = 12 + CURSOR_MOVE_TO_COLUMN = 13 + CURSOR_MOVE_TO = 14 + ERASE_IN_LINE = 15 + SET_WINDOW_TITLE = 16 + + +ControlCode = Union[ + Tuple[ControlType], + Tuple[ControlType, Union[int, str]], + Tuple[ControlType, int, int], +] + + +@rich_repr() +class Segment(NamedTuple): + """A piece of text with associated style. Segments are produced by the Console render process and + are ultimately converted in to strings to be written to the terminal. + + Args: + text (str): A piece of text. + style (:class:`~rich.style.Style`, optional): An optional style to apply to the text. + control (Tuple[ControlCode], optional): Optional sequence of control codes. + + Attributes: + cell_length (int): The cell length of this Segment. + """ + + text: str + style: Optional[Style] = None + control: Optional[Sequence[ControlCode]] = None + + @property + def cell_length(self) -> int: + """The number of terminal cells required to display self.text. + + Returns: + int: A number of cells. + """ + text, _style, control = self + return 0 if control else cell_len(text) + + def __rich_repr__(self) -> Result: + yield self.text + if self.control is None: + if self.style is not None: + yield self.style + else: + yield self.style + yield self.control + + def __bool__(self) -> bool: + """Check if the segment contains text.""" + return bool(self.text) + + @property + def is_control(self) -> bool: + """Check if the segment contains control codes.""" + return self.control is not None + + @classmethod + @lru_cache(1024 * 16) + def _split_cells(cls, segment: "Segment", cut: int) -> Tuple["Segment", "Segment"]: + text, style, control = segment + _Segment = Segment + + cell_length = segment.cell_length + if cut >= cell_length: + return segment, _Segment("", style, control) + + cell_size = get_character_cell_size + + pos = int((cut / cell_length) * (len(text) - 1)) + + before = text[:pos] + cell_pos = cell_len(before) + if cell_pos == cut: + return ( + _Segment(before, style, control), + _Segment(text[pos:], style, control), + ) + while pos < len(text): + char = text[pos] + pos += 1 + cell_pos += cell_size(char) + before = text[:pos] + if cell_pos == cut: + return ( + _Segment(before, style, control), + _Segment(text[pos:], style, control), + ) + if cell_pos > cut: + return ( + _Segment(before[: pos - 1] + " ", style, control), + _Segment(" " + text[pos:], style, control), + ) + + raise AssertionError("Will never reach here") + + def split_cells(self, cut: int) -> Tuple["Segment", "Segment"]: + """Split segment in to two segments at the specified column. + + If the cut point falls in the middle of a 2-cell wide character then it is replaced + by two spaces, to preserve the display width of the parent segment. + + Returns: + Tuple[Segment, Segment]: Two segments. + """ + text, style, control = self + + if _is_single_cell_widths(text): + # Fast path with all 1 cell characters + if cut >= len(text): + return self, Segment("", style, control) + return ( + Segment(text[:cut], style, control), + Segment(text[cut:], style, control), + ) + + return self._split_cells(self, cut) + + @classmethod + def line(cls) -> "Segment": + """Make a new line segment.""" + return cls("\n") + + @classmethod + def apply_style( + cls, + segments: Iterable["Segment"], + style: Optional[Style] = None, + post_style: Optional[Style] = None, + ) -> Iterable["Segment"]: + """Apply style(s) to an iterable of segments. + + Returns an iterable of segments where the style is replaced by ``style + segment.style + post_style``. + + Args: + segments (Iterable[Segment]): Segments to process. + style (Style, optional): Base style. Defaults to None. + post_style (Style, optional): Style to apply on top of segment style. Defaults to None. + + Returns: + Iterable[Segments]: A new iterable of segments (possibly the same iterable). + """ + result_segments = segments + if style: + apply = style.__add__ + result_segments = ( + cls(text, None if control else apply(_style), control) + for text, _style, control in result_segments + ) + if post_style: + result_segments = ( + cls( + text, + ( + None + if control + else (_style + post_style if _style else post_style) + ), + control, + ) + for text, _style, control in result_segments + ) + return result_segments + + @classmethod + def filter_control( + cls, segments: Iterable["Segment"], is_control: bool = False + ) -> Iterable["Segment"]: + """Filter segments by ``is_control`` attribute. + + Args: + segments (Iterable[Segment]): An iterable of Segment instances. + is_control (bool, optional): is_control flag to match in search. + + Returns: + Iterable[Segment]: And iterable of Segment instances. + + """ + if is_control: + return filter(attrgetter("control"), segments) + else: + return filterfalse(attrgetter("control"), segments) + + @classmethod + def split_lines(cls, segments: Iterable["Segment"]) -> Iterable[List["Segment"]]: + """Split a sequence of segments in to a list of lines. + + Args: + segments (Iterable[Segment]): Segments potentially containing line feeds. + + Yields: + Iterable[List[Segment]]: Iterable of segment lists, one per line. + """ + line: List[Segment] = [] + append = line.append + + for segment in segments: + if "\n" in segment.text and not segment.control: + text, style, _ = segment + while text: + _text, new_line, text = text.partition("\n") + if _text: + append(cls(_text, style)) + if new_line: + yield line + line = [] + append = line.append + else: + append(segment) + if line: + yield line + + @classmethod + def split_and_crop_lines( + cls, + segments: Iterable["Segment"], + length: int, + style: Optional[Style] = None, + pad: bool = True, + include_new_lines: bool = True, + ) -> Iterable[List["Segment"]]: + """Split segments in to lines, and crop lines greater than a given length. + + Args: + segments (Iterable[Segment]): An iterable of segments, probably + generated from console.render. + length (int): Desired line length. + style (Style, optional): Style to use for any padding. + pad (bool): Enable padding of lines that are less than `length`. + + Returns: + Iterable[List[Segment]]: An iterable of lines of segments. + """ + line: List[Segment] = [] + append = line.append + + adjust_line_length = cls.adjust_line_length + new_line_segment = cls("\n") + + for segment in segments: + if "\n" in segment.text and not segment.control: + text, segment_style, _ = segment + while text: + _text, new_line, text = text.partition("\n") + if _text: + append(cls(_text, segment_style)) + if new_line: + cropped_line = adjust_line_length( + line, length, style=style, pad=pad + ) + if include_new_lines: + cropped_line.append(new_line_segment) + yield cropped_line + line.clear() + else: + append(segment) + if line: + yield adjust_line_length(line, length, style=style, pad=pad) + + @classmethod + def adjust_line_length( + cls, + line: List["Segment"], + length: int, + style: Optional[Style] = None, + pad: bool = True, + ) -> List["Segment"]: + """Adjust a line to a given width (cropping or padding as required). + + Args: + segments (Iterable[Segment]): A list of segments in a single line. + length (int): The desired width of the line. + style (Style, optional): The style of padding if used (space on the end). Defaults to None. + pad (bool, optional): Pad lines with spaces if they are shorter than `length`. Defaults to True. + + Returns: + List[Segment]: A line of segments with the desired length. + """ + line_length = sum(segment.cell_length for segment in line) + new_line: List[Segment] + + if line_length < length: + if pad: + new_line = line + [cls(" " * (length - line_length), style)] + else: + new_line = line[:] + elif line_length > length: + new_line = [] + append = new_line.append + line_length = 0 + for segment in line: + segment_length = segment.cell_length + if line_length + segment_length < length or segment.control: + append(segment) + line_length += segment_length + else: + text, segment_style, _ = segment + text = set_cell_size(text, length - line_length) + append(cls(text, segment_style)) + break + else: + new_line = line[:] + return new_line + + @classmethod + def get_line_length(cls, line: List["Segment"]) -> int: + """Get the length of list of segments. + + Args: + line (List[Segment]): A line encoded as a list of Segments (assumes no '\\\\n' characters), + + Returns: + int: The length of the line. + """ + _cell_len = cell_len + return sum(_cell_len(text) for text, style, control in line if not control) + + @classmethod + def get_shape(cls, lines: List[List["Segment"]]) -> Tuple[int, int]: + """Get the shape (enclosing rectangle) of a list of lines. + + Args: + lines (List[List[Segment]]): A list of lines (no '\\\\n' characters). + + Returns: + Tuple[int, int]: Width and height in characters. + """ + get_line_length = cls.get_line_length + max_width = max(get_line_length(line) for line in lines) if lines else 0 + return (max_width, len(lines)) + + @classmethod + def set_shape( + cls, + lines: List[List["Segment"]], + width: int, + height: Optional[int] = None, + style: Optional[Style] = None, + new_lines: bool = False, + ) -> List[List["Segment"]]: + """Set the shape of a list of lines (enclosing rectangle). + + Args: + lines (List[List[Segment]]): A list of lines. + width (int): Desired width. + height (int, optional): Desired height or None for no change. + style (Style, optional): Style of any padding added. + new_lines (bool, optional): Padded lines should include "\n". Defaults to False. + + Returns: + List[List[Segment]]: New list of lines. + """ + _height = height or len(lines) + + blank = ( + [cls(" " * width + "\n", style)] if new_lines else [cls(" " * width, style)] + ) + + adjust_line_length = cls.adjust_line_length + shaped_lines = lines[:_height] + shaped_lines[:] = [ + adjust_line_length(line, width, style=style) for line in lines + ] + if len(shaped_lines) < _height: + shaped_lines.extend([blank] * (_height - len(shaped_lines))) + return shaped_lines + + @classmethod + def align_top( + cls: Type["Segment"], + lines: List[List["Segment"]], + width: int, + height: int, + style: Style, + new_lines: bool = False, + ) -> List[List["Segment"]]: + """Aligns lines to top (adds extra lines to bottom as required). + + Args: + lines (List[List[Segment]]): A list of lines. + width (int): Desired width. + height (int, optional): Desired height or None for no change. + style (Style): Style of any padding added. + new_lines (bool, optional): Padded lines should include "\n". Defaults to False. + + Returns: + List[List[Segment]]: New list of lines. + """ + extra_lines = height - len(lines) + if not extra_lines: + return lines[:] + lines = lines[:height] + blank = cls(" " * width + "\n", style) if new_lines else cls(" " * width, style) + lines = lines + [[blank]] * extra_lines + return lines + + @classmethod + def align_bottom( + cls: Type["Segment"], + lines: List[List["Segment"]], + width: int, + height: int, + style: Style, + new_lines: bool = False, + ) -> List[List["Segment"]]: + """Aligns render to bottom (adds extra lines above as required). + + Args: + lines (List[List[Segment]]): A list of lines. + width (int): Desired width. + height (int, optional): Desired height or None for no change. + style (Style): Style of any padding added. Defaults to None. + new_lines (bool, optional): Padded lines should include "\n". Defaults to False. + + Returns: + List[List[Segment]]: New list of lines. + """ + extra_lines = height - len(lines) + if not extra_lines: + return lines[:] + lines = lines[:height] + blank = cls(" " * width + "\n", style) if new_lines else cls(" " * width, style) + lines = [[blank]] * extra_lines + lines + return lines + + @classmethod + def align_middle( + cls: Type["Segment"], + lines: List[List["Segment"]], + width: int, + height: int, + style: Style, + new_lines: bool = False, + ) -> List[List["Segment"]]: + """Aligns lines to middle (adds extra lines to above and below as required). + + Args: + lines (List[List[Segment]]): A list of lines. + width (int): Desired width. + height (int, optional): Desired height or None for no change. + style (Style): Style of any padding added. + new_lines (bool, optional): Padded lines should include "\n". Defaults to False. + + Returns: + List[List[Segment]]: New list of lines. + """ + extra_lines = height - len(lines) + if not extra_lines: + return lines[:] + lines = lines[:height] + blank = cls(" " * width + "\n", style) if new_lines else cls(" " * width, style) + top_lines = extra_lines // 2 + bottom_lines = extra_lines - top_lines + lines = [[blank]] * top_lines + lines + [[blank]] * bottom_lines + return lines + + @classmethod + def simplify(cls, segments: Iterable["Segment"]) -> Iterable["Segment"]: + """Simplify an iterable of segments by combining contiguous segments with the same style. + + Args: + segments (Iterable[Segment]): An iterable of segments. + + Returns: + Iterable[Segment]: A possibly smaller iterable of segments that will render the same way. + """ + iter_segments = iter(segments) + try: + last_segment = next(iter_segments) + except StopIteration: + return + + _Segment = Segment + for segment in iter_segments: + if last_segment.style == segment.style and not segment.control: + last_segment = _Segment( + last_segment.text + segment.text, last_segment.style + ) + else: + yield last_segment + last_segment = segment + yield last_segment + + @classmethod + def strip_links(cls, segments: Iterable["Segment"]) -> Iterable["Segment"]: + """Remove all links from an iterable of styles. + + Args: + segments (Iterable[Segment]): An iterable segments. + + Yields: + Segment: Segments with link removed. + """ + for segment in segments: + if segment.control or segment.style is None: + yield segment + else: + text, style, _control = segment + yield cls(text, style.update_link(None) if style else None) + + @classmethod + def strip_styles(cls, segments: Iterable["Segment"]) -> Iterable["Segment"]: + """Remove all styles from an iterable of segments. + + Args: + segments (Iterable[Segment]): An iterable segments. + + Yields: + Segment: Segments with styles replace with None + """ + for text, _style, control in segments: + yield cls(text, None, control) + + @classmethod + def remove_color(cls, segments: Iterable["Segment"]) -> Iterable["Segment"]: + """Remove all color from an iterable of segments. + + Args: + segments (Iterable[Segment]): An iterable segments. + + Yields: + Segment: Segments with colorless style. + """ + + cache: Dict[Style, Style] = {} + for text, style, control in segments: + if style: + colorless_style = cache.get(style) + if colorless_style is None: + colorless_style = style.without_color + cache[style] = colorless_style + yield cls(text, colorless_style, control) + else: + yield cls(text, None, control) + + @classmethod + def divide( + cls, segments: Iterable["Segment"], cuts: Iterable[int] + ) -> Iterable[List["Segment"]]: + """Divides an iterable of segments in to portions. + + Args: + cuts (Iterable[int]): Cell positions where to divide. + + Yields: + [Iterable[List[Segment]]]: An iterable of Segments in List. + """ + split_segments: List["Segment"] = [] + add_segment = split_segments.append + + iter_cuts = iter(cuts) + + while True: + cut = next(iter_cuts, -1) + if cut == -1: + return [] + if cut != 0: + break + yield [] + pos = 0 + + segments_clear = split_segments.clear + segments_copy = split_segments.copy + + _cell_len = cached_cell_len + for segment in segments: + text, _style, control = segment + while text: + end_pos = pos if control else pos + _cell_len(text) + if end_pos < cut: + add_segment(segment) + pos = end_pos + break + + if end_pos == cut: + add_segment(segment) + yield segments_copy() + segments_clear() + pos = end_pos + + cut = next(iter_cuts, -1) + if cut == -1: + if split_segments: + yield segments_copy() + return + + break + + else: + before, segment = segment.split_cells(cut - pos) + text, _style, control = segment + add_segment(before) + yield segments_copy() + segments_clear() + pos = cut + + cut = next(iter_cuts, -1) + if cut == -1: + if split_segments: + yield segments_copy() + return + + yield segments_copy() + + +class Segments: + """A simple renderable to render an iterable of segments. This class may be useful if + you want to print segments outside of a __rich_console__ method. + + Args: + segments (Iterable[Segment]): An iterable of segments. + new_lines (bool, optional): Add new lines between segments. Defaults to False. + """ + + def __init__(self, segments: Iterable[Segment], new_lines: bool = False) -> None: + self.segments = list(segments) + self.new_lines = new_lines + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + if self.new_lines: + line = Segment.line() + for segment in self.segments: + yield segment + yield line + else: + yield from self.segments + + +class SegmentLines: + def __init__(self, lines: Iterable[List[Segment]], new_lines: bool = False) -> None: + """A simple renderable containing a number of lines of segments. May be used as an intermediate + in rendering process. + + Args: + lines (Iterable[List[Segment]]): Lists of segments forming lines. + new_lines (bool, optional): Insert new lines after each line. Defaults to False. + """ + self.lines = list(lines) + self.new_lines = new_lines + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + if self.new_lines: + new_line = Segment.line() + for line in self.lines: + yield from line + yield new_line + else: + for line in self.lines: + yield from line + + +if __name__ == "__main__": # pragma: no cover + from pip._vendor.rich.console import Console + from pip._vendor.rich.syntax import Syntax + from pip._vendor.rich.text import Text + + code = """from rich.console import Console +console = Console() +text = Text.from_markup("Hello, [bold magenta]World[/]!") +console.print(text)""" + + text = Text.from_markup("Hello, [bold magenta]World[/]!") + + console = Console() + + console.rule("rich.Segment") + console.print( + "A Segment is the last step in the Rich render process before generating text with ANSI codes." + ) + console.print("\nConsider the following code:\n") + console.print(Syntax(code, "python", line_numbers=True)) + console.print() + console.print( + "When you call [b]print()[/b], Rich [i]renders[/i] the object in to the following:\n" + ) + fragments = list(console.render(text)) + console.print(fragments) + console.print() + console.print("The Segments are then processed to produce the following output:\n") + console.print(text) + console.print( + "\nYou will only need to know this if you are implementing your own Rich renderables." + ) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/spinner.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/spinner.py new file mode 100644 index 0000000..91ea630 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/spinner.py @@ -0,0 +1,137 @@ +from typing import cast, List, Optional, TYPE_CHECKING, Union + +from ._spinners import SPINNERS +from .measure import Measurement +from .table import Table +from .text import Text + +if TYPE_CHECKING: + from .console import Console, ConsoleOptions, RenderResult, RenderableType + from .style import StyleType + + +class Spinner: + """A spinner animation. + + Args: + name (str): Name of spinner (run python -m rich.spinner). + text (RenderableType, optional): A renderable to display at the right of the spinner (str or Text typically). Defaults to "". + style (StyleType, optional): Style for spinner animation. Defaults to None. + speed (float, optional): Speed factor for animation. Defaults to 1.0. + + Raises: + KeyError: If name isn't one of the supported spinner animations. + """ + + def __init__( + self, + name: str, + text: "RenderableType" = "", + *, + style: Optional["StyleType"] = None, + speed: float = 1.0, + ) -> None: + try: + spinner = SPINNERS[name] + except KeyError: + raise KeyError(f"no spinner called {name!r}") + self.text: "Union[RenderableType, Text]" = ( + Text.from_markup(text) if isinstance(text, str) else text + ) + self.frames = cast(List[str], spinner["frames"])[:] + self.interval = cast(float, spinner["interval"]) + self.start_time: Optional[float] = None + self.style = style + self.speed = speed + self.frame_no_offset: float = 0.0 + self._update_speed = 0.0 + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + yield self.render(console.get_time()) + + def __rich_measure__( + self, console: "Console", options: "ConsoleOptions" + ) -> Measurement: + text = self.render(0) + return Measurement.get(console, options, text) + + def render(self, time: float) -> "RenderableType": + """Render the spinner for a given time. + + Args: + time (float): Time in seconds. + + Returns: + RenderableType: A renderable containing animation frame. + """ + if self.start_time is None: + self.start_time = time + + frame_no = ((time - self.start_time) * self.speed) / ( + self.interval / 1000.0 + ) + self.frame_no_offset + frame = Text( + self.frames[int(frame_no) % len(self.frames)], style=self.style or "" + ) + + if self._update_speed: + self.frame_no_offset = frame_no + self.start_time = time + self.speed = self._update_speed + self._update_speed = 0.0 + + if not self.text: + return frame + elif isinstance(self.text, (str, Text)): + return Text.assemble(frame, " ", self.text) + else: + table = Table.grid(padding=1) + table.add_row(frame, self.text) + return table + + def update( + self, + *, + text: "RenderableType" = "", + style: Optional["StyleType"] = None, + speed: Optional[float] = None, + ) -> None: + """Updates attributes of a spinner after it has been started. + + Args: + text (RenderableType, optional): A renderable to display at the right of the spinner (str or Text typically). Defaults to "". + style (StyleType, optional): Style for spinner animation. Defaults to None. + speed (float, optional): Speed factor for animation. Defaults to None. + """ + if text: + self.text = Text.from_markup(text) if isinstance(text, str) else text + if style: + self.style = style + if speed: + self._update_speed = speed + + +if __name__ == "__main__": # pragma: no cover + from time import sleep + + from .columns import Columns + from .panel import Panel + from .live import Live + + all_spinners = Columns( + [ + Spinner(spinner_name, text=Text(repr(spinner_name), style="green")) + for spinner_name in sorted(SPINNERS.keys()) + ], + column_first=True, + expand=True, + ) + + with Live( + Panel(all_spinners, title="Spinners", border_style="blue"), + refresh_per_second=20, + ) as live: + while True: + sleep(0.1) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/status.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/status.py new file mode 100644 index 0000000..6574483 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/status.py @@ -0,0 +1,131 @@ +from types import TracebackType +from typing import Optional, Type + +from .console import Console, RenderableType +from .jupyter import JupyterMixin +from .live import Live +from .spinner import Spinner +from .style import StyleType + + +class Status(JupyterMixin): + """Displays a status indicator with a 'spinner' animation. + + Args: + status (RenderableType): A status renderable (str or Text typically). + console (Console, optional): Console instance to use, or None for global console. Defaults to None. + spinner (str, optional): Name of spinner animation (see python -m rich.spinner). Defaults to "dots". + spinner_style (StyleType, optional): Style of spinner. Defaults to "status.spinner". + speed (float, optional): Speed factor for spinner animation. Defaults to 1.0. + refresh_per_second (float, optional): Number of refreshes per second. Defaults to 12.5. + """ + + def __init__( + self, + status: RenderableType, + *, + console: Optional[Console] = None, + spinner: str = "dots", + spinner_style: StyleType = "status.spinner", + speed: float = 1.0, + refresh_per_second: float = 12.5, + ): + self.status = status + self.spinner_style = spinner_style + self.speed = speed + self._spinner = Spinner(spinner, text=status, style=spinner_style, speed=speed) + self._live = Live( + self.renderable, + console=console, + refresh_per_second=refresh_per_second, + transient=True, + ) + + @property + def renderable(self) -> Spinner: + return self._spinner + + @property + def console(self) -> "Console": + """Get the Console used by the Status objects.""" + return self._live.console + + def update( + self, + status: Optional[RenderableType] = None, + *, + spinner: Optional[str] = None, + spinner_style: Optional[StyleType] = None, + speed: Optional[float] = None, + ) -> None: + """Update status. + + Args: + status (Optional[RenderableType], optional): New status renderable or None for no change. Defaults to None. + spinner (Optional[str], optional): New spinner or None for no change. Defaults to None. + spinner_style (Optional[StyleType], optional): New spinner style or None for no change. Defaults to None. + speed (Optional[float], optional): Speed factor for spinner animation or None for no change. Defaults to None. + """ + if status is not None: + self.status = status + if spinner_style is not None: + self.spinner_style = spinner_style + if speed is not None: + self.speed = speed + if spinner is not None: + self._spinner = Spinner( + spinner, text=self.status, style=self.spinner_style, speed=self.speed + ) + self._live.update(self.renderable, refresh=True) + else: + self._spinner.update( + text=self.status, style=self.spinner_style, speed=self.speed + ) + + def start(self) -> None: + """Start the status animation.""" + self._live.start() + + def stop(self) -> None: + """Stop the spinner animation.""" + self._live.stop() + + def __rich__(self) -> RenderableType: + return self.renderable + + def __enter__(self) -> "Status": + self.start() + return self + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + self.stop() + + +if __name__ == "__main__": # pragma: no cover + from time import sleep + + from .console import Console + + console = Console() + with console.status("[magenta]Covid detector booting up") as status: + sleep(3) + console.log("Importing advanced AI") + sleep(3) + console.log("Advanced Covid AI Ready") + sleep(3) + status.update(status="[bold blue] Scanning for Covid", spinner="earth") + sleep(3) + console.log("Found 10,000,000,000 copies of Covid32.exe") + sleep(3) + status.update( + status="[bold red]Moving Covid32.exe to Trash", + spinner="bouncingBall", + spinner_style="yellow", + ) + sleep(5) + console.print("[bold green]Covid deleted successfully") diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/style.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/style.py new file mode 100644 index 0000000..313c889 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/style.py @@ -0,0 +1,796 @@ +import sys +from functools import lru_cache +from marshal import dumps, loads +from random import randint +from typing import Any, Dict, Iterable, List, Optional, Type, Union, cast + +from . import errors +from .color import Color, ColorParseError, ColorSystem, blend_rgb +from .repr import Result, rich_repr +from .terminal_theme import DEFAULT_TERMINAL_THEME, TerminalTheme + +# Style instances and style definitions are often interchangeable +StyleType = Union[str, "Style"] + + +class _Bit: + """A descriptor to get/set a style attribute bit.""" + + __slots__ = ["bit"] + + def __init__(self, bit_no: int) -> None: + self.bit = 1 << bit_no + + def __get__(self, obj: "Style", objtype: Type["Style"]) -> Optional[bool]: + if obj._set_attributes & self.bit: + return obj._attributes & self.bit != 0 + return None + + +@rich_repr +class Style: + """A terminal style. + + A terminal style consists of a color (`color`), a background color (`bgcolor`), and a number of attributes, such + as bold, italic etc. The attributes have 3 states: they can either be on + (``True``), off (``False``), or not set (``None``). + + Args: + color (Union[Color, str], optional): Color of terminal text. Defaults to None. + bgcolor (Union[Color, str], optional): Color of terminal background. Defaults to None. + bold (bool, optional): Enable bold text. Defaults to None. + dim (bool, optional): Enable dim text. Defaults to None. + italic (bool, optional): Enable italic text. Defaults to None. + underline (bool, optional): Enable underlined text. Defaults to None. + blink (bool, optional): Enabled blinking text. Defaults to None. + blink2 (bool, optional): Enable fast blinking text. Defaults to None. + reverse (bool, optional): Enabled reverse text. Defaults to None. + conceal (bool, optional): Enable concealed text. Defaults to None. + strike (bool, optional): Enable strikethrough text. Defaults to None. + underline2 (bool, optional): Enable doubly underlined text. Defaults to None. + frame (bool, optional): Enable framed text. Defaults to None. + encircle (bool, optional): Enable encircled text. Defaults to None. + overline (bool, optional): Enable overlined text. Defaults to None. + link (str, link): Link URL. Defaults to None. + + """ + + _color: Optional[Color] + _bgcolor: Optional[Color] + _attributes: int + _set_attributes: int + _hash: Optional[int] + _null: bool + _meta: Optional[bytes] + + __slots__ = [ + "_color", + "_bgcolor", + "_attributes", + "_set_attributes", + "_link", + "_link_id", + "_ansi", + "_style_definition", + "_hash", + "_null", + "_meta", + ] + + # maps bits on to SGR parameter + _style_map = { + 0: "1", + 1: "2", + 2: "3", + 3: "4", + 4: "5", + 5: "6", + 6: "7", + 7: "8", + 8: "9", + 9: "21", + 10: "51", + 11: "52", + 12: "53", + } + + STYLE_ATTRIBUTES = { + "dim": "dim", + "d": "dim", + "bold": "bold", + "b": "bold", + "italic": "italic", + "i": "italic", + "underline": "underline", + "u": "underline", + "blink": "blink", + "blink2": "blink2", + "reverse": "reverse", + "r": "reverse", + "conceal": "conceal", + "c": "conceal", + "strike": "strike", + "s": "strike", + "underline2": "underline2", + "uu": "underline2", + "frame": "frame", + "encircle": "encircle", + "overline": "overline", + "o": "overline", + } + + def __init__( + self, + *, + color: Optional[Union[Color, str]] = None, + bgcolor: Optional[Union[Color, str]] = None, + bold: Optional[bool] = None, + dim: Optional[bool] = None, + italic: Optional[bool] = None, + underline: Optional[bool] = None, + blink: Optional[bool] = None, + blink2: Optional[bool] = None, + reverse: Optional[bool] = None, + conceal: Optional[bool] = None, + strike: Optional[bool] = None, + underline2: Optional[bool] = None, + frame: Optional[bool] = None, + encircle: Optional[bool] = None, + overline: Optional[bool] = None, + link: Optional[str] = None, + meta: Optional[Dict[str, Any]] = None, + ): + self._ansi: Optional[str] = None + self._style_definition: Optional[str] = None + + def _make_color(color: Union[Color, str]) -> Color: + return color if isinstance(color, Color) else Color.parse(color) + + self._color = None if color is None else _make_color(color) + self._bgcolor = None if bgcolor is None else _make_color(bgcolor) + self._set_attributes = sum( + ( + bold is not None, + dim is not None and 2, + italic is not None and 4, + underline is not None and 8, + blink is not None and 16, + blink2 is not None and 32, + reverse is not None and 64, + conceal is not None and 128, + strike is not None and 256, + underline2 is not None and 512, + frame is not None and 1024, + encircle is not None and 2048, + overline is not None and 4096, + ) + ) + self._attributes = ( + sum( + ( + bold and 1 or 0, + dim and 2 or 0, + italic and 4 or 0, + underline and 8 or 0, + blink and 16 or 0, + blink2 and 32 or 0, + reverse and 64 or 0, + conceal and 128 or 0, + strike and 256 or 0, + underline2 and 512 or 0, + frame and 1024 or 0, + encircle and 2048 or 0, + overline and 4096 or 0, + ) + ) + if self._set_attributes + else 0 + ) + + self._link = link + self._meta = None if meta is None else dumps(meta) + self._link_id = ( + f"{randint(0, 999999)}{hash(self._meta)}" if (link or meta) else "" + ) + self._hash: Optional[int] = None + self._null = not (self._set_attributes or color or bgcolor or link or meta) + + @classmethod + def null(cls) -> "Style": + """Create an 'null' style, equivalent to Style(), but more performant.""" + return NULL_STYLE + + @classmethod + def from_color( + cls, color: Optional[Color] = None, bgcolor: Optional[Color] = None + ) -> "Style": + """Create a new style with colors and no attributes. + + Returns: + color (Optional[Color]): A (foreground) color, or None for no color. Defaults to None. + bgcolor (Optional[Color]): A (background) color, or None for no color. Defaults to None. + """ + style: Style = cls.__new__(Style) + style._ansi = None + style._style_definition = None + style._color = color + style._bgcolor = bgcolor + style._set_attributes = 0 + style._attributes = 0 + style._link = None + style._link_id = "" + style._meta = None + style._null = not (color or bgcolor) + style._hash = None + return style + + @classmethod + def from_meta(cls, meta: Optional[Dict[str, Any]]) -> "Style": + """Create a new style with meta data. + + Returns: + meta (Optional[Dict[str, Any]]): A dictionary of meta data. Defaults to None. + """ + style: Style = cls.__new__(Style) + style._ansi = None + style._style_definition = None + style._color = None + style._bgcolor = None + style._set_attributes = 0 + style._attributes = 0 + style._link = None + style._meta = dumps(meta) + style._link_id = f"{randint(0, 999999)}{hash(style._meta)}" + style._hash = None + style._null = not (meta) + return style + + @classmethod + def on(cls, meta: Optional[Dict[str, Any]] = None, **handlers: Any) -> "Style": + """Create a blank style with meta information. + + Example: + style = Style.on(click=self.on_click) + + Args: + meta (Optional[Dict[str, Any]], optional): An optional dict of meta information. + **handlers (Any): Keyword arguments are translated in to handlers. + + Returns: + Style: A Style with meta information attached. + """ + meta = {} if meta is None else meta + meta.update({f"@{key}": value for key, value in handlers.items()}) + return cls.from_meta(meta) + + bold = _Bit(0) + dim = _Bit(1) + italic = _Bit(2) + underline = _Bit(3) + blink = _Bit(4) + blink2 = _Bit(5) + reverse = _Bit(6) + conceal = _Bit(7) + strike = _Bit(8) + underline2 = _Bit(9) + frame = _Bit(10) + encircle = _Bit(11) + overline = _Bit(12) + + @property + def link_id(self) -> str: + """Get a link id, used in ansi code for links.""" + return self._link_id + + def __str__(self) -> str: + """Re-generate style definition from attributes.""" + if self._style_definition is None: + attributes: List[str] = [] + append = attributes.append + bits = self._set_attributes + if bits & 0b0000000001111: + if bits & 1: + append("bold" if self.bold else "not bold") + if bits & (1 << 1): + append("dim" if self.dim else "not dim") + if bits & (1 << 2): + append("italic" if self.italic else "not italic") + if bits & (1 << 3): + append("underline" if self.underline else "not underline") + if bits & 0b0000111110000: + if bits & (1 << 4): + append("blink" if self.blink else "not blink") + if bits & (1 << 5): + append("blink2" if self.blink2 else "not blink2") + if bits & (1 << 6): + append("reverse" if self.reverse else "not reverse") + if bits & (1 << 7): + append("conceal" if self.conceal else "not conceal") + if bits & (1 << 8): + append("strike" if self.strike else "not strike") + if bits & 0b1111000000000: + if bits & (1 << 9): + append("underline2" if self.underline2 else "not underline2") + if bits & (1 << 10): + append("frame" if self.frame else "not frame") + if bits & (1 << 11): + append("encircle" if self.encircle else "not encircle") + if bits & (1 << 12): + append("overline" if self.overline else "not overline") + if self._color is not None: + append(self._color.name) + if self._bgcolor is not None: + append("on") + append(self._bgcolor.name) + if self._link: + append("link") + append(self._link) + self._style_definition = " ".join(attributes) or "none" + return self._style_definition + + def __bool__(self) -> bool: + """A Style is false if it has no attributes, colors, or links.""" + return not self._null + + def _make_ansi_codes(self, color_system: ColorSystem) -> str: + """Generate ANSI codes for this style. + + Args: + color_system (ColorSystem): Color system. + + Returns: + str: String containing codes. + """ + + if self._ansi is None: + sgr: List[str] = [] + append = sgr.append + _style_map = self._style_map + attributes = self._attributes & self._set_attributes + if attributes: + if attributes & 1: + append(_style_map[0]) + if attributes & 2: + append(_style_map[1]) + if attributes & 4: + append(_style_map[2]) + if attributes & 8: + append(_style_map[3]) + if attributes & 0b0000111110000: + for bit in range(4, 9): + if attributes & (1 << bit): + append(_style_map[bit]) + if attributes & 0b1111000000000: + for bit in range(9, 13): + if attributes & (1 << bit): + append(_style_map[bit]) + if self._color is not None: + sgr.extend(self._color.downgrade(color_system).get_ansi_codes()) + if self._bgcolor is not None: + sgr.extend( + self._bgcolor.downgrade(color_system).get_ansi_codes( + foreground=False + ) + ) + self._ansi = ";".join(sgr) + return self._ansi + + @classmethod + @lru_cache(maxsize=1024) + def normalize(cls, style: str) -> str: + """Normalize a style definition so that styles with the same effect have the same string + representation. + + Args: + style (str): A style definition. + + Returns: + str: Normal form of style definition. + """ + try: + return str(cls.parse(style)) + except errors.StyleSyntaxError: + return style.strip().lower() + + @classmethod + def pick_first(cls, *values: Optional[StyleType]) -> StyleType: + """Pick first non-None style.""" + for value in values: + if value is not None: + return value + raise ValueError("expected at least one non-None style") + + def __rich_repr__(self) -> Result: + yield "color", self.color, None + yield "bgcolor", self.bgcolor, None + yield "bold", self.bold, None, + yield "dim", self.dim, None, + yield "italic", self.italic, None + yield "underline", self.underline, None, + yield "blink", self.blink, None + yield "blink2", self.blink2, None + yield "reverse", self.reverse, None + yield "conceal", self.conceal, None + yield "strike", self.strike, None + yield "underline2", self.underline2, None + yield "frame", self.frame, None + yield "encircle", self.encircle, None + yield "link", self.link, None + if self._meta: + yield "meta", self.meta + + def __eq__(self, other: Any) -> bool: + if not isinstance(other, Style): + return NotImplemented + return self.__hash__() == other.__hash__() + + def __ne__(self, other: Any) -> bool: + if not isinstance(other, Style): + return NotImplemented + return self.__hash__() != other.__hash__() + + def __hash__(self) -> int: + if self._hash is not None: + return self._hash + self._hash = hash( + ( + self._color, + self._bgcolor, + self._attributes, + self._set_attributes, + self._link, + self._meta, + ) + ) + return self._hash + + @property + def color(self) -> Optional[Color]: + """The foreground color or None if it is not set.""" + return self._color + + @property + def bgcolor(self) -> Optional[Color]: + """The background color or None if it is not set.""" + return self._bgcolor + + @property + def link(self) -> Optional[str]: + """Link text, if set.""" + return self._link + + @property + def transparent_background(self) -> bool: + """Check if the style specified a transparent background.""" + return self.bgcolor is None or self.bgcolor.is_default + + @property + def background_style(self) -> "Style": + """A Style with background only.""" + return Style(bgcolor=self.bgcolor) + + @property + def meta(self) -> Dict[str, Any]: + """Get meta information (can not be changed after construction).""" + return {} if self._meta is None else cast(Dict[str, Any], loads(self._meta)) + + @property + def without_color(self) -> "Style": + """Get a copy of the style with color removed.""" + if self._null: + return NULL_STYLE + style: Style = self.__new__(Style) + style._ansi = None + style._style_definition = None + style._color = None + style._bgcolor = None + style._attributes = self._attributes + style._set_attributes = self._set_attributes + style._link = self._link + style._link_id = f"{randint(0, 999999)}" if self._link else "" + style._null = False + style._meta = None + style._hash = None + return style + + @classmethod + @lru_cache(maxsize=4096) + def parse(cls, style_definition: str) -> "Style": + """Parse a style definition. + + Args: + style_definition (str): A string containing a style. + + Raises: + errors.StyleSyntaxError: If the style definition syntax is invalid. + + Returns: + `Style`: A Style instance. + """ + if style_definition.strip() == "none" or not style_definition: + return cls.null() + + STYLE_ATTRIBUTES = cls.STYLE_ATTRIBUTES + color: Optional[str] = None + bgcolor: Optional[str] = None + attributes: Dict[str, Optional[Any]] = {} + link: Optional[str] = None + + words = iter(style_definition.split()) + for original_word in words: + word = original_word.lower() + if word == "on": + word = next(words, "") + if not word: + raise errors.StyleSyntaxError("color expected after 'on'") + try: + Color.parse(word) is None + except ColorParseError as error: + raise errors.StyleSyntaxError( + f"unable to parse {word!r} as background color; {error}" + ) from None + bgcolor = word + + elif word == "not": + word = next(words, "") + attribute = STYLE_ATTRIBUTES.get(word) + if attribute is None: + raise errors.StyleSyntaxError( + f"expected style attribute after 'not', found {word!r}" + ) + attributes[attribute] = False + + elif word == "link": + word = next(words, "") + if not word: + raise errors.StyleSyntaxError("URL expected after 'link'") + link = word + + elif word in STYLE_ATTRIBUTES: + attributes[STYLE_ATTRIBUTES[word]] = True + + else: + try: + Color.parse(word) + except ColorParseError as error: + raise errors.StyleSyntaxError( + f"unable to parse {word!r} as color; {error}" + ) from None + color = word + style = Style(color=color, bgcolor=bgcolor, link=link, **attributes) + return style + + @lru_cache(maxsize=1024) + def get_html_style(self, theme: Optional[TerminalTheme] = None) -> str: + """Get a CSS style rule.""" + theme = theme or DEFAULT_TERMINAL_THEME + css: List[str] = [] + append = css.append + + color = self.color + bgcolor = self.bgcolor + if self.reverse: + color, bgcolor = bgcolor, color + if self.dim: + foreground_color = ( + theme.foreground_color if color is None else color.get_truecolor(theme) + ) + color = Color.from_triplet( + blend_rgb(foreground_color, theme.background_color, 0.5) + ) + if color is not None: + theme_color = color.get_truecolor(theme) + append(f"color: {theme_color.hex}") + append(f"text-decoration-color: {theme_color.hex}") + if bgcolor is not None: + theme_color = bgcolor.get_truecolor(theme, foreground=False) + append(f"background-color: {theme_color.hex}") + if self.bold: + append("font-weight: bold") + if self.italic: + append("font-style: italic") + if self.underline: + append("text-decoration: underline") + if self.strike: + append("text-decoration: line-through") + if self.overline: + append("text-decoration: overline") + return "; ".join(css) + + @classmethod + def combine(cls, styles: Iterable["Style"]) -> "Style": + """Combine styles and get result. + + Args: + styles (Iterable[Style]): Styles to combine. + + Returns: + Style: A new style instance. + """ + iter_styles = iter(styles) + return sum(iter_styles, next(iter_styles)) + + @classmethod + def chain(cls, *styles: "Style") -> "Style": + """Combine styles from positional argument in to a single style. + + Args: + *styles (Iterable[Style]): Styles to combine. + + Returns: + Style: A new style instance. + """ + iter_styles = iter(styles) + return sum(iter_styles, next(iter_styles)) + + def copy(self) -> "Style": + """Get a copy of this style. + + Returns: + Style: A new Style instance with identical attributes. + """ + if self._null: + return NULL_STYLE + style: Style = self.__new__(Style) + style._ansi = self._ansi + style._style_definition = self._style_definition + style._color = self._color + style._bgcolor = self._bgcolor + style._attributes = self._attributes + style._set_attributes = self._set_attributes + style._link = self._link + style._link_id = f"{randint(0, 999999)}" if self._link else "" + style._hash = self._hash + style._null = False + style._meta = self._meta + return style + + @lru_cache(maxsize=128) + def clear_meta_and_links(self) -> "Style": + """Get a copy of this style with link and meta information removed. + + Returns: + Style: New style object. + """ + if self._null: + return NULL_STYLE + style: Style = self.__new__(Style) + style._ansi = self._ansi + style._style_definition = self._style_definition + style._color = self._color + style._bgcolor = self._bgcolor + style._attributes = self._attributes + style._set_attributes = self._set_attributes + style._link = None + style._link_id = "" + style._hash = self._hash + style._null = False + style._meta = None + return style + + def update_link(self, link: Optional[str] = None) -> "Style": + """Get a copy with a different value for link. + + Args: + link (str, optional): New value for link. Defaults to None. + + Returns: + Style: A new Style instance. + """ + style: Style = self.__new__(Style) + style._ansi = self._ansi + style._style_definition = self._style_definition + style._color = self._color + style._bgcolor = self._bgcolor + style._attributes = self._attributes + style._set_attributes = self._set_attributes + style._link = link + style._link_id = f"{randint(0, 999999)}" if link else "" + style._hash = None + style._null = False + style._meta = self._meta + return style + + def render( + self, + text: str = "", + *, + color_system: Optional[ColorSystem] = ColorSystem.TRUECOLOR, + legacy_windows: bool = False, + ) -> str: + """Render the ANSI codes for the style. + + Args: + text (str, optional): A string to style. Defaults to "". + color_system (Optional[ColorSystem], optional): Color system to render to. Defaults to ColorSystem.TRUECOLOR. + + Returns: + str: A string containing ANSI style codes. + """ + if not text or color_system is None: + return text + attrs = self._ansi or self._make_ansi_codes(color_system) + rendered = f"\x1b[{attrs}m{text}\x1b[0m" if attrs else text + if self._link and not legacy_windows: + rendered = ( + f"\x1b]8;id={self._link_id};{self._link}\x1b\\{rendered}\x1b]8;;\x1b\\" + ) + return rendered + + def test(self, text: Optional[str] = None) -> None: + """Write text with style directly to terminal. + + This method is for testing purposes only. + + Args: + text (Optional[str], optional): Text to style or None for style name. + + """ + text = text or str(self) + sys.stdout.write(f"{self.render(text)}\n") + + @lru_cache(maxsize=1024) + def _add(self, style: Optional["Style"]) -> "Style": + if style is None or style._null: + return self + if self._null: + return style + new_style: Style = self.__new__(Style) + new_style._ansi = None + new_style._style_definition = None + new_style._color = style._color or self._color + new_style._bgcolor = style._bgcolor or self._bgcolor + new_style._attributes = (self._attributes & ~style._set_attributes) | ( + style._attributes & style._set_attributes + ) + new_style._set_attributes = self._set_attributes | style._set_attributes + new_style._link = style._link or self._link + new_style._link_id = style._link_id or self._link_id + new_style._null = style._null + if self._meta and style._meta: + new_style._meta = dumps({**self.meta, **style.meta}) + else: + new_style._meta = self._meta or style._meta + new_style._hash = None + return new_style + + def __add__(self, style: Optional["Style"]) -> "Style": + combined_style = self._add(style) + return combined_style.copy() if combined_style.link else combined_style + + +NULL_STYLE = Style() + + +class StyleStack: + """A stack of styles.""" + + __slots__ = ["_stack"] + + def __init__(self, default_style: "Style") -> None: + self._stack: List[Style] = [default_style] + + def __repr__(self) -> str: + return f"" + + @property + def current(self) -> Style: + """Get the Style at the top of the stack.""" + return self._stack[-1] + + def push(self, style: Style) -> None: + """Push a new style on to the stack. + + Args: + style (Style): New style to combine with current style. + """ + self._stack.append(self._stack[-1] + style) + + def pop(self) -> Style: + """Pop last style and discard. + + Returns: + Style: New current style (also available as stack.current) + """ + self._stack.pop() + return self._stack[-1] diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/styled.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/styled.py new file mode 100644 index 0000000..91cd0db --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/styled.py @@ -0,0 +1,42 @@ +from typing import TYPE_CHECKING + +from .measure import Measurement +from .segment import Segment +from .style import StyleType + +if TYPE_CHECKING: + from .console import Console, ConsoleOptions, RenderResult, RenderableType + + +class Styled: + """Apply a style to a renderable. + + Args: + renderable (RenderableType): Any renderable. + style (StyleType): A style to apply across the entire renderable. + """ + + def __init__(self, renderable: "RenderableType", style: "StyleType") -> None: + self.renderable = renderable + self.style = style + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + style = console.get_style(self.style) + rendered_segments = console.render(self.renderable, options) + segments = Segment.apply_style(rendered_segments, style) + return segments + + def __rich_measure__( + self, console: "Console", options: "ConsoleOptions" + ) -> Measurement: + return Measurement.get(console, options, self.renderable) + + +if __name__ == "__main__": # pragma: no cover + from pip._vendor.rich import print + from pip._vendor.rich.panel import Panel + + panel = Styled(Panel("hello"), "on blue") + print(panel) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/syntax.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/syntax.py new file mode 100644 index 0000000..c26fd87 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/syntax.py @@ -0,0 +1,958 @@ +import os.path +import platform +import re +import sys +import textwrap +from abc import ABC, abstractmethod +from pathlib import Path +from typing import ( + Any, + Dict, + Iterable, + List, + NamedTuple, + Optional, + Sequence, + Set, + Tuple, + Type, + Union, +) + +from pip._vendor.pygments.lexer import Lexer +from pip._vendor.pygments.lexers import get_lexer_by_name, guess_lexer_for_filename +from pip._vendor.pygments.style import Style as PygmentsStyle +from pip._vendor.pygments.styles import get_style_by_name +from pip._vendor.pygments.token import ( + Comment, + Error, + Generic, + Keyword, + Name, + Number, + Operator, + String, + Token, + Whitespace, +) +from pip._vendor.pygments.util import ClassNotFound + +from pip._vendor.rich.containers import Lines +from pip._vendor.rich.padding import Padding, PaddingDimensions + +from ._loop import loop_first +from .cells import cell_len +from .color import Color, blend_rgb +from .console import Console, ConsoleOptions, JustifyMethod, RenderResult +from .jupyter import JupyterMixin +from .measure import Measurement +from .segment import Segment, Segments +from .style import Style, StyleType +from .text import Text + +TokenType = Tuple[str, ...] + +WINDOWS = platform.system() == "Windows" +DEFAULT_THEME = "monokai" + +# The following styles are based on https://github.com/pygments/pygments/blob/master/pygments/formatters/terminal.py +# A few modifications were made + +ANSI_LIGHT: Dict[TokenType, Style] = { + Token: Style(), + Whitespace: Style(color="white"), + Comment: Style(dim=True), + Comment.Preproc: Style(color="cyan"), + Keyword: Style(color="blue"), + Keyword.Type: Style(color="cyan"), + Operator.Word: Style(color="magenta"), + Name.Builtin: Style(color="cyan"), + Name.Function: Style(color="green"), + Name.Namespace: Style(color="cyan", underline=True), + Name.Class: Style(color="green", underline=True), + Name.Exception: Style(color="cyan"), + Name.Decorator: Style(color="magenta", bold=True), + Name.Variable: Style(color="red"), + Name.Constant: Style(color="red"), + Name.Attribute: Style(color="cyan"), + Name.Tag: Style(color="bright_blue"), + String: Style(color="yellow"), + Number: Style(color="blue"), + Generic.Deleted: Style(color="bright_red"), + Generic.Inserted: Style(color="green"), + Generic.Heading: Style(bold=True), + Generic.Subheading: Style(color="magenta", bold=True), + Generic.Prompt: Style(bold=True), + Generic.Error: Style(color="bright_red"), + Error: Style(color="red", underline=True), +} + +ANSI_DARK: Dict[TokenType, Style] = { + Token: Style(), + Whitespace: Style(color="bright_black"), + Comment: Style(dim=True), + Comment.Preproc: Style(color="bright_cyan"), + Keyword: Style(color="bright_blue"), + Keyword.Type: Style(color="bright_cyan"), + Operator.Word: Style(color="bright_magenta"), + Name.Builtin: Style(color="bright_cyan"), + Name.Function: Style(color="bright_green"), + Name.Namespace: Style(color="bright_cyan", underline=True), + Name.Class: Style(color="bright_green", underline=True), + Name.Exception: Style(color="bright_cyan"), + Name.Decorator: Style(color="bright_magenta", bold=True), + Name.Variable: Style(color="bright_red"), + Name.Constant: Style(color="bright_red"), + Name.Attribute: Style(color="bright_cyan"), + Name.Tag: Style(color="bright_blue"), + String: Style(color="yellow"), + Number: Style(color="bright_blue"), + Generic.Deleted: Style(color="bright_red"), + Generic.Inserted: Style(color="bright_green"), + Generic.Heading: Style(bold=True), + Generic.Subheading: Style(color="bright_magenta", bold=True), + Generic.Prompt: Style(bold=True), + Generic.Error: Style(color="bright_red"), + Error: Style(color="red", underline=True), +} + +RICH_SYNTAX_THEMES = {"ansi_light": ANSI_LIGHT, "ansi_dark": ANSI_DARK} +NUMBERS_COLUMN_DEFAULT_PADDING = 2 + + +class SyntaxTheme(ABC): + """Base class for a syntax theme.""" + + @abstractmethod + def get_style_for_token(self, token_type: TokenType) -> Style: + """Get a style for a given Pygments token.""" + raise NotImplementedError # pragma: no cover + + @abstractmethod + def get_background_style(self) -> Style: + """Get the background color.""" + raise NotImplementedError # pragma: no cover + + +class PygmentsSyntaxTheme(SyntaxTheme): + """Syntax theme that delegates to Pygments theme.""" + + def __init__(self, theme: Union[str, Type[PygmentsStyle]]) -> None: + self._style_cache: Dict[TokenType, Style] = {} + if isinstance(theme, str): + try: + self._pygments_style_class = get_style_by_name(theme) + except ClassNotFound: + self._pygments_style_class = get_style_by_name("default") + else: + self._pygments_style_class = theme + + self._background_color = self._pygments_style_class.background_color + self._background_style = Style(bgcolor=self._background_color) + + def get_style_for_token(self, token_type: TokenType) -> Style: + """Get a style from a Pygments class.""" + try: + return self._style_cache[token_type] + except KeyError: + try: + pygments_style = self._pygments_style_class.style_for_token(token_type) + except KeyError: + style = Style.null() + else: + color = pygments_style["color"] + bgcolor = pygments_style["bgcolor"] + style = Style( + color="#" + color if color else "#000000", + bgcolor="#" + bgcolor if bgcolor else self._background_color, + bold=pygments_style["bold"], + italic=pygments_style["italic"], + underline=pygments_style["underline"], + ) + self._style_cache[token_type] = style + return style + + def get_background_style(self) -> Style: + return self._background_style + + +class ANSISyntaxTheme(SyntaxTheme): + """Syntax theme to use standard colors.""" + + def __init__(self, style_map: Dict[TokenType, Style]) -> None: + self.style_map = style_map + self._missing_style = Style.null() + self._background_style = Style.null() + self._style_cache: Dict[TokenType, Style] = {} + + def get_style_for_token(self, token_type: TokenType) -> Style: + """Look up style in the style map.""" + try: + return self._style_cache[token_type] + except KeyError: + # Styles form a hierarchy + # We need to go from most to least specific + # e.g. ("foo", "bar", "baz") to ("foo", "bar") to ("foo",) + get_style = self.style_map.get + token = tuple(token_type) + style = self._missing_style + while token: + _style = get_style(token) + if _style is not None: + style = _style + break + token = token[:-1] + self._style_cache[token_type] = style + return style + + def get_background_style(self) -> Style: + return self._background_style + + +SyntaxPosition = Tuple[int, int] + + +class _SyntaxHighlightRange(NamedTuple): + """ + A range to highlight in a Syntax object. + `start` and `end` are 2-integers tuples, where the first integer is the line number + (starting from 1) and the second integer is the column index (starting from 0). + """ + + style: StyleType + start: SyntaxPosition + end: SyntaxPosition + + +class Syntax(JupyterMixin): + """Construct a Syntax object to render syntax highlighted code. + + Args: + code (str): Code to highlight. + lexer (Lexer | str): Lexer to use (see https://pygments.org/docs/lexers/) + theme (str, optional): Color theme, aka Pygments style (see https://pygments.org/docs/styles/#getting-a-list-of-available-styles). Defaults to "monokai". + dedent (bool, optional): Enable stripping of initial whitespace. Defaults to False. + line_numbers (bool, optional): Enable rendering of line numbers. Defaults to False. + start_line (int, optional): Starting number for line numbers. Defaults to 1. + line_range (Tuple[int | None, int | None], optional): If given should be a tuple of the start and end line to render. + A value of None in the tuple indicates the range is open in that direction. + highlight_lines (Set[int]): A set of line numbers to highlight. + code_width: Width of code to render (not including line numbers), or ``None`` to use all available width. + tab_size (int, optional): Size of tabs. Defaults to 4. + word_wrap (bool, optional): Enable word wrapping. + background_color (str, optional): Optional background color, or None to use theme color. Defaults to None. + indent_guides (bool, optional): Show indent guides. Defaults to False. + padding (PaddingDimensions): Padding to apply around the syntax. Defaults to 0 (no padding). + """ + + _pygments_style_class: Type[PygmentsStyle] + _theme: SyntaxTheme + + @classmethod + def get_theme(cls, name: Union[str, SyntaxTheme]) -> SyntaxTheme: + """Get a syntax theme instance.""" + if isinstance(name, SyntaxTheme): + return name + theme: SyntaxTheme + if name in RICH_SYNTAX_THEMES: + theme = ANSISyntaxTheme(RICH_SYNTAX_THEMES[name]) + else: + theme = PygmentsSyntaxTheme(name) + return theme + + def __init__( + self, + code: str, + lexer: Union[Lexer, str], + *, + theme: Union[str, SyntaxTheme] = DEFAULT_THEME, + dedent: bool = False, + line_numbers: bool = False, + start_line: int = 1, + line_range: Optional[Tuple[Optional[int], Optional[int]]] = None, + highlight_lines: Optional[Set[int]] = None, + code_width: Optional[int] = None, + tab_size: int = 4, + word_wrap: bool = False, + background_color: Optional[str] = None, + indent_guides: bool = False, + padding: PaddingDimensions = 0, + ) -> None: + self.code = code + self._lexer = lexer + self.dedent = dedent + self.line_numbers = line_numbers + self.start_line = start_line + self.line_range = line_range + self.highlight_lines = highlight_lines or set() + self.code_width = code_width + self.tab_size = tab_size + self.word_wrap = word_wrap + self.background_color = background_color + self.background_style = ( + Style(bgcolor=background_color) if background_color else Style() + ) + self.indent_guides = indent_guides + self.padding = padding + + self._theme = self.get_theme(theme) + self._stylized_ranges: List[_SyntaxHighlightRange] = [] + + @classmethod + def from_path( + cls, + path: str, + encoding: str = "utf-8", + lexer: Optional[Union[Lexer, str]] = None, + theme: Union[str, SyntaxTheme] = DEFAULT_THEME, + dedent: bool = False, + line_numbers: bool = False, + line_range: Optional[Tuple[int, int]] = None, + start_line: int = 1, + highlight_lines: Optional[Set[int]] = None, + code_width: Optional[int] = None, + tab_size: int = 4, + word_wrap: bool = False, + background_color: Optional[str] = None, + indent_guides: bool = False, + padding: PaddingDimensions = 0, + ) -> "Syntax": + """Construct a Syntax object from a file. + + Args: + path (str): Path to file to highlight. + encoding (str): Encoding of file. + lexer (str | Lexer, optional): Lexer to use. If None, lexer will be auto-detected from path/file content. + theme (str, optional): Color theme, aka Pygments style (see https://pygments.org/docs/styles/#getting-a-list-of-available-styles). Defaults to "emacs". + dedent (bool, optional): Enable stripping of initial whitespace. Defaults to True. + line_numbers (bool, optional): Enable rendering of line numbers. Defaults to False. + start_line (int, optional): Starting number for line numbers. Defaults to 1. + line_range (Tuple[int, int], optional): If given should be a tuple of the start and end line to render. + highlight_lines (Set[int]): A set of line numbers to highlight. + code_width: Width of code to render (not including line numbers), or ``None`` to use all available width. + tab_size (int, optional): Size of tabs. Defaults to 4. + word_wrap (bool, optional): Enable word wrapping of code. + background_color (str, optional): Optional background color, or None to use theme color. Defaults to None. + indent_guides (bool, optional): Show indent guides. Defaults to False. + padding (PaddingDimensions): Padding to apply around the syntax. Defaults to 0 (no padding). + + Returns: + [Syntax]: A Syntax object that may be printed to the console + """ + code = Path(path).read_text(encoding=encoding) + + if not lexer: + lexer = cls.guess_lexer(path, code=code) + + return cls( + code, + lexer, + theme=theme, + dedent=dedent, + line_numbers=line_numbers, + line_range=line_range, + start_line=start_line, + highlight_lines=highlight_lines, + code_width=code_width, + tab_size=tab_size, + word_wrap=word_wrap, + background_color=background_color, + indent_guides=indent_guides, + padding=padding, + ) + + @classmethod + def guess_lexer(cls, path: str, code: Optional[str] = None) -> str: + """Guess the alias of the Pygments lexer to use based on a path and an optional string of code. + If code is supplied, it will use a combination of the code and the filename to determine the + best lexer to use. For example, if the file is ``index.html`` and the file contains Django + templating syntax, then "html+django" will be returned. If the file is ``index.html``, and no + templating language is used, the "html" lexer will be used. If no string of code + is supplied, the lexer will be chosen based on the file extension.. + + Args: + path (AnyStr): The path to the file containing the code you wish to know the lexer for. + code (str, optional): Optional string of code that will be used as a fallback if no lexer + is found for the supplied path. + + Returns: + str: The name of the Pygments lexer that best matches the supplied path/code. + """ + lexer: Optional[Lexer] = None + lexer_name = "default" + if code: + try: + lexer = guess_lexer_for_filename(path, code) + except ClassNotFound: + pass + + if not lexer: + try: + _, ext = os.path.splitext(path) + if ext: + extension = ext.lstrip(".").lower() + lexer = get_lexer_by_name(extension) + except ClassNotFound: + pass + + if lexer: + if lexer.aliases: + lexer_name = lexer.aliases[0] + else: + lexer_name = lexer.name + + return lexer_name + + def _get_base_style(self) -> Style: + """Get the base style.""" + default_style = self._theme.get_background_style() + self.background_style + return default_style + + def _get_token_color(self, token_type: TokenType) -> Optional[Color]: + """Get a color (if any) for the given token. + + Args: + token_type (TokenType): A token type tuple from Pygments. + + Returns: + Optional[Color]: Color from theme, or None for no color. + """ + style = self._theme.get_style_for_token(token_type) + return style.color + + @property + def lexer(self) -> Optional[Lexer]: + """The lexer for this syntax, or None if no lexer was found. + + Tries to find the lexer by name if a string was passed to the constructor. + """ + + if isinstance(self._lexer, Lexer): + return self._lexer + try: + return get_lexer_by_name( + self._lexer, + stripnl=False, + ensurenl=True, + tabsize=self.tab_size, + ) + except ClassNotFound: + return None + + @property + def default_lexer(self) -> Lexer: + """A Pygments Lexer to use if one is not specified or invalid.""" + return get_lexer_by_name( + "text", + stripnl=False, + ensurenl=True, + tabsize=self.tab_size, + ) + + def highlight( + self, + code: str, + line_range: Optional[Tuple[Optional[int], Optional[int]]] = None, + ) -> Text: + """Highlight code and return a Text instance. + + Args: + code (str): Code to highlight. + line_range(Tuple[int, int], optional): Optional line range to highlight. + + Returns: + Text: A text instance containing highlighted syntax. + """ + + base_style = self._get_base_style() + justify: JustifyMethod = ( + "default" if base_style.transparent_background else "left" + ) + + text = Text( + justify=justify, + style=base_style, + tab_size=self.tab_size, + no_wrap=not self.word_wrap, + ) + _get_theme_style = self._theme.get_style_for_token + + lexer = self.lexer or self.default_lexer + + if lexer is None: + text.append(code) + else: + if line_range: + # More complicated path to only stylize a portion of the code + # This speeds up further operations as there are less spans to process + line_start, line_end = line_range + + def line_tokenize() -> Iterable[Tuple[Any, str]]: + """Split tokens to one per line.""" + assert lexer # required to make MyPy happy - we know lexer is not None at this point + + for token_type, token in lexer.get_tokens(code): + while token: + line_token, new_line, token = token.partition("\n") + yield token_type, line_token + new_line + + def tokens_to_spans() -> Iterable[Tuple[str, Optional[Style]]]: + """Convert tokens to spans.""" + tokens = iter(line_tokenize()) + line_no = 0 + _line_start = line_start - 1 if line_start else 0 + + # Skip over tokens until line start + while line_no < _line_start: + try: + _token_type, token = next(tokens) + except StopIteration: + break + yield (token, None) + if token.endswith("\n"): + line_no += 1 + # Generate spans until line end + for token_type, token in tokens: + yield (token, _get_theme_style(token_type)) + if token.endswith("\n"): + line_no += 1 + if line_end and line_no >= line_end: + break + + text.append_tokens(tokens_to_spans()) + + else: + text.append_tokens( + (token, _get_theme_style(token_type)) + for token_type, token in lexer.get_tokens(code) + ) + if self.background_color is not None: + text.stylize(f"on {self.background_color}") + + if self._stylized_ranges: + self._apply_stylized_ranges(text) + + return text + + def stylize_range( + self, style: StyleType, start: SyntaxPosition, end: SyntaxPosition + ) -> None: + """ + Adds a custom style on a part of the code, that will be applied to the syntax display when it's rendered. + Line numbers are 1-based, while column indexes are 0-based. + + Args: + style (StyleType): The style to apply. + start (Tuple[int, int]): The start of the range, in the form `[line number, column index]`. + end (Tuple[int, int]): The end of the range, in the form `[line number, column index]`. + """ + self._stylized_ranges.append(_SyntaxHighlightRange(style, start, end)) + + def _get_line_numbers_color(self, blend: float = 0.3) -> Color: + background_style = self._theme.get_background_style() + self.background_style + background_color = background_style.bgcolor + if background_color is None or background_color.is_system_defined: + return Color.default() + foreground_color = self._get_token_color(Token.Text) + if foreground_color is None or foreground_color.is_system_defined: + return foreground_color or Color.default() + new_color = blend_rgb( + background_color.get_truecolor(), + foreground_color.get_truecolor(), + cross_fade=blend, + ) + return Color.from_triplet(new_color) + + @property + def _numbers_column_width(self) -> int: + """Get the number of characters used to render the numbers column.""" + column_width = 0 + if self.line_numbers: + column_width = ( + len(str(self.start_line + self.code.count("\n"))) + + NUMBERS_COLUMN_DEFAULT_PADDING + ) + return column_width + + def _get_number_styles(self, console: Console) -> Tuple[Style, Style, Style]: + """Get background, number, and highlight styles for line numbers.""" + background_style = self._get_base_style() + if background_style.transparent_background: + return Style.null(), Style(dim=True), Style.null() + if console.color_system in ("256", "truecolor"): + number_style = Style.chain( + background_style, + self._theme.get_style_for_token(Token.Text), + Style(color=self._get_line_numbers_color()), + self.background_style, + ) + highlight_number_style = Style.chain( + background_style, + self._theme.get_style_for_token(Token.Text), + Style(bold=True, color=self._get_line_numbers_color(0.9)), + self.background_style, + ) + else: + number_style = background_style + Style(dim=True) + highlight_number_style = background_style + Style(dim=False) + return background_style, number_style, highlight_number_style + + def __rich_measure__( + self, console: "Console", options: "ConsoleOptions" + ) -> "Measurement": + _, right, _, left = Padding.unpack(self.padding) + padding = left + right + if self.code_width is not None: + width = self.code_width + self._numbers_column_width + padding + 1 + return Measurement(self._numbers_column_width, width) + lines = self.code.splitlines() + width = ( + self._numbers_column_width + + padding + + (max(cell_len(line) for line in lines) if lines else 0) + ) + if self.line_numbers: + width += 1 + return Measurement(self._numbers_column_width, width) + + def __rich_console__( + self, console: Console, options: ConsoleOptions + ) -> RenderResult: + segments = Segments(self._get_syntax(console, options)) + if self.padding: + yield Padding( + segments, style=self._theme.get_background_style(), pad=self.padding + ) + else: + yield segments + + def _get_syntax( + self, + console: Console, + options: ConsoleOptions, + ) -> Iterable[Segment]: + """ + Get the Segments for the Syntax object, excluding any vertical/horizontal padding + """ + transparent_background = self._get_base_style().transparent_background + code_width = ( + ( + (options.max_width - self._numbers_column_width - 1) + if self.line_numbers + else options.max_width + ) + if self.code_width is None + else self.code_width + ) + + ends_on_nl, processed_code = self._process_code(self.code) + text = self.highlight(processed_code, self.line_range) + + if not self.line_numbers and not self.word_wrap and not self.line_range: + if not ends_on_nl: + text.remove_suffix("\n") + # Simple case of just rendering text + style = ( + self._get_base_style() + + self._theme.get_style_for_token(Comment) + + Style(dim=True) + + self.background_style + ) + if self.indent_guides and not options.ascii_only: + text = text.with_indent_guides(self.tab_size, style=style) + text.overflow = "crop" + if style.transparent_background: + yield from console.render( + text, options=options.update(width=code_width) + ) + else: + syntax_lines = console.render_lines( + text, + options.update(width=code_width, height=None, justify="left"), + style=self.background_style, + pad=True, + new_lines=True, + ) + for syntax_line in syntax_lines: + yield from syntax_line + return + + start_line, end_line = self.line_range or (None, None) + line_offset = 0 + if start_line: + line_offset = max(0, start_line - 1) + lines: Union[List[Text], Lines] = text.split("\n", allow_blank=ends_on_nl) + if self.line_range: + if line_offset > len(lines): + return + lines = lines[line_offset:end_line] + + if self.indent_guides and not options.ascii_only: + style = ( + self._get_base_style() + + self._theme.get_style_for_token(Comment) + + Style(dim=True) + + self.background_style + ) + lines = ( + Text("\n") + .join(lines) + .with_indent_guides(self.tab_size, style=style + Style(italic=False)) + .split("\n", allow_blank=True) + ) + + numbers_column_width = self._numbers_column_width + render_options = options.update(width=code_width) + + highlight_line = self.highlight_lines.__contains__ + _Segment = Segment + new_line = _Segment("\n") + + line_pointer = "> " if options.legacy_windows else "❱ " + + ( + background_style, + number_style, + highlight_number_style, + ) = self._get_number_styles(console) + + for line_no, line in enumerate(lines, self.start_line + line_offset): + if self.word_wrap: + wrapped_lines = console.render_lines( + line, + render_options.update(height=None, justify="left"), + style=background_style, + pad=not transparent_background, + ) + else: + segments = list(line.render(console, end="")) + if options.no_wrap: + wrapped_lines = [segments] + else: + wrapped_lines = [ + _Segment.adjust_line_length( + segments, + render_options.max_width, + style=background_style, + pad=not transparent_background, + ) + ] + + if self.line_numbers: + wrapped_line_left_pad = _Segment( + " " * numbers_column_width + " ", background_style + ) + for first, wrapped_line in loop_first(wrapped_lines): + if first: + line_column = str(line_no).rjust(numbers_column_width - 2) + " " + if highlight_line(line_no): + yield _Segment(line_pointer, Style(color="red")) + yield _Segment(line_column, highlight_number_style) + else: + yield _Segment(" ", highlight_number_style) + yield _Segment(line_column, number_style) + else: + yield wrapped_line_left_pad + yield from wrapped_line + yield new_line + else: + for wrapped_line in wrapped_lines: + yield from wrapped_line + yield new_line + + def _apply_stylized_ranges(self, text: Text) -> None: + """ + Apply stylized ranges to a text instance, + using the given code to determine the right portion to apply the style to. + + Args: + text (Text): Text instance to apply the style to. + """ + code = text.plain + newlines_offsets = [ + # Let's add outer boundaries at each side of the list: + 0, + # N.B. using "\n" here is much faster than using metacharacters such as "^" or "\Z": + *[ + match.start() + 1 + for match in re.finditer("\n", code, flags=re.MULTILINE) + ], + len(code) + 1, + ] + + for stylized_range in self._stylized_ranges: + start = _get_code_index_for_syntax_position( + newlines_offsets, stylized_range.start + ) + end = _get_code_index_for_syntax_position( + newlines_offsets, stylized_range.end + ) + if start is not None and end is not None: + text.stylize(stylized_range.style, start, end) + + def _process_code(self, code: str) -> Tuple[bool, str]: + """ + Applies various processing to a raw code string + (normalises it so it always ends with a line return, dedents it if necessary, etc.) + + Args: + code (str): The raw code string to process + + Returns: + Tuple[bool, str]: the boolean indicates whether the raw code ends with a line return, + while the string is the processed code. + """ + ends_on_nl = code.endswith("\n") + processed_code = code if ends_on_nl else code + "\n" + processed_code = ( + textwrap.dedent(processed_code) if self.dedent else processed_code + ) + processed_code = processed_code.expandtabs(self.tab_size) + return ends_on_nl, processed_code + + +def _get_code_index_for_syntax_position( + newlines_offsets: Sequence[int], position: SyntaxPosition +) -> Optional[int]: + """ + Returns the index of the code string for the given positions. + + Args: + newlines_offsets (Sequence[int]): The offset of each newline character found in the code snippet. + position (SyntaxPosition): The position to search for. + + Returns: + Optional[int]: The index of the code string for this position, or `None` + if the given position's line number is out of range (if it's the column that is out of range + we silently clamp its value so that it reaches the end of the line) + """ + lines_count = len(newlines_offsets) + + line_number, column_index = position + if line_number > lines_count or len(newlines_offsets) < (line_number + 1): + return None # `line_number` is out of range + line_index = line_number - 1 + line_length = newlines_offsets[line_index + 1] - newlines_offsets[line_index] - 1 + # If `column_index` is out of range: let's silently clamp it: + column_index = min(line_length, column_index) + return newlines_offsets[line_index] + column_index + + +if __name__ == "__main__": # pragma: no cover + import argparse + import sys + + parser = argparse.ArgumentParser( + description="Render syntax to the console with Rich" + ) + parser.add_argument( + "path", + metavar="PATH", + help="path to file, or - for stdin", + ) + parser.add_argument( + "-c", + "--force-color", + dest="force_color", + action="store_true", + default=None, + help="force color for non-terminals", + ) + parser.add_argument( + "-i", + "--indent-guides", + dest="indent_guides", + action="store_true", + default=False, + help="display indent guides", + ) + parser.add_argument( + "-l", + "--line-numbers", + dest="line_numbers", + action="store_true", + help="render line numbers", + ) + parser.add_argument( + "-w", + "--width", + type=int, + dest="width", + default=None, + help="width of output (default will auto-detect)", + ) + parser.add_argument( + "-r", + "--wrap", + dest="word_wrap", + action="store_true", + default=False, + help="word wrap long lines", + ) + parser.add_argument( + "-s", + "--soft-wrap", + action="store_true", + dest="soft_wrap", + default=False, + help="enable soft wrapping mode", + ) + parser.add_argument( + "-t", "--theme", dest="theme", default="monokai", help="pygments theme" + ) + parser.add_argument( + "-b", + "--background-color", + dest="background_color", + default=None, + help="Override background color", + ) + parser.add_argument( + "-x", + "--lexer", + default=None, + dest="lexer_name", + help="Lexer name", + ) + parser.add_argument( + "-p", "--padding", type=int, default=0, dest="padding", help="Padding" + ) + parser.add_argument( + "--highlight-line", + type=int, + default=None, + dest="highlight_line", + help="The line number (not index!) to highlight", + ) + args = parser.parse_args() + + from pip._vendor.rich.console import Console + + console = Console(force_terminal=args.force_color, width=args.width) + + if args.path == "-": + code = sys.stdin.read() + syntax = Syntax( + code=code, + lexer=args.lexer_name, + line_numbers=args.line_numbers, + word_wrap=args.word_wrap, + theme=args.theme, + background_color=args.background_color, + indent_guides=args.indent_guides, + padding=args.padding, + highlight_lines={args.highlight_line}, + ) + else: + syntax = Syntax.from_path( + args.path, + lexer=args.lexer_name, + line_numbers=args.line_numbers, + word_wrap=args.word_wrap, + theme=args.theme, + background_color=args.background_color, + indent_guides=args.indent_guides, + padding=args.padding, + highlight_lines={args.highlight_line}, + ) + console.print(syntax, soft_wrap=args.soft_wrap) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/table.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/table.py new file mode 100644 index 0000000..43c718e --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/table.py @@ -0,0 +1,1000 @@ +from dataclasses import dataclass, field, replace +from typing import ( + TYPE_CHECKING, + Dict, + Iterable, + List, + NamedTuple, + Optional, + Sequence, + Tuple, + Union, +) + +from . import box, errors +from ._loop import loop_first_last, loop_last +from ._pick import pick_bool +from ._ratio import ratio_distribute, ratio_reduce +from .align import VerticalAlignMethod +from .jupyter import JupyterMixin +from .measure import Measurement +from .padding import Padding, PaddingDimensions +from .protocol import is_renderable +from .segment import Segment +from .style import Style, StyleType +from .text import Text, TextType + +if TYPE_CHECKING: + from .console import ( + Console, + ConsoleOptions, + JustifyMethod, + OverflowMethod, + RenderableType, + RenderResult, + ) + + +@dataclass +class Column: + """Defines a column within a ~Table. + + Args: + title (Union[str, Text], optional): The title of the table rendered at the top. Defaults to None. + caption (Union[str, Text], optional): The table caption rendered below. Defaults to None. + width (int, optional): The width in characters of the table, or ``None`` to automatically fit. Defaults to None. + min_width (Optional[int], optional): The minimum width of the table, or ``None`` for no minimum. Defaults to None. + box (box.Box, optional): One of the constants in box.py used to draw the edges (see :ref:`appendix_box`), or ``None`` for no box lines. Defaults to box.HEAVY_HEAD. + safe_box (Optional[bool], optional): Disable box characters that don't display on windows legacy terminal with *raster* fonts. Defaults to True. + padding (PaddingDimensions, optional): Padding for cells (top, right, bottom, left). Defaults to (0, 1). + collapse_padding (bool, optional): Enable collapsing of padding around cells. Defaults to False. + pad_edge (bool, optional): Enable padding of edge cells. Defaults to True. + expand (bool, optional): Expand the table to fit the available space if ``True``, otherwise the table width will be auto-calculated. Defaults to False. + show_header (bool, optional): Show a header row. Defaults to True. + show_footer (bool, optional): Show a footer row. Defaults to False. + show_edge (bool, optional): Draw a box around the outside of the table. Defaults to True. + show_lines (bool, optional): Draw lines between every row. Defaults to False. + leading (bool, optional): Number of blank lines between rows (precludes ``show_lines``). Defaults to 0. + style (Union[str, Style], optional): Default style for the table. Defaults to "none". + row_styles (List[Union, str], optional): Optional list of row styles, if more than one style is given then the styles will alternate. Defaults to None. + header_style (Union[str, Style], optional): Style of the header. Defaults to "table.header". + footer_style (Union[str, Style], optional): Style of the footer. Defaults to "table.footer". + border_style (Union[str, Style], optional): Style of the border. Defaults to None. + title_style (Union[str, Style], optional): Style of the title. Defaults to None. + caption_style (Union[str, Style], optional): Style of the caption. Defaults to None. + title_justify (str, optional): Justify method for title. Defaults to "center". + caption_justify (str, optional): Justify method for caption. Defaults to "center". + highlight (bool, optional): Highlight cell contents (if str). Defaults to False. + """ + + header: "RenderableType" = "" + """RenderableType: Renderable for the header (typically a string)""" + + footer: "RenderableType" = "" + """RenderableType: Renderable for the footer (typically a string)""" + + header_style: StyleType = "" + """StyleType: The style of the header.""" + + footer_style: StyleType = "" + """StyleType: The style of the footer.""" + + style: StyleType = "" + """StyleType: The style of the column.""" + + justify: "JustifyMethod" = "left" + """str: How to justify text within the column ("left", "center", "right", or "full")""" + + vertical: "VerticalAlignMethod" = "top" + """str: How to vertically align content ("top", "middle", or "bottom")""" + + overflow: "OverflowMethod" = "ellipsis" + """str: Overflow method.""" + + width: Optional[int] = None + """Optional[int]: Width of the column, or ``None`` (default) to auto calculate width.""" + + min_width: Optional[int] = None + """Optional[int]: Minimum width of column, or ``None`` for no minimum. Defaults to None.""" + + max_width: Optional[int] = None + """Optional[int]: Maximum width of column, or ``None`` for no maximum. Defaults to None.""" + + ratio: Optional[int] = None + """Optional[int]: Ratio to use when calculating column width, or ``None`` (default) to adapt to column contents.""" + + no_wrap: bool = False + """bool: Prevent wrapping of text within the column. Defaults to ``False``.""" + + _index: int = 0 + """Index of column.""" + + _cells: List["RenderableType"] = field(default_factory=list) + + def copy(self) -> "Column": + """Return a copy of this Column.""" + return replace(self, _cells=[]) + + @property + def cells(self) -> Iterable["RenderableType"]: + """Get all cells in the column, not including header.""" + yield from self._cells + + @property + def flexible(self) -> bool: + """Check if this column is flexible.""" + return self.ratio is not None + + +@dataclass +class Row: + """Information regarding a row.""" + + style: Optional[StyleType] = None + """Style to apply to row.""" + + end_section: bool = False + """Indicated end of section, which will force a line beneath the row.""" + + +class _Cell(NamedTuple): + """A single cell in a table.""" + + style: StyleType + """Style to apply to cell.""" + renderable: "RenderableType" + """Cell renderable.""" + vertical: VerticalAlignMethod + """Cell vertical alignment.""" + + +class Table(JupyterMixin): + """A console renderable to draw a table. + + Args: + *headers (Union[Column, str]): Column headers, either as a string, or :class:`~rich.table.Column` instance. + title (Union[str, Text], optional): The title of the table rendered at the top. Defaults to None. + caption (Union[str, Text], optional): The table caption rendered below. Defaults to None. + width (int, optional): The width in characters of the table, or ``None`` to automatically fit. Defaults to None. + min_width (Optional[int], optional): The minimum width of the table, or ``None`` for no minimum. Defaults to None. + box (box.Box, optional): One of the constants in box.py used to draw the edges (see :ref:`appendix_box`), or ``None`` for no box lines. Defaults to box.HEAVY_HEAD. + safe_box (Optional[bool], optional): Disable box characters that don't display on windows legacy terminal with *raster* fonts. Defaults to True. + padding (PaddingDimensions, optional): Padding for cells (top, right, bottom, left). Defaults to (0, 1). + collapse_padding (bool, optional): Enable collapsing of padding around cells. Defaults to False. + pad_edge (bool, optional): Enable padding of edge cells. Defaults to True. + expand (bool, optional): Expand the table to fit the available space if ``True``, otherwise the table width will be auto-calculated. Defaults to False. + show_header (bool, optional): Show a header row. Defaults to True. + show_footer (bool, optional): Show a footer row. Defaults to False. + show_edge (bool, optional): Draw a box around the outside of the table. Defaults to True. + show_lines (bool, optional): Draw lines between every row. Defaults to False. + leading (bool, optional): Number of blank lines between rows (precludes ``show_lines``). Defaults to 0. + style (Union[str, Style], optional): Default style for the table. Defaults to "none". + row_styles (List[Union, str], optional): Optional list of row styles, if more than one style is given then the styles will alternate. Defaults to None. + header_style (Union[str, Style], optional): Style of the header. Defaults to "table.header". + footer_style (Union[str, Style], optional): Style of the footer. Defaults to "table.footer". + border_style (Union[str, Style], optional): Style of the border. Defaults to None. + title_style (Union[str, Style], optional): Style of the title. Defaults to None. + caption_style (Union[str, Style], optional): Style of the caption. Defaults to None. + title_justify (str, optional): Justify method for title. Defaults to "center". + caption_justify (str, optional): Justify method for caption. Defaults to "center". + highlight (bool, optional): Highlight cell contents (if str). Defaults to False. + """ + + columns: List[Column] + rows: List[Row] + + def __init__( + self, + *headers: Union[Column, str], + title: Optional[TextType] = None, + caption: Optional[TextType] = None, + width: Optional[int] = None, + min_width: Optional[int] = None, + box: Optional[box.Box] = box.HEAVY_HEAD, + safe_box: Optional[bool] = None, + padding: PaddingDimensions = (0, 1), + collapse_padding: bool = False, + pad_edge: bool = True, + expand: bool = False, + show_header: bool = True, + show_footer: bool = False, + show_edge: bool = True, + show_lines: bool = False, + leading: int = 0, + style: StyleType = "none", + row_styles: Optional[Iterable[StyleType]] = None, + header_style: Optional[StyleType] = "table.header", + footer_style: Optional[StyleType] = "table.footer", + border_style: Optional[StyleType] = None, + title_style: Optional[StyleType] = None, + caption_style: Optional[StyleType] = None, + title_justify: "JustifyMethod" = "center", + caption_justify: "JustifyMethod" = "center", + highlight: bool = False, + ) -> None: + self.columns: List[Column] = [] + self.rows: List[Row] = [] + self.title = title + self.caption = caption + self.width = width + self.min_width = min_width + self.box = box + self.safe_box = safe_box + self._padding = Padding.unpack(padding) + self.pad_edge = pad_edge + self._expand = expand + self.show_header = show_header + self.show_footer = show_footer + self.show_edge = show_edge + self.show_lines = show_lines + self.leading = leading + self.collapse_padding = collapse_padding + self.style = style + self.header_style = header_style or "" + self.footer_style = footer_style or "" + self.border_style = border_style + self.title_style = title_style + self.caption_style = caption_style + self.title_justify: "JustifyMethod" = title_justify + self.caption_justify: "JustifyMethod" = caption_justify + self.highlight = highlight + self.row_styles: Sequence[StyleType] = list(row_styles or []) + append_column = self.columns.append + for header in headers: + if isinstance(header, str): + self.add_column(header=header) + else: + header._index = len(self.columns) + append_column(header) + + @classmethod + def grid( + cls, + *headers: Union[Column, str], + padding: PaddingDimensions = 0, + collapse_padding: bool = True, + pad_edge: bool = False, + expand: bool = False, + ) -> "Table": + """Get a table with no lines, headers, or footer. + + Args: + *headers (Union[Column, str]): Column headers, either as a string, or :class:`~rich.table.Column` instance. + padding (PaddingDimensions, optional): Get padding around cells. Defaults to 0. + collapse_padding (bool, optional): Enable collapsing of padding around cells. Defaults to True. + pad_edge (bool, optional): Enable padding around edges of table. Defaults to False. + expand (bool, optional): Expand the table to fit the available space if ``True``, otherwise the table width will be auto-calculated. Defaults to False. + + Returns: + Table: A table instance. + """ + return cls( + *headers, + box=None, + padding=padding, + collapse_padding=collapse_padding, + show_header=False, + show_footer=False, + show_edge=False, + pad_edge=pad_edge, + expand=expand, + ) + + @property + def expand(self) -> bool: + """Setting a non-None self.width implies expand.""" + return self._expand or self.width is not None + + @expand.setter + def expand(self, expand: bool) -> None: + """Set expand.""" + self._expand = expand + + @property + def _extra_width(self) -> int: + """Get extra width to add to cell content.""" + width = 0 + if self.box and self.show_edge: + width += 2 + if self.box: + width += len(self.columns) - 1 + return width + + @property + def row_count(self) -> int: + """Get the current number of rows.""" + return len(self.rows) + + def get_row_style(self, console: "Console", index: int) -> StyleType: + """Get the current row style.""" + style = Style.null() + if self.row_styles: + style += console.get_style(self.row_styles[index % len(self.row_styles)]) + row_style = self.rows[index].style + if row_style is not None: + style += console.get_style(row_style) + return style + + def __rich_measure__( + self, console: "Console", options: "ConsoleOptions" + ) -> Measurement: + max_width = options.max_width + if self.width is not None: + max_width = self.width + if max_width < 0: + return Measurement(0, 0) + + extra_width = self._extra_width + max_width = sum( + self._calculate_column_widths( + console, options.update_width(max_width - extra_width) + ) + ) + _measure_column = self._measure_column + + measurements = [ + _measure_column(console, options.update_width(max_width), column) + for column in self.columns + ] + minimum_width = ( + sum(measurement.minimum for measurement in measurements) + extra_width + ) + maximum_width = ( + sum(measurement.maximum for measurement in measurements) + extra_width + if (self.width is None) + else self.width + ) + measurement = Measurement(minimum_width, maximum_width) + measurement = measurement.clamp(self.min_width) + return measurement + + @property + def padding(self) -> Tuple[int, int, int, int]: + """Get cell padding.""" + return self._padding + + @padding.setter + def padding(self, padding: PaddingDimensions) -> "Table": + """Set cell padding.""" + self._padding = Padding.unpack(padding) + return self + + def add_column( + self, + header: "RenderableType" = "", + footer: "RenderableType" = "", + *, + header_style: Optional[StyleType] = None, + footer_style: Optional[StyleType] = None, + style: Optional[StyleType] = None, + justify: "JustifyMethod" = "left", + vertical: "VerticalAlignMethod" = "top", + overflow: "OverflowMethod" = "ellipsis", + width: Optional[int] = None, + min_width: Optional[int] = None, + max_width: Optional[int] = None, + ratio: Optional[int] = None, + no_wrap: bool = False, + ) -> None: + """Add a column to the table. + + Args: + header (RenderableType, optional): Text or renderable for the header. + Defaults to "". + footer (RenderableType, optional): Text or renderable for the footer. + Defaults to "". + header_style (Union[str, Style], optional): Style for the header, or None for default. Defaults to None. + footer_style (Union[str, Style], optional): Style for the footer, or None for default. Defaults to None. + style (Union[str, Style], optional): Style for the column cells, or None for default. Defaults to None. + justify (JustifyMethod, optional): Alignment for cells. Defaults to "left". + vertical (VerticalAlignMethod, optional): Vertical alignment, one of "top", "middle", or "bottom". Defaults to "top". + overflow (OverflowMethod): Overflow method: "crop", "fold", "ellipsis". Defaults to "ellipsis". + width (int, optional): Desired width of column in characters, or None to fit to contents. Defaults to None. + min_width (Optional[int], optional): Minimum width of column, or ``None`` for no minimum. Defaults to None. + max_width (Optional[int], optional): Maximum width of column, or ``None`` for no maximum. Defaults to None. + ratio (int, optional): Flexible ratio for the column (requires ``Table.expand`` or ``Table.width``). Defaults to None. + no_wrap (bool, optional): Set to ``True`` to disable wrapping of this column. + """ + + column = Column( + _index=len(self.columns), + header=header, + footer=footer, + header_style=header_style or "", + footer_style=footer_style or "", + style=style or "", + justify=justify, + vertical=vertical, + overflow=overflow, + width=width, + min_width=min_width, + max_width=max_width, + ratio=ratio, + no_wrap=no_wrap, + ) + self.columns.append(column) + + def add_row( + self, + *renderables: Optional["RenderableType"], + style: Optional[StyleType] = None, + end_section: bool = False, + ) -> None: + """Add a row of renderables. + + Args: + *renderables (None or renderable): Each cell in a row must be a renderable object (including str), + or ``None`` for a blank cell. + style (StyleType, optional): An optional style to apply to the entire row. Defaults to None. + end_section (bool, optional): End a section and draw a line. Defaults to False. + + Raises: + errors.NotRenderableError: If you add something that can't be rendered. + """ + + def add_cell(column: Column, renderable: "RenderableType") -> None: + column._cells.append(renderable) + + cell_renderables: List[Optional["RenderableType"]] = list(renderables) + + columns = self.columns + if len(cell_renderables) < len(columns): + cell_renderables = [ + *cell_renderables, + *[None] * (len(columns) - len(cell_renderables)), + ] + for index, renderable in enumerate(cell_renderables): + if index == len(columns): + column = Column(_index=index) + for _ in self.rows: + add_cell(column, Text("")) + self.columns.append(column) + else: + column = columns[index] + if renderable is None: + add_cell(column, "") + elif is_renderable(renderable): + add_cell(column, renderable) + else: + raise errors.NotRenderableError( + f"unable to render {type(renderable).__name__}; a string or other renderable object is required" + ) + self.rows.append(Row(style=style, end_section=end_section)) + + def add_section(self) -> None: + """Add a new section (draw a line after current row).""" + + if self.rows: + self.rows[-1].end_section = True + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + if not self.columns: + yield Segment("\n") + return + + max_width = options.max_width + if self.width is not None: + max_width = self.width + + extra_width = self._extra_width + widths = self._calculate_column_widths( + console, options.update_width(max_width - extra_width) + ) + table_width = sum(widths) + extra_width + + render_options = options.update( + width=table_width, highlight=self.highlight, height=None + ) + + def render_annotation( + text: TextType, style: StyleType, justify: "JustifyMethod" = "center" + ) -> "RenderResult": + render_text = ( + console.render_str(text, style=style, highlight=False) + if isinstance(text, str) + else text + ) + return console.render( + render_text, options=render_options.update(justify=justify) + ) + + if self.title: + yield from render_annotation( + self.title, + style=Style.pick_first(self.title_style, "table.title"), + justify=self.title_justify, + ) + yield from self._render(console, render_options, widths) + if self.caption: + yield from render_annotation( + self.caption, + style=Style.pick_first(self.caption_style, "table.caption"), + justify=self.caption_justify, + ) + + def _calculate_column_widths( + self, console: "Console", options: "ConsoleOptions" + ) -> List[int]: + """Calculate the widths of each column, including padding, not including borders.""" + max_width = options.max_width + columns = self.columns + width_ranges = [ + self._measure_column(console, options, column) for column in columns + ] + widths = [_range.maximum or 1 for _range in width_ranges] + get_padding_width = self._get_padding_width + extra_width = self._extra_width + if self.expand: + ratios = [col.ratio or 0 for col in columns if col.flexible] + if any(ratios): + fixed_widths = [ + 0 if column.flexible else _range.maximum + for _range, column in zip(width_ranges, columns) + ] + flex_minimum = [ + (column.width or 1) + get_padding_width(column._index) + for column in columns + if column.flexible + ] + flexible_width = max_width - sum(fixed_widths) + flex_widths = ratio_distribute(flexible_width, ratios, flex_minimum) + iter_flex_widths = iter(flex_widths) + for index, column in enumerate(columns): + if column.flexible: + widths[index] = fixed_widths[index] + next(iter_flex_widths) + table_width = sum(widths) + + if table_width > max_width: + widths = self._collapse_widths( + widths, + [(column.width is None and not column.no_wrap) for column in columns], + max_width, + ) + table_width = sum(widths) + # last resort, reduce columns evenly + if table_width > max_width: + excess_width = table_width - max_width + widths = ratio_reduce(excess_width, [1] * len(widths), widths, widths) + table_width = sum(widths) + + width_ranges = [ + self._measure_column(console, options.update_width(width), column) + for width, column in zip(widths, columns) + ] + widths = [_range.maximum or 0 for _range in width_ranges] + + if (table_width < max_width and self.expand) or ( + self.min_width is not None and table_width < (self.min_width - extra_width) + ): + _max_width = ( + max_width + if self.min_width is None + else min(self.min_width - extra_width, max_width) + ) + pad_widths = ratio_distribute(_max_width - table_width, widths) + widths = [_width + pad for _width, pad in zip(widths, pad_widths)] + + return widths + + @classmethod + def _collapse_widths( + cls, widths: List[int], wrapable: List[bool], max_width: int + ) -> List[int]: + """Reduce widths so that the total is under max_width. + + Args: + widths (List[int]): List of widths. + wrapable (List[bool]): List of booleans that indicate if a column may shrink. + max_width (int): Maximum width to reduce to. + + Returns: + List[int]: A new list of widths. + """ + total_width = sum(widths) + excess_width = total_width - max_width + if any(wrapable): + while total_width and excess_width > 0: + max_column = max( + width for width, allow_wrap in zip(widths, wrapable) if allow_wrap + ) + second_max_column = max( + width if allow_wrap and width != max_column else 0 + for width, allow_wrap in zip(widths, wrapable) + ) + column_difference = max_column - second_max_column + ratios = [ + (1 if (width == max_column and allow_wrap) else 0) + for width, allow_wrap in zip(widths, wrapable) + ] + if not any(ratios) or not column_difference: + break + max_reduce = [min(excess_width, column_difference)] * len(widths) + widths = ratio_reduce(excess_width, ratios, max_reduce, widths) + + total_width = sum(widths) + excess_width = total_width - max_width + return widths + + def _get_cells( + self, console: "Console", column_index: int, column: Column + ) -> Iterable[_Cell]: + """Get all the cells with padding and optional header.""" + + collapse_padding = self.collapse_padding + pad_edge = self.pad_edge + padding = self.padding + any_padding = any(padding) + + first_column = column_index == 0 + last_column = column_index == len(self.columns) - 1 + + _padding_cache: Dict[Tuple[bool, bool], Tuple[int, int, int, int]] = {} + + def get_padding(first_row: bool, last_row: bool) -> Tuple[int, int, int, int]: + cached = _padding_cache.get((first_row, last_row)) + if cached: + return cached + top, right, bottom, left = padding + + if collapse_padding: + if not first_column: + left = max(0, left - right) + if not last_row: + bottom = max(0, top - bottom) + + if not pad_edge: + if first_column: + left = 0 + if last_column: + right = 0 + if first_row: + top = 0 + if last_row: + bottom = 0 + _padding = (top, right, bottom, left) + _padding_cache[(first_row, last_row)] = _padding + return _padding + + raw_cells: List[Tuple[StyleType, "RenderableType"]] = [] + _append = raw_cells.append + get_style = console.get_style + if self.show_header: + header_style = get_style(self.header_style or "") + get_style( + column.header_style + ) + _append((header_style, column.header)) + cell_style = get_style(column.style or "") + for cell in column.cells: + _append((cell_style, cell)) + if self.show_footer: + footer_style = get_style(self.footer_style or "") + get_style( + column.footer_style + ) + _append((footer_style, column.footer)) + + if any_padding: + _Padding = Padding + for first, last, (style, renderable) in loop_first_last(raw_cells): + yield _Cell( + style, + _Padding(renderable, get_padding(first, last)), + getattr(renderable, "vertical", None) or column.vertical, + ) + else: + for style, renderable in raw_cells: + yield _Cell( + style, + renderable, + getattr(renderable, "vertical", None) or column.vertical, + ) + + def _get_padding_width(self, column_index: int) -> int: + """Get extra width from padding.""" + _, pad_right, _, pad_left = self.padding + if self.collapse_padding: + if column_index > 0: + pad_left = max(0, pad_left - pad_right) + return pad_left + pad_right + + def _measure_column( + self, + console: "Console", + options: "ConsoleOptions", + column: Column, + ) -> Measurement: + """Get the minimum and maximum width of the column.""" + + max_width = options.max_width + if max_width < 1: + return Measurement(0, 0) + + padding_width = self._get_padding_width(column._index) + + if column.width is not None: + # Fixed width column + return Measurement( + column.width + padding_width, column.width + padding_width + ).with_maximum(max_width) + # Flexible column, we need to measure contents + min_widths: List[int] = [] + max_widths: List[int] = [] + append_min = min_widths.append + append_max = max_widths.append + get_render_width = Measurement.get + for cell in self._get_cells(console, column._index, column): + _min, _max = get_render_width(console, options, cell.renderable) + append_min(_min) + append_max(_max) + + measurement = Measurement( + max(min_widths) if min_widths else 1, + max(max_widths) if max_widths else max_width, + ).with_maximum(max_width) + measurement = measurement.clamp( + None if column.min_width is None else column.min_width + padding_width, + None if column.max_width is None else column.max_width + padding_width, + ) + return measurement + + def _render( + self, console: "Console", options: "ConsoleOptions", widths: List[int] + ) -> "RenderResult": + table_style = console.get_style(self.style or "") + + border_style = table_style + console.get_style(self.border_style or "") + _column_cells = ( + self._get_cells(console, column_index, column) + for column_index, column in enumerate(self.columns) + ) + row_cells: List[Tuple[_Cell, ...]] = list(zip(*_column_cells)) + _box = ( + self.box.substitute( + options, safe=pick_bool(self.safe_box, console.safe_box) + ) + if self.box + else None + ) + _box = _box.get_plain_headed_box() if _box and not self.show_header else _box + + new_line = Segment.line() + + columns = self.columns + show_header = self.show_header + show_footer = self.show_footer + show_edge = self.show_edge + show_lines = self.show_lines + leading = self.leading + + _Segment = Segment + if _box: + box_segments = [ + ( + _Segment(_box.head_left, border_style), + _Segment(_box.head_right, border_style), + _Segment(_box.head_vertical, border_style), + ), + ( + _Segment(_box.foot_left, border_style), + _Segment(_box.foot_right, border_style), + _Segment(_box.foot_vertical, border_style), + ), + ( + _Segment(_box.mid_left, border_style), + _Segment(_box.mid_right, border_style), + _Segment(_box.mid_vertical, border_style), + ), + ] + if show_edge: + yield _Segment(_box.get_top(widths), border_style) + yield new_line + else: + box_segments = [] + + get_row_style = self.get_row_style + get_style = console.get_style + + for index, (first, last, row_cell) in enumerate(loop_first_last(row_cells)): + header_row = first and show_header + footer_row = last and show_footer + row = ( + self.rows[index - show_header] + if (not header_row and not footer_row) + else None + ) + max_height = 1 + cells: List[List[List[Segment]]] = [] + if header_row or footer_row: + row_style = Style.null() + else: + row_style = get_style( + get_row_style(console, index - 1 if show_header else index) + ) + for width, cell, column in zip(widths, row_cell, columns): + render_options = options.update( + width=width, + justify=column.justify, + no_wrap=column.no_wrap, + overflow=column.overflow, + height=None, + ) + lines = console.render_lines( + cell.renderable, + render_options, + style=get_style(cell.style) + row_style, + ) + max_height = max(max_height, len(lines)) + cells.append(lines) + + row_height = max(len(cell) for cell in cells) + + def align_cell( + cell: List[List[Segment]], + vertical: "VerticalAlignMethod", + width: int, + style: Style, + ) -> List[List[Segment]]: + if header_row: + vertical = "bottom" + elif footer_row: + vertical = "top" + + if vertical == "top": + return _Segment.align_top(cell, width, row_height, style) + elif vertical == "middle": + return _Segment.align_middle(cell, width, row_height, style) + return _Segment.align_bottom(cell, width, row_height, style) + + cells[:] = [ + _Segment.set_shape( + align_cell( + cell, + _cell.vertical, + width, + get_style(_cell.style) + row_style, + ), + width, + max_height, + ) + for width, _cell, cell, column in zip(widths, row_cell, cells, columns) + ] + + if _box: + if last and show_footer: + yield _Segment( + _box.get_row(widths, "foot", edge=show_edge), border_style + ) + yield new_line + left, right, _divider = box_segments[0 if first else (2 if last else 1)] + + # If the column divider is whitespace also style it with the row background + divider = ( + _divider + if _divider.text.strip() + else _Segment( + _divider.text, row_style.background_style + _divider.style + ) + ) + for line_no in range(max_height): + if show_edge: + yield left + for last_cell, rendered_cell in loop_last(cells): + yield from rendered_cell[line_no] + if not last_cell: + yield divider + if show_edge: + yield right + yield new_line + else: + for line_no in range(max_height): + for rendered_cell in cells: + yield from rendered_cell[line_no] + yield new_line + if _box and first and show_header: + yield _Segment( + _box.get_row(widths, "head", edge=show_edge), border_style + ) + yield new_line + end_section = row and row.end_section + if _box and (show_lines or leading or end_section): + if ( + not last + and not (show_footer and index >= len(row_cells) - 2) + and not (show_header and header_row) + ): + if leading: + yield _Segment( + _box.get_row(widths, "mid", edge=show_edge) * leading, + border_style, + ) + else: + yield _Segment( + _box.get_row(widths, "row", edge=show_edge), border_style + ) + yield new_line + + if _box and show_edge: + yield _Segment(_box.get_bottom(widths), border_style) + yield new_line + + +if __name__ == "__main__": # pragma: no cover + from pip._vendor.rich.console import Console + from pip._vendor.rich.highlighter import ReprHighlighter + from pip._vendor.rich.table import Table as Table + + from ._timer import timer + + with timer("Table render"): + table = Table( + title="Star Wars Movies", + caption="Rich example table", + caption_justify="right", + ) + + table.add_column( + "Released", header_style="bright_cyan", style="cyan", no_wrap=True + ) + table.add_column("Title", style="magenta") + table.add_column("Box Office", justify="right", style="green") + + table.add_row( + "Dec 20, 2019", + "Star Wars: The Rise of Skywalker", + "$952,110,690", + ) + table.add_row("May 25, 2018", "Solo: A Star Wars Story", "$393,151,347") + table.add_row( + "Dec 15, 2017", + "Star Wars Ep. V111: The Last Jedi", + "$1,332,539,889", + style="on black", + end_section=True, + ) + table.add_row( + "Dec 16, 2016", + "Rogue One: A Star Wars Story", + "$1,332,439,889", + ) + + def header(text: str) -> None: + console.print() + console.rule(highlight(text)) + console.print() + + console = Console() + highlight = ReprHighlighter() + header("Example Table") + console.print(table, justify="center") + + table.expand = True + header("expand=True") + console.print(table) + + table.width = 50 + header("width=50") + + console.print(table, justify="center") + + table.width = None + table.expand = False + table.row_styles = ["dim", "none"] + header("row_styles=['dim', 'none']") + + console.print(table, justify="center") + + table.width = None + table.expand = False + table.row_styles = ["dim", "none"] + table.leading = 1 + header("leading=1, row_styles=['dim', 'none']") + console.print(table, justify="center") + + table.width = None + table.expand = False + table.row_styles = ["dim", "none"] + table.show_lines = True + table.leading = 0 + header("show_lines=True, row_styles=['dim', 'none']") + console.print(table, justify="center") diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/terminal_theme.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/terminal_theme.py new file mode 100644 index 0000000..565e9d9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/terminal_theme.py @@ -0,0 +1,153 @@ +from typing import List, Optional, Tuple + +from .color_triplet import ColorTriplet +from .palette import Palette + +_ColorTuple = Tuple[int, int, int] + + +class TerminalTheme: + """A color theme used when exporting console content. + + Args: + background (Tuple[int, int, int]): The background color. + foreground (Tuple[int, int, int]): The foreground (text) color. + normal (List[Tuple[int, int, int]]): A list of 8 normal intensity colors. + bright (List[Tuple[int, int, int]], optional): A list of 8 bright colors, or None + to repeat normal intensity. Defaults to None. + """ + + def __init__( + self, + background: _ColorTuple, + foreground: _ColorTuple, + normal: List[_ColorTuple], + bright: Optional[List[_ColorTuple]] = None, + ) -> None: + self.background_color = ColorTriplet(*background) + self.foreground_color = ColorTriplet(*foreground) + self.ansi_colors = Palette(normal + (bright or normal)) + + +DEFAULT_TERMINAL_THEME = TerminalTheme( + (255, 255, 255), + (0, 0, 0), + [ + (0, 0, 0), + (128, 0, 0), + (0, 128, 0), + (128, 128, 0), + (0, 0, 128), + (128, 0, 128), + (0, 128, 128), + (192, 192, 192), + ], + [ + (128, 128, 128), + (255, 0, 0), + (0, 255, 0), + (255, 255, 0), + (0, 0, 255), + (255, 0, 255), + (0, 255, 255), + (255, 255, 255), + ], +) + +MONOKAI = TerminalTheme( + (12, 12, 12), + (217, 217, 217), + [ + (26, 26, 26), + (244, 0, 95), + (152, 224, 36), + (253, 151, 31), + (157, 101, 255), + (244, 0, 95), + (88, 209, 235), + (196, 197, 181), + (98, 94, 76), + ], + [ + (244, 0, 95), + (152, 224, 36), + (224, 213, 97), + (157, 101, 255), + (244, 0, 95), + (88, 209, 235), + (246, 246, 239), + ], +) +DIMMED_MONOKAI = TerminalTheme( + (25, 25, 25), + (185, 188, 186), + [ + (58, 61, 67), + (190, 63, 72), + (135, 154, 59), + (197, 166, 53), + (79, 118, 161), + (133, 92, 141), + (87, 143, 164), + (185, 188, 186), + (136, 137, 135), + ], + [ + (251, 0, 31), + (15, 114, 47), + (196, 112, 51), + (24, 109, 227), + (251, 0, 103), + (46, 112, 109), + (253, 255, 185), + ], +) +NIGHT_OWLISH = TerminalTheme( + (255, 255, 255), + (64, 63, 83), + [ + (1, 22, 39), + (211, 66, 62), + (42, 162, 152), + (218, 170, 1), + (72, 118, 214), + (64, 63, 83), + (8, 145, 106), + (122, 129, 129), + (122, 129, 129), + ], + [ + (247, 110, 110), + (73, 208, 197), + (218, 194, 107), + (92, 167, 228), + (105, 112, 152), + (0, 201, 144), + (152, 159, 177), + ], +) + +SVG_EXPORT_THEME = TerminalTheme( + (41, 41, 41), + (197, 200, 198), + [ + (75, 78, 85), + (204, 85, 90), + (152, 168, 75), + (208, 179, 68), + (96, 138, 177), + (152, 114, 159), + (104, 160, 179), + (197, 200, 198), + (154, 155, 153), + ], + [ + (255, 38, 39), + (0, 130, 61), + (208, 132, 66), + (25, 132, 233), + (255, 44, 122), + (57, 130, 128), + (253, 253, 197), + ], +) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/text.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/text.py new file mode 100644 index 0000000..209aa94 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/text.py @@ -0,0 +1,1357 @@ +import re +from functools import partial, reduce +from math import gcd +from operator import itemgetter +from typing import ( + TYPE_CHECKING, + Any, + Callable, + Dict, + Iterable, + List, + NamedTuple, + Optional, + Tuple, + Union, +) + +from ._loop import loop_last +from ._pick import pick_bool +from ._wrap import divide_line +from .align import AlignMethod +from .cells import cell_len, set_cell_size +from .containers import Lines +from .control import strip_control_codes +from .emoji import EmojiVariant +from .jupyter import JupyterMixin +from .measure import Measurement +from .segment import Segment +from .style import Style, StyleType + +if TYPE_CHECKING: # pragma: no cover + from .console import Console, ConsoleOptions, JustifyMethod, OverflowMethod + +DEFAULT_JUSTIFY: "JustifyMethod" = "default" +DEFAULT_OVERFLOW: "OverflowMethod" = "fold" + + +_re_whitespace = re.compile(r"\s+$") + +TextType = Union[str, "Text"] +"""A plain string or a :class:`Text` instance.""" + +GetStyleCallable = Callable[[str], Optional[StyleType]] + + +class Span(NamedTuple): + """A marked up region in some text.""" + + start: int + """Span start index.""" + end: int + """Span end index.""" + style: Union[str, Style] + """Style associated with the span.""" + + def __repr__(self) -> str: + return f"Span({self.start}, {self.end}, {self.style!r})" + + def __bool__(self) -> bool: + return self.end > self.start + + def split(self, offset: int) -> Tuple["Span", Optional["Span"]]: + """Split a span in to 2 from a given offset.""" + + if offset < self.start: + return self, None + if offset >= self.end: + return self, None + + start, end, style = self + span1 = Span(start, min(end, offset), style) + span2 = Span(span1.end, end, style) + return span1, span2 + + def move(self, offset: int) -> "Span": + """Move start and end by a given offset. + + Args: + offset (int): Number of characters to add to start and end. + + Returns: + TextSpan: A new TextSpan with adjusted position. + """ + start, end, style = self + return Span(start + offset, end + offset, style) + + def right_crop(self, offset: int) -> "Span": + """Crop the span at the given offset. + + Args: + offset (int): A value between start and end. + + Returns: + Span: A new (possibly smaller) span. + """ + start, end, style = self + if offset >= end: + return self + return Span(start, min(offset, end), style) + + def extend(self, cells: int) -> "Span": + """Extend the span by the given number of cells. + + Args: + cells (int): Additional space to add to end of span. + + Returns: + Span: A span. + """ + if cells: + start, end, style = self + return Span(start, end + cells, style) + else: + return self + + +class Text(JupyterMixin): + """Text with color / style. + + Args: + text (str, optional): Default unstyled text. Defaults to "". + style (Union[str, Style], optional): Base style for text. Defaults to "". + justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to None. + overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None. + no_wrap (bool, optional): Disable text wrapping, or None for default. Defaults to None. + end (str, optional): Character to end text with. Defaults to "\\\\n". + tab_size (int): Number of spaces per tab, or ``None`` to use ``console.tab_size``. Defaults to None. + spans (List[Span], optional). A list of predefined style spans. Defaults to None. + """ + + __slots__ = [ + "_text", + "style", + "justify", + "overflow", + "no_wrap", + "end", + "tab_size", + "_spans", + "_length", + ] + + def __init__( + self, + text: str = "", + style: Union[str, Style] = "", + *, + justify: Optional["JustifyMethod"] = None, + overflow: Optional["OverflowMethod"] = None, + no_wrap: Optional[bool] = None, + end: str = "\n", + tab_size: Optional[int] = None, + spans: Optional[List[Span]] = None, + ) -> None: + sanitized_text = strip_control_codes(text) + self._text = [sanitized_text] + self.style = style + self.justify: Optional["JustifyMethod"] = justify + self.overflow: Optional["OverflowMethod"] = overflow + self.no_wrap = no_wrap + self.end = end + self.tab_size = tab_size + self._spans: List[Span] = spans or [] + self._length: int = len(sanitized_text) + + def __len__(self) -> int: + return self._length + + def __bool__(self) -> bool: + return bool(self._length) + + def __str__(self) -> str: + return self.plain + + def __repr__(self) -> str: + return f"" + + def __add__(self, other: Any) -> "Text": + if isinstance(other, (str, Text)): + result = self.copy() + result.append(other) + return result + return NotImplemented + + def __eq__(self, other: object) -> bool: + if not isinstance(other, Text): + return NotImplemented + return self.plain == other.plain and self._spans == other._spans + + def __contains__(self, other: object) -> bool: + if isinstance(other, str): + return other in self.plain + elif isinstance(other, Text): + return other.plain in self.plain + return False + + def __getitem__(self, slice: Union[int, slice]) -> "Text": + def get_text_at(offset: int) -> "Text": + _Span = Span + text = Text( + self.plain[offset], + spans=[ + _Span(0, 1, style) + for start, end, style in self._spans + if end > offset >= start + ], + end="", + ) + return text + + if isinstance(slice, int): + return get_text_at(slice) + else: + start, stop, step = slice.indices(len(self.plain)) + if step == 1: + lines = self.divide([start, stop]) + return lines[1] + else: + # This would be a bit of work to implement efficiently + # For now, its not required + raise TypeError("slices with step!=1 are not supported") + + @property + def cell_len(self) -> int: + """Get the number of cells required to render this text.""" + return cell_len(self.plain) + + @property + def markup(self) -> str: + """Get console markup to render this Text. + + Returns: + str: A string potentially creating markup tags. + """ + from .markup import escape + + output: List[str] = [] + + plain = self.plain + markup_spans = [ + (0, False, self.style), + *((span.start, False, span.style) for span in self._spans), + *((span.end, True, span.style) for span in self._spans), + (len(plain), True, self.style), + ] + markup_spans.sort(key=itemgetter(0, 1)) + position = 0 + append = output.append + for offset, closing, style in markup_spans: + if offset > position: + append(escape(plain[position:offset])) + position = offset + if style: + append(f"[/{style}]" if closing else f"[{style}]") + markup = "".join(output) + return markup + + @classmethod + def from_markup( + cls, + text: str, + *, + style: Union[str, Style] = "", + emoji: bool = True, + emoji_variant: Optional[EmojiVariant] = None, + justify: Optional["JustifyMethod"] = None, + overflow: Optional["OverflowMethod"] = None, + end: str = "\n", + ) -> "Text": + """Create Text instance from markup. + + Args: + text (str): A string containing console markup. + style (Union[str, Style], optional): Base style for text. Defaults to "". + emoji (bool, optional): Also render emoji code. Defaults to True. + emoji_variant (str, optional): Optional emoji variant, either "text" or "emoji". Defaults to None. + justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to None. + overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None. + end (str, optional): Character to end text with. Defaults to "\\\\n". + + Returns: + Text: A Text instance with markup rendered. + """ + from .markup import render + + rendered_text = render(text, style, emoji=emoji, emoji_variant=emoji_variant) + rendered_text.justify = justify + rendered_text.overflow = overflow + rendered_text.end = end + return rendered_text + + @classmethod + def from_ansi( + cls, + text: str, + *, + style: Union[str, Style] = "", + justify: Optional["JustifyMethod"] = None, + overflow: Optional["OverflowMethod"] = None, + no_wrap: Optional[bool] = None, + end: str = "\n", + tab_size: Optional[int] = 8, + ) -> "Text": + """Create a Text object from a string containing ANSI escape codes. + + Args: + text (str): A string containing escape codes. + style (Union[str, Style], optional): Base style for text. Defaults to "". + justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to None. + overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None. + no_wrap (bool, optional): Disable text wrapping, or None for default. Defaults to None. + end (str, optional): Character to end text with. Defaults to "\\\\n". + tab_size (int): Number of spaces per tab, or ``None`` to use ``console.tab_size``. Defaults to None. + """ + from .ansi import AnsiDecoder + + joiner = Text( + "\n", + justify=justify, + overflow=overflow, + no_wrap=no_wrap, + end=end, + tab_size=tab_size, + style=style, + ) + decoder = AnsiDecoder() + result = joiner.join(line for line in decoder.decode(text)) + return result + + @classmethod + def styled( + cls, + text: str, + style: StyleType = "", + *, + justify: Optional["JustifyMethod"] = None, + overflow: Optional["OverflowMethod"] = None, + ) -> "Text": + """Construct a Text instance with a pre-applied styled. A style applied in this way won't be used + to pad the text when it is justified. + + Args: + text (str): A string containing console markup. + style (Union[str, Style]): Style to apply to the text. Defaults to "". + justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to None. + overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None. + + Returns: + Text: A text instance with a style applied to the entire string. + """ + styled_text = cls(text, justify=justify, overflow=overflow) + styled_text.stylize(style) + return styled_text + + @classmethod + def assemble( + cls, + *parts: Union[str, "Text", Tuple[str, StyleType]], + style: Union[str, Style] = "", + justify: Optional["JustifyMethod"] = None, + overflow: Optional["OverflowMethod"] = None, + no_wrap: Optional[bool] = None, + end: str = "\n", + tab_size: int = 8, + meta: Optional[Dict[str, Any]] = None, + ) -> "Text": + """Construct a text instance by combining a sequence of strings with optional styles. + The positional arguments should be either strings, or a tuple of string + style. + + Args: + style (Union[str, Style], optional): Base style for text. Defaults to "". + justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to None. + overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None. + no_wrap (bool, optional): Disable text wrapping, or None for default. Defaults to None. + end (str, optional): Character to end text with. Defaults to "\\\\n". + tab_size (int): Number of spaces per tab, or ``None`` to use ``console.tab_size``. Defaults to None. + meta (Dict[str, Any], optional). Meta data to apply to text, or None for no meta data. Default to None + + Returns: + Text: A new text instance. + """ + text = cls( + style=style, + justify=justify, + overflow=overflow, + no_wrap=no_wrap, + end=end, + tab_size=tab_size, + ) + append = text.append + _Text = Text + for part in parts: + if isinstance(part, (_Text, str)): + append(part) + else: + append(*part) + if meta: + text.apply_meta(meta) + return text + + @property + def plain(self) -> str: + """Get the text as a single string.""" + if len(self._text) != 1: + self._text[:] = ["".join(self._text)] + return self._text[0] + + @plain.setter + def plain(self, new_text: str) -> None: + """Set the text to a new value.""" + if new_text != self.plain: + sanitized_text = strip_control_codes(new_text) + self._text[:] = [sanitized_text] + old_length = self._length + self._length = len(sanitized_text) + if old_length > self._length: + self._trim_spans() + + @property + def spans(self) -> List[Span]: + """Get a reference to the internal list of spans.""" + return self._spans + + @spans.setter + def spans(self, spans: List[Span]) -> None: + """Set spans.""" + self._spans = spans[:] + + def blank_copy(self, plain: str = "") -> "Text": + """Return a new Text instance with copied metadata (but not the string or spans).""" + copy_self = Text( + plain, + style=self.style, + justify=self.justify, + overflow=self.overflow, + no_wrap=self.no_wrap, + end=self.end, + tab_size=self.tab_size, + ) + return copy_self + + def copy(self) -> "Text": + """Return a copy of this instance.""" + copy_self = Text( + self.plain, + style=self.style, + justify=self.justify, + overflow=self.overflow, + no_wrap=self.no_wrap, + end=self.end, + tab_size=self.tab_size, + ) + copy_self._spans[:] = self._spans + return copy_self + + def stylize( + self, + style: Union[str, Style], + start: int = 0, + end: Optional[int] = None, + ) -> None: + """Apply a style to the text, or a portion of the text. + + Args: + style (Union[str, Style]): Style instance or style definition to apply. + start (int): Start offset (negative indexing is supported). Defaults to 0. + end (Optional[int], optional): End offset (negative indexing is supported), or None for end of text. Defaults to None. + """ + if style: + length = len(self) + if start < 0: + start = length + start + if end is None: + end = length + if end < 0: + end = length + end + if start >= length or end <= start: + # Span not in text or not valid + return + self._spans.append(Span(start, min(length, end), style)) + + def stylize_before( + self, + style: Union[str, Style], + start: int = 0, + end: Optional[int] = None, + ) -> None: + """Apply a style to the text, or a portion of the text. Styles will be applied before other styles already present. + + Args: + style (Union[str, Style]): Style instance or style definition to apply. + start (int): Start offset (negative indexing is supported). Defaults to 0. + end (Optional[int], optional): End offset (negative indexing is supported), or None for end of text. Defaults to None. + """ + if style: + length = len(self) + if start < 0: + start = length + start + if end is None: + end = length + if end < 0: + end = length + end + if start >= length or end <= start: + # Span not in text or not valid + return + self._spans.insert(0, Span(start, min(length, end), style)) + + def apply_meta( + self, meta: Dict[str, Any], start: int = 0, end: Optional[int] = None + ) -> None: + """Apply metadata to the text, or a portion of the text. + + Args: + meta (Dict[str, Any]): A dict of meta information. + start (int): Start offset (negative indexing is supported). Defaults to 0. + end (Optional[int], optional): End offset (negative indexing is supported), or None for end of text. Defaults to None. + + """ + style = Style.from_meta(meta) + self.stylize(style, start=start, end=end) + + def on(self, meta: Optional[Dict[str, Any]] = None, **handlers: Any) -> "Text": + """Apply event handlers (used by Textual project). + + Example: + >>> from rich.text import Text + >>> text = Text("hello world") + >>> text.on(click="view.toggle('world')") + + Args: + meta (Dict[str, Any]): Mapping of meta information. + **handlers: Keyword args are prefixed with "@" to defined handlers. + + Returns: + Text: Self is returned to method may be chained. + """ + meta = {} if meta is None else meta + meta.update({f"@{key}": value for key, value in handlers.items()}) + self.stylize(Style.from_meta(meta)) + return self + + def remove_suffix(self, suffix: str) -> None: + """Remove a suffix if it exists. + + Args: + suffix (str): Suffix to remove. + """ + if self.plain.endswith(suffix): + self.right_crop(len(suffix)) + + def get_style_at_offset(self, console: "Console", offset: int) -> Style: + """Get the style of a character at give offset. + + Args: + console (~Console): Console where text will be rendered. + offset (int): Offset in to text (negative indexing supported) + + Returns: + Style: A Style instance. + """ + # TODO: This is a little inefficient, it is only used by full justify + if offset < 0: + offset = len(self) + offset + get_style = console.get_style + style = get_style(self.style).copy() + for start, end, span_style in self._spans: + if end > offset >= start: + style += get_style(span_style, default="") + return style + + def extend_style(self, spaces: int) -> None: + """Extend the Text given number of spaces where the spaces have the same style as the last character. + + Args: + spaces (int): Number of spaces to add to the Text. + """ + if spaces <= 0: + return + spans = self.spans + new_spaces = " " * spaces + if spans: + end_offset = len(self) + self._spans[:] = [ + span.extend(spaces) if span.end >= end_offset else span + for span in spans + ] + self._text.append(new_spaces) + self._length += spaces + else: + self.plain += new_spaces + + def highlight_regex( + self, + re_highlight: str, + style: Optional[Union[GetStyleCallable, StyleType]] = None, + *, + style_prefix: str = "", + ) -> int: + """Highlight text with a regular expression, where group names are + translated to styles. + + Args: + re_highlight (str): A regular expression. + style (Union[GetStyleCallable, StyleType]): Optional style to apply to whole match, or a callable + which accepts the matched text and returns a style. Defaults to None. + style_prefix (str, optional): Optional prefix to add to style group names. + + Returns: + int: Number of regex matches + """ + count = 0 + append_span = self._spans.append + _Span = Span + plain = self.plain + for match in re.finditer(re_highlight, plain): + get_span = match.span + if style: + start, end = get_span() + match_style = style(plain[start:end]) if callable(style) else style + if match_style is not None and end > start: + append_span(_Span(start, end, match_style)) + + count += 1 + for name in match.groupdict().keys(): + start, end = get_span(name) + if start != -1 and end > start: + append_span(_Span(start, end, f"{style_prefix}{name}")) + return count + + def highlight_words( + self, + words: Iterable[str], + style: Union[str, Style], + *, + case_sensitive: bool = True, + ) -> int: + """Highlight words with a style. + + Args: + words (Iterable[str]): Words to highlight. + style (Union[str, Style]): Style to apply. + case_sensitive (bool, optional): Enable case sensitive matching. Defaults to True. + + Returns: + int: Number of words highlighted. + """ + re_words = "|".join(re.escape(word) for word in words) + add_span = self._spans.append + count = 0 + _Span = Span + for match in re.finditer( + re_words, self.plain, flags=0 if case_sensitive else re.IGNORECASE + ): + start, end = match.span(0) + add_span(_Span(start, end, style)) + count += 1 + return count + + def rstrip(self) -> None: + """Strip whitespace from end of text.""" + self.plain = self.plain.rstrip() + + def rstrip_end(self, size: int) -> None: + """Remove whitespace beyond a certain width at the end of the text. + + Args: + size (int): The desired size of the text. + """ + text_length = len(self) + if text_length > size: + excess = text_length - size + whitespace_match = _re_whitespace.search(self.plain) + if whitespace_match is not None: + whitespace_count = len(whitespace_match.group(0)) + self.right_crop(min(whitespace_count, excess)) + + def set_length(self, new_length: int) -> None: + """Set new length of the text, clipping or padding is required.""" + length = len(self) + if length != new_length: + if length < new_length: + self.pad_right(new_length - length) + else: + self.right_crop(length - new_length) + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> Iterable[Segment]: + tab_size: int = console.tab_size if self.tab_size is None else self.tab_size + justify = self.justify or options.justify or DEFAULT_JUSTIFY + + overflow = self.overflow or options.overflow or DEFAULT_OVERFLOW + + lines = self.wrap( + console, + options.max_width, + justify=justify, + overflow=overflow, + tab_size=tab_size or 8, + no_wrap=pick_bool(self.no_wrap, options.no_wrap, False), + ) + all_lines = Text("\n").join(lines) + yield from all_lines.render(console, end=self.end) + + def __rich_measure__( + self, console: "Console", options: "ConsoleOptions" + ) -> Measurement: + text = self.plain + lines = text.splitlines() + max_text_width = max(cell_len(line) for line in lines) if lines else 0 + words = text.split() + min_text_width = ( + max(cell_len(word) for word in words) if words else max_text_width + ) + return Measurement(min_text_width, max_text_width) + + def render(self, console: "Console", end: str = "") -> Iterable["Segment"]: + """Render the text as Segments. + + Args: + console (Console): Console instance. + end (Optional[str], optional): Optional end character. + + Returns: + Iterable[Segment]: Result of render that may be written to the console. + """ + _Segment = Segment + text = self.plain + if not self._spans: + yield Segment(text) + if end: + yield _Segment(end) + return + get_style = partial(console.get_style, default=Style.null()) + + enumerated_spans = list(enumerate(self._spans, 1)) + style_map = {index: get_style(span.style) for index, span in enumerated_spans} + style_map[0] = get_style(self.style) + + spans = [ + (0, False, 0), + *((span.start, False, index) for index, span in enumerated_spans), + *((span.end, True, index) for index, span in enumerated_spans), + (len(text), True, 0), + ] + spans.sort(key=itemgetter(0, 1)) + + stack: List[int] = [] + stack_append = stack.append + stack_pop = stack.remove + + style_cache: Dict[Tuple[Style, ...], Style] = {} + style_cache_get = style_cache.get + combine = Style.combine + + def get_current_style() -> Style: + """Construct current style from stack.""" + styles = tuple(style_map[_style_id] for _style_id in sorted(stack)) + cached_style = style_cache_get(styles) + if cached_style is not None: + return cached_style + current_style = combine(styles) + style_cache[styles] = current_style + return current_style + + for (offset, leaving, style_id), (next_offset, _, _) in zip(spans, spans[1:]): + if leaving: + stack_pop(style_id) + else: + stack_append(style_id) + if next_offset > offset: + yield _Segment(text[offset:next_offset], get_current_style()) + if end: + yield _Segment(end) + + def join(self, lines: Iterable["Text"]) -> "Text": + """Join text together with this instance as the separator. + + Args: + lines (Iterable[Text]): An iterable of Text instances to join. + + Returns: + Text: A new text instance containing join text. + """ + + new_text = self.blank_copy() + + def iter_text() -> Iterable["Text"]: + if self.plain: + for last, line in loop_last(lines): + yield line + if not last: + yield self + else: + yield from lines + + extend_text = new_text._text.extend + append_span = new_text._spans.append + extend_spans = new_text._spans.extend + offset = 0 + _Span = Span + + for text in iter_text(): + extend_text(text._text) + if text.style: + append_span(_Span(offset, offset + len(text), text.style)) + extend_spans( + _Span(offset + start, offset + end, style) + for start, end, style in text._spans + ) + offset += len(text) + new_text._length = offset + return new_text + + def expand_tabs(self, tab_size: Optional[int] = None) -> None: + """Converts tabs to spaces. + + Args: + tab_size (int, optional): Size of tabs. Defaults to 8. + + """ + if "\t" not in self.plain: + return + if tab_size is None: + tab_size = self.tab_size + if tab_size is None: + tab_size = 8 + + new_text: List[Text] = [] + append = new_text.append + + for line in self.split("\n", include_separator=True): + if "\t" not in line.plain: + append(line) + else: + cell_position = 0 + parts = line.split("\t", include_separator=True) + for part in parts: + if part.plain.endswith("\t"): + part._text[-1] = part._text[-1][:-1] + " " + cell_position += part.cell_len + tab_remainder = cell_position % tab_size + if tab_remainder: + spaces = tab_size - tab_remainder + part.extend_style(spaces) + cell_position += spaces + else: + cell_position += part.cell_len + append(part) + + result = Text("").join(new_text) + + self._text = [result.plain] + self._length = len(self.plain) + self._spans[:] = result._spans + + def truncate( + self, + max_width: int, + *, + overflow: Optional["OverflowMethod"] = None, + pad: bool = False, + ) -> None: + """Truncate text if it is longer that a given width. + + Args: + max_width (int): Maximum number of characters in text. + overflow (str, optional): Overflow method: "crop", "fold", or "ellipsis". Defaults to None, to use self.overflow. + pad (bool, optional): Pad with spaces if the length is less than max_width. Defaults to False. + """ + _overflow = overflow or self.overflow or DEFAULT_OVERFLOW + if _overflow != "ignore": + length = cell_len(self.plain) + if length > max_width: + if _overflow == "ellipsis": + self.plain = set_cell_size(self.plain, max_width - 1) + "…" + else: + self.plain = set_cell_size(self.plain, max_width) + if pad and length < max_width: + spaces = max_width - length + self._text = [f"{self.plain}{' ' * spaces}"] + self._length = len(self.plain) + + def _trim_spans(self) -> None: + """Remove or modify any spans that are over the end of the text.""" + max_offset = len(self.plain) + _Span = Span + self._spans[:] = [ + ( + span + if span.end < max_offset + else _Span(span.start, min(max_offset, span.end), span.style) + ) + for span in self._spans + if span.start < max_offset + ] + + def pad(self, count: int, character: str = " ") -> None: + """Pad left and right with a given number of characters. + + Args: + count (int): Width of padding. + character (str): The character to pad with. Must be a string of length 1. + """ + assert len(character) == 1, "Character must be a string of length 1" + if count: + pad_characters = character * count + self.plain = f"{pad_characters}{self.plain}{pad_characters}" + _Span = Span + self._spans[:] = [ + _Span(start + count, end + count, style) + for start, end, style in self._spans + ] + + def pad_left(self, count: int, character: str = " ") -> None: + """Pad the left with a given character. + + Args: + count (int): Number of characters to pad. + character (str, optional): Character to pad with. Defaults to " ". + """ + assert len(character) == 1, "Character must be a string of length 1" + if count: + self.plain = f"{character * count}{self.plain}" + _Span = Span + self._spans[:] = [ + _Span(start + count, end + count, style) + for start, end, style in self._spans + ] + + def pad_right(self, count: int, character: str = " ") -> None: + """Pad the right with a given character. + + Args: + count (int): Number of characters to pad. + character (str, optional): Character to pad with. Defaults to " ". + """ + assert len(character) == 1, "Character must be a string of length 1" + if count: + self.plain = f"{self.plain}{character * count}" + + def align(self, align: AlignMethod, width: int, character: str = " ") -> None: + """Align text to a given width. + + Args: + align (AlignMethod): One of "left", "center", or "right". + width (int): Desired width. + character (str, optional): Character to pad with. Defaults to " ". + """ + self.truncate(width) + excess_space = width - cell_len(self.plain) + if excess_space: + if align == "left": + self.pad_right(excess_space, character) + elif align == "center": + left = excess_space // 2 + self.pad_left(left, character) + self.pad_right(excess_space - left, character) + else: + self.pad_left(excess_space, character) + + def append( + self, text: Union["Text", str], style: Optional[Union[str, "Style"]] = None + ) -> "Text": + """Add text with an optional style. + + Args: + text (Union[Text, str]): A str or Text to append. + style (str, optional): A style name. Defaults to None. + + Returns: + Text: Returns self for chaining. + """ + + if not isinstance(text, (str, Text)): + raise TypeError("Only str or Text can be appended to Text") + + if len(text): + if isinstance(text, str): + sanitized_text = strip_control_codes(text) + self._text.append(sanitized_text) + offset = len(self) + text_length = len(sanitized_text) + if style: + self._spans.append(Span(offset, offset + text_length, style)) + self._length += text_length + elif isinstance(text, Text): + _Span = Span + if style is not None: + raise ValueError( + "style must not be set when appending Text instance" + ) + text_length = self._length + if text.style: + self._spans.append( + _Span(text_length, text_length + len(text), text.style) + ) + self._text.append(text.plain) + self._spans.extend( + _Span(start + text_length, end + text_length, style) + for start, end, style in text._spans + ) + self._length += len(text) + return self + + def append_text(self, text: "Text") -> "Text": + """Append another Text instance. This method is more performant that Text.append, but + only works for Text. + + Args: + text (Text): The Text instance to append to this instance. + + Returns: + Text: Returns self for chaining. + """ + _Span = Span + text_length = self._length + if text.style: + self._spans.append(_Span(text_length, text_length + len(text), text.style)) + self._text.append(text.plain) + self._spans.extend( + _Span(start + text_length, end + text_length, style) + for start, end, style in text._spans + ) + self._length += len(text) + return self + + def append_tokens( + self, tokens: Iterable[Tuple[str, Optional[StyleType]]] + ) -> "Text": + """Append iterable of str and style. Style may be a Style instance or a str style definition. + + Args: + tokens (Iterable[Tuple[str, Optional[StyleType]]]): An iterable of tuples containing str content and style. + + Returns: + Text: Returns self for chaining. + """ + append_text = self._text.append + append_span = self._spans.append + _Span = Span + offset = len(self) + for content, style in tokens: + append_text(content) + if style: + append_span(_Span(offset, offset + len(content), style)) + offset += len(content) + self._length = offset + return self + + def copy_styles(self, text: "Text") -> None: + """Copy styles from another Text instance. + + Args: + text (Text): A Text instance to copy styles from, must be the same length. + """ + self._spans.extend(text._spans) + + def split( + self, + separator: str = "\n", + *, + include_separator: bool = False, + allow_blank: bool = False, + ) -> Lines: + """Split rich text in to lines, preserving styles. + + Args: + separator (str, optional): String to split on. Defaults to "\\\\n". + include_separator (bool, optional): Include the separator in the lines. Defaults to False. + allow_blank (bool, optional): Return a blank line if the text ends with a separator. Defaults to False. + + Returns: + List[RichText]: A list of rich text, one per line of the original. + """ + assert separator, "separator must not be empty" + + text = self.plain + if separator not in text: + return Lines([self.copy()]) + + if include_separator: + lines = self.divide( + match.end() for match in re.finditer(re.escape(separator), text) + ) + else: + + def flatten_spans() -> Iterable[int]: + for match in re.finditer(re.escape(separator), text): + start, end = match.span() + yield start + yield end + + lines = Lines( + line for line in self.divide(flatten_spans()) if line.plain != separator + ) + + if not allow_blank and text.endswith(separator): + lines.pop() + + return lines + + def divide(self, offsets: Iterable[int]) -> Lines: + """Divide text in to a number of lines at given offsets. + + Args: + offsets (Iterable[int]): Offsets used to divide text. + + Returns: + Lines: New RichText instances between offsets. + """ + _offsets = list(offsets) + + if not _offsets: + return Lines([self.copy()]) + + text = self.plain + text_length = len(text) + divide_offsets = [0, *_offsets, text_length] + line_ranges = list(zip(divide_offsets, divide_offsets[1:])) + + style = self.style + justify = self.justify + overflow = self.overflow + _Text = Text + new_lines = Lines( + _Text( + text[start:end], + style=style, + justify=justify, + overflow=overflow, + ) + for start, end in line_ranges + ) + if not self._spans: + return new_lines + + _line_appends = [line._spans.append for line in new_lines._lines] + line_count = len(line_ranges) + _Span = Span + + for span_start, span_end, style in self._spans: + lower_bound = 0 + upper_bound = line_count + start_line_no = (lower_bound + upper_bound) // 2 + + while True: + line_start, line_end = line_ranges[start_line_no] + if span_start < line_start: + upper_bound = start_line_no - 1 + elif span_start > line_end: + lower_bound = start_line_no + 1 + else: + break + start_line_no = (lower_bound + upper_bound) // 2 + + if span_end < line_end: + end_line_no = start_line_no + else: + end_line_no = lower_bound = start_line_no + upper_bound = line_count + + while True: + line_start, line_end = line_ranges[end_line_no] + if span_end < line_start: + upper_bound = end_line_no - 1 + elif span_end > line_end: + lower_bound = end_line_no + 1 + else: + break + end_line_no = (lower_bound + upper_bound) // 2 + + for line_no in range(start_line_no, end_line_no + 1): + line_start, line_end = line_ranges[line_no] + new_start = max(0, span_start - line_start) + new_end = min(span_end - line_start, line_end - line_start) + if new_end > new_start: + _line_appends[line_no](_Span(new_start, new_end, style)) + + return new_lines + + def right_crop(self, amount: int = 1) -> None: + """Remove a number of characters from the end of the text.""" + max_offset = len(self.plain) - amount + _Span = Span + self._spans[:] = [ + ( + span + if span.end < max_offset + else _Span(span.start, min(max_offset, span.end), span.style) + ) + for span in self._spans + if span.start < max_offset + ] + self._text = [self.plain[:-amount]] + self._length -= amount + + def wrap( + self, + console: "Console", + width: int, + *, + justify: Optional["JustifyMethod"] = None, + overflow: Optional["OverflowMethod"] = None, + tab_size: int = 8, + no_wrap: Optional[bool] = None, + ) -> Lines: + """Word wrap the text. + + Args: + console (Console): Console instance. + width (int): Number of cells available per line. + justify (str, optional): Justify method: "default", "left", "center", "full", "right". Defaults to "default". + overflow (str, optional): Overflow method: "crop", "fold", or "ellipsis". Defaults to None. + tab_size (int, optional): Default tab size. Defaults to 8. + no_wrap (bool, optional): Disable wrapping, Defaults to False. + + Returns: + Lines: Number of lines. + """ + wrap_justify = justify or self.justify or DEFAULT_JUSTIFY + wrap_overflow = overflow or self.overflow or DEFAULT_OVERFLOW + + no_wrap = pick_bool(no_wrap, self.no_wrap, False) or overflow == "ignore" + + lines = Lines() + for line in self.split(allow_blank=True): + if "\t" in line: + line.expand_tabs(tab_size) + if no_wrap: + new_lines = Lines([line]) + else: + offsets = divide_line(str(line), width, fold=wrap_overflow == "fold") + new_lines = line.divide(offsets) + for line in new_lines: + line.rstrip_end(width) + if wrap_justify: + new_lines.justify( + console, width, justify=wrap_justify, overflow=wrap_overflow + ) + for line in new_lines: + line.truncate(width, overflow=wrap_overflow) + lines.extend(new_lines) + return lines + + def fit(self, width: int) -> Lines: + """Fit the text in to given width by chopping in to lines. + + Args: + width (int): Maximum characters in a line. + + Returns: + Lines: Lines container. + """ + lines: Lines = Lines() + append = lines.append + for line in self.split(): + line.set_length(width) + append(line) + return lines + + def detect_indentation(self) -> int: + """Auto-detect indentation of code. + + Returns: + int: Number of spaces used to indent code. + """ + + _indentations = { + len(match.group(1)) + for match in re.finditer(r"^( *)(.*)$", self.plain, flags=re.MULTILINE) + } + + try: + indentation = ( + reduce(gcd, [indent for indent in _indentations if not indent % 2]) or 1 + ) + except TypeError: + indentation = 1 + + return indentation + + def with_indent_guides( + self, + indent_size: Optional[int] = None, + *, + character: str = "│", + style: StyleType = "dim green", + ) -> "Text": + """Adds indent guide lines to text. + + Args: + indent_size (Optional[int]): Size of indentation, or None to auto detect. Defaults to None. + character (str, optional): Character to use for indentation. Defaults to "│". + style (Union[Style, str], optional): Style of indent guides. + + Returns: + Text: New text with indentation guides. + """ + + _indent_size = self.detect_indentation() if indent_size is None else indent_size + + text = self.copy() + text.expand_tabs() + indent_line = f"{character}{' ' * (_indent_size - 1)}" + + re_indent = re.compile(r"^( *)(.*)$") + new_lines: List[Text] = [] + add_line = new_lines.append + blank_lines = 0 + for line in text.split(allow_blank=True): + match = re_indent.match(line.plain) + if not match or not match.group(2): + blank_lines += 1 + continue + indent = match.group(1) + full_indents, remaining_space = divmod(len(indent), _indent_size) + new_indent = f"{indent_line * full_indents}{' ' * remaining_space}" + line.plain = new_indent + line.plain[len(new_indent) :] + line.stylize(style, 0, len(new_indent)) + if blank_lines: + new_lines.extend([Text(new_indent, style=style)] * blank_lines) + blank_lines = 0 + add_line(line) + if blank_lines: + new_lines.extend([Text("", style=style)] * blank_lines) + + new_text = text.blank_copy("\n").join(new_lines) + return new_text + + +if __name__ == "__main__": # pragma: no cover + from pip._vendor.rich.console import Console + + text = Text( + """\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n""" + ) + text.highlight_words(["Lorem"], "bold") + text.highlight_words(["ipsum"], "italic") + + console = Console() + + console.rule("justify='left'") + console.print(text, style="red") + console.print() + + console.rule("justify='center'") + console.print(text, style="green", justify="center") + console.print() + + console.rule("justify='right'") + console.print(text, style="blue", justify="right") + console.print() + + console.rule("justify='full'") + console.print(text, style="magenta", justify="full") + console.print() diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/theme.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/theme.py new file mode 100644 index 0000000..471dfb2 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/theme.py @@ -0,0 +1,115 @@ +import configparser +from typing import Dict, List, IO, Mapping, Optional + +from .default_styles import DEFAULT_STYLES +from .style import Style, StyleType + + +class Theme: + """A container for style information, used by :class:`~rich.console.Console`. + + Args: + styles (Dict[str, Style], optional): A mapping of style names on to styles. Defaults to None for a theme with no styles. + inherit (bool, optional): Inherit default styles. Defaults to True. + """ + + styles: Dict[str, Style] + + def __init__( + self, styles: Optional[Mapping[str, StyleType]] = None, inherit: bool = True + ): + self.styles = DEFAULT_STYLES.copy() if inherit else {} + if styles is not None: + self.styles.update( + { + name: style if isinstance(style, Style) else Style.parse(style) + for name, style in styles.items() + } + ) + + @property + def config(self) -> str: + """Get contents of a config file for this theme.""" + config = "[styles]\n" + "\n".join( + f"{name} = {style}" for name, style in sorted(self.styles.items()) + ) + return config + + @classmethod + def from_file( + cls, config_file: IO[str], source: Optional[str] = None, inherit: bool = True + ) -> "Theme": + """Load a theme from a text mode file. + + Args: + config_file (IO[str]): An open conf file. + source (str, optional): The filename of the open file. Defaults to None. + inherit (bool, optional): Inherit default styles. Defaults to True. + + Returns: + Theme: A New theme instance. + """ + config = configparser.ConfigParser() + config.read_file(config_file, source=source) + styles = {name: Style.parse(value) for name, value in config.items("styles")} + theme = Theme(styles, inherit=inherit) + return theme + + @classmethod + def read( + cls, path: str, inherit: bool = True, encoding: Optional[str] = None + ) -> "Theme": + """Read a theme from a path. + + Args: + path (str): Path to a config file readable by Python configparser module. + inherit (bool, optional): Inherit default styles. Defaults to True. + encoding (str, optional): Encoding of the config file. Defaults to None. + + Returns: + Theme: A new theme instance. + """ + with open(path, "rt", encoding=encoding) as config_file: + return cls.from_file(config_file, source=path, inherit=inherit) + + +class ThemeStackError(Exception): + """Base exception for errors related to the theme stack.""" + + +class ThemeStack: + """A stack of themes. + + Args: + theme (Theme): A theme instance + """ + + def __init__(self, theme: Theme) -> None: + self._entries: List[Dict[str, Style]] = [theme.styles] + self.get = self._entries[-1].get + + def push_theme(self, theme: Theme, inherit: bool = True) -> None: + """Push a theme on the top of the stack. + + Args: + theme (Theme): A Theme instance. + inherit (boolean, optional): Inherit styles from current top of stack. + """ + styles: Dict[str, Style] + styles = ( + {**self._entries[-1], **theme.styles} if inherit else theme.styles.copy() + ) + self._entries.append(styles) + self.get = self._entries[-1].get + + def pop_theme(self) -> None: + """Pop (and discard) the top-most theme.""" + if len(self._entries) == 1: + raise ThemeStackError("Unable to pop base theme") + self._entries.pop() + self.get = self._entries[-1].get + + +if __name__ == "__main__": # pragma: no cover + theme = Theme() + print(theme.config) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/themes.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/themes.py new file mode 100644 index 0000000..bf6db10 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/themes.py @@ -0,0 +1,5 @@ +from .default_styles import DEFAULT_STYLES +from .theme import Theme + + +DEFAULT = Theme(DEFAULT_STYLES) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/traceback.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/traceback.py new file mode 100644 index 0000000..f223ad4 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/traceback.py @@ -0,0 +1,753 @@ +from __future__ import absolute_import + +import linecache +import os +import platform +import sys +from dataclasses import dataclass, field +from traceback import walk_tb +from types import ModuleType, TracebackType +from typing import ( + Any, + Callable, + Dict, + Iterable, + List, + Optional, + Sequence, + Tuple, + Type, + Union, +) + +from pip._vendor.pygments.lexers import guess_lexer_for_filename +from pip._vendor.pygments.token import Comment, Keyword, Name, Number, Operator, String +from pip._vendor.pygments.token import Text as TextToken +from pip._vendor.pygments.token import Token +from pip._vendor.pygments.util import ClassNotFound + +from . import pretty +from ._loop import loop_last +from .columns import Columns +from .console import Console, ConsoleOptions, ConsoleRenderable, RenderResult, group +from .constrain import Constrain +from .highlighter import RegexHighlighter, ReprHighlighter +from .panel import Panel +from .scope import render_scope +from .style import Style +from .syntax import Syntax +from .text import Text +from .theme import Theme + +WINDOWS = platform.system() == "Windows" + +LOCALS_MAX_LENGTH = 10 +LOCALS_MAX_STRING = 80 + + +def install( + *, + console: Optional[Console] = None, + width: Optional[int] = 100, + extra_lines: int = 3, + theme: Optional[str] = None, + word_wrap: bool = False, + show_locals: bool = False, + locals_max_length: int = LOCALS_MAX_LENGTH, + locals_max_string: int = LOCALS_MAX_STRING, + locals_hide_dunder: bool = True, + locals_hide_sunder: Optional[bool] = None, + indent_guides: bool = True, + suppress: Iterable[Union[str, ModuleType]] = (), + max_frames: int = 100, +) -> Callable[[Type[BaseException], BaseException, Optional[TracebackType]], Any]: + """Install a rich traceback handler. + + Once installed, any tracebacks will be printed with syntax highlighting and rich formatting. + + + Args: + console (Optional[Console], optional): Console to write exception to. Default uses internal Console instance. + width (Optional[int], optional): Width (in characters) of traceback. Defaults to 100. + extra_lines (int, optional): Extra lines of code. Defaults to 3. + theme (Optional[str], optional): Pygments theme to use in traceback. Defaults to ``None`` which will pick + a theme appropriate for the platform. + word_wrap (bool, optional): Enable word wrapping of long lines. Defaults to False. + show_locals (bool, optional): Enable display of local variables. Defaults to False. + locals_max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation. + Defaults to 10. + locals_max_string (int, optional): Maximum length of string before truncating, or None to disable. Defaults to 80. + locals_hide_dunder (bool, optional): Hide locals prefixed with double underscore. Defaults to True. + locals_hide_sunder (bool, optional): Hide locals prefixed with single underscore. Defaults to False. + indent_guides (bool, optional): Enable indent guides in code and locals. Defaults to True. + suppress (Sequence[Union[str, ModuleType]]): Optional sequence of modules or paths to exclude from traceback. + + Returns: + Callable: The previous exception handler that was replaced. + + """ + traceback_console = Console(stderr=True) if console is None else console + + locals_hide_sunder = ( + True + if (traceback_console.is_jupyter and locals_hide_sunder is None) + else locals_hide_sunder + ) + + def excepthook( + type_: Type[BaseException], + value: BaseException, + traceback: Optional[TracebackType], + ) -> None: + traceback_console.print( + Traceback.from_exception( + type_, + value, + traceback, + width=width, + extra_lines=extra_lines, + theme=theme, + word_wrap=word_wrap, + show_locals=show_locals, + locals_max_length=locals_max_length, + locals_max_string=locals_max_string, + locals_hide_dunder=locals_hide_dunder, + locals_hide_sunder=bool(locals_hide_sunder), + indent_guides=indent_guides, + suppress=suppress, + max_frames=max_frames, + ) + ) + + def ipy_excepthook_closure(ip: Any) -> None: # pragma: no cover + tb_data = {} # store information about showtraceback call + default_showtraceback = ip.showtraceback # keep reference of default traceback + + def ipy_show_traceback(*args: Any, **kwargs: Any) -> None: + """wrap the default ip.showtraceback to store info for ip._showtraceback""" + nonlocal tb_data + tb_data = kwargs + default_showtraceback(*args, **kwargs) + + def ipy_display_traceback( + *args: Any, is_syntax: bool = False, **kwargs: Any + ) -> None: + """Internally called traceback from ip._showtraceback""" + nonlocal tb_data + exc_tuple = ip._get_exc_info() + + # do not display trace on syntax error + tb: Optional[TracebackType] = None if is_syntax else exc_tuple[2] + + # determine correct tb_offset + compiled = tb_data.get("running_compiled_code", False) + tb_offset = tb_data.get("tb_offset", 1 if compiled else 0) + # remove ipython internal frames from trace with tb_offset + for _ in range(tb_offset): + if tb is None: + break + tb = tb.tb_next + + excepthook(exc_tuple[0], exc_tuple[1], tb) + tb_data = {} # clear data upon usage + + # replace _showtraceback instead of showtraceback to allow ipython features such as debugging to work + # this is also what the ipython docs recommends to modify when subclassing InteractiveShell + ip._showtraceback = ipy_display_traceback + # add wrapper to capture tb_data + ip.showtraceback = ipy_show_traceback + ip.showsyntaxerror = lambda *args, **kwargs: ipy_display_traceback( + *args, is_syntax=True, **kwargs + ) + + try: # pragma: no cover + # if within ipython, use customized traceback + ip = get_ipython() # type: ignore[name-defined] + ipy_excepthook_closure(ip) + return sys.excepthook + except Exception: + # otherwise use default system hook + old_excepthook = sys.excepthook + sys.excepthook = excepthook + return old_excepthook + + +@dataclass +class Frame: + filename: str + lineno: int + name: str + line: str = "" + locals: Optional[Dict[str, pretty.Node]] = None + + +@dataclass +class _SyntaxError: + offset: int + filename: str + line: str + lineno: int + msg: str + + +@dataclass +class Stack: + exc_type: str + exc_value: str + syntax_error: Optional[_SyntaxError] = None + is_cause: bool = False + frames: List[Frame] = field(default_factory=list) + + +@dataclass +class Trace: + stacks: List[Stack] + + +class PathHighlighter(RegexHighlighter): + highlights = [r"(?P.*/)(?P.+)"] + + +class Traceback: + """A Console renderable that renders a traceback. + + Args: + trace (Trace, optional): A `Trace` object produced from `extract`. Defaults to None, which uses + the last exception. + width (Optional[int], optional): Number of characters used to traceback. Defaults to 100. + extra_lines (int, optional): Additional lines of code to render. Defaults to 3. + theme (str, optional): Override pygments theme used in traceback. + word_wrap (bool, optional): Enable word wrapping of long lines. Defaults to False. + show_locals (bool, optional): Enable display of local variables. Defaults to False. + indent_guides (bool, optional): Enable indent guides in code and locals. Defaults to True. + locals_max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation. + Defaults to 10. + locals_max_string (int, optional): Maximum length of string before truncating, or None to disable. Defaults to 80. + locals_hide_dunder (bool, optional): Hide locals prefixed with double underscore. Defaults to True. + locals_hide_sunder (bool, optional): Hide locals prefixed with single underscore. Defaults to False. + suppress (Sequence[Union[str, ModuleType]]): Optional sequence of modules or paths to exclude from traceback. + max_frames (int): Maximum number of frames to show in a traceback, 0 for no maximum. Defaults to 100. + + """ + + LEXERS = { + "": "text", + ".py": "python", + ".pxd": "cython", + ".pyx": "cython", + ".pxi": "pyrex", + } + + def __init__( + self, + trace: Optional[Trace] = None, + *, + width: Optional[int] = 100, + extra_lines: int = 3, + theme: Optional[str] = None, + word_wrap: bool = False, + show_locals: bool = False, + locals_max_length: int = LOCALS_MAX_LENGTH, + locals_max_string: int = LOCALS_MAX_STRING, + locals_hide_dunder: bool = True, + locals_hide_sunder: bool = False, + indent_guides: bool = True, + suppress: Iterable[Union[str, ModuleType]] = (), + max_frames: int = 100, + ): + if trace is None: + exc_type, exc_value, traceback = sys.exc_info() + if exc_type is None or exc_value is None or traceback is None: + raise ValueError( + "Value for 'trace' required if not called in except: block" + ) + trace = self.extract( + exc_type, exc_value, traceback, show_locals=show_locals + ) + self.trace = trace + self.width = width + self.extra_lines = extra_lines + self.theme = Syntax.get_theme(theme or "ansi_dark") + self.word_wrap = word_wrap + self.show_locals = show_locals + self.indent_guides = indent_guides + self.locals_max_length = locals_max_length + self.locals_max_string = locals_max_string + self.locals_hide_dunder = locals_hide_dunder + self.locals_hide_sunder = locals_hide_sunder + + self.suppress: Sequence[str] = [] + for suppress_entity in suppress: + if not isinstance(suppress_entity, str): + assert ( + suppress_entity.__file__ is not None + ), f"{suppress_entity!r} must be a module with '__file__' attribute" + path = os.path.dirname(suppress_entity.__file__) + else: + path = suppress_entity + path = os.path.normpath(os.path.abspath(path)) + self.suppress.append(path) + self.max_frames = max(4, max_frames) if max_frames > 0 else 0 + + @classmethod + def from_exception( + cls, + exc_type: Type[Any], + exc_value: BaseException, + traceback: Optional[TracebackType], + *, + width: Optional[int] = 100, + extra_lines: int = 3, + theme: Optional[str] = None, + word_wrap: bool = False, + show_locals: bool = False, + locals_max_length: int = LOCALS_MAX_LENGTH, + locals_max_string: int = LOCALS_MAX_STRING, + locals_hide_dunder: bool = True, + locals_hide_sunder: bool = False, + indent_guides: bool = True, + suppress: Iterable[Union[str, ModuleType]] = (), + max_frames: int = 100, + ) -> "Traceback": + """Create a traceback from exception info + + Args: + exc_type (Type[BaseException]): Exception type. + exc_value (BaseException): Exception value. + traceback (TracebackType): Python Traceback object. + width (Optional[int], optional): Number of characters used to traceback. Defaults to 100. + extra_lines (int, optional): Additional lines of code to render. Defaults to 3. + theme (str, optional): Override pygments theme used in traceback. + word_wrap (bool, optional): Enable word wrapping of long lines. Defaults to False. + show_locals (bool, optional): Enable display of local variables. Defaults to False. + indent_guides (bool, optional): Enable indent guides in code and locals. Defaults to True. + locals_max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation. + Defaults to 10. + locals_max_string (int, optional): Maximum length of string before truncating, or None to disable. Defaults to 80. + locals_hide_dunder (bool, optional): Hide locals prefixed with double underscore. Defaults to True. + locals_hide_sunder (bool, optional): Hide locals prefixed with single underscore. Defaults to False. + suppress (Iterable[Union[str, ModuleType]]): Optional sequence of modules or paths to exclude from traceback. + max_frames (int): Maximum number of frames to show in a traceback, 0 for no maximum. Defaults to 100. + + Returns: + Traceback: A Traceback instance that may be printed. + """ + rich_traceback = cls.extract( + exc_type, + exc_value, + traceback, + show_locals=show_locals, + locals_max_length=locals_max_length, + locals_max_string=locals_max_string, + locals_hide_dunder=locals_hide_dunder, + locals_hide_sunder=locals_hide_sunder, + ) + + return cls( + rich_traceback, + width=width, + extra_lines=extra_lines, + theme=theme, + word_wrap=word_wrap, + show_locals=show_locals, + indent_guides=indent_guides, + locals_max_length=locals_max_length, + locals_max_string=locals_max_string, + locals_hide_dunder=locals_hide_dunder, + locals_hide_sunder=locals_hide_sunder, + suppress=suppress, + max_frames=max_frames, + ) + + @classmethod + def extract( + cls, + exc_type: Type[BaseException], + exc_value: BaseException, + traceback: Optional[TracebackType], + *, + show_locals: bool = False, + locals_max_length: int = LOCALS_MAX_LENGTH, + locals_max_string: int = LOCALS_MAX_STRING, + locals_hide_dunder: bool = True, + locals_hide_sunder: bool = False, + ) -> Trace: + """Extract traceback information. + + Args: + exc_type (Type[BaseException]): Exception type. + exc_value (BaseException): Exception value. + traceback (TracebackType): Python Traceback object. + show_locals (bool, optional): Enable display of local variables. Defaults to False. + locals_max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation. + Defaults to 10. + locals_max_string (int, optional): Maximum length of string before truncating, or None to disable. Defaults to 80. + locals_hide_dunder (bool, optional): Hide locals prefixed with double underscore. Defaults to True. + locals_hide_sunder (bool, optional): Hide locals prefixed with single underscore. Defaults to False. + + Returns: + Trace: A Trace instance which you can use to construct a `Traceback`. + """ + + stacks: List[Stack] = [] + is_cause = False + + from pip._vendor.rich import _IMPORT_CWD + + def safe_str(_object: Any) -> str: + """Don't allow exceptions from __str__ to propagate.""" + try: + return str(_object) + except Exception: + return "" + + while True: + stack = Stack( + exc_type=safe_str(exc_type.__name__), + exc_value=safe_str(exc_value), + is_cause=is_cause, + ) + + if isinstance(exc_value, SyntaxError): + stack.syntax_error = _SyntaxError( + offset=exc_value.offset or 0, + filename=exc_value.filename or "?", + lineno=exc_value.lineno or 0, + line=exc_value.text or "", + msg=exc_value.msg, + ) + + stacks.append(stack) + append = stack.frames.append + + def get_locals( + iter_locals: Iterable[Tuple[str, object]] + ) -> Iterable[Tuple[str, object]]: + """Extract locals from an iterator of key pairs.""" + if not (locals_hide_dunder or locals_hide_sunder): + yield from iter_locals + return + for key, value in iter_locals: + if locals_hide_dunder and key.startswith("__"): + continue + if locals_hide_sunder and key.startswith("_"): + continue + yield key, value + + for frame_summary, line_no in walk_tb(traceback): + filename = frame_summary.f_code.co_filename + if filename and not filename.startswith("<"): + if not os.path.isabs(filename): + filename = os.path.join(_IMPORT_CWD, filename) + if frame_summary.f_locals.get("_rich_traceback_omit", False): + continue + + frame = Frame( + filename=filename or "?", + lineno=line_no, + name=frame_summary.f_code.co_name, + locals={ + key: pretty.traverse( + value, + max_length=locals_max_length, + max_string=locals_max_string, + ) + for key, value in get_locals(frame_summary.f_locals.items()) + } + if show_locals + else None, + ) + append(frame) + if frame_summary.f_locals.get("_rich_traceback_guard", False): + del stack.frames[:] + + cause = getattr(exc_value, "__cause__", None) + if cause: + exc_type = cause.__class__ + exc_value = cause + # __traceback__ can be None, e.g. for exceptions raised by the + # 'multiprocessing' module + traceback = cause.__traceback__ + is_cause = True + continue + + cause = exc_value.__context__ + if cause and not getattr(exc_value, "__suppress_context__", False): + exc_type = cause.__class__ + exc_value = cause + traceback = cause.__traceback__ + is_cause = False + continue + # No cover, code is reached but coverage doesn't recognize it. + break # pragma: no cover + + trace = Trace(stacks=stacks) + return trace + + def __rich_console__( + self, console: Console, options: ConsoleOptions + ) -> RenderResult: + theme = self.theme + background_style = theme.get_background_style() + token_style = theme.get_style_for_token + + traceback_theme = Theme( + { + "pretty": token_style(TextToken), + "pygments.text": token_style(Token), + "pygments.string": token_style(String), + "pygments.function": token_style(Name.Function), + "pygments.number": token_style(Number), + "repr.indent": token_style(Comment) + Style(dim=True), + "repr.str": token_style(String), + "repr.brace": token_style(TextToken) + Style(bold=True), + "repr.number": token_style(Number), + "repr.bool_true": token_style(Keyword.Constant), + "repr.bool_false": token_style(Keyword.Constant), + "repr.none": token_style(Keyword.Constant), + "scope.border": token_style(String.Delimiter), + "scope.equals": token_style(Operator), + "scope.key": token_style(Name), + "scope.key.special": token_style(Name.Constant) + Style(dim=True), + }, + inherit=False, + ) + + highlighter = ReprHighlighter() + for last, stack in loop_last(reversed(self.trace.stacks)): + if stack.frames: + stack_renderable: ConsoleRenderable = Panel( + self._render_stack(stack), + title="[traceback.title]Traceback [dim](most recent call last)", + style=background_style, + border_style="traceback.border", + expand=True, + padding=(0, 1), + ) + stack_renderable = Constrain(stack_renderable, self.width) + with console.use_theme(traceback_theme): + yield stack_renderable + if stack.syntax_error is not None: + with console.use_theme(traceback_theme): + yield Constrain( + Panel( + self._render_syntax_error(stack.syntax_error), + style=background_style, + border_style="traceback.border.syntax_error", + expand=True, + padding=(0, 1), + width=self.width, + ), + self.width, + ) + yield Text.assemble( + (f"{stack.exc_type}: ", "traceback.exc_type"), + highlighter(stack.syntax_error.msg), + ) + elif stack.exc_value: + yield Text.assemble( + (f"{stack.exc_type}: ", "traceback.exc_type"), + highlighter(stack.exc_value), + ) + else: + yield Text.assemble((f"{stack.exc_type}", "traceback.exc_type")) + + if not last: + if stack.is_cause: + yield Text.from_markup( + "\n[i]The above exception was the direct cause of the following exception:\n", + ) + else: + yield Text.from_markup( + "\n[i]During handling of the above exception, another exception occurred:\n", + ) + + @group() + def _render_syntax_error(self, syntax_error: _SyntaxError) -> RenderResult: + highlighter = ReprHighlighter() + path_highlighter = PathHighlighter() + if syntax_error.filename != "": + if os.path.exists(syntax_error.filename): + text = Text.assemble( + (f" {syntax_error.filename}", "pygments.string"), + (":", "pygments.text"), + (str(syntax_error.lineno), "pygments.number"), + style="pygments.text", + ) + yield path_highlighter(text) + syntax_error_text = highlighter(syntax_error.line.rstrip()) + syntax_error_text.no_wrap = True + offset = min(syntax_error.offset - 1, len(syntax_error_text)) + syntax_error_text.stylize("bold underline", offset, offset) + syntax_error_text += Text.from_markup( + "\n" + " " * offset + "[traceback.offset]▲[/]", + style="pygments.text", + ) + yield syntax_error_text + + @classmethod + def _guess_lexer(cls, filename: str, code: str) -> str: + ext = os.path.splitext(filename)[-1] + if not ext: + # No extension, look at first line to see if it is a hashbang + # Note, this is an educated guess and not a guarantee + # If it fails, the only downside is that the code is highlighted strangely + new_line_index = code.index("\n") + first_line = code[:new_line_index] if new_line_index != -1 else code + if first_line.startswith("#!") and "python" in first_line.lower(): + return "python" + try: + return cls.LEXERS.get(ext) or guess_lexer_for_filename(filename, code).name + except ClassNotFound: + return "text" + + @group() + def _render_stack(self, stack: Stack) -> RenderResult: + path_highlighter = PathHighlighter() + theme = self.theme + + def read_code(filename: str) -> str: + """Read files, and cache results on filename. + + Args: + filename (str): Filename to read + + Returns: + str: Contents of file + """ + return "".join(linecache.getlines(filename)) + + def render_locals(frame: Frame) -> Iterable[ConsoleRenderable]: + if frame.locals: + yield render_scope( + frame.locals, + title="locals", + indent_guides=self.indent_guides, + max_length=self.locals_max_length, + max_string=self.locals_max_string, + ) + + exclude_frames: Optional[range] = None + if self.max_frames != 0: + exclude_frames = range( + self.max_frames // 2, + len(stack.frames) - self.max_frames // 2, + ) + + excluded = False + for frame_index, frame in enumerate(stack.frames): + if exclude_frames and frame_index in exclude_frames: + excluded = True + continue + + if excluded: + assert exclude_frames is not None + yield Text( + f"\n... {len(exclude_frames)} frames hidden ...", + justify="center", + style="traceback.error", + ) + excluded = False + + first = frame_index == 0 + frame_filename = frame.filename + suppressed = any(frame_filename.startswith(path) for path in self.suppress) + + if os.path.exists(frame.filename): + text = Text.assemble( + path_highlighter(Text(frame.filename, style="pygments.string")), + (":", "pygments.text"), + (str(frame.lineno), "pygments.number"), + " in ", + (frame.name, "pygments.function"), + style="pygments.text", + ) + else: + text = Text.assemble( + "in ", + (frame.name, "pygments.function"), + (":", "pygments.text"), + (str(frame.lineno), "pygments.number"), + style="pygments.text", + ) + if not frame.filename.startswith("<") and not first: + yield "" + yield text + if frame.filename.startswith("<"): + yield from render_locals(frame) + continue + if not suppressed: + try: + code = read_code(frame.filename) + if not code: + # code may be an empty string if the file doesn't exist, OR + # if the traceback filename is generated dynamically + continue + lexer_name = self._guess_lexer(frame.filename, code) + syntax = Syntax( + code, + lexer_name, + theme=theme, + line_numbers=True, + line_range=( + frame.lineno - self.extra_lines, + frame.lineno + self.extra_lines, + ), + highlight_lines={frame.lineno}, + word_wrap=self.word_wrap, + code_width=88, + indent_guides=self.indent_guides, + dedent=False, + ) + yield "" + except Exception as error: + yield Text.assemble( + (f"\n{error}", "traceback.error"), + ) + else: + yield ( + Columns( + [ + syntax, + *render_locals(frame), + ], + padding=1, + ) + if frame.locals + else syntax + ) + + +if __name__ == "__main__": # pragma: no cover + from .console import Console + + console = Console() + import sys + + def bar(a: Any) -> None: # 这是对亚洲语言支持的测试。面对模棱两可的想法,拒绝猜测的诱惑 + one = 1 + print(one / a) + + def foo(a: Any) -> None: + _rich_traceback_guard = True + zed = { + "characters": { + "Paul Atreides", + "Vladimir Harkonnen", + "Thufir Hawat", + "Duncan Idaho", + }, + "atomic_types": (None, False, True), + } + bar(a) + + def error() -> None: + try: + try: + foo(0) + except: + slfkjsldkfj # type: ignore[name-defined] + except: + console.print_exception(show_locals=True) + + error() diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/rich/tree.py b/backend/.venv/Lib/site-packages/pip/_vendor/rich/tree.py new file mode 100644 index 0000000..64bc75d --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/rich/tree.py @@ -0,0 +1,249 @@ +from typing import Iterator, List, Optional, Tuple + +from ._loop import loop_first, loop_last +from .console import Console, ConsoleOptions, RenderableType, RenderResult +from .jupyter import JupyterMixin +from .measure import Measurement +from .segment import Segment +from .style import Style, StyleStack, StyleType +from .styled import Styled + + +class Tree(JupyterMixin): + """A renderable for a tree structure. + + Args: + label (RenderableType): The renderable or str for the tree label. + style (StyleType, optional): Style of this tree. Defaults to "tree". + guide_style (StyleType, optional): Style of the guide lines. Defaults to "tree.line". + expanded (bool, optional): Also display children. Defaults to True. + highlight (bool, optional): Highlight renderable (if str). Defaults to False. + """ + + def __init__( + self, + label: RenderableType, + *, + style: StyleType = "tree", + guide_style: StyleType = "tree.line", + expanded: bool = True, + highlight: bool = False, + hide_root: bool = False, + ) -> None: + self.label = label + self.style = style + self.guide_style = guide_style + self.children: List[Tree] = [] + self.expanded = expanded + self.highlight = highlight + self.hide_root = hide_root + + def add( + self, + label: RenderableType, + *, + style: Optional[StyleType] = None, + guide_style: Optional[StyleType] = None, + expanded: bool = True, + highlight: Optional[bool] = False, + ) -> "Tree": + """Add a child tree. + + Args: + label (RenderableType): The renderable or str for the tree label. + style (StyleType, optional): Style of this tree. Defaults to "tree". + guide_style (StyleType, optional): Style of the guide lines. Defaults to "tree.line". + expanded (bool, optional): Also display children. Defaults to True. + highlight (Optional[bool], optional): Highlight renderable (if str). Defaults to False. + + Returns: + Tree: A new child Tree, which may be further modified. + """ + node = Tree( + label, + style=self.style if style is None else style, + guide_style=self.guide_style if guide_style is None else guide_style, + expanded=expanded, + highlight=self.highlight if highlight is None else highlight, + ) + self.children.append(node) + return node + + def __rich_console__( + self, console: "Console", options: "ConsoleOptions" + ) -> "RenderResult": + stack: List[Iterator[Tuple[bool, Tree]]] = [] + pop = stack.pop + push = stack.append + new_line = Segment.line() + + get_style = console.get_style + null_style = Style.null() + guide_style = get_style(self.guide_style, default="") or null_style + SPACE, CONTINUE, FORK, END = range(4) + + ASCII_GUIDES = (" ", "| ", "+-- ", "`-- ") + TREE_GUIDES = [ + (" ", "│ ", "├── ", "└── "), + (" ", "┃ ", "┣━━ ", "┗━━ "), + (" ", "║ ", "╠══ ", "╚══ "), + ] + _Segment = Segment + + def make_guide(index: int, style: Style) -> Segment: + """Make a Segment for a level of the guide lines.""" + if options.ascii_only: + line = ASCII_GUIDES[index] + else: + guide = 1 if style.bold else (2 if style.underline2 else 0) + line = TREE_GUIDES[0 if options.legacy_windows else guide][index] + return _Segment(line, style) + + levels: List[Segment] = [make_guide(CONTINUE, guide_style)] + push(iter(loop_last([self]))) + + guide_style_stack = StyleStack(get_style(self.guide_style)) + style_stack = StyleStack(get_style(self.style)) + remove_guide_styles = Style(bold=False, underline2=False) + + depth = 0 + + while stack: + stack_node = pop() + try: + last, node = next(stack_node) + except StopIteration: + levels.pop() + if levels: + guide_style = levels[-1].style or null_style + levels[-1] = make_guide(FORK, guide_style) + guide_style_stack.pop() + style_stack.pop() + continue + push(stack_node) + if last: + levels[-1] = make_guide(END, levels[-1].style or null_style) + + guide_style = guide_style_stack.current + get_style(node.guide_style) + style = style_stack.current + get_style(node.style) + prefix = levels[(2 if self.hide_root else 1) :] + renderable_lines = console.render_lines( + Styled(node.label, style), + options.update( + width=options.max_width + - sum(level.cell_length for level in prefix), + highlight=self.highlight, + height=None, + ), + pad=options.justify is not None, + ) + + if not (depth == 0 and self.hide_root): + for first, line in loop_first(renderable_lines): + if prefix: + yield from _Segment.apply_style( + prefix, + style.background_style, + post_style=remove_guide_styles, + ) + yield from line + yield new_line + if first and prefix: + prefix[-1] = make_guide( + SPACE if last else CONTINUE, prefix[-1].style or null_style + ) + + if node.expanded and node.children: + levels[-1] = make_guide( + SPACE if last else CONTINUE, levels[-1].style or null_style + ) + levels.append( + make_guide(END if len(node.children) == 1 else FORK, guide_style) + ) + style_stack.push(get_style(node.style)) + guide_style_stack.push(get_style(node.guide_style)) + push(iter(loop_last(node.children))) + depth += 1 + + def __rich_measure__( + self, console: "Console", options: "ConsoleOptions" + ) -> "Measurement": + stack: List[Iterator[Tree]] = [iter([self])] + pop = stack.pop + push = stack.append + minimum = 0 + maximum = 0 + measure = Measurement.get + level = 0 + while stack: + iter_tree = pop() + try: + tree = next(iter_tree) + except StopIteration: + level -= 1 + continue + push(iter_tree) + min_measure, max_measure = measure(console, options, tree.label) + indent = level * 4 + minimum = max(min_measure + indent, minimum) + maximum = max(max_measure + indent, maximum) + if tree.expanded and tree.children: + push(iter(tree.children)) + level += 1 + return Measurement(minimum, maximum) + + +if __name__ == "__main__": # pragma: no cover + from pip._vendor.rich.console import Group + from pip._vendor.rich.markdown import Markdown + from pip._vendor.rich.panel import Panel + from pip._vendor.rich.syntax import Syntax + from pip._vendor.rich.table import Table + + table = Table(row_styles=["", "dim"]) + + table.add_column("Released", style="cyan", no_wrap=True) + table.add_column("Title", style="magenta") + table.add_column("Box Office", justify="right", style="green") + + table.add_row("Dec 20, 2019", "Star Wars: The Rise of Skywalker", "$952,110,690") + table.add_row("May 25, 2018", "Solo: A Star Wars Story", "$393,151,347") + table.add_row("Dec 15, 2017", "Star Wars Ep. V111: The Last Jedi", "$1,332,539,889") + table.add_row("Dec 16, 2016", "Rogue One: A Star Wars Story", "$1,332,439,889") + + code = """\ +class Segment(NamedTuple): + text: str = "" + style: Optional[Style] = None + is_control: bool = False +""" + syntax = Syntax(code, "python", theme="monokai", line_numbers=True) + + markdown = Markdown( + """\ +### example.md +> Hello, World! +> +> Markdown _all_ the things +""" + ) + + root = Tree("🌲 [b green]Rich Tree", highlight=True, hide_root=True) + + node = root.add(":file_folder: Renderables", guide_style="red") + simple_node = node.add(":file_folder: [bold yellow]Atomic", guide_style="uu green") + simple_node.add(Group("📄 Syntax", syntax)) + simple_node.add(Group("📄 Markdown", Panel(markdown, border_style="green"))) + + containers_node = node.add( + ":file_folder: [bold magenta]Containers", guide_style="bold magenta" + ) + containers_node.expanded = True + panel = Panel.fit("Just a panel", border_style="red") + containers_node.add(Group("📄 Panels", panel)) + + containers_node.add(Group("📄 [b magenta]Table", table)) + + console = Console() + + console.print(root) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/tomli/__init__.py b/backend/.venv/Lib/site-packages/pip/_vendor/tomli/__init__.py new file mode 100644 index 0000000..4c6ec97 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/tomli/__init__.py @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: MIT +# SPDX-FileCopyrightText: 2021 Taneli Hukkinen +# Licensed to PSF under a Contributor Agreement. + +__all__ = ("loads", "load", "TOMLDecodeError") +__version__ = "2.0.1" # DO NOT EDIT THIS LINE MANUALLY. LET bump2version UTILITY DO IT + +from ._parser import TOMLDecodeError, load, loads + +# Pretend this exception was created here. +TOMLDecodeError.__module__ = __name__ diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..40a8593da8811272cea7aa9a4777816f4461678c GIT binary patch literal 388 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_types.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_types.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..75a8cc32f7bc50aaa1bb37c073008aee70c71f7d GIT binary patch literal 370 zcmXv|ze~eV5PmN&jcp`42!f-Nc4&)hQ9%kK_=AE@F;ddxENNfz!h2~YTf244rvHL} zi&MAqRwuVY2f;zSKs~tczT@t``#v1UCK$JmXVEX#&$9Uswjt{_l2;Ovka7}Jm&S%` z#LQ)sfC1)!0(~|PaL26x12Z%>odsKNHD`76s}!m;%`TE$S35rEexHM`Jd9Hg&AWO{ zTUnk)$v~DbrCCA+K{J&}ZFhaC;F1eJ)9e~@&7uTZSEzTg#x3&m)Ma!&xX~D-$t~T0OJ` zs+pqW(^!OK4(D dict[str, Any]: + """Parse TOML from a binary file object.""" + b = __fp.read() + try: + s = b.decode() + except AttributeError: + raise TypeError( + "File must be opened in binary mode, e.g. use `open('foo.toml', 'rb')`" + ) from None + return loads(s, parse_float=parse_float) + + +def loads(__s: str, *, parse_float: ParseFloat = float) -> dict[str, Any]: # noqa: C901 + """Parse TOML from a string.""" + + # The spec allows converting "\r\n" to "\n", even in string + # literals. Let's do so to simplify parsing. + src = __s.replace("\r\n", "\n") + pos = 0 + out = Output(NestedDict(), Flags()) + header: Key = () + parse_float = make_safe_parse_float(parse_float) + + # Parse one statement at a time + # (typically means one line in TOML source) + while True: + # 1. Skip line leading whitespace + pos = skip_chars(src, pos, TOML_WS) + + # 2. Parse rules. Expect one of the following: + # - end of file + # - end of line + # - comment + # - key/value pair + # - append dict to list (and move to its namespace) + # - create dict (and move to its namespace) + # Skip trailing whitespace when applicable. + try: + char = src[pos] + except IndexError: + break + if char == "\n": + pos += 1 + continue + if char in KEY_INITIAL_CHARS: + pos = key_value_rule(src, pos, out, header, parse_float) + pos = skip_chars(src, pos, TOML_WS) + elif char == "[": + try: + second_char: str | None = src[pos + 1] + except IndexError: + second_char = None + out.flags.finalize_pending() + if second_char == "[": + pos, header = create_list_rule(src, pos, out) + else: + pos, header = create_dict_rule(src, pos, out) + pos = skip_chars(src, pos, TOML_WS) + elif char != "#": + raise suffixed_err(src, pos, "Invalid statement") + + # 3. Skip comment + pos = skip_comment(src, pos) + + # 4. Expect end of line or end of file + try: + char = src[pos] + except IndexError: + break + if char != "\n": + raise suffixed_err( + src, pos, "Expected newline or end of document after a statement" + ) + pos += 1 + + return out.data.dict + + +class Flags: + """Flags that map to parsed keys/namespaces.""" + + # Marks an immutable namespace (inline array or inline table). + FROZEN = 0 + # Marks a nest that has been explicitly created and can no longer + # be opened using the "[table]" syntax. + EXPLICIT_NEST = 1 + + def __init__(self) -> None: + self._flags: dict[str, dict] = {} + self._pending_flags: set[tuple[Key, int]] = set() + + def add_pending(self, key: Key, flag: int) -> None: + self._pending_flags.add((key, flag)) + + def finalize_pending(self) -> None: + for key, flag in self._pending_flags: + self.set(key, flag, recursive=False) + self._pending_flags.clear() + + def unset_all(self, key: Key) -> None: + cont = self._flags + for k in key[:-1]: + if k not in cont: + return + cont = cont[k]["nested"] + cont.pop(key[-1], None) + + def set(self, key: Key, flag: int, *, recursive: bool) -> None: # noqa: A003 + cont = self._flags + key_parent, key_stem = key[:-1], key[-1] + for k in key_parent: + if k not in cont: + cont[k] = {"flags": set(), "recursive_flags": set(), "nested": {}} + cont = cont[k]["nested"] + if key_stem not in cont: + cont[key_stem] = {"flags": set(), "recursive_flags": set(), "nested": {}} + cont[key_stem]["recursive_flags" if recursive else "flags"].add(flag) + + def is_(self, key: Key, flag: int) -> bool: + if not key: + return False # document root has no flags + cont = self._flags + for k in key[:-1]: + if k not in cont: + return False + inner_cont = cont[k] + if flag in inner_cont["recursive_flags"]: + return True + cont = inner_cont["nested"] + key_stem = key[-1] + if key_stem in cont: + cont = cont[key_stem] + return flag in cont["flags"] or flag in cont["recursive_flags"] + return False + + +class NestedDict: + def __init__(self) -> None: + # The parsed content of the TOML document + self.dict: dict[str, Any] = {} + + def get_or_create_nest( + self, + key: Key, + *, + access_lists: bool = True, + ) -> dict: + cont: Any = self.dict + for k in key: + if k not in cont: + cont[k] = {} + cont = cont[k] + if access_lists and isinstance(cont, list): + cont = cont[-1] + if not isinstance(cont, dict): + raise KeyError("There is no nest behind this key") + return cont + + def append_nest_to_list(self, key: Key) -> None: + cont = self.get_or_create_nest(key[:-1]) + last_key = key[-1] + if last_key in cont: + list_ = cont[last_key] + if not isinstance(list_, list): + raise KeyError("An object other than list found behind this key") + list_.append({}) + else: + cont[last_key] = [{}] + + +class Output(NamedTuple): + data: NestedDict + flags: Flags + + +def skip_chars(src: str, pos: Pos, chars: Iterable[str]) -> Pos: + try: + while src[pos] in chars: + pos += 1 + except IndexError: + pass + return pos + + +def skip_until( + src: str, + pos: Pos, + expect: str, + *, + error_on: frozenset[str], + error_on_eof: bool, +) -> Pos: + try: + new_pos = src.index(expect, pos) + except ValueError: + new_pos = len(src) + if error_on_eof: + raise suffixed_err(src, new_pos, f"Expected {expect!r}") from None + + if not error_on.isdisjoint(src[pos:new_pos]): + while src[pos] not in error_on: + pos += 1 + raise suffixed_err(src, pos, f"Found invalid character {src[pos]!r}") + return new_pos + + +def skip_comment(src: str, pos: Pos) -> Pos: + try: + char: str | None = src[pos] + except IndexError: + char = None + if char == "#": + return skip_until( + src, pos + 1, "\n", error_on=ILLEGAL_COMMENT_CHARS, error_on_eof=False + ) + return pos + + +def skip_comments_and_array_ws(src: str, pos: Pos) -> Pos: + while True: + pos_before_skip = pos + pos = skip_chars(src, pos, TOML_WS_AND_NEWLINE) + pos = skip_comment(src, pos) + if pos == pos_before_skip: + return pos + + +def create_dict_rule(src: str, pos: Pos, out: Output) -> tuple[Pos, Key]: + pos += 1 # Skip "[" + pos = skip_chars(src, pos, TOML_WS) + pos, key = parse_key(src, pos) + + if out.flags.is_(key, Flags.EXPLICIT_NEST) or out.flags.is_(key, Flags.FROZEN): + raise suffixed_err(src, pos, f"Cannot declare {key} twice") + out.flags.set(key, Flags.EXPLICIT_NEST, recursive=False) + try: + out.data.get_or_create_nest(key) + except KeyError: + raise suffixed_err(src, pos, "Cannot overwrite a value") from None + + if not src.startswith("]", pos): + raise suffixed_err(src, pos, "Expected ']' at the end of a table declaration") + return pos + 1, key + + +def create_list_rule(src: str, pos: Pos, out: Output) -> tuple[Pos, Key]: + pos += 2 # Skip "[[" + pos = skip_chars(src, pos, TOML_WS) + pos, key = parse_key(src, pos) + + if out.flags.is_(key, Flags.FROZEN): + raise suffixed_err(src, pos, f"Cannot mutate immutable namespace {key}") + # Free the namespace now that it points to another empty list item... + out.flags.unset_all(key) + # ...but this key precisely is still prohibited from table declaration + out.flags.set(key, Flags.EXPLICIT_NEST, recursive=False) + try: + out.data.append_nest_to_list(key) + except KeyError: + raise suffixed_err(src, pos, "Cannot overwrite a value") from None + + if not src.startswith("]]", pos): + raise suffixed_err(src, pos, "Expected ']]' at the end of an array declaration") + return pos + 2, key + + +def key_value_rule( + src: str, pos: Pos, out: Output, header: Key, parse_float: ParseFloat +) -> Pos: + pos, key, value = parse_key_value_pair(src, pos, parse_float) + key_parent, key_stem = key[:-1], key[-1] + abs_key_parent = header + key_parent + + relative_path_cont_keys = (header + key[:i] for i in range(1, len(key))) + for cont_key in relative_path_cont_keys: + # Check that dotted key syntax does not redefine an existing table + if out.flags.is_(cont_key, Flags.EXPLICIT_NEST): + raise suffixed_err(src, pos, f"Cannot redefine namespace {cont_key}") + # Containers in the relative path can't be opened with the table syntax or + # dotted key/value syntax in following table sections. + out.flags.add_pending(cont_key, Flags.EXPLICIT_NEST) + + if out.flags.is_(abs_key_parent, Flags.FROZEN): + raise suffixed_err( + src, pos, f"Cannot mutate immutable namespace {abs_key_parent}" + ) + + try: + nest = out.data.get_or_create_nest(abs_key_parent) + except KeyError: + raise suffixed_err(src, pos, "Cannot overwrite a value") from None + if key_stem in nest: + raise suffixed_err(src, pos, "Cannot overwrite a value") + # Mark inline table and array namespaces recursively immutable + if isinstance(value, (dict, list)): + out.flags.set(header + key, Flags.FROZEN, recursive=True) + nest[key_stem] = value + return pos + + +def parse_key_value_pair( + src: str, pos: Pos, parse_float: ParseFloat +) -> tuple[Pos, Key, Any]: + pos, key = parse_key(src, pos) + try: + char: str | None = src[pos] + except IndexError: + char = None + if char != "=": + raise suffixed_err(src, pos, "Expected '=' after a key in a key/value pair") + pos += 1 + pos = skip_chars(src, pos, TOML_WS) + pos, value = parse_value(src, pos, parse_float) + return pos, key, value + + +def parse_key(src: str, pos: Pos) -> tuple[Pos, Key]: + pos, key_part = parse_key_part(src, pos) + key: Key = (key_part,) + pos = skip_chars(src, pos, TOML_WS) + while True: + try: + char: str | None = src[pos] + except IndexError: + char = None + if char != ".": + return pos, key + pos += 1 + pos = skip_chars(src, pos, TOML_WS) + pos, key_part = parse_key_part(src, pos) + key += (key_part,) + pos = skip_chars(src, pos, TOML_WS) + + +def parse_key_part(src: str, pos: Pos) -> tuple[Pos, str]: + try: + char: str | None = src[pos] + except IndexError: + char = None + if char in BARE_KEY_CHARS: + start_pos = pos + pos = skip_chars(src, pos, BARE_KEY_CHARS) + return pos, src[start_pos:pos] + if char == "'": + return parse_literal_str(src, pos) + if char == '"': + return parse_one_line_basic_str(src, pos) + raise suffixed_err(src, pos, "Invalid initial character for a key part") + + +def parse_one_line_basic_str(src: str, pos: Pos) -> tuple[Pos, str]: + pos += 1 + return parse_basic_str(src, pos, multiline=False) + + +def parse_array(src: str, pos: Pos, parse_float: ParseFloat) -> tuple[Pos, list]: + pos += 1 + array: list = [] + + pos = skip_comments_and_array_ws(src, pos) + if src.startswith("]", pos): + return pos + 1, array + while True: + pos, val = parse_value(src, pos, parse_float) + array.append(val) + pos = skip_comments_and_array_ws(src, pos) + + c = src[pos : pos + 1] + if c == "]": + return pos + 1, array + if c != ",": + raise suffixed_err(src, pos, "Unclosed array") + pos += 1 + + pos = skip_comments_and_array_ws(src, pos) + if src.startswith("]", pos): + return pos + 1, array + + +def parse_inline_table(src: str, pos: Pos, parse_float: ParseFloat) -> tuple[Pos, dict]: + pos += 1 + nested_dict = NestedDict() + flags = Flags() + + pos = skip_chars(src, pos, TOML_WS) + if src.startswith("}", pos): + return pos + 1, nested_dict.dict + while True: + pos, key, value = parse_key_value_pair(src, pos, parse_float) + key_parent, key_stem = key[:-1], key[-1] + if flags.is_(key, Flags.FROZEN): + raise suffixed_err(src, pos, f"Cannot mutate immutable namespace {key}") + try: + nest = nested_dict.get_or_create_nest(key_parent, access_lists=False) + except KeyError: + raise suffixed_err(src, pos, "Cannot overwrite a value") from None + if key_stem in nest: + raise suffixed_err(src, pos, f"Duplicate inline table key {key_stem!r}") + nest[key_stem] = value + pos = skip_chars(src, pos, TOML_WS) + c = src[pos : pos + 1] + if c == "}": + return pos + 1, nested_dict.dict + if c != ",": + raise suffixed_err(src, pos, "Unclosed inline table") + if isinstance(value, (dict, list)): + flags.set(key, Flags.FROZEN, recursive=True) + pos += 1 + pos = skip_chars(src, pos, TOML_WS) + + +def parse_basic_str_escape( + src: str, pos: Pos, *, multiline: bool = False +) -> tuple[Pos, str]: + escape_id = src[pos : pos + 2] + pos += 2 + if multiline and escape_id in {"\\ ", "\\\t", "\\\n"}: + # Skip whitespace until next non-whitespace character or end of + # the doc. Error if non-whitespace is found before newline. + if escape_id != "\\\n": + pos = skip_chars(src, pos, TOML_WS) + try: + char = src[pos] + except IndexError: + return pos, "" + if char != "\n": + raise suffixed_err(src, pos, "Unescaped '\\' in a string") + pos += 1 + pos = skip_chars(src, pos, TOML_WS_AND_NEWLINE) + return pos, "" + if escape_id == "\\u": + return parse_hex_char(src, pos, 4) + if escape_id == "\\U": + return parse_hex_char(src, pos, 8) + try: + return pos, BASIC_STR_ESCAPE_REPLACEMENTS[escape_id] + except KeyError: + raise suffixed_err(src, pos, "Unescaped '\\' in a string") from None + + +def parse_basic_str_escape_multiline(src: str, pos: Pos) -> tuple[Pos, str]: + return parse_basic_str_escape(src, pos, multiline=True) + + +def parse_hex_char(src: str, pos: Pos, hex_len: int) -> tuple[Pos, str]: + hex_str = src[pos : pos + hex_len] + if len(hex_str) != hex_len or not HEXDIGIT_CHARS.issuperset(hex_str): + raise suffixed_err(src, pos, "Invalid hex value") + pos += hex_len + hex_int = int(hex_str, 16) + if not is_unicode_scalar_value(hex_int): + raise suffixed_err(src, pos, "Escaped character is not a Unicode scalar value") + return pos, chr(hex_int) + + +def parse_literal_str(src: str, pos: Pos) -> tuple[Pos, str]: + pos += 1 # Skip starting apostrophe + start_pos = pos + pos = skip_until( + src, pos, "'", error_on=ILLEGAL_LITERAL_STR_CHARS, error_on_eof=True + ) + return pos + 1, src[start_pos:pos] # Skip ending apostrophe + + +def parse_multiline_str(src: str, pos: Pos, *, literal: bool) -> tuple[Pos, str]: + pos += 3 + if src.startswith("\n", pos): + pos += 1 + + if literal: + delim = "'" + end_pos = skip_until( + src, + pos, + "'''", + error_on=ILLEGAL_MULTILINE_LITERAL_STR_CHARS, + error_on_eof=True, + ) + result = src[pos:end_pos] + pos = end_pos + 3 + else: + delim = '"' + pos, result = parse_basic_str(src, pos, multiline=True) + + # Add at maximum two extra apostrophes/quotes if the end sequence + # is 4 or 5 chars long instead of just 3. + if not src.startswith(delim, pos): + return pos, result + pos += 1 + if not src.startswith(delim, pos): + return pos, result + delim + pos += 1 + return pos, result + (delim * 2) + + +def parse_basic_str(src: str, pos: Pos, *, multiline: bool) -> tuple[Pos, str]: + if multiline: + error_on = ILLEGAL_MULTILINE_BASIC_STR_CHARS + parse_escapes = parse_basic_str_escape_multiline + else: + error_on = ILLEGAL_BASIC_STR_CHARS + parse_escapes = parse_basic_str_escape + result = "" + start_pos = pos + while True: + try: + char = src[pos] + except IndexError: + raise suffixed_err(src, pos, "Unterminated string") from None + if char == '"': + if not multiline: + return pos + 1, result + src[start_pos:pos] + if src.startswith('"""', pos): + return pos + 3, result + src[start_pos:pos] + pos += 1 + continue + if char == "\\": + result += src[start_pos:pos] + pos, parsed_escape = parse_escapes(src, pos) + result += parsed_escape + start_pos = pos + continue + if char in error_on: + raise suffixed_err(src, pos, f"Illegal character {char!r}") + pos += 1 + + +def parse_value( # noqa: C901 + src: str, pos: Pos, parse_float: ParseFloat +) -> tuple[Pos, Any]: + try: + char: str | None = src[pos] + except IndexError: + char = None + + # IMPORTANT: order conditions based on speed of checking and likelihood + + # Basic strings + if char == '"': + if src.startswith('"""', pos): + return parse_multiline_str(src, pos, literal=False) + return parse_one_line_basic_str(src, pos) + + # Literal strings + if char == "'": + if src.startswith("'''", pos): + return parse_multiline_str(src, pos, literal=True) + return parse_literal_str(src, pos) + + # Booleans + if char == "t": + if src.startswith("true", pos): + return pos + 4, True + if char == "f": + if src.startswith("false", pos): + return pos + 5, False + + # Arrays + if char == "[": + return parse_array(src, pos, parse_float) + + # Inline tables + if char == "{": + return parse_inline_table(src, pos, parse_float) + + # Dates and times + datetime_match = RE_DATETIME.match(src, pos) + if datetime_match: + try: + datetime_obj = match_to_datetime(datetime_match) + except ValueError as e: + raise suffixed_err(src, pos, "Invalid date or datetime") from e + return datetime_match.end(), datetime_obj + localtime_match = RE_LOCALTIME.match(src, pos) + if localtime_match: + return localtime_match.end(), match_to_localtime(localtime_match) + + # Integers and "normal" floats. + # The regex will greedily match any type starting with a decimal + # char, so needs to be located after handling of dates and times. + number_match = RE_NUMBER.match(src, pos) + if number_match: + return number_match.end(), match_to_number(number_match, parse_float) + + # Special floats + first_three = src[pos : pos + 3] + if first_three in {"inf", "nan"}: + return pos + 3, parse_float(first_three) + first_four = src[pos : pos + 4] + if first_four in {"-inf", "+inf", "-nan", "+nan"}: + return pos + 4, parse_float(first_four) + + raise suffixed_err(src, pos, "Invalid value") + + +def suffixed_err(src: str, pos: Pos, msg: str) -> TOMLDecodeError: + """Return a `TOMLDecodeError` where error message is suffixed with + coordinates in source.""" + + def coord_repr(src: str, pos: Pos) -> str: + if pos >= len(src): + return "end of document" + line = src.count("\n", 0, pos) + 1 + if line == 1: + column = pos + 1 + else: + column = pos - src.rindex("\n", 0, pos) + return f"line {line}, column {column}" + + return TOMLDecodeError(f"{msg} (at {coord_repr(src, pos)})") + + +def is_unicode_scalar_value(codepoint: int) -> bool: + return (0 <= codepoint <= 55295) or (57344 <= codepoint <= 1114111) + + +def make_safe_parse_float(parse_float: ParseFloat) -> ParseFloat: + """A decorator to make `parse_float` safe. + + `parse_float` must not return dicts or lists, because these types + would be mixed with parsed TOML tables and arrays, thus confusing + the parser. The returned decorated callable raises `ValueError` + instead of returning illegal types. + """ + # The default `float` callable never returns illegal types. Optimize it. + if parse_float is float: # type: ignore[comparison-overlap] + return float + + def safe_parse_float(float_str: str) -> Any: + float_value = parse_float(float_str) + if isinstance(float_value, (dict, list)): + raise ValueError("parse_float must not return dicts or lists") + return float_value + + return safe_parse_float diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/tomli/_re.py b/backend/.venv/Lib/site-packages/pip/_vendor/tomli/_re.py new file mode 100644 index 0000000..994bb74 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/tomli/_re.py @@ -0,0 +1,107 @@ +# SPDX-License-Identifier: MIT +# SPDX-FileCopyrightText: 2021 Taneli Hukkinen +# Licensed to PSF under a Contributor Agreement. + +from __future__ import annotations + +from datetime import date, datetime, time, timedelta, timezone, tzinfo +from functools import lru_cache +import re +from typing import Any + +from ._types import ParseFloat + +# E.g. +# - 00:32:00.999999 +# - 00:32:00 +_TIME_RE_STR = r"([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])(?:\.([0-9]{1,6})[0-9]*)?" + +RE_NUMBER = re.compile( + r""" +0 +(?: + x[0-9A-Fa-f](?:_?[0-9A-Fa-f])* # hex + | + b[01](?:_?[01])* # bin + | + o[0-7](?:_?[0-7])* # oct +) +| +[+-]?(?:0|[1-9](?:_?[0-9])*) # dec, integer part +(?P + (?:\.[0-9](?:_?[0-9])*)? # optional fractional part + (?:[eE][+-]?[0-9](?:_?[0-9])*)? # optional exponent part +) +""", + flags=re.VERBOSE, +) +RE_LOCALTIME = re.compile(_TIME_RE_STR) +RE_DATETIME = re.compile( + rf""" +([0-9]{{4}})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01]) # date, e.g. 1988-10-27 +(?: + [Tt ] + {_TIME_RE_STR} + (?:([Zz])|([+-])([01][0-9]|2[0-3]):([0-5][0-9]))? # optional time offset +)? +""", + flags=re.VERBOSE, +) + + +def match_to_datetime(match: re.Match) -> datetime | date: + """Convert a `RE_DATETIME` match to `datetime.datetime` or `datetime.date`. + + Raises ValueError if the match does not correspond to a valid date + or datetime. + """ + ( + year_str, + month_str, + day_str, + hour_str, + minute_str, + sec_str, + micros_str, + zulu_time, + offset_sign_str, + offset_hour_str, + offset_minute_str, + ) = match.groups() + year, month, day = int(year_str), int(month_str), int(day_str) + if hour_str is None: + return date(year, month, day) + hour, minute, sec = int(hour_str), int(minute_str), int(sec_str) + micros = int(micros_str.ljust(6, "0")) if micros_str else 0 + if offset_sign_str: + tz: tzinfo | None = cached_tz( + offset_hour_str, offset_minute_str, offset_sign_str + ) + elif zulu_time: + tz = timezone.utc + else: # local date-time + tz = None + return datetime(year, month, day, hour, minute, sec, micros, tzinfo=tz) + + +@lru_cache(maxsize=None) +def cached_tz(hour_str: str, minute_str: str, sign_str: str) -> timezone: + sign = 1 if sign_str == "+" else -1 + return timezone( + timedelta( + hours=sign * int(hour_str), + minutes=sign * int(minute_str), + ) + ) + + +def match_to_localtime(match: re.Match) -> time: + hour_str, minute_str, sec_str, micros_str = match.groups() + micros = int(micros_str.ljust(6, "0")) if micros_str else 0 + return time(int(hour_str), int(minute_str), int(sec_str), micros) + + +def match_to_number(match: re.Match, parse_float: ParseFloat) -> Any: + if match.group("floatpart"): + return parse_float(match.group()) + return int(match.group(), 0) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/tomli/_types.py b/backend/.venv/Lib/site-packages/pip/_vendor/tomli/_types.py new file mode 100644 index 0000000..d949412 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/tomli/_types.py @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: MIT +# SPDX-FileCopyrightText: 2021 Taneli Hukkinen +# Licensed to PSF under a Contributor Agreement. + +from typing import Any, Callable, Tuple + +# Type annotations +ParseFloat = Callable[[str], Any] +Key = Tuple[str, ...] +Pos = int diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/tomli/py.typed b/backend/.venv/Lib/site-packages/pip/_vendor/tomli/py.typed new file mode 100644 index 0000000..7632ecf --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/tomli/py.typed @@ -0,0 +1 @@ +# Marker file for PEP 561 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/truststore/__init__.py b/backend/.venv/Lib/site-packages/pip/_vendor/truststore/__init__.py new file mode 100644 index 0000000..e468bf8 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/truststore/__init__.py @@ -0,0 +1,36 @@ +"""Verify certificates using native system trust stores""" + +import sys as _sys + +if _sys.version_info < (3, 10): + raise ImportError("truststore requires Python 3.10 or later") + +# Detect Python runtimes which don't implement SSLObject.get_unverified_chain() API +# This API only became public in Python 3.13 but was available in CPython and PyPy since 3.10. +if _sys.version_info < (3, 13): + try: + import ssl as _ssl + except ImportError: + raise ImportError("truststore requires the 'ssl' module") + else: + _sslmem = _ssl.MemoryBIO() + _sslobj = _ssl.create_default_context().wrap_bio( + _sslmem, + _sslmem, + ) + try: + while not hasattr(_sslobj, "get_unverified_chain"): + _sslobj = _sslobj._sslobj # type: ignore[attr-defined] + except AttributeError: + raise ImportError( + "truststore requires peer certificate chain APIs to be available" + ) from None + + del _ssl, _sslobj, _sslmem # noqa: F821 + +from ._api import SSLContext, extract_from_ssl, inject_into_ssl # noqa: E402 + +del _api, _sys # type: ignore[name-defined] # noqa: F821 + +__all__ = ["SSLContext", "inject_into_ssl", "extract_from_ssl"] +__version__ = "0.10.0" diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..33a93609a49acb49ba0b825329bc5e548e6075ff GIT binary patch literal 1348 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 Kz(N^`7XBC7aD;;Z literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_macos.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_macos.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1de31d18f4668f8482c1abe4d75c4bcaa5d0f9bd GIT binary patch literal 18991 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
    ufjAjjf&A{BX~PwWOTE~ z80kaj-b83dV0E6yPUt8$c&l6UwBYS%;ZNIO&!(+4kDC_0#-0_1>=;-CEPsv{F-DW< z8{Y&@34iJ2zqOgKRd1kmZm+YimWn|Sf zn4%k&%qwl#E!K0~?FPBGM;ph&CFzKjOQB;yMip)wYs%nlIOgBc-s!2(1SW!ob zq2)Tqi7}o#sSoEYosl#+j4C6<%2o7A2DUXclV%tlvzW!eEhC#1VnALxE0cCTzieI~ z8KcC#HaX8IFHREvRt3l(=%0(|Q45MUti=wj#17nvr7s>|55_*3y)?UY==!m1$5u1_ zKNfy6Z=0)`57$G{wNU#?sQqrJkuiPT8XE= zOD@M#tMNnk;!REvOdmy%Kk~1|p>(O|$a^jLc6TdK%5nNklkhBUd<6s=1ZZ{a)F4H_ zx4Jb?BM(Ftp2XW4Y==hKvIS_v>oS8`$cwa7TTDL&D8P6Zz)}zqJUzatf!+d9N2Q4Z zVFf~^D%2!$UWc+silIp!>LeF+l5R*~2nH3RGNMU&la>|MIdCQwptW!U$~(;V>z1Zd zJ6M7+oN1Ad_Y58H?~{A`PoHt2IoNZmUq0P$`@vf+qy#sgwrD72V(|w>k|=+tDgTJL zQ8zA+q$=FY*0X#0Sx~wP$_3M6{46T3==R}On7?R? z(Aqcg;7tS#vm0c(hm#k8c)j9Y0NU4UZ9=G6ZN^~Ds9^uyTL4Z3sb;uv4t-#Y4 zfu!o;SkUhP{E|NGX4V!cq1@OGu*nK^8|9d^gQ{7sKs(cBF4b*1l@$YejoOi+p_9GU zICkg+BUFK2b6W}CAVzI**fdLSer=H#%k~dX!uP{H9hD$r^+>!FcIch5sg0FLH%)`c z-+$|SAdU}Xd>k4jlgk~IB>b*XAbiB_&oszqjx)!nyw{k)#5P1{^&b`zBEmZwi literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c3ef1d43a501c922bc41c8c9c778dab921705ad1 GIT binary patch literal 1103 zcmZ`&%}*0S6rb%*x24c3NikXhiG+_O(nc;u1TJ`_ctAa@O(x6kfV*vHH#1YT2_YW* z2RPNMCqq2QpWxj~D>22<1BoYZO&}gTIlKK#z{$>=_kQ!<%zMAL^Cg)~06Fq6Rvi}t z@GCI7L+dE#f22|a&wveVr38%jsu)UWM~nytZr8UPD^~+X0FGja;m1fDHZ&Y@Qv)s? z6~}K$4G-Com0*oaO${~0O<(qQZ(PP~Seyrd%G-<)TQQOZ;*>EWt)v~jIy+mF_~aEQ z#cX9qv*T}}alNYOL%#!;O)-r)tuW5GM={#k+F17p$FDiEE5ybWStXM(arZw?tm5~4 zVwPX!FFhiL87m>HeT*31!_?WSqOxaWp;62$lvo|s!W?C9fGX$tV<~EYhhQMwL9Y(# zMtj>mWgqM--99Lw3Up;tS49SS)Y)~2Swih3`=!yCj1@7280HA+5gN2O1X*z9)YM;h zeYx<;qebSM7A_E%vqjUgyb9qC*<6vU`~96*iph0&_TClmSI^7qf!z z_&Fr^Y>(#p1m{qP8^%q-S=O(L@i2`6%4AfJF`ASKjmyb0QoI2d8i?L$!i5H0Xu_oi zTsnUAdH5ULIG4LX9~G)RM~W&F8n5~?S&``1Ez*5X2GD584-H<6h(GbU<4Mv4l<`tvI-OyLNDRPzUMn6L;&=59$x|Cli}>kZGmB z?7a`@Jvx5cm{~pn%PkGe=qF(QOx2p|SVJ9as+oqGdFOmp=T7z2I-EUS$Tr~InVt*v mwK|+@X{wS}PDj(V$-~K(8XDRApU4qu8)wm>i)es`iT?xn!ydl? literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_windows.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_windows.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6a42b28f4e71400453ef106d7305f15c46a94780 GIT binary patch literal 15769 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/truststore/_api.py b/backend/.venv/Lib/site-packages/pip/_vendor/truststore/_api.py new file mode 100644 index 0000000..aeb023a --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/truststore/_api.py @@ -0,0 +1,316 @@ +import os +import platform +import socket +import ssl +import sys +import typing + +import _ssl # type: ignore[import-not-found] + +from ._ssl_constants import ( + _original_SSLContext, + _original_super_SSLContext, + _truststore_SSLContext_dunder_class, + _truststore_SSLContext_super_class, +) + +if platform.system() == "Windows": + from ._windows import _configure_context, _verify_peercerts_impl +elif platform.system() == "Darwin": + from ._macos import _configure_context, _verify_peercerts_impl +else: + from ._openssl import _configure_context, _verify_peercerts_impl + +if typing.TYPE_CHECKING: + from pip._vendor.typing_extensions import Buffer + +# From typeshed/stdlib/ssl.pyi +_StrOrBytesPath: typing.TypeAlias = str | bytes | os.PathLike[str] | os.PathLike[bytes] +_PasswordType: typing.TypeAlias = str | bytes | typing.Callable[[], str | bytes] + + +def inject_into_ssl() -> None: + """Injects the :class:`truststore.SSLContext` into the ``ssl`` + module by replacing :class:`ssl.SSLContext`. + """ + setattr(ssl, "SSLContext", SSLContext) + # urllib3 holds on to its own reference of ssl.SSLContext + # so we need to replace that reference too. + try: + import pip._vendor.urllib3.util.ssl_ as urllib3_ssl + + setattr(urllib3_ssl, "SSLContext", SSLContext) + except ImportError: + pass + + +def extract_from_ssl() -> None: + """Restores the :class:`ssl.SSLContext` class to its original state""" + setattr(ssl, "SSLContext", _original_SSLContext) + try: + import pip._vendor.urllib3.util.ssl_ as urllib3_ssl + + urllib3_ssl.SSLContext = _original_SSLContext # type: ignore[assignment] + except ImportError: + pass + + +class SSLContext(_truststore_SSLContext_super_class): # type: ignore[misc] + """SSLContext API that uses system certificates on all platforms""" + + @property # type: ignore[misc] + def __class__(self) -> type: + # Dirty hack to get around isinstance() checks + # for ssl.SSLContext instances in aiohttp/trustme + # when using non-CPython implementations. + return _truststore_SSLContext_dunder_class or SSLContext + + def __init__(self, protocol: int = None) -> None: # type: ignore[assignment] + self._ctx = _original_SSLContext(protocol) + + class TruststoreSSLObject(ssl.SSLObject): + # This object exists because wrap_bio() doesn't + # immediately do the handshake so we need to do + # certificate verifications after SSLObject.do_handshake() + + def do_handshake(self) -> None: + ret = super().do_handshake() + _verify_peercerts(self, server_hostname=self.server_hostname) + return ret + + self._ctx.sslobject_class = TruststoreSSLObject + + def wrap_socket( + self, + sock: socket.socket, + server_side: bool = False, + do_handshake_on_connect: bool = True, + suppress_ragged_eofs: bool = True, + server_hostname: str | None = None, + session: ssl.SSLSession | None = None, + ) -> ssl.SSLSocket: + # Use a context manager here because the + # inner SSLContext holds on to our state + # but also does the actual handshake. + with _configure_context(self._ctx): + ssl_sock = self._ctx.wrap_socket( + sock, + server_side=server_side, + server_hostname=server_hostname, + do_handshake_on_connect=do_handshake_on_connect, + suppress_ragged_eofs=suppress_ragged_eofs, + session=session, + ) + try: + _verify_peercerts(ssl_sock, server_hostname=server_hostname) + except Exception: + ssl_sock.close() + raise + return ssl_sock + + def wrap_bio( + self, + incoming: ssl.MemoryBIO, + outgoing: ssl.MemoryBIO, + server_side: bool = False, + server_hostname: str | None = None, + session: ssl.SSLSession | None = None, + ) -> ssl.SSLObject: + with _configure_context(self._ctx): + ssl_obj = self._ctx.wrap_bio( + incoming, + outgoing, + server_hostname=server_hostname, + server_side=server_side, + session=session, + ) + return ssl_obj + + def load_verify_locations( + self, + cafile: str | bytes | os.PathLike[str] | os.PathLike[bytes] | None = None, + capath: str | bytes | os.PathLike[str] | os.PathLike[bytes] | None = None, + cadata: typing.Union[str, "Buffer", None] = None, + ) -> None: + return self._ctx.load_verify_locations( + cafile=cafile, capath=capath, cadata=cadata + ) + + def load_cert_chain( + self, + certfile: _StrOrBytesPath, + keyfile: _StrOrBytesPath | None = None, + password: _PasswordType | None = None, + ) -> None: + return self._ctx.load_cert_chain( + certfile=certfile, keyfile=keyfile, password=password + ) + + def load_default_certs( + self, purpose: ssl.Purpose = ssl.Purpose.SERVER_AUTH + ) -> None: + return self._ctx.load_default_certs(purpose) + + def set_alpn_protocols(self, alpn_protocols: typing.Iterable[str]) -> None: + return self._ctx.set_alpn_protocols(alpn_protocols) + + def set_npn_protocols(self, npn_protocols: typing.Iterable[str]) -> None: + return self._ctx.set_npn_protocols(npn_protocols) + + def set_ciphers(self, __cipherlist: str) -> None: + return self._ctx.set_ciphers(__cipherlist) + + def get_ciphers(self) -> typing.Any: + return self._ctx.get_ciphers() + + def session_stats(self) -> dict[str, int]: + return self._ctx.session_stats() + + def cert_store_stats(self) -> dict[str, int]: + raise NotImplementedError() + + def set_default_verify_paths(self) -> None: + self._ctx.set_default_verify_paths() + + @typing.overload + def get_ca_certs( + self, binary_form: typing.Literal[False] = ... + ) -> list[typing.Any]: ... + + @typing.overload + def get_ca_certs(self, binary_form: typing.Literal[True] = ...) -> list[bytes]: ... + + @typing.overload + def get_ca_certs(self, binary_form: bool = ...) -> typing.Any: ... + + def get_ca_certs(self, binary_form: bool = False) -> list[typing.Any] | list[bytes]: + raise NotImplementedError() + + @property + def check_hostname(self) -> bool: + return self._ctx.check_hostname + + @check_hostname.setter + def check_hostname(self, value: bool) -> None: + self._ctx.check_hostname = value + + @property + def hostname_checks_common_name(self) -> bool: + return self._ctx.hostname_checks_common_name + + @hostname_checks_common_name.setter + def hostname_checks_common_name(self, value: bool) -> None: + self._ctx.hostname_checks_common_name = value + + @property + def keylog_filename(self) -> str: + return self._ctx.keylog_filename + + @keylog_filename.setter + def keylog_filename(self, value: str) -> None: + self._ctx.keylog_filename = value + + @property + def maximum_version(self) -> ssl.TLSVersion: + return self._ctx.maximum_version + + @maximum_version.setter + def maximum_version(self, value: ssl.TLSVersion) -> None: + _original_super_SSLContext.maximum_version.__set__( # type: ignore[attr-defined] + self._ctx, value + ) + + @property + def minimum_version(self) -> ssl.TLSVersion: + return self._ctx.minimum_version + + @minimum_version.setter + def minimum_version(self, value: ssl.TLSVersion) -> None: + _original_super_SSLContext.minimum_version.__set__( # type: ignore[attr-defined] + self._ctx, value + ) + + @property + def options(self) -> ssl.Options: + return self._ctx.options + + @options.setter + def options(self, value: ssl.Options) -> None: + _original_super_SSLContext.options.__set__( # type: ignore[attr-defined] + self._ctx, value + ) + + @property + def post_handshake_auth(self) -> bool: + return self._ctx.post_handshake_auth + + @post_handshake_auth.setter + def post_handshake_auth(self, value: bool) -> None: + self._ctx.post_handshake_auth = value + + @property + def protocol(self) -> ssl._SSLMethod: + return self._ctx.protocol + + @property + def security_level(self) -> int: + return self._ctx.security_level + + @property + def verify_flags(self) -> ssl.VerifyFlags: + return self._ctx.verify_flags + + @verify_flags.setter + def verify_flags(self, value: ssl.VerifyFlags) -> None: + _original_super_SSLContext.verify_flags.__set__( # type: ignore[attr-defined] + self._ctx, value + ) + + @property + def verify_mode(self) -> ssl.VerifyMode: + return self._ctx.verify_mode + + @verify_mode.setter + def verify_mode(self, value: ssl.VerifyMode) -> None: + _original_super_SSLContext.verify_mode.__set__( # type: ignore[attr-defined] + self._ctx, value + ) + + +# Python 3.13+ makes get_unverified_chain() a public API that only returns DER +# encoded certificates. We detect whether we need to call public_bytes() for 3.10->3.12 +# Pre-3.13 returned None instead of an empty list from get_unverified_chain() +if sys.version_info >= (3, 13): + + def _get_unverified_chain_bytes(sslobj: ssl.SSLObject) -> list[bytes]: + unverified_chain = sslobj.get_unverified_chain() or () # type: ignore[attr-defined] + return [ + cert if isinstance(cert, bytes) else cert.public_bytes(_ssl.ENCODING_DER) + for cert in unverified_chain + ] + +else: + + def _get_unverified_chain_bytes(sslobj: ssl.SSLObject) -> list[bytes]: + unverified_chain = sslobj.get_unverified_chain() or () # type: ignore[attr-defined] + return [cert.public_bytes(_ssl.ENCODING_DER) for cert in unverified_chain] + + +def _verify_peercerts( + sock_or_sslobj: ssl.SSLSocket | ssl.SSLObject, server_hostname: str | None +) -> None: + """ + Verifies the peer certificates from an SSLSocket or SSLObject + against the certificates in the OS trust store. + """ + sslobj: ssl.SSLObject = sock_or_sslobj # type: ignore[assignment] + try: + while not hasattr(sslobj, "get_unverified_chain"): + sslobj = sslobj._sslobj # type: ignore[attr-defined] + except AttributeError: + pass + + cert_bytes = _get_unverified_chain_bytes(sslobj) + _verify_peercerts_impl( + sock_or_sslobj.context, cert_bytes, server_hostname=server_hostname + ) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/truststore/_macos.py b/backend/.venv/Lib/site-packages/pip/_vendor/truststore/_macos.py new file mode 100644 index 0000000..3450307 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/truststore/_macos.py @@ -0,0 +1,571 @@ +import contextlib +import ctypes +import platform +import ssl +import typing +from ctypes import ( + CDLL, + POINTER, + c_bool, + c_char_p, + c_int32, + c_long, + c_uint32, + c_ulong, + c_void_p, +) +from ctypes.util import find_library + +from ._ssl_constants import _set_ssl_context_verify_mode + +_mac_version = platform.mac_ver()[0] +_mac_version_info = tuple(map(int, _mac_version.split("."))) +if _mac_version_info < (10, 8): + raise ImportError( + f"Only OS X 10.8 and newer are supported, not {_mac_version_info[0]}.{_mac_version_info[1]}" + ) + +_is_macos_version_10_14_or_later = _mac_version_info >= (10, 14) + + +def _load_cdll(name: str, macos10_16_path: str) -> CDLL: + """Loads a CDLL by name, falling back to known path on 10.16+""" + try: + # Big Sur is technically 11 but we use 10.16 due to the Big Sur + # beta being labeled as 10.16. + path: str | None + if _mac_version_info >= (10, 16): + path = macos10_16_path + else: + path = find_library(name) + if not path: + raise OSError # Caught and reraised as 'ImportError' + return CDLL(path, use_errno=True) + except OSError: + raise ImportError(f"The library {name} failed to load") from None + + +Security = _load_cdll( + "Security", "/System/Library/Frameworks/Security.framework/Security" +) +CoreFoundation = _load_cdll( + "CoreFoundation", + "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", +) + +Boolean = c_bool +CFIndex = c_long +CFStringEncoding = c_uint32 +CFData = c_void_p +CFString = c_void_p +CFArray = c_void_p +CFMutableArray = c_void_p +CFError = c_void_p +CFType = c_void_p +CFTypeID = c_ulong +CFTypeRef = POINTER(CFType) +CFAllocatorRef = c_void_p + +OSStatus = c_int32 + +CFErrorRef = POINTER(CFError) +CFDataRef = POINTER(CFData) +CFStringRef = POINTER(CFString) +CFArrayRef = POINTER(CFArray) +CFMutableArrayRef = POINTER(CFMutableArray) +CFArrayCallBacks = c_void_p +CFOptionFlags = c_uint32 + +SecCertificateRef = POINTER(c_void_p) +SecPolicyRef = POINTER(c_void_p) +SecTrustRef = POINTER(c_void_p) +SecTrustResultType = c_uint32 +SecTrustOptionFlags = c_uint32 + +try: + Security.SecCertificateCreateWithData.argtypes = [CFAllocatorRef, CFDataRef] + Security.SecCertificateCreateWithData.restype = SecCertificateRef + + Security.SecCertificateCopyData.argtypes = [SecCertificateRef] + Security.SecCertificateCopyData.restype = CFDataRef + + Security.SecCopyErrorMessageString.argtypes = [OSStatus, c_void_p] + Security.SecCopyErrorMessageString.restype = CFStringRef + + Security.SecTrustSetAnchorCertificates.argtypes = [SecTrustRef, CFArrayRef] + Security.SecTrustSetAnchorCertificates.restype = OSStatus + + Security.SecTrustSetAnchorCertificatesOnly.argtypes = [SecTrustRef, Boolean] + Security.SecTrustSetAnchorCertificatesOnly.restype = OSStatus + + Security.SecPolicyCreateRevocation.argtypes = [CFOptionFlags] + Security.SecPolicyCreateRevocation.restype = SecPolicyRef + + Security.SecPolicyCreateSSL.argtypes = [Boolean, CFStringRef] + Security.SecPolicyCreateSSL.restype = SecPolicyRef + + Security.SecTrustCreateWithCertificates.argtypes = [ + CFTypeRef, + CFTypeRef, + POINTER(SecTrustRef), + ] + Security.SecTrustCreateWithCertificates.restype = OSStatus + + Security.SecTrustGetTrustResult.argtypes = [ + SecTrustRef, + POINTER(SecTrustResultType), + ] + Security.SecTrustGetTrustResult.restype = OSStatus + + Security.SecTrustEvaluate.argtypes = [ + SecTrustRef, + POINTER(SecTrustResultType), + ] + Security.SecTrustEvaluate.restype = OSStatus + + Security.SecTrustRef = SecTrustRef # type: ignore[attr-defined] + Security.SecTrustResultType = SecTrustResultType # type: ignore[attr-defined] + Security.OSStatus = OSStatus # type: ignore[attr-defined] + + kSecRevocationUseAnyAvailableMethod = 3 + kSecRevocationRequirePositiveResponse = 8 + + CoreFoundation.CFRelease.argtypes = [CFTypeRef] + CoreFoundation.CFRelease.restype = None + + CoreFoundation.CFGetTypeID.argtypes = [CFTypeRef] + CoreFoundation.CFGetTypeID.restype = CFTypeID + + CoreFoundation.CFStringCreateWithCString.argtypes = [ + CFAllocatorRef, + c_char_p, + CFStringEncoding, + ] + CoreFoundation.CFStringCreateWithCString.restype = CFStringRef + + CoreFoundation.CFStringGetCStringPtr.argtypes = [CFStringRef, CFStringEncoding] + CoreFoundation.CFStringGetCStringPtr.restype = c_char_p + + CoreFoundation.CFStringGetCString.argtypes = [ + CFStringRef, + c_char_p, + CFIndex, + CFStringEncoding, + ] + CoreFoundation.CFStringGetCString.restype = c_bool + + CoreFoundation.CFDataCreate.argtypes = [CFAllocatorRef, c_char_p, CFIndex] + CoreFoundation.CFDataCreate.restype = CFDataRef + + CoreFoundation.CFDataGetLength.argtypes = [CFDataRef] + CoreFoundation.CFDataGetLength.restype = CFIndex + + CoreFoundation.CFDataGetBytePtr.argtypes = [CFDataRef] + CoreFoundation.CFDataGetBytePtr.restype = c_void_p + + CoreFoundation.CFArrayCreate.argtypes = [ + CFAllocatorRef, + POINTER(CFTypeRef), + CFIndex, + CFArrayCallBacks, + ] + CoreFoundation.CFArrayCreate.restype = CFArrayRef + + CoreFoundation.CFArrayCreateMutable.argtypes = [ + CFAllocatorRef, + CFIndex, + CFArrayCallBacks, + ] + CoreFoundation.CFArrayCreateMutable.restype = CFMutableArrayRef + + CoreFoundation.CFArrayAppendValue.argtypes = [CFMutableArrayRef, c_void_p] + CoreFoundation.CFArrayAppendValue.restype = None + + CoreFoundation.CFArrayGetCount.argtypes = [CFArrayRef] + CoreFoundation.CFArrayGetCount.restype = CFIndex + + CoreFoundation.CFArrayGetValueAtIndex.argtypes = [CFArrayRef, CFIndex] + CoreFoundation.CFArrayGetValueAtIndex.restype = c_void_p + + CoreFoundation.CFErrorGetCode.argtypes = [CFErrorRef] + CoreFoundation.CFErrorGetCode.restype = CFIndex + + CoreFoundation.CFErrorCopyDescription.argtypes = [CFErrorRef] + CoreFoundation.CFErrorCopyDescription.restype = CFStringRef + + CoreFoundation.kCFAllocatorDefault = CFAllocatorRef.in_dll( # type: ignore[attr-defined] + CoreFoundation, "kCFAllocatorDefault" + ) + CoreFoundation.kCFTypeArrayCallBacks = c_void_p.in_dll( # type: ignore[attr-defined] + CoreFoundation, "kCFTypeArrayCallBacks" + ) + + CoreFoundation.CFTypeRef = CFTypeRef # type: ignore[attr-defined] + CoreFoundation.CFArrayRef = CFArrayRef # type: ignore[attr-defined] + CoreFoundation.CFStringRef = CFStringRef # type: ignore[attr-defined] + CoreFoundation.CFErrorRef = CFErrorRef # type: ignore[attr-defined] + +except AttributeError as e: + raise ImportError(f"Error initializing ctypes: {e}") from None + +# SecTrustEvaluateWithError is macOS 10.14+ +if _is_macos_version_10_14_or_later: + try: + Security.SecTrustEvaluateWithError.argtypes = [ + SecTrustRef, + POINTER(CFErrorRef), + ] + Security.SecTrustEvaluateWithError.restype = c_bool + except AttributeError as e: + raise ImportError(f"Error initializing ctypes: {e}") from None + + +def _handle_osstatus(result: OSStatus, _: typing.Any, args: typing.Any) -> typing.Any: + """ + Raises an error if the OSStatus value is non-zero. + """ + if int(result) == 0: + return args + + # Returns a CFString which we need to transform + # into a UTF-8 Python string. + error_message_cfstring = None + try: + error_message_cfstring = Security.SecCopyErrorMessageString(result, None) + + # First step is convert the CFString into a C string pointer. + # We try the fast no-copy way first. + error_message_cfstring_c_void_p = ctypes.cast( + error_message_cfstring, ctypes.POINTER(ctypes.c_void_p) + ) + message = CoreFoundation.CFStringGetCStringPtr( + error_message_cfstring_c_void_p, CFConst.kCFStringEncodingUTF8 + ) + + # Quoting the Apple dev docs: + # + # "A pointer to a C string or NULL if the internal + # storage of theString does not allow this to be + # returned efficiently." + # + # So we need to get our hands dirty. + if message is None: + buffer = ctypes.create_string_buffer(1024) + result = CoreFoundation.CFStringGetCString( + error_message_cfstring_c_void_p, + buffer, + 1024, + CFConst.kCFStringEncodingUTF8, + ) + if not result: + raise OSError("Error copying C string from CFStringRef") + message = buffer.value + + finally: + if error_message_cfstring is not None: + CoreFoundation.CFRelease(error_message_cfstring) + + # If no message can be found for this status we come + # up with a generic one that forwards the status code. + if message is None or message == "": + message = f"SecureTransport operation returned a non-zero OSStatus: {result}" + + raise ssl.SSLError(message) + + +Security.SecTrustCreateWithCertificates.errcheck = _handle_osstatus # type: ignore[assignment] +Security.SecTrustSetAnchorCertificates.errcheck = _handle_osstatus # type: ignore[assignment] +Security.SecTrustSetAnchorCertificatesOnly.errcheck = _handle_osstatus # type: ignore[assignment] +Security.SecTrustGetTrustResult.errcheck = _handle_osstatus # type: ignore[assignment] +Security.SecTrustEvaluate.errcheck = _handle_osstatus # type: ignore[assignment] + + +class CFConst: + """CoreFoundation constants""" + + kCFStringEncodingUTF8 = CFStringEncoding(0x08000100) + + errSecIncompleteCertRevocationCheck = -67635 + errSecHostNameMismatch = -67602 + errSecCertificateExpired = -67818 + errSecNotTrusted = -67843 + + +def _bytes_to_cf_data_ref(value: bytes) -> CFDataRef: # type: ignore[valid-type] + return CoreFoundation.CFDataCreate( # type: ignore[no-any-return] + CoreFoundation.kCFAllocatorDefault, value, len(value) + ) + + +def _bytes_to_cf_string(value: bytes) -> CFString: + """ + Given a Python binary data, create a CFString. + The string must be CFReleased by the caller. + """ + c_str = ctypes.c_char_p(value) + cf_str = CoreFoundation.CFStringCreateWithCString( + CoreFoundation.kCFAllocatorDefault, + c_str, + CFConst.kCFStringEncodingUTF8, + ) + return cf_str # type: ignore[no-any-return] + + +def _cf_string_ref_to_str(cf_string_ref: CFStringRef) -> str | None: # type: ignore[valid-type] + """ + Creates a Unicode string from a CFString object. Used entirely for error + reporting. + Yes, it annoys me quite a lot that this function is this complex. + """ + + string = CoreFoundation.CFStringGetCStringPtr( + cf_string_ref, CFConst.kCFStringEncodingUTF8 + ) + if string is None: + buffer = ctypes.create_string_buffer(1024) + result = CoreFoundation.CFStringGetCString( + cf_string_ref, buffer, 1024, CFConst.kCFStringEncodingUTF8 + ) + if not result: + raise OSError("Error copying C string from CFStringRef") + string = buffer.value + if string is not None: + string = string.decode("utf-8") + return string # type: ignore[no-any-return] + + +def _der_certs_to_cf_cert_array(certs: list[bytes]) -> CFMutableArrayRef: # type: ignore[valid-type] + """Builds a CFArray of SecCertificateRefs from a list of DER-encoded certificates. + Responsibility of the caller to call CoreFoundation.CFRelease on the CFArray. + """ + cf_array = CoreFoundation.CFArrayCreateMutable( + CoreFoundation.kCFAllocatorDefault, + 0, + ctypes.byref(CoreFoundation.kCFTypeArrayCallBacks), + ) + if not cf_array: + raise MemoryError("Unable to allocate memory!") + + for cert_data in certs: + cf_data = None + sec_cert_ref = None + try: + cf_data = _bytes_to_cf_data_ref(cert_data) + sec_cert_ref = Security.SecCertificateCreateWithData( + CoreFoundation.kCFAllocatorDefault, cf_data + ) + CoreFoundation.CFArrayAppendValue(cf_array, sec_cert_ref) + finally: + if cf_data: + CoreFoundation.CFRelease(cf_data) + if sec_cert_ref: + CoreFoundation.CFRelease(sec_cert_ref) + + return cf_array # type: ignore[no-any-return] + + +@contextlib.contextmanager +def _configure_context(ctx: ssl.SSLContext) -> typing.Iterator[None]: + check_hostname = ctx.check_hostname + verify_mode = ctx.verify_mode + ctx.check_hostname = False + _set_ssl_context_verify_mode(ctx, ssl.CERT_NONE) + try: + yield + finally: + ctx.check_hostname = check_hostname + _set_ssl_context_verify_mode(ctx, verify_mode) + + +def _verify_peercerts_impl( + ssl_context: ssl.SSLContext, + cert_chain: list[bytes], + server_hostname: str | None = None, +) -> None: + certs = None + policies = None + trust = None + try: + # Only set a hostname on the policy if we're verifying the hostname + # on the leaf certificate. + if server_hostname is not None and ssl_context.check_hostname: + cf_str_hostname = None + try: + cf_str_hostname = _bytes_to_cf_string(server_hostname.encode("ascii")) + ssl_policy = Security.SecPolicyCreateSSL(True, cf_str_hostname) + finally: + if cf_str_hostname: + CoreFoundation.CFRelease(cf_str_hostname) + else: + ssl_policy = Security.SecPolicyCreateSSL(True, None) + + policies = ssl_policy + if ssl_context.verify_flags & ssl.VERIFY_CRL_CHECK_CHAIN: + # Add explicit policy requiring positive revocation checks + policies = CoreFoundation.CFArrayCreateMutable( + CoreFoundation.kCFAllocatorDefault, + 0, + ctypes.byref(CoreFoundation.kCFTypeArrayCallBacks), + ) + CoreFoundation.CFArrayAppendValue(policies, ssl_policy) + CoreFoundation.CFRelease(ssl_policy) + revocation_policy = Security.SecPolicyCreateRevocation( + kSecRevocationUseAnyAvailableMethod + | kSecRevocationRequirePositiveResponse + ) + CoreFoundation.CFArrayAppendValue(policies, revocation_policy) + CoreFoundation.CFRelease(revocation_policy) + elif ssl_context.verify_flags & ssl.VERIFY_CRL_CHECK_LEAF: + raise NotImplementedError("VERIFY_CRL_CHECK_LEAF not implemented for macOS") + + certs = None + try: + certs = _der_certs_to_cf_cert_array(cert_chain) + + # Now that we have certificates loaded and a SecPolicy + # we can finally create a SecTrust object! + trust = Security.SecTrustRef() + Security.SecTrustCreateWithCertificates( + certs, policies, ctypes.byref(trust) + ) + + finally: + # The certs are now being held by SecTrust so we can + # release our handles for the array. + if certs: + CoreFoundation.CFRelease(certs) + + # If there are additional trust anchors to load we need to transform + # the list of DER-encoded certificates into a CFArray. + ctx_ca_certs_der: list[bytes] | None = ssl_context.get_ca_certs( + binary_form=True + ) + if ctx_ca_certs_der: + ctx_ca_certs = None + try: + ctx_ca_certs = _der_certs_to_cf_cert_array(ctx_ca_certs_der) + Security.SecTrustSetAnchorCertificates(trust, ctx_ca_certs) + finally: + if ctx_ca_certs: + CoreFoundation.CFRelease(ctx_ca_certs) + + # We always want system certificates. + Security.SecTrustSetAnchorCertificatesOnly(trust, False) + + # macOS 10.13 and earlier don't support SecTrustEvaluateWithError() + # so we use SecTrustEvaluate() which means we need to construct error + # messages ourselves. + if _is_macos_version_10_14_or_later: + _verify_peercerts_impl_macos_10_14(ssl_context, trust) + else: + _verify_peercerts_impl_macos_10_13(ssl_context, trust) + finally: + if policies: + CoreFoundation.CFRelease(policies) + if trust: + CoreFoundation.CFRelease(trust) + + +def _verify_peercerts_impl_macos_10_13( + ssl_context: ssl.SSLContext, sec_trust_ref: typing.Any +) -> None: + """Verify using 'SecTrustEvaluate' API for macOS 10.13 and earlier. + macOS 10.14 added the 'SecTrustEvaluateWithError' API. + """ + sec_trust_result_type = Security.SecTrustResultType() + Security.SecTrustEvaluate(sec_trust_ref, ctypes.byref(sec_trust_result_type)) + + try: + sec_trust_result_type_as_int = int(sec_trust_result_type.value) + except (ValueError, TypeError): + sec_trust_result_type_as_int = -1 + + # Apple doesn't document these values in their own API docs. + # See: https://github.com/xybp888/iOS-SDKs/blob/master/iPhoneOS13.0.sdk/System/Library/Frameworks/Security.framework/Headers/SecTrust.h#L84 + if ( + ssl_context.verify_mode == ssl.CERT_REQUIRED + and sec_trust_result_type_as_int not in (1, 4) + ): + # Note that we're not able to ignore only hostname errors + # for macOS 10.13 and earlier, so check_hostname=False will + # still return an error. + sec_trust_result_type_to_message = { + 0: "Invalid trust result type", + # 1: "Trust evaluation succeeded", + 2: "User confirmation required", + 3: "User specified that certificate is not trusted", + # 4: "Trust result is unspecified", + 5: "Recoverable trust failure occurred", + 6: "Fatal trust failure occurred", + 7: "Other error occurred, certificate may be revoked", + } + error_message = sec_trust_result_type_to_message.get( + sec_trust_result_type_as_int, + f"Unknown trust result: {sec_trust_result_type_as_int}", + ) + + err = ssl.SSLCertVerificationError(error_message) + err.verify_message = error_message + err.verify_code = sec_trust_result_type_as_int + raise err + + +def _verify_peercerts_impl_macos_10_14( + ssl_context: ssl.SSLContext, sec_trust_ref: typing.Any +) -> None: + """Verify using 'SecTrustEvaluateWithError' API for macOS 10.14+.""" + cf_error = CoreFoundation.CFErrorRef() + sec_trust_eval_result = Security.SecTrustEvaluateWithError( + sec_trust_ref, ctypes.byref(cf_error) + ) + # sec_trust_eval_result is a bool (0 or 1) + # where 1 means that the certs are trusted. + if sec_trust_eval_result == 1: + is_trusted = True + elif sec_trust_eval_result == 0: + is_trusted = False + else: + raise ssl.SSLError( + f"Unknown result from Security.SecTrustEvaluateWithError: {sec_trust_eval_result!r}" + ) + + cf_error_code = 0 + if not is_trusted: + cf_error_code = CoreFoundation.CFErrorGetCode(cf_error) + + # If the error is a known failure that we're + # explicitly okay with from SSLContext configuration + # we can set is_trusted accordingly. + if ssl_context.verify_mode != ssl.CERT_REQUIRED and ( + cf_error_code == CFConst.errSecNotTrusted + or cf_error_code == CFConst.errSecCertificateExpired + ): + is_trusted = True + + # If we're still not trusted then we start to + # construct and raise the SSLCertVerificationError. + if not is_trusted: + cf_error_string_ref = None + try: + cf_error_string_ref = CoreFoundation.CFErrorCopyDescription(cf_error) + + # Can this ever return 'None' if there's a CFError? + cf_error_message = ( + _cf_string_ref_to_str(cf_error_string_ref) + or "Certificate verification failed" + ) + + # TODO: Not sure if we need the SecTrustResultType for anything? + # We only care whether or not it's a success or failure for now. + sec_trust_result_type = Security.SecTrustResultType() + Security.SecTrustGetTrustResult( + sec_trust_ref, ctypes.byref(sec_trust_result_type) + ) + + err = ssl.SSLCertVerificationError(cf_error_message) + err.verify_message = cf_error_message + err.verify_code = cf_error_code + raise err + finally: + if cf_error_string_ref: + CoreFoundation.CFRelease(cf_error_string_ref) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/truststore/_openssl.py b/backend/.venv/Lib/site-packages/pip/_vendor/truststore/_openssl.py new file mode 100644 index 0000000..9951cf7 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/truststore/_openssl.py @@ -0,0 +1,66 @@ +import contextlib +import os +import re +import ssl +import typing + +# candidates based on https://github.com/tiran/certifi-system-store by Christian Heimes +_CA_FILE_CANDIDATES = [ + # Alpine, Arch, Fedora 34+, OpenWRT, RHEL 9+, BSD + "/etc/ssl/cert.pem", + # Fedora <= 34, RHEL <= 9, CentOS <= 9 + "/etc/pki/tls/cert.pem", + # Debian, Ubuntu (requires ca-certificates) + "/etc/ssl/certs/ca-certificates.crt", + # SUSE + "/etc/ssl/ca-bundle.pem", +] + +_HASHED_CERT_FILENAME_RE = re.compile(r"^[0-9a-fA-F]{8}\.[0-9]$") + + +@contextlib.contextmanager +def _configure_context(ctx: ssl.SSLContext) -> typing.Iterator[None]: + # First, check whether the default locations from OpenSSL + # seem like they will give us a usable set of CA certs. + # ssl.get_default_verify_paths already takes care of: + # - getting cafile from either the SSL_CERT_FILE env var + # or the path configured when OpenSSL was compiled, + # and verifying that that path exists + # - getting capath from either the SSL_CERT_DIR env var + # or the path configured when OpenSSL was compiled, + # and verifying that that path exists + # In addition we'll check whether capath appears to contain certs. + defaults = ssl.get_default_verify_paths() + if defaults.cafile or (defaults.capath and _capath_contains_certs(defaults.capath)): + ctx.set_default_verify_paths() + else: + # cafile from OpenSSL doesn't exist + # and capath from OpenSSL doesn't contain certs. + # Let's search other common locations instead. + for cafile in _CA_FILE_CANDIDATES: + if os.path.isfile(cafile): + ctx.load_verify_locations(cafile=cafile) + break + + yield + + +def _capath_contains_certs(capath: str) -> bool: + """Check whether capath exists and contains certs in the expected format.""" + if not os.path.isdir(capath): + return False + for name in os.listdir(capath): + if _HASHED_CERT_FILENAME_RE.match(name): + return True + return False + + +def _verify_peercerts_impl( + ssl_context: ssl.SSLContext, + cert_chain: list[bytes], + server_hostname: str | None = None, +) -> None: + # This is a no-op because we've enabled SSLContext's built-in + # verification via verify_mode=CERT_REQUIRED, and don't need to repeat it. + pass diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/truststore/_ssl_constants.py b/backend/.venv/Lib/site-packages/pip/_vendor/truststore/_ssl_constants.py new file mode 100644 index 0000000..b1ee7a3 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/truststore/_ssl_constants.py @@ -0,0 +1,31 @@ +import ssl +import sys +import typing + +# Hold on to the original class so we can create it consistently +# even if we inject our own SSLContext into the ssl module. +_original_SSLContext = ssl.SSLContext +_original_super_SSLContext = super(_original_SSLContext, _original_SSLContext) + +# CPython is known to be good, but non-CPython implementations +# may implement SSLContext differently so to be safe we don't +# subclass the SSLContext. + +# This is returned by truststore.SSLContext.__class__() +_truststore_SSLContext_dunder_class: typing.Optional[type] + +# This value is the superclass of truststore.SSLContext. +_truststore_SSLContext_super_class: type + +if sys.implementation.name == "cpython": + _truststore_SSLContext_super_class = _original_SSLContext + _truststore_SSLContext_dunder_class = None +else: + _truststore_SSLContext_super_class = object + _truststore_SSLContext_dunder_class = _original_SSLContext + + +def _set_ssl_context_verify_mode( + ssl_context: ssl.SSLContext, verify_mode: ssl.VerifyMode +) -> None: + _original_super_SSLContext.verify_mode.__set__(ssl_context, verify_mode) # type: ignore[attr-defined] diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/truststore/_windows.py b/backend/.venv/Lib/site-packages/pip/_vendor/truststore/_windows.py new file mode 100644 index 0000000..a9bf9ab --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/truststore/_windows.py @@ -0,0 +1,567 @@ +import contextlib +import ssl +import typing +from ctypes import WinDLL # type: ignore +from ctypes import WinError # type: ignore +from ctypes import ( + POINTER, + Structure, + c_char_p, + c_ulong, + c_void_p, + c_wchar_p, + cast, + create_unicode_buffer, + pointer, + sizeof, +) +from ctypes.wintypes import ( + BOOL, + DWORD, + HANDLE, + LONG, + LPCSTR, + LPCVOID, + LPCWSTR, + LPFILETIME, + LPSTR, + LPWSTR, +) +from typing import TYPE_CHECKING, Any + +from ._ssl_constants import _set_ssl_context_verify_mode + +HCERTCHAINENGINE = HANDLE +HCERTSTORE = HANDLE +HCRYPTPROV_LEGACY = HANDLE + + +class CERT_CONTEXT(Structure): + _fields_ = ( + ("dwCertEncodingType", DWORD), + ("pbCertEncoded", c_void_p), + ("cbCertEncoded", DWORD), + ("pCertInfo", c_void_p), + ("hCertStore", HCERTSTORE), + ) + + +PCERT_CONTEXT = POINTER(CERT_CONTEXT) +PCCERT_CONTEXT = POINTER(PCERT_CONTEXT) + + +class CERT_ENHKEY_USAGE(Structure): + _fields_ = ( + ("cUsageIdentifier", DWORD), + ("rgpszUsageIdentifier", POINTER(LPSTR)), + ) + + +PCERT_ENHKEY_USAGE = POINTER(CERT_ENHKEY_USAGE) + + +class CERT_USAGE_MATCH(Structure): + _fields_ = ( + ("dwType", DWORD), + ("Usage", CERT_ENHKEY_USAGE), + ) + + +class CERT_CHAIN_PARA(Structure): + _fields_ = ( + ("cbSize", DWORD), + ("RequestedUsage", CERT_USAGE_MATCH), + ("RequestedIssuancePolicy", CERT_USAGE_MATCH), + ("dwUrlRetrievalTimeout", DWORD), + ("fCheckRevocationFreshnessTime", BOOL), + ("dwRevocationFreshnessTime", DWORD), + ("pftCacheResync", LPFILETIME), + ("pStrongSignPara", c_void_p), + ("dwStrongSignFlags", DWORD), + ) + + +if TYPE_CHECKING: + PCERT_CHAIN_PARA = pointer[CERT_CHAIN_PARA] # type: ignore[misc] +else: + PCERT_CHAIN_PARA = POINTER(CERT_CHAIN_PARA) + + +class CERT_TRUST_STATUS(Structure): + _fields_ = ( + ("dwErrorStatus", DWORD), + ("dwInfoStatus", DWORD), + ) + + +class CERT_CHAIN_ELEMENT(Structure): + _fields_ = ( + ("cbSize", DWORD), + ("pCertContext", PCERT_CONTEXT), + ("TrustStatus", CERT_TRUST_STATUS), + ("pRevocationInfo", c_void_p), + ("pIssuanceUsage", PCERT_ENHKEY_USAGE), + ("pApplicationUsage", PCERT_ENHKEY_USAGE), + ("pwszExtendedErrorInfo", LPCWSTR), + ) + + +PCERT_CHAIN_ELEMENT = POINTER(CERT_CHAIN_ELEMENT) + + +class CERT_SIMPLE_CHAIN(Structure): + _fields_ = ( + ("cbSize", DWORD), + ("TrustStatus", CERT_TRUST_STATUS), + ("cElement", DWORD), + ("rgpElement", POINTER(PCERT_CHAIN_ELEMENT)), + ("pTrustListInfo", c_void_p), + ("fHasRevocationFreshnessTime", BOOL), + ("dwRevocationFreshnessTime", DWORD), + ) + + +PCERT_SIMPLE_CHAIN = POINTER(CERT_SIMPLE_CHAIN) + + +class CERT_CHAIN_CONTEXT(Structure): + _fields_ = ( + ("cbSize", DWORD), + ("TrustStatus", CERT_TRUST_STATUS), + ("cChain", DWORD), + ("rgpChain", POINTER(PCERT_SIMPLE_CHAIN)), + ("cLowerQualityChainContext", DWORD), + ("rgpLowerQualityChainContext", c_void_p), + ("fHasRevocationFreshnessTime", BOOL), + ("dwRevocationFreshnessTime", DWORD), + ) + + +PCERT_CHAIN_CONTEXT = POINTER(CERT_CHAIN_CONTEXT) +PCCERT_CHAIN_CONTEXT = POINTER(PCERT_CHAIN_CONTEXT) + + +class SSL_EXTRA_CERT_CHAIN_POLICY_PARA(Structure): + _fields_ = ( + ("cbSize", DWORD), + ("dwAuthType", DWORD), + ("fdwChecks", DWORD), + ("pwszServerName", LPCWSTR), + ) + + +class CERT_CHAIN_POLICY_PARA(Structure): + _fields_ = ( + ("cbSize", DWORD), + ("dwFlags", DWORD), + ("pvExtraPolicyPara", c_void_p), + ) + + +PCERT_CHAIN_POLICY_PARA = POINTER(CERT_CHAIN_POLICY_PARA) + + +class CERT_CHAIN_POLICY_STATUS(Structure): + _fields_ = ( + ("cbSize", DWORD), + ("dwError", DWORD), + ("lChainIndex", LONG), + ("lElementIndex", LONG), + ("pvExtraPolicyStatus", c_void_p), + ) + + +PCERT_CHAIN_POLICY_STATUS = POINTER(CERT_CHAIN_POLICY_STATUS) + + +class CERT_CHAIN_ENGINE_CONFIG(Structure): + _fields_ = ( + ("cbSize", DWORD), + ("hRestrictedRoot", HCERTSTORE), + ("hRestrictedTrust", HCERTSTORE), + ("hRestrictedOther", HCERTSTORE), + ("cAdditionalStore", DWORD), + ("rghAdditionalStore", c_void_p), + ("dwFlags", DWORD), + ("dwUrlRetrievalTimeout", DWORD), + ("MaximumCachedCertificates", DWORD), + ("CycleDetectionModulus", DWORD), + ("hExclusiveRoot", HCERTSTORE), + ("hExclusiveTrustedPeople", HCERTSTORE), + ("dwExclusiveFlags", DWORD), + ) + + +PCERT_CHAIN_ENGINE_CONFIG = POINTER(CERT_CHAIN_ENGINE_CONFIG) +PHCERTCHAINENGINE = POINTER(HCERTCHAINENGINE) + +X509_ASN_ENCODING = 0x00000001 +PKCS_7_ASN_ENCODING = 0x00010000 +CERT_STORE_PROV_MEMORY = b"Memory" +CERT_STORE_ADD_USE_EXISTING = 2 +USAGE_MATCH_TYPE_OR = 1 +OID_PKIX_KP_SERVER_AUTH = c_char_p(b"1.3.6.1.5.5.7.3.1") +CERT_CHAIN_REVOCATION_CHECK_END_CERT = 0x10000000 +CERT_CHAIN_REVOCATION_CHECK_CHAIN = 0x20000000 +CERT_CHAIN_POLICY_IGNORE_ALL_NOT_TIME_VALID_FLAGS = 0x00000007 +CERT_CHAIN_POLICY_IGNORE_INVALID_BASIC_CONSTRAINTS_FLAG = 0x00000008 +CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG = 0x00000010 +CERT_CHAIN_POLICY_IGNORE_INVALID_NAME_FLAG = 0x00000040 +CERT_CHAIN_POLICY_IGNORE_WRONG_USAGE_FLAG = 0x00000020 +CERT_CHAIN_POLICY_IGNORE_INVALID_POLICY_FLAG = 0x00000080 +CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGS = 0x00000F00 +CERT_CHAIN_POLICY_ALLOW_TESTROOT_FLAG = 0x00008000 +CERT_CHAIN_POLICY_TRUST_TESTROOT_FLAG = 0x00004000 +SECURITY_FLAG_IGNORE_CERT_CN_INVALID = 0x00001000 +AUTHTYPE_SERVER = 2 +CERT_CHAIN_POLICY_SSL = 4 +FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000 +FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200 + +# Flags to set for SSLContext.verify_mode=CERT_NONE +CERT_CHAIN_POLICY_VERIFY_MODE_NONE_FLAGS = ( + CERT_CHAIN_POLICY_IGNORE_ALL_NOT_TIME_VALID_FLAGS + | CERT_CHAIN_POLICY_IGNORE_INVALID_BASIC_CONSTRAINTS_FLAG + | CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG + | CERT_CHAIN_POLICY_IGNORE_INVALID_NAME_FLAG + | CERT_CHAIN_POLICY_IGNORE_WRONG_USAGE_FLAG + | CERT_CHAIN_POLICY_IGNORE_INVALID_POLICY_FLAG + | CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGS + | CERT_CHAIN_POLICY_ALLOW_TESTROOT_FLAG + | CERT_CHAIN_POLICY_TRUST_TESTROOT_FLAG +) + +wincrypt = WinDLL("crypt32.dll") +kernel32 = WinDLL("kernel32.dll") + + +def _handle_win_error(result: bool, _: Any, args: Any) -> Any: + if not result: + # Note, actually raises OSError after calling GetLastError and FormatMessage + raise WinError() + return args + + +CertCreateCertificateChainEngine = wincrypt.CertCreateCertificateChainEngine +CertCreateCertificateChainEngine.argtypes = ( + PCERT_CHAIN_ENGINE_CONFIG, + PHCERTCHAINENGINE, +) +CertCreateCertificateChainEngine.errcheck = _handle_win_error + +CertOpenStore = wincrypt.CertOpenStore +CertOpenStore.argtypes = (LPCSTR, DWORD, HCRYPTPROV_LEGACY, DWORD, c_void_p) +CertOpenStore.restype = HCERTSTORE +CertOpenStore.errcheck = _handle_win_error + +CertAddEncodedCertificateToStore = wincrypt.CertAddEncodedCertificateToStore +CertAddEncodedCertificateToStore.argtypes = ( + HCERTSTORE, + DWORD, + c_char_p, + DWORD, + DWORD, + PCCERT_CONTEXT, +) +CertAddEncodedCertificateToStore.restype = BOOL + +CertCreateCertificateContext = wincrypt.CertCreateCertificateContext +CertCreateCertificateContext.argtypes = (DWORD, c_char_p, DWORD) +CertCreateCertificateContext.restype = PCERT_CONTEXT +CertCreateCertificateContext.errcheck = _handle_win_error + +CertGetCertificateChain = wincrypt.CertGetCertificateChain +CertGetCertificateChain.argtypes = ( + HCERTCHAINENGINE, + PCERT_CONTEXT, + LPFILETIME, + HCERTSTORE, + PCERT_CHAIN_PARA, + DWORD, + c_void_p, + PCCERT_CHAIN_CONTEXT, +) +CertGetCertificateChain.restype = BOOL +CertGetCertificateChain.errcheck = _handle_win_error + +CertVerifyCertificateChainPolicy = wincrypt.CertVerifyCertificateChainPolicy +CertVerifyCertificateChainPolicy.argtypes = ( + c_ulong, + PCERT_CHAIN_CONTEXT, + PCERT_CHAIN_POLICY_PARA, + PCERT_CHAIN_POLICY_STATUS, +) +CertVerifyCertificateChainPolicy.restype = BOOL + +CertCloseStore = wincrypt.CertCloseStore +CertCloseStore.argtypes = (HCERTSTORE, DWORD) +CertCloseStore.restype = BOOL +CertCloseStore.errcheck = _handle_win_error + +CertFreeCertificateChain = wincrypt.CertFreeCertificateChain +CertFreeCertificateChain.argtypes = (PCERT_CHAIN_CONTEXT,) + +CertFreeCertificateContext = wincrypt.CertFreeCertificateContext +CertFreeCertificateContext.argtypes = (PCERT_CONTEXT,) + +CertFreeCertificateChainEngine = wincrypt.CertFreeCertificateChainEngine +CertFreeCertificateChainEngine.argtypes = (HCERTCHAINENGINE,) + +FormatMessageW = kernel32.FormatMessageW +FormatMessageW.argtypes = ( + DWORD, + LPCVOID, + DWORD, + DWORD, + LPWSTR, + DWORD, + c_void_p, +) +FormatMessageW.restype = DWORD + + +def _verify_peercerts_impl( + ssl_context: ssl.SSLContext, + cert_chain: list[bytes], + server_hostname: str | None = None, +) -> None: + """Verify the cert_chain from the server using Windows APIs.""" + + # If the peer didn't send any certificates then + # we can't do verification. Raise an error. + if not cert_chain: + raise ssl.SSLCertVerificationError("Peer sent no certificates to verify") + + pCertContext = None + hIntermediateCertStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, None, 0, None) + try: + # Add intermediate certs to an in-memory cert store + for cert_bytes in cert_chain[1:]: + CertAddEncodedCertificateToStore( + hIntermediateCertStore, + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + cert_bytes, + len(cert_bytes), + CERT_STORE_ADD_USE_EXISTING, + None, + ) + + # Cert context for leaf cert + leaf_cert = cert_chain[0] + pCertContext = CertCreateCertificateContext( + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, leaf_cert, len(leaf_cert) + ) + + # Chain params to match certs for serverAuth extended usage + cert_enhkey_usage = CERT_ENHKEY_USAGE() + cert_enhkey_usage.cUsageIdentifier = 1 + cert_enhkey_usage.rgpszUsageIdentifier = (c_char_p * 1)(OID_PKIX_KP_SERVER_AUTH) + cert_usage_match = CERT_USAGE_MATCH() + cert_usage_match.Usage = cert_enhkey_usage + chain_params = CERT_CHAIN_PARA() + chain_params.RequestedUsage = cert_usage_match + chain_params.cbSize = sizeof(chain_params) + pChainPara = pointer(chain_params) + + if ssl_context.verify_flags & ssl.VERIFY_CRL_CHECK_CHAIN: + chain_flags = CERT_CHAIN_REVOCATION_CHECK_CHAIN + elif ssl_context.verify_flags & ssl.VERIFY_CRL_CHECK_LEAF: + chain_flags = CERT_CHAIN_REVOCATION_CHECK_END_CERT + else: + chain_flags = 0 + + try: + # First attempt to verify using the default Windows system trust roots + # (default chain engine). + _get_and_verify_cert_chain( + ssl_context, + None, + hIntermediateCertStore, + pCertContext, + pChainPara, + server_hostname, + chain_flags=chain_flags, + ) + except ssl.SSLCertVerificationError as e: + # If that fails but custom CA certs have been added + # to the SSLContext using load_verify_locations, + # try verifying using a custom chain engine + # that trusts the custom CA certs. + custom_ca_certs: list[bytes] | None = ssl_context.get_ca_certs( + binary_form=True + ) + if custom_ca_certs: + try: + _verify_using_custom_ca_certs( + ssl_context, + custom_ca_certs, + hIntermediateCertStore, + pCertContext, + pChainPara, + server_hostname, + chain_flags=chain_flags, + ) + # Raise the original error, not the new error. + except ssl.SSLCertVerificationError: + raise e from None + else: + raise + finally: + CertCloseStore(hIntermediateCertStore, 0) + if pCertContext: + CertFreeCertificateContext(pCertContext) + + +def _get_and_verify_cert_chain( + ssl_context: ssl.SSLContext, + hChainEngine: HCERTCHAINENGINE | None, + hIntermediateCertStore: HCERTSTORE, + pPeerCertContext: c_void_p, + pChainPara: PCERT_CHAIN_PARA, # type: ignore[valid-type] + server_hostname: str | None, + chain_flags: int, +) -> None: + ppChainContext = None + try: + # Get cert chain + ppChainContext = pointer(PCERT_CHAIN_CONTEXT()) + CertGetCertificateChain( + hChainEngine, # chain engine + pPeerCertContext, # leaf cert context + None, # current system time + hIntermediateCertStore, # additional in-memory cert store + pChainPara, # chain-building parameters + chain_flags, + None, # reserved + ppChainContext, # the resulting chain context + ) + pChainContext = ppChainContext.contents + + # Verify cert chain + ssl_extra_cert_chain_policy_para = SSL_EXTRA_CERT_CHAIN_POLICY_PARA() + ssl_extra_cert_chain_policy_para.cbSize = sizeof( + ssl_extra_cert_chain_policy_para + ) + ssl_extra_cert_chain_policy_para.dwAuthType = AUTHTYPE_SERVER + ssl_extra_cert_chain_policy_para.fdwChecks = 0 + if ssl_context.check_hostname is False: + ssl_extra_cert_chain_policy_para.fdwChecks = ( + SECURITY_FLAG_IGNORE_CERT_CN_INVALID + ) + if server_hostname: + ssl_extra_cert_chain_policy_para.pwszServerName = c_wchar_p(server_hostname) + + chain_policy = CERT_CHAIN_POLICY_PARA() + chain_policy.pvExtraPolicyPara = cast( + pointer(ssl_extra_cert_chain_policy_para), c_void_p + ) + if ssl_context.verify_mode == ssl.CERT_NONE: + chain_policy.dwFlags |= CERT_CHAIN_POLICY_VERIFY_MODE_NONE_FLAGS + chain_policy.cbSize = sizeof(chain_policy) + + pPolicyPara = pointer(chain_policy) + policy_status = CERT_CHAIN_POLICY_STATUS() + policy_status.cbSize = sizeof(policy_status) + pPolicyStatus = pointer(policy_status) + CertVerifyCertificateChainPolicy( + CERT_CHAIN_POLICY_SSL, + pChainContext, + pPolicyPara, + pPolicyStatus, + ) + + # Check status + error_code = policy_status.dwError + if error_code: + # Try getting a human readable message for an error code. + error_message_buf = create_unicode_buffer(1024) + error_message_chars = FormatMessageW( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + None, + error_code, + 0, + error_message_buf, + sizeof(error_message_buf), + None, + ) + + # See if we received a message for the error, + # otherwise we use a generic error with the + # error code and hope that it's search-able. + if error_message_chars <= 0: + error_message = f"Certificate chain policy error {error_code:#x} [{policy_status.lElementIndex}]" + else: + error_message = error_message_buf.value.strip() + + err = ssl.SSLCertVerificationError(error_message) + err.verify_message = error_message + err.verify_code = error_code + raise err from None + finally: + if ppChainContext: + CertFreeCertificateChain(ppChainContext.contents) + + +def _verify_using_custom_ca_certs( + ssl_context: ssl.SSLContext, + custom_ca_certs: list[bytes], + hIntermediateCertStore: HCERTSTORE, + pPeerCertContext: c_void_p, + pChainPara: PCERT_CHAIN_PARA, # type: ignore[valid-type] + server_hostname: str | None, + chain_flags: int, +) -> None: + hChainEngine = None + hRootCertStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, None, 0, None) + try: + # Add custom CA certs to an in-memory cert store + for cert_bytes in custom_ca_certs: + CertAddEncodedCertificateToStore( + hRootCertStore, + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + cert_bytes, + len(cert_bytes), + CERT_STORE_ADD_USE_EXISTING, + None, + ) + + # Create a custom cert chain engine which exclusively trusts + # certs from our hRootCertStore + cert_chain_engine_config = CERT_CHAIN_ENGINE_CONFIG() + cert_chain_engine_config.cbSize = sizeof(cert_chain_engine_config) + cert_chain_engine_config.hExclusiveRoot = hRootCertStore + pConfig = pointer(cert_chain_engine_config) + phChainEngine = pointer(HCERTCHAINENGINE()) + CertCreateCertificateChainEngine( + pConfig, + phChainEngine, + ) + hChainEngine = phChainEngine.contents + + # Get and verify a cert chain using the custom chain engine + _get_and_verify_cert_chain( + ssl_context, + hChainEngine, + hIntermediateCertStore, + pPeerCertContext, + pChainPara, + server_hostname, + chain_flags, + ) + finally: + if hChainEngine: + CertFreeCertificateChainEngine(hChainEngine) + CertCloseStore(hRootCertStore, 0) + + +@contextlib.contextmanager +def _configure_context(ctx: ssl.SSLContext) -> typing.Iterator[None]: + check_hostname = ctx.check_hostname + verify_mode = ctx.verify_mode + ctx.check_hostname = False + _set_ssl_context_verify_mode(ctx, ssl.CERT_NONE) + try: + yield + finally: + ctx.check_hostname = check_hostname + _set_ssl_context_verify_mode(ctx, verify_mode) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/truststore/py.typed b/backend/.venv/Lib/site-packages/pip/_vendor/truststore/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/typing_extensions.py b/backend/.venv/Lib/site-packages/pip/_vendor/typing_extensions.py new file mode 100644 index 0000000..e429384 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/typing_extensions.py @@ -0,0 +1,3641 @@ +import abc +import collections +import collections.abc +import contextlib +import functools +import inspect +import operator +import sys +import types as _types +import typing +import warnings + +__all__ = [ + # Super-special typing primitives. + 'Any', + 'ClassVar', + 'Concatenate', + 'Final', + 'LiteralString', + 'ParamSpec', + 'ParamSpecArgs', + 'ParamSpecKwargs', + 'Self', + 'Type', + 'TypeVar', + 'TypeVarTuple', + 'Unpack', + + # ABCs (from collections.abc). + 'Awaitable', + 'AsyncIterator', + 'AsyncIterable', + 'Coroutine', + 'AsyncGenerator', + 'AsyncContextManager', + 'Buffer', + 'ChainMap', + + # Concrete collection types. + 'ContextManager', + 'Counter', + 'Deque', + 'DefaultDict', + 'NamedTuple', + 'OrderedDict', + 'TypedDict', + + # Structural checks, a.k.a. protocols. + 'SupportsAbs', + 'SupportsBytes', + 'SupportsComplex', + 'SupportsFloat', + 'SupportsIndex', + 'SupportsInt', + 'SupportsRound', + + # One-off things. + 'Annotated', + 'assert_never', + 'assert_type', + 'clear_overloads', + 'dataclass_transform', + 'deprecated', + 'Doc', + 'get_overloads', + 'final', + 'get_args', + 'get_origin', + 'get_original_bases', + 'get_protocol_members', + 'get_type_hints', + 'IntVar', + 'is_protocol', + 'is_typeddict', + 'Literal', + 'NewType', + 'overload', + 'override', + 'Protocol', + 'reveal_type', + 'runtime', + 'runtime_checkable', + 'Text', + 'TypeAlias', + 'TypeAliasType', + 'TypeGuard', + 'TypeIs', + 'TYPE_CHECKING', + 'Never', + 'NoReturn', + 'ReadOnly', + 'Required', + 'NotRequired', + + # Pure aliases, have always been in typing + 'AbstractSet', + 'AnyStr', + 'BinaryIO', + 'Callable', + 'Collection', + 'Container', + 'Dict', + 'ForwardRef', + 'FrozenSet', + 'Generator', + 'Generic', + 'Hashable', + 'IO', + 'ItemsView', + 'Iterable', + 'Iterator', + 'KeysView', + 'List', + 'Mapping', + 'MappingView', + 'Match', + 'MutableMapping', + 'MutableSequence', + 'MutableSet', + 'NoDefault', + 'Optional', + 'Pattern', + 'Reversible', + 'Sequence', + 'Set', + 'Sized', + 'TextIO', + 'Tuple', + 'Union', + 'ValuesView', + 'cast', + 'no_type_check', + 'no_type_check_decorator', +] + +# for backward compatibility +PEP_560 = True +GenericMeta = type +_PEP_696_IMPLEMENTED = sys.version_info >= (3, 13, 0, "beta") + +# The functions below are modified copies of typing internal helpers. +# They are needed by _ProtocolMeta and they provide support for PEP 646. + + +class _Sentinel: + def __repr__(self): + return "" + + +_marker = _Sentinel() + + +if sys.version_info >= (3, 10): + def _should_collect_from_parameters(t): + return isinstance( + t, (typing._GenericAlias, _types.GenericAlias, _types.UnionType) + ) +elif sys.version_info >= (3, 9): + def _should_collect_from_parameters(t): + return isinstance(t, (typing._GenericAlias, _types.GenericAlias)) +else: + def _should_collect_from_parameters(t): + return isinstance(t, typing._GenericAlias) and not t._special + + +NoReturn = typing.NoReturn + +# Some unconstrained type variables. These are used by the container types. +# (These are not for export.) +T = typing.TypeVar('T') # Any type. +KT = typing.TypeVar('KT') # Key type. +VT = typing.TypeVar('VT') # Value type. +T_co = typing.TypeVar('T_co', covariant=True) # Any type covariant containers. +T_contra = typing.TypeVar('T_contra', contravariant=True) # Ditto contravariant. + + +if sys.version_info >= (3, 11): + from typing import Any +else: + + class _AnyMeta(type): + def __instancecheck__(self, obj): + if self is Any: + raise TypeError("typing_extensions.Any cannot be used with isinstance()") + return super().__instancecheck__(obj) + + def __repr__(self): + if self is Any: + return "typing_extensions.Any" + return super().__repr__() + + class Any(metaclass=_AnyMeta): + """Special type indicating an unconstrained type. + - Any is compatible with every type. + - Any assumed to have all methods. + - All values assumed to be instances of Any. + Note that all the above statements are true from the point of view of + static type checkers. At runtime, Any should not be used with instance + checks. + """ + def __new__(cls, *args, **kwargs): + if cls is Any: + raise TypeError("Any cannot be instantiated") + return super().__new__(cls, *args, **kwargs) + + +ClassVar = typing.ClassVar + + +class _ExtensionsSpecialForm(typing._SpecialForm, _root=True): + def __repr__(self): + return 'typing_extensions.' + self._name + + +Final = typing.Final + +if sys.version_info >= (3, 11): + final = typing.final +else: + # @final exists in 3.8+, but we backport it for all versions + # before 3.11 to keep support for the __final__ attribute. + # See https://bugs.python.org/issue46342 + def final(f): + """This decorator can be used to indicate to type checkers that + the decorated method cannot be overridden, and decorated class + cannot be subclassed. For example: + + class Base: + @final + def done(self) -> None: + ... + class Sub(Base): + def done(self) -> None: # Error reported by type checker + ... + @final + class Leaf: + ... + class Other(Leaf): # Error reported by type checker + ... + + There is no runtime checking of these properties. The decorator + sets the ``__final__`` attribute to ``True`` on the decorated object + to allow runtime introspection. + """ + try: + f.__final__ = True + except (AttributeError, TypeError): + # Skip the attribute silently if it is not writable. + # AttributeError happens if the object has __slots__ or a + # read-only property, TypeError if it's a builtin class. + pass + return f + + +def IntVar(name): + return typing.TypeVar(name) + + +# A Literal bug was fixed in 3.11.0, 3.10.1 and 3.9.8 +if sys.version_info >= (3, 10, 1): + Literal = typing.Literal +else: + def _flatten_literal_params(parameters): + """An internal helper for Literal creation: flatten Literals among parameters""" + params = [] + for p in parameters: + if isinstance(p, _LiteralGenericAlias): + params.extend(p.__args__) + else: + params.append(p) + return tuple(params) + + def _value_and_type_iter(params): + for p in params: + yield p, type(p) + + class _LiteralGenericAlias(typing._GenericAlias, _root=True): + def __eq__(self, other): + if not isinstance(other, _LiteralGenericAlias): + return NotImplemented + these_args_deduped = set(_value_and_type_iter(self.__args__)) + other_args_deduped = set(_value_and_type_iter(other.__args__)) + return these_args_deduped == other_args_deduped + + def __hash__(self): + return hash(frozenset(_value_and_type_iter(self.__args__))) + + class _LiteralForm(_ExtensionsSpecialForm, _root=True): + def __init__(self, doc: str): + self._name = 'Literal' + self._doc = self.__doc__ = doc + + def __getitem__(self, parameters): + if not isinstance(parameters, tuple): + parameters = (parameters,) + + parameters = _flatten_literal_params(parameters) + + val_type_pairs = list(_value_and_type_iter(parameters)) + try: + deduped_pairs = set(val_type_pairs) + except TypeError: + # unhashable parameters + pass + else: + # similar logic to typing._deduplicate on Python 3.9+ + if len(deduped_pairs) < len(val_type_pairs): + new_parameters = [] + for pair in val_type_pairs: + if pair in deduped_pairs: + new_parameters.append(pair[0]) + deduped_pairs.remove(pair) + assert not deduped_pairs, deduped_pairs + parameters = tuple(new_parameters) + + return _LiteralGenericAlias(self, parameters) + + Literal = _LiteralForm(doc="""\ + A type that can be used to indicate to type checkers + that the corresponding value has a value literally equivalent + to the provided parameter. For example: + + var: Literal[4] = 4 + + The type checker understands that 'var' is literally equal to + the value 4 and no other value. + + Literal[...] cannot be subclassed. There is no runtime + checking verifying that the parameter is actually a value + instead of a type.""") + + +_overload_dummy = typing._overload_dummy + + +if hasattr(typing, "get_overloads"): # 3.11+ + overload = typing.overload + get_overloads = typing.get_overloads + clear_overloads = typing.clear_overloads +else: + # {module: {qualname: {firstlineno: func}}} + _overload_registry = collections.defaultdict( + functools.partial(collections.defaultdict, dict) + ) + + def overload(func): + """Decorator for overloaded functions/methods. + + In a stub file, place two or more stub definitions for the same + function in a row, each decorated with @overload. For example: + + @overload + def utf8(value: None) -> None: ... + @overload + def utf8(value: bytes) -> bytes: ... + @overload + def utf8(value: str) -> bytes: ... + + In a non-stub file (i.e. a regular .py file), do the same but + follow it with an implementation. The implementation should *not* + be decorated with @overload. For example: + + @overload + def utf8(value: None) -> None: ... + @overload + def utf8(value: bytes) -> bytes: ... + @overload + def utf8(value: str) -> bytes: ... + def utf8(value): + # implementation goes here + + The overloads for a function can be retrieved at runtime using the + get_overloads() function. + """ + # classmethod and staticmethod + f = getattr(func, "__func__", func) + try: + _overload_registry[f.__module__][f.__qualname__][ + f.__code__.co_firstlineno + ] = func + except AttributeError: + # Not a normal function; ignore. + pass + return _overload_dummy + + def get_overloads(func): + """Return all defined overloads for *func* as a sequence.""" + # classmethod and staticmethod + f = getattr(func, "__func__", func) + if f.__module__ not in _overload_registry: + return [] + mod_dict = _overload_registry[f.__module__] + if f.__qualname__ not in mod_dict: + return [] + return list(mod_dict[f.__qualname__].values()) + + def clear_overloads(): + """Clear all overloads in the registry.""" + _overload_registry.clear() + + +# This is not a real generic class. Don't use outside annotations. +Type = typing.Type + +# Various ABCs mimicking those in collections.abc. +# A few are simply re-exported for completeness. +Awaitable = typing.Awaitable +Coroutine = typing.Coroutine +AsyncIterable = typing.AsyncIterable +AsyncIterator = typing.AsyncIterator +Deque = typing.Deque +DefaultDict = typing.DefaultDict +OrderedDict = typing.OrderedDict +Counter = typing.Counter +ChainMap = typing.ChainMap +Text = typing.Text +TYPE_CHECKING = typing.TYPE_CHECKING + + +if sys.version_info >= (3, 13, 0, "beta"): + from typing import AsyncContextManager, AsyncGenerator, ContextManager, Generator +else: + def _is_dunder(attr): + return attr.startswith('__') and attr.endswith('__') + + # Python <3.9 doesn't have typing._SpecialGenericAlias + _special_generic_alias_base = getattr( + typing, "_SpecialGenericAlias", typing._GenericAlias + ) + + class _SpecialGenericAlias(_special_generic_alias_base, _root=True): + def __init__(self, origin, nparams, *, inst=True, name=None, defaults=()): + if _special_generic_alias_base is typing._GenericAlias: + # Python <3.9 + self.__origin__ = origin + self._nparams = nparams + super().__init__(origin, nparams, special=True, inst=inst, name=name) + else: + # Python >= 3.9 + super().__init__(origin, nparams, inst=inst, name=name) + self._defaults = defaults + + def __setattr__(self, attr, val): + allowed_attrs = {'_name', '_inst', '_nparams', '_defaults'} + if _special_generic_alias_base is typing._GenericAlias: + # Python <3.9 + allowed_attrs.add("__origin__") + if _is_dunder(attr) or attr in allowed_attrs: + object.__setattr__(self, attr, val) + else: + setattr(self.__origin__, attr, val) + + @typing._tp_cache + def __getitem__(self, params): + if not isinstance(params, tuple): + params = (params,) + msg = "Parameters to generic types must be types." + params = tuple(typing._type_check(p, msg) for p in params) + if ( + self._defaults + and len(params) < self._nparams + and len(params) + len(self._defaults) >= self._nparams + ): + params = (*params, *self._defaults[len(params) - self._nparams:]) + actual_len = len(params) + + if actual_len != self._nparams: + if self._defaults: + expected = f"at least {self._nparams - len(self._defaults)}" + else: + expected = str(self._nparams) + if not self._nparams: + raise TypeError(f"{self} is not a generic class") + raise TypeError( + f"Too {'many' if actual_len > self._nparams else 'few'}" + f" arguments for {self};" + f" actual {actual_len}, expected {expected}" + ) + return self.copy_with(params) + + _NoneType = type(None) + Generator = _SpecialGenericAlias( + collections.abc.Generator, 3, defaults=(_NoneType, _NoneType) + ) + AsyncGenerator = _SpecialGenericAlias( + collections.abc.AsyncGenerator, 2, defaults=(_NoneType,) + ) + ContextManager = _SpecialGenericAlias( + contextlib.AbstractContextManager, + 2, + name="ContextManager", + defaults=(typing.Optional[bool],) + ) + AsyncContextManager = _SpecialGenericAlias( + contextlib.AbstractAsyncContextManager, + 2, + name="AsyncContextManager", + defaults=(typing.Optional[bool],) + ) + + +_PROTO_ALLOWLIST = { + 'collections.abc': [ + 'Callable', 'Awaitable', 'Iterable', 'Iterator', 'AsyncIterable', + 'Hashable', 'Sized', 'Container', 'Collection', 'Reversible', 'Buffer', + ], + 'contextlib': ['AbstractContextManager', 'AbstractAsyncContextManager'], + 'typing_extensions': ['Buffer'], +} + + +_EXCLUDED_ATTRS = frozenset(typing.EXCLUDED_ATTRIBUTES) | { + "__match_args__", "__protocol_attrs__", "__non_callable_proto_members__", + "__final__", +} + + +def _get_protocol_attrs(cls): + attrs = set() + for base in cls.__mro__[:-1]: # without object + if base.__name__ in {'Protocol', 'Generic'}: + continue + annotations = getattr(base, '__annotations__', {}) + for attr in (*base.__dict__, *annotations): + if (not attr.startswith('_abc_') and attr not in _EXCLUDED_ATTRS): + attrs.add(attr) + return attrs + + +def _caller(depth=2): + try: + return sys._getframe(depth).f_globals.get('__name__', '__main__') + except (AttributeError, ValueError): # For platforms without _getframe() + return None + + +# `__match_args__` attribute was removed from protocol members in 3.13, +# we want to backport this change to older Python versions. +if sys.version_info >= (3, 13): + Protocol = typing.Protocol +else: + def _allow_reckless_class_checks(depth=3): + """Allow instance and class checks for special stdlib modules. + The abc and functools modules indiscriminately call isinstance() and + issubclass() on the whole MRO of a user class, which may contain protocols. + """ + return _caller(depth) in {'abc', 'functools', None} + + def _no_init(self, *args, **kwargs): + if type(self)._is_protocol: + raise TypeError('Protocols cannot be instantiated') + + def _type_check_issubclass_arg_1(arg): + """Raise TypeError if `arg` is not an instance of `type` + in `issubclass(arg, )`. + + In most cases, this is verified by type.__subclasscheck__. + Checking it again unnecessarily would slow down issubclass() checks, + so, we don't perform this check unless we absolutely have to. + + For various error paths, however, + we want to ensure that *this* error message is shown to the user + where relevant, rather than a typing.py-specific error message. + """ + if not isinstance(arg, type): + # Same error message as for issubclass(1, int). + raise TypeError('issubclass() arg 1 must be a class') + + # Inheriting from typing._ProtocolMeta isn't actually desirable, + # but is necessary to allow typing.Protocol and typing_extensions.Protocol + # to mix without getting TypeErrors about "metaclass conflict" + class _ProtocolMeta(type(typing.Protocol)): + # This metaclass is somewhat unfortunate, + # but is necessary for several reasons... + # + # NOTE: DO NOT call super() in any methods in this class + # That would call the methods on typing._ProtocolMeta on Python 3.8-3.11 + # and those are slow + def __new__(mcls, name, bases, namespace, **kwargs): + if name == "Protocol" and len(bases) < 2: + pass + elif {Protocol, typing.Protocol} & set(bases): + for base in bases: + if not ( + base in {object, typing.Generic, Protocol, typing.Protocol} + or base.__name__ in _PROTO_ALLOWLIST.get(base.__module__, []) + or is_protocol(base) + ): + raise TypeError( + f"Protocols can only inherit from other protocols, " + f"got {base!r}" + ) + return abc.ABCMeta.__new__(mcls, name, bases, namespace, **kwargs) + + def __init__(cls, *args, **kwargs): + abc.ABCMeta.__init__(cls, *args, **kwargs) + if getattr(cls, "_is_protocol", False): + cls.__protocol_attrs__ = _get_protocol_attrs(cls) + + def __subclasscheck__(cls, other): + if cls is Protocol: + return type.__subclasscheck__(cls, other) + if ( + getattr(cls, '_is_protocol', False) + and not _allow_reckless_class_checks() + ): + if not getattr(cls, '_is_runtime_protocol', False): + _type_check_issubclass_arg_1(other) + raise TypeError( + "Instance and class checks can only be used with " + "@runtime_checkable protocols" + ) + if ( + # this attribute is set by @runtime_checkable: + cls.__non_callable_proto_members__ + and cls.__dict__.get("__subclasshook__") is _proto_hook + ): + _type_check_issubclass_arg_1(other) + non_method_attrs = sorted(cls.__non_callable_proto_members__) + raise TypeError( + "Protocols with non-method members don't support issubclass()." + f" Non-method members: {str(non_method_attrs)[1:-1]}." + ) + return abc.ABCMeta.__subclasscheck__(cls, other) + + def __instancecheck__(cls, instance): + # We need this method for situations where attributes are + # assigned in __init__. + if cls is Protocol: + return type.__instancecheck__(cls, instance) + if not getattr(cls, "_is_protocol", False): + # i.e., it's a concrete subclass of a protocol + return abc.ABCMeta.__instancecheck__(cls, instance) + + if ( + not getattr(cls, '_is_runtime_protocol', False) and + not _allow_reckless_class_checks() + ): + raise TypeError("Instance and class checks can only be used with" + " @runtime_checkable protocols") + + if abc.ABCMeta.__instancecheck__(cls, instance): + return True + + for attr in cls.__protocol_attrs__: + try: + val = inspect.getattr_static(instance, attr) + except AttributeError: + break + # this attribute is set by @runtime_checkable: + if val is None and attr not in cls.__non_callable_proto_members__: + break + else: + return True + + return False + + def __eq__(cls, other): + # Hack so that typing.Generic.__class_getitem__ + # treats typing_extensions.Protocol + # as equivalent to typing.Protocol + if abc.ABCMeta.__eq__(cls, other) is True: + return True + return cls is Protocol and other is typing.Protocol + + # This has to be defined, or the abc-module cache + # complains about classes with this metaclass being unhashable, + # if we define only __eq__! + def __hash__(cls) -> int: + return type.__hash__(cls) + + @classmethod + def _proto_hook(cls, other): + if not cls.__dict__.get('_is_protocol', False): + return NotImplemented + + for attr in cls.__protocol_attrs__: + for base in other.__mro__: + # Check if the members appears in the class dictionary... + if attr in base.__dict__: + if base.__dict__[attr] is None: + return NotImplemented + break + + # ...or in annotations, if it is a sub-protocol. + annotations = getattr(base, '__annotations__', {}) + if ( + isinstance(annotations, collections.abc.Mapping) + and attr in annotations + and is_protocol(other) + ): + break + else: + return NotImplemented + return True + + class Protocol(typing.Generic, metaclass=_ProtocolMeta): + __doc__ = typing.Protocol.__doc__ + __slots__ = () + _is_protocol = True + _is_runtime_protocol = False + + def __init_subclass__(cls, *args, **kwargs): + super().__init_subclass__(*args, **kwargs) + + # Determine if this is a protocol or a concrete subclass. + if not cls.__dict__.get('_is_protocol', False): + cls._is_protocol = any(b is Protocol for b in cls.__bases__) + + # Set (or override) the protocol subclass hook. + if '__subclasshook__' not in cls.__dict__: + cls.__subclasshook__ = _proto_hook + + # Prohibit instantiation for protocol classes + if cls._is_protocol and cls.__init__ is Protocol.__init__: + cls.__init__ = _no_init + + +if sys.version_info >= (3, 13): + runtime_checkable = typing.runtime_checkable +else: + def runtime_checkable(cls): + """Mark a protocol class as a runtime protocol. + + Such protocol can be used with isinstance() and issubclass(). + Raise TypeError if applied to a non-protocol class. + This allows a simple-minded structural check very similar to + one trick ponies in collections.abc such as Iterable. + + For example:: + + @runtime_checkable + class Closable(Protocol): + def close(self): ... + + assert isinstance(open('/some/file'), Closable) + + Warning: this will check only the presence of the required methods, + not their type signatures! + """ + if not issubclass(cls, typing.Generic) or not getattr(cls, '_is_protocol', False): + raise TypeError(f'@runtime_checkable can be only applied to protocol classes,' + f' got {cls!r}') + cls._is_runtime_protocol = True + + # typing.Protocol classes on <=3.11 break if we execute this block, + # because typing.Protocol classes on <=3.11 don't have a + # `__protocol_attrs__` attribute, and this block relies on the + # `__protocol_attrs__` attribute. Meanwhile, typing.Protocol classes on 3.12.2+ + # break if we *don't* execute this block, because *they* assume that all + # protocol classes have a `__non_callable_proto_members__` attribute + # (which this block sets) + if isinstance(cls, _ProtocolMeta) or sys.version_info >= (3, 12, 2): + # PEP 544 prohibits using issubclass() + # with protocols that have non-method members. + # See gh-113320 for why we compute this attribute here, + # rather than in `_ProtocolMeta.__init__` + cls.__non_callable_proto_members__ = set() + for attr in cls.__protocol_attrs__: + try: + is_callable = callable(getattr(cls, attr, None)) + except Exception as e: + raise TypeError( + f"Failed to determine whether protocol member {attr!r} " + "is a method member" + ) from e + else: + if not is_callable: + cls.__non_callable_proto_members__.add(attr) + + return cls + + +# The "runtime" alias exists for backwards compatibility. +runtime = runtime_checkable + + +# Our version of runtime-checkable protocols is faster on Python 3.8-3.11 +if sys.version_info >= (3, 12): + SupportsInt = typing.SupportsInt + SupportsFloat = typing.SupportsFloat + SupportsComplex = typing.SupportsComplex + SupportsBytes = typing.SupportsBytes + SupportsIndex = typing.SupportsIndex + SupportsAbs = typing.SupportsAbs + SupportsRound = typing.SupportsRound +else: + @runtime_checkable + class SupportsInt(Protocol): + """An ABC with one abstract method __int__.""" + __slots__ = () + + @abc.abstractmethod + def __int__(self) -> int: + pass + + @runtime_checkable + class SupportsFloat(Protocol): + """An ABC with one abstract method __float__.""" + __slots__ = () + + @abc.abstractmethod + def __float__(self) -> float: + pass + + @runtime_checkable + class SupportsComplex(Protocol): + """An ABC with one abstract method __complex__.""" + __slots__ = () + + @abc.abstractmethod + def __complex__(self) -> complex: + pass + + @runtime_checkable + class SupportsBytes(Protocol): + """An ABC with one abstract method __bytes__.""" + __slots__ = () + + @abc.abstractmethod + def __bytes__(self) -> bytes: + pass + + @runtime_checkable + class SupportsIndex(Protocol): + __slots__ = () + + @abc.abstractmethod + def __index__(self) -> int: + pass + + @runtime_checkable + class SupportsAbs(Protocol[T_co]): + """ + An ABC with one abstract method __abs__ that is covariant in its return type. + """ + __slots__ = () + + @abc.abstractmethod + def __abs__(self) -> T_co: + pass + + @runtime_checkable + class SupportsRound(Protocol[T_co]): + """ + An ABC with one abstract method __round__ that is covariant in its return type. + """ + __slots__ = () + + @abc.abstractmethod + def __round__(self, ndigits: int = 0) -> T_co: + pass + + +def _ensure_subclassable(mro_entries): + def inner(func): + if sys.implementation.name == "pypy" and sys.version_info < (3, 9): + cls_dict = { + "__call__": staticmethod(func), + "__mro_entries__": staticmethod(mro_entries) + } + t = type(func.__name__, (), cls_dict) + return functools.update_wrapper(t(), func) + else: + func.__mro_entries__ = mro_entries + return func + return inner + + +# Update this to something like >=3.13.0b1 if and when +# PEP 728 is implemented in CPython +_PEP_728_IMPLEMENTED = False + +if _PEP_728_IMPLEMENTED: + # The standard library TypedDict in Python 3.8 does not store runtime information + # about which (if any) keys are optional. See https://bugs.python.org/issue38834 + # The standard library TypedDict in Python 3.9.0/1 does not honour the "total" + # keyword with old-style TypedDict(). See https://bugs.python.org/issue42059 + # The standard library TypedDict below Python 3.11 does not store runtime + # information about optional and required keys when using Required or NotRequired. + # Generic TypedDicts are also impossible using typing.TypedDict on Python <3.11. + # Aaaand on 3.12 we add __orig_bases__ to TypedDict + # to enable better runtime introspection. + # On 3.13 we deprecate some odd ways of creating TypedDicts. + # Also on 3.13, PEP 705 adds the ReadOnly[] qualifier. + # PEP 728 (still pending) makes more changes. + TypedDict = typing.TypedDict + _TypedDictMeta = typing._TypedDictMeta + is_typeddict = typing.is_typeddict +else: + # 3.10.0 and later + _TAKES_MODULE = "module" in inspect.signature(typing._type_check).parameters + + def _get_typeddict_qualifiers(annotation_type): + while True: + annotation_origin = get_origin(annotation_type) + if annotation_origin is Annotated: + annotation_args = get_args(annotation_type) + if annotation_args: + annotation_type = annotation_args[0] + else: + break + elif annotation_origin is Required: + yield Required + annotation_type, = get_args(annotation_type) + elif annotation_origin is NotRequired: + yield NotRequired + annotation_type, = get_args(annotation_type) + elif annotation_origin is ReadOnly: + yield ReadOnly + annotation_type, = get_args(annotation_type) + else: + break + + class _TypedDictMeta(type): + def __new__(cls, name, bases, ns, *, total=True, closed=False): + """Create new typed dict class object. + + This method is called when TypedDict is subclassed, + or when TypedDict is instantiated. This way + TypedDict supports all three syntax forms described in its docstring. + Subclasses and instances of TypedDict return actual dictionaries. + """ + for base in bases: + if type(base) is not _TypedDictMeta and base is not typing.Generic: + raise TypeError('cannot inherit from both a TypedDict type ' + 'and a non-TypedDict base class') + + if any(issubclass(b, typing.Generic) for b in bases): + generic_base = (typing.Generic,) + else: + generic_base = () + + # typing.py generally doesn't let you inherit from plain Generic, unless + # the name of the class happens to be "Protocol" + tp_dict = type.__new__(_TypedDictMeta, "Protocol", (*generic_base, dict), ns) + tp_dict.__name__ = name + if tp_dict.__qualname__ == "Protocol": + tp_dict.__qualname__ = name + + if not hasattr(tp_dict, '__orig_bases__'): + tp_dict.__orig_bases__ = bases + + annotations = {} + if "__annotations__" in ns: + own_annotations = ns["__annotations__"] + elif "__annotate__" in ns: + # TODO: Use inspect.VALUE here, and make the annotations lazily evaluated + own_annotations = ns["__annotate__"](1) + else: + own_annotations = {} + msg = "TypedDict('Name', {f0: t0, f1: t1, ...}); each t must be a type" + if _TAKES_MODULE: + own_annotations = { + n: typing._type_check(tp, msg, module=tp_dict.__module__) + for n, tp in own_annotations.items() + } + else: + own_annotations = { + n: typing._type_check(tp, msg) + for n, tp in own_annotations.items() + } + required_keys = set() + optional_keys = set() + readonly_keys = set() + mutable_keys = set() + extra_items_type = None + + for base in bases: + base_dict = base.__dict__ + + annotations.update(base_dict.get('__annotations__', {})) + required_keys.update(base_dict.get('__required_keys__', ())) + optional_keys.update(base_dict.get('__optional_keys__', ())) + readonly_keys.update(base_dict.get('__readonly_keys__', ())) + mutable_keys.update(base_dict.get('__mutable_keys__', ())) + base_extra_items_type = base_dict.get('__extra_items__', None) + if base_extra_items_type is not None: + extra_items_type = base_extra_items_type + + if closed and extra_items_type is None: + extra_items_type = Never + if closed and "__extra_items__" in own_annotations: + annotation_type = own_annotations.pop("__extra_items__") + qualifiers = set(_get_typeddict_qualifiers(annotation_type)) + if Required in qualifiers: + raise TypeError( + "Special key __extra_items__ does not support " + "Required" + ) + if NotRequired in qualifiers: + raise TypeError( + "Special key __extra_items__ does not support " + "NotRequired" + ) + extra_items_type = annotation_type + + annotations.update(own_annotations) + for annotation_key, annotation_type in own_annotations.items(): + qualifiers = set(_get_typeddict_qualifiers(annotation_type)) + + if Required in qualifiers: + required_keys.add(annotation_key) + elif NotRequired in qualifiers: + optional_keys.add(annotation_key) + elif total: + required_keys.add(annotation_key) + else: + optional_keys.add(annotation_key) + if ReadOnly in qualifiers: + mutable_keys.discard(annotation_key) + readonly_keys.add(annotation_key) + else: + mutable_keys.add(annotation_key) + readonly_keys.discard(annotation_key) + + tp_dict.__annotations__ = annotations + tp_dict.__required_keys__ = frozenset(required_keys) + tp_dict.__optional_keys__ = frozenset(optional_keys) + tp_dict.__readonly_keys__ = frozenset(readonly_keys) + tp_dict.__mutable_keys__ = frozenset(mutable_keys) + if not hasattr(tp_dict, '__total__'): + tp_dict.__total__ = total + tp_dict.__closed__ = closed + tp_dict.__extra_items__ = extra_items_type + return tp_dict + + __call__ = dict # static method + + def __subclasscheck__(cls, other): + # Typed dicts are only for static structural subtyping. + raise TypeError('TypedDict does not support instance and class checks') + + __instancecheck__ = __subclasscheck__ + + _TypedDict = type.__new__(_TypedDictMeta, 'TypedDict', (), {}) + + @_ensure_subclassable(lambda bases: (_TypedDict,)) + def TypedDict(typename, fields=_marker, /, *, total=True, closed=False, **kwargs): + """A simple typed namespace. At runtime it is equivalent to a plain dict. + + TypedDict creates a dictionary type such that a type checker will expect all + instances to have a certain set of keys, where each key is + associated with a value of a consistent type. This expectation + is not checked at runtime. + + Usage:: + + class Point2D(TypedDict): + x: int + y: int + label: str + + a: Point2D = {'x': 1, 'y': 2, 'label': 'good'} # OK + b: Point2D = {'z': 3, 'label': 'bad'} # Fails type check + + assert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first') + + The type info can be accessed via the Point2D.__annotations__ dict, and + the Point2D.__required_keys__ and Point2D.__optional_keys__ frozensets. + TypedDict supports an additional equivalent form:: + + Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str}) + + By default, all keys must be present in a TypedDict. It is possible + to override this by specifying totality:: + + class Point2D(TypedDict, total=False): + x: int + y: int + + This means that a Point2D TypedDict can have any of the keys omitted. A type + checker is only expected to support a literal False or True as the value of + the total argument. True is the default, and makes all items defined in the + class body be required. + + The Required and NotRequired special forms can also be used to mark + individual keys as being required or not required:: + + class Point2D(TypedDict): + x: int # the "x" key must always be present (Required is the default) + y: NotRequired[int] # the "y" key can be omitted + + See PEP 655 for more details on Required and NotRequired. + """ + if fields is _marker or fields is None: + if fields is _marker: + deprecated_thing = "Failing to pass a value for the 'fields' parameter" + else: + deprecated_thing = "Passing `None` as the 'fields' parameter" + + example = f"`{typename} = TypedDict({typename!r}, {{}})`" + deprecation_msg = ( + f"{deprecated_thing} is deprecated and will be disallowed in " + "Python 3.15. To create a TypedDict class with 0 fields " + "using the functional syntax, pass an empty dictionary, e.g. " + ) + example + "." + warnings.warn(deprecation_msg, DeprecationWarning, stacklevel=2) + if closed is not False and closed is not True: + kwargs["closed"] = closed + closed = False + fields = kwargs + elif kwargs: + raise TypeError("TypedDict takes either a dict or keyword arguments," + " but not both") + if kwargs: + if sys.version_info >= (3, 13): + raise TypeError("TypedDict takes no keyword arguments") + warnings.warn( + "The kwargs-based syntax for TypedDict definitions is deprecated " + "in Python 3.11, will be removed in Python 3.13, and may not be " + "understood by third-party type checkers.", + DeprecationWarning, + stacklevel=2, + ) + + ns = {'__annotations__': dict(fields)} + module = _caller() + if module is not None: + # Setting correct module is necessary to make typed dict classes pickleable. + ns['__module__'] = module + + td = _TypedDictMeta(typename, (), ns, total=total, closed=closed) + td.__orig_bases__ = (TypedDict,) + return td + + if hasattr(typing, "_TypedDictMeta"): + _TYPEDDICT_TYPES = (typing._TypedDictMeta, _TypedDictMeta) + else: + _TYPEDDICT_TYPES = (_TypedDictMeta,) + + def is_typeddict(tp): + """Check if an annotation is a TypedDict class + + For example:: + class Film(TypedDict): + title: str + year: int + + is_typeddict(Film) # => True + is_typeddict(Union[list, str]) # => False + """ + # On 3.8, this would otherwise return True + if hasattr(typing, "TypedDict") and tp is typing.TypedDict: + return False + return isinstance(tp, _TYPEDDICT_TYPES) + + +if hasattr(typing, "assert_type"): + assert_type = typing.assert_type + +else: + def assert_type(val, typ, /): + """Assert (to the type checker) that the value is of the given type. + + When the type checker encounters a call to assert_type(), it + emits an error if the value is not of the specified type:: + + def greet(name: str) -> None: + assert_type(name, str) # ok + assert_type(name, int) # type checker error + + At runtime this returns the first argument unchanged and otherwise + does nothing. + """ + return val + + +if hasattr(typing, "ReadOnly"): # 3.13+ + get_type_hints = typing.get_type_hints +else: # <=3.13 + # replaces _strip_annotations() + def _strip_extras(t): + """Strips Annotated, Required and NotRequired from a given type.""" + if isinstance(t, _AnnotatedAlias): + return _strip_extras(t.__origin__) + if hasattr(t, "__origin__") and t.__origin__ in (Required, NotRequired, ReadOnly): + return _strip_extras(t.__args__[0]) + if isinstance(t, typing._GenericAlias): + stripped_args = tuple(_strip_extras(a) for a in t.__args__) + if stripped_args == t.__args__: + return t + return t.copy_with(stripped_args) + if hasattr(_types, "GenericAlias") and isinstance(t, _types.GenericAlias): + stripped_args = tuple(_strip_extras(a) for a in t.__args__) + if stripped_args == t.__args__: + return t + return _types.GenericAlias(t.__origin__, stripped_args) + if hasattr(_types, "UnionType") and isinstance(t, _types.UnionType): + stripped_args = tuple(_strip_extras(a) for a in t.__args__) + if stripped_args == t.__args__: + return t + return functools.reduce(operator.or_, stripped_args) + + return t + + def get_type_hints(obj, globalns=None, localns=None, include_extras=False): + """Return type hints for an object. + + This is often the same as obj.__annotations__, but it handles + forward references encoded as string literals, adds Optional[t] if a + default value equal to None is set and recursively replaces all + 'Annotated[T, ...]', 'Required[T]' or 'NotRequired[T]' with 'T' + (unless 'include_extras=True'). + + The argument may be a module, class, method, or function. The annotations + are returned as a dictionary. For classes, annotations include also + inherited members. + + TypeError is raised if the argument is not of a type that can contain + annotations, and an empty dictionary is returned if no annotations are + present. + + BEWARE -- the behavior of globalns and localns is counterintuitive + (unless you are familiar with how eval() and exec() work). The + search order is locals first, then globals. + + - If no dict arguments are passed, an attempt is made to use the + globals from obj (or the respective module's globals for classes), + and these are also used as the locals. If the object does not appear + to have globals, an empty dictionary is used. + + - If one dict argument is passed, it is used for both globals and + locals. + + - If two dict arguments are passed, they specify globals and + locals, respectively. + """ + if hasattr(typing, "Annotated"): # 3.9+ + hint = typing.get_type_hints( + obj, globalns=globalns, localns=localns, include_extras=True + ) + else: # 3.8 + hint = typing.get_type_hints(obj, globalns=globalns, localns=localns) + if include_extras: + return hint + return {k: _strip_extras(t) for k, t in hint.items()} + + +# Python 3.9+ has PEP 593 (Annotated) +if hasattr(typing, 'Annotated'): + Annotated = typing.Annotated + # Not exported and not a public API, but needed for get_origin() and get_args() + # to work. + _AnnotatedAlias = typing._AnnotatedAlias +# 3.8 +else: + class _AnnotatedAlias(typing._GenericAlias, _root=True): + """Runtime representation of an annotated type. + + At its core 'Annotated[t, dec1, dec2, ...]' is an alias for the type 't' + with extra annotations. The alias behaves like a normal typing alias, + instantiating is the same as instantiating the underlying type, binding + it to types is also the same. + """ + def __init__(self, origin, metadata): + if isinstance(origin, _AnnotatedAlias): + metadata = origin.__metadata__ + metadata + origin = origin.__origin__ + super().__init__(origin, origin) + self.__metadata__ = metadata + + def copy_with(self, params): + assert len(params) == 1 + new_type = params[0] + return _AnnotatedAlias(new_type, self.__metadata__) + + def __repr__(self): + return (f"typing_extensions.Annotated[{typing._type_repr(self.__origin__)}, " + f"{', '.join(repr(a) for a in self.__metadata__)}]") + + def __reduce__(self): + return operator.getitem, ( + Annotated, (self.__origin__, *self.__metadata__) + ) + + def __eq__(self, other): + if not isinstance(other, _AnnotatedAlias): + return NotImplemented + if self.__origin__ != other.__origin__: + return False + return self.__metadata__ == other.__metadata__ + + def __hash__(self): + return hash((self.__origin__, self.__metadata__)) + + class Annotated: + """Add context specific metadata to a type. + + Example: Annotated[int, runtime_check.Unsigned] indicates to the + hypothetical runtime_check module that this type is an unsigned int. + Every other consumer of this type can ignore this metadata and treat + this type as int. + + The first argument to Annotated must be a valid type (and will be in + the __origin__ field), the remaining arguments are kept as a tuple in + the __extra__ field. + + Details: + + - It's an error to call `Annotated` with less than two arguments. + - Nested Annotated are flattened:: + + Annotated[Annotated[T, Ann1, Ann2], Ann3] == Annotated[T, Ann1, Ann2, Ann3] + + - Instantiating an annotated type is equivalent to instantiating the + underlying type:: + + Annotated[C, Ann1](5) == C(5) + + - Annotated can be used as a generic type alias:: + + Optimized = Annotated[T, runtime.Optimize()] + Optimized[int] == Annotated[int, runtime.Optimize()] + + OptimizedList = Annotated[List[T], runtime.Optimize()] + OptimizedList[int] == Annotated[List[int], runtime.Optimize()] + """ + + __slots__ = () + + def __new__(cls, *args, **kwargs): + raise TypeError("Type Annotated cannot be instantiated.") + + @typing._tp_cache + def __class_getitem__(cls, params): + if not isinstance(params, tuple) or len(params) < 2: + raise TypeError("Annotated[...] should be used " + "with at least two arguments (a type and an " + "annotation).") + allowed_special_forms = (ClassVar, Final) + if get_origin(params[0]) in allowed_special_forms: + origin = params[0] + else: + msg = "Annotated[t, ...]: t must be a type." + origin = typing._type_check(params[0], msg) + metadata = tuple(params[1:]) + return _AnnotatedAlias(origin, metadata) + + def __init_subclass__(cls, *args, **kwargs): + raise TypeError( + f"Cannot subclass {cls.__module__}.Annotated" + ) + +# Python 3.8 has get_origin() and get_args() but those implementations aren't +# Annotated-aware, so we can't use those. Python 3.9's versions don't support +# ParamSpecArgs and ParamSpecKwargs, so only Python 3.10's versions will do. +if sys.version_info[:2] >= (3, 10): + get_origin = typing.get_origin + get_args = typing.get_args +# 3.8-3.9 +else: + try: + # 3.9+ + from typing import _BaseGenericAlias + except ImportError: + _BaseGenericAlias = typing._GenericAlias + try: + # 3.9+ + from typing import GenericAlias as _typing_GenericAlias + except ImportError: + _typing_GenericAlias = typing._GenericAlias + + def get_origin(tp): + """Get the unsubscripted version of a type. + + This supports generic types, Callable, Tuple, Union, Literal, Final, ClassVar + and Annotated. Return None for unsupported types. Examples:: + + get_origin(Literal[42]) is Literal + get_origin(int) is None + get_origin(ClassVar[int]) is ClassVar + get_origin(Generic) is Generic + get_origin(Generic[T]) is Generic + get_origin(Union[T, int]) is Union + get_origin(List[Tuple[T, T]][int]) == list + get_origin(P.args) is P + """ + if isinstance(tp, _AnnotatedAlias): + return Annotated + if isinstance(tp, (typing._GenericAlias, _typing_GenericAlias, _BaseGenericAlias, + ParamSpecArgs, ParamSpecKwargs)): + return tp.__origin__ + if tp is typing.Generic: + return typing.Generic + return None + + def get_args(tp): + """Get type arguments with all substitutions performed. + + For unions, basic simplifications used by Union constructor are performed. + Examples:: + get_args(Dict[str, int]) == (str, int) + get_args(int) == () + get_args(Union[int, Union[T, int], str][int]) == (int, str) + get_args(Union[int, Tuple[T, int]][str]) == (int, Tuple[str, int]) + get_args(Callable[[], T][int]) == ([], int) + """ + if isinstance(tp, _AnnotatedAlias): + return (tp.__origin__, *tp.__metadata__) + if isinstance(tp, (typing._GenericAlias, _typing_GenericAlias)): + if getattr(tp, "_special", False): + return () + res = tp.__args__ + if get_origin(tp) is collections.abc.Callable and res[0] is not Ellipsis: + res = (list(res[:-1]), res[-1]) + return res + return () + + +# 3.10+ +if hasattr(typing, 'TypeAlias'): + TypeAlias = typing.TypeAlias +# 3.9 +elif sys.version_info[:2] >= (3, 9): + @_ExtensionsSpecialForm + def TypeAlias(self, parameters): + """Special marker indicating that an assignment should + be recognized as a proper type alias definition by type + checkers. + + For example:: + + Predicate: TypeAlias = Callable[..., bool] + + It's invalid when used anywhere except as in the example above. + """ + raise TypeError(f"{self} is not subscriptable") +# 3.8 +else: + TypeAlias = _ExtensionsSpecialForm( + 'TypeAlias', + doc="""Special marker indicating that an assignment should + be recognized as a proper type alias definition by type + checkers. + + For example:: + + Predicate: TypeAlias = Callable[..., bool] + + It's invalid when used anywhere except as in the example + above.""" + ) + + +if hasattr(typing, "NoDefault"): + NoDefault = typing.NoDefault +else: + class NoDefaultTypeMeta(type): + def __setattr__(cls, attr, value): + # TypeError is consistent with the behavior of NoneType + raise TypeError( + f"cannot set {attr!r} attribute of immutable type {cls.__name__!r}" + ) + + class NoDefaultType(metaclass=NoDefaultTypeMeta): + """The type of the NoDefault singleton.""" + + __slots__ = () + + def __new__(cls): + return globals().get("NoDefault") or object.__new__(cls) + + def __repr__(self): + return "typing_extensions.NoDefault" + + def __reduce__(self): + return "NoDefault" + + NoDefault = NoDefaultType() + del NoDefaultType, NoDefaultTypeMeta + + +def _set_default(type_param, default): + type_param.has_default = lambda: default is not NoDefault + type_param.__default__ = default + + +def _set_module(typevarlike): + # for pickling: + def_mod = _caller(depth=3) + if def_mod != 'typing_extensions': + typevarlike.__module__ = def_mod + + +class _DefaultMixin: + """Mixin for TypeVarLike defaults.""" + + __slots__ = () + __init__ = _set_default + + +# Classes using this metaclass must provide a _backported_typevarlike ClassVar +class _TypeVarLikeMeta(type): + def __instancecheck__(cls, __instance: Any) -> bool: + return isinstance(__instance, cls._backported_typevarlike) + + +if _PEP_696_IMPLEMENTED: + from typing import TypeVar +else: + # Add default and infer_variance parameters from PEP 696 and 695 + class TypeVar(metaclass=_TypeVarLikeMeta): + """Type variable.""" + + _backported_typevarlike = typing.TypeVar + + def __new__(cls, name, *constraints, bound=None, + covariant=False, contravariant=False, + default=NoDefault, infer_variance=False): + if hasattr(typing, "TypeAliasType"): + # PEP 695 implemented (3.12+), can pass infer_variance to typing.TypeVar + typevar = typing.TypeVar(name, *constraints, bound=bound, + covariant=covariant, contravariant=contravariant, + infer_variance=infer_variance) + else: + typevar = typing.TypeVar(name, *constraints, bound=bound, + covariant=covariant, contravariant=contravariant) + if infer_variance and (covariant or contravariant): + raise ValueError("Variance cannot be specified with infer_variance.") + typevar.__infer_variance__ = infer_variance + + _set_default(typevar, default) + _set_module(typevar) + + def _tvar_prepare_subst(alias, args): + if ( + typevar.has_default() + and alias.__parameters__.index(typevar) == len(args) + ): + args += (typevar.__default__,) + return args + + typevar.__typing_prepare_subst__ = _tvar_prepare_subst + return typevar + + def __init_subclass__(cls) -> None: + raise TypeError(f"type '{__name__}.TypeVar' is not an acceptable base type") + + +# Python 3.10+ has PEP 612 +if hasattr(typing, 'ParamSpecArgs'): + ParamSpecArgs = typing.ParamSpecArgs + ParamSpecKwargs = typing.ParamSpecKwargs +# 3.8-3.9 +else: + class _Immutable: + """Mixin to indicate that object should not be copied.""" + __slots__ = () + + def __copy__(self): + return self + + def __deepcopy__(self, memo): + return self + + class ParamSpecArgs(_Immutable): + """The args for a ParamSpec object. + + Given a ParamSpec object P, P.args is an instance of ParamSpecArgs. + + ParamSpecArgs objects have a reference back to their ParamSpec: + + P.args.__origin__ is P + + This type is meant for runtime introspection and has no special meaning to + static type checkers. + """ + def __init__(self, origin): + self.__origin__ = origin + + def __repr__(self): + return f"{self.__origin__.__name__}.args" + + def __eq__(self, other): + if not isinstance(other, ParamSpecArgs): + return NotImplemented + return self.__origin__ == other.__origin__ + + class ParamSpecKwargs(_Immutable): + """The kwargs for a ParamSpec object. + + Given a ParamSpec object P, P.kwargs is an instance of ParamSpecKwargs. + + ParamSpecKwargs objects have a reference back to their ParamSpec: + + P.kwargs.__origin__ is P + + This type is meant for runtime introspection and has no special meaning to + static type checkers. + """ + def __init__(self, origin): + self.__origin__ = origin + + def __repr__(self): + return f"{self.__origin__.__name__}.kwargs" + + def __eq__(self, other): + if not isinstance(other, ParamSpecKwargs): + return NotImplemented + return self.__origin__ == other.__origin__ + + +if _PEP_696_IMPLEMENTED: + from typing import ParamSpec + +# 3.10+ +elif hasattr(typing, 'ParamSpec'): + + # Add default parameter - PEP 696 + class ParamSpec(metaclass=_TypeVarLikeMeta): + """Parameter specification.""" + + _backported_typevarlike = typing.ParamSpec + + def __new__(cls, name, *, bound=None, + covariant=False, contravariant=False, + infer_variance=False, default=NoDefault): + if hasattr(typing, "TypeAliasType"): + # PEP 695 implemented, can pass infer_variance to typing.TypeVar + paramspec = typing.ParamSpec(name, bound=bound, + covariant=covariant, + contravariant=contravariant, + infer_variance=infer_variance) + else: + paramspec = typing.ParamSpec(name, bound=bound, + covariant=covariant, + contravariant=contravariant) + paramspec.__infer_variance__ = infer_variance + + _set_default(paramspec, default) + _set_module(paramspec) + + def _paramspec_prepare_subst(alias, args): + params = alias.__parameters__ + i = params.index(paramspec) + if i == len(args) and paramspec.has_default(): + args = [*args, paramspec.__default__] + if i >= len(args): + raise TypeError(f"Too few arguments for {alias}") + # Special case where Z[[int, str, bool]] == Z[int, str, bool] in PEP 612. + if len(params) == 1 and not typing._is_param_expr(args[0]): + assert i == 0 + args = (args,) + # Convert lists to tuples to help other libraries cache the results. + elif isinstance(args[i], list): + args = (*args[:i], tuple(args[i]), *args[i + 1:]) + return args + + paramspec.__typing_prepare_subst__ = _paramspec_prepare_subst + return paramspec + + def __init_subclass__(cls) -> None: + raise TypeError(f"type '{__name__}.ParamSpec' is not an acceptable base type") + +# 3.8-3.9 +else: + + # Inherits from list as a workaround for Callable checks in Python < 3.9.2. + class ParamSpec(list, _DefaultMixin): + """Parameter specification variable. + + Usage:: + + P = ParamSpec('P') + + Parameter specification variables exist primarily for the benefit of static + type checkers. They are used to forward the parameter types of one + callable to another callable, a pattern commonly found in higher order + functions and decorators. They are only valid when used in ``Concatenate``, + or s the first argument to ``Callable``. In Python 3.10 and higher, + they are also supported in user-defined Generics at runtime. + See class Generic for more information on generic types. An + example for annotating a decorator:: + + T = TypeVar('T') + P = ParamSpec('P') + + def add_logging(f: Callable[P, T]) -> Callable[P, T]: + '''A type-safe decorator to add logging to a function.''' + def inner(*args: P.args, **kwargs: P.kwargs) -> T: + logging.info(f'{f.__name__} was called') + return f(*args, **kwargs) + return inner + + @add_logging + def add_two(x: float, y: float) -> float: + '''Add two numbers together.''' + return x + y + + Parameter specification variables defined with covariant=True or + contravariant=True can be used to declare covariant or contravariant + generic types. These keyword arguments are valid, but their actual semantics + are yet to be decided. See PEP 612 for details. + + Parameter specification variables can be introspected. e.g.: + + P.__name__ == 'T' + P.__bound__ == None + P.__covariant__ == False + P.__contravariant__ == False + + Note that only parameter specification variables defined in global scope can + be pickled. + """ + + # Trick Generic __parameters__. + __class__ = typing.TypeVar + + @property + def args(self): + return ParamSpecArgs(self) + + @property + def kwargs(self): + return ParamSpecKwargs(self) + + def __init__(self, name, *, bound=None, covariant=False, contravariant=False, + infer_variance=False, default=NoDefault): + list.__init__(self, [self]) + self.__name__ = name + self.__covariant__ = bool(covariant) + self.__contravariant__ = bool(contravariant) + self.__infer_variance__ = bool(infer_variance) + if bound: + self.__bound__ = typing._type_check(bound, 'Bound must be a type.') + else: + self.__bound__ = None + _DefaultMixin.__init__(self, default) + + # for pickling: + def_mod = _caller() + if def_mod != 'typing_extensions': + self.__module__ = def_mod + + def __repr__(self): + if self.__infer_variance__: + prefix = '' + elif self.__covariant__: + prefix = '+' + elif self.__contravariant__: + prefix = '-' + else: + prefix = '~' + return prefix + self.__name__ + + def __hash__(self): + return object.__hash__(self) + + def __eq__(self, other): + return self is other + + def __reduce__(self): + return self.__name__ + + # Hack to get typing._type_check to pass. + def __call__(self, *args, **kwargs): + pass + + +# 3.8-3.9 +if not hasattr(typing, 'Concatenate'): + # Inherits from list as a workaround for Callable checks in Python < 3.9.2. + class _ConcatenateGenericAlias(list): + + # Trick Generic into looking into this for __parameters__. + __class__ = typing._GenericAlias + + # Flag in 3.8. + _special = False + + def __init__(self, origin, args): + super().__init__(args) + self.__origin__ = origin + self.__args__ = args + + def __repr__(self): + _type_repr = typing._type_repr + return (f'{_type_repr(self.__origin__)}' + f'[{", ".join(_type_repr(arg) for arg in self.__args__)}]') + + def __hash__(self): + return hash((self.__origin__, self.__args__)) + + # Hack to get typing._type_check to pass in Generic. + def __call__(self, *args, **kwargs): + pass + + @property + def __parameters__(self): + return tuple( + tp for tp in self.__args__ if isinstance(tp, (typing.TypeVar, ParamSpec)) + ) + + +# 3.8-3.9 +@typing._tp_cache +def _concatenate_getitem(self, parameters): + if parameters == (): + raise TypeError("Cannot take a Concatenate of no types.") + if not isinstance(parameters, tuple): + parameters = (parameters,) + if not isinstance(parameters[-1], ParamSpec): + raise TypeError("The last parameter to Concatenate should be a " + "ParamSpec variable.") + msg = "Concatenate[arg, ...]: each arg must be a type." + parameters = tuple(typing._type_check(p, msg) for p in parameters) + return _ConcatenateGenericAlias(self, parameters) + + +# 3.10+ +if hasattr(typing, 'Concatenate'): + Concatenate = typing.Concatenate + _ConcatenateGenericAlias = typing._ConcatenateGenericAlias +# 3.9 +elif sys.version_info[:2] >= (3, 9): + @_ExtensionsSpecialForm + def Concatenate(self, parameters): + """Used in conjunction with ``ParamSpec`` and ``Callable`` to represent a + higher order function which adds, removes or transforms parameters of a + callable. + + For example:: + + Callable[Concatenate[int, P], int] + + See PEP 612 for detailed information. + """ + return _concatenate_getitem(self, parameters) +# 3.8 +else: + class _ConcatenateForm(_ExtensionsSpecialForm, _root=True): + def __getitem__(self, parameters): + return _concatenate_getitem(self, parameters) + + Concatenate = _ConcatenateForm( + 'Concatenate', + doc="""Used in conjunction with ``ParamSpec`` and ``Callable`` to represent a + higher order function which adds, removes or transforms parameters of a + callable. + + For example:: + + Callable[Concatenate[int, P], int] + + See PEP 612 for detailed information. + """) + +# 3.10+ +if hasattr(typing, 'TypeGuard'): + TypeGuard = typing.TypeGuard +# 3.9 +elif sys.version_info[:2] >= (3, 9): + @_ExtensionsSpecialForm + def TypeGuard(self, parameters): + """Special typing form used to annotate the return type of a user-defined + type guard function. ``TypeGuard`` only accepts a single type argument. + At runtime, functions marked this way should return a boolean. + + ``TypeGuard`` aims to benefit *type narrowing* -- a technique used by static + type checkers to determine a more precise type of an expression within a + program's code flow. Usually type narrowing is done by analyzing + conditional code flow and applying the narrowing to a block of code. The + conditional expression here is sometimes referred to as a "type guard". + + Sometimes it would be convenient to use a user-defined boolean function + as a type guard. Such a function should use ``TypeGuard[...]`` as its + return type to alert static type checkers to this intention. + + Using ``-> TypeGuard`` tells the static type checker that for a given + function: + + 1. The return value is a boolean. + 2. If the return value is ``True``, the type of its argument + is the type inside ``TypeGuard``. + + For example:: + + def is_str(val: Union[str, float]): + # "isinstance" type guard + if isinstance(val, str): + # Type of ``val`` is narrowed to ``str`` + ... + else: + # Else, type of ``val`` is narrowed to ``float``. + ... + + Strict type narrowing is not enforced -- ``TypeB`` need not be a narrower + form of ``TypeA`` (it can even be a wider form) and this may lead to + type-unsafe results. The main reason is to allow for things like + narrowing ``List[object]`` to ``List[str]`` even though the latter is not + a subtype of the former, since ``List`` is invariant. The responsibility of + writing type-safe type guards is left to the user. + + ``TypeGuard`` also works with type variables. For more information, see + PEP 647 (User-Defined Type Guards). + """ + item = typing._type_check(parameters, f'{self} accepts only a single type.') + return typing._GenericAlias(self, (item,)) +# 3.8 +else: + class _TypeGuardForm(_ExtensionsSpecialForm, _root=True): + def __getitem__(self, parameters): + item = typing._type_check(parameters, + f'{self._name} accepts only a single type') + return typing._GenericAlias(self, (item,)) + + TypeGuard = _TypeGuardForm( + 'TypeGuard', + doc="""Special typing form used to annotate the return type of a user-defined + type guard function. ``TypeGuard`` only accepts a single type argument. + At runtime, functions marked this way should return a boolean. + + ``TypeGuard`` aims to benefit *type narrowing* -- a technique used by static + type checkers to determine a more precise type of an expression within a + program's code flow. Usually type narrowing is done by analyzing + conditional code flow and applying the narrowing to a block of code. The + conditional expression here is sometimes referred to as a "type guard". + + Sometimes it would be convenient to use a user-defined boolean function + as a type guard. Such a function should use ``TypeGuard[...]`` as its + return type to alert static type checkers to this intention. + + Using ``-> TypeGuard`` tells the static type checker that for a given + function: + + 1. The return value is a boolean. + 2. If the return value is ``True``, the type of its argument + is the type inside ``TypeGuard``. + + For example:: + + def is_str(val: Union[str, float]): + # "isinstance" type guard + if isinstance(val, str): + # Type of ``val`` is narrowed to ``str`` + ... + else: + # Else, type of ``val`` is narrowed to ``float``. + ... + + Strict type narrowing is not enforced -- ``TypeB`` need not be a narrower + form of ``TypeA`` (it can even be a wider form) and this may lead to + type-unsafe results. The main reason is to allow for things like + narrowing ``List[object]`` to ``List[str]`` even though the latter is not + a subtype of the former, since ``List`` is invariant. The responsibility of + writing type-safe type guards is left to the user. + + ``TypeGuard`` also works with type variables. For more information, see + PEP 647 (User-Defined Type Guards). + """) + +# 3.13+ +if hasattr(typing, 'TypeIs'): + TypeIs = typing.TypeIs +# 3.9 +elif sys.version_info[:2] >= (3, 9): + @_ExtensionsSpecialForm + def TypeIs(self, parameters): + """Special typing form used to annotate the return type of a user-defined + type narrower function. ``TypeIs`` only accepts a single type argument. + At runtime, functions marked this way should return a boolean. + + ``TypeIs`` aims to benefit *type narrowing* -- a technique used by static + type checkers to determine a more precise type of an expression within a + program's code flow. Usually type narrowing is done by analyzing + conditional code flow and applying the narrowing to a block of code. The + conditional expression here is sometimes referred to as a "type guard". + + Sometimes it would be convenient to use a user-defined boolean function + as a type guard. Such a function should use ``TypeIs[...]`` as its + return type to alert static type checkers to this intention. + + Using ``-> TypeIs`` tells the static type checker that for a given + function: + + 1. The return value is a boolean. + 2. If the return value is ``True``, the type of its argument + is the intersection of the type inside ``TypeGuard`` and the argument's + previously known type. + + For example:: + + def is_awaitable(val: object) -> TypeIs[Awaitable[Any]]: + return hasattr(val, '__await__') + + def f(val: Union[int, Awaitable[int]]) -> int: + if is_awaitable(val): + assert_type(val, Awaitable[int]) + else: + assert_type(val, int) + + ``TypeIs`` also works with type variables. For more information, see + PEP 742 (Narrowing types with TypeIs). + """ + item = typing._type_check(parameters, f'{self} accepts only a single type.') + return typing._GenericAlias(self, (item,)) +# 3.8 +else: + class _TypeIsForm(_ExtensionsSpecialForm, _root=True): + def __getitem__(self, parameters): + item = typing._type_check(parameters, + f'{self._name} accepts only a single type') + return typing._GenericAlias(self, (item,)) + + TypeIs = _TypeIsForm( + 'TypeIs', + doc="""Special typing form used to annotate the return type of a user-defined + type narrower function. ``TypeIs`` only accepts a single type argument. + At runtime, functions marked this way should return a boolean. + + ``TypeIs`` aims to benefit *type narrowing* -- a technique used by static + type checkers to determine a more precise type of an expression within a + program's code flow. Usually type narrowing is done by analyzing + conditional code flow and applying the narrowing to a block of code. The + conditional expression here is sometimes referred to as a "type guard". + + Sometimes it would be convenient to use a user-defined boolean function + as a type guard. Such a function should use ``TypeIs[...]`` as its + return type to alert static type checkers to this intention. + + Using ``-> TypeIs`` tells the static type checker that for a given + function: + + 1. The return value is a boolean. + 2. If the return value is ``True``, the type of its argument + is the intersection of the type inside ``TypeGuard`` and the argument's + previously known type. + + For example:: + + def is_awaitable(val: object) -> TypeIs[Awaitable[Any]]: + return hasattr(val, '__await__') + + def f(val: Union[int, Awaitable[int]]) -> int: + if is_awaitable(val): + assert_type(val, Awaitable[int]) + else: + assert_type(val, int) + + ``TypeIs`` also works with type variables. For more information, see + PEP 742 (Narrowing types with TypeIs). + """) + + +# Vendored from cpython typing._SpecialFrom +class _SpecialForm(typing._Final, _root=True): + __slots__ = ('_name', '__doc__', '_getitem') + + def __init__(self, getitem): + self._getitem = getitem + self._name = getitem.__name__ + self.__doc__ = getitem.__doc__ + + def __getattr__(self, item): + if item in {'__name__', '__qualname__'}: + return self._name + + raise AttributeError(item) + + def __mro_entries__(self, bases): + raise TypeError(f"Cannot subclass {self!r}") + + def __repr__(self): + return f'typing_extensions.{self._name}' + + def __reduce__(self): + return self._name + + def __call__(self, *args, **kwds): + raise TypeError(f"Cannot instantiate {self!r}") + + def __or__(self, other): + return typing.Union[self, other] + + def __ror__(self, other): + return typing.Union[other, self] + + def __instancecheck__(self, obj): + raise TypeError(f"{self} cannot be used with isinstance()") + + def __subclasscheck__(self, cls): + raise TypeError(f"{self} cannot be used with issubclass()") + + @typing._tp_cache + def __getitem__(self, parameters): + return self._getitem(self, parameters) + + +if hasattr(typing, "LiteralString"): # 3.11+ + LiteralString = typing.LiteralString +else: + @_SpecialForm + def LiteralString(self, params): + """Represents an arbitrary literal string. + + Example:: + + from pip._vendor.typing_extensions import LiteralString + + def query(sql: LiteralString) -> ...: + ... + + query("SELECT * FROM table") # ok + query(f"SELECT * FROM {input()}") # not ok + + See PEP 675 for details. + + """ + raise TypeError(f"{self} is not subscriptable") + + +if hasattr(typing, "Self"): # 3.11+ + Self = typing.Self +else: + @_SpecialForm + def Self(self, params): + """Used to spell the type of "self" in classes. + + Example:: + + from typing import Self + + class ReturnsSelf: + def parse(self, data: bytes) -> Self: + ... + return self + + """ + + raise TypeError(f"{self} is not subscriptable") + + +if hasattr(typing, "Never"): # 3.11+ + Never = typing.Never +else: + @_SpecialForm + def Never(self, params): + """The bottom type, a type that has no members. + + This can be used to define a function that should never be + called, or a function that never returns:: + + from pip._vendor.typing_extensions import Never + + def never_call_me(arg: Never) -> None: + pass + + def int_or_str(arg: int | str) -> None: + never_call_me(arg) # type checker error + match arg: + case int(): + print("It's an int") + case str(): + print("It's a str") + case _: + never_call_me(arg) # ok, arg is of type Never + + """ + + raise TypeError(f"{self} is not subscriptable") + + +if hasattr(typing, 'Required'): # 3.11+ + Required = typing.Required + NotRequired = typing.NotRequired +elif sys.version_info[:2] >= (3, 9): # 3.9-3.10 + @_ExtensionsSpecialForm + def Required(self, parameters): + """A special typing construct to mark a key of a total=False TypedDict + as required. For example: + + class Movie(TypedDict, total=False): + title: Required[str] + year: int + + m = Movie( + title='The Matrix', # typechecker error if key is omitted + year=1999, + ) + + There is no runtime checking that a required key is actually provided + when instantiating a related TypedDict. + """ + item = typing._type_check(parameters, f'{self._name} accepts only a single type.') + return typing._GenericAlias(self, (item,)) + + @_ExtensionsSpecialForm + def NotRequired(self, parameters): + """A special typing construct to mark a key of a TypedDict as + potentially missing. For example: + + class Movie(TypedDict): + title: str + year: NotRequired[int] + + m = Movie( + title='The Matrix', # typechecker error if key is omitted + year=1999, + ) + """ + item = typing._type_check(parameters, f'{self._name} accepts only a single type.') + return typing._GenericAlias(self, (item,)) + +else: # 3.8 + class _RequiredForm(_ExtensionsSpecialForm, _root=True): + def __getitem__(self, parameters): + item = typing._type_check(parameters, + f'{self._name} accepts only a single type.') + return typing._GenericAlias(self, (item,)) + + Required = _RequiredForm( + 'Required', + doc="""A special typing construct to mark a key of a total=False TypedDict + as required. For example: + + class Movie(TypedDict, total=False): + title: Required[str] + year: int + + m = Movie( + title='The Matrix', # typechecker error if key is omitted + year=1999, + ) + + There is no runtime checking that a required key is actually provided + when instantiating a related TypedDict. + """) + NotRequired = _RequiredForm( + 'NotRequired', + doc="""A special typing construct to mark a key of a TypedDict as + potentially missing. For example: + + class Movie(TypedDict): + title: str + year: NotRequired[int] + + m = Movie( + title='The Matrix', # typechecker error if key is omitted + year=1999, + ) + """) + + +if hasattr(typing, 'ReadOnly'): + ReadOnly = typing.ReadOnly +elif sys.version_info[:2] >= (3, 9): # 3.9-3.12 + @_ExtensionsSpecialForm + def ReadOnly(self, parameters): + """A special typing construct to mark an item of a TypedDict as read-only. + + For example: + + class Movie(TypedDict): + title: ReadOnly[str] + year: int + + def mutate_movie(m: Movie) -> None: + m["year"] = 1992 # allowed + m["title"] = "The Matrix" # typechecker error + + There is no runtime checking for this property. + """ + item = typing._type_check(parameters, f'{self._name} accepts only a single type.') + return typing._GenericAlias(self, (item,)) + +else: # 3.8 + class _ReadOnlyForm(_ExtensionsSpecialForm, _root=True): + def __getitem__(self, parameters): + item = typing._type_check(parameters, + f'{self._name} accepts only a single type.') + return typing._GenericAlias(self, (item,)) + + ReadOnly = _ReadOnlyForm( + 'ReadOnly', + doc="""A special typing construct to mark a key of a TypedDict as read-only. + + For example: + + class Movie(TypedDict): + title: ReadOnly[str] + year: int + + def mutate_movie(m: Movie) -> None: + m["year"] = 1992 # allowed + m["title"] = "The Matrix" # typechecker error + + There is no runtime checking for this propery. + """) + + +_UNPACK_DOC = """\ +Type unpack operator. + +The type unpack operator takes the child types from some container type, +such as `tuple[int, str]` or a `TypeVarTuple`, and 'pulls them out'. For +example: + + # For some generic class `Foo`: + Foo[Unpack[tuple[int, str]]] # Equivalent to Foo[int, str] + + Ts = TypeVarTuple('Ts') + # Specifies that `Bar` is generic in an arbitrary number of types. + # (Think of `Ts` as a tuple of an arbitrary number of individual + # `TypeVar`s, which the `Unpack` is 'pulling out' directly into the + # `Generic[]`.) + class Bar(Generic[Unpack[Ts]]): ... + Bar[int] # Valid + Bar[int, str] # Also valid + +From Python 3.11, this can also be done using the `*` operator: + + Foo[*tuple[int, str]] + class Bar(Generic[*Ts]): ... + +The operator can also be used along with a `TypedDict` to annotate +`**kwargs` in a function signature. For instance: + + class Movie(TypedDict): + name: str + year: int + + # This function expects two keyword arguments - *name* of type `str` and + # *year* of type `int`. + def foo(**kwargs: Unpack[Movie]): ... + +Note that there is only some runtime checking of this operator. Not +everything the runtime allows may be accepted by static type checkers. + +For more information, see PEP 646 and PEP 692. +""" + + +if sys.version_info >= (3, 12): # PEP 692 changed the repr of Unpack[] + Unpack = typing.Unpack + + def _is_unpack(obj): + return get_origin(obj) is Unpack + +elif sys.version_info[:2] >= (3, 9): # 3.9+ + class _UnpackSpecialForm(_ExtensionsSpecialForm, _root=True): + def __init__(self, getitem): + super().__init__(getitem) + self.__doc__ = _UNPACK_DOC + + class _UnpackAlias(typing._GenericAlias, _root=True): + __class__ = typing.TypeVar + + @property + def __typing_unpacked_tuple_args__(self): + assert self.__origin__ is Unpack + assert len(self.__args__) == 1 + arg, = self.__args__ + if isinstance(arg, (typing._GenericAlias, _types.GenericAlias)): + if arg.__origin__ is not tuple: + raise TypeError("Unpack[...] must be used with a tuple type") + return arg.__args__ + return None + + @_UnpackSpecialForm + def Unpack(self, parameters): + item = typing._type_check(parameters, f'{self._name} accepts only a single type.') + return _UnpackAlias(self, (item,)) + + def _is_unpack(obj): + return isinstance(obj, _UnpackAlias) + +else: # 3.8 + class _UnpackAlias(typing._GenericAlias, _root=True): + __class__ = typing.TypeVar + + class _UnpackForm(_ExtensionsSpecialForm, _root=True): + def __getitem__(self, parameters): + item = typing._type_check(parameters, + f'{self._name} accepts only a single type.') + return _UnpackAlias(self, (item,)) + + Unpack = _UnpackForm('Unpack', doc=_UNPACK_DOC) + + def _is_unpack(obj): + return isinstance(obj, _UnpackAlias) + + +if _PEP_696_IMPLEMENTED: + from typing import TypeVarTuple + +elif hasattr(typing, "TypeVarTuple"): # 3.11+ + + def _unpack_args(*args): + newargs = [] + for arg in args: + subargs = getattr(arg, '__typing_unpacked_tuple_args__', None) + if subargs is not None and not (subargs and subargs[-1] is ...): + newargs.extend(subargs) + else: + newargs.append(arg) + return newargs + + # Add default parameter - PEP 696 + class TypeVarTuple(metaclass=_TypeVarLikeMeta): + """Type variable tuple.""" + + _backported_typevarlike = typing.TypeVarTuple + + def __new__(cls, name, *, default=NoDefault): + tvt = typing.TypeVarTuple(name) + _set_default(tvt, default) + _set_module(tvt) + + def _typevartuple_prepare_subst(alias, args): + params = alias.__parameters__ + typevartuple_index = params.index(tvt) + for param in params[typevartuple_index + 1:]: + if isinstance(param, TypeVarTuple): + raise TypeError( + f"More than one TypeVarTuple parameter in {alias}" + ) + + alen = len(args) + plen = len(params) + left = typevartuple_index + right = plen - typevartuple_index - 1 + var_tuple_index = None + fillarg = None + for k, arg in enumerate(args): + if not isinstance(arg, type): + subargs = getattr(arg, '__typing_unpacked_tuple_args__', None) + if subargs and len(subargs) == 2 and subargs[-1] is ...: + if var_tuple_index is not None: + raise TypeError( + "More than one unpacked " + "arbitrary-length tuple argument" + ) + var_tuple_index = k + fillarg = subargs[0] + if var_tuple_index is not None: + left = min(left, var_tuple_index) + right = min(right, alen - var_tuple_index - 1) + elif left + right > alen: + raise TypeError(f"Too few arguments for {alias};" + f" actual {alen}, expected at least {plen - 1}") + if left == alen - right and tvt.has_default(): + replacement = _unpack_args(tvt.__default__) + else: + replacement = args[left: alen - right] + + return ( + *args[:left], + *([fillarg] * (typevartuple_index - left)), + replacement, + *([fillarg] * (plen - right - left - typevartuple_index - 1)), + *args[alen - right:], + ) + + tvt.__typing_prepare_subst__ = _typevartuple_prepare_subst + return tvt + + def __init_subclass__(self, *args, **kwds): + raise TypeError("Cannot subclass special typing classes") + +else: # <=3.10 + class TypeVarTuple(_DefaultMixin): + """Type variable tuple. + + Usage:: + + Ts = TypeVarTuple('Ts') + + In the same way that a normal type variable is a stand-in for a single + type such as ``int``, a type variable *tuple* is a stand-in for a *tuple* + type such as ``Tuple[int, str]``. + + Type variable tuples can be used in ``Generic`` declarations. + Consider the following example:: + + class Array(Generic[*Ts]): ... + + The ``Ts`` type variable tuple here behaves like ``tuple[T1, T2]``, + where ``T1`` and ``T2`` are type variables. To use these type variables + as type parameters of ``Array``, we must *unpack* the type variable tuple using + the star operator: ``*Ts``. The signature of ``Array`` then behaves + as if we had simply written ``class Array(Generic[T1, T2]): ...``. + In contrast to ``Generic[T1, T2]``, however, ``Generic[*Shape]`` allows + us to parameterise the class with an *arbitrary* number of type parameters. + + Type variable tuples can be used anywhere a normal ``TypeVar`` can. + This includes class definitions, as shown above, as well as function + signatures and variable annotations:: + + class Array(Generic[*Ts]): + + def __init__(self, shape: Tuple[*Ts]): + self._shape: Tuple[*Ts] = shape + + def get_shape(self) -> Tuple[*Ts]: + return self._shape + + shape = (Height(480), Width(640)) + x: Array[Height, Width] = Array(shape) + y = abs(x) # Inferred type is Array[Height, Width] + z = x + x # ... is Array[Height, Width] + x.get_shape() # ... is tuple[Height, Width] + + """ + + # Trick Generic __parameters__. + __class__ = typing.TypeVar + + def __iter__(self): + yield self.__unpacked__ + + def __init__(self, name, *, default=NoDefault): + self.__name__ = name + _DefaultMixin.__init__(self, default) + + # for pickling: + def_mod = _caller() + if def_mod != 'typing_extensions': + self.__module__ = def_mod + + self.__unpacked__ = Unpack[self] + + def __repr__(self): + return self.__name__ + + def __hash__(self): + return object.__hash__(self) + + def __eq__(self, other): + return self is other + + def __reduce__(self): + return self.__name__ + + def __init_subclass__(self, *args, **kwds): + if '_root' not in kwds: + raise TypeError("Cannot subclass special typing classes") + + +if hasattr(typing, "reveal_type"): # 3.11+ + reveal_type = typing.reveal_type +else: # <=3.10 + def reveal_type(obj: T, /) -> T: + """Reveal the inferred type of a variable. + + When a static type checker encounters a call to ``reveal_type()``, + it will emit the inferred type of the argument:: + + x: int = 1 + reveal_type(x) + + Running a static type checker (e.g., ``mypy``) on this example + will produce output similar to 'Revealed type is "builtins.int"'. + + At runtime, the function prints the runtime type of the + argument and returns it unchanged. + + """ + print(f"Runtime type is {type(obj).__name__!r}", file=sys.stderr) + return obj + + +if hasattr(typing, "_ASSERT_NEVER_REPR_MAX_LENGTH"): # 3.11+ + _ASSERT_NEVER_REPR_MAX_LENGTH = typing._ASSERT_NEVER_REPR_MAX_LENGTH +else: # <=3.10 + _ASSERT_NEVER_REPR_MAX_LENGTH = 100 + + +if hasattr(typing, "assert_never"): # 3.11+ + assert_never = typing.assert_never +else: # <=3.10 + def assert_never(arg: Never, /) -> Never: + """Assert to the type checker that a line of code is unreachable. + + Example:: + + def int_or_str(arg: int | str) -> None: + match arg: + case int(): + print("It's an int") + case str(): + print("It's a str") + case _: + assert_never(arg) + + If a type checker finds that a call to assert_never() is + reachable, it will emit an error. + + At runtime, this throws an exception when called. + + """ + value = repr(arg) + if len(value) > _ASSERT_NEVER_REPR_MAX_LENGTH: + value = value[:_ASSERT_NEVER_REPR_MAX_LENGTH] + '...' + raise AssertionError(f"Expected code to be unreachable, but got: {value}") + + +if sys.version_info >= (3, 12): # 3.12+ + # dataclass_transform exists in 3.11 but lacks the frozen_default parameter + dataclass_transform = typing.dataclass_transform +else: # <=3.11 + def dataclass_transform( + *, + eq_default: bool = True, + order_default: bool = False, + kw_only_default: bool = False, + frozen_default: bool = False, + field_specifiers: typing.Tuple[ + typing.Union[typing.Type[typing.Any], typing.Callable[..., typing.Any]], + ... + ] = (), + **kwargs: typing.Any, + ) -> typing.Callable[[T], T]: + """Decorator that marks a function, class, or metaclass as providing + dataclass-like behavior. + + Example: + + from pip._vendor.typing_extensions import dataclass_transform + + _T = TypeVar("_T") + + # Used on a decorator function + @dataclass_transform() + def create_model(cls: type[_T]) -> type[_T]: + ... + return cls + + @create_model + class CustomerModel: + id: int + name: str + + # Used on a base class + @dataclass_transform() + class ModelBase: ... + + class CustomerModel(ModelBase): + id: int + name: str + + # Used on a metaclass + @dataclass_transform() + class ModelMeta(type): ... + + class ModelBase(metaclass=ModelMeta): ... + + class CustomerModel(ModelBase): + id: int + name: str + + Each of the ``CustomerModel`` classes defined in this example will now + behave similarly to a dataclass created with the ``@dataclasses.dataclass`` + decorator. For example, the type checker will synthesize an ``__init__`` + method. + + The arguments to this decorator can be used to customize this behavior: + - ``eq_default`` indicates whether the ``eq`` parameter is assumed to be + True or False if it is omitted by the caller. + - ``order_default`` indicates whether the ``order`` parameter is + assumed to be True or False if it is omitted by the caller. + - ``kw_only_default`` indicates whether the ``kw_only`` parameter is + assumed to be True or False if it is omitted by the caller. + - ``frozen_default`` indicates whether the ``frozen`` parameter is + assumed to be True or False if it is omitted by the caller. + - ``field_specifiers`` specifies a static list of supported classes + or functions that describe fields, similar to ``dataclasses.field()``. + + At runtime, this decorator records its arguments in the + ``__dataclass_transform__`` attribute on the decorated object. + + See PEP 681 for details. + + """ + def decorator(cls_or_fn): + cls_or_fn.__dataclass_transform__ = { + "eq_default": eq_default, + "order_default": order_default, + "kw_only_default": kw_only_default, + "frozen_default": frozen_default, + "field_specifiers": field_specifiers, + "kwargs": kwargs, + } + return cls_or_fn + return decorator + + +if hasattr(typing, "override"): # 3.12+ + override = typing.override +else: # <=3.11 + _F = typing.TypeVar("_F", bound=typing.Callable[..., typing.Any]) + + def override(arg: _F, /) -> _F: + """Indicate that a method is intended to override a method in a base class. + + Usage: + + class Base: + def method(self) -> None: + pass + + class Child(Base): + @override + def method(self) -> None: + super().method() + + When this decorator is applied to a method, the type checker will + validate that it overrides a method with the same name on a base class. + This helps prevent bugs that may occur when a base class is changed + without an equivalent change to a child class. + + There is no runtime checking of these properties. The decorator + sets the ``__override__`` attribute to ``True`` on the decorated object + to allow runtime introspection. + + See PEP 698 for details. + + """ + try: + arg.__override__ = True + except (AttributeError, TypeError): + # Skip the attribute silently if it is not writable. + # AttributeError happens if the object has __slots__ or a + # read-only property, TypeError if it's a builtin class. + pass + return arg + + +if hasattr(warnings, "deprecated"): + deprecated = warnings.deprecated +else: + _T = typing.TypeVar("_T") + + class deprecated: + """Indicate that a class, function or overload is deprecated. + + When this decorator is applied to an object, the type checker + will generate a diagnostic on usage of the deprecated object. + + Usage: + + @deprecated("Use B instead") + class A: + pass + + @deprecated("Use g instead") + def f(): + pass + + @overload + @deprecated("int support is deprecated") + def g(x: int) -> int: ... + @overload + def g(x: str) -> int: ... + + The warning specified by *category* will be emitted at runtime + on use of deprecated objects. For functions, that happens on calls; + for classes, on instantiation and on creation of subclasses. + If the *category* is ``None``, no warning is emitted at runtime. + The *stacklevel* determines where the + warning is emitted. If it is ``1`` (the default), the warning + is emitted at the direct caller of the deprecated object; if it + is higher, it is emitted further up the stack. + Static type checker behavior is not affected by the *category* + and *stacklevel* arguments. + + The deprecation message passed to the decorator is saved in the + ``__deprecated__`` attribute on the decorated object. + If applied to an overload, the decorator + must be after the ``@overload`` decorator for the attribute to + exist on the overload as returned by ``get_overloads()``. + + See PEP 702 for details. + + """ + def __init__( + self, + message: str, + /, + *, + category: typing.Optional[typing.Type[Warning]] = DeprecationWarning, + stacklevel: int = 1, + ) -> None: + if not isinstance(message, str): + raise TypeError( + "Expected an object of type str for 'message', not " + f"{type(message).__name__!r}" + ) + self.message = message + self.category = category + self.stacklevel = stacklevel + + def __call__(self, arg: _T, /) -> _T: + # Make sure the inner functions created below don't + # retain a reference to self. + msg = self.message + category = self.category + stacklevel = self.stacklevel + if category is None: + arg.__deprecated__ = msg + return arg + elif isinstance(arg, type): + import functools + from types import MethodType + + original_new = arg.__new__ + + @functools.wraps(original_new) + def __new__(cls, *args, **kwargs): + if cls is arg: + warnings.warn(msg, category=category, stacklevel=stacklevel + 1) + if original_new is not object.__new__: + return original_new(cls, *args, **kwargs) + # Mirrors a similar check in object.__new__. + elif cls.__init__ is object.__init__ and (args or kwargs): + raise TypeError(f"{cls.__name__}() takes no arguments") + else: + return original_new(cls) + + arg.__new__ = staticmethod(__new__) + + original_init_subclass = arg.__init_subclass__ + # We need slightly different behavior if __init_subclass__ + # is a bound method (likely if it was implemented in Python) + if isinstance(original_init_subclass, MethodType): + original_init_subclass = original_init_subclass.__func__ + + @functools.wraps(original_init_subclass) + def __init_subclass__(*args, **kwargs): + warnings.warn(msg, category=category, stacklevel=stacklevel + 1) + return original_init_subclass(*args, **kwargs) + + arg.__init_subclass__ = classmethod(__init_subclass__) + # Or otherwise, which likely means it's a builtin such as + # object's implementation of __init_subclass__. + else: + @functools.wraps(original_init_subclass) + def __init_subclass__(*args, **kwargs): + warnings.warn(msg, category=category, stacklevel=stacklevel + 1) + return original_init_subclass(*args, **kwargs) + + arg.__init_subclass__ = __init_subclass__ + + arg.__deprecated__ = __new__.__deprecated__ = msg + __init_subclass__.__deprecated__ = msg + return arg + elif callable(arg): + import functools + + @functools.wraps(arg) + def wrapper(*args, **kwargs): + warnings.warn(msg, category=category, stacklevel=stacklevel + 1) + return arg(*args, **kwargs) + + arg.__deprecated__ = wrapper.__deprecated__ = msg + return wrapper + else: + raise TypeError( + "@deprecated decorator with non-None category must be applied to " + f"a class or callable, not {arg!r}" + ) + + +# We have to do some monkey patching to deal with the dual nature of +# Unpack/TypeVarTuple: +# - We want Unpack to be a kind of TypeVar so it gets accepted in +# Generic[Unpack[Ts]] +# - We want it to *not* be treated as a TypeVar for the purposes of +# counting generic parameters, so that when we subscript a generic, +# the runtime doesn't try to substitute the Unpack with the subscripted type. +if not hasattr(typing, "TypeVarTuple"): + def _check_generic(cls, parameters, elen=_marker): + """Check correct count for parameters of a generic cls (internal helper). + + This gives a nice error message in case of count mismatch. + """ + if not elen: + raise TypeError(f"{cls} is not a generic class") + if elen is _marker: + if not hasattr(cls, "__parameters__") or not cls.__parameters__: + raise TypeError(f"{cls} is not a generic class") + elen = len(cls.__parameters__) + alen = len(parameters) + if alen != elen: + expect_val = elen + if hasattr(cls, "__parameters__"): + parameters = [p for p in cls.__parameters__ if not _is_unpack(p)] + num_tv_tuples = sum(isinstance(p, TypeVarTuple) for p in parameters) + if (num_tv_tuples > 0) and (alen >= elen - num_tv_tuples): + return + + # deal with TypeVarLike defaults + # required TypeVarLikes cannot appear after a defaulted one. + if alen < elen: + # since we validate TypeVarLike default in _collect_type_vars + # or _collect_parameters we can safely check parameters[alen] + if ( + getattr(parameters[alen], '__default__', NoDefault) + is not NoDefault + ): + return + + num_default_tv = sum(getattr(p, '__default__', NoDefault) + is not NoDefault for p in parameters) + + elen -= num_default_tv + + expect_val = f"at least {elen}" + + things = "arguments" if sys.version_info >= (3, 10) else "parameters" + raise TypeError(f"Too {'many' if alen > elen else 'few'} {things}" + f" for {cls}; actual {alen}, expected {expect_val}") +else: + # Python 3.11+ + + def _check_generic(cls, parameters, elen): + """Check correct count for parameters of a generic cls (internal helper). + + This gives a nice error message in case of count mismatch. + """ + if not elen: + raise TypeError(f"{cls} is not a generic class") + alen = len(parameters) + if alen != elen: + expect_val = elen + if hasattr(cls, "__parameters__"): + parameters = [p for p in cls.__parameters__ if not _is_unpack(p)] + + # deal with TypeVarLike defaults + # required TypeVarLikes cannot appear after a defaulted one. + if alen < elen: + # since we validate TypeVarLike default in _collect_type_vars + # or _collect_parameters we can safely check parameters[alen] + if ( + getattr(parameters[alen], '__default__', NoDefault) + is not NoDefault + ): + return + + num_default_tv = sum(getattr(p, '__default__', NoDefault) + is not NoDefault for p in parameters) + + elen -= num_default_tv + + expect_val = f"at least {elen}" + + raise TypeError(f"Too {'many' if alen > elen else 'few'} arguments" + f" for {cls}; actual {alen}, expected {expect_val}") + +if not _PEP_696_IMPLEMENTED: + typing._check_generic = _check_generic + + +def _has_generic_or_protocol_as_origin() -> bool: + try: + frame = sys._getframe(2) + # - Catch AttributeError: not all Python implementations have sys._getframe() + # - Catch ValueError: maybe we're called from an unexpected module + # and the call stack isn't deep enough + except (AttributeError, ValueError): + return False # err on the side of leniency + else: + # If we somehow get invoked from outside typing.py, + # also err on the side of leniency + if frame.f_globals.get("__name__") != "typing": + return False + origin = frame.f_locals.get("origin") + # Cannot use "in" because origin may be an object with a buggy __eq__ that + # throws an error. + return origin is typing.Generic or origin is Protocol or origin is typing.Protocol + + +_TYPEVARTUPLE_TYPES = {TypeVarTuple, getattr(typing, "TypeVarTuple", None)} + + +def _is_unpacked_typevartuple(x) -> bool: + if get_origin(x) is not Unpack: + return False + args = get_args(x) + return ( + bool(args) + and len(args) == 1 + and type(args[0]) in _TYPEVARTUPLE_TYPES + ) + + +# Python 3.11+ _collect_type_vars was renamed to _collect_parameters +if hasattr(typing, '_collect_type_vars'): + def _collect_type_vars(types, typevar_types=None): + """Collect all type variable contained in types in order of + first appearance (lexicographic order). For example:: + + _collect_type_vars((T, List[S, T])) == (T, S) + """ + if typevar_types is None: + typevar_types = typing.TypeVar + tvars = [] + + # A required TypeVarLike cannot appear after a TypeVarLike with a default + # if it was a direct call to `Generic[]` or `Protocol[]` + enforce_default_ordering = _has_generic_or_protocol_as_origin() + default_encountered = False + + # Also, a TypeVarLike with a default cannot appear after a TypeVarTuple + type_var_tuple_encountered = False + + for t in types: + if _is_unpacked_typevartuple(t): + type_var_tuple_encountered = True + elif isinstance(t, typevar_types) and t not in tvars: + if enforce_default_ordering: + has_default = getattr(t, '__default__', NoDefault) is not NoDefault + if has_default: + if type_var_tuple_encountered: + raise TypeError('Type parameter with a default' + ' follows TypeVarTuple') + default_encountered = True + elif default_encountered: + raise TypeError(f'Type parameter {t!r} without a default' + ' follows type parameter with a default') + + tvars.append(t) + if _should_collect_from_parameters(t): + tvars.extend([t for t in t.__parameters__ if t not in tvars]) + return tuple(tvars) + + typing._collect_type_vars = _collect_type_vars +else: + def _collect_parameters(args): + """Collect all type variables and parameter specifications in args + in order of first appearance (lexicographic order). + + For example:: + + assert _collect_parameters((T, Callable[P, T])) == (T, P) + """ + parameters = [] + + # A required TypeVarLike cannot appear after a TypeVarLike with default + # if it was a direct call to `Generic[]` or `Protocol[]` + enforce_default_ordering = _has_generic_or_protocol_as_origin() + default_encountered = False + + # Also, a TypeVarLike with a default cannot appear after a TypeVarTuple + type_var_tuple_encountered = False + + for t in args: + if isinstance(t, type): + # We don't want __parameters__ descriptor of a bare Python class. + pass + elif isinstance(t, tuple): + # `t` might be a tuple, when `ParamSpec` is substituted with + # `[T, int]`, or `[int, *Ts]`, etc. + for x in t: + for collected in _collect_parameters([x]): + if collected not in parameters: + parameters.append(collected) + elif hasattr(t, '__typing_subst__'): + if t not in parameters: + if enforce_default_ordering: + has_default = ( + getattr(t, '__default__', NoDefault) is not NoDefault + ) + + if type_var_tuple_encountered and has_default: + raise TypeError('Type parameter with a default' + ' follows TypeVarTuple') + + if has_default: + default_encountered = True + elif default_encountered: + raise TypeError(f'Type parameter {t!r} without a default' + ' follows type parameter with a default') + + parameters.append(t) + else: + if _is_unpacked_typevartuple(t): + type_var_tuple_encountered = True + for x in getattr(t, '__parameters__', ()): + if x not in parameters: + parameters.append(x) + + return tuple(parameters) + + if not _PEP_696_IMPLEMENTED: + typing._collect_parameters = _collect_parameters + +# Backport typing.NamedTuple as it exists in Python 3.13. +# In 3.11, the ability to define generic `NamedTuple`s was supported. +# This was explicitly disallowed in 3.9-3.10, and only half-worked in <=3.8. +# On 3.12, we added __orig_bases__ to call-based NamedTuples +# On 3.13, we deprecated kwargs-based NamedTuples +if sys.version_info >= (3, 13): + NamedTuple = typing.NamedTuple +else: + def _make_nmtuple(name, types, module, defaults=()): + fields = [n for n, t in types] + annotations = {n: typing._type_check(t, f"field {n} annotation must be a type") + for n, t in types} + nm_tpl = collections.namedtuple(name, fields, + defaults=defaults, module=module) + nm_tpl.__annotations__ = nm_tpl.__new__.__annotations__ = annotations + # The `_field_types` attribute was removed in 3.9; + # in earlier versions, it is the same as the `__annotations__` attribute + if sys.version_info < (3, 9): + nm_tpl._field_types = annotations + return nm_tpl + + _prohibited_namedtuple_fields = typing._prohibited + _special_namedtuple_fields = frozenset({'__module__', '__name__', '__annotations__'}) + + class _NamedTupleMeta(type): + def __new__(cls, typename, bases, ns): + assert _NamedTuple in bases + for base in bases: + if base is not _NamedTuple and base is not typing.Generic: + raise TypeError( + 'can only inherit from a NamedTuple type and Generic') + bases = tuple(tuple if base is _NamedTuple else base for base in bases) + if "__annotations__" in ns: + types = ns["__annotations__"] + elif "__annotate__" in ns: + # TODO: Use inspect.VALUE here, and make the annotations lazily evaluated + types = ns["__annotate__"](1) + else: + types = {} + default_names = [] + for field_name in types: + if field_name in ns: + default_names.append(field_name) + elif default_names: + raise TypeError(f"Non-default namedtuple field {field_name} " + f"cannot follow default field" + f"{'s' if len(default_names) > 1 else ''} " + f"{', '.join(default_names)}") + nm_tpl = _make_nmtuple( + typename, types.items(), + defaults=[ns[n] for n in default_names], + module=ns['__module__'] + ) + nm_tpl.__bases__ = bases + if typing.Generic in bases: + if hasattr(typing, '_generic_class_getitem'): # 3.12+ + nm_tpl.__class_getitem__ = classmethod(typing._generic_class_getitem) + else: + class_getitem = typing.Generic.__class_getitem__.__func__ + nm_tpl.__class_getitem__ = classmethod(class_getitem) + # update from user namespace without overriding special namedtuple attributes + for key, val in ns.items(): + if key in _prohibited_namedtuple_fields: + raise AttributeError("Cannot overwrite NamedTuple attribute " + key) + elif key not in _special_namedtuple_fields: + if key not in nm_tpl._fields: + setattr(nm_tpl, key, ns[key]) + try: + set_name = type(val).__set_name__ + except AttributeError: + pass + else: + try: + set_name(val, nm_tpl, key) + except BaseException as e: + msg = ( + f"Error calling __set_name__ on {type(val).__name__!r} " + f"instance {key!r} in {typename!r}" + ) + # BaseException.add_note() existed on py311, + # but the __set_name__ machinery didn't start + # using add_note() until py312. + # Making sure exceptions are raised in the same way + # as in "normal" classes seems most important here. + if sys.version_info >= (3, 12): + e.add_note(msg) + raise + else: + raise RuntimeError(msg) from e + + if typing.Generic in bases: + nm_tpl.__init_subclass__() + return nm_tpl + + _NamedTuple = type.__new__(_NamedTupleMeta, 'NamedTuple', (), {}) + + def _namedtuple_mro_entries(bases): + assert NamedTuple in bases + return (_NamedTuple,) + + @_ensure_subclassable(_namedtuple_mro_entries) + def NamedTuple(typename, fields=_marker, /, **kwargs): + """Typed version of namedtuple. + + Usage:: + + class Employee(NamedTuple): + name: str + id: int + + This is equivalent to:: + + Employee = collections.namedtuple('Employee', ['name', 'id']) + + The resulting class has an extra __annotations__ attribute, giving a + dict that maps field names to types. (The field names are also in + the _fields attribute, which is part of the namedtuple API.) + An alternative equivalent functional syntax is also accepted:: + + Employee = NamedTuple('Employee', [('name', str), ('id', int)]) + """ + if fields is _marker: + if kwargs: + deprecated_thing = "Creating NamedTuple classes using keyword arguments" + deprecation_msg = ( + "{name} is deprecated and will be disallowed in Python {remove}. " + "Use the class-based or functional syntax instead." + ) + else: + deprecated_thing = "Failing to pass a value for the 'fields' parameter" + example = f"`{typename} = NamedTuple({typename!r}, [])`" + deprecation_msg = ( + "{name} is deprecated and will be disallowed in Python {remove}. " + "To create a NamedTuple class with 0 fields " + "using the functional syntax, " + "pass an empty list, e.g. " + ) + example + "." + elif fields is None: + if kwargs: + raise TypeError( + "Cannot pass `None` as the 'fields' parameter " + "and also specify fields using keyword arguments" + ) + else: + deprecated_thing = "Passing `None` as the 'fields' parameter" + example = f"`{typename} = NamedTuple({typename!r}, [])`" + deprecation_msg = ( + "{name} is deprecated and will be disallowed in Python {remove}. " + "To create a NamedTuple class with 0 fields " + "using the functional syntax, " + "pass an empty list, e.g. " + ) + example + "." + elif kwargs: + raise TypeError("Either list of fields or keywords" + " can be provided to NamedTuple, not both") + if fields is _marker or fields is None: + warnings.warn( + deprecation_msg.format(name=deprecated_thing, remove="3.15"), + DeprecationWarning, + stacklevel=2, + ) + fields = kwargs.items() + nt = _make_nmtuple(typename, fields, module=_caller()) + nt.__orig_bases__ = (NamedTuple,) + return nt + + +if hasattr(collections.abc, "Buffer"): + Buffer = collections.abc.Buffer +else: + class Buffer(abc.ABC): # noqa: B024 + """Base class for classes that implement the buffer protocol. + + The buffer protocol allows Python objects to expose a low-level + memory buffer interface. Before Python 3.12, it is not possible + to implement the buffer protocol in pure Python code, or even + to check whether a class implements the buffer protocol. In + Python 3.12 and higher, the ``__buffer__`` method allows access + to the buffer protocol from Python code, and the + ``collections.abc.Buffer`` ABC allows checking whether a class + implements the buffer protocol. + + To indicate support for the buffer protocol in earlier versions, + inherit from this ABC, either in a stub file or at runtime, + or use ABC registration. This ABC provides no methods, because + there is no Python-accessible methods shared by pre-3.12 buffer + classes. It is useful primarily for static checks. + + """ + + # As a courtesy, register the most common stdlib buffer classes. + Buffer.register(memoryview) + Buffer.register(bytearray) + Buffer.register(bytes) + + +# Backport of types.get_original_bases, available on 3.12+ in CPython +if hasattr(_types, "get_original_bases"): + get_original_bases = _types.get_original_bases +else: + def get_original_bases(cls, /): + """Return the class's "original" bases prior to modification by `__mro_entries__`. + + Examples:: + + from typing import TypeVar, Generic + from pip._vendor.typing_extensions import NamedTuple, TypedDict + + T = TypeVar("T") + class Foo(Generic[T]): ... + class Bar(Foo[int], float): ... + class Baz(list[str]): ... + Eggs = NamedTuple("Eggs", [("a", int), ("b", str)]) + Spam = TypedDict("Spam", {"a": int, "b": str}) + + assert get_original_bases(Bar) == (Foo[int], float) + assert get_original_bases(Baz) == (list[str],) + assert get_original_bases(Eggs) == (NamedTuple,) + assert get_original_bases(Spam) == (TypedDict,) + assert get_original_bases(int) == (object,) + """ + try: + return cls.__dict__.get("__orig_bases__", cls.__bases__) + except AttributeError: + raise TypeError( + f'Expected an instance of type, not {type(cls).__name__!r}' + ) from None + + +# NewType is a class on Python 3.10+, making it pickleable +# The error message for subclassing instances of NewType was improved on 3.11+ +if sys.version_info >= (3, 11): + NewType = typing.NewType +else: + class NewType: + """NewType creates simple unique types with almost zero + runtime overhead. NewType(name, tp) is considered a subtype of tp + by static type checkers. At runtime, NewType(name, tp) returns + a dummy callable that simply returns its argument. Usage:: + UserId = NewType('UserId', int) + def name_by_id(user_id: UserId) -> str: + ... + UserId('user') # Fails type check + name_by_id(42) # Fails type check + name_by_id(UserId(42)) # OK + num = UserId(5) + 1 # type: int + """ + + def __call__(self, obj, /): + return obj + + def __init__(self, name, tp): + self.__qualname__ = name + if '.' in name: + name = name.rpartition('.')[-1] + self.__name__ = name + self.__supertype__ = tp + def_mod = _caller() + if def_mod != 'typing_extensions': + self.__module__ = def_mod + + def __mro_entries__(self, bases): + # We defined __mro_entries__ to get a better error message + # if a user attempts to subclass a NewType instance. bpo-46170 + supercls_name = self.__name__ + + class Dummy: + def __init_subclass__(cls): + subcls_name = cls.__name__ + raise TypeError( + f"Cannot subclass an instance of NewType. " + f"Perhaps you were looking for: " + f"`{subcls_name} = NewType({subcls_name!r}, {supercls_name})`" + ) + + return (Dummy,) + + def __repr__(self): + return f'{self.__module__}.{self.__qualname__}' + + def __reduce__(self): + return self.__qualname__ + + if sys.version_info >= (3, 10): + # PEP 604 methods + # It doesn't make sense to have these methods on Python <3.10 + + def __or__(self, other): + return typing.Union[self, other] + + def __ror__(self, other): + return typing.Union[other, self] + + +if hasattr(typing, "TypeAliasType"): + TypeAliasType = typing.TypeAliasType +else: + def _is_unionable(obj): + """Corresponds to is_unionable() in unionobject.c in CPython.""" + return obj is None or isinstance(obj, ( + type, + _types.GenericAlias, + _types.UnionType, + TypeAliasType, + )) + + class TypeAliasType: + """Create named, parameterized type aliases. + + This provides a backport of the new `type` statement in Python 3.12: + + type ListOrSet[T] = list[T] | set[T] + + is equivalent to: + + T = TypeVar("T") + ListOrSet = TypeAliasType("ListOrSet", list[T] | set[T], type_params=(T,)) + + The name ListOrSet can then be used as an alias for the type it refers to. + + The type_params argument should contain all the type parameters used + in the value of the type alias. If the alias is not generic, this + argument is omitted. + + Static type checkers should only support type aliases declared using + TypeAliasType that follow these rules: + + - The first argument (the name) must be a string literal. + - The TypeAliasType instance must be immediately assigned to a variable + of the same name. (For example, 'X = TypeAliasType("Y", int)' is invalid, + as is 'X, Y = TypeAliasType("X", int), TypeAliasType("Y", int)'). + + """ + + def __init__(self, name: str, value, *, type_params=()): + if not isinstance(name, str): + raise TypeError("TypeAliasType name must be a string") + self.__value__ = value + self.__type_params__ = type_params + + parameters = [] + for type_param in type_params: + if isinstance(type_param, TypeVarTuple): + parameters.extend(type_param) + else: + parameters.append(type_param) + self.__parameters__ = tuple(parameters) + def_mod = _caller() + if def_mod != 'typing_extensions': + self.__module__ = def_mod + # Setting this attribute closes the TypeAliasType from further modification + self.__name__ = name + + def __setattr__(self, name: str, value: object, /) -> None: + if hasattr(self, "__name__"): + self._raise_attribute_error(name) + super().__setattr__(name, value) + + def __delattr__(self, name: str, /) -> Never: + self._raise_attribute_error(name) + + def _raise_attribute_error(self, name: str) -> Never: + # Match the Python 3.12 error messages exactly + if name == "__name__": + raise AttributeError("readonly attribute") + elif name in {"__value__", "__type_params__", "__parameters__", "__module__"}: + raise AttributeError( + f"attribute '{name}' of 'typing.TypeAliasType' objects " + "is not writable" + ) + else: + raise AttributeError( + f"'typing.TypeAliasType' object has no attribute '{name}'" + ) + + def __repr__(self) -> str: + return self.__name__ + + def __getitem__(self, parameters): + if not isinstance(parameters, tuple): + parameters = (parameters,) + parameters = [ + typing._type_check( + item, f'Subscripting {self.__name__} requires a type.' + ) + for item in parameters + ] + return typing._GenericAlias(self, tuple(parameters)) + + def __reduce__(self): + return self.__name__ + + def __init_subclass__(cls, *args, **kwargs): + raise TypeError( + "type 'typing_extensions.TypeAliasType' is not an acceptable base type" + ) + + # The presence of this method convinces typing._type_check + # that TypeAliasTypes are types. + def __call__(self): + raise TypeError("Type alias is not callable") + + if sys.version_info >= (3, 10): + def __or__(self, right): + # For forward compatibility with 3.12, reject Unions + # that are not accepted by the built-in Union. + if not _is_unionable(right): + return NotImplemented + return typing.Union[self, right] + + def __ror__(self, left): + if not _is_unionable(left): + return NotImplemented + return typing.Union[left, self] + + +if hasattr(typing, "is_protocol"): + is_protocol = typing.is_protocol + get_protocol_members = typing.get_protocol_members +else: + def is_protocol(tp: type, /) -> bool: + """Return True if the given type is a Protocol. + + Example:: + + >>> from typing_extensions import Protocol, is_protocol + >>> class P(Protocol): + ... def a(self) -> str: ... + ... b: int + >>> is_protocol(P) + True + >>> is_protocol(int) + False + """ + return ( + isinstance(tp, type) + and getattr(tp, '_is_protocol', False) + and tp is not Protocol + and tp is not typing.Protocol + ) + + def get_protocol_members(tp: type, /) -> typing.FrozenSet[str]: + """Return the set of members defined in a Protocol. + + Example:: + + >>> from typing_extensions import Protocol, get_protocol_members + >>> class P(Protocol): + ... def a(self) -> str: ... + ... b: int + >>> get_protocol_members(P) + frozenset({'a', 'b'}) + + Raise a TypeError for arguments that are not Protocols. + """ + if not is_protocol(tp): + raise TypeError(f'{tp!r} is not a Protocol') + if hasattr(tp, '__protocol_attrs__'): + return frozenset(tp.__protocol_attrs__) + return frozenset(_get_protocol_attrs(tp)) + + +if hasattr(typing, "Doc"): + Doc = typing.Doc +else: + class Doc: + """Define the documentation of a type annotation using ``Annotated``, to be + used in class attributes, function and method parameters, return values, + and variables. + + The value should be a positional-only string literal to allow static tools + like editors and documentation generators to use it. + + This complements docstrings. + + The string value passed is available in the attribute ``documentation``. + + Example:: + + >>> from typing_extensions import Annotated, Doc + >>> def hi(to: Annotated[str, Doc("Who to say hi to")]) -> None: ... + """ + def __init__(self, documentation: str, /) -> None: + self.documentation = documentation + + def __repr__(self) -> str: + return f"Doc({self.documentation!r})" + + def __hash__(self) -> int: + return hash(self.documentation) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, Doc): + return NotImplemented + return self.documentation == other.documentation + + +_CapsuleType = getattr(_types, "CapsuleType", None) + +if _CapsuleType is None: + try: + import _socket + except ImportError: + pass + else: + _CAPI = getattr(_socket, "CAPI", None) + if _CAPI is not None: + _CapsuleType = type(_CAPI) + +if _CapsuleType is not None: + CapsuleType = _CapsuleType + __all__.append("CapsuleType") + + +# Aliases for items that have always been in typing. +# Explicitly assign these (rather than using `from typing import *` at the top), +# so that we get a CI error if one of these is deleted from typing.py +# in a future version of Python +AbstractSet = typing.AbstractSet +AnyStr = typing.AnyStr +BinaryIO = typing.BinaryIO +Callable = typing.Callable +Collection = typing.Collection +Container = typing.Container +Dict = typing.Dict +ForwardRef = typing.ForwardRef +FrozenSet = typing.FrozenSet +Generic = typing.Generic +Hashable = typing.Hashable +IO = typing.IO +ItemsView = typing.ItemsView +Iterable = typing.Iterable +Iterator = typing.Iterator +KeysView = typing.KeysView +List = typing.List +Mapping = typing.Mapping +MappingView = typing.MappingView +Match = typing.Match +MutableMapping = typing.MutableMapping +MutableSequence = typing.MutableSequence +MutableSet = typing.MutableSet +Optional = typing.Optional +Pattern = typing.Pattern +Reversible = typing.Reversible +Sequence = typing.Sequence +Set = typing.Set +Sized = typing.Sized +TextIO = typing.TextIO +Tuple = typing.Tuple +Union = typing.Union +ValuesView = typing.ValuesView +cast = typing.cast +no_type_check = typing.no_type_check +no_type_check_decorator = typing.no_type_check_decorator diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/__init__.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/__init__.py new file mode 100644 index 0000000..c6fa382 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/__init__.py @@ -0,0 +1,102 @@ +""" +Python HTTP library with thread-safe connection pooling, file post support, user friendly, and more +""" +from __future__ import absolute_import + +# Set default logging handler to avoid "No handler found" warnings. +import logging +import warnings +from logging import NullHandler + +from . import exceptions +from ._version import __version__ +from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool, connection_from_url +from .filepost import encode_multipart_formdata +from .poolmanager import PoolManager, ProxyManager, proxy_from_url +from .response import HTTPResponse +from .util.request import make_headers +from .util.retry import Retry +from .util.timeout import Timeout +from .util.url import get_host + +# === NOTE TO REPACKAGERS AND VENDORS === +# Please delete this block, this logic is only +# for urllib3 being distributed via PyPI. +# See: https://github.com/urllib3/urllib3/issues/2680 +try: + import urllib3_secure_extra # type: ignore # noqa: F401 +except ImportError: + pass +else: + warnings.warn( + "'urllib3[secure]' extra is deprecated and will be removed " + "in a future release of urllib3 2.x. Read more in this issue: " + "https://github.com/urllib3/urllib3/issues/2680", + category=DeprecationWarning, + stacklevel=2, + ) + +__author__ = "Andrey Petrov (andrey.petrov@shazow.net)" +__license__ = "MIT" +__version__ = __version__ + +__all__ = ( + "HTTPConnectionPool", + "HTTPSConnectionPool", + "PoolManager", + "ProxyManager", + "HTTPResponse", + "Retry", + "Timeout", + "add_stderr_logger", + "connection_from_url", + "disable_warnings", + "encode_multipart_formdata", + "get_host", + "make_headers", + "proxy_from_url", +) + +logging.getLogger(__name__).addHandler(NullHandler()) + + +def add_stderr_logger(level=logging.DEBUG): + """ + Helper for quickly adding a StreamHandler to the logger. Useful for + debugging. + + Returns the handler after adding it. + """ + # This method needs to be in this __init__.py to get the __name__ correct + # even if urllib3 is vendored within another package. + logger = logging.getLogger(__name__) + handler = logging.StreamHandler() + handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(message)s")) + logger.addHandler(handler) + logger.setLevel(level) + logger.debug("Added a stderr logging handler to logger: %s", __name__) + return handler + + +# ... Clean up. +del NullHandler + + +# All warning filters *must* be appended unless you're really certain that they +# shouldn't be: otherwise, it's very hard for users to use most Python +# mechanisms to silence them. +# SecurityWarning's always go off by default. +warnings.simplefilter("always", exceptions.SecurityWarning, append=True) +# SubjectAltNameWarning's should go off once per host +warnings.simplefilter("default", exceptions.SubjectAltNameWarning, append=True) +# InsecurePlatformWarning's don't vary between requests, so we keep it default. +warnings.simplefilter("default", exceptions.InsecurePlatformWarning, append=True) +# SNIMissingWarnings should go off only once. +warnings.simplefilter("default", exceptions.SNIMissingWarning, append=True) + + +def disable_warnings(category=exceptions.HTTPWarning): + """ + Helper for quickly disabling all urllib3 warnings. + """ + warnings.simplefilter("ignore", category) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e23ac4e27ae3d4eb3df4ea758bd9011ef08d11b5 GIT binary patch literal 3409 zcmb7G-ESMm5#J+^-(M0XTB2piCtH%m)S}$fEmFabD}N-iE6J**w9Z-W;mBK(N8bmt zdnbvi4bVW*y!62j1=0cm>Z0gF;rtOPkOBev62cOwUMi$O(Feb=RRR=w>g>2WcxC&YxSi)cwbC8k_H zs`cspV!xgi)B1oo;Ob)9pq>#kE+5xU=|kd>%O|v9Ju7BiKB=A7N5m1APibfLQE`+* zk&c&R;+PL%zWTa%wce=oVL|EtApP9m(SiMdcupA<&tvdd$%qqR>95}DS$G_tdd_wD z>RnIQ8^J2@yeoR^IJVPDZ;i*5IOWtYI5GDi;Ci{{>3gFxghSOI_hgS#hCj&mJpWqj z(_nqyv+0fBz*_8CdE7U!UiWNz<8f>7?`OR^kAt|3KwK`>{pS%LpFqUVp|{bmnwx0L z|2Ep>a%Z-2bfs=pOhZ^$TU!w{wLoN27dBO^B3KoIWo3rSB`g$8!@xyLg@rZK)KsH< zQ7EYz28mh%wQDt#SQiDGVj`4?iVa1pUle3R5phRtJayCvC>%a}Ov6=H7HJt}(kx*)HUZras#>JRIGXboSNny>{s(U>C~yoG|mI zY?8VYrIuWLsNoH)ZBNe|3c+<@1uklC2-EP4Am(eX_ybyzx6RGGfvue5U%I`POOi0` zMk0*F83D*dB*jQSBWWN`zpN+{wIGH>(#$eE1YsEK^eHNp3mTR-Wnw@EQW9e}1B~=B zk_1xhLJF`5F#u+;bTACs_mFisS7nzv@maj5@Zjb#cf=y-&GtqQo*w%i`Ks(rC%z-r zZj(4Zt#IBs-pHXxT$M%S#P`T|Yy}I~iSH3Qwt~g-#HaX<+^>6kIM26=a{ldKMg{m5 zuvTN`YZBodTZI>{3-A&UXvnoy3$Q@%R;gf_kWg6YJWgJCi{g^4F++DB1sCjc8SL^= zSB4_6i9ubHN~g{Rxn#jn-R)H??=IY)oSc>^pp1@lRG6H0Q_PUNl8z~bs?5>ti}Q-Y z3Pb25iR%Y*)7u=}>$o;2OwwG$2{8#4I1#A5MK`0Iuq3gaCCNz~yPFfI*m?u-K(@d` zC(>i1;B7YmP8b#~vI1}d?ri}$0N-PN{y}iRlyA(fZ<^#Gt;t2aZd5Hg zBNvONZCK#hOc79Wy#Qqe$hn^1z{bY~c*;hXK*1Z?m)g69qkB_$aOq0(%E${GSAiaC{$=#>7cKFkbUwpFoN&mHv zhIjZod$Dw5`2bEsPEgi1b(;F9Gxa3RB@Ay$@5i z?t_HA@^uN@fe4liG9adhhaO;b(##2}Wdq{9%uvmnf_I0Oq+w`k@a{Q|WWY1Z07D=b zfRe073T$E!2n08b0*Mx%ZSvXQOg~%Lz0Q;Qh7CkPNTcr=L98E}h?GBVB_4BWhR z{jE1U**(h?sa4i5RjcmppINmFRro!b*Q{kIYEM0M8#ZR0bw!gcKquXs=wDsFy#zfD z^2AfcSS#-e?pyx}xo_z{z7xKpn~JUB*U24lfMo@}0<`VtIPTv*AIE}=B&3=ZiH_`QdbZ#F_?W0kc+DBvUc#I2v%AajR7Nr{t?=C%A zYWsYV@3(^}J+U`1_(d!j2)6rB^0h{EFFDYN?Ip8~SesA9e2q~19OBZAPz&`pQUBBF z7igq~rkZH#_dox`;~n%}*kg3!cT2xrIzTCIpgn~GeeERTPBp?Ulxd>O)5^1GOPFg4 zb01#bMGOBxnZp_N+3D8!d~pF literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..67ab0b814a89adead42955f064355d5b3048abba GIT binary patch literal 16368 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_version.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_version.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0916dd8dd46798533c1f5bb5b1f88479956a66a1 GIT binary patch literal 222 zcmX@j%ge<81isO>nGQhuF^B^Lj8MjB4j^MXLkdF_LnWgoQx&_Ro{^cJk%6Bk<1Oy^ z__EZZ;>`TK`1q9!pFui)B|2Nhl;;;^7Z)TZr^e)El@#kHCMV~Y=9OgTrRyf=7p2A| zB_?O5=B32wm8IsD#rR|<#S~|jr0N1SWGAMl7RMB17U%;F&P&NJ(l0H_$;nJI2Jyib p=@nGo;;_lhPbtkwwJTx++6Z!JF~}bum>C%vAMlAcau=}xxd7`oK7arK literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e40038f4c8c7b299199834b571393918b799926b GIT binary patch literal 20407 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 aS7}-)|HkS+>Ja|Y;W=7k`^#zz!v7bl*A&YD literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cd417a683867830fe2b8003d2e7248e6a6d15826 GIT binary patch literal 13497 zcmcIqYiu0Xb)MM=xup0IA9_$SrIGdGMieQ_mMl?kQPjhhRthQEF(Y6(+!>N9?aplO z%!=ZMPF2KhB*bad0)>ehE|mVMRH1;|U+J&3Kl-Nu3M#c>cHsa<`Tz{{hg@#rpg@6s z=iHg$EVY!)03C1+@1FaZbI;?RbI-j$Z*Fc>@Lc-#v22&7DE~%3{HM+n}^#L})*aWZ*W?g`7 zU~D6>Ys`iK+sN1^V4Fj2*D$sP*wzrXiLq;eZ3|(W8QTtQM+n3@Pj}4670qo8Yb|YhV0lV8I`us6AF}?@*q`4{h;%3Hv1K2$w>^@*$GPeZSt&H6d?8_mn#@JVYJrKffW9&g-UkzbjWb7ee z4~M?Cov{PJ9tmN0F!m_0$IKS9E12_6#vcd%L}(tn7<&@fQ)ZnR3tC4Re;W9~D*SH7 zp8Ev@L7hBiKt3%iBgVXZEEY#mb3v z+S2o8I$dr|rzIZcrgZu{MLp-$)Th&iok^!3DU0;=|H%vvT%WeZO{bt|%ld@**PX0u?nQ^2`lRVxFJue-Y1A3E=r4*~ zE<65me?Y9$SC|p?_!5Hz3J!sHlz)xw{VbLcEq>Lin6rkM^QJB=5Lw#B?3tFoYBNXB zH$^i6{$MMW+I&E$fT}$KRa9S_suxgGEixnWjxriEqJZ(4STbI2xMJHmDZc(?;+wFA zW|CkXEu*t6r?U{HrRiD$o%%9S4DUa*n$z#a^8oKDv+Asp_UjZk;umkk{nFC^S+ss% zHPqS2`|1bL$6i}inNgCFR4Fo`LCa$FMHUTdPu9x1=`^7oGdCgDVXSg}-gF$2Gf|;w znqc0o$B$BbFvmW>?*`zVEdY0vh0cw4WA8S6nrQnZvFS--)7&e6b@gvvo!@rk1F#=1H9~Pvr(-mpz6$5g8%s@t1m}mK)OPOip(ksIw~g(=? zD0PM@^|71L)*&I^Q9f(!`0@AdeQ$1dzID%hVh@v-dQ>MGP%FsQiZuk92+-6;H-TmP z)Im4`op>E$6KVP3|BglC#}*Tjc(2qwYLUSkJU$y1zlK^h4V&L7nvN?q>rf5N3TEnH zeb8NPO21`l;E|ol>MqueYr_|vzKrK^mqd zJuv=q>L*hl#^$#km~TBWpEw}3O_1U*S1FBf1n3P^>NKg;K2oWJQl+RigEx2rm0H2M zBt}LqN)`9JtJr3{aRWvCZjJFmOhjAl?1_;+m_(T|}a?isW#*RIZmyt& zM6Mt(fHzRWp+E_#YE|?$LkzB+@jd$SFvX6YH_3fZYDLSuU4V6f+9|zIFfBx9S!1t| zOLo67oq}ySh}CLZ4vAF|IEgn1N6rUCQ&knwf#r}sRojh0p@=#fLnIk5H(%0k51X!# zCZjh&IAQw9YV!K+Y`&P+tYUuL6q-Gu33SMsFn)&vPt!1szQ#sU&w+w2^gM?u1KQPU zlcQ)tHgZWu^m9NPU>`j&_B}5+>|0tys6ijCED)`?u8{v43xCJ~A;esPq3ClSJIR#^ z?_-jpP|P_L#LB|d9ov#Ui|57YsX?%syopW@`6)Qp^)K9w{bOTq-n?%yBtdQEI={lP3>ybv`xK7Z_PFmU& z#;OjF0*$x`0+COFGbjNE+2gl-Zbbdk(tnD+t7Xr+iN0L#nWyhjmUQ3*C|Fqsx|XvlP=j&w^VOjJ*xyH=v=82`|8%+hKT5p1uwe_7 zq={vgN~)jJ)Ws13%Vd6xa0F<-;!qGxzT-kA7L9L}5~s=x-r)Hvx6yVrn>X#EJK`cb zk)nPnEb0Q{ToN-xp0#f2xvZf%)KrE7uIyZU^*s$D1c52M!RmV?SbeE#RkSvFv`R96 z7A8~I5RKn7UCpCNu11=j$rOd-t+Io16Vo+#wfE8 z{+7dw=h5Zp<6~fp;q~#B+p2Eb(Hhv}V|_eaZKj`Sque@mwM1z!B{8h^M50AaDn7K>TX~@l>@c;@eZ^v`0T;e5t$V!?aJ! z$csqBHdG(aWt}N-*fOU>p?9Bl%|Xg3H=_*=UQVTkht6Ib89K8<-18b}6a@Y-Jcr?6 z4pgi7&tY{n*H*+{AhY?|rKwEH_F@pnK`_=3#HM zESK;z*C+*mbxo($+SRib7Ca8z5!_R11&*KgdCb%tMbw;5uio*LHo7*JcHNo@`p6Br zQ`!~Oe3t^oqLZfd#M{f;rIIyM!sX_3L#d(R3xnyQ;o-}}<(82vLxUI2`oEV4#@8`* zLEvxk21&itXPtd_E-kD(_WLQxJ8DszcPk|IT1QL-kXd)eKN#6Z1@MA%d&o?IVR;IT z9IqXihWt1O%$(A5YJ0gc5F!Zt9p1pp4FoGMRjrE9btA>`8_1KK%DE|=SNY_g4wLIU zWj_kyCD?Nq;S^;)>xKN<$f?u{u7ijZ1b&7$a2*$e2~gFlCb0ej(m3EXPW3n&@6Vt= zJcGP`)7y&_EkvKlsX`Poi|V=Y705M-Tmt_XCiieaE>*3H+_sS!$2Id5?faBgsfNSV zyc=ORU39!G7ChXzsj;)Jts0X=DuJI8VfXg)mD=@UVUD z>cx?M&Q;siM0T<$IQ$^eEv&2hEqF!*rY5Bf5g~a4uE6Xp(M;e8-at1-0%lXys%FwQ zlDcq7Dy2V%!{IsjYEi8U91BrAirz~zSb^r7L^FX;sIZ#=bDdDDqxFo5tb<`%nPAPx z@OCduFr1|BLVXG@aX7CVyq%T@-Qcf0XO^*?Z;UpdQ|mH2XZYVhI`Mg%$vn-2z%TJG zHUUtMD2mNwW3ZW|>Q&9K-S;E#xPwzg>!xXxj`%q2T1*4SWUS>GSxb(?7RVD48cqeC z1S*A-TB>$d5J&-J2?GB~g_jAiKnS%eayOo~jTw-7-gOH&M<2xH0q8b#x%2~;3sq~* zlwHi>0)QE0R;SRsF9W}4xtvY)Cpf0%vNuic*(1*ZEp4Je;uP6&Tvwn?Gm;5NCKUxX zKSIYQj^~+V=StI0dwl6hK2LUnrcB_!s6g2O$pAuCF(3%(dQh|SX^%We=QE!=ocY8= z9L-Dr%ro&Pr{zp*5?K(#HXUoX3(cg&NRWZYE|w1qE^;fG>V@CoTr}f>v z0P)l_gG>~Y@*fK0==WkD03S#BHPy#aYvgg%(&oTFeu~Plkr)*|bS>9=be0o7YgUXK zu?UB+s{~Qw|6)vs4z&?A(t(pTXFN&tK78}TsgDyUSkP5R`7{ll${`duV6J(XU;E&7 zf|IL!$Y1KOrl)6T7Pnqp97+%qdo}#zeY!udB+hAz_@uZ+;01utIW1jp5N1K(GQhLb zlodGH3pP5fCl{L5{`lg(i}df(y-QEy(KBk}7fN((<5MNt(8#lXRKIcp{5H|BkHGTS znI%Nv*F<3l01nl@h{TZ$Z&BkX)!)>`;&Ob}`V1Nb&+lkH<@O6Q9Xd$XEiIz7$HPgJ z_pOQJX3yrqXYa(SwyKsu*H@|PjrxH2pzzo$&8jyjXR_>BQf=Nk5vTa!dkJ;^FJJBJ zrP_ZNc)44Oxj4%#ua%1fM4m^$fHBgx{mCcL>lSzke$sd-S#wObE6!^o;F@ z84UT1ZLk;#)YEutQQ!mT1C>}j-u;`Fz%Zyum0_ScKPw$LH+$?jkCnp|r5-v+oZ>Rw z5V)1)^EbG8N>NSmg3reXEBO2G<6DBjMk3SC`|S^cMyjeJFR(5;zS-W#0eFoI&kWMhZlb-Ol22*iATM5iyjvk(s&^H6m|E zthf<7eVrX;f+MtR$3%7Jo7LaKp!m z!))uKW;TUMB(R0P7HIvEFB47ifu{<9>`YCn)C$e{SxM{HSIsO)IF*i_HNDd%e?RKj zMUjDLb*F?~oSgDDCk0%d@h$;`WKer6cn_2a0{dwazD=A9Y=Ww)i2ogILRv57D6yi; z%uve9@8O&rhkw`~rlnb@5%y54UJZe+hEoe96tD}&9tOv5bTKGrPxeiFcSiY;Fi+8Q zCdv$zfXehPo(7Nxb6a&HxJOU-DkHd88Tlakc62F~`;3u9AA2I=lmBR{T<_;4+j^0D zBpMMD(oq%N#*_;CLwrm|aPok^TyK~Y$d)+eX1_<8dW3R-adbfru8xeYMxJ&(Qrd^TDiD(X5L`=BXBl`? z&f8nw;t6)r-$&ze%PBTF|D;f^wY(6pVla1`X;j_~w^EnHQJF9}F8&NZNe!G|0X~hY zs`^W1*MBHiD~(aL;eJC!!M{oqm3MpP2DO*)_*dE3pdP$`n92t$8`0+OjMpZv?zrDo zQSh&_mii_`<6PkK(-x&eyVF`}YE=*2zgSW5ud<^~-FknvqTpYp9o^>q&(~uJdk?= z?I3Zbv9hB@ZJg_x-!V{8P^!F0w16)Bt2DK#19MyEli&?Xl^){8s8RO1{!=UG literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b38063e70e93667884aba6428442f5b01e9b72a9 GIT binary patch literal 10406 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 U?_b}KGtgH>L;m-jhgtr=0A5x~dH?_b literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d326547e6c9300b93d7250c6af048787ecbb56d4 GIT binary patch literal 4016 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..26a10b5b68d916ed44c1f68f2b778dd73ba94232 GIT binary patch literal 7298 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 F{W~^I_L~3z literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..57adccc00621d0442aa5f136ff02d8a77228feb4 GIT binary patch literal 33947 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 self._maxsize: + _key, evicted_value = self._container.popitem(last=False) + + if self.dispose_func and evicted_value is not _Null: + self.dispose_func(evicted_value) + + def __delitem__(self, key): + with self.lock: + value = self._container.pop(key) + + if self.dispose_func: + self.dispose_func(value) + + def __len__(self): + with self.lock: + return len(self._container) + + def __iter__(self): + raise NotImplementedError( + "Iteration over this class is unlikely to be threadsafe." + ) + + def clear(self): + with self.lock: + # Copy pointers to all values, then wipe the mapping + values = list(itervalues(self._container)) + self._container.clear() + + if self.dispose_func: + for value in values: + self.dispose_func(value) + + def keys(self): + with self.lock: + return list(iterkeys(self._container)) + + +class HTTPHeaderDict(MutableMapping): + """ + :param headers: + An iterable of field-value pairs. Must not contain multiple field names + when compared case-insensitively. + + :param kwargs: + Additional field-value pairs to pass in to ``dict.update``. + + A ``dict`` like container for storing HTTP Headers. + + Field names are stored and compared case-insensitively in compliance with + RFC 7230. Iteration provides the first case-sensitive key seen for each + case-insensitive pair. + + Using ``__setitem__`` syntax overwrites fields that compare equal + case-insensitively in order to maintain ``dict``'s api. For fields that + compare equal, instead create a new ``HTTPHeaderDict`` and use ``.add`` + in a loop. + + If multiple fields that are equal case-insensitively are passed to the + constructor or ``.update``, the behavior is undefined and some will be + lost. + + >>> headers = HTTPHeaderDict() + >>> headers.add('Set-Cookie', 'foo=bar') + >>> headers.add('set-cookie', 'baz=quxx') + >>> headers['content-length'] = '7' + >>> headers['SET-cookie'] + 'foo=bar, baz=quxx' + >>> headers['Content-Length'] + '7' + """ + + def __init__(self, headers=None, **kwargs): + super(HTTPHeaderDict, self).__init__() + self._container = OrderedDict() + if headers is not None: + if isinstance(headers, HTTPHeaderDict): + self._copy_from(headers) + else: + self.extend(headers) + if kwargs: + self.extend(kwargs) + + def __setitem__(self, key, val): + self._container[key.lower()] = [key, val] + return self._container[key.lower()] + + def __getitem__(self, key): + val = self._container[key.lower()] + return ", ".join(val[1:]) + + def __delitem__(self, key): + del self._container[key.lower()] + + def __contains__(self, key): + return key.lower() in self._container + + def __eq__(self, other): + if not isinstance(other, Mapping) and not hasattr(other, "keys"): + return False + if not isinstance(other, type(self)): + other = type(self)(other) + return dict((k.lower(), v) for k, v in self.itermerged()) == dict( + (k.lower(), v) for k, v in other.itermerged() + ) + + def __ne__(self, other): + return not self.__eq__(other) + + if six.PY2: # Python 2 + iterkeys = MutableMapping.iterkeys + itervalues = MutableMapping.itervalues + + __marker = object() + + def __len__(self): + return len(self._container) + + def __iter__(self): + # Only provide the originally cased names + for vals in self._container.values(): + yield vals[0] + + def pop(self, key, default=__marker): + """D.pop(k[,d]) -> v, remove specified key and return the corresponding value. + If key is not found, d is returned if given, otherwise KeyError is raised. + """ + # Using the MutableMapping function directly fails due to the private marker. + # Using ordinary dict.pop would expose the internal structures. + # So let's reinvent the wheel. + try: + value = self[key] + except KeyError: + if default is self.__marker: + raise + return default + else: + del self[key] + return value + + def discard(self, key): + try: + del self[key] + except KeyError: + pass + + def add(self, key, val): + """Adds a (name, value) pair, doesn't overwrite the value if it already + exists. + + >>> headers = HTTPHeaderDict(foo='bar') + >>> headers.add('Foo', 'baz') + >>> headers['foo'] + 'bar, baz' + """ + key_lower = key.lower() + new_vals = [key, val] + # Keep the common case aka no item present as fast as possible + vals = self._container.setdefault(key_lower, new_vals) + if new_vals is not vals: + vals.append(val) + + def extend(self, *args, **kwargs): + """Generic import function for any type of header-like object. + Adapted version of MutableMapping.update in order to insert items + with self.add instead of self.__setitem__ + """ + if len(args) > 1: + raise TypeError( + "extend() takes at most 1 positional " + "arguments ({0} given)".format(len(args)) + ) + other = args[0] if len(args) >= 1 else () + + if isinstance(other, HTTPHeaderDict): + for key, val in other.iteritems(): + self.add(key, val) + elif isinstance(other, Mapping): + for key in other: + self.add(key, other[key]) + elif hasattr(other, "keys"): + for key in other.keys(): + self.add(key, other[key]) + else: + for key, value in other: + self.add(key, value) + + for key, value in kwargs.items(): + self.add(key, value) + + def getlist(self, key, default=__marker): + """Returns a list of all the values for the named field. Returns an + empty list if the key doesn't exist.""" + try: + vals = self._container[key.lower()] + except KeyError: + if default is self.__marker: + return [] + return default + else: + return vals[1:] + + def _prepare_for_method_change(self): + """ + Remove content-specific header fields before changing the request + method to GET or HEAD according to RFC 9110, Section 15.4. + """ + content_specific_headers = [ + "Content-Encoding", + "Content-Language", + "Content-Location", + "Content-Type", + "Content-Length", + "Digest", + "Last-Modified", + ] + for header in content_specific_headers: + self.discard(header) + return self + + # Backwards compatibility for httplib + getheaders = getlist + getallmatchingheaders = getlist + iget = getlist + + # Backwards compatibility for http.cookiejar + get_all = getlist + + def __repr__(self): + return "%s(%s)" % (type(self).__name__, dict(self.itermerged())) + + def _copy_from(self, other): + for key in other: + val = other.getlist(key) + if isinstance(val, list): + # Don't need to convert tuples + val = list(val) + self._container[key.lower()] = [key] + val + + def copy(self): + clone = type(self)() + clone._copy_from(self) + return clone + + def iteritems(self): + """Iterate over all header lines, including duplicate ones.""" + for key in self: + vals = self._container[key.lower()] + for val in vals[1:]: + yield vals[0], val + + def itermerged(self): + """Iterate over all headers, merging duplicate ones together.""" + for key in self: + val = self._container[key.lower()] + yield val[0], ", ".join(val[1:]) + + def items(self): + return list(self.iteritems()) + + @classmethod + def from_httplib(cls, message): # Python 2 + """Read headers from a Python 2 httplib message object.""" + # python2.7 does not expose a proper API for exporting multiheaders + # efficiently. This function re-reads raw lines from the message + # object and extracts the multiheaders properly. + obs_fold_continued_leaders = (" ", "\t") + headers = [] + + for line in message.headers: + if line.startswith(obs_fold_continued_leaders): + if not headers: + # We received a header line that starts with OWS as described + # in RFC-7230 S3.2.4. This indicates a multiline header, but + # there exists no previous header to which we can attach it. + raise InvalidHeader( + "Header continuation with no previous header: %s" % line + ) + else: + key, value = headers[-1] + headers[-1] = (key, value + " " + line.strip()) + continue + + key, value = line.split(":", 1) + headers.append((key, value.strip())) + + return cls(headers) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/_version.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/_version.py new file mode 100644 index 0000000..d49df2a --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/_version.py @@ -0,0 +1,2 @@ +# This file is protected via CODEOWNERS +__version__ = "1.26.20" diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/connection.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/connection.py new file mode 100644 index 0000000..de35b63 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/connection.py @@ -0,0 +1,572 @@ +from __future__ import absolute_import + +import datetime +import logging +import os +import re +import socket +import warnings +from socket import error as SocketError +from socket import timeout as SocketTimeout + +from .packages import six +from .packages.six.moves.http_client import HTTPConnection as _HTTPConnection +from .packages.six.moves.http_client import HTTPException # noqa: F401 +from .util.proxy import create_proxy_ssl_context + +try: # Compiled with SSL? + import ssl + + BaseSSLError = ssl.SSLError +except (ImportError, AttributeError): # Platform-specific: No SSL. + ssl = None + + class BaseSSLError(BaseException): + pass + + +try: + # Python 3: not a no-op, we're adding this to the namespace so it can be imported. + ConnectionError = ConnectionError +except NameError: + # Python 2 + class ConnectionError(Exception): + pass + + +try: # Python 3: + # Not a no-op, we're adding this to the namespace so it can be imported. + BrokenPipeError = BrokenPipeError +except NameError: # Python 2: + + class BrokenPipeError(Exception): + pass + + +from ._collections import HTTPHeaderDict # noqa (historical, removed in v2) +from ._version import __version__ +from .exceptions import ( + ConnectTimeoutError, + NewConnectionError, + SubjectAltNameWarning, + SystemTimeWarning, +) +from .util import SKIP_HEADER, SKIPPABLE_HEADERS, connection +from .util.ssl_ import ( + assert_fingerprint, + create_urllib3_context, + is_ipaddress, + resolve_cert_reqs, + resolve_ssl_version, + ssl_wrap_socket, +) +from .util.ssl_match_hostname import CertificateError, match_hostname + +log = logging.getLogger(__name__) + +port_by_scheme = {"http": 80, "https": 443} + +# When it comes time to update this value as a part of regular maintenance +# (ie test_recent_date is failing) update it to ~6 months before the current date. +RECENT_DATE = datetime.date(2024, 1, 1) + +_CONTAINS_CONTROL_CHAR_RE = re.compile(r"[^-!#$%&'*+.^_`|~0-9a-zA-Z]") + + +class HTTPConnection(_HTTPConnection, object): + """ + Based on :class:`http.client.HTTPConnection` but provides an extra constructor + backwards-compatibility layer between older and newer Pythons. + + Additional keyword parameters are used to configure attributes of the connection. + Accepted parameters include: + + - ``strict``: See the documentation on :class:`urllib3.connectionpool.HTTPConnectionPool` + - ``source_address``: Set the source address for the current connection. + - ``socket_options``: Set specific options on the underlying socket. If not specified, then + defaults are loaded from ``HTTPConnection.default_socket_options`` which includes disabling + Nagle's algorithm (sets TCP_NODELAY to 1) unless the connection is behind a proxy. + + For example, if you wish to enable TCP Keep Alive in addition to the defaults, + you might pass: + + .. code-block:: python + + HTTPConnection.default_socket_options + [ + (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1), + ] + + Or you may want to disable the defaults by passing an empty list (e.g., ``[]``). + """ + + default_port = port_by_scheme["http"] + + #: Disable Nagle's algorithm by default. + #: ``[(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)]`` + default_socket_options = [(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)] + + #: Whether this connection verifies the host's certificate. + is_verified = False + + #: Whether this proxy connection (if used) verifies the proxy host's + #: certificate. + proxy_is_verified = None + + def __init__(self, *args, **kw): + if not six.PY2: + kw.pop("strict", None) + + # Pre-set source_address. + self.source_address = kw.get("source_address") + + #: The socket options provided by the user. If no options are + #: provided, we use the default options. + self.socket_options = kw.pop("socket_options", self.default_socket_options) + + # Proxy options provided by the user. + self.proxy = kw.pop("proxy", None) + self.proxy_config = kw.pop("proxy_config", None) + + _HTTPConnection.__init__(self, *args, **kw) + + @property + def host(self): + """ + Getter method to remove any trailing dots that indicate the hostname is an FQDN. + + In general, SSL certificates don't include the trailing dot indicating a + fully-qualified domain name, and thus, they don't validate properly when + checked against a domain name that includes the dot. In addition, some + servers may not expect to receive the trailing dot when provided. + + However, the hostname with trailing dot is critical to DNS resolution; doing a + lookup with the trailing dot will properly only resolve the appropriate FQDN, + whereas a lookup without a trailing dot will search the system's search domain + list. Thus, it's important to keep the original host around for use only in + those cases where it's appropriate (i.e., when doing DNS lookup to establish the + actual TCP connection across which we're going to send HTTP requests). + """ + return self._dns_host.rstrip(".") + + @host.setter + def host(self, value): + """ + Setter for the `host` property. + + We assume that only urllib3 uses the _dns_host attribute; httplib itself + only uses `host`, and it seems reasonable that other libraries follow suit. + """ + self._dns_host = value + + def _new_conn(self): + """Establish a socket connection and set nodelay settings on it. + + :return: New socket connection. + """ + extra_kw = {} + if self.source_address: + extra_kw["source_address"] = self.source_address + + if self.socket_options: + extra_kw["socket_options"] = self.socket_options + + try: + conn = connection.create_connection( + (self._dns_host, self.port), self.timeout, **extra_kw + ) + + except SocketTimeout: + raise ConnectTimeoutError( + self, + "Connection to %s timed out. (connect timeout=%s)" + % (self.host, self.timeout), + ) + + except SocketError as e: + raise NewConnectionError( + self, "Failed to establish a new connection: %s" % e + ) + + return conn + + def _is_using_tunnel(self): + # Google App Engine's httplib does not define _tunnel_host + return getattr(self, "_tunnel_host", None) + + def _prepare_conn(self, conn): + self.sock = conn + if self._is_using_tunnel(): + # TODO: Fix tunnel so it doesn't depend on self.sock state. + self._tunnel() + # Mark this connection as not reusable + self.auto_open = 0 + + def connect(self): + conn = self._new_conn() + self._prepare_conn(conn) + + def putrequest(self, method, url, *args, **kwargs): + """ """ + # Empty docstring because the indentation of CPython's implementation + # is broken but we don't want this method in our documentation. + match = _CONTAINS_CONTROL_CHAR_RE.search(method) + if match: + raise ValueError( + "Method cannot contain non-token characters %r (found at least %r)" + % (method, match.group()) + ) + + return _HTTPConnection.putrequest(self, method, url, *args, **kwargs) + + def putheader(self, header, *values): + """ """ + if not any(isinstance(v, str) and v == SKIP_HEADER for v in values): + _HTTPConnection.putheader(self, header, *values) + elif six.ensure_str(header.lower()) not in SKIPPABLE_HEADERS: + raise ValueError( + "urllib3.util.SKIP_HEADER only supports '%s'" + % ("', '".join(map(str.title, sorted(SKIPPABLE_HEADERS))),) + ) + + def request(self, method, url, body=None, headers=None): + # Update the inner socket's timeout value to send the request. + # This only triggers if the connection is re-used. + if getattr(self, "sock", None) is not None: + self.sock.settimeout(self.timeout) + + if headers is None: + headers = {} + else: + # Avoid modifying the headers passed into .request() + headers = headers.copy() + if "user-agent" not in (six.ensure_str(k.lower()) for k in headers): + headers["User-Agent"] = _get_default_user_agent() + super(HTTPConnection, self).request(method, url, body=body, headers=headers) + + def request_chunked(self, method, url, body=None, headers=None): + """ + Alternative to the common request method, which sends the + body with chunked encoding and not as one block + """ + headers = headers or {} + header_keys = set([six.ensure_str(k.lower()) for k in headers]) + skip_accept_encoding = "accept-encoding" in header_keys + skip_host = "host" in header_keys + self.putrequest( + method, url, skip_accept_encoding=skip_accept_encoding, skip_host=skip_host + ) + if "user-agent" not in header_keys: + self.putheader("User-Agent", _get_default_user_agent()) + for header, value in headers.items(): + self.putheader(header, value) + if "transfer-encoding" not in header_keys: + self.putheader("Transfer-Encoding", "chunked") + self.endheaders() + + if body is not None: + stringish_types = six.string_types + (bytes,) + if isinstance(body, stringish_types): + body = (body,) + for chunk in body: + if not chunk: + continue + if not isinstance(chunk, bytes): + chunk = chunk.encode("utf8") + len_str = hex(len(chunk))[2:] + to_send = bytearray(len_str.encode()) + to_send += b"\r\n" + to_send += chunk + to_send += b"\r\n" + self.send(to_send) + + # After the if clause, to always have a closed body + self.send(b"0\r\n\r\n") + + +class HTTPSConnection(HTTPConnection): + """ + Many of the parameters to this constructor are passed to the underlying SSL + socket by means of :py:func:`urllib3.util.ssl_wrap_socket`. + """ + + default_port = port_by_scheme["https"] + + cert_reqs = None + ca_certs = None + ca_cert_dir = None + ca_cert_data = None + ssl_version = None + assert_fingerprint = None + tls_in_tls_required = False + + def __init__( + self, + host, + port=None, + key_file=None, + cert_file=None, + key_password=None, + strict=None, + timeout=socket._GLOBAL_DEFAULT_TIMEOUT, + ssl_context=None, + server_hostname=None, + **kw + ): + + HTTPConnection.__init__(self, host, port, strict=strict, timeout=timeout, **kw) + + self.key_file = key_file + self.cert_file = cert_file + self.key_password = key_password + self.ssl_context = ssl_context + self.server_hostname = server_hostname + + # Required property for Google AppEngine 1.9.0 which otherwise causes + # HTTPS requests to go out as HTTP. (See Issue #356) + self._protocol = "https" + + def set_cert( + self, + key_file=None, + cert_file=None, + cert_reqs=None, + key_password=None, + ca_certs=None, + assert_hostname=None, + assert_fingerprint=None, + ca_cert_dir=None, + ca_cert_data=None, + ): + """ + This method should only be called once, before the connection is used. + """ + # If cert_reqs is not provided we'll assume CERT_REQUIRED unless we also + # have an SSLContext object in which case we'll use its verify_mode. + if cert_reqs is None: + if self.ssl_context is not None: + cert_reqs = self.ssl_context.verify_mode + else: + cert_reqs = resolve_cert_reqs(None) + + self.key_file = key_file + self.cert_file = cert_file + self.cert_reqs = cert_reqs + self.key_password = key_password + self.assert_hostname = assert_hostname + self.assert_fingerprint = assert_fingerprint + self.ca_certs = ca_certs and os.path.expanduser(ca_certs) + self.ca_cert_dir = ca_cert_dir and os.path.expanduser(ca_cert_dir) + self.ca_cert_data = ca_cert_data + + def connect(self): + # Add certificate verification + self.sock = conn = self._new_conn() + hostname = self.host + tls_in_tls = False + + if self._is_using_tunnel(): + if self.tls_in_tls_required: + self.sock = conn = self._connect_tls_proxy(hostname, conn) + tls_in_tls = True + + # Calls self._set_hostport(), so self.host is + # self._tunnel_host below. + self._tunnel() + # Mark this connection as not reusable + self.auto_open = 0 + + # Override the host with the one we're requesting data from. + hostname = self._tunnel_host + + server_hostname = hostname + if self.server_hostname is not None: + server_hostname = self.server_hostname + + is_time_off = datetime.date.today() < RECENT_DATE + if is_time_off: + warnings.warn( + ( + "System time is way off (before {0}). This will probably " + "lead to SSL verification errors" + ).format(RECENT_DATE), + SystemTimeWarning, + ) + + # Wrap socket using verification with the root certs in + # trusted_root_certs + default_ssl_context = False + if self.ssl_context is None: + default_ssl_context = True + self.ssl_context = create_urllib3_context( + ssl_version=resolve_ssl_version(self.ssl_version), + cert_reqs=resolve_cert_reqs(self.cert_reqs), + ) + + context = self.ssl_context + context.verify_mode = resolve_cert_reqs(self.cert_reqs) + + # Try to load OS default certs if none are given. + # Works well on Windows (requires Python3.4+) + if ( + not self.ca_certs + and not self.ca_cert_dir + and not self.ca_cert_data + and default_ssl_context + and hasattr(context, "load_default_certs") + ): + context.load_default_certs() + + self.sock = ssl_wrap_socket( + sock=conn, + keyfile=self.key_file, + certfile=self.cert_file, + key_password=self.key_password, + ca_certs=self.ca_certs, + ca_cert_dir=self.ca_cert_dir, + ca_cert_data=self.ca_cert_data, + server_hostname=server_hostname, + ssl_context=context, + tls_in_tls=tls_in_tls, + ) + + # If we're using all defaults and the connection + # is TLSv1 or TLSv1.1 we throw a DeprecationWarning + # for the host. + if ( + default_ssl_context + and self.ssl_version is None + and hasattr(self.sock, "version") + and self.sock.version() in {"TLSv1", "TLSv1.1"} + ): # Defensive: + warnings.warn( + "Negotiating TLSv1/TLSv1.1 by default is deprecated " + "and will be disabled in urllib3 v2.0.0. Connecting to " + "'%s' with '%s' can be enabled by explicitly opting-in " + "with 'ssl_version'" % (self.host, self.sock.version()), + DeprecationWarning, + ) + + if self.assert_fingerprint: + assert_fingerprint( + self.sock.getpeercert(binary_form=True), self.assert_fingerprint + ) + elif ( + context.verify_mode != ssl.CERT_NONE + and not getattr(context, "check_hostname", False) + and self.assert_hostname is not False + ): + # While urllib3 attempts to always turn off hostname matching from + # the TLS library, this cannot always be done. So we check whether + # the TLS Library still thinks it's matching hostnames. + cert = self.sock.getpeercert() + if not cert.get("subjectAltName", ()): + warnings.warn( + ( + "Certificate for {0} has no `subjectAltName`, falling back to check for a " + "`commonName` for now. This feature is being removed by major browsers and " + "deprecated by RFC 2818. (See https://github.com/urllib3/urllib3/issues/497 " + "for details.)".format(hostname) + ), + SubjectAltNameWarning, + ) + _match_hostname(cert, self.assert_hostname or server_hostname) + + self.is_verified = ( + context.verify_mode == ssl.CERT_REQUIRED + or self.assert_fingerprint is not None + ) + + def _connect_tls_proxy(self, hostname, conn): + """ + Establish a TLS connection to the proxy using the provided SSL context. + """ + proxy_config = self.proxy_config + ssl_context = proxy_config.ssl_context + if ssl_context: + # If the user provided a proxy context, we assume CA and client + # certificates have already been set + return ssl_wrap_socket( + sock=conn, + server_hostname=hostname, + ssl_context=ssl_context, + ) + + ssl_context = create_proxy_ssl_context( + self.ssl_version, + self.cert_reqs, + self.ca_certs, + self.ca_cert_dir, + self.ca_cert_data, + ) + + # If no cert was provided, use only the default options for server + # certificate validation + socket = ssl_wrap_socket( + sock=conn, + ca_certs=self.ca_certs, + ca_cert_dir=self.ca_cert_dir, + ca_cert_data=self.ca_cert_data, + server_hostname=hostname, + ssl_context=ssl_context, + ) + + if ssl_context.verify_mode != ssl.CERT_NONE and not getattr( + ssl_context, "check_hostname", False + ): + # While urllib3 attempts to always turn off hostname matching from + # the TLS library, this cannot always be done. So we check whether + # the TLS Library still thinks it's matching hostnames. + cert = socket.getpeercert() + if not cert.get("subjectAltName", ()): + warnings.warn( + ( + "Certificate for {0} has no `subjectAltName`, falling back to check for a " + "`commonName` for now. This feature is being removed by major browsers and " + "deprecated by RFC 2818. (See https://github.com/urllib3/urllib3/issues/497 " + "for details.)".format(hostname) + ), + SubjectAltNameWarning, + ) + _match_hostname(cert, hostname) + + self.proxy_is_verified = ssl_context.verify_mode == ssl.CERT_REQUIRED + return socket + + +def _match_hostname(cert, asserted_hostname): + # Our upstream implementation of ssl.match_hostname() + # only applies this normalization to IP addresses so it doesn't + # match DNS SANs so we do the same thing! + stripped_hostname = asserted_hostname.strip("u[]") + if is_ipaddress(stripped_hostname): + asserted_hostname = stripped_hostname + + try: + match_hostname(cert, asserted_hostname) + except CertificateError as e: + log.warning( + "Certificate did not match expected hostname: %s. Certificate: %s", + asserted_hostname, + cert, + ) + # Add cert to exception and reraise so client code can inspect + # the cert when catching the exception, if they want to + e._peer_cert = cert + raise + + +def _get_default_user_agent(): + return "python-urllib3/%s" % __version__ + + +class DummyConnection(object): + """Used to detect a failed ConnectionCls import.""" + + pass + + +if not ssl: + HTTPSConnection = DummyConnection # noqa: F811 + + +VerifiedHTTPSConnection = HTTPSConnection diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py new file mode 100644 index 0000000..0872ed7 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py @@ -0,0 +1,1140 @@ +from __future__ import absolute_import + +import errno +import logging +import re +import socket +import sys +import warnings +from socket import error as SocketError +from socket import timeout as SocketTimeout + +from ._collections import HTTPHeaderDict +from .connection import ( + BaseSSLError, + BrokenPipeError, + DummyConnection, + HTTPConnection, + HTTPException, + HTTPSConnection, + VerifiedHTTPSConnection, + port_by_scheme, +) +from .exceptions import ( + ClosedPoolError, + EmptyPoolError, + HeaderParsingError, + HostChangedError, + InsecureRequestWarning, + LocationValueError, + MaxRetryError, + NewConnectionError, + ProtocolError, + ProxyError, + ReadTimeoutError, + SSLError, + TimeoutError, +) +from .packages import six +from .packages.six.moves import queue +from .request import RequestMethods +from .response import HTTPResponse +from .util.connection import is_connection_dropped +from .util.proxy import connection_requires_http_tunnel +from .util.queue import LifoQueue +from .util.request import set_file_position +from .util.response import assert_header_parsing +from .util.retry import Retry +from .util.ssl_match_hostname import CertificateError +from .util.timeout import Timeout +from .util.url import Url, _encode_target +from .util.url import _normalize_host as normalize_host +from .util.url import get_host, parse_url + +try: # Platform-specific: Python 3 + import weakref + + weakref_finalize = weakref.finalize +except AttributeError: # Platform-specific: Python 2 + from .packages.backports.weakref_finalize import weakref_finalize + +xrange = six.moves.xrange + +log = logging.getLogger(__name__) + +_Default = object() + + +# Pool objects +class ConnectionPool(object): + """ + Base class for all connection pools, such as + :class:`.HTTPConnectionPool` and :class:`.HTTPSConnectionPool`. + + .. note:: + ConnectionPool.urlopen() does not normalize or percent-encode target URIs + which is useful if your target server doesn't support percent-encoded + target URIs. + """ + + scheme = None + QueueCls = LifoQueue + + def __init__(self, host, port=None): + if not host: + raise LocationValueError("No host specified.") + + self.host = _normalize_host(host, scheme=self.scheme) + self._proxy_host = host.lower() + self.port = port + + def __str__(self): + return "%s(host=%r, port=%r)" % (type(self).__name__, self.host, self.port) + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.close() + # Return False to re-raise any potential exceptions + return False + + def close(self): + """ + Close all pooled connections and disable the pool. + """ + pass + + +# This is taken from http://hg.python.org/cpython/file/7aaba721ebc0/Lib/socket.py#l252 +_blocking_errnos = {errno.EAGAIN, errno.EWOULDBLOCK} + + +class HTTPConnectionPool(ConnectionPool, RequestMethods): + """ + Thread-safe connection pool for one host. + + :param host: + Host used for this HTTP Connection (e.g. "localhost"), passed into + :class:`http.client.HTTPConnection`. + + :param port: + Port used for this HTTP Connection (None is equivalent to 80), passed + into :class:`http.client.HTTPConnection`. + + :param strict: + Causes BadStatusLine to be raised if the status line can't be parsed + as a valid HTTP/1.0 or 1.1 status line, passed into + :class:`http.client.HTTPConnection`. + + .. note:: + Only works in Python 2. This parameter is ignored in Python 3. + + :param timeout: + Socket timeout in seconds for each individual connection. This can + be a float or integer, which sets the timeout for the HTTP request, + or an instance of :class:`urllib3.util.Timeout` which gives you more + fine-grained control over request timeouts. After the constructor has + been parsed, this is always a `urllib3.util.Timeout` object. + + :param maxsize: + Number of connections to save that can be reused. More than 1 is useful + in multithreaded situations. If ``block`` is set to False, more + connections will be created but they will not be saved once they've + been used. + + :param block: + If set to True, no more than ``maxsize`` connections will be used at + a time. When no free connections are available, the call will block + until a connection has been released. This is a useful side effect for + particular multithreaded situations where one does not want to use more + than maxsize connections per host to prevent flooding. + + :param headers: + Headers to include with all requests, unless other headers are given + explicitly. + + :param retries: + Retry configuration to use by default with requests in this pool. + + :param _proxy: + Parsed proxy URL, should not be used directly, instead, see + :class:`urllib3.ProxyManager` + + :param _proxy_headers: + A dictionary with proxy headers, should not be used directly, + instead, see :class:`urllib3.ProxyManager` + + :param \\**conn_kw: + Additional parameters are used to create fresh :class:`urllib3.connection.HTTPConnection`, + :class:`urllib3.connection.HTTPSConnection` instances. + """ + + scheme = "http" + ConnectionCls = HTTPConnection + ResponseCls = HTTPResponse + + def __init__( + self, + host, + port=None, + strict=False, + timeout=Timeout.DEFAULT_TIMEOUT, + maxsize=1, + block=False, + headers=None, + retries=None, + _proxy=None, + _proxy_headers=None, + _proxy_config=None, + **conn_kw + ): + ConnectionPool.__init__(self, host, port) + RequestMethods.__init__(self, headers) + + self.strict = strict + + if not isinstance(timeout, Timeout): + timeout = Timeout.from_float(timeout) + + if retries is None: + retries = Retry.DEFAULT + + self.timeout = timeout + self.retries = retries + + self.pool = self.QueueCls(maxsize) + self.block = block + + self.proxy = _proxy + self.proxy_headers = _proxy_headers or {} + self.proxy_config = _proxy_config + + # Fill the queue up so that doing get() on it will block properly + for _ in xrange(maxsize): + self.pool.put(None) + + # These are mostly for testing and debugging purposes. + self.num_connections = 0 + self.num_requests = 0 + self.conn_kw = conn_kw + + if self.proxy: + # Enable Nagle's algorithm for proxies, to avoid packet fragmentation. + # We cannot know if the user has added default socket options, so we cannot replace the + # list. + self.conn_kw.setdefault("socket_options", []) + + self.conn_kw["proxy"] = self.proxy + self.conn_kw["proxy_config"] = self.proxy_config + + # Do not pass 'self' as callback to 'finalize'. + # Then the 'finalize' would keep an endless living (leak) to self. + # By just passing a reference to the pool allows the garbage collector + # to free self if nobody else has a reference to it. + pool = self.pool + + # Close all the HTTPConnections in the pool before the + # HTTPConnectionPool object is garbage collected. + weakref_finalize(self, _close_pool_connections, pool) + + def _new_conn(self): + """ + Return a fresh :class:`HTTPConnection`. + """ + self.num_connections += 1 + log.debug( + "Starting new HTTP connection (%d): %s:%s", + self.num_connections, + self.host, + self.port or "80", + ) + + conn = self.ConnectionCls( + host=self.host, + port=self.port, + timeout=self.timeout.connect_timeout, + strict=self.strict, + **self.conn_kw + ) + return conn + + def _get_conn(self, timeout=None): + """ + Get a connection. Will return a pooled connection if one is available. + + If no connections are available and :prop:`.block` is ``False``, then a + fresh connection is returned. + + :param timeout: + Seconds to wait before giving up and raising + :class:`urllib3.exceptions.EmptyPoolError` if the pool is empty and + :prop:`.block` is ``True``. + """ + conn = None + try: + conn = self.pool.get(block=self.block, timeout=timeout) + + except AttributeError: # self.pool is None + raise ClosedPoolError(self, "Pool is closed.") + + except queue.Empty: + if self.block: + raise EmptyPoolError( + self, + "Pool reached maximum size and no more connections are allowed.", + ) + pass # Oh well, we'll create a new connection then + + # If this is a persistent connection, check if it got disconnected + if conn and is_connection_dropped(conn): + log.debug("Resetting dropped connection: %s", self.host) + conn.close() + if getattr(conn, "auto_open", 1) == 0: + # This is a proxied connection that has been mutated by + # http.client._tunnel() and cannot be reused (since it would + # attempt to bypass the proxy) + conn = None + + return conn or self._new_conn() + + def _put_conn(self, conn): + """ + Put a connection back into the pool. + + :param conn: + Connection object for the current host and port as returned by + :meth:`._new_conn` or :meth:`._get_conn`. + + If the pool is already full, the connection is closed and discarded + because we exceeded maxsize. If connections are discarded frequently, + then maxsize should be increased. + + If the pool is closed, then the connection will be closed and discarded. + """ + try: + self.pool.put(conn, block=False) + return # Everything is dandy, done. + except AttributeError: + # self.pool is None. + pass + except queue.Full: + # This should never happen if self.block == True + log.warning( + "Connection pool is full, discarding connection: %s. Connection pool size: %s", + self.host, + self.pool.qsize(), + ) + # Connection never got put back into the pool, close it. + if conn: + conn.close() + + def _validate_conn(self, conn): + """ + Called right before a request is made, after the socket is created. + """ + pass + + def _prepare_proxy(self, conn): + # Nothing to do for HTTP connections. + pass + + def _get_timeout(self, timeout): + """Helper that always returns a :class:`urllib3.util.Timeout`""" + if timeout is _Default: + return self.timeout.clone() + + if isinstance(timeout, Timeout): + return timeout.clone() + else: + # User passed us an int/float. This is for backwards compatibility, + # can be removed later + return Timeout.from_float(timeout) + + def _raise_timeout(self, err, url, timeout_value): + """Is the error actually a timeout? Will raise a ReadTimeout or pass""" + + if isinstance(err, SocketTimeout): + raise ReadTimeoutError( + self, url, "Read timed out. (read timeout=%s)" % timeout_value + ) + + # See the above comment about EAGAIN in Python 3. In Python 2 we have + # to specifically catch it and throw the timeout error + if hasattr(err, "errno") and err.errno in _blocking_errnos: + raise ReadTimeoutError( + self, url, "Read timed out. (read timeout=%s)" % timeout_value + ) + + # Catch possible read timeouts thrown as SSL errors. If not the + # case, rethrow the original. We need to do this because of: + # http://bugs.python.org/issue10272 + if "timed out" in str(err) or "did not complete (read)" in str( + err + ): # Python < 2.7.4 + raise ReadTimeoutError( + self, url, "Read timed out. (read timeout=%s)" % timeout_value + ) + + def _make_request( + self, conn, method, url, timeout=_Default, chunked=False, **httplib_request_kw + ): + """ + Perform a request on a given urllib connection object taken from our + pool. + + :param conn: + a connection from one of our connection pools + + :param timeout: + Socket timeout in seconds for the request. This can be a + float or integer, which will set the same timeout value for + the socket connect and the socket read, or an instance of + :class:`urllib3.util.Timeout`, which gives you more fine-grained + control over your timeouts. + """ + self.num_requests += 1 + + timeout_obj = self._get_timeout(timeout) + timeout_obj.start_connect() + conn.timeout = Timeout.resolve_default_timeout(timeout_obj.connect_timeout) + + # Trigger any extra validation we need to do. + try: + self._validate_conn(conn) + except (SocketTimeout, BaseSSLError) as e: + # Py2 raises this as a BaseSSLError, Py3 raises it as socket timeout. + self._raise_timeout(err=e, url=url, timeout_value=conn.timeout) + raise + + # conn.request() calls http.client.*.request, not the method in + # urllib3.request. It also calls makefile (recv) on the socket. + try: + if chunked: + conn.request_chunked(method, url, **httplib_request_kw) + else: + conn.request(method, url, **httplib_request_kw) + + # We are swallowing BrokenPipeError (errno.EPIPE) since the server is + # legitimately able to close the connection after sending a valid response. + # With this behaviour, the received response is still readable. + except BrokenPipeError: + # Python 3 + pass + except IOError as e: + # Python 2 and macOS/Linux + # EPIPE and ESHUTDOWN are BrokenPipeError on Python 2, and EPROTOTYPE/ECONNRESET are needed on macOS + # https://erickt.github.io/blog/2014/11/19/adventures-in-debugging-a-potential-osx-kernel-bug/ + if e.errno not in { + errno.EPIPE, + errno.ESHUTDOWN, + errno.EPROTOTYPE, + errno.ECONNRESET, + }: + raise + + # Reset the timeout for the recv() on the socket + read_timeout = timeout_obj.read_timeout + + # App Engine doesn't have a sock attr + if getattr(conn, "sock", None): + # In Python 3 socket.py will catch EAGAIN and return None when you + # try and read into the file pointer created by http.client, which + # instead raises a BadStatusLine exception. Instead of catching + # the exception and assuming all BadStatusLine exceptions are read + # timeouts, check for a zero timeout before making the request. + if read_timeout == 0: + raise ReadTimeoutError( + self, url, "Read timed out. (read timeout=%s)" % read_timeout + ) + if read_timeout is Timeout.DEFAULT_TIMEOUT: + conn.sock.settimeout(socket.getdefaulttimeout()) + else: # None or a value + conn.sock.settimeout(read_timeout) + + # Receive the response from the server + try: + try: + # Python 2.7, use buffering of HTTP responses + httplib_response = conn.getresponse(buffering=True) + except TypeError: + # Python 3 + try: + httplib_response = conn.getresponse() + except BaseException as e: + # Remove the TypeError from the exception chain in + # Python 3 (including for exceptions like SystemExit). + # Otherwise it looks like a bug in the code. + six.raise_from(e, None) + except (SocketTimeout, BaseSSLError, SocketError) as e: + self._raise_timeout(err=e, url=url, timeout_value=read_timeout) + raise + + # AppEngine doesn't have a version attr. + http_version = getattr(conn, "_http_vsn_str", "HTTP/?") + log.debug( + '%s://%s:%s "%s %s %s" %s %s', + self.scheme, + self.host, + self.port, + method, + url, + http_version, + httplib_response.status, + httplib_response.length, + ) + + try: + assert_header_parsing(httplib_response.msg) + except (HeaderParsingError, TypeError) as hpe: # Platform-specific: Python 3 + log.warning( + "Failed to parse headers (url=%s): %s", + self._absolute_url(url), + hpe, + exc_info=True, + ) + + return httplib_response + + def _absolute_url(self, path): + return Url(scheme=self.scheme, host=self.host, port=self.port, path=path).url + + def close(self): + """ + Close all pooled connections and disable the pool. + """ + if self.pool is None: + return + # Disable access to the pool + old_pool, self.pool = self.pool, None + + # Close all the HTTPConnections in the pool. + _close_pool_connections(old_pool) + + def is_same_host(self, url): + """ + Check if the given ``url`` is a member of the same host as this + connection pool. + """ + if url.startswith("/"): + return True + + # TODO: Add optional support for socket.gethostbyname checking. + scheme, host, port = get_host(url) + if host is not None: + host = _normalize_host(host, scheme=scheme) + + # Use explicit default port for comparison when none is given + if self.port and not port: + port = port_by_scheme.get(scheme) + elif not self.port and port == port_by_scheme.get(scheme): + port = None + + return (scheme, host, port) == (self.scheme, self.host, self.port) + + def urlopen( + self, + method, + url, + body=None, + headers=None, + retries=None, + redirect=True, + assert_same_host=True, + timeout=_Default, + pool_timeout=None, + release_conn=None, + chunked=False, + body_pos=None, + **response_kw + ): + """ + Get a connection from the pool and perform an HTTP request. This is the + lowest level call for making a request, so you'll need to specify all + the raw details. + + .. note:: + + More commonly, it's appropriate to use a convenience method provided + by :class:`.RequestMethods`, such as :meth:`request`. + + .. note:: + + `release_conn` will only behave as expected if + `preload_content=False` because we want to make + `preload_content=False` the default behaviour someday soon without + breaking backwards compatibility. + + :param method: + HTTP request method (such as GET, POST, PUT, etc.) + + :param url: + The URL to perform the request on. + + :param body: + Data to send in the request body, either :class:`str`, :class:`bytes`, + an iterable of :class:`str`/:class:`bytes`, or a file-like object. + + :param headers: + Dictionary of custom headers to send, such as User-Agent, + If-None-Match, etc. If None, pool headers are used. If provided, + these headers completely replace any pool-specific headers. + + :param retries: + Configure the number of retries to allow before raising a + :class:`~urllib3.exceptions.MaxRetryError` exception. + + Pass ``None`` to retry until you receive a response. Pass a + :class:`~urllib3.util.retry.Retry` object for fine-grained control + over different types of retries. + Pass an integer number to retry connection errors that many times, + but no other types of errors. Pass zero to never retry. + + If ``False``, then retries are disabled and any exception is raised + immediately. Also, instead of raising a MaxRetryError on redirects, + the redirect response will be returned. + + :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. + + :param redirect: + If True, automatically handle redirects (status codes 301, 302, + 303, 307, 308). Each redirect counts as a retry. Disabling retries + will disable redirect, too. + + :param assert_same_host: + If ``True``, will make sure that the host of the pool requests is + consistent else will raise HostChangedError. When ``False``, you can + use the pool on an HTTP proxy and request foreign hosts. + + :param timeout: + If specified, overrides the default timeout for this one + request. It may be a float (in seconds) or an instance of + :class:`urllib3.util.Timeout`. + + :param pool_timeout: + If set and the pool is set to block=True, then this method will + block for ``pool_timeout`` seconds and raise EmptyPoolError if no + connection is available within the time period. + + :param release_conn: + If False, then the urlopen call will not release the connection + back into the pool once a response is received (but will release if + you read the entire contents of the response such as when + `preload_content=True`). This is useful if you're not preloading + the response's content immediately. You will need to call + ``r.release_conn()`` on the response ``r`` to return the connection + back into the pool. If None, it takes the value of + ``response_kw.get('preload_content', True)``. + + :param chunked: + If True, urllib3 will send the body using chunked transfer + encoding. Otherwise, urllib3 will send the body using the standard + content-length form. Defaults to False. + + :param int body_pos: + Position to seek to in file-like body in the event of a retry or + redirect. Typically this won't need to be set because urllib3 will + auto-populate the value when needed. + + :param \\**response_kw: + Additional parameters are passed to + :meth:`urllib3.response.HTTPResponse.from_httplib` + """ + + parsed_url = parse_url(url) + destination_scheme = parsed_url.scheme + + if headers is None: + headers = self.headers + + if not isinstance(retries, Retry): + retries = Retry.from_int(retries, redirect=redirect, default=self.retries) + + if release_conn is None: + release_conn = response_kw.get("preload_content", True) + + # Check host + if assert_same_host and not self.is_same_host(url): + raise HostChangedError(self, url, retries) + + # Ensure that the URL we're connecting to is properly encoded + if url.startswith("/"): + url = six.ensure_str(_encode_target(url)) + else: + url = six.ensure_str(parsed_url.url) + + conn = None + + # Track whether `conn` needs to be released before + # returning/raising/recursing. Update this variable if necessary, and + # leave `release_conn` constant throughout the function. That way, if + # the function recurses, the original value of `release_conn` will be + # passed down into the recursive call, and its value will be respected. + # + # See issue #651 [1] for details. + # + # [1] + release_this_conn = release_conn + + http_tunnel_required = connection_requires_http_tunnel( + self.proxy, self.proxy_config, destination_scheme + ) + + # Merge the proxy headers. Only done when not using HTTP CONNECT. We + # have to copy the headers dict so we can safely change it without those + # changes being reflected in anyone else's copy. + if not http_tunnel_required: + headers = headers.copy() + headers.update(self.proxy_headers) + + # Must keep the exception bound to a separate variable or else Python 3 + # complains about UnboundLocalError. + err = None + + # Keep track of whether we cleanly exited the except block. This + # ensures we do proper cleanup in finally. + clean_exit = False + + # Rewind body position, if needed. Record current position + # for future rewinds in the event of a redirect/retry. + body_pos = set_file_position(body, body_pos) + + try: + # Request a connection from the queue. + timeout_obj = self._get_timeout(timeout) + conn = self._get_conn(timeout=pool_timeout) + + conn.timeout = timeout_obj.connect_timeout + + is_new_proxy_conn = self.proxy is not None and not getattr( + conn, "sock", None + ) + if is_new_proxy_conn and http_tunnel_required: + self._prepare_proxy(conn) + + # Make the request on the httplib connection object. + httplib_response = self._make_request( + conn, + method, + url, + timeout=timeout_obj, + body=body, + headers=headers, + chunked=chunked, + ) + + # If we're going to release the connection in ``finally:``, then + # the response doesn't need to know about the connection. Otherwise + # it will also try to release it and we'll have a double-release + # mess. + response_conn = conn if not release_conn else None + + # Pass method to Response for length checking + response_kw["request_method"] = method + + # Import httplib's response into our own wrapper object + response = self.ResponseCls.from_httplib( + httplib_response, + pool=self, + connection=response_conn, + retries=retries, + **response_kw + ) + + # Everything went great! + clean_exit = True + + except EmptyPoolError: + # Didn't get a connection from the pool, no need to clean up + clean_exit = True + release_this_conn = False + raise + + except ( + TimeoutError, + HTTPException, + SocketError, + ProtocolError, + BaseSSLError, + SSLError, + CertificateError, + ) as e: + # Discard the connection for these exceptions. It will be + # replaced during the next _get_conn() call. + clean_exit = False + + def _is_ssl_error_message_from_http_proxy(ssl_error): + # We're trying to detect the message 'WRONG_VERSION_NUMBER' but + # SSLErrors are kinda all over the place when it comes to the message, + # so we try to cover our bases here! + message = " ".join(re.split("[^a-z]", str(ssl_error).lower())) + return ( + "wrong version number" in message + or "unknown protocol" in message + or "record layer failure" in message + ) + + # Try to detect a common user error with proxies which is to + # set an HTTP proxy to be HTTPS when it should be 'http://' + # (ie {'http': 'http://proxy', 'https': 'https://proxy'}) + # Instead we add a nice error message and point to a URL. + if ( + isinstance(e, BaseSSLError) + and self.proxy + and _is_ssl_error_message_from_http_proxy(e) + and conn.proxy + and conn.proxy.scheme == "https" + ): + e = ProxyError( + "Your proxy appears to only use HTTP and not HTTPS, " + "try changing your proxy URL to be HTTP. See: " + "https://urllib3.readthedocs.io/en/1.26.x/advanced-usage.html" + "#https-proxy-error-http-proxy", + SSLError(e), + ) + elif isinstance(e, (BaseSSLError, CertificateError)): + e = SSLError(e) + elif isinstance(e, (SocketError, NewConnectionError)) and self.proxy: + e = ProxyError("Cannot connect to proxy.", e) + elif isinstance(e, (SocketError, HTTPException)): + e = ProtocolError("Connection aborted.", e) + + retries = retries.increment( + method, url, error=e, _pool=self, _stacktrace=sys.exc_info()[2] + ) + retries.sleep() + + # Keep track of the error for the retry warning. + err = e + + finally: + if not clean_exit: + # We hit some kind of exception, handled or otherwise. We need + # to throw the connection away unless explicitly told not to. + # Close the connection, set the variable to None, and make sure + # we put the None back in the pool to avoid leaking it. + conn = conn and conn.close() + release_this_conn = True + + if release_this_conn: + # Put the connection back to be reused. If the connection is + # expired then it will be None, which will get replaced with a + # fresh connection during _get_conn. + self._put_conn(conn) + + if not conn: + # Try again + log.warning( + "Retrying (%r) after connection broken by '%r': %s", retries, err, url + ) + return self.urlopen( + method, + url, + body, + headers, + retries, + redirect, + assert_same_host, + timeout=timeout, + pool_timeout=pool_timeout, + release_conn=release_conn, + chunked=chunked, + body_pos=body_pos, + **response_kw + ) + + # Handle redirect? + redirect_location = redirect and response.get_redirect_location() + if redirect_location: + if response.status == 303: + # Change the method according to RFC 9110, Section 15.4.4. + method = "GET" + # And lose the body not to transfer anything sensitive. + body = None + headers = HTTPHeaderDict(headers)._prepare_for_method_change() + + try: + retries = retries.increment(method, url, response=response, _pool=self) + except MaxRetryError: + if retries.raise_on_redirect: + response.drain_conn() + raise + return response + + response.drain_conn() + retries.sleep_for_retry(response) + log.debug("Redirecting %s -> %s", url, redirect_location) + return self.urlopen( + method, + redirect_location, + body, + headers, + retries=retries, + redirect=redirect, + assert_same_host=assert_same_host, + timeout=timeout, + pool_timeout=pool_timeout, + release_conn=release_conn, + chunked=chunked, + body_pos=body_pos, + **response_kw + ) + + # Check if we should retry the HTTP response. + has_retry_after = bool(response.headers.get("Retry-After")) + if retries.is_retry(method, response.status, has_retry_after): + try: + retries = retries.increment(method, url, response=response, _pool=self) + except MaxRetryError: + if retries.raise_on_status: + response.drain_conn() + raise + return response + + response.drain_conn() + retries.sleep(response) + log.debug("Retry: %s", url) + return self.urlopen( + method, + url, + body, + headers, + retries=retries, + redirect=redirect, + assert_same_host=assert_same_host, + timeout=timeout, + pool_timeout=pool_timeout, + release_conn=release_conn, + chunked=chunked, + body_pos=body_pos, + **response_kw + ) + + return response + + +class HTTPSConnectionPool(HTTPConnectionPool): + """ + Same as :class:`.HTTPConnectionPool`, but HTTPS. + + :class:`.HTTPSConnection` uses one of ``assert_fingerprint``, + ``assert_hostname`` and ``host`` in this order to verify connections. + If ``assert_hostname`` is False, no verification is done. + + The ``key_file``, ``cert_file``, ``cert_reqs``, ``ca_certs``, + ``ca_cert_dir``, ``ssl_version``, ``key_password`` are only used if :mod:`ssl` + is available and are fed into :meth:`urllib3.util.ssl_wrap_socket` to upgrade + the connection socket into an SSL socket. + """ + + scheme = "https" + ConnectionCls = HTTPSConnection + + def __init__( + self, + host, + port=None, + strict=False, + timeout=Timeout.DEFAULT_TIMEOUT, + maxsize=1, + block=False, + headers=None, + retries=None, + _proxy=None, + _proxy_headers=None, + key_file=None, + cert_file=None, + cert_reqs=None, + key_password=None, + ca_certs=None, + ssl_version=None, + assert_hostname=None, + assert_fingerprint=None, + ca_cert_dir=None, + **conn_kw + ): + + HTTPConnectionPool.__init__( + self, + host, + port, + strict, + timeout, + maxsize, + block, + headers, + retries, + _proxy, + _proxy_headers, + **conn_kw + ) + + self.key_file = key_file + self.cert_file = cert_file + self.cert_reqs = cert_reqs + self.key_password = key_password + self.ca_certs = ca_certs + self.ca_cert_dir = ca_cert_dir + self.ssl_version = ssl_version + self.assert_hostname = assert_hostname + self.assert_fingerprint = assert_fingerprint + + def _prepare_conn(self, conn): + """ + Prepare the ``connection`` for :meth:`urllib3.util.ssl_wrap_socket` + and establish the tunnel if proxy is used. + """ + + if isinstance(conn, VerifiedHTTPSConnection): + conn.set_cert( + key_file=self.key_file, + key_password=self.key_password, + cert_file=self.cert_file, + cert_reqs=self.cert_reqs, + ca_certs=self.ca_certs, + ca_cert_dir=self.ca_cert_dir, + assert_hostname=self.assert_hostname, + assert_fingerprint=self.assert_fingerprint, + ) + conn.ssl_version = self.ssl_version + return conn + + def _prepare_proxy(self, conn): + """ + Establishes a tunnel connection through HTTP CONNECT. + + Tunnel connection is established early because otherwise httplib would + improperly set Host: header to proxy's IP:port. + """ + + conn.set_tunnel(self._proxy_host, self.port, self.proxy_headers) + + if self.proxy.scheme == "https": + conn.tls_in_tls_required = True + + conn.connect() + + def _new_conn(self): + """ + Return a fresh :class:`http.client.HTTPSConnection`. + """ + self.num_connections += 1 + log.debug( + "Starting new HTTPS connection (%d): %s:%s", + self.num_connections, + self.host, + self.port or "443", + ) + + if not self.ConnectionCls or self.ConnectionCls is DummyConnection: + raise SSLError( + "Can't connect to HTTPS URL because the SSL module is not available." + ) + + actual_host = self.host + actual_port = self.port + if self.proxy is not None: + actual_host = self.proxy.host + actual_port = self.proxy.port + + conn = self.ConnectionCls( + host=actual_host, + port=actual_port, + timeout=self.timeout.connect_timeout, + strict=self.strict, + cert_file=self.cert_file, + key_file=self.key_file, + key_password=self.key_password, + **self.conn_kw + ) + + return self._prepare_conn(conn) + + def _validate_conn(self, conn): + """ + Called right before a request is made, after the socket is created. + """ + super(HTTPSConnectionPool, self)._validate_conn(conn) + + # Force connect early to allow us to validate the connection. + if not getattr(conn, "sock", None): # AppEngine might not have `.sock` + conn.connect() + + if not conn.is_verified: + warnings.warn( + ( + "Unverified HTTPS request is being made to host '%s'. " + "Adding certificate verification is strongly advised. See: " + "https://urllib3.readthedocs.io/en/1.26.x/advanced-usage.html" + "#ssl-warnings" % conn.host + ), + InsecureRequestWarning, + ) + + if getattr(conn, "proxy_is_verified", None) is False: + warnings.warn( + ( + "Unverified HTTPS connection done to an HTTPS proxy. " + "Adding certificate verification is strongly advised. See: " + "https://urllib3.readthedocs.io/en/1.26.x/advanced-usage.html" + "#ssl-warnings" + ), + InsecureRequestWarning, + ) + + +def connection_from_url(url, **kw): + """ + Given a url, return an :class:`.ConnectionPool` instance of its host. + + This is a shortcut for not having to parse out the scheme, host, and port + of the url before creating an :class:`.ConnectionPool` instance. + + :param url: + Absolute URL string that must include the scheme. Port is optional. + + :param \\**kw: + Passes additional parameters to the constructor of the appropriate + :class:`.ConnectionPool`. Useful for specifying things like + timeout, maxsize, headers, etc. + + Example:: + + >>> conn = connection_from_url('http://google.com/') + >>> r = conn.request('GET', '/') + """ + scheme, host, port = get_host(url) + port = port or port_by_scheme.get(scheme, 80) + if scheme == "https": + return HTTPSConnectionPool(host, port=port, **kw) + else: + return HTTPConnectionPool(host, port=port, **kw) + + +def _normalize_host(host, scheme): + """ + Normalize hosts for comparisons and use with sockets. + """ + + host = normalize_host(host, scheme) + + # httplib doesn't like it when we include brackets in IPv6 addresses + # Specifically, if we include brackets but also pass the port then + # httplib crazily doubles up the square brackets on the Host header. + # Instead, we need to make sure we never pass ``None`` as the port. + # However, for backward compatibility reasons we can't actually + # *assert* that. See http://bugs.python.org/issue28539 + if host.startswith("[") and host.endswith("]"): + host = host[1:-1] + return host + + +def _close_pool_connections(pool): + """Drains a queue of connections and closes each one.""" + try: + while True: + conn = pool.get(block=False) + if conn: + conn.close() + except queue.Empty: + pass # Done. diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__init__.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6a347695c9c86bbbb85b7fd5e48b5bb214279982 GIT binary patch literal 202 zcmX@j%ge<81isO>nIQTxh(HIQS%4zb87dhx8U0o=6fpsLpFwJVWjb5Ml;;;^7Z)TZ zr^e)El@#kHCMV~Y=9OgTrRyf=7p2A|B_?O5=B32wm8IsD#rR|<#S~|jr0N1SWGAMl z7RMB17U;(VW3bq#9Vnav*ZX<`_L=Cpvf-6{7J7a0()y^_A zQY@cb=%LU{Z*HMb3WXAU3KViG^xlgS=Ma`23O$tGQoE;~`eyYbj_v*deXwtz=FPtO z=6m0aei<3bAh5fiTz7wpA@sZcF)*Va92FthLlkWwimBn@4NPO7p$&t^!N+I#ihCPFo%$f#7YIGWgAGUlPR$Wr{h9s5&D{K|o4=&Gi{!e%lq? zZ!%vMGk4k25L8KsYHc88n*+XZMBqo5QL4#2v4iirp#g|}& z8e4B81mwl+Y2bR51zade+|8(QfRaFuMa%br590dK=%y>AA~ohSVJnyWMA|;B^6g?K zL%`OdG>1(wDR-nP73|9v)Er=sDukm;_wJR-w{Dk9*6N4l_1kw#VLIrjI``)n z3$du5p}}RC>bG1Zf#;}+LiafwKi+<;&z(3AsT@3#fZIiXpF_EeU)*?-UHPW^ZR6`k zw{Y!o{`$|8kMk?t_{wQX=mtmU=5q+(EMo=lo;8Lt7>pp)M%!4JAd%tFS+g36VR{%) zgU0sz6&qTaCyd7T`)3wJl_-lWY0>K D1Hzv( literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2a1a1c16af228f042553d4fe6490e939eab011f2 GIT binary patch literal 11568 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..70e998ff04d83b49a99276a0143ef30d59f6ad69 GIT binary patch literal 5718 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

    QwlHjRi)Bbm{OEiIz1Rd4k4ul5Xz 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 WKMw7FUSvPs6@I>#{dhkE?f(KPYkk`Q literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py new file mode 100644 index 0000000..8765b90 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py @@ -0,0 +1,36 @@ +""" +This module provides means to detect the App Engine environment. +""" + +import os + + +def is_appengine(): + return is_local_appengine() or is_prod_appengine() + + +def is_appengine_sandbox(): + """Reports if the app is running in the first generation sandbox. + + The second generation runtimes are technically still in a sandbox, but it + is much less restrictive, so generally you shouldn't need to check for it. + see https://cloud.google.com/appengine/docs/standard/runtimes + """ + return is_appengine() and os.environ["APPENGINE_RUNTIME"] == "python27" + + +def is_local_appengine(): + return "APPENGINE_RUNTIME" in os.environ and os.environ.get( + "SERVER_SOFTWARE", "" + ).startswith("Development/") + + +def is_prod_appengine(): + return "APPENGINE_RUNTIME" in os.environ and os.environ.get( + "SERVER_SOFTWARE", "" + ).startswith("Google App Engine/") + + +def is_prod_appengine_mvms(): + """Deprecated.""" + return False diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b34987bb5a12b9693997bedd52fe9661c6573fdf GIT binary patch literal 219 zcmZ8bF%H5o3~VS!2&oTYC>hugu&@FjAX1d37BVeKY2yfsm{D74gAT}n_m6Ogs z`_7UdMKQ_}HoFCO{neF!eEMl~%P!fNZSNWN()8&v-|K27&XyYQlm=lA!Iw&F8%;p7 zFSR8QmC_BET1-x0PGXIf@ED*>2aVc;7Y-el$*V2#NNtPNlxu4OVa25f9SH&{ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..09c832e1820468652a2abb5ab56211591104d355 GIT binary patch literal 17431 zcmb_?3ve4rdftE-k|6kgzs2F3AOVmBAEF*B2?RkAyCldXC{dbh3I$?@BqTiO89)-1 zbBfuzO4dFlDs*9!j|q?rAS~ zbxHa1|2@-~0R+ldm9T{F{{Q~_>%ag0yZi4R{rlQlD+7OPf8(77JK+r)3;dK;scXV_cey^1L;1YUTC0*JV!W-ZtDfggt72>eFjHwHf&{KnxoA=dMDXk95z&|Y{4@SS2cKS}t*dHxik zNAmPEp-1zyi_l|vdWO)pJUt7zbMTvo-+5Bkkgr<+JukrTViErm@GgV=J4O5}z`qK= zYejr_5xod99{4T6&kMh0_+5wJN);nciRuV0P%TK?iEk2&0rl9z%4B zQ+s8g?XT zwt8NKQc6NcnG$D<{2j;r9UYC9icm{Q3I=qDT!j#{LVnU{Eu}kS_DgNfcwg%@+TWqUm{&)}A>BGFV z16EG|oi8b^=Y~0OoFSplfr|3K^wzYbqX=d|DJ4;i@*~<-&vg{h4k)E0bQCAVC_}LN z`tST$N1!DG()1Y;I?^=Yl!4U$p{@1YfMY#F!iZxP2LX!($-mMuXvu(OIYUCn!qE-l z=pLEwPyj=2z?wQ!Mn{{%*$1RD1B6yIAPt@=^ClAeR-^`kR7yria+34GLC=Rm3hX#9 zp5Ln=I2CX0YxYbTy{}o(finyiu)GxuR=^oDI#!Y1py?dWIJC3A729>Di~*aVsk2`5 zRDq3dgm&@KMb$7Yqw|1#nB0Jqn`eROCZWW;+zjKrFl z+sq^LFZ||x=7IS(bKj)#tH?`ko6t$u;RhxvVLKN(gr#TQ+KxSdE`;6mK}{RGtQq~hUyF0sq)LLnJR#APl7)nO z;_^X4N;xNZNX|mS<>WM+L3W$>At8K9Iy@@{rq;5;9TZenPs--H#;qomSNb;RL7z z3Wm6y5DZBYBC;rO_e4pC!Q#MCT_UubNWsV>ac(;jjdF{LxG*Yn2{|ks9>4&iksT={ z9XdI8oD<^-DV9jdoFMKb5j=4pFu?@-kr=m|khq;_=wT$j2iRyDDHMqkc1m_~%LxgT z4<$KC49SVOU6mmU$oq*@RN!_{pSTRBlvGs00F8m#NhJ5VokK1qMM0sNQ5p0Ki*d9h z=nfTB-%M0nwcUm& z#Ue5>5{v<-8PNB@1CpX(2d@xCG+uZ=B<+bXhy*Bb$Q^)L(W*PiP$Z592oW8^po3~^ zfRYot$@@6(sBuV^6X8e*FgYO+PQ}0xLg?Sl9J*G$K}diJNzZr0a1xQw2)l_WtT`Me_>K@ED_Qe^EvOFdB<`VG zQD2BBlAt!30^*}Eadft|DtR9kB>JLiKfZ*99by__$=ZEUXJ^euUpxB+(n=m9&o?b}*ezp=%E#HQQ7b(>pX=G^|< z+)ax=^{;PntG+eg765OplTI}_ zpBLILb8FsB&kCTs7k#U~t=sCnE&I0oh`qeN$+@`=_vV(*b7R%L$!*-&+*l8IL5(GV z_WS(Ho6wVY&FkNCLeIeCyf=a10xRy-RqT!^=e_|W*+gAA&-%vgP2csEEpBCfb;%3N zMK5URUR?F6-N67ot8U+#om+CRxv!&^o7_4espCXZRa0(z#fxn0*A4$XTfTKa4#~6b z-`WJy4kO;&$~WKk1-y37z3B^p%0#W@&2{JoO$@D|7XX5`ey@sz<}aKj5W!iy0R|}0 zY02we1x%PWe?bGM^%Wj%Hj`2x+L04cSR=tm4E@4yt5I0b((0;GpuUMcT=ed2X_*QD9I0#qGAaLac2o0D3#%0B%YjcVO2B{-@__7@=y#Wv6NElKqy5k z?-ne}d`m`|#n@{8iJ>mc^@+C`JCh%6zPSg8kXDua?Ob$$W7Bfhmc2s#KX! z_S853p>$|A9^mnkCB3W5DJU$$L}O%M<^VI^FIj# za)c9-_&$zGj0^8O?}_ny@2^I7-j^du(E$zahW14H{e#HCWDx3vgfyw0#*?u1;>j=> zlu5h<2frFGO=8Fe$g=a`P^rS<1;au#Dh+@-_;Mk`>@!EqDO+9cH+@;b)O0*vcu_r= zZ65f!rN3zI`-sgn4}ZAyvcCEArp^!7KCf?nwDi%^Nxdy?vHj@t>Zb2ACTRD$rRg7B zO7~rP-g4aM%``86%KnLE?bM7_KbGsEgAXR0%?Zy zF*XUq#2{yKSpp*x15HvP=Pu>tSxTJ;EVYbb6FIaWF1`h)P}G1{SfO;?g&wsjeSiyb z17d`OeJLc1N}FEi19g1@#*N8CrTMOB*$wAkIFw9COX6-Q6-_Fwz}$kE*DXn*Ll5}s zB21mE^lI!SH9&yTz9$;0``)O&8H%RFeEWx;#L?g|gfli2jgT-;jjh9A>7D zeUlLx-UR>2qf9XIX1JoTLK$6meEFf-#wwMbWe>*O4})Z*c5~q%v;F1v9-MLZRRzaK;?-WM(Nnw zE+)T>$GD|H2AG3_d|_i{Sl$xTs)9oZMZ2OFlK?&1bMs2mm{+-gP`1Aj@3 zAF9WJfq4T?R52XcjX;Buq6V8{7;ZUIXeSC!70~T6L=^CBp>RcV%b{c_S|HI`B(V-x zDv50LN}VW42CFL#D!q+Y^+h;x?kX)R#}iG!%ffXDB8uHqw2y}59lAe9IH&Z*+XtLz}f$HId`?nMiMe|6|%KP9T0*?bqtJVNm(A{k@2}c*$ zTVvmdlK^cqkw{`!bRhmjp3|nbUrESGKb#C}5gBGQyiYaU5JhPPF1T`#!148SW823S-S!vnAZiA|I)wYg^3LitfxGeNIsX~m0a zz#YU(P|)oS1YL9U!Rwy2AYANb7G{-UU2yX)VrSz`yA~)OK%a?MB<9e&HRuNySor6f z3T~{g-kzSBnnNuSbwU@3hf zl=r|gU!Y4U--5ua8vrzxX7H#cv1&h-=4tX2;#2vzAi?0atlV;HVa6xY>`1Pq^=K`t zC#`Kq{wyZB)^;fM4W!wgoX+eymu5S2y^wZgNqSnrboZp$_G~{$p36F%X?8q2I+kXK zvRr?f?aj4z0ZcoHv}C)vG~1!29ldF`HFs_>&30#-JC0VfM2>K?JB{6nV=^7BtUy)JFi|;OoKw>^Xz}&Zl z?|E3-6n7CLe+@_4vK|P)OM6O2A?z5L)wFLUtXlV2ZYRyu~Yx5Kdqe1c4+x8W81?<$a(=S86b;G#gkLQIL_>0h7Kwph_J`<7i&__lF9P5%Sly&oWAIH>$MKNxN4;RETGku-B;kEy0TyY9@CA1ha?R97tythQ zP!haARx0u93zU?0=*(c^>mtzs9Hs>-r~!3uJ#fJkI-{qsy$7xvNpTy#;SdjQE2@Pr z8-(A9d?1LouEBK*9_!R+3UxZPCnFurpd#@KIvuJ+0c%ObAXPz4H{SCErd{fklUdso zL&7qALRD(ORNE5F7ol*@AU5@_BPEkcATcHeL!hC7GHTHC1`98K3BZF-No1C>K_aeA zG}w|rAmCCW23~}LJLx7LsVkKrgX+P9pQaiqk^72*9fHmMsn`zsnfCOpx}B`FskLwL zwQjv}+%E(w-DSios;kr-glG&M7FBB<`NciBC*kKn6;tWcAoF~BzlFO1*%?*GKR84S z5Z6|EVR~qc?}m@t3CUn!S?PakH9qkxRiG>JVYIjg=7qa!3KUbiDF+5&0QTVHvEFxK zr5oj$wx(^H;dGI#g!SP}d@H*lX13)}8<~Bfw>y0=ZW={InfxFYcuF zrBd6xBk>@eRlJWXK#*A^9S>p(%XRWZH?4;!$pYm7zs{G);B$B)*m#kiqEW3s0!we(0J zhE+gFJs}9G9cic&;kpkF;K^QX2wD&xYENdbO=l1ZZQ7(!G}jm=HcZCRa24vytop`D zV!^`rP_bNA-&C(i@ZgI782OJOMt}!-lj)1Hb0+o&R~XaipELD8EUPt@{g9!_Yb^bs zhcONRXJ#a4ZaP}{dsqL?)r`62vE_xCdueS=w@qfO5K~R%tX&_DeP-=CwsvK#J&(U~ zZ0$R$d|BV}jlkpP$9umK`-ib7p3J$aOzU)}-gQ)yHP=5HePQlYtc|(q_Q$5LUwyp# zr14kQL8B_iYqPn!;*>F$SA4&w*5o&R!7(+hS+*|Su=3hmR#SFl`J#ep>dr!}$*#OE zH#e0X)t%Nb)s07$S!)9%&E09HAzRgWRFSQ2KC)!3O~7pIJgUpqw?p5ARBM}#EZ?hX zezg4c^`j~xk*hYcUe>if+RxPW9aX=qZF#hvsqHJ05pr8V5iZRd^79I0Lt??Wme) z^0J}*u_e>ce^je$p>@;Rn`W9+ylhh!^saV5hJ9M`H(Aq6&eE8*G{3aeryKe+mH|>2 z%vgr97LJssGM4GAr47oDtQkx9X=BxB#nH-VY!?KjC+y&93p3)>>4Dso3#p-FcIbq4 zWGBz-ls)H|M5_Oo?LUD_fqhn|Y`L*5BK?SWh{NCmFz__NXIejIAP~ct;_|t2^*-4IcxxCYasvXAT^(V{!Wc`!vXSXtQ%dj9?Dvnm+`ZG57^zQS^=@DX3 zZ63434#ZWdf!xT<(_7CTq=#3K*$JOJPS}C$kX@(xa}x{C#?#|u8cL2OH}83VJH4@; zp1Xz3@)Ji4uTs;w@$=~mzO?OKl;}NXdr#n2rH)XghI3AsyXOzm4x(&n*BP1lD5z^z ztY^RTspZ+&cdviCl3BWu=5C^7%Q4$>0vE-;QJw0^4NN}mc((A}?N4uIyf@SR+gR6n z%(kAuJ(e5Osa}x$s86ShYv(-_V~${y96C-lSykw8INz3xr4t-)ip;m>$1vaO3er5e zpb^Y5$UBL=W*Crn%%Nf`ZOhGE(;Or1+Cu*5F*}Ox?;<{^Q3a?5Ro)Ig_0AvNfBv^K zS8t{#$td$nZyq};R=7H2={YSoUm)7rk6HT(I|r_~aE&Z0l`#wM@JH>>yE7No(l$S$ zly-^pi_hOp&#$Av_%Syp-q9&n?(+3d+tZi6f-L7T>pWo>vKQPsHJ=-w`{aK5 z>Q^%7H`BHNR+R2&?%LBetQ|XM$4=m7V1`&trKWPA#`X04DhlM)Sk@^QnzcP^fqyu! z<7DJoKQK==VkYY4j*IEbtDo+r?ZiE~W0pICw~2`vgj1=poa^fI?({TKX!w{NK4G2N zsRa~JDaT(caLSgK*Jh`$Jh!H&-uuwy7pkc5TA2lpNoUOF=B}j|H`B8L1K5?@r@0IyIV` zTzGO9>46vQzzMu)Ic9ZgJU4aW2{Fsy3++st$6A$|AVb5oUX`(Q(VS?;Wi11zwUwH3 zFNmYTF*Xe=6}2M_M{X83_nCEMjlRG=Wh(0;gH@@?0{r}l9c0AZ3*z1|VmnburN=aD z6XR5}vqV(GhDn}TBK>RdIhW`8t@Jdpjj9qX1~Pi8;N*oTQQaEFwwb^7d^A1xE(+LQ zXc5I_otnoGlD z_`|E8sCDO|4u=88fx3CG>FKRM41N+M?JhvwJgIZRHptmfswc~hW8RzXw_|=TI}AgD zllRM-3e$xTcfVvH`?6`@S%)s3Z zLck8Z5ThTEqqWGAYYFZ;Wn^o23o^a6+@vZ+SDad{9XqZhKQJ|*2WsJmldvk$KR#5k zEvHiX&h6>$0W>04$yP2fx9{A(?|be!-#O>be+mS=9KywKo=S{#a@>ETFGg?`5>Ngo z61O;!8|Fk_v?cjro;_{DHukg++u74G>|jslu#-Jq!!Gu854+jZGwc!Vq9a*0=^ge? z`i6az{$W4Q**M8LUT<`2Jw+$-8?Em~>W)oM4F^TnyWDU{bR!On9>f)58RAOOi?~Xx z6MgUU!_}f6-y&iFagA7xxK<1zt`kFu>%}nQ2C+h{6syE)F(TIdz&YF~)*`oQ*4A1d z`)i)#y#48!_M~)8N(y6Aa!QgFVKglZ>X;-9O7Uq~8j@ovWhyPJ!bl<|CQ?_G4zG7; zOj0BvCQHIAv+7tnC5%p|;%XwDQcyFdvNx%;Du@YLimS<4L6(v+RT2d?&6*xdTpcU) zdiIq*#XB-xs3XNCMTyC?RPd^#QsGHT&!pvv4guZH3W-!aIW3}hVP-6yl!OsF-Bt&CebDaF2qLC)K5x8&SV;$OvX~NtJ0*DQd!$VJe`V5GA5Bo zq347mOs2)@q~xWE#*&k1MHNsMbHa@D##DKhTE+-t*U|~I;iMFsP*_h>a{5|=mdzWR zLV8M0U>(?-X+;{HP6{!MO;Ka$xOj0Sxv)I(v?z6WKO?%h^cnVxYqe|cuHG&zwW^hG zo~Y(wTb58~l^0O5ox-`E^L>|uuAa+7eZ75MXNP)Nu6J+8zB8>}mhQRK{iXMD>d6Rh zB<%P+`4*yEoNB%sFOaKIke;gfW!zyV%|wP%sWlcd+?_&8cc^uQL9UgbyXF-T&L^%( zDQxk`tSTw0jP+|1;x}ch#lMfZgN^tS$iWA-dvWj zFAAt|1oQ<0kH?ZpN$y|;S{pur+%1j9rjx2>PfDp) zUh`UGQ)nW>7k||C{1qZpWhxezuB66Qr9BppgAP@Uzda73yfPAtPe>{8N(ZKQ?Mi=Q z*JqIf5!mg@zx}Kmcw}}Eg$Y2yui-{IffVGG7V4UxA8LpeVL)8)HZK7>Uj$JM6G{=>s z4t@@Mkg-qp#teP}BPP5n&GLDQh!xxodB4cx*qPPCdZ|K{d zLZ6^r``pW$Xg7&-O?;`qBGu`sq@-A64Dwc#be#BsNMxH}3>3UiC&*13K+AR*pC>Jd zUgmggLWX;*42#TXc#*3^?w|6vc%FOT=ip}fzp>Botu~pae(59bBb#RHcuwP0g)#&| zrfFzpC$CB=>Fp``^jte59kYL(fb`*ZoFw8;DyKWl;%%s{R3rKy-0v2+Ro{-=EjM0W zJi8eClkVFszkfof{(3OX{}YU#W_?KxBbF-=6%Svg0esDYw^JL|zyrH(_ulySV(bS0 zC*tki-^&raZgtB<0Xi!v>*^hvosup~qgqAr{^-0x#_Drg6Bq;)vUcxfX|@Y|(^t+X~`_m>e5{LLTf?M+5janCuxoeX;#r(*QkP`xpBH#Mi~-%os$pv;T^lk*3^1(gX z;GUHO+2DzL-K*ti7tU{lx97vH*>LO1KsNlsz0uWB&qCh=UtQkUmi4unEM?sjT=#_6 zJvA)nNY-V7RV$&HfoNYiO0xiUTtpkojJ;+3texLzf1YMK~B$k9{ zizK(^imM%ZXO%D4YV$LmspvB{I*EX zk|%772)#J1#zvCTSy_%1geaZ47=8Um968qeN-m#%PFSG{qV_XGrNrTf*abfiO3Eqvh)0`u- zGK3EuWRfv@SyQ(7E;1#C4UipEl2WY9*{LZYNG54C2(bd})dJ@LetX`IOH-s3X?DyI z8be`SUM^1qhaupLJXERryyt|(Ky4$I*$Nnp(?RinHWVMKFV(p zEpQLZx$+7ee_N&V9M5FOk!<+L1|X=vBkS*2_Xjro6(97!*Z+fU`MOitx>Gs-X|Rk6 z@1pCGmkUKUDwnOWhw{S?v9!vTh@?V|C~0T;$AZ=*&Z# zJ#cU%v@IVxm<=7g+j6gEEp+w)eczi6?Olo74?XuN$W_-qtYwVocc1$>NHXi?A2xio zk2yO=`H3&g#B^0r?5<<{8s0L%1=T*WlER2_6g#g8-FdQdIy(O6KKrAi{6^*O}LlaFl zF>f#GwIoByz~1tVo(ppagK~hy5}sp0EMhJh`#7PwErCS%JK>CNoZ#}7V6paspm)rz zFovL?O>hL^wN!$XaYKePwKHbQ_<}atA-qNkrfDT0TZ%+1gf%8hWJtkzfeD39(>F*T zNRUY)m7ayQK@z?_jdO?2k}#eyOA0eX7}ga53NFitrzfFIysa~%1cxP=+oN-;czTLi zB)T?@(?9~ivR^o-)zS9j;6b~w2AU%t!>M<_GSGKvsOK^P4YFexK%?5IcwSNq2;&ui z0@?z34^^)!FakgYVgn=7qoa~cjA)Q$Sk*N5z#to;=49wqbBPiyXRA~0p@xDiHyTq4 z{cA40NzGMg(Ky+P%eCE(Z#sgp=|ijy1!xR_2r=-AItB*kllX)wHW(yG4@rrTHlqc=w9`AuZL@H zHQsDobgjDstL{4b+H|vNX(kumgFIi@Ku4ywieb|#GxqRHBuL>C`H8()cz)Jabl{3> zpd1C1v{?t#LdV7U#h`#Vk?OFQe^2}#b)fx!Ub@C%`*W9NC^20UV6l*4Lo%~>L&-?$^I?rj_OO+ReA-L@F~FW$PPmYjFTs$<8OkvC~V zjJ7%v6K#zba3u20K&EYzj<_N_h^cRxMbW~YLJQs82YlRim5bZnY9Rx~GboK8_gSqN zDT^H&t=_b~zt;h@4NPuRsx3@jN;ruQqtP z(OgQbM8;{-fvadm$*8a;pk#p#z&Tvc9G}}Ly=kX*Z)p@?Gxm(j7z4B-YgbE+!JIX; zqJPP>BKsidk;i8q8V7V8P^KQB>(o56y&^5^I%jGup1JE@I_ZYS0!M@hWdIgGI1yCl zM0lm=BDqs0V``f~T#j)(SgTXyFaUO7aNVrIT4Pc_4kict09*vjWdhllfNg<*0W~ea z7LZ8k!k-z%0^TRI=w6wQ^xU>fX+cf{Kv3DlXadG-s5Huy6vr1yWU7ly#<00YOMe-e zP9#OWb=|JMqqRzN1F$4v%hm!>%p^))gu&?L9?dgKt{@eX-ZcW9qVtGWHqv=S7wDSv zs+^vlvY4pOSUb?4rP{~`=qmweW}?;^bR#inYsfnCBHIR8`*qHI2sN}aQ-^7FYu+gd z#%{LqniK0BAJfW2Nsh8D(7g1}l@mRinZgG^% zBTFbowkc&4s}0ue=PDZW;a%DAuI2M9ujRsr7hd|@#U1PB^PT zCs#cuACS$B=}m^ke%({H;VJ*X|DON*-^y2?$X1`od7dY|$+hqj^d^7AY~on1{P?Qp z_(Mmfv;5P#or`@NHTzahnC|aBKaTl6=A6!Qm?O(-@*W}U5ti%MJZC=xYTucmz)NH16U}Vzn`?__bfUm39 z%=ySBpTJl(5A5`CbxC5e30(6;6AGhKc>;z0JwAq;$HRqc^FbJH59ERe7cOj&g|<2C zYhD&}zWpn2XMM+39ml>53jY5s+jGWHk5JcRv1@=TDaq;scRvL9BPXQ7We8m_lSI}Q&f3d` ziNJ<*O|4WUp1jy9Xf)7(;OfPC`{G4?`L$*FMURek9-PIZ);eyrQukchCf|QPs-mw zCUDHbPKn$llH5z*J=6&;s^*@Y5b2BNpfPBU@pK}kxe8?&UoYQ0W-VOwT?aF|bCJ-k z4uD7(1cveJBhY>J1g>zwAT}v!9%Gxe0QGFnPzxA@5oKfX7+=X~LR#;a0ZnDpTrF}V zGK!S{8MZu)v*MRpi$5H=kb``SA2Y|329Ukwqn5UAe56Kz3DQzG`>2YIm-xW#Qrjw0ZvK`CI)r`MTp zt6u!LCRf$Ba1qFY_-;!!*pdtGMdd(sKCmYn*t71b{=Tww{KNU>vAfQ@>Q7()`zt@W z@~geMQ-cM|3~D;7Z@j+dXnY9VRCVL6Ro~84$4*_W5#Kig88R7*{x^tkaaW;5;sZk? z^s2%Ehkj9{>mJ3ef{b&V>TC%nOQP#v_%j$C56{cf8M^8)nkwa&`eT>HkS(@jYL4!r zwoS9F(H`y~6q1;a>5CdSHCwA(hAykoALfpmI3{y0rTbcX<{dgR2=g9G8_sy{n5?mA zY$chqQF6Ylh)tInxzKQz(YCj!l@b@@a8JW)to6LFXym1sy02)h1seJ0P}I&Y<4wkA zj7Q#6G!iCfntD0e|1vfbeY?1WoWjpQi~a@#BG28xEDYaa=AW?dKQ8Lq)U_RR|Ith8 znW1abeLe^aVwG($md8Yh$7E6$3o?1vbtM+^S-%}tP`SxVMHWO|sF4scn4vBtN(dwJ zLn_a+mPZpZT4s((vP0@A$g2XTOprAnZL)zXux`VcX%%9MrrygX%_fg9HM}*VInr>} zX%6_)L>;^`2}N*^Nej(euo6J*>gq!PVxV3jdaBeHUzrIUcJb3;pZi%7vHKD{B_|ACv_a#T(sgWpzuhuGiGw zx_0y0hi@WRdA>%*55>*Aq=2BzM-|{3}Mm~Yht2lHYS@Q^=`&m;* zvo%NWCUZ4iXso(^>Ey4g_b&FZfshh@ukqvQT;)YLJuB;Oy>Rn|CG{`Am2Wg<0Ro{~h?OAcGh1%Ccjrq{7Y-rbV_x(`oM!0E7ydU1RwM>0Jv?CkZ zvAp|!XwRccF4Foa!ue}0ef`Rs|Ih<6HZXO(cFnWzH~z?yf7RE#>S+G$AdfZ6meu{? z(FOi#)$V)teW4Kg{xICzWdED)Nbf%G7mmG%f7#^h-Q)h{zK-)-6nQek(C5i35WU5M z8rKN;di26HXSo^H-2p=HnlCQ~2i9;CG%009H(>^PsB_@LGfdG>HOp_A$NxnirU;wt4#QIo4M2^Wlc~oFu0O_{eb`UzeLG*=30q(lrZ`yiHKx8)w&T z$f-^mG{ysicrpR&Q1OHWl@I_MU6G-D)6EOw65t-C@6!UFxiWmweOiw0(|*M3S5a}V zmgtCy!D920ej|0CE}!&4=|*II3}3!Sdl`&Np{DeEwEni+(hc!1)c1#OOTSl$aa?zY z`S0SRBZUek7;`Dg5-CQ$p~Kn1DcZ*P(}WLnz+G=6S3%OX?aSTG3;%?Mp_wtXD~?f7rmO5 zuTw=I+cmo8h%T7b(~h103K&rH70WEIps5a8*n)}vMIJhB0SUmo9%#QU<@{|6Jr5l_ zo%=qm+Xj>P-c$F+epQy+dpYZGUc9u_x9*SR{Y_ba(^6{9-@fjz&HJ}!{o9wzV8(vv z=IXaUD(6D=8x6bi4TrJ~hjI-^7W+4wGk)5kL^}Fw%cvg`w*cN@zeYoc^_lv`adYkQqo9Ca=A#1gL zM$%O$VVnFTN>c{Pu=GboY0AJgG$*d4T|1;d4r|V#{=sVp=iKbkVI~f3I?enDp*Ylo?hYX2xos31DBgY#tGRzP<49*%DDt;>>vfp8mtuQr_ zO3$Q(uCu!KAk&(CMrU)*e)`^9AGTqWaGe1a(!t!0|~8h-9YR{<#zos5ka5#(H(#!lm^l+-|7f@PvormwfaqsHKGr7RP>gCt6f!7v# zt=l*9pP{eTZJIk871Qx(l$iu|mI*IBC(DSSx=Ffk^IuWcG-Y{=U&iSdqZmJB{Mk+S zw7?HFSNFis+5Ud{4XQ);iRGOX?Wc$?P3kvL1}P;`G(i!0D430oael_y0Nhpe?0OZ6913@=L*{v0*}3J-u1Yu5>cCvuXx + + 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. +""" +from __future__ import absolute_import + +import platform +from ctypes import ( + CDLL, + CFUNCTYPE, + POINTER, + c_bool, + c_byte, + c_char_p, + c_int32, + c_long, + c_size_t, + c_uint32, + c_ulong, + c_void_p, +) +from ctypes.util import find_library + +from ...packages.six import raise_from + +if platform.system() != "Darwin": + raise ImportError("Only macOS is supported") + +version = platform.mac_ver()[0] +version_info = tuple(map(int, version.split("."))) +if version_info < (10, 8): + raise OSError( + "Only OS X 10.8 and newer are supported, not %s.%s" + % (version_info[0], version_info[1]) + ) + + +def load_cdll(name, macos10_16_path): + """Loads a CDLL by name, falling back to known path on 10.16+""" + try: + # Big Sur is technically 11 but we use 10.16 due to the Big Sur + # beta being labeled as 10.16. + if version_info >= (10, 16): + path = macos10_16_path + else: + path = find_library(name) + if not path: + raise OSError # Caught and reraised as 'ImportError' + return CDLL(path, use_errno=True) + except OSError: + raise_from(ImportError("The library %s failed to load" % name), None) + + +Security = load_cdll( + "Security", "/System/Library/Frameworks/Security.framework/Security" +) +CoreFoundation = load_cdll( + "CoreFoundation", + "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", +) + + +Boolean = c_bool +CFIndex = c_long +CFStringEncoding = c_uint32 +CFData = c_void_p +CFString = c_void_p +CFArray = c_void_p +CFMutableArray = c_void_p +CFDictionary = c_void_p +CFError = c_void_p +CFType = c_void_p +CFTypeID = c_ulong + +CFTypeRef = POINTER(CFType) +CFAllocatorRef = c_void_p + +OSStatus = c_int32 + +CFDataRef = POINTER(CFData) +CFStringRef = POINTER(CFString) +CFArrayRef = POINTER(CFArray) +CFMutableArrayRef = POINTER(CFMutableArray) +CFDictionaryRef = POINTER(CFDictionary) +CFArrayCallBacks = c_void_p +CFDictionaryKeyCallBacks = c_void_p +CFDictionaryValueCallBacks = c_void_p + +SecCertificateRef = POINTER(c_void_p) +SecExternalFormat = c_uint32 +SecExternalItemType = c_uint32 +SecIdentityRef = POINTER(c_void_p) +SecItemImportExportFlags = c_uint32 +SecItemImportExportKeyParameters = c_void_p +SecKeychainRef = POINTER(c_void_p) +SSLProtocol = c_uint32 +SSLCipherSuite = c_uint32 +SSLContextRef = POINTER(c_void_p) +SecTrustRef = POINTER(c_void_p) +SSLConnectionRef = c_uint32 +SecTrustResultType = c_uint32 +SecTrustOptionFlags = c_uint32 +SSLProtocolSide = c_uint32 +SSLConnectionType = c_uint32 +SSLSessionOption = c_uint32 + + +try: + Security.SecItemImport.argtypes = [ + CFDataRef, + CFStringRef, + POINTER(SecExternalFormat), + POINTER(SecExternalItemType), + SecItemImportExportFlags, + POINTER(SecItemImportExportKeyParameters), + SecKeychainRef, + POINTER(CFArrayRef), + ] + Security.SecItemImport.restype = OSStatus + + Security.SecCertificateGetTypeID.argtypes = [] + Security.SecCertificateGetTypeID.restype = CFTypeID + + Security.SecIdentityGetTypeID.argtypes = [] + Security.SecIdentityGetTypeID.restype = CFTypeID + + Security.SecKeyGetTypeID.argtypes = [] + Security.SecKeyGetTypeID.restype = CFTypeID + + Security.SecCertificateCreateWithData.argtypes = [CFAllocatorRef, CFDataRef] + Security.SecCertificateCreateWithData.restype = SecCertificateRef + + Security.SecCertificateCopyData.argtypes = [SecCertificateRef] + Security.SecCertificateCopyData.restype = CFDataRef + + Security.SecCopyErrorMessageString.argtypes = [OSStatus, c_void_p] + Security.SecCopyErrorMessageString.restype = CFStringRef + + Security.SecIdentityCreateWithCertificate.argtypes = [ + CFTypeRef, + SecCertificateRef, + POINTER(SecIdentityRef), + ] + Security.SecIdentityCreateWithCertificate.restype = OSStatus + + Security.SecKeychainCreate.argtypes = [ + c_char_p, + c_uint32, + c_void_p, + Boolean, + c_void_p, + POINTER(SecKeychainRef), + ] + Security.SecKeychainCreate.restype = OSStatus + + Security.SecKeychainDelete.argtypes = [SecKeychainRef] + Security.SecKeychainDelete.restype = OSStatus + + Security.SecPKCS12Import.argtypes = [ + CFDataRef, + CFDictionaryRef, + POINTER(CFArrayRef), + ] + Security.SecPKCS12Import.restype = OSStatus + + SSLReadFunc = CFUNCTYPE(OSStatus, SSLConnectionRef, c_void_p, POINTER(c_size_t)) + SSLWriteFunc = CFUNCTYPE( + OSStatus, SSLConnectionRef, POINTER(c_byte), POINTER(c_size_t) + ) + + Security.SSLSetIOFuncs.argtypes = [SSLContextRef, SSLReadFunc, SSLWriteFunc] + Security.SSLSetIOFuncs.restype = OSStatus + + Security.SSLSetPeerID.argtypes = [SSLContextRef, c_char_p, c_size_t] + Security.SSLSetPeerID.restype = OSStatus + + Security.SSLSetCertificate.argtypes = [SSLContextRef, CFArrayRef] + Security.SSLSetCertificate.restype = OSStatus + + Security.SSLSetCertificateAuthorities.argtypes = [SSLContextRef, CFTypeRef, Boolean] + Security.SSLSetCertificateAuthorities.restype = OSStatus + + Security.SSLSetConnection.argtypes = [SSLContextRef, SSLConnectionRef] + Security.SSLSetConnection.restype = OSStatus + + Security.SSLSetPeerDomainName.argtypes = [SSLContextRef, c_char_p, c_size_t] + Security.SSLSetPeerDomainName.restype = OSStatus + + Security.SSLHandshake.argtypes = [SSLContextRef] + Security.SSLHandshake.restype = OSStatus + + Security.SSLRead.argtypes = [SSLContextRef, c_char_p, c_size_t, POINTER(c_size_t)] + Security.SSLRead.restype = OSStatus + + Security.SSLWrite.argtypes = [SSLContextRef, c_char_p, c_size_t, POINTER(c_size_t)] + Security.SSLWrite.restype = OSStatus + + Security.SSLClose.argtypes = [SSLContextRef] + Security.SSLClose.restype = OSStatus + + Security.SSLGetNumberSupportedCiphers.argtypes = [SSLContextRef, POINTER(c_size_t)] + Security.SSLGetNumberSupportedCiphers.restype = OSStatus + + Security.SSLGetSupportedCiphers.argtypes = [ + SSLContextRef, + POINTER(SSLCipherSuite), + POINTER(c_size_t), + ] + Security.SSLGetSupportedCiphers.restype = OSStatus + + Security.SSLSetEnabledCiphers.argtypes = [ + SSLContextRef, + POINTER(SSLCipherSuite), + c_size_t, + ] + Security.SSLSetEnabledCiphers.restype = OSStatus + + Security.SSLGetNumberEnabledCiphers.argtype = [SSLContextRef, POINTER(c_size_t)] + Security.SSLGetNumberEnabledCiphers.restype = OSStatus + + Security.SSLGetEnabledCiphers.argtypes = [ + SSLContextRef, + POINTER(SSLCipherSuite), + POINTER(c_size_t), + ] + Security.SSLGetEnabledCiphers.restype = OSStatus + + Security.SSLGetNegotiatedCipher.argtypes = [SSLContextRef, POINTER(SSLCipherSuite)] + Security.SSLGetNegotiatedCipher.restype = OSStatus + + Security.SSLGetNegotiatedProtocolVersion.argtypes = [ + SSLContextRef, + POINTER(SSLProtocol), + ] + Security.SSLGetNegotiatedProtocolVersion.restype = OSStatus + + Security.SSLCopyPeerTrust.argtypes = [SSLContextRef, POINTER(SecTrustRef)] + Security.SSLCopyPeerTrust.restype = OSStatus + + Security.SecTrustSetAnchorCertificates.argtypes = [SecTrustRef, CFArrayRef] + Security.SecTrustSetAnchorCertificates.restype = OSStatus + + Security.SecTrustSetAnchorCertificatesOnly.argstypes = [SecTrustRef, Boolean] + Security.SecTrustSetAnchorCertificatesOnly.restype = OSStatus + + Security.SecTrustEvaluate.argtypes = [SecTrustRef, POINTER(SecTrustResultType)] + Security.SecTrustEvaluate.restype = OSStatus + + Security.SecTrustGetCertificateCount.argtypes = [SecTrustRef] + Security.SecTrustGetCertificateCount.restype = CFIndex + + Security.SecTrustGetCertificateAtIndex.argtypes = [SecTrustRef, CFIndex] + Security.SecTrustGetCertificateAtIndex.restype = SecCertificateRef + + Security.SSLCreateContext.argtypes = [ + CFAllocatorRef, + SSLProtocolSide, + SSLConnectionType, + ] + Security.SSLCreateContext.restype = SSLContextRef + + Security.SSLSetSessionOption.argtypes = [SSLContextRef, SSLSessionOption, Boolean] + Security.SSLSetSessionOption.restype = OSStatus + + Security.SSLSetProtocolVersionMin.argtypes = [SSLContextRef, SSLProtocol] + Security.SSLSetProtocolVersionMin.restype = OSStatus + + Security.SSLSetProtocolVersionMax.argtypes = [SSLContextRef, SSLProtocol] + Security.SSLSetProtocolVersionMax.restype = OSStatus + + try: + Security.SSLSetALPNProtocols.argtypes = [SSLContextRef, CFArrayRef] + Security.SSLSetALPNProtocols.restype = OSStatus + except AttributeError: + # Supported only in 10.12+ + pass + + Security.SecCopyErrorMessageString.argtypes = [OSStatus, c_void_p] + Security.SecCopyErrorMessageString.restype = CFStringRef + + Security.SSLReadFunc = SSLReadFunc + Security.SSLWriteFunc = SSLWriteFunc + Security.SSLContextRef = SSLContextRef + Security.SSLProtocol = SSLProtocol + Security.SSLCipherSuite = SSLCipherSuite + Security.SecIdentityRef = SecIdentityRef + Security.SecKeychainRef = SecKeychainRef + Security.SecTrustRef = SecTrustRef + Security.SecTrustResultType = SecTrustResultType + Security.SecExternalFormat = SecExternalFormat + Security.OSStatus = OSStatus + + Security.kSecImportExportPassphrase = CFStringRef.in_dll( + Security, "kSecImportExportPassphrase" + ) + Security.kSecImportItemIdentity = CFStringRef.in_dll( + Security, "kSecImportItemIdentity" + ) + + # CoreFoundation time! + CoreFoundation.CFRetain.argtypes = [CFTypeRef] + CoreFoundation.CFRetain.restype = CFTypeRef + + CoreFoundation.CFRelease.argtypes = [CFTypeRef] + CoreFoundation.CFRelease.restype = None + + CoreFoundation.CFGetTypeID.argtypes = [CFTypeRef] + CoreFoundation.CFGetTypeID.restype = CFTypeID + + CoreFoundation.CFStringCreateWithCString.argtypes = [ + CFAllocatorRef, + c_char_p, + CFStringEncoding, + ] + CoreFoundation.CFStringCreateWithCString.restype = CFStringRef + + CoreFoundation.CFStringGetCStringPtr.argtypes = [CFStringRef, CFStringEncoding] + CoreFoundation.CFStringGetCStringPtr.restype = c_char_p + + CoreFoundation.CFStringGetCString.argtypes = [ + CFStringRef, + c_char_p, + CFIndex, + CFStringEncoding, + ] + CoreFoundation.CFStringGetCString.restype = c_bool + + CoreFoundation.CFDataCreate.argtypes = [CFAllocatorRef, c_char_p, CFIndex] + CoreFoundation.CFDataCreate.restype = CFDataRef + + CoreFoundation.CFDataGetLength.argtypes = [CFDataRef] + CoreFoundation.CFDataGetLength.restype = CFIndex + + CoreFoundation.CFDataGetBytePtr.argtypes = [CFDataRef] + CoreFoundation.CFDataGetBytePtr.restype = c_void_p + + CoreFoundation.CFDictionaryCreate.argtypes = [ + CFAllocatorRef, + POINTER(CFTypeRef), + POINTER(CFTypeRef), + CFIndex, + CFDictionaryKeyCallBacks, + CFDictionaryValueCallBacks, + ] + CoreFoundation.CFDictionaryCreate.restype = CFDictionaryRef + + CoreFoundation.CFDictionaryGetValue.argtypes = [CFDictionaryRef, CFTypeRef] + CoreFoundation.CFDictionaryGetValue.restype = CFTypeRef + + CoreFoundation.CFArrayCreate.argtypes = [ + CFAllocatorRef, + POINTER(CFTypeRef), + CFIndex, + CFArrayCallBacks, + ] + CoreFoundation.CFArrayCreate.restype = CFArrayRef + + CoreFoundation.CFArrayCreateMutable.argtypes = [ + CFAllocatorRef, + CFIndex, + CFArrayCallBacks, + ] + CoreFoundation.CFArrayCreateMutable.restype = CFMutableArrayRef + + CoreFoundation.CFArrayAppendValue.argtypes = [CFMutableArrayRef, c_void_p] + CoreFoundation.CFArrayAppendValue.restype = None + + CoreFoundation.CFArrayGetCount.argtypes = [CFArrayRef] + CoreFoundation.CFArrayGetCount.restype = CFIndex + + CoreFoundation.CFArrayGetValueAtIndex.argtypes = [CFArrayRef, CFIndex] + CoreFoundation.CFArrayGetValueAtIndex.restype = c_void_p + + CoreFoundation.kCFAllocatorDefault = CFAllocatorRef.in_dll( + CoreFoundation, "kCFAllocatorDefault" + ) + CoreFoundation.kCFTypeArrayCallBacks = c_void_p.in_dll( + CoreFoundation, "kCFTypeArrayCallBacks" + ) + CoreFoundation.kCFTypeDictionaryKeyCallBacks = c_void_p.in_dll( + CoreFoundation, "kCFTypeDictionaryKeyCallBacks" + ) + CoreFoundation.kCFTypeDictionaryValueCallBacks = c_void_p.in_dll( + CoreFoundation, "kCFTypeDictionaryValueCallBacks" + ) + + CoreFoundation.CFTypeRef = CFTypeRef + CoreFoundation.CFArrayRef = CFArrayRef + CoreFoundation.CFStringRef = CFStringRef + CoreFoundation.CFDictionaryRef = CFDictionaryRef + +except (AttributeError): + raise ImportError("Error initializing ctypes") + + +class CFConst(object): + """ + A class object that acts as essentially a namespace for CoreFoundation + constants. + """ + + kCFStringEncodingUTF8 = CFStringEncoding(0x08000100) + + +class SecurityConst(object): + """ + A class object that acts as essentially a namespace for Security constants. + """ + + kSSLSessionOptionBreakOnServerAuth = 0 + + kSSLProtocol2 = 1 + kSSLProtocol3 = 2 + kTLSProtocol1 = 4 + kTLSProtocol11 = 7 + kTLSProtocol12 = 8 + # SecureTransport does not support TLS 1.3 even if there's a constant for it + kTLSProtocol13 = 10 + kTLSProtocolMaxSupported = 999 + + kSSLClientSide = 1 + kSSLStreamType = 0 + + kSecFormatPEMSequence = 10 + + kSecTrustResultInvalid = 0 + kSecTrustResultProceed = 1 + # This gap is present on purpose: this was kSecTrustResultConfirm, which + # is deprecated. + kSecTrustResultDeny = 3 + kSecTrustResultUnspecified = 4 + kSecTrustResultRecoverableTrustFailure = 5 + kSecTrustResultFatalTrustFailure = 6 + kSecTrustResultOtherError = 7 + + errSSLProtocol = -9800 + errSSLWouldBlock = -9803 + errSSLClosedGraceful = -9805 + errSSLClosedNoNotify = -9816 + errSSLClosedAbort = -9806 + + errSSLXCertChainInvalid = -9807 + errSSLCrypto = -9809 + errSSLInternal = -9810 + errSSLCertExpired = -9814 + errSSLCertNotYetValid = -9815 + errSSLUnknownRootCert = -9812 + errSSLNoRootCert = -9813 + errSSLHostNameMismatch = -9843 + errSSLPeerHandshakeFail = -9824 + errSSLPeerUserCancelled = -9839 + errSSLWeakPeerEphemeralDHKey = -9850 + errSSLServerAuthCompleted = -9841 + errSSLRecordOverflow = -9847 + + errSecVerifyFailed = -67808 + errSecNoTrustSettings = -25263 + errSecItemNotFound = -25300 + errSecInvalidTrustSettings = -25262 + + # Cipher suites. We only pick the ones our default cipher string allows. + # Source: https://developer.apple.com/documentation/security/1550981-ssl_cipher_suite_values + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030 + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA9 + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA8 + TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F + TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024 + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028 + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014 + TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B + TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039 + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023 + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027 + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009 + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013 + TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067 + TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033 + TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D + TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C + TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D + TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C + TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035 + TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F + TLS_AES_128_GCM_SHA256 = 0x1301 + TLS_AES_256_GCM_SHA384 = 0x1302 + TLS_AES_128_CCM_8_SHA256 = 0x1305 + TLS_AES_128_CCM_SHA256 = 0x1304 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py new file mode 100644 index 0000000..fa0b245 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py @@ -0,0 +1,397 @@ +""" +Low-level helpers for the SecureTransport bindings. + +These are Python functions that are not directly related to the high-level APIs +but are necessary to get them to work. They include a whole bunch of low-level +CoreFoundation messing about and memory management. The concerns in this module +are almost entirely about trying to avoid memory leaks and providing +appropriate and useful assistance to the higher-level code. +""" +import base64 +import ctypes +import itertools +import os +import re +import ssl +import struct +import tempfile + +from .bindings import CFConst, CoreFoundation, Security + +# This regular expression is used to grab PEM data out of a PEM bundle. +_PEM_CERTS_RE = re.compile( + b"-----BEGIN CERTIFICATE-----\n(.*?)\n-----END CERTIFICATE-----", re.DOTALL +) + + +def _cf_data_from_bytes(bytestring): + """ + Given a bytestring, create a CFData object from it. This CFData object must + be CFReleased by the caller. + """ + return CoreFoundation.CFDataCreate( + CoreFoundation.kCFAllocatorDefault, bytestring, len(bytestring) + ) + + +def _cf_dictionary_from_tuples(tuples): + """ + Given a list of Python tuples, create an associated CFDictionary. + """ + dictionary_size = len(tuples) + + # We need to get the dictionary keys and values out in the same order. + keys = (t[0] for t in tuples) + values = (t[1] for t in tuples) + cf_keys = (CoreFoundation.CFTypeRef * dictionary_size)(*keys) + cf_values = (CoreFoundation.CFTypeRef * dictionary_size)(*values) + + return CoreFoundation.CFDictionaryCreate( + CoreFoundation.kCFAllocatorDefault, + cf_keys, + cf_values, + dictionary_size, + CoreFoundation.kCFTypeDictionaryKeyCallBacks, + CoreFoundation.kCFTypeDictionaryValueCallBacks, + ) + + +def _cfstr(py_bstr): + """ + Given a Python binary data, create a CFString. + The string must be CFReleased by the caller. + """ + c_str = ctypes.c_char_p(py_bstr) + cf_str = CoreFoundation.CFStringCreateWithCString( + CoreFoundation.kCFAllocatorDefault, + c_str, + CFConst.kCFStringEncodingUTF8, + ) + return cf_str + + +def _create_cfstring_array(lst): + """ + Given a list of Python binary data, create an associated CFMutableArray. + The array must be CFReleased by the caller. + + Raises an ssl.SSLError on failure. + """ + cf_arr = None + try: + cf_arr = CoreFoundation.CFArrayCreateMutable( + CoreFoundation.kCFAllocatorDefault, + 0, + ctypes.byref(CoreFoundation.kCFTypeArrayCallBacks), + ) + if not cf_arr: + raise MemoryError("Unable to allocate memory!") + for item in lst: + cf_str = _cfstr(item) + if not cf_str: + raise MemoryError("Unable to allocate memory!") + try: + CoreFoundation.CFArrayAppendValue(cf_arr, cf_str) + finally: + CoreFoundation.CFRelease(cf_str) + except BaseException as e: + if cf_arr: + CoreFoundation.CFRelease(cf_arr) + raise ssl.SSLError("Unable to allocate array: %s" % (e,)) + return cf_arr + + +def _cf_string_to_unicode(value): + """ + Creates a Unicode string from a CFString object. Used entirely for error + reporting. + + Yes, it annoys me quite a lot that this function is this complex. + """ + value_as_void_p = ctypes.cast(value, ctypes.POINTER(ctypes.c_void_p)) + + string = CoreFoundation.CFStringGetCStringPtr( + value_as_void_p, CFConst.kCFStringEncodingUTF8 + ) + if string is None: + buffer = ctypes.create_string_buffer(1024) + result = CoreFoundation.CFStringGetCString( + value_as_void_p, buffer, 1024, CFConst.kCFStringEncodingUTF8 + ) + if not result: + raise OSError("Error copying C string from CFStringRef") + string = buffer.value + if string is not None: + string = string.decode("utf-8") + return string + + +def _assert_no_error(error, exception_class=None): + """ + Checks the return code and throws an exception if there is an error to + report + """ + if error == 0: + return + + cf_error_string = Security.SecCopyErrorMessageString(error, None) + output = _cf_string_to_unicode(cf_error_string) + CoreFoundation.CFRelease(cf_error_string) + + if output is None or output == u"": + output = u"OSStatus %s" % error + + if exception_class is None: + exception_class = ssl.SSLError + + raise exception_class(output) + + +def _cert_array_from_pem(pem_bundle): + """ + Given a bundle of certs in PEM format, turns them into a CFArray of certs + that can be used to validate a cert chain. + """ + # Normalize the PEM bundle's line endings. + pem_bundle = pem_bundle.replace(b"\r\n", b"\n") + + der_certs = [ + base64.b64decode(match.group(1)) for match in _PEM_CERTS_RE.finditer(pem_bundle) + ] + if not der_certs: + raise ssl.SSLError("No root certificates specified") + + cert_array = CoreFoundation.CFArrayCreateMutable( + CoreFoundation.kCFAllocatorDefault, + 0, + ctypes.byref(CoreFoundation.kCFTypeArrayCallBacks), + ) + if not cert_array: + raise ssl.SSLError("Unable to allocate memory!") + + try: + for der_bytes in der_certs: + certdata = _cf_data_from_bytes(der_bytes) + if not certdata: + raise ssl.SSLError("Unable to allocate memory!") + cert = Security.SecCertificateCreateWithData( + CoreFoundation.kCFAllocatorDefault, certdata + ) + CoreFoundation.CFRelease(certdata) + if not cert: + raise ssl.SSLError("Unable to build cert object!") + + CoreFoundation.CFArrayAppendValue(cert_array, cert) + CoreFoundation.CFRelease(cert) + except Exception: + # We need to free the array before the exception bubbles further. + # We only want to do that if an error occurs: otherwise, the caller + # should free. + CoreFoundation.CFRelease(cert_array) + raise + + return cert_array + + +def _is_cert(item): + """ + Returns True if a given CFTypeRef is a certificate. + """ + expected = Security.SecCertificateGetTypeID() + return CoreFoundation.CFGetTypeID(item) == expected + + +def _is_identity(item): + """ + Returns True if a given CFTypeRef is an identity. + """ + expected = Security.SecIdentityGetTypeID() + return CoreFoundation.CFGetTypeID(item) == expected + + +def _temporary_keychain(): + """ + This function creates a temporary Mac keychain that we can use to work with + credentials. This keychain uses a one-time password and a temporary file to + store the data. We expect to have one keychain per socket. The returned + SecKeychainRef must be freed by the caller, including calling + SecKeychainDelete. + + Returns a tuple of the SecKeychainRef and the path to the temporary + directory that contains it. + """ + # Unfortunately, SecKeychainCreate requires a path to a keychain. This + # means we cannot use mkstemp to use a generic temporary file. Instead, + # we're going to create a temporary directory and a filename to use there. + # This filename will be 8 random bytes expanded into base64. We also need + # some random bytes to password-protect the keychain we're creating, so we + # ask for 40 random bytes. + random_bytes = os.urandom(40) + filename = base64.b16encode(random_bytes[:8]).decode("utf-8") + password = base64.b16encode(random_bytes[8:]) # Must be valid UTF-8 + tempdirectory = tempfile.mkdtemp() + + keychain_path = os.path.join(tempdirectory, filename).encode("utf-8") + + # We now want to create the keychain itself. + keychain = Security.SecKeychainRef() + status = Security.SecKeychainCreate( + keychain_path, len(password), password, False, None, ctypes.byref(keychain) + ) + _assert_no_error(status) + + # Having created the keychain, we want to pass it off to the caller. + return keychain, tempdirectory + + +def _load_items_from_file(keychain, path): + """ + Given a single file, loads all the trust objects from it into arrays and + the keychain. + Returns a tuple of lists: the first list is a list of identities, the + second a list of certs. + """ + certificates = [] + identities = [] + result_array = None + + with open(path, "rb") as f: + raw_filedata = f.read() + + try: + filedata = CoreFoundation.CFDataCreate( + CoreFoundation.kCFAllocatorDefault, raw_filedata, len(raw_filedata) + ) + result_array = CoreFoundation.CFArrayRef() + result = Security.SecItemImport( + filedata, # cert data + None, # Filename, leaving it out for now + None, # What the type of the file is, we don't care + None, # what's in the file, we don't care + 0, # import flags + None, # key params, can include passphrase in the future + keychain, # The keychain to insert into + ctypes.byref(result_array), # Results + ) + _assert_no_error(result) + + # A CFArray is not very useful to us as an intermediary + # representation, so we are going to extract the objects we want + # and then free the array. We don't need to keep hold of keys: the + # keychain already has them! + result_count = CoreFoundation.CFArrayGetCount(result_array) + for index in range(result_count): + item = CoreFoundation.CFArrayGetValueAtIndex(result_array, index) + item = ctypes.cast(item, CoreFoundation.CFTypeRef) + + if _is_cert(item): + CoreFoundation.CFRetain(item) + certificates.append(item) + elif _is_identity(item): + CoreFoundation.CFRetain(item) + identities.append(item) + finally: + if result_array: + CoreFoundation.CFRelease(result_array) + + CoreFoundation.CFRelease(filedata) + + return (identities, certificates) + + +def _load_client_cert_chain(keychain, *paths): + """ + Load certificates and maybe keys from a number of files. Has the end goal + of returning a CFArray containing one SecIdentityRef, and then zero or more + SecCertificateRef objects, suitable for use as a client certificate trust + chain. + """ + # Ok, the strategy. + # + # This relies on knowing that macOS will not give you a SecIdentityRef + # unless you have imported a key into a keychain. This is a somewhat + # artificial limitation of macOS (for example, it doesn't necessarily + # affect iOS), but there is nothing inside Security.framework that lets you + # get a SecIdentityRef without having a key in a keychain. + # + # So the policy here is we take all the files and iterate them in order. + # Each one will use SecItemImport to have one or more objects loaded from + # it. We will also point at a keychain that macOS can use to work with the + # private key. + # + # Once we have all the objects, we'll check what we actually have. If we + # already have a SecIdentityRef in hand, fab: we'll use that. Otherwise, + # we'll take the first certificate (which we assume to be our leaf) and + # ask the keychain to give us a SecIdentityRef with that cert's associated + # key. + # + # We'll then return a CFArray containing the trust chain: one + # SecIdentityRef and then zero-or-more SecCertificateRef objects. The + # responsibility for freeing this CFArray will be with the caller. This + # CFArray must remain alive for the entire connection, so in practice it + # will be stored with a single SSLSocket, along with the reference to the + # keychain. + certificates = [] + identities = [] + + # Filter out bad paths. + paths = (path for path in paths if path) + + try: + for file_path in paths: + new_identities, new_certs = _load_items_from_file(keychain, file_path) + identities.extend(new_identities) + certificates.extend(new_certs) + + # Ok, we have everything. The question is: do we have an identity? If + # not, we want to grab one from the first cert we have. + if not identities: + new_identity = Security.SecIdentityRef() + status = Security.SecIdentityCreateWithCertificate( + keychain, certificates[0], ctypes.byref(new_identity) + ) + _assert_no_error(status) + identities.append(new_identity) + + # We now want to release the original certificate, as we no longer + # need it. + CoreFoundation.CFRelease(certificates.pop(0)) + + # We now need to build a new CFArray that holds the trust chain. + trust_chain = CoreFoundation.CFArrayCreateMutable( + CoreFoundation.kCFAllocatorDefault, + 0, + ctypes.byref(CoreFoundation.kCFTypeArrayCallBacks), + ) + for item in itertools.chain(identities, certificates): + # ArrayAppendValue does a CFRetain on the item. That's fine, + # because the finally block will release our other refs to them. + CoreFoundation.CFArrayAppendValue(trust_chain, item) + + return trust_chain + finally: + for obj in itertools.chain(identities, certificates): + CoreFoundation.CFRelease(obj) + + +TLS_PROTOCOL_VERSIONS = { + "SSLv2": (0, 2), + "SSLv3": (3, 0), + "TLSv1": (3, 1), + "TLSv1.1": (3, 2), + "TLSv1.2": (3, 3), +} + + +def _build_tls_unknown_ca_alert(version): + """ + Builds a TLS alert record for an unknown CA. + """ + ver_maj, ver_min = TLS_PROTOCOL_VERSIONS[version] + severity_fatal = 0x02 + description_unknown_ca = 0x30 + msg = struct.pack(">BB", severity_fatal, description_unknown_ca) + msg_len = len(msg) + record_type_alert = 0x15 + record = struct.pack(">BBBH", record_type_alert, ver_maj, ver_min, msg_len) + msg + return record diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/appengine.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/appengine.py new file mode 100644 index 0000000..1717ee2 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/appengine.py @@ -0,0 +1,314 @@ +""" +This module provides a pool manager that uses Google App Engine's +`URLFetch Service `_. + +Example usage:: + + from pip._vendor.urllib3 import PoolManager + from pip._vendor.urllib3.contrib.appengine import AppEngineManager, is_appengine_sandbox + + if is_appengine_sandbox(): + # AppEngineManager uses AppEngine's URLFetch API behind the scenes + http = AppEngineManager() + else: + # PoolManager uses a socket-level API behind the scenes + http = PoolManager() + + r = http.request('GET', 'https://google.com/') + +There are `limitations `_ to the URLFetch service and it may not be +the best choice for your application. There are three options for using +urllib3 on Google App Engine: + +1. You can use :class:`AppEngineManager` with URLFetch. URLFetch is + cost-effective in many circumstances as long as your usage is within the + limitations. +2. You can use a normal :class:`~urllib3.PoolManager` by enabling sockets. + Sockets also have `limitations and restrictions + `_ and have a lower free quota than URLFetch. + To use sockets, be sure to specify the following in your ``app.yaml``:: + + env_variables: + GAE_USE_SOCKETS_HTTPLIB : 'true' + +3. If you are using `App Engine Flexible +`_, you can use the standard +:class:`PoolManager` without any configuration or special environment variables. +""" + +from __future__ import absolute_import + +import io +import logging +import warnings + +from ..exceptions import ( + HTTPError, + HTTPWarning, + MaxRetryError, + ProtocolError, + SSLError, + TimeoutError, +) +from ..packages.six.moves.urllib.parse import urljoin +from ..request import RequestMethods +from ..response import HTTPResponse +from ..util.retry import Retry +from ..util.timeout import Timeout +from . import _appengine_environ + +try: + from google.appengine.api import urlfetch +except ImportError: + urlfetch = None + + +log = logging.getLogger(__name__) + + +class AppEnginePlatformWarning(HTTPWarning): + pass + + +class AppEnginePlatformError(HTTPError): + pass + + +class AppEngineManager(RequestMethods): + """ + Connection manager for Google App Engine sandbox applications. + + This manager uses the URLFetch service directly instead of using the + emulated httplib, and is subject to URLFetch limitations as described in + the App Engine documentation `here + `_. + + Notably it will raise an :class:`AppEnginePlatformError` if: + * URLFetch is not available. + * If you attempt to use this on App Engine Flexible, as full socket + support is available. + * If a request size is more than 10 megabytes. + * If a response size is more than 32 megabytes. + * If you use an unsupported request method such as OPTIONS. + + Beyond those cases, it will raise normal urllib3 errors. + """ + + def __init__( + self, + headers=None, + retries=None, + validate_certificate=True, + urlfetch_retries=True, + ): + if not urlfetch: + raise AppEnginePlatformError( + "URLFetch is not available in this environment." + ) + + warnings.warn( + "urllib3 is using URLFetch on Google App Engine sandbox instead " + "of sockets. To use sockets directly instead of URLFetch see " + "https://urllib3.readthedocs.io/en/1.26.x/reference/urllib3.contrib.html.", + AppEnginePlatformWarning, + ) + + RequestMethods.__init__(self, headers) + self.validate_certificate = validate_certificate + self.urlfetch_retries = urlfetch_retries + + self.retries = retries or Retry.DEFAULT + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + # Return False to re-raise any potential exceptions + return False + + def urlopen( + self, + method, + url, + body=None, + headers=None, + retries=None, + redirect=True, + timeout=Timeout.DEFAULT_TIMEOUT, + **response_kw + ): + + retries = self._get_retries(retries, redirect) + + try: + follow_redirects = redirect and retries.redirect != 0 and retries.total + response = urlfetch.fetch( + url, + payload=body, + method=method, + headers=headers or {}, + allow_truncated=False, + follow_redirects=self.urlfetch_retries and follow_redirects, + deadline=self._get_absolute_timeout(timeout), + validate_certificate=self.validate_certificate, + ) + except urlfetch.DeadlineExceededError as e: + raise TimeoutError(self, e) + + except urlfetch.InvalidURLError as e: + if "too large" in str(e): + raise AppEnginePlatformError( + "URLFetch request too large, URLFetch only " + "supports requests up to 10mb in size.", + e, + ) + raise ProtocolError(e) + + except urlfetch.DownloadError as e: + if "Too many redirects" in str(e): + raise MaxRetryError(self, url, reason=e) + raise ProtocolError(e) + + except urlfetch.ResponseTooLargeError as e: + raise AppEnginePlatformError( + "URLFetch response too large, URLFetch only supports" + "responses up to 32mb in size.", + e, + ) + + except urlfetch.SSLCertificateError as e: + raise SSLError(e) + + except urlfetch.InvalidMethodError as e: + raise AppEnginePlatformError( + "URLFetch does not support method: %s" % method, e + ) + + http_response = self._urlfetch_response_to_http_response( + response, retries=retries, **response_kw + ) + + # Handle redirect? + redirect_location = redirect and http_response.get_redirect_location() + if redirect_location: + # Check for redirect response + if self.urlfetch_retries and retries.raise_on_redirect: + raise MaxRetryError(self, url, "too many redirects") + else: + if http_response.status == 303: + method = "GET" + + try: + retries = retries.increment( + method, url, response=http_response, _pool=self + ) + except MaxRetryError: + if retries.raise_on_redirect: + raise MaxRetryError(self, url, "too many redirects") + return http_response + + retries.sleep_for_retry(http_response) + log.debug("Redirecting %s -> %s", url, redirect_location) + redirect_url = urljoin(url, redirect_location) + return self.urlopen( + method, + redirect_url, + body, + headers, + retries=retries, + redirect=redirect, + timeout=timeout, + **response_kw + ) + + # Check if we should retry the HTTP response. + has_retry_after = bool(http_response.headers.get("Retry-After")) + if retries.is_retry(method, http_response.status, has_retry_after): + retries = retries.increment(method, url, response=http_response, _pool=self) + log.debug("Retry: %s", url) + retries.sleep(http_response) + return self.urlopen( + method, + url, + body=body, + headers=headers, + retries=retries, + redirect=redirect, + timeout=timeout, + **response_kw + ) + + return http_response + + def _urlfetch_response_to_http_response(self, urlfetch_resp, **response_kw): + + if is_prod_appengine(): + # Production GAE handles deflate encoding automatically, but does + # not remove the encoding header. + content_encoding = urlfetch_resp.headers.get("content-encoding") + + if content_encoding == "deflate": + del urlfetch_resp.headers["content-encoding"] + + transfer_encoding = urlfetch_resp.headers.get("transfer-encoding") + # We have a full response's content, + # so let's make sure we don't report ourselves as chunked data. + if transfer_encoding == "chunked": + encodings = transfer_encoding.split(",") + encodings.remove("chunked") + urlfetch_resp.headers["transfer-encoding"] = ",".join(encodings) + + original_response = HTTPResponse( + # In order for decoding to work, we must present the content as + # a file-like object. + body=io.BytesIO(urlfetch_resp.content), + msg=urlfetch_resp.header_msg, + headers=urlfetch_resp.headers, + status=urlfetch_resp.status_code, + **response_kw + ) + + return HTTPResponse( + body=io.BytesIO(urlfetch_resp.content), + headers=urlfetch_resp.headers, + status=urlfetch_resp.status_code, + original_response=original_response, + **response_kw + ) + + def _get_absolute_timeout(self, timeout): + if timeout is Timeout.DEFAULT_TIMEOUT: + return None # Defer to URLFetch's default. + if isinstance(timeout, Timeout): + if timeout._read is not None or timeout._connect is not None: + warnings.warn( + "URLFetch does not support granular timeout settings, " + "reverting to total or default URLFetch timeout.", + AppEnginePlatformWarning, + ) + return timeout.total + return timeout + + def _get_retries(self, retries, redirect): + if not isinstance(retries, Retry): + retries = Retry.from_int(retries, redirect=redirect, default=self.retries) + + if retries.connect or retries.read or retries.redirect: + warnings.warn( + "URLFetch only supports total retries and does not " + "recognize connect, read, or redirect retry parameters.", + AppEnginePlatformWarning, + ) + + return retries + + +# Alias methods from _appengine_environ to maintain public API interface. + +is_appengine = _appengine_environ.is_appengine +is_appengine_sandbox = _appengine_environ.is_appengine_sandbox +is_local_appengine = _appengine_environ.is_local_appengine +is_prod_appengine = _appengine_environ.is_prod_appengine +is_prod_appengine_mvms = _appengine_environ.is_prod_appengine_mvms diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py new file mode 100644 index 0000000..4716657 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py @@ -0,0 +1,130 @@ +""" +NTLM authenticating pool, contributed by erikcederstran + +Issue #10, see: http://code.google.com/p/urllib3/issues/detail?id=10 +""" +from __future__ import absolute_import + +import warnings +from logging import getLogger + +from ntlm import ntlm + +from .. import HTTPSConnectionPool +from ..packages.six.moves.http_client import HTTPSConnection + +warnings.warn( + "The 'urllib3.contrib.ntlmpool' module is deprecated and will be removed " + "in urllib3 v2.0 release, urllib3 is not able to support it properly due " + "to reasons listed in issue: https://github.com/urllib3/urllib3/issues/2282. " + "If you are a user of this module please comment in the mentioned issue.", + DeprecationWarning, +) + +log = getLogger(__name__) + + +class NTLMConnectionPool(HTTPSConnectionPool): + """ + Implements an NTLM authentication version of an urllib3 connection pool + """ + + scheme = "https" + + def __init__(self, user, pw, authurl, *args, **kwargs): + """ + authurl is a random URL on the server that is protected by NTLM. + user is the Windows user, probably in the DOMAIN\\username format. + pw is the password for the user. + """ + super(NTLMConnectionPool, self).__init__(*args, **kwargs) + self.authurl = authurl + self.rawuser = user + user_parts = user.split("\\", 1) + self.domain = user_parts[0].upper() + self.user = user_parts[1] + self.pw = pw + + def _new_conn(self): + # Performs the NTLM handshake that secures the connection. The socket + # must be kept open while requests are performed. + self.num_connections += 1 + log.debug( + "Starting NTLM HTTPS connection no. %d: https://%s%s", + self.num_connections, + self.host, + self.authurl, + ) + + headers = {"Connection": "Keep-Alive"} + req_header = "Authorization" + resp_header = "www-authenticate" + + conn = HTTPSConnection(host=self.host, port=self.port) + + # Send negotiation message + headers[req_header] = "NTLM %s" % ntlm.create_NTLM_NEGOTIATE_MESSAGE( + self.rawuser + ) + log.debug("Request headers: %s", headers) + conn.request("GET", self.authurl, None, headers) + res = conn.getresponse() + reshdr = dict(res.headers) + log.debug("Response status: %s %s", res.status, res.reason) + log.debug("Response headers: %s", reshdr) + log.debug("Response data: %s [...]", res.read(100)) + + # Remove the reference to the socket, so that it can not be closed by + # the response object (we want to keep the socket open) + res.fp = None + + # Server should respond with a challenge message + auth_header_values = reshdr[resp_header].split(", ") + auth_header_value = None + for s in auth_header_values: + if s[:5] == "NTLM ": + auth_header_value = s[5:] + if auth_header_value is None: + raise Exception( + "Unexpected %s response header: %s" % (resp_header, reshdr[resp_header]) + ) + + # Send authentication message + ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE( + auth_header_value + ) + auth_msg = ntlm.create_NTLM_AUTHENTICATE_MESSAGE( + ServerChallenge, self.user, self.domain, self.pw, NegotiateFlags + ) + headers[req_header] = "NTLM %s" % auth_msg + log.debug("Request headers: %s", headers) + conn.request("GET", self.authurl, None, headers) + res = conn.getresponse() + log.debug("Response status: %s %s", res.status, res.reason) + log.debug("Response headers: %s", dict(res.headers)) + log.debug("Response data: %s [...]", res.read()[:100]) + if res.status != 200: + if res.status == 401: + raise Exception("Server rejected request: wrong username or password") + raise Exception("Wrong server response: %s %s" % (res.status, res.reason)) + + res.fp = None + log.debug("Connection established") + return conn + + def urlopen( + self, + method, + url, + body=None, + headers=None, + retries=3, + redirect=True, + assert_same_host=True, + ): + if headers is None: + headers = {} + headers["Connection"] = "Keep-Alive" + return super(NTLMConnectionPool, self).urlopen( + method, url, body, headers, retries, redirect, assert_same_host + ) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py new file mode 100644 index 0000000..19e4aa9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py @@ -0,0 +1,518 @@ +""" +TLS with SNI_-support for Python 2. Follow these instructions if you would +like to verify TLS certificates in Python 2. Note, the default libraries do +*not* do certificate checking; you need to do additional work to validate +certificates yourself. + +This needs the following packages installed: + +* `pyOpenSSL`_ (tested with 16.0.0) +* `cryptography`_ (minimum 1.3.4, from pyopenssl) +* `idna`_ (minimum 2.0, from cryptography) + +However, pyopenssl depends on cryptography, which depends on idna, so while we +use all three directly here we end up having relatively few packages required. + +You can install them with the following command: + +.. code-block:: bash + + $ python -m pip install pyopenssl cryptography idna + +To activate certificate checking, call +:func:`~urllib3.contrib.pyopenssl.inject_into_urllib3` from your Python code +before you begin making HTTP requests. This can be done in a ``sitecustomize`` +module, or at any other time before your application begins using ``urllib3``, +like this: + +.. code-block:: python + + try: + import pip._vendor.urllib3.contrib.pyopenssl as pyopenssl + pyopenssl.inject_into_urllib3() + except ImportError: + pass + +Now you can use :mod:`urllib3` as you normally would, and it will support SNI +when the required modules are installed. + +Activating this module also has the positive side effect of disabling SSL/TLS +compression in Python 2 (see `CRIME attack`_). + +.. _sni: https://en.wikipedia.org/wiki/Server_Name_Indication +.. _crime attack: https://en.wikipedia.org/wiki/CRIME_(security_exploit) +.. _pyopenssl: https://www.pyopenssl.org +.. _cryptography: https://cryptography.io +.. _idna: https://github.com/kjd/idna +""" +from __future__ import absolute_import + +import OpenSSL.crypto +import OpenSSL.SSL +from cryptography import x509 +from cryptography.hazmat.backends.openssl import backend as openssl_backend + +try: + from cryptography.x509 import UnsupportedExtension +except ImportError: + # UnsupportedExtension is gone in cryptography >= 2.1.0 + class UnsupportedExtension(Exception): + pass + + +from io import BytesIO +from socket import error as SocketError +from socket import timeout + +try: # Platform-specific: Python 2 + from socket import _fileobject +except ImportError: # Platform-specific: Python 3 + _fileobject = None + from ..packages.backports.makefile import backport_makefile + +import logging +import ssl +import sys +import warnings + +from .. import util +from ..packages import six +from ..util.ssl_ import PROTOCOL_TLS_CLIENT + +warnings.warn( + "'urllib3.contrib.pyopenssl' module is deprecated and will be removed " + "in a future release of urllib3 2.x. Read more in this issue: " + "https://github.com/urllib3/urllib3/issues/2680", + category=DeprecationWarning, + stacklevel=2, +) + +__all__ = ["inject_into_urllib3", "extract_from_urllib3"] + +# SNI always works. +HAS_SNI = True + +# Map from urllib3 to PyOpenSSL compatible parameter-values. +_openssl_versions = { + util.PROTOCOL_TLS: OpenSSL.SSL.SSLv23_METHOD, + PROTOCOL_TLS_CLIENT: OpenSSL.SSL.SSLv23_METHOD, + ssl.PROTOCOL_TLSv1: OpenSSL.SSL.TLSv1_METHOD, +} + +if hasattr(ssl, "PROTOCOL_SSLv3") and hasattr(OpenSSL.SSL, "SSLv3_METHOD"): + _openssl_versions[ssl.PROTOCOL_SSLv3] = OpenSSL.SSL.SSLv3_METHOD + +if hasattr(ssl, "PROTOCOL_TLSv1_1") and hasattr(OpenSSL.SSL, "TLSv1_1_METHOD"): + _openssl_versions[ssl.PROTOCOL_TLSv1_1] = OpenSSL.SSL.TLSv1_1_METHOD + +if hasattr(ssl, "PROTOCOL_TLSv1_2") and hasattr(OpenSSL.SSL, "TLSv1_2_METHOD"): + _openssl_versions[ssl.PROTOCOL_TLSv1_2] = OpenSSL.SSL.TLSv1_2_METHOD + + +_stdlib_to_openssl_verify = { + ssl.CERT_NONE: OpenSSL.SSL.VERIFY_NONE, + ssl.CERT_OPTIONAL: OpenSSL.SSL.VERIFY_PEER, + ssl.CERT_REQUIRED: OpenSSL.SSL.VERIFY_PEER + + OpenSSL.SSL.VERIFY_FAIL_IF_NO_PEER_CERT, +} +_openssl_to_stdlib_verify = dict((v, k) for k, v in _stdlib_to_openssl_verify.items()) + +# OpenSSL will only write 16K at a time +SSL_WRITE_BLOCKSIZE = 16384 + +orig_util_HAS_SNI = util.HAS_SNI +orig_util_SSLContext = util.ssl_.SSLContext + + +log = logging.getLogger(__name__) + + +def inject_into_urllib3(): + "Monkey-patch urllib3 with PyOpenSSL-backed SSL-support." + + _validate_dependencies_met() + + util.SSLContext = PyOpenSSLContext + util.ssl_.SSLContext = PyOpenSSLContext + util.HAS_SNI = HAS_SNI + util.ssl_.HAS_SNI = HAS_SNI + util.IS_PYOPENSSL = True + util.ssl_.IS_PYOPENSSL = True + + +def extract_from_urllib3(): + "Undo monkey-patching by :func:`inject_into_urllib3`." + + util.SSLContext = orig_util_SSLContext + util.ssl_.SSLContext = orig_util_SSLContext + util.HAS_SNI = orig_util_HAS_SNI + util.ssl_.HAS_SNI = orig_util_HAS_SNI + util.IS_PYOPENSSL = False + util.ssl_.IS_PYOPENSSL = False + + +def _validate_dependencies_met(): + """ + Verifies that PyOpenSSL's package-level dependencies have been met. + Throws `ImportError` if they are not met. + """ + # Method added in `cryptography==1.1`; not available in older versions + from cryptography.x509.extensions import Extensions + + if getattr(Extensions, "get_extension_for_class", None) is None: + raise ImportError( + "'cryptography' module missing required functionality. " + "Try upgrading to v1.3.4 or newer." + ) + + # pyOpenSSL 0.14 and above use cryptography for OpenSSL bindings. The _x509 + # attribute is only present on those versions. + from OpenSSL.crypto import X509 + + x509 = X509() + if getattr(x509, "_x509", None) is None: + raise ImportError( + "'pyOpenSSL' module missing required functionality. " + "Try upgrading to v0.14 or newer." + ) + + +def _dnsname_to_stdlib(name): + """ + Converts a dNSName SubjectAlternativeName field to the form used by the + standard library on the given Python version. + + Cryptography produces a dNSName as a unicode string that was idna-decoded + from ASCII bytes. We need to idna-encode that string to get it back, and + then on Python 3 we also need to convert to unicode via UTF-8 (the stdlib + uses PyUnicode_FromStringAndSize on it, which decodes via UTF-8). + + If the name cannot be idna-encoded then we return None signalling that + the name given should be skipped. + """ + + def idna_encode(name): + """ + Borrowed wholesale from the Python Cryptography Project. It turns out + that we can't just safely call `idna.encode`: it can explode for + wildcard names. This avoids that problem. + """ + from pip._vendor import idna + + try: + for prefix in [u"*.", u"."]: + if name.startswith(prefix): + name = name[len(prefix) :] + return prefix.encode("ascii") + idna.encode(name) + return idna.encode(name) + except idna.core.IDNAError: + return None + + # Don't send IPv6 addresses through the IDNA encoder. + if ":" in name: + return name + + name = idna_encode(name) + if name is None: + return None + elif sys.version_info >= (3, 0): + name = name.decode("utf-8") + return name + + +def get_subj_alt_name(peer_cert): + """ + Given an PyOpenSSL certificate, provides all the subject alternative names. + """ + # Pass the cert to cryptography, which has much better APIs for this. + if hasattr(peer_cert, "to_cryptography"): + cert = peer_cert.to_cryptography() + else: + der = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_ASN1, peer_cert) + cert = x509.load_der_x509_certificate(der, openssl_backend) + + # We want to find the SAN extension. Ask Cryptography to locate it (it's + # faster than looping in Python) + try: + ext = cert.extensions.get_extension_for_class(x509.SubjectAlternativeName).value + except x509.ExtensionNotFound: + # No such extension, return the empty list. + return [] + except ( + x509.DuplicateExtension, + UnsupportedExtension, + x509.UnsupportedGeneralNameType, + UnicodeError, + ) as e: + # A problem has been found with the quality of the certificate. Assume + # no SAN field is present. + log.warning( + "A problem was encountered with the certificate that prevented " + "urllib3 from finding the SubjectAlternativeName field. This can " + "affect certificate validation. The error was %s", + e, + ) + return [] + + # We want to return dNSName and iPAddress fields. We need to cast the IPs + # back to strings because the match_hostname function wants them as + # strings. + # Sadly the DNS names need to be idna encoded and then, on Python 3, UTF-8 + # decoded. This is pretty frustrating, but that's what the standard library + # does with certificates, and so we need to attempt to do the same. + # We also want to skip over names which cannot be idna encoded. + names = [ + ("DNS", name) + for name in map(_dnsname_to_stdlib, ext.get_values_for_type(x509.DNSName)) + if name is not None + ] + names.extend( + ("IP Address", str(name)) for name in ext.get_values_for_type(x509.IPAddress) + ) + + return names + + +class WrappedSocket(object): + """API-compatibility wrapper for Python OpenSSL's Connection-class. + + Note: _makefile_refs, _drop() and _reuse() are needed for the garbage + collector of pypy. + """ + + def __init__(self, connection, socket, suppress_ragged_eofs=True): + self.connection = connection + self.socket = socket + self.suppress_ragged_eofs = suppress_ragged_eofs + self._makefile_refs = 0 + self._closed = False + + def fileno(self): + return self.socket.fileno() + + # Copy-pasted from Python 3.5 source code + def _decref_socketios(self): + if self._makefile_refs > 0: + self._makefile_refs -= 1 + if self._closed: + self.close() + + def recv(self, *args, **kwargs): + try: + data = self.connection.recv(*args, **kwargs) + except OpenSSL.SSL.SysCallError as e: + if self.suppress_ragged_eofs and e.args == (-1, "Unexpected EOF"): + return b"" + else: + raise SocketError(str(e)) + except OpenSSL.SSL.ZeroReturnError: + if self.connection.get_shutdown() == OpenSSL.SSL.RECEIVED_SHUTDOWN: + return b"" + else: + raise + except OpenSSL.SSL.WantReadError: + if not util.wait_for_read(self.socket, self.socket.gettimeout()): + raise timeout("The read operation timed out") + else: + return self.recv(*args, **kwargs) + + # TLS 1.3 post-handshake authentication + except OpenSSL.SSL.Error as e: + raise ssl.SSLError("read error: %r" % e) + else: + return data + + def recv_into(self, *args, **kwargs): + try: + return self.connection.recv_into(*args, **kwargs) + except OpenSSL.SSL.SysCallError as e: + if self.suppress_ragged_eofs and e.args == (-1, "Unexpected EOF"): + return 0 + else: + raise SocketError(str(e)) + except OpenSSL.SSL.ZeroReturnError: + if self.connection.get_shutdown() == OpenSSL.SSL.RECEIVED_SHUTDOWN: + return 0 + else: + raise + except OpenSSL.SSL.WantReadError: + if not util.wait_for_read(self.socket, self.socket.gettimeout()): + raise timeout("The read operation timed out") + else: + return self.recv_into(*args, **kwargs) + + # TLS 1.3 post-handshake authentication + except OpenSSL.SSL.Error as e: + raise ssl.SSLError("read error: %r" % e) + + def settimeout(self, timeout): + return self.socket.settimeout(timeout) + + def _send_until_done(self, data): + while True: + try: + return self.connection.send(data) + except OpenSSL.SSL.WantWriteError: + if not util.wait_for_write(self.socket, self.socket.gettimeout()): + raise timeout() + continue + except OpenSSL.SSL.SysCallError as e: + raise SocketError(str(e)) + + def sendall(self, data): + total_sent = 0 + while total_sent < len(data): + sent = self._send_until_done( + data[total_sent : total_sent + SSL_WRITE_BLOCKSIZE] + ) + total_sent += sent + + def shutdown(self): + # FIXME rethrow compatible exceptions should we ever use this + self.connection.shutdown() + + def close(self): + if self._makefile_refs < 1: + try: + self._closed = True + return self.connection.close() + except OpenSSL.SSL.Error: + return + else: + self._makefile_refs -= 1 + + def getpeercert(self, binary_form=False): + x509 = self.connection.get_peer_certificate() + + if not x509: + return x509 + + if binary_form: + return OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_ASN1, x509) + + return { + "subject": ((("commonName", x509.get_subject().CN),),), + "subjectAltName": get_subj_alt_name(x509), + } + + def version(self): + return self.connection.get_protocol_version_name() + + def _reuse(self): + self._makefile_refs += 1 + + def _drop(self): + if self._makefile_refs < 1: + self.close() + else: + self._makefile_refs -= 1 + + +if _fileobject: # Platform-specific: Python 2 + + def makefile(self, mode, bufsize=-1): + self._makefile_refs += 1 + return _fileobject(self, mode, bufsize, close=True) + +else: # Platform-specific: Python 3 + makefile = backport_makefile + +WrappedSocket.makefile = makefile + + +class PyOpenSSLContext(object): + """ + I am a wrapper class for the PyOpenSSL ``Context`` object. I am responsible + for translating the interface of the standard library ``SSLContext`` object + to calls into PyOpenSSL. + """ + + def __init__(self, protocol): + self.protocol = _openssl_versions[protocol] + self._ctx = OpenSSL.SSL.Context(self.protocol) + self._options = 0 + self.check_hostname = False + + @property + def options(self): + return self._options + + @options.setter + def options(self, value): + self._options = value + self._ctx.set_options(value) + + @property + def verify_mode(self): + return _openssl_to_stdlib_verify[self._ctx.get_verify_mode()] + + @verify_mode.setter + def verify_mode(self, value): + self._ctx.set_verify(_stdlib_to_openssl_verify[value], _verify_callback) + + def set_default_verify_paths(self): + self._ctx.set_default_verify_paths() + + def set_ciphers(self, ciphers): + if isinstance(ciphers, six.text_type): + ciphers = ciphers.encode("utf-8") + self._ctx.set_cipher_list(ciphers) + + def load_verify_locations(self, cafile=None, capath=None, cadata=None): + if cafile is not None: + cafile = cafile.encode("utf-8") + if capath is not None: + capath = capath.encode("utf-8") + try: + self._ctx.load_verify_locations(cafile, capath) + if cadata is not None: + self._ctx.load_verify_locations(BytesIO(cadata)) + except OpenSSL.SSL.Error as e: + raise ssl.SSLError("unable to load trusted certificates: %r" % e) + + def load_cert_chain(self, certfile, keyfile=None, password=None): + self._ctx.use_certificate_chain_file(certfile) + if password is not None: + if not isinstance(password, six.binary_type): + password = password.encode("utf-8") + self._ctx.set_passwd_cb(lambda *_: password) + self._ctx.use_privatekey_file(keyfile or certfile) + + def set_alpn_protocols(self, protocols): + protocols = [six.ensure_binary(p) for p in protocols] + return self._ctx.set_alpn_protos(protocols) + + def wrap_socket( + self, + sock, + server_side=False, + do_handshake_on_connect=True, + suppress_ragged_eofs=True, + server_hostname=None, + ): + cnx = OpenSSL.SSL.Connection(self._ctx, sock) + + if isinstance(server_hostname, six.text_type): # Platform-specific: Python 3 + server_hostname = server_hostname.encode("utf-8") + + if server_hostname is not None: + cnx.set_tlsext_host_name(server_hostname) + + cnx.set_connect_state() + + while True: + try: + cnx.do_handshake() + except OpenSSL.SSL.WantReadError: + if not util.wait_for_read(sock, sock.gettimeout()): + raise timeout("select timed out") + continue + except OpenSSL.SSL.Error as e: + raise ssl.SSLError("bad handshake: %r" % e) + break + + return WrappedSocket(cnx, sock) + + +def _verify_callback(cnx, x509, err_no, err_depth, return_code): + return err_no == 0 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/securetransport.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/securetransport.py new file mode 100644 index 0000000..722ee4e --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/securetransport.py @@ -0,0 +1,920 @@ +""" +SecureTranport support for urllib3 via ctypes. + +This makes platform-native TLS available to urllib3 users on macOS without the +use of a compiler. This is an important feature because the Python Package +Index is moving to become a TLSv1.2-or-higher server, and the default OpenSSL +that ships with macOS is not capable of doing TLSv1.2. The only way to resolve +this is to give macOS users an alternative solution to the problem, and that +solution is to use SecureTransport. + +We use ctypes here because this solution must not require a compiler. That's +because pip is not allowed to require a compiler either. + +This is not intended to be a seriously long-term solution to this problem. +The hope is that PEP 543 will eventually solve this issue for us, at which +point we can retire this contrib module. But in the short term, we need to +solve the impending tire fire that is Python on Mac without this kind of +contrib module. So...here we are. + +To use this module, simply import and inject it:: + + import pip._vendor.urllib3.contrib.securetransport as securetransport + securetransport.inject_into_urllib3() + +Happy TLSing! + +This code is a bastardised version of the code found in Will Bond's oscrypto +library. An enormous debt is owed to him for blazing this trail for us. For +that reason, this code should be considered to be covered both by urllib3's +license and by oscrypto's: + +.. code-block:: + + Copyright (c) 2015-2016 Will Bond + + 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. +""" +from __future__ import absolute_import + +import contextlib +import ctypes +import errno +import os.path +import shutil +import socket +import ssl +import struct +import threading +import weakref + +from .. import util +from ..packages import six +from ..util.ssl_ import PROTOCOL_TLS_CLIENT +from ._securetransport.bindings import CoreFoundation, Security, SecurityConst +from ._securetransport.low_level import ( + _assert_no_error, + _build_tls_unknown_ca_alert, + _cert_array_from_pem, + _create_cfstring_array, + _load_client_cert_chain, + _temporary_keychain, +) + +try: # Platform-specific: Python 2 + from socket import _fileobject +except ImportError: # Platform-specific: Python 3 + _fileobject = None + from ..packages.backports.makefile import backport_makefile + +__all__ = ["inject_into_urllib3", "extract_from_urllib3"] + +# SNI always works +HAS_SNI = True + +orig_util_HAS_SNI = util.HAS_SNI +orig_util_SSLContext = util.ssl_.SSLContext + +# This dictionary is used by the read callback to obtain a handle to the +# calling wrapped socket. This is a pretty silly approach, but for now it'll +# do. I feel like I should be able to smuggle a handle to the wrapped socket +# directly in the SSLConnectionRef, but for now this approach will work I +# guess. +# +# We need to lock around this structure for inserts, but we don't do it for +# reads/writes in the callbacks. The reasoning here goes as follows: +# +# 1. It is not possible to call into the callbacks before the dictionary is +# populated, so once in the callback the id must be in the dictionary. +# 2. The callbacks don't mutate the dictionary, they only read from it, and +# so cannot conflict with any of the insertions. +# +# This is good: if we had to lock in the callbacks we'd drastically slow down +# the performance of this code. +_connection_refs = weakref.WeakValueDictionary() +_connection_ref_lock = threading.Lock() + +# Limit writes to 16kB. This is OpenSSL's limit, but we'll cargo-cult it over +# for no better reason than we need *a* limit, and this one is right there. +SSL_WRITE_BLOCKSIZE = 16384 + +# This is our equivalent of util.ssl_.DEFAULT_CIPHERS, but expanded out to +# individual cipher suites. We need to do this because this is how +# SecureTransport wants them. +CIPHER_SUITES = [ + SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + SecurityConst.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + SecurityConst.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + SecurityConst.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, + SecurityConst.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, + SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, + SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + SecurityConst.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, + SecurityConst.TLS_DHE_RSA_WITH_AES_256_CBC_SHA, + SecurityConst.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + SecurityConst.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, + SecurityConst.TLS_AES_256_GCM_SHA384, + SecurityConst.TLS_AES_128_GCM_SHA256, + SecurityConst.TLS_RSA_WITH_AES_256_GCM_SHA384, + SecurityConst.TLS_RSA_WITH_AES_128_GCM_SHA256, + SecurityConst.TLS_AES_128_CCM_8_SHA256, + SecurityConst.TLS_AES_128_CCM_SHA256, + SecurityConst.TLS_RSA_WITH_AES_256_CBC_SHA256, + SecurityConst.TLS_RSA_WITH_AES_128_CBC_SHA256, + SecurityConst.TLS_RSA_WITH_AES_256_CBC_SHA, + SecurityConst.TLS_RSA_WITH_AES_128_CBC_SHA, +] + +# Basically this is simple: for PROTOCOL_SSLv23 we turn it into a low of +# TLSv1 and a high of TLSv1.2. For everything else, we pin to that version. +# TLSv1 to 1.2 are supported on macOS 10.8+ +_protocol_to_min_max = { + util.PROTOCOL_TLS: (SecurityConst.kTLSProtocol1, SecurityConst.kTLSProtocol12), + PROTOCOL_TLS_CLIENT: (SecurityConst.kTLSProtocol1, SecurityConst.kTLSProtocol12), +} + +if hasattr(ssl, "PROTOCOL_SSLv2"): + _protocol_to_min_max[ssl.PROTOCOL_SSLv2] = ( + SecurityConst.kSSLProtocol2, + SecurityConst.kSSLProtocol2, + ) +if hasattr(ssl, "PROTOCOL_SSLv3"): + _protocol_to_min_max[ssl.PROTOCOL_SSLv3] = ( + SecurityConst.kSSLProtocol3, + SecurityConst.kSSLProtocol3, + ) +if hasattr(ssl, "PROTOCOL_TLSv1"): + _protocol_to_min_max[ssl.PROTOCOL_TLSv1] = ( + SecurityConst.kTLSProtocol1, + SecurityConst.kTLSProtocol1, + ) +if hasattr(ssl, "PROTOCOL_TLSv1_1"): + _protocol_to_min_max[ssl.PROTOCOL_TLSv1_1] = ( + SecurityConst.kTLSProtocol11, + SecurityConst.kTLSProtocol11, + ) +if hasattr(ssl, "PROTOCOL_TLSv1_2"): + _protocol_to_min_max[ssl.PROTOCOL_TLSv1_2] = ( + SecurityConst.kTLSProtocol12, + SecurityConst.kTLSProtocol12, + ) + + +def inject_into_urllib3(): + """ + Monkey-patch urllib3 with SecureTransport-backed SSL-support. + """ + util.SSLContext = SecureTransportContext + util.ssl_.SSLContext = SecureTransportContext + util.HAS_SNI = HAS_SNI + util.ssl_.HAS_SNI = HAS_SNI + util.IS_SECURETRANSPORT = True + util.ssl_.IS_SECURETRANSPORT = True + + +def extract_from_urllib3(): + """ + Undo monkey-patching by :func:`inject_into_urllib3`. + """ + util.SSLContext = orig_util_SSLContext + util.ssl_.SSLContext = orig_util_SSLContext + util.HAS_SNI = orig_util_HAS_SNI + util.ssl_.HAS_SNI = orig_util_HAS_SNI + util.IS_SECURETRANSPORT = False + util.ssl_.IS_SECURETRANSPORT = False + + +def _read_callback(connection_id, data_buffer, data_length_pointer): + """ + SecureTransport read callback. This is called by ST to request that data + be returned from the socket. + """ + wrapped_socket = None + try: + wrapped_socket = _connection_refs.get(connection_id) + if wrapped_socket is None: + return SecurityConst.errSSLInternal + base_socket = wrapped_socket.socket + + requested_length = data_length_pointer[0] + + timeout = wrapped_socket.gettimeout() + error = None + read_count = 0 + + try: + while read_count < requested_length: + if timeout is None or timeout >= 0: + if not util.wait_for_read(base_socket, timeout): + raise socket.error(errno.EAGAIN, "timed out") + + remaining = requested_length - read_count + buffer = (ctypes.c_char * remaining).from_address( + data_buffer + read_count + ) + chunk_size = base_socket.recv_into(buffer, remaining) + read_count += chunk_size + if not chunk_size: + if not read_count: + return SecurityConst.errSSLClosedGraceful + break + except (socket.error) as e: + error = e.errno + + if error is not None and error != errno.EAGAIN: + data_length_pointer[0] = read_count + if error == errno.ECONNRESET or error == errno.EPIPE: + return SecurityConst.errSSLClosedAbort + raise + + data_length_pointer[0] = read_count + + if read_count != requested_length: + return SecurityConst.errSSLWouldBlock + + return 0 + except Exception as e: + if wrapped_socket is not None: + wrapped_socket._exception = e + return SecurityConst.errSSLInternal + + +def _write_callback(connection_id, data_buffer, data_length_pointer): + """ + SecureTransport write callback. This is called by ST to request that data + actually be sent on the network. + """ + wrapped_socket = None + try: + wrapped_socket = _connection_refs.get(connection_id) + if wrapped_socket is None: + return SecurityConst.errSSLInternal + base_socket = wrapped_socket.socket + + bytes_to_write = data_length_pointer[0] + data = ctypes.string_at(data_buffer, bytes_to_write) + + timeout = wrapped_socket.gettimeout() + error = None + sent = 0 + + try: + while sent < bytes_to_write: + if timeout is None or timeout >= 0: + if not util.wait_for_write(base_socket, timeout): + raise socket.error(errno.EAGAIN, "timed out") + chunk_sent = base_socket.send(data) + sent += chunk_sent + + # This has some needless copying here, but I'm not sure there's + # much value in optimising this data path. + data = data[chunk_sent:] + except (socket.error) as e: + error = e.errno + + if error is not None and error != errno.EAGAIN: + data_length_pointer[0] = sent + if error == errno.ECONNRESET or error == errno.EPIPE: + return SecurityConst.errSSLClosedAbort + raise + + data_length_pointer[0] = sent + + if sent != bytes_to_write: + return SecurityConst.errSSLWouldBlock + + return 0 + except Exception as e: + if wrapped_socket is not None: + wrapped_socket._exception = e + return SecurityConst.errSSLInternal + + +# We need to keep these two objects references alive: if they get GC'd while +# in use then SecureTransport could attempt to call a function that is in freed +# memory. That would be...uh...bad. Yeah, that's the word. Bad. +_read_callback_pointer = Security.SSLReadFunc(_read_callback) +_write_callback_pointer = Security.SSLWriteFunc(_write_callback) + + +class WrappedSocket(object): + """ + API-compatibility wrapper for Python's OpenSSL wrapped socket object. + + Note: _makefile_refs, _drop(), and _reuse() are needed for the garbage + collector of PyPy. + """ + + def __init__(self, socket): + self.socket = socket + self.context = None + self._makefile_refs = 0 + self._closed = False + self._exception = None + self._keychain = None + self._keychain_dir = None + self._client_cert_chain = None + + # We save off the previously-configured timeout and then set it to + # zero. This is done because we use select and friends to handle the + # timeouts, but if we leave the timeout set on the lower socket then + # Python will "kindly" call select on that socket again for us. Avoid + # that by forcing the timeout to zero. + self._timeout = self.socket.gettimeout() + self.socket.settimeout(0) + + @contextlib.contextmanager + def _raise_on_error(self): + """ + A context manager that can be used to wrap calls that do I/O from + SecureTransport. If any of the I/O callbacks hit an exception, this + context manager will correctly propagate the exception after the fact. + This avoids silently swallowing those exceptions. + + It also correctly forces the socket closed. + """ + self._exception = None + + # We explicitly don't catch around this yield because in the unlikely + # event that an exception was hit in the block we don't want to swallow + # it. + yield + if self._exception is not None: + exception, self._exception = self._exception, None + self.close() + raise exception + + def _set_ciphers(self): + """ + Sets up the allowed ciphers. By default this matches the set in + util.ssl_.DEFAULT_CIPHERS, at least as supported by macOS. This is done + custom and doesn't allow changing at this time, mostly because parsing + OpenSSL cipher strings is going to be a freaking nightmare. + """ + ciphers = (Security.SSLCipherSuite * len(CIPHER_SUITES))(*CIPHER_SUITES) + result = Security.SSLSetEnabledCiphers( + self.context, ciphers, len(CIPHER_SUITES) + ) + _assert_no_error(result) + + def _set_alpn_protocols(self, protocols): + """ + Sets up the ALPN protocols on the context. + """ + if not protocols: + return + protocols_arr = _create_cfstring_array(protocols) + try: + result = Security.SSLSetALPNProtocols(self.context, protocols_arr) + _assert_no_error(result) + finally: + CoreFoundation.CFRelease(protocols_arr) + + def _custom_validate(self, verify, trust_bundle): + """ + Called when we have set custom validation. We do this in two cases: + first, when cert validation is entirely disabled; and second, when + using a custom trust DB. + Raises an SSLError if the connection is not trusted. + """ + # If we disabled cert validation, just say: cool. + if not verify: + return + + successes = ( + SecurityConst.kSecTrustResultUnspecified, + SecurityConst.kSecTrustResultProceed, + ) + try: + trust_result = self._evaluate_trust(trust_bundle) + if trust_result in successes: + return + reason = "error code: %d" % (trust_result,) + except Exception as e: + # Do not trust on error + reason = "exception: %r" % (e,) + + # SecureTransport does not send an alert nor shuts down the connection. + rec = _build_tls_unknown_ca_alert(self.version()) + self.socket.sendall(rec) + # close the connection immediately + # l_onoff = 1, activate linger + # l_linger = 0, linger for 0 seoncds + opts = struct.pack("ii", 1, 0) + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, opts) + self.close() + raise ssl.SSLError("certificate verify failed, %s" % reason) + + def _evaluate_trust(self, trust_bundle): + # We want data in memory, so load it up. + if os.path.isfile(trust_bundle): + with open(trust_bundle, "rb") as f: + trust_bundle = f.read() + + cert_array = None + trust = Security.SecTrustRef() + + try: + # Get a CFArray that contains the certs we want. + cert_array = _cert_array_from_pem(trust_bundle) + + # Ok, now the hard part. We want to get the SecTrustRef that ST has + # created for this connection, shove our CAs into it, tell ST to + # ignore everything else it knows, and then ask if it can build a + # chain. This is a buuuunch of code. + result = Security.SSLCopyPeerTrust(self.context, ctypes.byref(trust)) + _assert_no_error(result) + if not trust: + raise ssl.SSLError("Failed to copy trust reference") + + result = Security.SecTrustSetAnchorCertificates(trust, cert_array) + _assert_no_error(result) + + result = Security.SecTrustSetAnchorCertificatesOnly(trust, True) + _assert_no_error(result) + + trust_result = Security.SecTrustResultType() + result = Security.SecTrustEvaluate(trust, ctypes.byref(trust_result)) + _assert_no_error(result) + finally: + if trust: + CoreFoundation.CFRelease(trust) + + if cert_array is not None: + CoreFoundation.CFRelease(cert_array) + + return trust_result.value + + def handshake( + self, + server_hostname, + verify, + trust_bundle, + min_version, + max_version, + client_cert, + client_key, + client_key_passphrase, + alpn_protocols, + ): + """ + Actually performs the TLS handshake. This is run automatically by + wrapped socket, and shouldn't be needed in user code. + """ + # First, we do the initial bits of connection setup. We need to create + # a context, set its I/O funcs, and set the connection reference. + self.context = Security.SSLCreateContext( + None, SecurityConst.kSSLClientSide, SecurityConst.kSSLStreamType + ) + result = Security.SSLSetIOFuncs( + self.context, _read_callback_pointer, _write_callback_pointer + ) + _assert_no_error(result) + + # Here we need to compute the handle to use. We do this by taking the + # id of self modulo 2**31 - 1. If this is already in the dictionary, we + # just keep incrementing by one until we find a free space. + with _connection_ref_lock: + handle = id(self) % 2147483647 + while handle in _connection_refs: + handle = (handle + 1) % 2147483647 + _connection_refs[handle] = self + + result = Security.SSLSetConnection(self.context, handle) + _assert_no_error(result) + + # If we have a server hostname, we should set that too. + if server_hostname: + if not isinstance(server_hostname, bytes): + server_hostname = server_hostname.encode("utf-8") + + result = Security.SSLSetPeerDomainName( + self.context, server_hostname, len(server_hostname) + ) + _assert_no_error(result) + + # Setup the ciphers. + self._set_ciphers() + + # Setup the ALPN protocols. + self._set_alpn_protocols(alpn_protocols) + + # Set the minimum and maximum TLS versions. + result = Security.SSLSetProtocolVersionMin(self.context, min_version) + _assert_no_error(result) + + result = Security.SSLSetProtocolVersionMax(self.context, max_version) + _assert_no_error(result) + + # If there's a trust DB, we need to use it. We do that by telling + # SecureTransport to break on server auth. We also do that if we don't + # want to validate the certs at all: we just won't actually do any + # authing in that case. + if not verify or trust_bundle is not None: + result = Security.SSLSetSessionOption( + self.context, SecurityConst.kSSLSessionOptionBreakOnServerAuth, True + ) + _assert_no_error(result) + + # If there's a client cert, we need to use it. + if client_cert: + self._keychain, self._keychain_dir = _temporary_keychain() + self._client_cert_chain = _load_client_cert_chain( + self._keychain, client_cert, client_key + ) + result = Security.SSLSetCertificate(self.context, self._client_cert_chain) + _assert_no_error(result) + + while True: + with self._raise_on_error(): + result = Security.SSLHandshake(self.context) + + if result == SecurityConst.errSSLWouldBlock: + raise socket.timeout("handshake timed out") + elif result == SecurityConst.errSSLServerAuthCompleted: + self._custom_validate(verify, trust_bundle) + continue + else: + _assert_no_error(result) + break + + def fileno(self): + return self.socket.fileno() + + # Copy-pasted from Python 3.5 source code + def _decref_socketios(self): + if self._makefile_refs > 0: + self._makefile_refs -= 1 + if self._closed: + self.close() + + def recv(self, bufsiz): + buffer = ctypes.create_string_buffer(bufsiz) + bytes_read = self.recv_into(buffer, bufsiz) + data = buffer[:bytes_read] + return data + + def recv_into(self, buffer, nbytes=None): + # Read short on EOF. + if self._closed: + return 0 + + if nbytes is None: + nbytes = len(buffer) + + buffer = (ctypes.c_char * nbytes).from_buffer(buffer) + processed_bytes = ctypes.c_size_t(0) + + with self._raise_on_error(): + result = Security.SSLRead( + self.context, buffer, nbytes, ctypes.byref(processed_bytes) + ) + + # There are some result codes that we want to treat as "not always + # errors". Specifically, those are errSSLWouldBlock, + # errSSLClosedGraceful, and errSSLClosedNoNotify. + if result == SecurityConst.errSSLWouldBlock: + # If we didn't process any bytes, then this was just a time out. + # However, we can get errSSLWouldBlock in situations when we *did* + # read some data, and in those cases we should just read "short" + # and return. + if processed_bytes.value == 0: + # Timed out, no data read. + raise socket.timeout("recv timed out") + elif result in ( + SecurityConst.errSSLClosedGraceful, + SecurityConst.errSSLClosedNoNotify, + ): + # The remote peer has closed this connection. We should do so as + # well. Note that we don't actually return here because in + # principle this could actually be fired along with return data. + # It's unlikely though. + self.close() + else: + _assert_no_error(result) + + # Ok, we read and probably succeeded. We should return whatever data + # was actually read. + return processed_bytes.value + + def settimeout(self, timeout): + self._timeout = timeout + + def gettimeout(self): + return self._timeout + + def send(self, data): + processed_bytes = ctypes.c_size_t(0) + + with self._raise_on_error(): + result = Security.SSLWrite( + self.context, data, len(data), ctypes.byref(processed_bytes) + ) + + if result == SecurityConst.errSSLWouldBlock and processed_bytes.value == 0: + # Timed out + raise socket.timeout("send timed out") + else: + _assert_no_error(result) + + # We sent, and probably succeeded. Tell them how much we sent. + return processed_bytes.value + + def sendall(self, data): + total_sent = 0 + while total_sent < len(data): + sent = self.send(data[total_sent : total_sent + SSL_WRITE_BLOCKSIZE]) + total_sent += sent + + def shutdown(self): + with self._raise_on_error(): + Security.SSLClose(self.context) + + def close(self): + # TODO: should I do clean shutdown here? Do I have to? + if self._makefile_refs < 1: + self._closed = True + if self.context: + CoreFoundation.CFRelease(self.context) + self.context = None + if self._client_cert_chain: + CoreFoundation.CFRelease(self._client_cert_chain) + self._client_cert_chain = None + if self._keychain: + Security.SecKeychainDelete(self._keychain) + CoreFoundation.CFRelease(self._keychain) + shutil.rmtree(self._keychain_dir) + self._keychain = self._keychain_dir = None + return self.socket.close() + else: + self._makefile_refs -= 1 + + def getpeercert(self, binary_form=False): + # Urgh, annoying. + # + # Here's how we do this: + # + # 1. Call SSLCopyPeerTrust to get hold of the trust object for this + # connection. + # 2. Call SecTrustGetCertificateAtIndex for index 0 to get the leaf. + # 3. To get the CN, call SecCertificateCopyCommonName and process that + # string so that it's of the appropriate type. + # 4. To get the SAN, we need to do something a bit more complex: + # a. Call SecCertificateCopyValues to get the data, requesting + # kSecOIDSubjectAltName. + # b. Mess about with this dictionary to try to get the SANs out. + # + # This is gross. Really gross. It's going to be a few hundred LoC extra + # just to repeat something that SecureTransport can *already do*. So my + # operating assumption at this time is that what we want to do is + # instead to just flag to urllib3 that it shouldn't do its own hostname + # validation when using SecureTransport. + if not binary_form: + raise ValueError("SecureTransport only supports dumping binary certs") + trust = Security.SecTrustRef() + certdata = None + der_bytes = None + + try: + # Grab the trust store. + result = Security.SSLCopyPeerTrust(self.context, ctypes.byref(trust)) + _assert_no_error(result) + if not trust: + # Probably we haven't done the handshake yet. No biggie. + return None + + cert_count = Security.SecTrustGetCertificateCount(trust) + if not cert_count: + # Also a case that might happen if we haven't handshaked. + # Handshook? Handshaken? + return None + + leaf = Security.SecTrustGetCertificateAtIndex(trust, 0) + assert leaf + + # Ok, now we want the DER bytes. + certdata = Security.SecCertificateCopyData(leaf) + assert certdata + + data_length = CoreFoundation.CFDataGetLength(certdata) + data_buffer = CoreFoundation.CFDataGetBytePtr(certdata) + der_bytes = ctypes.string_at(data_buffer, data_length) + finally: + if certdata: + CoreFoundation.CFRelease(certdata) + if trust: + CoreFoundation.CFRelease(trust) + + return der_bytes + + def version(self): + protocol = Security.SSLProtocol() + result = Security.SSLGetNegotiatedProtocolVersion( + self.context, ctypes.byref(protocol) + ) + _assert_no_error(result) + if protocol.value == SecurityConst.kTLSProtocol13: + raise ssl.SSLError("SecureTransport does not support TLS 1.3") + elif protocol.value == SecurityConst.kTLSProtocol12: + return "TLSv1.2" + elif protocol.value == SecurityConst.kTLSProtocol11: + return "TLSv1.1" + elif protocol.value == SecurityConst.kTLSProtocol1: + return "TLSv1" + elif protocol.value == SecurityConst.kSSLProtocol3: + return "SSLv3" + elif protocol.value == SecurityConst.kSSLProtocol2: + return "SSLv2" + else: + raise ssl.SSLError("Unknown TLS version: %r" % protocol) + + def _reuse(self): + self._makefile_refs += 1 + + def _drop(self): + if self._makefile_refs < 1: + self.close() + else: + self._makefile_refs -= 1 + + +if _fileobject: # Platform-specific: Python 2 + + def makefile(self, mode, bufsize=-1): + self._makefile_refs += 1 + return _fileobject(self, mode, bufsize, close=True) + +else: # Platform-specific: Python 3 + + def makefile(self, mode="r", buffering=None, *args, **kwargs): + # We disable buffering with SecureTransport because it conflicts with + # the buffering that ST does internally (see issue #1153 for more). + buffering = 0 + return backport_makefile(self, mode, buffering, *args, **kwargs) + + +WrappedSocket.makefile = makefile + + +class SecureTransportContext(object): + """ + I am a wrapper class for the SecureTransport library, to translate the + interface of the standard library ``SSLContext`` object to calls into + SecureTransport. + """ + + def __init__(self, protocol): + self._min_version, self._max_version = _protocol_to_min_max[protocol] + self._options = 0 + self._verify = False + self._trust_bundle = None + self._client_cert = None + self._client_key = None + self._client_key_passphrase = None + self._alpn_protocols = None + + @property + def check_hostname(self): + """ + SecureTransport cannot have its hostname checking disabled. For more, + see the comment on getpeercert() in this file. + """ + return True + + @check_hostname.setter + def check_hostname(self, value): + """ + SecureTransport cannot have its hostname checking disabled. For more, + see the comment on getpeercert() in this file. + """ + pass + + @property + def options(self): + # TODO: Well, crap. + # + # So this is the bit of the code that is the most likely to cause us + # trouble. Essentially we need to enumerate all of the SSL options that + # users might want to use and try to see if we can sensibly translate + # them, or whether we should just ignore them. + return self._options + + @options.setter + def options(self, value): + # TODO: Update in line with above. + self._options = value + + @property + def verify_mode(self): + return ssl.CERT_REQUIRED if self._verify else ssl.CERT_NONE + + @verify_mode.setter + def verify_mode(self, value): + self._verify = True if value == ssl.CERT_REQUIRED else False + + def set_default_verify_paths(self): + # So, this has to do something a bit weird. Specifically, what it does + # is nothing. + # + # This means that, if we had previously had load_verify_locations + # called, this does not undo that. We need to do that because it turns + # out that the rest of the urllib3 code will attempt to load the + # default verify paths if it hasn't been told about any paths, even if + # the context itself was sometime earlier. We resolve that by just + # ignoring it. + pass + + def load_default_certs(self): + return self.set_default_verify_paths() + + def set_ciphers(self, ciphers): + # For now, we just require the default cipher string. + if ciphers != util.ssl_.DEFAULT_CIPHERS: + raise ValueError("SecureTransport doesn't support custom cipher strings") + + def load_verify_locations(self, cafile=None, capath=None, cadata=None): + # OK, we only really support cadata and cafile. + if capath is not None: + raise ValueError("SecureTransport does not support cert directories") + + # Raise if cafile does not exist. + if cafile is not None: + with open(cafile): + pass + + self._trust_bundle = cafile or cadata + + def load_cert_chain(self, certfile, keyfile=None, password=None): + self._client_cert = certfile + self._client_key = keyfile + self._client_cert_passphrase = password + + def set_alpn_protocols(self, protocols): + """ + Sets the ALPN protocols that will later be set on the context. + + Raises a NotImplementedError if ALPN is not supported. + """ + if not hasattr(Security, "SSLSetALPNProtocols"): + raise NotImplementedError( + "SecureTransport supports ALPN only in macOS 10.12+" + ) + self._alpn_protocols = [six.ensure_binary(p) for p in protocols] + + def wrap_socket( + self, + sock, + server_side=False, + do_handshake_on_connect=True, + suppress_ragged_eofs=True, + server_hostname=None, + ): + # So, what do we do here? Firstly, we assert some properties. This is a + # stripped down shim, so there is some functionality we don't support. + # See PEP 543 for the real deal. + assert not server_side + assert do_handshake_on_connect + assert suppress_ragged_eofs + + # Ok, we're good to go. Now we want to create the wrapped socket object + # and store it in the appropriate place. + wrapped_socket = WrappedSocket(sock) + + # Now we can handshake + wrapped_socket.handshake( + server_hostname, + self._verify, + self._trust_bundle, + self._min_version, + self._max_version, + self._client_cert, + self._client_key, + self._client_key_passphrase, + self._alpn_protocols, + ) + return wrapped_socket diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/socks.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/socks.py new file mode 100644 index 0000000..c326e80 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/contrib/socks.py @@ -0,0 +1,216 @@ +# -*- coding: utf-8 -*- +""" +This module contains provisional support for SOCKS proxies from within +urllib3. This module supports SOCKS4, SOCKS4A (an extension of SOCKS4), and +SOCKS5. To enable its functionality, either install PySocks or install this +module with the ``socks`` extra. + +The SOCKS implementation supports the full range of urllib3 features. It also +supports the following SOCKS features: + +- SOCKS4A (``proxy_url='socks4a://...``) +- SOCKS4 (``proxy_url='socks4://...``) +- SOCKS5 with remote DNS (``proxy_url='socks5h://...``) +- SOCKS5 with local DNS (``proxy_url='socks5://...``) +- Usernames and passwords for the SOCKS proxy + +.. note:: + It is recommended to use ``socks5h://`` or ``socks4a://`` schemes in + your ``proxy_url`` to ensure that DNS resolution is done from the remote + server instead of client-side when connecting to a domain name. + +SOCKS4 supports IPv4 and domain names with the SOCKS4A extension. SOCKS5 +supports IPv4, IPv6, and domain names. + +When connecting to a SOCKS4 proxy the ``username`` portion of the ``proxy_url`` +will be sent as the ``userid`` section of the SOCKS request: + +.. code-block:: python + + proxy_url="socks4a://@proxy-host" + +When connecting to a SOCKS5 proxy the ``username`` and ``password`` portion +of the ``proxy_url`` will be sent as the username/password to authenticate +with the proxy: + +.. code-block:: python + + proxy_url="socks5h://:@proxy-host" + +""" +from __future__ import absolute_import + +try: + import socks +except ImportError: + import warnings + + from ..exceptions import DependencyWarning + + warnings.warn( + ( + "SOCKS support in urllib3 requires the installation of optional " + "dependencies: specifically, PySocks. For more information, see " + "https://urllib3.readthedocs.io/en/1.26.x/contrib.html#socks-proxies" + ), + DependencyWarning, + ) + raise + +from socket import error as SocketError +from socket import timeout as SocketTimeout + +from ..connection import HTTPConnection, HTTPSConnection +from ..connectionpool import HTTPConnectionPool, HTTPSConnectionPool +from ..exceptions import ConnectTimeoutError, NewConnectionError +from ..poolmanager import PoolManager +from ..util.url import parse_url + +try: + import ssl +except ImportError: + ssl = None + + +class SOCKSConnection(HTTPConnection): + """ + A plain-text HTTP connection that connects via a SOCKS proxy. + """ + + def __init__(self, *args, **kwargs): + self._socks_options = kwargs.pop("_socks_options") + super(SOCKSConnection, self).__init__(*args, **kwargs) + + def _new_conn(self): + """ + Establish a new connection via the SOCKS proxy. + """ + extra_kw = {} + if self.source_address: + extra_kw["source_address"] = self.source_address + + if self.socket_options: + extra_kw["socket_options"] = self.socket_options + + try: + conn = socks.create_connection( + (self.host, self.port), + proxy_type=self._socks_options["socks_version"], + proxy_addr=self._socks_options["proxy_host"], + proxy_port=self._socks_options["proxy_port"], + proxy_username=self._socks_options["username"], + proxy_password=self._socks_options["password"], + proxy_rdns=self._socks_options["rdns"], + timeout=self.timeout, + **extra_kw + ) + + except SocketTimeout: + raise ConnectTimeoutError( + self, + "Connection to %s timed out. (connect timeout=%s)" + % (self.host, self.timeout), + ) + + except socks.ProxyError as e: + # This is fragile as hell, but it seems to be the only way to raise + # useful errors here. + if e.socket_err: + error = e.socket_err + if isinstance(error, SocketTimeout): + raise ConnectTimeoutError( + self, + "Connection to %s timed out. (connect timeout=%s)" + % (self.host, self.timeout), + ) + else: + raise NewConnectionError( + self, "Failed to establish a new connection: %s" % error + ) + else: + raise NewConnectionError( + self, "Failed to establish a new connection: %s" % e + ) + + except SocketError as e: # Defensive: PySocks should catch all these. + raise NewConnectionError( + self, "Failed to establish a new connection: %s" % e + ) + + return conn + + +# We don't need to duplicate the Verified/Unverified distinction from +# urllib3/connection.py here because the HTTPSConnection will already have been +# correctly set to either the Verified or Unverified form by that module. This +# means the SOCKSHTTPSConnection will automatically be the correct type. +class SOCKSHTTPSConnection(SOCKSConnection, HTTPSConnection): + pass + + +class SOCKSHTTPConnectionPool(HTTPConnectionPool): + ConnectionCls = SOCKSConnection + + +class SOCKSHTTPSConnectionPool(HTTPSConnectionPool): + ConnectionCls = SOCKSHTTPSConnection + + +class SOCKSProxyManager(PoolManager): + """ + A version of the urllib3 ProxyManager that routes connections via the + defined SOCKS proxy. + """ + + pool_classes_by_scheme = { + "http": SOCKSHTTPConnectionPool, + "https": SOCKSHTTPSConnectionPool, + } + + def __init__( + self, + proxy_url, + username=None, + password=None, + num_pools=10, + headers=None, + **connection_pool_kw + ): + parsed = parse_url(proxy_url) + + if username is None and password is None and parsed.auth is not None: + split = parsed.auth.split(":") + if len(split) == 2: + username, password = split + if parsed.scheme == "socks5": + socks_version = socks.PROXY_TYPE_SOCKS5 + rdns = False + elif parsed.scheme == "socks5h": + socks_version = socks.PROXY_TYPE_SOCKS5 + rdns = True + elif parsed.scheme == "socks4": + socks_version = socks.PROXY_TYPE_SOCKS4 + rdns = False + elif parsed.scheme == "socks4a": + socks_version = socks.PROXY_TYPE_SOCKS4 + rdns = True + else: + raise ValueError("Unable to determine SOCKS version from %s" % proxy_url) + + self.proxy_url = proxy_url + + socks_options = { + "socks_version": socks_version, + "proxy_host": parsed.host, + "proxy_port": parsed.port, + "username": username, + "password": password, + "rdns": rdns, + } + connection_pool_kw["_socks_options"] = socks_options + + super(SOCKSProxyManager, self).__init__( + num_pools, headers, **connection_pool_kw + ) + + self.pool_classes_by_scheme = SOCKSProxyManager.pool_classes_by_scheme diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/exceptions.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/exceptions.py new file mode 100644 index 0000000..cba6f3f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/exceptions.py @@ -0,0 +1,323 @@ +from __future__ import absolute_import + +from .packages.six.moves.http_client import IncompleteRead as httplib_IncompleteRead + +# Base Exceptions + + +class HTTPError(Exception): + """Base exception used by this module.""" + + pass + + +class HTTPWarning(Warning): + """Base warning used by this module.""" + + pass + + +class PoolError(HTTPError): + """Base exception for errors caused within a pool.""" + + def __init__(self, pool, message): + self.pool = pool + HTTPError.__init__(self, "%s: %s" % (pool, message)) + + def __reduce__(self): + # For pickling purposes. + return self.__class__, (None, None) + + +class RequestError(PoolError): + """Base exception for PoolErrors that have associated URLs.""" + + def __init__(self, pool, url, message): + self.url = url + PoolError.__init__(self, pool, message) + + def __reduce__(self): + # For pickling purposes. + return self.__class__, (None, self.url, None) + + +class SSLError(HTTPError): + """Raised when SSL certificate fails in an HTTPS connection.""" + + pass + + +class ProxyError(HTTPError): + """Raised when the connection to a proxy fails.""" + + def __init__(self, message, error, *args): + super(ProxyError, self).__init__(message, error, *args) + self.original_error = error + + +class DecodeError(HTTPError): + """Raised when automatic decoding based on Content-Type fails.""" + + pass + + +class ProtocolError(HTTPError): + """Raised when something unexpected happens mid-request/response.""" + + pass + + +#: Renamed to ProtocolError but aliased for backwards compatibility. +ConnectionError = ProtocolError + + +# Leaf Exceptions + + +class MaxRetryError(RequestError): + """Raised when the maximum number of retries is exceeded. + + :param pool: The connection pool + :type pool: :class:`~urllib3.connectionpool.HTTPConnectionPool` + :param string url: The requested Url + :param exceptions.Exception reason: The underlying error + + """ + + def __init__(self, pool, url, reason=None): + self.reason = reason + + message = "Max retries exceeded with url: %s (Caused by %r)" % (url, reason) + + RequestError.__init__(self, pool, url, message) + + +class HostChangedError(RequestError): + """Raised when an existing pool gets a request for a foreign host.""" + + def __init__(self, pool, url, retries=3): + message = "Tried to open a foreign host with url: %s" % url + RequestError.__init__(self, pool, url, message) + self.retries = retries + + +class TimeoutStateError(HTTPError): + """Raised when passing an invalid state to a timeout""" + + pass + + +class TimeoutError(HTTPError): + """Raised when a socket timeout error occurs. + + Catching this error will catch both :exc:`ReadTimeoutErrors + ` and :exc:`ConnectTimeoutErrors `. + """ + + pass + + +class ReadTimeoutError(TimeoutError, RequestError): + """Raised when a socket timeout occurs while receiving data from a server""" + + pass + + +# This timeout error does not have a URL attached and needs to inherit from the +# base HTTPError +class ConnectTimeoutError(TimeoutError): + """Raised when a socket timeout occurs while connecting to a server""" + + pass + + +class NewConnectionError(ConnectTimeoutError, PoolError): + """Raised when we fail to establish a new connection. Usually ECONNREFUSED.""" + + pass + + +class EmptyPoolError(PoolError): + """Raised when a pool runs out of connections and no more are allowed.""" + + pass + + +class ClosedPoolError(PoolError): + """Raised when a request enters a pool after the pool has been closed.""" + + pass + + +class LocationValueError(ValueError, HTTPError): + """Raised when there is something wrong with a given URL input.""" + + pass + + +class LocationParseError(LocationValueError): + """Raised when get_host or similar fails to parse the URL input.""" + + def __init__(self, location): + message = "Failed to parse: %s" % location + HTTPError.__init__(self, message) + + self.location = location + + +class URLSchemeUnknown(LocationValueError): + """Raised when a URL input has an unsupported scheme.""" + + def __init__(self, scheme): + message = "Not supported URL scheme %s" % scheme + super(URLSchemeUnknown, self).__init__(message) + + self.scheme = scheme + + +class ResponseError(HTTPError): + """Used as a container for an error reason supplied in a MaxRetryError.""" + + GENERIC_ERROR = "too many error responses" + SPECIFIC_ERROR = "too many {status_code} error responses" + + +class SecurityWarning(HTTPWarning): + """Warned when performing security reducing actions""" + + pass + + +class SubjectAltNameWarning(SecurityWarning): + """Warned when connecting to a host with a certificate missing a SAN.""" + + pass + + +class InsecureRequestWarning(SecurityWarning): + """Warned when making an unverified HTTPS request.""" + + pass + + +class SystemTimeWarning(SecurityWarning): + """Warned when system time is suspected to be wrong""" + + pass + + +class InsecurePlatformWarning(SecurityWarning): + """Warned when certain TLS/SSL configuration is not available on a platform.""" + + pass + + +class SNIMissingWarning(HTTPWarning): + """Warned when making a HTTPS request without SNI available.""" + + pass + + +class DependencyWarning(HTTPWarning): + """ + Warned when an attempt is made to import a module with missing optional + dependencies. + """ + + pass + + +class ResponseNotChunked(ProtocolError, ValueError): + """Response needs to be chunked in order to read it as chunks.""" + + pass + + +class BodyNotHttplibCompatible(HTTPError): + """ + Body should be :class:`http.client.HTTPResponse` like + (have an fp attribute which returns raw chunks) for read_chunked(). + """ + + pass + + +class IncompleteRead(HTTPError, httplib_IncompleteRead): + """ + Response length doesn't match expected Content-Length + + Subclass of :class:`http.client.IncompleteRead` to allow int value + for ``partial`` to avoid creating large objects on streamed reads. + """ + + def __init__(self, partial, expected): + super(IncompleteRead, self).__init__(partial, expected) + + def __repr__(self): + return "IncompleteRead(%i bytes read, %i more expected)" % ( + self.partial, + self.expected, + ) + + +class InvalidChunkLength(HTTPError, httplib_IncompleteRead): + """Invalid chunk length in a chunked response.""" + + def __init__(self, response, length): + super(InvalidChunkLength, self).__init__( + response.tell(), response.length_remaining + ) + self.response = response + self.length = length + + def __repr__(self): + return "InvalidChunkLength(got length %r, %i bytes read)" % ( + self.length, + self.partial, + ) + + +class InvalidHeader(HTTPError): + """The header provided was somehow invalid.""" + + pass + + +class ProxySchemeUnknown(AssertionError, URLSchemeUnknown): + """ProxyManager does not support the supplied scheme""" + + # TODO(t-8ch): Stop inheriting from AssertionError in v2.0. + + def __init__(self, scheme): + # 'localhost' is here because our URL parser parses + # localhost:8080 -> scheme=localhost, remove if we fix this. + if scheme == "localhost": + scheme = None + if scheme is None: + message = "Proxy URL had no scheme, should start with http:// or https://" + else: + message = ( + "Proxy URL had unsupported scheme %s, should use http:// or https://" + % scheme + ) + super(ProxySchemeUnknown, self).__init__(message) + + +class ProxySchemeUnsupported(ValueError): + """Fetching HTTPS resources through HTTPS proxies is unsupported""" + + pass + + +class HeaderParsingError(HTTPError): + """Raised by assert_header_parsing, but we convert it to a log.warning statement.""" + + def __init__(self, defects, unparsed_data): + message = "%s, unparsed data: %r" % (defects or "Unknown", unparsed_data) + super(HeaderParsingError, self).__init__(message) + + +class UnrewindableBodyError(HTTPError): + """urllib3 encountered an error when trying to rewind a body""" + + pass diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/fields.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/fields.py new file mode 100644 index 0000000..9d630f4 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/fields.py @@ -0,0 +1,274 @@ +from __future__ import absolute_import + +import email.utils +import mimetypes +import re + +from .packages import six + + +def guess_content_type(filename, default="application/octet-stream"): + """ + Guess the "Content-Type" of a file. + + :param filename: + The filename to guess the "Content-Type" of using :mod:`mimetypes`. + :param default: + If no "Content-Type" can be guessed, default to `default`. + """ + if filename: + return mimetypes.guess_type(filename)[0] or default + return default + + +def format_header_param_rfc2231(name, value): + """ + Helper function to format and quote a single header parameter using the + strategy defined in RFC 2231. + + Particularly useful for header parameters which might contain + non-ASCII values, like file names. This follows + `RFC 2388 Section 4.4 `_. + + :param name: + The name of the parameter, a string expected to be ASCII only. + :param value: + The value of the parameter, provided as ``bytes`` or `str``. + :ret: + An RFC-2231-formatted unicode string. + """ + if isinstance(value, six.binary_type): + value = value.decode("utf-8") + + if not any(ch in value for ch in '"\\\r\n'): + result = u'%s="%s"' % (name, value) + try: + result.encode("ascii") + except (UnicodeEncodeError, UnicodeDecodeError): + pass + else: + return result + + if six.PY2: # Python 2: + value = value.encode("utf-8") + + # encode_rfc2231 accepts an encoded string and returns an ascii-encoded + # string in Python 2 but accepts and returns unicode strings in Python 3 + value = email.utils.encode_rfc2231(value, "utf-8") + value = "%s*=%s" % (name, value) + + if six.PY2: # Python 2: + value = value.decode("utf-8") + + return value + + +_HTML5_REPLACEMENTS = { + u"\u0022": u"%22", + # Replace "\" with "\\". + u"\u005C": u"\u005C\u005C", +} + +# All control characters from 0x00 to 0x1F *except* 0x1B. +_HTML5_REPLACEMENTS.update( + { + six.unichr(cc): u"%{:02X}".format(cc) + for cc in range(0x00, 0x1F + 1) + if cc not in (0x1B,) + } +) + + +def _replace_multiple(value, needles_and_replacements): + def replacer(match): + return needles_and_replacements[match.group(0)] + + pattern = re.compile( + r"|".join([re.escape(needle) for needle in needles_and_replacements.keys()]) + ) + + result = pattern.sub(replacer, value) + + return result + + +def format_header_param_html5(name, value): + """ + Helper function to format and quote a single header parameter using the + HTML5 strategy. + + Particularly useful for header parameters which might contain + non-ASCII values, like file names. This follows the `HTML5 Working Draft + Section 4.10.22.7`_ and matches the behavior of curl and modern browsers. + + .. _HTML5 Working Draft Section 4.10.22.7: + https://w3c.github.io/html/sec-forms.html#multipart-form-data + + :param name: + The name of the parameter, a string expected to be ASCII only. + :param value: + The value of the parameter, provided as ``bytes`` or `str``. + :ret: + A unicode string, stripped of troublesome characters. + """ + if isinstance(value, six.binary_type): + value = value.decode("utf-8") + + value = _replace_multiple(value, _HTML5_REPLACEMENTS) + + return u'%s="%s"' % (name, value) + + +# For backwards-compatibility. +format_header_param = format_header_param_html5 + + +class RequestField(object): + """ + A data container for request body parameters. + + :param name: + The name of this request field. Must be unicode. + :param data: + The data/value body. + :param filename: + An optional filename of the request field. Must be unicode. + :param headers: + An optional dict-like object of headers to initially use for the field. + :param header_formatter: + An optional callable that is used to encode and format the headers. By + default, this is :func:`format_header_param_html5`. + """ + + def __init__( + self, + name, + data, + filename=None, + headers=None, + header_formatter=format_header_param_html5, + ): + self._name = name + self._filename = filename + self.data = data + self.headers = {} + if headers: + self.headers = dict(headers) + self.header_formatter = header_formatter + + @classmethod + def from_tuples(cls, fieldname, value, header_formatter=format_header_param_html5): + """ + A :class:`~urllib3.fields.RequestField` factory from old-style tuple parameters. + + Supports constructing :class:`~urllib3.fields.RequestField` from + parameter of key/value strings AND key/filetuple. A filetuple is a + (filename, data, MIME type) tuple where the MIME type is optional. + For example:: + + 'foo': 'bar', + 'fakefile': ('foofile.txt', 'contents of foofile'), + 'realfile': ('barfile.txt', open('realfile').read()), + 'typedfile': ('bazfile.bin', open('bazfile').read(), 'image/jpeg'), + 'nonamefile': 'contents of nonamefile field', + + Field names and filenames must be unicode. + """ + if isinstance(value, tuple): + if len(value) == 3: + filename, data, content_type = value + else: + filename, data = value + content_type = guess_content_type(filename) + else: + filename = None + content_type = None + data = value + + request_param = cls( + fieldname, data, filename=filename, header_formatter=header_formatter + ) + request_param.make_multipart(content_type=content_type) + + return request_param + + def _render_part(self, name, value): + """ + Overridable helper function to format a single header parameter. By + default, this calls ``self.header_formatter``. + + :param name: + The name of the parameter, a string expected to be ASCII only. + :param value: + The value of the parameter, provided as a unicode string. + """ + + return self.header_formatter(name, value) + + def _render_parts(self, header_parts): + """ + Helper function to format and quote a single header. + + Useful for single headers that are composed of multiple items. E.g., + 'Content-Disposition' fields. + + :param header_parts: + A sequence of (k, v) tuples or a :class:`dict` of (k, v) to format + as `k1="v1"; k2="v2"; ...`. + """ + parts = [] + iterable = header_parts + if isinstance(header_parts, dict): + iterable = header_parts.items() + + for name, value in iterable: + if value is not None: + parts.append(self._render_part(name, value)) + + return u"; ".join(parts) + + def render_headers(self): + """ + Renders the headers for this request field. + """ + lines = [] + + sort_keys = ["Content-Disposition", "Content-Type", "Content-Location"] + for sort_key in sort_keys: + if self.headers.get(sort_key, False): + lines.append(u"%s: %s" % (sort_key, self.headers[sort_key])) + + for header_name, header_value in self.headers.items(): + if header_name not in sort_keys: + if header_value: + lines.append(u"%s: %s" % (header_name, header_value)) + + lines.append(u"\r\n") + return u"\r\n".join(lines) + + def make_multipart( + self, content_disposition=None, content_type=None, content_location=None + ): + """ + Makes this request field into a multipart request field. + + This method overrides "Content-Disposition", "Content-Type" and + "Content-Location" headers to the request parameter. + + :param content_type: + The 'Content-Type' of the request body. + :param content_location: + The 'Content-Location' of the request body. + + """ + self.headers["Content-Disposition"] = content_disposition or u"form-data" + self.headers["Content-Disposition"] += u"; ".join( + [ + u"", + self._render_parts( + ((u"name", self._name), (u"filename", self._filename)) + ), + ] + ) + self.headers["Content-Type"] = content_type + self.headers["Content-Location"] = content_location diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/filepost.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/filepost.py new file mode 100644 index 0000000..36c9252 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/filepost.py @@ -0,0 +1,98 @@ +from __future__ import absolute_import + +import binascii +import codecs +import os +from io import BytesIO + +from .fields import RequestField +from .packages import six +from .packages.six import b + +writer = codecs.lookup("utf-8")[3] + + +def choose_boundary(): + """ + Our embarrassingly-simple replacement for mimetools.choose_boundary. + """ + boundary = binascii.hexlify(os.urandom(16)) + if not six.PY2: + boundary = boundary.decode("ascii") + return boundary + + +def iter_field_objects(fields): + """ + Iterate over fields. + + Supports list of (k, v) tuples and dicts, and lists of + :class:`~urllib3.fields.RequestField`. + + """ + if isinstance(fields, dict): + i = six.iteritems(fields) + else: + i = iter(fields) + + for field in i: + if isinstance(field, RequestField): + yield field + else: + yield RequestField.from_tuples(*field) + + +def iter_fields(fields): + """ + .. deprecated:: 1.6 + + Iterate over fields. + + The addition of :class:`~urllib3.fields.RequestField` makes this function + obsolete. Instead, use :func:`iter_field_objects`, which returns + :class:`~urllib3.fields.RequestField` objects. + + Supports list of (k, v) tuples and dicts. + """ + if isinstance(fields, dict): + return ((k, v) for k, v in six.iteritems(fields)) + + return ((k, v) for k, v in fields) + + +def encode_multipart_formdata(fields, boundary=None): + """ + Encode a dictionary of ``fields`` using the multipart/form-data MIME format. + + :param fields: + Dictionary of fields or list of (key, :class:`~urllib3.fields.RequestField`). + + :param boundary: + If not specified, then a random boundary will be generated using + :func:`urllib3.filepost.choose_boundary`. + """ + body = BytesIO() + if boundary is None: + boundary = choose_boundary() + + for field in iter_field_objects(fields): + body.write(b("--%s\r\n" % (boundary))) + + writer(body).write(field.render_headers()) + data = field.data + + if isinstance(data, int): + data = str(data) # Backwards compatibility + + if isinstance(data, six.text_type): + writer(body).write(data) + else: + body.write(data) + + body.write(b"\r\n") + + body.write(b("--%s--\r\n" % (boundary))) + + content_type = str("multipart/form-data; boundary=%s" % boundary) + + return body.getvalue(), content_type diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/packages/__init__.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/packages/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..91e4cdfb18a5e7556f67205dacb7fff043da4b86 GIT binary patch literal 203 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 JNuvqw{{rt?R2KjM literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1c74db71a3fee2c9393148c9796aed3ddc685a3d GIT binary patch literal 213 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" % (type(self).__name__, id(self)) + else: + return "<%s object at %#x; for %r at %#x>" % ( + type(self).__name__, + id(self), + type(obj).__name__, + id(obj), + ) + + @classmethod + def _select_for_exit(cls): + # Return live finalizers marked for exit, oldest first + L = [(f, i) for (f, i) in cls._registry.items() if i.atexit] + L.sort(key=lambda item: item[1].index) + return [f for (f, i) in L] + + @classmethod + def _exitfunc(cls): + # At shutdown invoke finalizers for which atexit is true. + # This is called once all other non-daemonic threads have been + # joined. + reenable_gc = False + try: + if cls._registry: + import gc + + if gc.isenabled(): + reenable_gc = True + gc.disable() + pending = None + while True: + if pending is None or weakref_finalize._dirty: + pending = cls._select_for_exit() + weakref_finalize._dirty = False + if not pending: + break + f = pending.pop() + try: + # gc is disabled, so (assuming no daemonic + # threads) the following is the only line in + # this function which might trigger creation + # of a new finalizer + f() + except Exception: + sys.excepthook(*sys.exc_info()) + assert f not in cls._registry + finally: + # prevent any more finalizers from executing during shutdown + weakref_finalize._shutdown = True + if reenable_gc: + gc.enable() diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/packages/six.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/packages/six.py new file mode 100644 index 0000000..f099a3d --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/packages/six.py @@ -0,0 +1,1076 @@ +# Copyright (c) 2010-2020 Benjamin Peterson +# +# 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. + +"""Utilities for writing code that runs on Python 2 and 3""" + +from __future__ import absolute_import + +import functools +import itertools +import operator +import sys +import types + +__author__ = "Benjamin Peterson " +__version__ = "1.16.0" + + +# Useful for very coarse version differentiation. +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 +PY34 = sys.version_info[0:2] >= (3, 4) + +if PY3: + string_types = (str,) + integer_types = (int,) + class_types = (type,) + text_type = str + binary_type = bytes + + MAXSIZE = sys.maxsize +else: + string_types = (basestring,) + integer_types = (int, long) + class_types = (type, types.ClassType) + text_type = unicode + binary_type = str + + if sys.platform.startswith("java"): + # Jython always uses 32 bits. + MAXSIZE = int((1 << 31) - 1) + else: + # It's possible to have sizeof(long) != sizeof(Py_ssize_t). + class X(object): + def __len__(self): + return 1 << 31 + + try: + len(X()) + except OverflowError: + # 32-bit + MAXSIZE = int((1 << 31) - 1) + else: + # 64-bit + MAXSIZE = int((1 << 63) - 1) + del X + +if PY34: + from importlib.util import spec_from_loader +else: + spec_from_loader = None + + +def _add_doc(func, doc): + """Add documentation to a function.""" + func.__doc__ = doc + + +def _import_module(name): + """Import module, returning the module after the last dot.""" + __import__(name) + return sys.modules[name] + + +class _LazyDescr(object): + def __init__(self, name): + self.name = name + + def __get__(self, obj, tp): + result = self._resolve() + setattr(obj, self.name, result) # Invokes __set__. + try: + # This is a bit ugly, but it avoids running this again by + # removing this descriptor. + delattr(obj.__class__, self.name) + except AttributeError: + pass + return result + + +class MovedModule(_LazyDescr): + def __init__(self, name, old, new=None): + super(MovedModule, self).__init__(name) + if PY3: + if new is None: + new = name + self.mod = new + else: + self.mod = old + + def _resolve(self): + return _import_module(self.mod) + + def __getattr__(self, attr): + _module = self._resolve() + value = getattr(_module, attr) + setattr(self, attr, value) + return value + + +class _LazyModule(types.ModuleType): + def __init__(self, name): + super(_LazyModule, self).__init__(name) + self.__doc__ = self.__class__.__doc__ + + def __dir__(self): + attrs = ["__doc__", "__name__"] + attrs += [attr.name for attr in self._moved_attributes] + return attrs + + # Subclasses should override this + _moved_attributes = [] + + +class MovedAttribute(_LazyDescr): + def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): + super(MovedAttribute, self).__init__(name) + if PY3: + if new_mod is None: + new_mod = name + self.mod = new_mod + if new_attr is None: + if old_attr is None: + new_attr = name + else: + new_attr = old_attr + self.attr = new_attr + else: + self.mod = old_mod + if old_attr is None: + old_attr = name + self.attr = old_attr + + def _resolve(self): + module = _import_module(self.mod) + return getattr(module, self.attr) + + +class _SixMetaPathImporter(object): + + """ + A meta path importer to import six.moves and its submodules. + + This class implements a PEP302 finder and loader. It should be compatible + with Python 2.5 and all existing versions of Python3 + """ + + def __init__(self, six_module_name): + self.name = six_module_name + self.known_modules = {} + + def _add_module(self, mod, *fullnames): + for fullname in fullnames: + self.known_modules[self.name + "." + fullname] = mod + + def _get_module(self, fullname): + return self.known_modules[self.name + "." + fullname] + + def find_module(self, fullname, path=None): + if fullname in self.known_modules: + return self + return None + + def find_spec(self, fullname, path, target=None): + if fullname in self.known_modules: + return spec_from_loader(fullname, self) + return None + + def __get_module(self, fullname): + try: + return self.known_modules[fullname] + except KeyError: + raise ImportError("This loader does not know module " + fullname) + + def load_module(self, fullname): + try: + # in case of a reload + return sys.modules[fullname] + except KeyError: + pass + mod = self.__get_module(fullname) + if isinstance(mod, MovedModule): + mod = mod._resolve() + else: + mod.__loader__ = self + sys.modules[fullname] = mod + return mod + + def is_package(self, fullname): + """ + Return true, if the named module is a package. + + We need this method to get correct spec objects with + Python 3.4 (see PEP451) + """ + return hasattr(self.__get_module(fullname), "__path__") + + def get_code(self, fullname): + """Return None + + Required, if is_package is implemented""" + self.__get_module(fullname) # eventually raises ImportError + return None + + get_source = get_code # same as get_code + + def create_module(self, spec): + return self.load_module(spec.name) + + def exec_module(self, module): + pass + + +_importer = _SixMetaPathImporter(__name__) + + +class _MovedItems(_LazyModule): + + """Lazy loading of moved objects""" + + __path__ = [] # mark as package + + +_moved_attributes = [ + MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), + MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), + MovedAttribute( + "filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse" + ), + MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), + MovedAttribute("intern", "__builtin__", "sys"), + MovedAttribute("map", "itertools", "builtins", "imap", "map"), + MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), + MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), + MovedAttribute("getoutput", "commands", "subprocess"), + MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute( + "reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload" + ), + MovedAttribute("reduce", "__builtin__", "functools"), + MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), + MovedAttribute("StringIO", "StringIO", "io"), + MovedAttribute("UserDict", "UserDict", "collections"), + MovedAttribute("UserList", "UserList", "collections"), + MovedAttribute("UserString", "UserString", "collections"), + MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), + MovedAttribute( + "zip_longest", "itertools", "itertools", "izip_longest", "zip_longest" + ), + MovedModule("builtins", "__builtin__"), + MovedModule("configparser", "ConfigParser"), + MovedModule( + "collections_abc", + "collections", + "collections.abc" if sys.version_info >= (3, 3) else "collections", + ), + MovedModule("copyreg", "copy_reg"), + MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), + MovedModule("dbm_ndbm", "dbm", "dbm.ndbm"), + MovedModule( + "_dummy_thread", + "dummy_thread", + "_dummy_thread" if sys.version_info < (3, 9) else "_thread", + ), + MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), + MovedModule("http_cookies", "Cookie", "http.cookies"), + MovedModule("html_entities", "htmlentitydefs", "html.entities"), + MovedModule("html_parser", "HTMLParser", "html.parser"), + MovedModule("http_client", "httplib", "http.client"), + MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), + MovedModule("email_mime_image", "email.MIMEImage", "email.mime.image"), + MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), + MovedModule( + "email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart" + ), + MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), + MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), + MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), + MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), + MovedModule("cPickle", "cPickle", "pickle"), + MovedModule("queue", "Queue"), + MovedModule("reprlib", "repr"), + MovedModule("socketserver", "SocketServer"), + MovedModule("_thread", "thread", "_thread"), + MovedModule("tkinter", "Tkinter"), + MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), + MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), + MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), + MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), + MovedModule("tkinter_tix", "Tix", "tkinter.tix"), + MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), + MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), + MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), + MovedModule("tkinter_colorchooser", "tkColorChooser", "tkinter.colorchooser"), + MovedModule("tkinter_commondialog", "tkCommonDialog", "tkinter.commondialog"), + MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), + MovedModule("tkinter_font", "tkFont", "tkinter.font"), + MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), + MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", "tkinter.simpledialog"), + MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), + MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), + MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), + MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), + MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), + MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), +] +# Add windows specific modules. +if sys.platform == "win32": + _moved_attributes += [ + MovedModule("winreg", "_winreg"), + ] + +for attr in _moved_attributes: + setattr(_MovedItems, attr.name, attr) + if isinstance(attr, MovedModule): + _importer._add_module(attr, "moves." + attr.name) +del attr + +_MovedItems._moved_attributes = _moved_attributes + +moves = _MovedItems(__name__ + ".moves") +_importer._add_module(moves, "moves") + + +class Module_six_moves_urllib_parse(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_parse""" + + +_urllib_parse_moved_attributes = [ + MovedAttribute("ParseResult", "urlparse", "urllib.parse"), + MovedAttribute("SplitResult", "urlparse", "urllib.parse"), + MovedAttribute("parse_qs", "urlparse", "urllib.parse"), + MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), + MovedAttribute("urldefrag", "urlparse", "urllib.parse"), + MovedAttribute("urljoin", "urlparse", "urllib.parse"), + MovedAttribute("urlparse", "urlparse", "urllib.parse"), + MovedAttribute("urlsplit", "urlparse", "urllib.parse"), + MovedAttribute("urlunparse", "urlparse", "urllib.parse"), + MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), + MovedAttribute("quote", "urllib", "urllib.parse"), + MovedAttribute("quote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote", "urllib", "urllib.parse"), + MovedAttribute("unquote_plus", "urllib", "urllib.parse"), + MovedAttribute( + "unquote_to_bytes", "urllib", "urllib.parse", "unquote", "unquote_to_bytes" + ), + MovedAttribute("urlencode", "urllib", "urllib.parse"), + MovedAttribute("splitquery", "urllib", "urllib.parse"), + MovedAttribute("splittag", "urllib", "urllib.parse"), + MovedAttribute("splituser", "urllib", "urllib.parse"), + MovedAttribute("splitvalue", "urllib", "urllib.parse"), + MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), + MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), + MovedAttribute("uses_params", "urlparse", "urllib.parse"), + MovedAttribute("uses_query", "urlparse", "urllib.parse"), + MovedAttribute("uses_relative", "urlparse", "urllib.parse"), +] +for attr in _urllib_parse_moved_attributes: + setattr(Module_six_moves_urllib_parse, attr.name, attr) +del attr + +Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes + +_importer._add_module( + Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), + "moves.urllib_parse", + "moves.urllib.parse", +) + + +class Module_six_moves_urllib_error(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_error""" + + +_urllib_error_moved_attributes = [ + MovedAttribute("URLError", "urllib2", "urllib.error"), + MovedAttribute("HTTPError", "urllib2", "urllib.error"), + MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), +] +for attr in _urllib_error_moved_attributes: + setattr(Module_six_moves_urllib_error, attr.name, attr) +del attr + +Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes + +_importer._add_module( + Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), + "moves.urllib_error", + "moves.urllib.error", +) + + +class Module_six_moves_urllib_request(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_request""" + + +_urllib_request_moved_attributes = [ + MovedAttribute("urlopen", "urllib2", "urllib.request"), + MovedAttribute("install_opener", "urllib2", "urllib.request"), + MovedAttribute("build_opener", "urllib2", "urllib.request"), + MovedAttribute("pathname2url", "urllib", "urllib.request"), + MovedAttribute("url2pathname", "urllib", "urllib.request"), + MovedAttribute("getproxies", "urllib", "urllib.request"), + MovedAttribute("Request", "urllib2", "urllib.request"), + MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), + MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), + MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), + MovedAttribute("BaseHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), + MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), + MovedAttribute("FileHandler", "urllib2", "urllib.request"), + MovedAttribute("FTPHandler", "urllib2", "urllib.request"), + MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), + MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), + MovedAttribute("urlretrieve", "urllib", "urllib.request"), + MovedAttribute("urlcleanup", "urllib", "urllib.request"), + MovedAttribute("URLopener", "urllib", "urllib.request"), + MovedAttribute("FancyURLopener", "urllib", "urllib.request"), + MovedAttribute("proxy_bypass", "urllib", "urllib.request"), + MovedAttribute("parse_http_list", "urllib2", "urllib.request"), + MovedAttribute("parse_keqv_list", "urllib2", "urllib.request"), +] +for attr in _urllib_request_moved_attributes: + setattr(Module_six_moves_urllib_request, attr.name, attr) +del attr + +Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes + +_importer._add_module( + Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), + "moves.urllib_request", + "moves.urllib.request", +) + + +class Module_six_moves_urllib_response(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_response""" + + +_urllib_response_moved_attributes = [ + MovedAttribute("addbase", "urllib", "urllib.response"), + MovedAttribute("addclosehook", "urllib", "urllib.response"), + MovedAttribute("addinfo", "urllib", "urllib.response"), + MovedAttribute("addinfourl", "urllib", "urllib.response"), +] +for attr in _urllib_response_moved_attributes: + setattr(Module_six_moves_urllib_response, attr.name, attr) +del attr + +Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes + +_importer._add_module( + Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), + "moves.urllib_response", + "moves.urllib.response", +) + + +class Module_six_moves_urllib_robotparser(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_robotparser""" + + +_urllib_robotparser_moved_attributes = [ + MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), +] +for attr in _urllib_robotparser_moved_attributes: + setattr(Module_six_moves_urllib_robotparser, attr.name, attr) +del attr + +Module_six_moves_urllib_robotparser._moved_attributes = ( + _urllib_robotparser_moved_attributes +) + +_importer._add_module( + Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), + "moves.urllib_robotparser", + "moves.urllib.robotparser", +) + + +class Module_six_moves_urllib(types.ModuleType): + + """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" + + __path__ = [] # mark as package + parse = _importer._get_module("moves.urllib_parse") + error = _importer._get_module("moves.urllib_error") + request = _importer._get_module("moves.urllib_request") + response = _importer._get_module("moves.urllib_response") + robotparser = _importer._get_module("moves.urllib_robotparser") + + def __dir__(self): + return ["parse", "error", "request", "response", "robotparser"] + + +_importer._add_module( + Module_six_moves_urllib(__name__ + ".moves.urllib"), "moves.urllib" +) + + +def add_move(move): + """Add an item to six.moves.""" + setattr(_MovedItems, move.name, move) + + +def remove_move(name): + """Remove item from six.moves.""" + try: + delattr(_MovedItems, name) + except AttributeError: + try: + del moves.__dict__[name] + except KeyError: + raise AttributeError("no such move, %r" % (name,)) + + +if PY3: + _meth_func = "__func__" + _meth_self = "__self__" + + _func_closure = "__closure__" + _func_code = "__code__" + _func_defaults = "__defaults__" + _func_globals = "__globals__" +else: + _meth_func = "im_func" + _meth_self = "im_self" + + _func_closure = "func_closure" + _func_code = "func_code" + _func_defaults = "func_defaults" + _func_globals = "func_globals" + + +try: + advance_iterator = next +except NameError: + + def advance_iterator(it): + return it.next() + + +next = advance_iterator + + +try: + callable = callable +except NameError: + + def callable(obj): + return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) + + +if PY3: + + def get_unbound_function(unbound): + return unbound + + create_bound_method = types.MethodType + + def create_unbound_method(func, cls): + return func + + Iterator = object +else: + + def get_unbound_function(unbound): + return unbound.im_func + + def create_bound_method(func, obj): + return types.MethodType(func, obj, obj.__class__) + + def create_unbound_method(func, cls): + return types.MethodType(func, None, cls) + + class Iterator(object): + def next(self): + return type(self).__next__(self) + + callable = callable +_add_doc( + get_unbound_function, """Get the function out of a possibly unbound function""" +) + + +get_method_function = operator.attrgetter(_meth_func) +get_method_self = operator.attrgetter(_meth_self) +get_function_closure = operator.attrgetter(_func_closure) +get_function_code = operator.attrgetter(_func_code) +get_function_defaults = operator.attrgetter(_func_defaults) +get_function_globals = operator.attrgetter(_func_globals) + + +if PY3: + + def iterkeys(d, **kw): + return iter(d.keys(**kw)) + + def itervalues(d, **kw): + return iter(d.values(**kw)) + + def iteritems(d, **kw): + return iter(d.items(**kw)) + + def iterlists(d, **kw): + return iter(d.lists(**kw)) + + viewkeys = operator.methodcaller("keys") + + viewvalues = operator.methodcaller("values") + + viewitems = operator.methodcaller("items") +else: + + def iterkeys(d, **kw): + return d.iterkeys(**kw) + + def itervalues(d, **kw): + return d.itervalues(**kw) + + def iteritems(d, **kw): + return d.iteritems(**kw) + + def iterlists(d, **kw): + return d.iterlists(**kw) + + viewkeys = operator.methodcaller("viewkeys") + + viewvalues = operator.methodcaller("viewvalues") + + viewitems = operator.methodcaller("viewitems") + +_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") +_add_doc(itervalues, "Return an iterator over the values of a dictionary.") +_add_doc(iteritems, "Return an iterator over the (key, value) pairs of a dictionary.") +_add_doc( + iterlists, "Return an iterator over the (key, [values]) pairs of a dictionary." +) + + +if PY3: + + def b(s): + return s.encode("latin-1") + + def u(s): + return s + + unichr = chr + import struct + + int2byte = struct.Struct(">B").pack + del struct + byte2int = operator.itemgetter(0) + indexbytes = operator.getitem + iterbytes = iter + import io + + StringIO = io.StringIO + BytesIO = io.BytesIO + del io + _assertCountEqual = "assertCountEqual" + if sys.version_info[1] <= 1: + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" + _assertNotRegex = "assertNotRegexpMatches" + else: + _assertRaisesRegex = "assertRaisesRegex" + _assertRegex = "assertRegex" + _assertNotRegex = "assertNotRegex" +else: + + def b(s): + return s + + # Workaround for standalone backslash + + def u(s): + return unicode(s.replace(r"\\", r"\\\\"), "unicode_escape") + + unichr = unichr + int2byte = chr + + def byte2int(bs): + return ord(bs[0]) + + def indexbytes(buf, i): + return ord(buf[i]) + + iterbytes = functools.partial(itertools.imap, ord) + import StringIO + + StringIO = BytesIO = StringIO.StringIO + _assertCountEqual = "assertItemsEqual" + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" + _assertNotRegex = "assertNotRegexpMatches" +_add_doc(b, """Byte literal""") +_add_doc(u, """Text literal""") + + +def assertCountEqual(self, *args, **kwargs): + return getattr(self, _assertCountEqual)(*args, **kwargs) + + +def assertRaisesRegex(self, *args, **kwargs): + return getattr(self, _assertRaisesRegex)(*args, **kwargs) + + +def assertRegex(self, *args, **kwargs): + return getattr(self, _assertRegex)(*args, **kwargs) + + +def assertNotRegex(self, *args, **kwargs): + return getattr(self, _assertNotRegex)(*args, **kwargs) + + +if PY3: + exec_ = getattr(moves.builtins, "exec") + + def reraise(tp, value, tb=None): + try: + if value is None: + value = tp() + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + finally: + value = None + tb = None + +else: + + def exec_(_code_, _globs_=None, _locs_=None): + """Execute code in a namespace.""" + if _globs_ is None: + frame = sys._getframe(1) + _globs_ = frame.f_globals + if _locs_ is None: + _locs_ = frame.f_locals + del frame + elif _locs_ is None: + _locs_ = _globs_ + exec ("""exec _code_ in _globs_, _locs_""") + + exec_( + """def reraise(tp, value, tb=None): + try: + raise tp, value, tb + finally: + tb = None +""" + ) + + +if sys.version_info[:2] > (3,): + exec_( + """def raise_from(value, from_value): + try: + raise value from from_value + finally: + value = None +""" + ) +else: + + def raise_from(value, from_value): + raise value + + +print_ = getattr(moves.builtins, "print", None) +if print_ is None: + + def print_(*args, **kwargs): + """The new-style print function for Python 2.4 and 2.5.""" + fp = kwargs.pop("file", sys.stdout) + if fp is None: + return + + def write(data): + if not isinstance(data, basestring): + data = str(data) + # If the file has an encoding, encode unicode with it. + if ( + isinstance(fp, file) + and isinstance(data, unicode) + and fp.encoding is not None + ): + errors = getattr(fp, "errors", None) + if errors is None: + errors = "strict" + data = data.encode(fp.encoding, errors) + fp.write(data) + + want_unicode = False + sep = kwargs.pop("sep", None) + if sep is not None: + if isinstance(sep, unicode): + want_unicode = True + elif not isinstance(sep, str): + raise TypeError("sep must be None or a string") + end = kwargs.pop("end", None) + if end is not None: + if isinstance(end, unicode): + want_unicode = True + elif not isinstance(end, str): + raise TypeError("end must be None or a string") + if kwargs: + raise TypeError("invalid keyword arguments to print()") + if not want_unicode: + for arg in args: + if isinstance(arg, unicode): + want_unicode = True + break + if want_unicode: + newline = unicode("\n") + space = unicode(" ") + else: + newline = "\n" + space = " " + if sep is None: + sep = space + if end is None: + end = newline + for i, arg in enumerate(args): + if i: + write(sep) + write(arg) + write(end) + + +if sys.version_info[:2] < (3, 3): + _print = print_ + + def print_(*args, **kwargs): + fp = kwargs.get("file", sys.stdout) + flush = kwargs.pop("flush", False) + _print(*args, **kwargs) + if flush and fp is not None: + fp.flush() + + +_add_doc(reraise, """Reraise an exception.""") + +if sys.version_info[0:2] < (3, 4): + # This does exactly the same what the :func:`py3:functools.update_wrapper` + # function does on Python versions after 3.2. It sets the ``__wrapped__`` + # attribute on ``wrapper`` object and it doesn't raise an error if any of + # the attributes mentioned in ``assigned`` and ``updated`` are missing on + # ``wrapped`` object. + def _update_wrapper( + wrapper, + wrapped, + assigned=functools.WRAPPER_ASSIGNMENTS, + updated=functools.WRAPPER_UPDATES, + ): + for attr in assigned: + try: + value = getattr(wrapped, attr) + except AttributeError: + continue + else: + setattr(wrapper, attr, value) + for attr in updated: + getattr(wrapper, attr).update(getattr(wrapped, attr, {})) + wrapper.__wrapped__ = wrapped + return wrapper + + _update_wrapper.__doc__ = functools.update_wrapper.__doc__ + + def wraps( + wrapped, + assigned=functools.WRAPPER_ASSIGNMENTS, + updated=functools.WRAPPER_UPDATES, + ): + return functools.partial( + _update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated + ) + + wraps.__doc__ = functools.wraps.__doc__ + +else: + wraps = functools.wraps + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(type): + def __new__(cls, name, this_bases, d): + if sys.version_info[:2] >= (3, 7): + # This version introduced PEP 560 that requires a bit + # of extra care (we mimic what is done by __build_class__). + resolved_bases = types.resolve_bases(bases) + if resolved_bases is not bases: + d["__orig_bases__"] = bases + else: + resolved_bases = bases + return meta(name, resolved_bases, d) + + @classmethod + def __prepare__(cls, name, this_bases): + return meta.__prepare__(name, bases) + + return type.__new__(metaclass, "temporary_class", (), {}) + + +def add_metaclass(metaclass): + """Class decorator for creating a class with a metaclass.""" + + def wrapper(cls): + orig_vars = cls.__dict__.copy() + slots = orig_vars.get("__slots__") + if slots is not None: + if isinstance(slots, str): + slots = [slots] + for slots_var in slots: + orig_vars.pop(slots_var) + orig_vars.pop("__dict__", None) + orig_vars.pop("__weakref__", None) + if hasattr(cls, "__qualname__"): + orig_vars["__qualname__"] = cls.__qualname__ + return metaclass(cls.__name__, cls.__bases__, orig_vars) + + return wrapper + + +def ensure_binary(s, encoding="utf-8", errors="strict"): + """Coerce **s** to six.binary_type. + + For Python 2: + - `unicode` -> encoded to `str` + - `str` -> `str` + + For Python 3: + - `str` -> encoded to `bytes` + - `bytes` -> `bytes` + """ + if isinstance(s, binary_type): + return s + if isinstance(s, text_type): + return s.encode(encoding, errors) + raise TypeError("not expecting type '%s'" % type(s)) + + +def ensure_str(s, encoding="utf-8", errors="strict"): + """Coerce *s* to `str`. + + For Python 2: + - `unicode` -> encoded to `str` + - `str` -> `str` + + For Python 3: + - `str` -> `str` + - `bytes` -> decoded to `str` + """ + # Optimization: Fast return for the common case. + if type(s) is str: + return s + if PY2 and isinstance(s, text_type): + return s.encode(encoding, errors) + elif PY3 and isinstance(s, binary_type): + return s.decode(encoding, errors) + elif not isinstance(s, (text_type, binary_type)): + raise TypeError("not expecting type '%s'" % type(s)) + return s + + +def ensure_text(s, encoding="utf-8", errors="strict"): + """Coerce *s* to six.text_type. + + For Python 2: + - `unicode` -> `unicode` + - `str` -> `unicode` + + For Python 3: + - `str` -> `str` + - `bytes` -> decoded to `str` + """ + if isinstance(s, binary_type): + return s.decode(encoding, errors) + elif isinstance(s, text_type): + return s + else: + raise TypeError("not expecting type '%s'" % type(s)) + + +def python_2_unicode_compatible(klass): + """ + A class decorator that defines __unicode__ and __str__ methods under Python 2. + Under Python 3 it does nothing. + + To support Python 2 and 3 with a single code base, define a __str__ method + returning text and apply this decorator to the class. + """ + if PY2: + if "__str__" not in klass.__dict__: + raise ValueError( + "@python_2_unicode_compatible cannot be applied " + "to %s because it doesn't define __str__()." % klass.__name__ + ) + klass.__unicode__ = klass.__str__ + klass.__str__ = lambda self: self.__unicode__().encode("utf-8") + return klass + + +# Complete the moves implementation. +# This code is at the end of this module to speed up module loading. +# Turn this module into a package. +__path__ = [] # required for PEP 302 and PEP 451 +__package__ = __name__ # see PEP 366 @ReservedAssignment +if globals().get("__spec__") is not None: + __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable +# Remove other six meta path importers, since they cause problems. This can +# happen if six is removed from sys.modules and then reloaded. (Setuptools does +# this for some reason.) +if sys.meta_path: + for i, importer in enumerate(sys.meta_path): + # Here's some real nastiness: Another "instance" of the six module might + # be floating around. Therefore, we can't use isinstance() to check for + # the six meta path importer, since the other six instance will have + # inserted an importer with different class. + if ( + type(importer).__name__ == "_SixMetaPathImporter" + and importer.name == __name__ + ): + del sys.meta_path[i] + break + del i, importer +# Finally, add the importer to the meta path import hook. +sys.meta_path.append(_importer) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/poolmanager.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/poolmanager.py new file mode 100644 index 0000000..fb51bf7 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/poolmanager.py @@ -0,0 +1,540 @@ +from __future__ import absolute_import + +import collections +import functools +import logging + +from ._collections import HTTPHeaderDict, RecentlyUsedContainer +from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool, port_by_scheme +from .exceptions import ( + LocationValueError, + MaxRetryError, + ProxySchemeUnknown, + ProxySchemeUnsupported, + URLSchemeUnknown, +) +from .packages import six +from .packages.six.moves.urllib.parse import urljoin +from .request import RequestMethods +from .util.proxy import connection_requires_http_tunnel +from .util.retry import Retry +from .util.url import parse_url + +__all__ = ["PoolManager", "ProxyManager", "proxy_from_url"] + + +log = logging.getLogger(__name__) + +SSL_KEYWORDS = ( + "key_file", + "cert_file", + "cert_reqs", + "ca_certs", + "ssl_version", + "ca_cert_dir", + "ssl_context", + "key_password", + "server_hostname", +) + +# All known keyword arguments that could be provided to the pool manager, its +# pools, or the underlying connections. This is used to construct a pool key. +_key_fields = ( + "key_scheme", # str + "key_host", # str + "key_port", # int + "key_timeout", # int or float or Timeout + "key_retries", # int or Retry + "key_strict", # bool + "key_block", # bool + "key_source_address", # str + "key_key_file", # str + "key_key_password", # str + "key_cert_file", # str + "key_cert_reqs", # str + "key_ca_certs", # str + "key_ssl_version", # str + "key_ca_cert_dir", # str + "key_ssl_context", # instance of ssl.SSLContext or urllib3.util.ssl_.SSLContext + "key_maxsize", # int + "key_headers", # dict + "key__proxy", # parsed proxy url + "key__proxy_headers", # dict + "key__proxy_config", # class + "key_socket_options", # list of (level (int), optname (int), value (int or str)) tuples + "key__socks_options", # dict + "key_assert_hostname", # bool or string + "key_assert_fingerprint", # str + "key_server_hostname", # str +) + +#: The namedtuple class used to construct keys for the connection pool. +#: All custom key schemes should include the fields in this key at a minimum. +PoolKey = collections.namedtuple("PoolKey", _key_fields) + +_proxy_config_fields = ("ssl_context", "use_forwarding_for_https") +ProxyConfig = collections.namedtuple("ProxyConfig", _proxy_config_fields) + + +def _default_key_normalizer(key_class, request_context): + """ + Create a pool key out of a request context dictionary. + + According to RFC 3986, both the scheme and host are case-insensitive. + Therefore, this function normalizes both before constructing the pool + key for an HTTPS request. If you wish to change this behaviour, provide + alternate callables to ``key_fn_by_scheme``. + + :param key_class: + The class to use when constructing the key. This should be a namedtuple + with the ``scheme`` and ``host`` keys at a minimum. + :type key_class: namedtuple + :param request_context: + A dictionary-like object that contain the context for a request. + :type request_context: dict + + :return: A namedtuple that can be used as a connection pool key. + :rtype: PoolKey + """ + # Since we mutate the dictionary, make a copy first + context = request_context.copy() + context["scheme"] = context["scheme"].lower() + context["host"] = context["host"].lower() + + # These are both dictionaries and need to be transformed into frozensets + for key in ("headers", "_proxy_headers", "_socks_options"): + if key in context and context[key] is not None: + context[key] = frozenset(context[key].items()) + + # The socket_options key may be a list and needs to be transformed into a + # tuple. + socket_opts = context.get("socket_options") + if socket_opts is not None: + context["socket_options"] = tuple(socket_opts) + + # Map the kwargs to the names in the namedtuple - this is necessary since + # namedtuples can't have fields starting with '_'. + for key in list(context.keys()): + context["key_" + key] = context.pop(key) + + # Default to ``None`` for keys missing from the context + for field in key_class._fields: + if field not in context: + context[field] = None + + return key_class(**context) + + +#: A dictionary that maps a scheme to a callable that creates a pool key. +#: This can be used to alter the way pool keys are constructed, if desired. +#: Each PoolManager makes a copy of this dictionary so they can be configured +#: globally here, or individually on the instance. +key_fn_by_scheme = { + "http": functools.partial(_default_key_normalizer, PoolKey), + "https": functools.partial(_default_key_normalizer, PoolKey), +} + +pool_classes_by_scheme = {"http": HTTPConnectionPool, "https": HTTPSConnectionPool} + + +class PoolManager(RequestMethods): + """ + Allows for arbitrary requests while transparently keeping track of + necessary connection pools for you. + + :param num_pools: + Number of connection pools to cache before discarding the least + recently used pool. + + :param headers: + Headers to include with all requests, unless other headers are given + explicitly. + + :param \\**connection_pool_kw: + Additional parameters are used to create fresh + :class:`urllib3.connectionpool.ConnectionPool` instances. + + Example:: + + >>> manager = PoolManager(num_pools=2) + >>> r = manager.request('GET', 'http://google.com/') + >>> r = manager.request('GET', 'http://google.com/mail') + >>> r = manager.request('GET', 'http://yahoo.com/') + >>> len(manager.pools) + 2 + + """ + + proxy = None + proxy_config = None + + def __init__(self, num_pools=10, headers=None, **connection_pool_kw): + RequestMethods.__init__(self, headers) + self.connection_pool_kw = connection_pool_kw + self.pools = RecentlyUsedContainer(num_pools) + + # Locally set the pool classes and keys so other PoolManagers can + # override them. + self.pool_classes_by_scheme = pool_classes_by_scheme + self.key_fn_by_scheme = key_fn_by_scheme.copy() + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.clear() + # Return False to re-raise any potential exceptions + return False + + def _new_pool(self, scheme, host, port, request_context=None): + """ + Create a new :class:`urllib3.connectionpool.ConnectionPool` based on host, port, scheme, and + any additional pool keyword arguments. + + If ``request_context`` is provided, it is provided as keyword arguments + to the pool class used. This method is used to actually create the + connection pools handed out by :meth:`connection_from_url` and + companion methods. It is intended to be overridden for customization. + """ + pool_cls = self.pool_classes_by_scheme[scheme] + if request_context is None: + request_context = self.connection_pool_kw.copy() + + # Although the context has everything necessary to create the pool, + # this function has historically only used the scheme, host, and port + # in the positional args. When an API change is acceptable these can + # be removed. + for key in ("scheme", "host", "port"): + request_context.pop(key, None) + + if scheme == "http": + for kw in SSL_KEYWORDS: + request_context.pop(kw, None) + + return pool_cls(host, port, **request_context) + + def clear(self): + """ + Empty our store of pools and direct them all to close. + + This will not affect in-flight connections, but they will not be + re-used after completion. + """ + self.pools.clear() + + def connection_from_host(self, host, port=None, scheme="http", pool_kwargs=None): + """ + Get a :class:`urllib3.connectionpool.ConnectionPool` based on the host, port, and scheme. + + If ``port`` isn't given, it will be derived from the ``scheme`` using + ``urllib3.connectionpool.port_by_scheme``. If ``pool_kwargs`` is + provided, it is merged with the instance's ``connection_pool_kw`` + variable and used to create the new connection pool, if one is + needed. + """ + + if not host: + raise LocationValueError("No host specified.") + + request_context = self._merge_pool_kwargs(pool_kwargs) + request_context["scheme"] = scheme or "http" + if not port: + port = port_by_scheme.get(request_context["scheme"].lower(), 80) + request_context["port"] = port + request_context["host"] = host + + return self.connection_from_context(request_context) + + def connection_from_context(self, request_context): + """ + Get a :class:`urllib3.connectionpool.ConnectionPool` based on the request context. + + ``request_context`` must at least contain the ``scheme`` key and its + value must be a key in ``key_fn_by_scheme`` instance variable. + """ + scheme = request_context["scheme"].lower() + pool_key_constructor = self.key_fn_by_scheme.get(scheme) + if not pool_key_constructor: + raise URLSchemeUnknown(scheme) + pool_key = pool_key_constructor(request_context) + + return self.connection_from_pool_key(pool_key, request_context=request_context) + + def connection_from_pool_key(self, pool_key, request_context=None): + """ + Get a :class:`urllib3.connectionpool.ConnectionPool` based on the provided pool key. + + ``pool_key`` should be a namedtuple that only contains immutable + objects. At a minimum it must have the ``scheme``, ``host``, and + ``port`` fields. + """ + with self.pools.lock: + # If the scheme, host, or port doesn't match existing open + # connections, open a new ConnectionPool. + pool = self.pools.get(pool_key) + if pool: + return pool + + # Make a fresh ConnectionPool of the desired type + scheme = request_context["scheme"] + host = request_context["host"] + port = request_context["port"] + pool = self._new_pool(scheme, host, port, request_context=request_context) + self.pools[pool_key] = pool + + return pool + + def connection_from_url(self, url, pool_kwargs=None): + """ + Similar to :func:`urllib3.connectionpool.connection_from_url`. + + If ``pool_kwargs`` is not provided and a new pool needs to be + constructed, ``self.connection_pool_kw`` is used to initialize + the :class:`urllib3.connectionpool.ConnectionPool`. If ``pool_kwargs`` + is provided, it is used instead. Note that if a new pool does not + need to be created for the request, the provided ``pool_kwargs`` are + not used. + """ + u = parse_url(url) + return self.connection_from_host( + u.host, port=u.port, scheme=u.scheme, pool_kwargs=pool_kwargs + ) + + def _merge_pool_kwargs(self, override): + """ + Merge a dictionary of override values for self.connection_pool_kw. + + This does not modify self.connection_pool_kw and returns a new dict. + Any keys in the override dictionary with a value of ``None`` are + removed from the merged dictionary. + """ + base_pool_kwargs = self.connection_pool_kw.copy() + if override: + for key, value in override.items(): + if value is None: + try: + del base_pool_kwargs[key] + except KeyError: + pass + else: + base_pool_kwargs[key] = value + return base_pool_kwargs + + def _proxy_requires_url_absolute_form(self, parsed_url): + """ + Indicates if the proxy requires the complete destination URL in the + request. Normally this is only needed when not using an HTTP CONNECT + tunnel. + """ + if self.proxy is None: + return False + + return not connection_requires_http_tunnel( + self.proxy, self.proxy_config, parsed_url.scheme + ) + + def _validate_proxy_scheme_url_selection(self, url_scheme): + """ + Validates that were not attempting to do TLS in TLS connections on + Python2 or with unsupported SSL implementations. + """ + if self.proxy is None or url_scheme != "https": + return + + if self.proxy.scheme != "https": + return + + if six.PY2 and not self.proxy_config.use_forwarding_for_https: + raise ProxySchemeUnsupported( + "Contacting HTTPS destinations through HTTPS proxies " + "'via CONNECT tunnels' is not supported in Python 2" + ) + + def urlopen(self, method, url, redirect=True, **kw): + """ + Same as :meth:`urllib3.HTTPConnectionPool.urlopen` + with custom cross-host redirect logic and only sends the request-uri + portion of the ``url``. + + The given ``url`` parameter must be absolute, such that an appropriate + :class:`urllib3.connectionpool.ConnectionPool` can be chosen for it. + """ + u = parse_url(url) + self._validate_proxy_scheme_url_selection(u.scheme) + + conn = self.connection_from_host(u.host, port=u.port, scheme=u.scheme) + + kw["assert_same_host"] = False + kw["redirect"] = False + + if "headers" not in kw: + kw["headers"] = self.headers.copy() + + if self._proxy_requires_url_absolute_form(u): + response = conn.urlopen(method, url, **kw) + else: + response = conn.urlopen(method, u.request_uri, **kw) + + redirect_location = redirect and response.get_redirect_location() + if not redirect_location: + return response + + # Support relative URLs for redirecting. + redirect_location = urljoin(url, redirect_location) + + if response.status == 303: + # Change the method according to RFC 9110, Section 15.4.4. + method = "GET" + # And lose the body not to transfer anything sensitive. + kw["body"] = None + kw["headers"] = HTTPHeaderDict(kw["headers"])._prepare_for_method_change() + + retries = kw.get("retries") + if not isinstance(retries, Retry): + retries = Retry.from_int(retries, redirect=redirect) + + # Strip headers marked as unsafe to forward to the redirected location. + # Check remove_headers_on_redirect to avoid a potential network call within + # conn.is_same_host() which may use socket.gethostbyname() in the future. + if retries.remove_headers_on_redirect and not conn.is_same_host( + redirect_location + ): + headers = list(six.iterkeys(kw["headers"])) + for header in headers: + if header.lower() in retries.remove_headers_on_redirect: + kw["headers"].pop(header, None) + + try: + retries = retries.increment(method, url, response=response, _pool=conn) + except MaxRetryError: + if retries.raise_on_redirect: + response.drain_conn() + raise + return response + + kw["retries"] = retries + kw["redirect"] = redirect + + log.info("Redirecting %s -> %s", url, redirect_location) + + response.drain_conn() + return self.urlopen(method, redirect_location, **kw) + + +class ProxyManager(PoolManager): + """ + Behaves just like :class:`PoolManager`, but sends all requests through + the defined proxy, using the CONNECT method for HTTPS URLs. + + :param proxy_url: + The URL of the proxy to be used. + + :param proxy_headers: + A dictionary containing headers that will be sent to the proxy. In case + of HTTP they are being sent with each request, while in the + HTTPS/CONNECT case they are sent only once. Could be used for proxy + authentication. + + :param proxy_ssl_context: + The proxy SSL context is used to establish the TLS connection to the + proxy when using HTTPS proxies. + + :param use_forwarding_for_https: + (Defaults to False) If set to True will forward requests to the HTTPS + proxy to be made on behalf of the client instead of creating a TLS + tunnel via the CONNECT method. **Enabling this flag means that request + and response headers and content will be visible from the HTTPS proxy** + whereas tunneling keeps request and response headers and content + private. IP address, target hostname, SNI, and port are always visible + to an HTTPS proxy even when this flag is disabled. + + Example: + >>> proxy = urllib3.ProxyManager('http://localhost:3128/') + >>> r1 = proxy.request('GET', 'http://google.com/') + >>> r2 = proxy.request('GET', 'http://httpbin.org/') + >>> len(proxy.pools) + 1 + >>> r3 = proxy.request('GET', 'https://httpbin.org/') + >>> r4 = proxy.request('GET', 'https://twitter.com/') + >>> len(proxy.pools) + 3 + + """ + + def __init__( + self, + proxy_url, + num_pools=10, + headers=None, + proxy_headers=None, + proxy_ssl_context=None, + use_forwarding_for_https=False, + **connection_pool_kw + ): + + if isinstance(proxy_url, HTTPConnectionPool): + proxy_url = "%s://%s:%i" % ( + proxy_url.scheme, + proxy_url.host, + proxy_url.port, + ) + proxy = parse_url(proxy_url) + + if proxy.scheme not in ("http", "https"): + raise ProxySchemeUnknown(proxy.scheme) + + if not proxy.port: + port = port_by_scheme.get(proxy.scheme, 80) + proxy = proxy._replace(port=port) + + self.proxy = proxy + self.proxy_headers = proxy_headers or {} + self.proxy_ssl_context = proxy_ssl_context + self.proxy_config = ProxyConfig(proxy_ssl_context, use_forwarding_for_https) + + connection_pool_kw["_proxy"] = self.proxy + connection_pool_kw["_proxy_headers"] = self.proxy_headers + connection_pool_kw["_proxy_config"] = self.proxy_config + + super(ProxyManager, self).__init__(num_pools, headers, **connection_pool_kw) + + def connection_from_host(self, host, port=None, scheme="http", pool_kwargs=None): + if scheme == "https": + return super(ProxyManager, self).connection_from_host( + host, port, scheme, pool_kwargs=pool_kwargs + ) + + return super(ProxyManager, self).connection_from_host( + self.proxy.host, self.proxy.port, self.proxy.scheme, pool_kwargs=pool_kwargs + ) + + def _set_proxy_headers(self, url, headers=None): + """ + Sets headers needed by proxies: specifically, the Accept and Host + headers. Only sets headers not provided by the user. + """ + headers_ = {"Accept": "*/*"} + + netloc = parse_url(url).netloc + if netloc: + headers_["Host"] = netloc + + if headers: + headers_.update(headers) + return headers_ + + def urlopen(self, method, url, redirect=True, **kw): + "Same as HTTP(S)ConnectionPool.urlopen, ``url`` must be absolute." + u = parse_url(url) + if not connection_requires_http_tunnel(self.proxy, self.proxy_config, u.scheme): + # For connections using HTTP CONNECT, httplib sets the necessary + # headers on the CONNECT to the proxy. If we're not using CONNECT, + # we'll definitely need to set 'Host' at the very least. + headers = kw.get("headers", self.headers) + kw["headers"] = self._set_proxy_headers(url, headers) + + return super(ProxyManager, self).urlopen(method, url, redirect=redirect, **kw) + + +def proxy_from_url(url, **kw): + return ProxyManager(proxy_url=url, **kw) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/request.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/request.py new file mode 100644 index 0000000..3b4cf99 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/request.py @@ -0,0 +1,191 @@ +from __future__ import absolute_import + +import sys + +from .filepost import encode_multipart_formdata +from .packages import six +from .packages.six.moves.urllib.parse import urlencode + +__all__ = ["RequestMethods"] + + +class RequestMethods(object): + """ + Convenience mixin for classes who implement a :meth:`urlopen` method, such + as :class:`urllib3.HTTPConnectionPool` and + :class:`urllib3.PoolManager`. + + Provides behavior for making common types of HTTP request methods and + decides which type of request field encoding to use. + + Specifically, + + :meth:`.request_encode_url` is for sending requests whose fields are + encoded in the URL (such as GET, HEAD, DELETE). + + :meth:`.request_encode_body` is for sending requests whose fields are + encoded in the *body* of the request using multipart or www-form-urlencoded + (such as for POST, PUT, PATCH). + + :meth:`.request` is for making any kind of request, it will look up the + appropriate encoding format and use one of the above two methods to make + the request. + + Initializer parameters: + + :param headers: + Headers to include with all requests, unless other headers are given + explicitly. + """ + + _encode_url_methods = {"DELETE", "GET", "HEAD", "OPTIONS"} + + def __init__(self, headers=None): + self.headers = headers or {} + + def urlopen( + self, + method, + url, + body=None, + headers=None, + encode_multipart=True, + multipart_boundary=None, + **kw + ): # Abstract + raise NotImplementedError( + "Classes extending RequestMethods must implement " + "their own ``urlopen`` method." + ) + + def request(self, method, url, fields=None, headers=None, **urlopen_kw): + """ + Make a request using :meth:`urlopen` with the appropriate encoding of + ``fields`` based on the ``method`` used. + + This is a convenience method that requires the least amount of manual + effort. It can be used in most situations, while still having the + option to drop down to more specific methods when necessary, such as + :meth:`request_encode_url`, :meth:`request_encode_body`, + or even the lowest level :meth:`urlopen`. + """ + method = method.upper() + + urlopen_kw["request_url"] = url + + if method in self._encode_url_methods: + return self.request_encode_url( + method, url, fields=fields, headers=headers, **urlopen_kw + ) + else: + return self.request_encode_body( + method, url, fields=fields, headers=headers, **urlopen_kw + ) + + def request_encode_url(self, method, url, fields=None, headers=None, **urlopen_kw): + """ + Make a request using :meth:`urlopen` with the ``fields`` encoded in + the url. This is useful for request methods like GET, HEAD, DELETE, etc. + """ + if headers is None: + headers = self.headers + + extra_kw = {"headers": headers} + extra_kw.update(urlopen_kw) + + if fields: + url += "?" + urlencode(fields) + + return self.urlopen(method, url, **extra_kw) + + def request_encode_body( + self, + method, + url, + fields=None, + headers=None, + encode_multipart=True, + multipart_boundary=None, + **urlopen_kw + ): + """ + Make a request using :meth:`urlopen` with the ``fields`` encoded in + the body. This is useful for request methods like POST, PUT, PATCH, etc. + + When ``encode_multipart=True`` (default), then + :func:`urllib3.encode_multipart_formdata` is used to encode + the payload with the appropriate content type. Otherwise + :func:`urllib.parse.urlencode` is used with the + 'application/x-www-form-urlencoded' content type. + + Multipart encoding must be used when posting files, and it's reasonably + safe to use it in other times too. However, it may break request + signing, such as with OAuth. + + Supports an optional ``fields`` parameter of key/value strings AND + key/filetuple. A filetuple is a (filename, data, MIME type) tuple where + the MIME type is optional. For example:: + + fields = { + 'foo': 'bar', + 'fakefile': ('foofile.txt', 'contents of foofile'), + 'realfile': ('barfile.txt', open('realfile').read()), + 'typedfile': ('bazfile.bin', open('bazfile').read(), + 'image/jpeg'), + 'nonamefile': 'contents of nonamefile field', + } + + When uploading a file, providing a filename (the first parameter of the + tuple) is optional but recommended to best mimic behavior of browsers. + + Note that if ``headers`` are supplied, the 'Content-Type' header will + be overwritten because it depends on the dynamic random boundary string + which is used to compose the body of the request. The random boundary + string can be explicitly set with the ``multipart_boundary`` parameter. + """ + if headers is None: + headers = self.headers + + extra_kw = {"headers": {}} + + if fields: + if "body" in urlopen_kw: + raise TypeError( + "request got values for both 'fields' and 'body', can only specify one." + ) + + if encode_multipart: + body, content_type = encode_multipart_formdata( + fields, boundary=multipart_boundary + ) + else: + body, content_type = ( + urlencode(fields), + "application/x-www-form-urlencoded", + ) + + extra_kw["body"] = body + extra_kw["headers"] = {"Content-Type": content_type} + + extra_kw["headers"].update(headers) + extra_kw.update(urlopen_kw) + + return self.urlopen(method, url, **extra_kw) + + +if not six.PY2: + + class RequestModule(sys.modules[__name__].__class__): + def __call__(self, *args, **kwargs): + """ + If user tries to call this module directly urllib3 v2.x style raise an error to the user + suggesting they may need urllib3 v2 + """ + raise TypeError( + "'module' object is not callable\n" + "urllib3.request() method is not supported in this release, " + "upgrade to urllib3 v2 to use it\n" + "see https://urllib3.readthedocs.io/en/stable/v2-migration-guide.html" + ) + + sys.modules[__name__].__class__ = RequestModule diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/response.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/response.py new file mode 100644 index 0000000..8909f84 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/response.py @@ -0,0 +1,879 @@ +from __future__ import absolute_import + +import io +import logging +import sys +import warnings +import zlib +from contextlib import contextmanager +from socket import error as SocketError +from socket import timeout as SocketTimeout + +brotli = None + +from . import util +from ._collections import HTTPHeaderDict +from .connection import BaseSSLError, HTTPException +from .exceptions import ( + BodyNotHttplibCompatible, + DecodeError, + HTTPError, + IncompleteRead, + InvalidChunkLength, + InvalidHeader, + ProtocolError, + ReadTimeoutError, + ResponseNotChunked, + SSLError, +) +from .packages import six +from .util.response import is_fp_closed, is_response_to_head + +log = logging.getLogger(__name__) + + +class DeflateDecoder(object): + def __init__(self): + self._first_try = True + self._data = b"" + self._obj = zlib.decompressobj() + + def __getattr__(self, name): + return getattr(self._obj, name) + + def decompress(self, data): + if not data: + return data + + if not self._first_try: + return self._obj.decompress(data) + + self._data += data + try: + decompressed = self._obj.decompress(data) + if decompressed: + self._first_try = False + self._data = None + return decompressed + except zlib.error: + self._first_try = False + self._obj = zlib.decompressobj(-zlib.MAX_WBITS) + try: + return self.decompress(self._data) + finally: + self._data = None + + +class GzipDecoderState(object): + + FIRST_MEMBER = 0 + OTHER_MEMBERS = 1 + SWALLOW_DATA = 2 + + +class GzipDecoder(object): + def __init__(self): + self._obj = zlib.decompressobj(16 + zlib.MAX_WBITS) + self._state = GzipDecoderState.FIRST_MEMBER + + def __getattr__(self, name): + return getattr(self._obj, name) + + def decompress(self, data): + ret = bytearray() + if self._state == GzipDecoderState.SWALLOW_DATA or not data: + return bytes(ret) + while True: + try: + ret += self._obj.decompress(data) + except zlib.error: + previous_state = self._state + # Ignore data after the first error + self._state = GzipDecoderState.SWALLOW_DATA + if previous_state == GzipDecoderState.OTHER_MEMBERS: + # Allow trailing garbage acceptable in other gzip clients + return bytes(ret) + raise + data = self._obj.unused_data + if not data: + return bytes(ret) + self._state = GzipDecoderState.OTHER_MEMBERS + self._obj = zlib.decompressobj(16 + zlib.MAX_WBITS) + + +if brotli is not None: + + class BrotliDecoder(object): + # Supports both 'brotlipy' and 'Brotli' packages + # since they share an import name. The top branches + # are for 'brotlipy' and bottom branches for 'Brotli' + def __init__(self): + self._obj = brotli.Decompressor() + if hasattr(self._obj, "decompress"): + self.decompress = self._obj.decompress + else: + self.decompress = self._obj.process + + def flush(self): + if hasattr(self._obj, "flush"): + return self._obj.flush() + return b"" + + +class MultiDecoder(object): + """ + From RFC7231: + If one or more encodings have been applied to a representation, the + sender that applied the encodings MUST generate a Content-Encoding + header field that lists the content codings in the order in which + they were applied. + """ + + def __init__(self, modes): + self._decoders = [_get_decoder(m.strip()) for m in modes.split(",")] + + def flush(self): + return self._decoders[0].flush() + + def decompress(self, data): + for d in reversed(self._decoders): + data = d.decompress(data) + return data + + +def _get_decoder(mode): + if "," in mode: + return MultiDecoder(mode) + + if mode == "gzip": + return GzipDecoder() + + if brotli is not None and mode == "br": + return BrotliDecoder() + + return DeflateDecoder() + + +class HTTPResponse(io.IOBase): + """ + HTTP Response container. + + Backwards-compatible with :class:`http.client.HTTPResponse` but the response ``body`` is + loaded and decoded on-demand when the ``data`` property is accessed. This + class is also compatible with the Python standard library's :mod:`io` + module, and can hence be treated as a readable object in the context of that + framework. + + Extra parameters for behaviour not present in :class:`http.client.HTTPResponse`: + + :param preload_content: + If True, the response's body will be preloaded during construction. + + :param decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + + :param original_response: + When this HTTPResponse wrapper is generated from an :class:`http.client.HTTPResponse` + object, it's convenient to include the original for debug purposes. It's + otherwise unused. + + :param retries: + The retries contains the last :class:`~urllib3.util.retry.Retry` that + was used during the request. + + :param enforce_content_length: + Enforce content length checking. Body returned by server must match + value of Content-Length header, if present. Otherwise, raise error. + """ + + CONTENT_DECODERS = ["gzip", "deflate"] + if brotli is not None: + CONTENT_DECODERS += ["br"] + REDIRECT_STATUSES = [301, 302, 303, 307, 308] + + def __init__( + self, + body="", + headers=None, + status=0, + version=0, + reason=None, + strict=0, + preload_content=True, + decode_content=True, + original_response=None, + pool=None, + connection=None, + msg=None, + retries=None, + enforce_content_length=False, + request_method=None, + request_url=None, + auto_close=True, + ): + + if isinstance(headers, HTTPHeaderDict): + self.headers = headers + else: + self.headers = HTTPHeaderDict(headers) + self.status = status + self.version = version + self.reason = reason + self.strict = strict + self.decode_content = decode_content + self.retries = retries + self.enforce_content_length = enforce_content_length + self.auto_close = auto_close + + self._decoder = None + self._body = None + self._fp = None + self._original_response = original_response + self._fp_bytes_read = 0 + self.msg = msg + self._request_url = request_url + + if body and isinstance(body, (six.string_types, bytes)): + self._body = body + + self._pool = pool + self._connection = connection + + if hasattr(body, "read"): + self._fp = body + + # Are we using the chunked-style of transfer encoding? + self.chunked = False + self.chunk_left = None + tr_enc = self.headers.get("transfer-encoding", "").lower() + # Don't incur the penalty of creating a list and then discarding it + encodings = (enc.strip() for enc in tr_enc.split(",")) + if "chunked" in encodings: + self.chunked = True + + # Determine length of response + self.length_remaining = self._init_length(request_method) + + # If requested, preload the body. + if preload_content and not self._body: + self._body = self.read(decode_content=decode_content) + + def get_redirect_location(self): + """ + Should we redirect and where to? + + :returns: Truthy redirect location string if we got a redirect status + code and valid location. ``None`` if redirect status and no + location. ``False`` if not a redirect status code. + """ + if self.status in self.REDIRECT_STATUSES: + return self.headers.get("location") + + return False + + def release_conn(self): + if not self._pool or not self._connection: + return + + self._pool._put_conn(self._connection) + self._connection = None + + def drain_conn(self): + """ + Read and discard any remaining HTTP response data in the response connection. + + Unread data in the HTTPResponse connection blocks the connection from being released back to the pool. + """ + try: + self.read() + except (HTTPError, SocketError, BaseSSLError, HTTPException): + pass + + @property + def data(self): + # For backwards-compat with earlier urllib3 0.4 and earlier. + if self._body: + return self._body + + if self._fp: + return self.read(cache_content=True) + + @property + def connection(self): + return self._connection + + def isclosed(self): + return is_fp_closed(self._fp) + + def tell(self): + """ + Obtain the number of bytes pulled over the wire so far. May differ from + the amount of content returned by :meth:``urllib3.response.HTTPResponse.read`` + if bytes are encoded on the wire (e.g, compressed). + """ + return self._fp_bytes_read + + def _init_length(self, request_method): + """ + Set initial length value for Response content if available. + """ + length = self.headers.get("content-length") + + if length is not None: + if self.chunked: + # This Response will fail with an IncompleteRead if it can't be + # received as chunked. This method falls back to attempt reading + # the response before raising an exception. + log.warning( + "Received response with both Content-Length and " + "Transfer-Encoding set. This is expressly forbidden " + "by RFC 7230 sec 3.3.2. Ignoring Content-Length and " + "attempting to process response as Transfer-Encoding: " + "chunked." + ) + return None + + try: + # RFC 7230 section 3.3.2 specifies multiple content lengths can + # be sent in a single Content-Length header + # (e.g. Content-Length: 42, 42). This line ensures the values + # are all valid ints and that as long as the `set` length is 1, + # all values are the same. Otherwise, the header is invalid. + lengths = set([int(val) for val in length.split(",")]) + if len(lengths) > 1: + raise InvalidHeader( + "Content-Length contained multiple " + "unmatching values (%s)" % length + ) + length = lengths.pop() + except ValueError: + length = None + else: + if length < 0: + length = None + + # Convert status to int for comparison + # In some cases, httplib returns a status of "_UNKNOWN" + try: + status = int(self.status) + except ValueError: + status = 0 + + # Check for responses that shouldn't include a body + if status in (204, 304) or 100 <= status < 200 or request_method == "HEAD": + length = 0 + + return length + + def _init_decoder(self): + """ + Set-up the _decoder attribute if necessary. + """ + # Note: content-encoding value should be case-insensitive, per RFC 7230 + # Section 3.2 + content_encoding = self.headers.get("content-encoding", "").lower() + if self._decoder is None: + if content_encoding in self.CONTENT_DECODERS: + self._decoder = _get_decoder(content_encoding) + elif "," in content_encoding: + encodings = [ + e.strip() + for e in content_encoding.split(",") + if e.strip() in self.CONTENT_DECODERS + ] + if len(encodings): + self._decoder = _get_decoder(content_encoding) + + DECODER_ERROR_CLASSES = (IOError, zlib.error) + if brotli is not None: + DECODER_ERROR_CLASSES += (brotli.error,) + + def _decode(self, data, decode_content, flush_decoder): + """ + Decode the data passed in and potentially flush the decoder. + """ + if not decode_content: + return data + + try: + if self._decoder: + data = self._decoder.decompress(data) + except self.DECODER_ERROR_CLASSES as e: + content_encoding = self.headers.get("content-encoding", "").lower() + raise DecodeError( + "Received response with content-encoding: %s, but " + "failed to decode it." % content_encoding, + e, + ) + if flush_decoder: + data += self._flush_decoder() + + return data + + def _flush_decoder(self): + """ + Flushes the decoder. Should only be called if the decoder is actually + being used. + """ + if self._decoder: + buf = self._decoder.decompress(b"") + return buf + self._decoder.flush() + + return b"" + + @contextmanager + def _error_catcher(self): + """ + Catch low-level python exceptions, instead re-raising urllib3 + variants, so that low-level exceptions are not leaked in the + high-level api. + + On exit, release the connection back to the pool. + """ + clean_exit = False + + try: + try: + yield + + except SocketTimeout: + # FIXME: Ideally we'd like to include the url in the ReadTimeoutError but + # there is yet no clean way to get at it from this context. + raise ReadTimeoutError(self._pool, None, "Read timed out.") + + except BaseSSLError as e: + # FIXME: Is there a better way to differentiate between SSLErrors? + if "read operation timed out" not in str(e): + # SSL errors related to framing/MAC get wrapped and reraised here + raise SSLError(e) + + raise ReadTimeoutError(self._pool, None, "Read timed out.") + + except (HTTPException, SocketError) as e: + # This includes IncompleteRead. + raise ProtocolError("Connection broken: %r" % e, e) + + # If no exception is thrown, we should avoid cleaning up + # unnecessarily. + clean_exit = True + finally: + # If we didn't terminate cleanly, we need to throw away our + # connection. + if not clean_exit: + # The response may not be closed but we're not going to use it + # anymore so close it now to ensure that the connection is + # released back to the pool. + if self._original_response: + self._original_response.close() + + # Closing the response may not actually be sufficient to close + # everything, so if we have a hold of the connection close that + # too. + if self._connection: + self._connection.close() + + # If we hold the original response but it's closed now, we should + # return the connection back to the pool. + if self._original_response and self._original_response.isclosed(): + self.release_conn() + + def _fp_read(self, amt): + """ + Read a response with the thought that reading the number of bytes + larger than can fit in a 32-bit int at a time via SSL in some + known cases leads to an overflow error that has to be prevented + if `amt` or `self.length_remaining` indicate that a problem may + happen. + + The known cases: + * 3.8 <= CPython < 3.9.7 because of a bug + https://github.com/urllib3/urllib3/issues/2513#issuecomment-1152559900. + * urllib3 injected with pyOpenSSL-backed SSL-support. + * CPython < 3.10 only when `amt` does not fit 32-bit int. + """ + assert self._fp + c_int_max = 2 ** 31 - 1 + if ( + ( + (amt and amt > c_int_max) + or (self.length_remaining and self.length_remaining > c_int_max) + ) + and not util.IS_SECURETRANSPORT + and (util.IS_PYOPENSSL or sys.version_info < (3, 10)) + ): + buffer = io.BytesIO() + # Besides `max_chunk_amt` being a maximum chunk size, it + # affects memory overhead of reading a response by this + # method in CPython. + # `c_int_max` equal to 2 GiB - 1 byte is the actual maximum + # chunk size that does not lead to an overflow error, but + # 256 MiB is a compromise. + max_chunk_amt = 2 ** 28 + while amt is None or amt != 0: + if amt is not None: + chunk_amt = min(amt, max_chunk_amt) + amt -= chunk_amt + else: + chunk_amt = max_chunk_amt + data = self._fp.read(chunk_amt) + if not data: + break + buffer.write(data) + del data # to reduce peak memory usage by `max_chunk_amt`. + return buffer.getvalue() + else: + # StringIO doesn't like amt=None + return self._fp.read(amt) if amt is not None else self._fp.read() + + def read(self, amt=None, decode_content=None, cache_content=False): + """ + Similar to :meth:`http.client.HTTPResponse.read`, but with two additional + parameters: ``decode_content`` and ``cache_content``. + + :param amt: + How much of the content to read. If specified, caching is skipped + because it doesn't make sense to cache partial content as the full + response. + + :param decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + + :param cache_content: + If True, will save the returned data such that the same result is + returned despite of the state of the underlying file object. This + is useful if you want the ``.data`` property to continue working + after having ``.read()`` the file object. (Overridden if ``amt`` is + set.) + """ + self._init_decoder() + if decode_content is None: + decode_content = self.decode_content + + if self._fp is None: + return + + flush_decoder = False + fp_closed = getattr(self._fp, "closed", False) + + with self._error_catcher(): + data = self._fp_read(amt) if not fp_closed else b"" + if amt is None: + flush_decoder = True + else: + cache_content = False + if ( + amt != 0 and not data + ): # Platform-specific: Buggy versions of Python. + # Close the connection when no data is returned + # + # This is redundant to what httplib/http.client _should_ + # already do. However, versions of python released before + # December 15, 2012 (http://bugs.python.org/issue16298) do + # not properly close the connection in all cases. There is + # no harm in redundantly calling close. + self._fp.close() + flush_decoder = True + if self.enforce_content_length and self.length_remaining not in ( + 0, + None, + ): + # This is an edge case that httplib failed to cover due + # to concerns of backward compatibility. We're + # addressing it here to make sure IncompleteRead is + # raised during streaming, so all calls with incorrect + # Content-Length are caught. + raise IncompleteRead(self._fp_bytes_read, self.length_remaining) + + if data: + self._fp_bytes_read += len(data) + if self.length_remaining is not None: + self.length_remaining -= len(data) + + data = self._decode(data, decode_content, flush_decoder) + + if cache_content: + self._body = data + + return data + + def stream(self, amt=2 ** 16, decode_content=None): + """ + A generator wrapper for the read() method. A call will block until + ``amt`` bytes have been read from the connection or until the + connection is closed. + + :param amt: + How much of the content to read. The generator will return up to + much data per iteration, but may return less. This is particularly + likely when using compressed data. However, the empty string will + never be returned. + + :param decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + """ + if self.chunked and self.supports_chunked_reads(): + for line in self.read_chunked(amt, decode_content=decode_content): + yield line + else: + while not is_fp_closed(self._fp): + data = self.read(amt=amt, decode_content=decode_content) + + if data: + yield data + + @classmethod + def from_httplib(ResponseCls, r, **response_kw): + """ + Given an :class:`http.client.HTTPResponse` instance ``r``, return a + corresponding :class:`urllib3.response.HTTPResponse` object. + + Remaining parameters are passed to the HTTPResponse constructor, along + with ``original_response=r``. + """ + headers = r.msg + + if not isinstance(headers, HTTPHeaderDict): + if six.PY2: + # Python 2.7 + headers = HTTPHeaderDict.from_httplib(headers) + else: + headers = HTTPHeaderDict(headers.items()) + + # HTTPResponse objects in Python 3 don't have a .strict attribute + strict = getattr(r, "strict", 0) + resp = ResponseCls( + body=r, + headers=headers, + status=r.status, + version=r.version, + reason=r.reason, + strict=strict, + original_response=r, + **response_kw + ) + return resp + + # Backwards-compatibility methods for http.client.HTTPResponse + def getheaders(self): + warnings.warn( + "HTTPResponse.getheaders() is deprecated and will be removed " + "in urllib3 v2.1.0. Instead access HTTPResponse.headers directly.", + category=DeprecationWarning, + stacklevel=2, + ) + return self.headers + + def getheader(self, name, default=None): + warnings.warn( + "HTTPResponse.getheader() is deprecated and will be removed " + "in urllib3 v2.1.0. Instead use HTTPResponse.headers.get(name, default).", + category=DeprecationWarning, + stacklevel=2, + ) + return self.headers.get(name, default) + + # Backwards compatibility for http.cookiejar + def info(self): + return self.headers + + # Overrides from io.IOBase + def close(self): + if not self.closed: + self._fp.close() + + if self._connection: + self._connection.close() + + if not self.auto_close: + io.IOBase.close(self) + + @property + def closed(self): + if not self.auto_close: + return io.IOBase.closed.__get__(self) + elif self._fp is None: + return True + elif hasattr(self._fp, "isclosed"): + return self._fp.isclosed() + elif hasattr(self._fp, "closed"): + return self._fp.closed + else: + return True + + def fileno(self): + if self._fp is None: + raise IOError("HTTPResponse has no file to get a fileno from") + elif hasattr(self._fp, "fileno"): + return self._fp.fileno() + else: + raise IOError( + "The file-like object this HTTPResponse is wrapped " + "around has no file descriptor" + ) + + def flush(self): + if ( + self._fp is not None + and hasattr(self._fp, "flush") + and not getattr(self._fp, "closed", False) + ): + return self._fp.flush() + + def readable(self): + # This method is required for `io` module compatibility. + return True + + def readinto(self, b): + # This method is required for `io` module compatibility. + temp = self.read(len(b)) + if len(temp) == 0: + return 0 + else: + b[: len(temp)] = temp + return len(temp) + + def supports_chunked_reads(self): + """ + Checks if the underlying file-like object looks like a + :class:`http.client.HTTPResponse` object. We do this by testing for + the fp attribute. If it is present we assume it returns raw chunks as + processed by read_chunked(). + """ + return hasattr(self._fp, "fp") + + def _update_chunk_length(self): + # First, we'll figure out length of a chunk and then + # we'll try to read it from socket. + if self.chunk_left is not None: + return + line = self._fp.fp.readline() + line = line.split(b";", 1)[0] + try: + self.chunk_left = int(line, 16) + except ValueError: + # Invalid chunked protocol response, abort. + self.close() + raise InvalidChunkLength(self, line) + + def _handle_chunk(self, amt): + returned_chunk = None + if amt is None: + chunk = self._fp._safe_read(self.chunk_left) + returned_chunk = chunk + self._fp._safe_read(2) # Toss the CRLF at the end of the chunk. + self.chunk_left = None + elif amt < self.chunk_left: + value = self._fp._safe_read(amt) + self.chunk_left = self.chunk_left - amt + returned_chunk = value + elif amt == self.chunk_left: + value = self._fp._safe_read(amt) + self._fp._safe_read(2) # Toss the CRLF at the end of the chunk. + self.chunk_left = None + returned_chunk = value + else: # amt > self.chunk_left + returned_chunk = self._fp._safe_read(self.chunk_left) + self._fp._safe_read(2) # Toss the CRLF at the end of the chunk. + self.chunk_left = None + return returned_chunk + + def read_chunked(self, amt=None, decode_content=None): + """ + Similar to :meth:`HTTPResponse.read`, but with an additional + parameter: ``decode_content``. + + :param amt: + How much of the content to read. If specified, caching is skipped + because it doesn't make sense to cache partial content as the full + response. + + :param decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + """ + self._init_decoder() + # FIXME: Rewrite this method and make it a class with a better structured logic. + if not self.chunked: + raise ResponseNotChunked( + "Response is not chunked. " + "Header 'transfer-encoding: chunked' is missing." + ) + if not self.supports_chunked_reads(): + raise BodyNotHttplibCompatible( + "Body should be http.client.HTTPResponse like. " + "It should have have an fp attribute which returns raw chunks." + ) + + with self._error_catcher(): + # Don't bother reading the body of a HEAD request. + if self._original_response and is_response_to_head(self._original_response): + self._original_response.close() + return + + # If a response is already read and closed + # then return immediately. + if self._fp.fp is None: + return + + while True: + self._update_chunk_length() + if self.chunk_left == 0: + break + chunk = self._handle_chunk(amt) + decoded = self._decode( + chunk, decode_content=decode_content, flush_decoder=False + ) + if decoded: + yield decoded + + if decode_content: + # On CPython and PyPy, we should never need to flush the + # decoder. However, on Jython we *might* need to, so + # lets defensively do it anyway. + decoded = self._flush_decoder() + if decoded: # Platform-specific: Jython. + yield decoded + + # Chunk content ends with \r\n: discard it. + while True: + line = self._fp.fp.readline() + if not line: + # Some sites may not end with '\r\n'. + break + if line == b"\r\n": + break + + # We read everything; close the "file". + if self._original_response: + self._original_response.close() + + def geturl(self): + """ + Returns the URL that was the source of this response. + If the request that generated this response redirected, this method + will return the final redirect location. + """ + if self.retries is not None and len(self.retries.history): + return self.retries.history[-1].redirect_location + else: + return self._request_url + + def __iter__(self): + buffer = [] + for chunk in self.stream(decode_content=True): + if b"\n" in chunk: + chunk = chunk.split(b"\n") + yield b"".join(buffer) + chunk[0] + b"\n" + for x in chunk[1:-1]: + yield x + b"\n" + if chunk[-1]: + buffer = [chunk[-1]] + else: + buffer = [] + else: + buffer.append(chunk) + if buffer: + yield b"".join(buffer) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/__init__.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/__init__.py new file mode 100644 index 0000000..4547fc5 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/__init__.py @@ -0,0 +1,49 @@ +from __future__ import absolute_import + +# For backwards compatibility, provide imports that used to be here. +from .connection import is_connection_dropped +from .request import SKIP_HEADER, SKIPPABLE_HEADERS, make_headers +from .response import is_fp_closed +from .retry import Retry +from .ssl_ import ( + ALPN_PROTOCOLS, + HAS_SNI, + IS_PYOPENSSL, + IS_SECURETRANSPORT, + PROTOCOL_TLS, + SSLContext, + assert_fingerprint, + resolve_cert_reqs, + resolve_ssl_version, + ssl_wrap_socket, +) +from .timeout import Timeout, current_time +from .url import Url, get_host, parse_url, split_first +from .wait import wait_for_read, wait_for_write + +__all__ = ( + "HAS_SNI", + "IS_PYOPENSSL", + "IS_SECURETRANSPORT", + "SSLContext", + "PROTOCOL_TLS", + "ALPN_PROTOCOLS", + "Retry", + "Timeout", + "Url", + "assert_fingerprint", + "current_time", + "is_connection_dropped", + "is_fp_closed", + "get_host", + "parse_url", + "make_headers", + "resolve_cert_reqs", + "resolve_ssl_version", + "split_first", + "ssl_wrap_socket", + "wait_for_read", + "wait_for_write", + "SKIP_HEADER", + "SKIPPABLE_HEADERS", +) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7de5a437d614bac387fe9d795a62097fc2eaf188 GIT binary patch literal 1150 zcmZ9LOK;mo5XYB#QEyrDBXaDdNeUEI3tNW*ITTF+)fEtiryA5eCR2+06`I;r_RuE1eAv#W`>-d`Ohr>XtnADo^QW@7X4Bp zj>AT5eZF zT{dVVw_VYcE!vW8+Lj&KksEYFc4=4kXisj^O}Rz4-O_X`% z+{U*f&4MJ3d0?U>W}!;bl!t?&ZFt`t&)M_w=?ny1|H;^%uQgYOoksB)SE-6(W4nrj#0$;> ze53e}+HT&3v=;0F8U>BEgU+S$Q>K&PoSQ+xy30uNBr~=dWJ>YaFav=>$rfKIVXJ4{ zu$PH8wwC%zbCyA{p;HlI14`owtxF%hL_uLcwC(rqrHTw6^i>n)ty+jSVgu1ZG!S?P z)i&ZDqKnu;lo2&VAF+$5B6^5T#C^mTVh^#8s32Uxbnv0AGj^JpOmW6k5n{H!-gsWX zx-hMbYqQSFi`Xj6FHK??HMU^O3U`_}YfCuA+vfi#EmxK6%Vn$^#U8DTlZ8>=szr^q z2=lzvz1E1LYze2hR%Knrd?6V7jl6-^lab9h5Wf0EHPd2&tqZwn2l@RqzspE#f1 Xkf(oH}u0ToYQ&uE9l%t5|S7d<(Nr^p?y|m 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 DZdRRM literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/proxy.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/proxy.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2c80fff1515d1a220a8c052525aaf6447fd69abb GIT binary patch literal 1556 zcmZ8h%}?A$6rWkI7cZEw+1=7rN>it(36@|{)Qv<{VK~e`fv+xfF z7gI^59ZGCYtcd!)*Z$CQ!hn-!Jh@H@3;k_kIfQbHk{?)78E!G=Tib*(FAN%vG6VyE zfk&***I?R3G1|cc9OvBJ)*M1q$Y>KZ{~xX*^;0pXlQG^LRyATKd}VKuH>7=^hR+7| zaT#x^Z&SNxe7pA8klW%wmZU~x6Wd{$By$qGna`>Svm6E;ubcS-5LjHfOA7%Hb|Y#_ zgdH08jD8sUJv*?wgx33mQ6P*{!zGM+fi$<6vq5^~Dr6JtP4|YtMy%_`oL48t2IqY? zFMsm};f^U2JWTRJk*HGLG;>KI4V2U(MyyUqpW4**g02uPX#_keUY<&#r(#-8QXa{h zp=5#sa6WIG<)zlskZ!TQ?T}Wm$=QPKIAIh(S=|LEq@>lhoh=f$t@<_zwp)+Ac8htO zEP%rnoC<68z5XJQEpS7+m~nJ5;-0@KLBOFU?*WkP+67PLwM*C*k3iwmDL|8lkKKc5 z2c69z?fU*$?bTHEtbnu|&%Zkyn-vQU70X9j?LezNe{`tL9_zJNdhJNRd#K+%m9~26 z93mh`6>~PAB~!}(0>UohqOIiMmyHply=<3Xdd7IT_b1-V2>+8B=a>;I>}H&2Gkk0q zDOTOw(1w;`b+b6sT>bYl5u;fB2KxHPmb~jnBp|>y(Fee$jve_trKkZtEC?xjU9?Xa z09|Yr+~G!>kU$u1doFQ}_CU0X3N|ltt^*(Jea9caTZh* zPsK$fW01<`oYE?+%mOV7O+{!l$4;G+iA=Iwk0$!%!sd3GI|I+e1pwDz&}$+>Eql;X zk_wcWCA|Ua58z`DVcJ0#*HFbgsowd0;zjkNlk)6uU%e>TFI1&c*jf2kN0V0f!4CF5OlJzl_%&KRK&!yUPw$^AH*x9g3yfCq6MUgm@!K-S Ef64HwmjD0& literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..501869f93268f9cc8a5620039fd6f2b80cf4f3fb GIT binary patch literal 1356 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..00354e3670b265246858495176e3deaa4125ba15 GIT binary patch literal 2996 zcma)8OKc=Z8LocK(=+4uW3!L;&L+!$rq<<~}vWVEJXIY8x7G{S&2)hW5i}Xz5p^eR9eSxY=bC}IxqH5}_xrlAGWLkK@G8eGw6zAb+Rgd{KdHzZRp&nPp4j9{?z^^Dw6F^E24XIV5Ij@V^aX4iGkMtc;>>r<;tVwz9sq>}Z5Gp+idh*fz?$KZ!78yVvp6(ZWu`Sq zFs(Q?#raCjZ82$~#M6f#5NQM7{P5`==+@9dtD>Y1BB-_FUVXj(?vEO=3;)?q_8lTY zNj;3U97yo~@*pBBsn0U)_g2BiOxpXH+K@F4SDn+ z%5Bmd_`jQJNAJfkN36Bo7W7F=eDt#PNxuO7sjQEIrkC~a z!$ICh>^S4=P1!yF6?wcB*(n}($i{aO*+_XoTwT2q3Jsg$9aBoDc%iuvE zPuGR(=$@jBvq%?za1NqUnye_SGt_0>;poH)73<1-;!n=Yu$NV(F2J`$QmikOtP6GN zV#DHg7)pbm1scKm@ z6`<<@nPYZ*nGsC~eQbNczyupA=B!B75^>5Z(1HrN4&19cB~KNw6M6{9;B_0UdO%Yh zTfJFhbMP8E%@mwq^FG1mZ``_da{|HvgoT!dRiBqBCx%5#%u+4XCz?qyRRi?p@v@F9 zob+k_Nh&`fqt{M?4Ys2ZpeJ4sd@5SGjF&4wZLnV+8z4I$#PqB>>oE1sbE|nbYIv1} zPP)li%nB8)W;vRX6G;c$lbfpA{#h0bjcK`*n=qlMP^Q^BcB6q+H`%mZH-4*D2`Q}P zkg~>HnZcAB1^XIsoJS_*u++IqvBofUCCUg&#;GutmZVi2L5w&!0%zm)+;L`Kkm!98E z4(+FV8oeVAddIeV$NqHv&pm&f*y(*^Cq31OO+89?ZOm@gKDx4#9$b5MzrAns>W44= z`pQoGi)-Khth0A*;$gI%vtZAIOm;hy-OW7xu)F`K<#%3vlmXFSjDI}z;mB_0xjpsj zM(SZS{rP$H)a4^3(vkT4x&DpFe#eEq*6!WD7k0n#W~29eUr1tS`cOfsj=gjJ2MUU} z9v~3?ycNYV?+xsy)sK39pW01NHe!qI4Hzfj9)#)wJLbL+p#(5&2n%q0Q?NdN%zh_!Las4HUkYmQzdZ<_slh(t-mYTm zK~CfF^GXfinfh?n)EncY*9Qppr2Kroq1lE7IN|DVS52sT9I&I6%D6oXH8w<(U$@Vq z@r}?$=<5VX$4g-)SIv^=#33dahW{_%gCG)bJ3P&*Krrf69^_ROg4WbB{9iZ$@*eYp zbY;Gplig^+Un86(UCFeWt5ho$OyHj{7KYA8p%s=7a2R^x|HoYqM?rP9t`1FWGi)WPRk_Yn!*Xli7xx zJpw&6$-!JGl&Y*saG^lFh+A-3Gp)Q&Cq584B;CXbC3(nn+r!_7JT;f|WoHpn!b>XY z;T``!@Sx_!`b$Ix_=Jbc*htwisusRRhG33YMVf^U{t*P>Q}oQg(3}56U;h-nco;b^ Uyeu4E8xmd@jw~T1T=9(j52?%umH+?% literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5cbdfe0dc6ff619fd096f80518f2ed817cb73a3c GIT binary patch literal 21726 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..103ded9bfdc00680238a0bdd41e4efa312c2e493 GIT binary patch literal 15368 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 Qifuo-={(GQP90|c4V46;y8r+H literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-312.pyc b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6565678dae9beb7f6023bc9ff33aaaacc41e6a7e GIT binary patch literal 10757 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 make_headers(keep_alive=True, user_agent="Batman/1.0") + {'connection': 'keep-alive', 'user-agent': 'Batman/1.0'} + >>> make_headers(accept_encoding=True) + {'accept-encoding': 'gzip,deflate'} + """ + headers = {} + if accept_encoding: + if isinstance(accept_encoding, str): + pass + elif isinstance(accept_encoding, list): + accept_encoding = ",".join(accept_encoding) + else: + accept_encoding = ACCEPT_ENCODING + headers["accept-encoding"] = accept_encoding + + if user_agent: + headers["user-agent"] = user_agent + + if keep_alive: + headers["connection"] = "keep-alive" + + if basic_auth: + headers["authorization"] = "Basic " + b64encode(b(basic_auth)).decode("utf-8") + + if proxy_basic_auth: + headers["proxy-authorization"] = "Basic " + b64encode( + b(proxy_basic_auth) + ).decode("utf-8") + + if disable_cache: + headers["cache-control"] = "no-cache" + + return headers + + +def set_file_position(body, pos): + """ + If a position is provided, move file to that point. + Otherwise, we'll attempt to record a position for future use. + """ + if pos is not None: + rewind_body(body, pos) + elif getattr(body, "tell", None) is not None: + try: + pos = body.tell() + except (IOError, OSError): + # This differentiates from None, allowing us to catch + # a failed `tell()` later when trying to rewind the body. + pos = _FAILEDTELL + + return pos + + +def rewind_body(body, body_pos): + """ + Attempt to rewind body to a certain position. + Primarily used for request redirects and retries. + + :param body: + File-like object that supports seek. + + :param int pos: + Position to seek to in file. + """ + body_seek = getattr(body, "seek", None) + if body_seek is not None and isinstance(body_pos, integer_types): + try: + body_seek(body_pos) + except (IOError, OSError): + raise UnrewindableBodyError( + "An error occurred when rewinding request body for redirect/retry." + ) + elif body_pos is _FAILEDTELL: + raise UnrewindableBodyError( + "Unable to record file position for rewinding " + "request body during a redirect/retry." + ) + else: + raise ValueError( + "body_pos must be of type integer, instead it was %s." % type(body_pos) + ) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/response.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/response.py new file mode 100644 index 0000000..5ea609c --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/response.py @@ -0,0 +1,107 @@ +from __future__ import absolute_import + +from email.errors import MultipartInvariantViolationDefect, StartBoundaryNotFoundDefect + +from ..exceptions import HeaderParsingError +from ..packages.six.moves import http_client as httplib + + +def is_fp_closed(obj): + """ + Checks whether a given file-like object is closed. + + :param obj: + The file-like object to check. + """ + + try: + # Check `isclosed()` first, in case Python3 doesn't set `closed`. + # GH Issue #928 + return obj.isclosed() + except AttributeError: + pass + + try: + # Check via the official file-like-object way. + return obj.closed + except AttributeError: + pass + + try: + # Check if the object is a container for another file-like object that + # gets released on exhaustion (e.g. HTTPResponse). + return obj.fp is None + except AttributeError: + pass + + raise ValueError("Unable to determine whether fp is closed.") + + +def assert_header_parsing(headers): + """ + Asserts whether all headers have been successfully parsed. + Extracts encountered errors from the result of parsing headers. + + Only works on Python 3. + + :param http.client.HTTPMessage headers: Headers to verify. + + :raises urllib3.exceptions.HeaderParsingError: + If parsing errors are found. + """ + + # This will fail silently if we pass in the wrong kind of parameter. + # To make debugging easier add an explicit check. + if not isinstance(headers, httplib.HTTPMessage): + raise TypeError("expected httplib.Message, got {0}.".format(type(headers))) + + defects = getattr(headers, "defects", None) + get_payload = getattr(headers, "get_payload", None) + + unparsed_data = None + if get_payload: + # get_payload is actually email.message.Message.get_payload; + # we're only interested in the result if it's not a multipart message + if not headers.is_multipart(): + payload = get_payload() + + if isinstance(payload, (bytes, str)): + unparsed_data = payload + if defects: + # httplib is assuming a response body is available + # when parsing headers even when httplib only sends + # header data to parse_headers() This results in + # defects on multipart responses in particular. + # See: https://github.com/urllib3/urllib3/issues/800 + + # So we ignore the following defects: + # - StartBoundaryNotFoundDefect: + # The claimed start boundary was never found. + # - MultipartInvariantViolationDefect: + # A message claimed to be a multipart but no subparts were found. + defects = [ + defect + for defect in defects + if not isinstance( + defect, (StartBoundaryNotFoundDefect, MultipartInvariantViolationDefect) + ) + ] + + if defects or unparsed_data: + raise HeaderParsingError(defects=defects, unparsed_data=unparsed_data) + + +def is_response_to_head(response): + """ + Checks whether the request of a response has been a HEAD-request. + Handles the quirks of AppEngine. + + :param http.client.HTTPResponse response: + Response to check if the originating request + used 'HEAD' as a method. + """ + # FIXME: Can we do this somehow without accessing private httplib _method? + method = response._method + if isinstance(method, int): # Platform-specific: Appengine + return method == 3 + return method.upper() == "HEAD" diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/retry.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/retry.py new file mode 100644 index 0000000..9a1e90d --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/retry.py @@ -0,0 +1,622 @@ +from __future__ import absolute_import + +import email +import logging +import re +import time +import warnings +from collections import namedtuple +from itertools import takewhile + +from ..exceptions import ( + ConnectTimeoutError, + InvalidHeader, + MaxRetryError, + ProtocolError, + ProxyError, + ReadTimeoutError, + ResponseError, +) +from ..packages import six + +log = logging.getLogger(__name__) + + +# Data structure for representing the metadata of requests that result in a retry. +RequestHistory = namedtuple( + "RequestHistory", ["method", "url", "error", "status", "redirect_location"] +) + + +# TODO: In v2 we can remove this sentinel and metaclass with deprecated options. +_Default = object() + + +class _RetryMeta(type): + @property + def DEFAULT_METHOD_WHITELIST(cls): + warnings.warn( + "Using 'Retry.DEFAULT_METHOD_WHITELIST' is deprecated and " + "will be removed in v2.0. Use 'Retry.DEFAULT_ALLOWED_METHODS' instead", + DeprecationWarning, + ) + return cls.DEFAULT_ALLOWED_METHODS + + @DEFAULT_METHOD_WHITELIST.setter + def DEFAULT_METHOD_WHITELIST(cls, value): + warnings.warn( + "Using 'Retry.DEFAULT_METHOD_WHITELIST' is deprecated and " + "will be removed in v2.0. Use 'Retry.DEFAULT_ALLOWED_METHODS' instead", + DeprecationWarning, + ) + cls.DEFAULT_ALLOWED_METHODS = value + + @property + def DEFAULT_REDIRECT_HEADERS_BLACKLIST(cls): + warnings.warn( + "Using 'Retry.DEFAULT_REDIRECT_HEADERS_BLACKLIST' is deprecated and " + "will be removed in v2.0. Use 'Retry.DEFAULT_REMOVE_HEADERS_ON_REDIRECT' instead", + DeprecationWarning, + ) + return cls.DEFAULT_REMOVE_HEADERS_ON_REDIRECT + + @DEFAULT_REDIRECT_HEADERS_BLACKLIST.setter + def DEFAULT_REDIRECT_HEADERS_BLACKLIST(cls, value): + warnings.warn( + "Using 'Retry.DEFAULT_REDIRECT_HEADERS_BLACKLIST' is deprecated and " + "will be removed in v2.0. Use 'Retry.DEFAULT_REMOVE_HEADERS_ON_REDIRECT' instead", + DeprecationWarning, + ) + cls.DEFAULT_REMOVE_HEADERS_ON_REDIRECT = value + + @property + def BACKOFF_MAX(cls): + warnings.warn( + "Using 'Retry.BACKOFF_MAX' is deprecated and " + "will be removed in v2.0. Use 'Retry.DEFAULT_BACKOFF_MAX' instead", + DeprecationWarning, + ) + return cls.DEFAULT_BACKOFF_MAX + + @BACKOFF_MAX.setter + def BACKOFF_MAX(cls, value): + warnings.warn( + "Using 'Retry.BACKOFF_MAX' is deprecated and " + "will be removed in v2.0. Use 'Retry.DEFAULT_BACKOFF_MAX' instead", + DeprecationWarning, + ) + cls.DEFAULT_BACKOFF_MAX = value + + +@six.add_metaclass(_RetryMeta) +class Retry(object): + """Retry configuration. + + Each retry attempt will create a new Retry object with updated values, so + they can be safely reused. + + Retries can be defined as a default for a pool:: + + retries = Retry(connect=5, read=2, redirect=5) + http = PoolManager(retries=retries) + response = http.request('GET', 'http://example.com/') + + Or per-request (which overrides the default for the pool):: + + response = http.request('GET', 'http://example.com/', retries=Retry(10)) + + Retries can be disabled by passing ``False``:: + + response = http.request('GET', 'http://example.com/', retries=False) + + Errors will be wrapped in :class:`~urllib3.exceptions.MaxRetryError` unless + retries are disabled, in which case the causing exception will be raised. + + :param int total: + Total number of retries to allow. Takes precedence over other counts. + + Set to ``None`` to remove this constraint and fall back on other + counts. + + Set to ``0`` to fail on the first retry. + + Set to ``False`` to disable and imply ``raise_on_redirect=False``. + + :param int connect: + How many connection-related errors to retry on. + + These are errors raised before the request is sent to the remote server, + which we assume has not triggered the server to process the request. + + Set to ``0`` to fail on the first retry of this type. + + :param int read: + How many times to retry on read errors. + + These errors are raised after the request was sent to the server, so the + request may have side-effects. + + Set to ``0`` to fail on the first retry of this type. + + :param int redirect: + How many redirects to perform. Limit this to avoid infinite redirect + loops. + + A redirect is a HTTP response with a status code 301, 302, 303, 307 or + 308. + + Set to ``0`` to fail on the first retry of this type. + + Set to ``False`` to disable and imply ``raise_on_redirect=False``. + + :param int status: + How many times to retry on bad status codes. + + These are retries made on responses, where status code matches + ``status_forcelist``. + + Set to ``0`` to fail on the first retry of this type. + + :param int other: + How many times to retry on other errors. + + Other errors are errors that are not connect, read, redirect or status errors. + These errors might be raised after the request was sent to the server, so the + request might have side-effects. + + Set to ``0`` to fail on the first retry of this type. + + If ``total`` is not set, it's a good idea to set this to 0 to account + for unexpected edge cases and avoid infinite retry loops. + + :param iterable allowed_methods: + Set of uppercased HTTP method verbs that we should retry on. + + By default, we only retry on methods which are considered to be + idempotent (multiple requests with the same parameters end with the + same state). See :attr:`Retry.DEFAULT_ALLOWED_METHODS`. + + Set to a ``False`` value to retry on any verb. + + .. warning:: + + Previously this parameter was named ``method_whitelist``, that + usage is deprecated in v1.26.0 and will be removed in v2.0. + + :param iterable status_forcelist: + A set of integer HTTP status codes that we should force a retry on. + A retry is initiated if the request method is in ``allowed_methods`` + and the response status code is in ``status_forcelist``. + + By default, this is disabled with ``None``. + + :param float backoff_factor: + A backoff factor to apply between attempts after the second try + (most errors are resolved immediately by a second try without a + delay). urllib3 will sleep for:: + + {backoff factor} * (2 ** ({number of total retries} - 1)) + + seconds. If the backoff_factor is 0.1, then :func:`.sleep` will sleep + for [0.0s, 0.2s, 0.4s, ...] between retries. It will never be longer + than :attr:`Retry.DEFAULT_BACKOFF_MAX`. + + By default, backoff is disabled (set to 0). + + :param bool raise_on_redirect: Whether, if the number of redirects is + exhausted, to raise a MaxRetryError, or to return a response with a + response code in the 3xx range. + + :param bool raise_on_status: Similar meaning to ``raise_on_redirect``: + whether we should raise an exception, or return a response, + if status falls in ``status_forcelist`` range and retries have + been exhausted. + + :param tuple history: The history of the request encountered during + each call to :meth:`~Retry.increment`. The list is in the order + the requests occurred. Each list item is of class :class:`RequestHistory`. + + :param bool respect_retry_after_header: + Whether to respect Retry-After header on status codes defined as + :attr:`Retry.RETRY_AFTER_STATUS_CODES` or not. + + :param iterable remove_headers_on_redirect: + Sequence of headers to remove from the request when a response + indicating a redirect is returned before firing off the redirected + request. + """ + + #: Default methods to be used for ``allowed_methods`` + DEFAULT_ALLOWED_METHODS = frozenset( + ["HEAD", "GET", "PUT", "DELETE", "OPTIONS", "TRACE"] + ) + + #: Default status codes to be used for ``status_forcelist`` + RETRY_AFTER_STATUS_CODES = frozenset([413, 429, 503]) + + #: Default headers to be used for ``remove_headers_on_redirect`` + DEFAULT_REMOVE_HEADERS_ON_REDIRECT = frozenset( + ["Cookie", "Authorization", "Proxy-Authorization"] + ) + + #: Maximum backoff time. + DEFAULT_BACKOFF_MAX = 120 + + def __init__( + self, + total=10, + connect=None, + read=None, + redirect=None, + status=None, + other=None, + allowed_methods=_Default, + status_forcelist=None, + backoff_factor=0, + raise_on_redirect=True, + raise_on_status=True, + history=None, + respect_retry_after_header=True, + remove_headers_on_redirect=_Default, + # TODO: Deprecated, remove in v2.0 + method_whitelist=_Default, + ): + + if method_whitelist is not _Default: + if allowed_methods is not _Default: + raise ValueError( + "Using both 'allowed_methods' and " + "'method_whitelist' together is not allowed. " + "Instead only use 'allowed_methods'" + ) + warnings.warn( + "Using 'method_whitelist' with Retry is deprecated and " + "will be removed in v2.0. Use 'allowed_methods' instead", + DeprecationWarning, + stacklevel=2, + ) + allowed_methods = method_whitelist + if allowed_methods is _Default: + allowed_methods = self.DEFAULT_ALLOWED_METHODS + if remove_headers_on_redirect is _Default: + remove_headers_on_redirect = self.DEFAULT_REMOVE_HEADERS_ON_REDIRECT + + self.total = total + self.connect = connect + self.read = read + self.status = status + self.other = other + + if redirect is False or total is False: + redirect = 0 + raise_on_redirect = False + + self.redirect = redirect + self.status_forcelist = status_forcelist or set() + self.allowed_methods = allowed_methods + self.backoff_factor = backoff_factor + self.raise_on_redirect = raise_on_redirect + self.raise_on_status = raise_on_status + self.history = history or tuple() + self.respect_retry_after_header = respect_retry_after_header + self.remove_headers_on_redirect = frozenset( + [h.lower() for h in remove_headers_on_redirect] + ) + + def new(self, **kw): + params = dict( + total=self.total, + connect=self.connect, + read=self.read, + redirect=self.redirect, + status=self.status, + other=self.other, + status_forcelist=self.status_forcelist, + backoff_factor=self.backoff_factor, + raise_on_redirect=self.raise_on_redirect, + raise_on_status=self.raise_on_status, + history=self.history, + remove_headers_on_redirect=self.remove_headers_on_redirect, + respect_retry_after_header=self.respect_retry_after_header, + ) + + # TODO: If already given in **kw we use what's given to us + # If not given we need to figure out what to pass. We decide + # based on whether our class has the 'method_whitelist' property + # and if so we pass the deprecated 'method_whitelist' otherwise + # we use 'allowed_methods'. Remove in v2.0 + if "method_whitelist" not in kw and "allowed_methods" not in kw: + if "method_whitelist" in self.__dict__: + warnings.warn( + "Using 'method_whitelist' with Retry is deprecated and " + "will be removed in v2.0. Use 'allowed_methods' instead", + DeprecationWarning, + ) + params["method_whitelist"] = self.allowed_methods + else: + params["allowed_methods"] = self.allowed_methods + + params.update(kw) + return type(self)(**params) + + @classmethod + def from_int(cls, retries, redirect=True, default=None): + """Backwards-compatibility for the old retries format.""" + if retries is None: + retries = default if default is not None else cls.DEFAULT + + if isinstance(retries, Retry): + return retries + + redirect = bool(redirect) and None + new_retries = cls(retries, redirect=redirect) + log.debug("Converted retries value: %r -> %r", retries, new_retries) + return new_retries + + def get_backoff_time(self): + """Formula for computing the current backoff + + :rtype: float + """ + # We want to consider only the last consecutive errors sequence (Ignore redirects). + consecutive_errors_len = len( + list( + takewhile(lambda x: x.redirect_location is None, reversed(self.history)) + ) + ) + if consecutive_errors_len <= 1: + return 0 + + backoff_value = self.backoff_factor * (2 ** (consecutive_errors_len - 1)) + return min(self.DEFAULT_BACKOFF_MAX, backoff_value) + + def parse_retry_after(self, retry_after): + # Whitespace: https://tools.ietf.org/html/rfc7230#section-3.2.4 + if re.match(r"^\s*[0-9]+\s*$", retry_after): + seconds = int(retry_after) + else: + retry_date_tuple = email.utils.parsedate_tz(retry_after) + if retry_date_tuple is None: + raise InvalidHeader("Invalid Retry-After header: %s" % retry_after) + if retry_date_tuple[9] is None: # Python 2 + # Assume UTC if no timezone was specified + # On Python2.7, parsedate_tz returns None for a timezone offset + # instead of 0 if no timezone is given, where mktime_tz treats + # a None timezone offset as local time. + retry_date_tuple = retry_date_tuple[:9] + (0,) + retry_date_tuple[10:] + + retry_date = email.utils.mktime_tz(retry_date_tuple) + seconds = retry_date - time.time() + + if seconds < 0: + seconds = 0 + + return seconds + + def get_retry_after(self, response): + """Get the value of Retry-After in seconds.""" + + retry_after = response.headers.get("Retry-After") + + if retry_after is None: + return None + + return self.parse_retry_after(retry_after) + + def sleep_for_retry(self, response=None): + retry_after = self.get_retry_after(response) + if retry_after: + time.sleep(retry_after) + return True + + return False + + def _sleep_backoff(self): + backoff = self.get_backoff_time() + if backoff <= 0: + return + time.sleep(backoff) + + def sleep(self, response=None): + """Sleep between retry attempts. + + This method will respect a server's ``Retry-After`` response header + and sleep the duration of the time requested. If that is not present, it + will use an exponential backoff. By default, the backoff factor is 0 and + this method will return immediately. + """ + + if self.respect_retry_after_header and response: + slept = self.sleep_for_retry(response) + if slept: + return + + self._sleep_backoff() + + def _is_connection_error(self, err): + """Errors when we're fairly sure that the server did not receive the + request, so it should be safe to retry. + """ + if isinstance(err, ProxyError): + err = err.original_error + return isinstance(err, ConnectTimeoutError) + + def _is_read_error(self, err): + """Errors that occur after the request has been started, so we should + assume that the server began processing it. + """ + return isinstance(err, (ReadTimeoutError, ProtocolError)) + + def _is_method_retryable(self, method): + """Checks if a given HTTP method should be retried upon, depending if + it is included in the allowed_methods + """ + # TODO: For now favor if the Retry implementation sets its own method_whitelist + # property outside of our constructor to avoid breaking custom implementations. + if "method_whitelist" in self.__dict__: + warnings.warn( + "Using 'method_whitelist' with Retry is deprecated and " + "will be removed in v2.0. Use 'allowed_methods' instead", + DeprecationWarning, + ) + allowed_methods = self.method_whitelist + else: + allowed_methods = self.allowed_methods + + if allowed_methods and method.upper() not in allowed_methods: + return False + return True + + def is_retry(self, method, status_code, has_retry_after=False): + """Is this method/status code retryable? (Based on allowlists and control + variables such as the number of total retries to allow, whether to + respect the Retry-After header, whether this header is present, and + whether the returned status code is on the list of status codes to + be retried upon on the presence of the aforementioned header) + """ + if not self._is_method_retryable(method): + return False + + if self.status_forcelist and status_code in self.status_forcelist: + return True + + return ( + self.total + and self.respect_retry_after_header + and has_retry_after + and (status_code in self.RETRY_AFTER_STATUS_CODES) + ) + + def is_exhausted(self): + """Are we out of retries?""" + retry_counts = ( + self.total, + self.connect, + self.read, + self.redirect, + self.status, + self.other, + ) + retry_counts = list(filter(None, retry_counts)) + if not retry_counts: + return False + + return min(retry_counts) < 0 + + def increment( + self, + method=None, + url=None, + response=None, + error=None, + _pool=None, + _stacktrace=None, + ): + """Return a new Retry object with incremented retry counters. + + :param response: A response object, or None, if the server did not + return a response. + :type response: :class:`~urllib3.response.HTTPResponse` + :param Exception error: An error encountered during the request, or + None if the response was received successfully. + + :return: A new ``Retry`` object. + """ + if self.total is False and error: + # Disabled, indicate to re-raise the error. + raise six.reraise(type(error), error, _stacktrace) + + total = self.total + if total is not None: + total -= 1 + + connect = self.connect + read = self.read + redirect = self.redirect + status_count = self.status + other = self.other + cause = "unknown" + status = None + redirect_location = None + + if error and self._is_connection_error(error): + # Connect retry? + if connect is False: + raise six.reraise(type(error), error, _stacktrace) + elif connect is not None: + connect -= 1 + + elif error and self._is_read_error(error): + # Read retry? + if read is False or not self._is_method_retryable(method): + raise six.reraise(type(error), error, _stacktrace) + elif read is not None: + read -= 1 + + elif error: + # Other retry? + if other is not None: + other -= 1 + + elif response and response.get_redirect_location(): + # Redirect retry? + if redirect is not None: + redirect -= 1 + cause = "too many redirects" + redirect_location = response.get_redirect_location() + status = response.status + + else: + # Incrementing because of a server error like a 500 in + # status_forcelist and the given method is in the allowed_methods + cause = ResponseError.GENERIC_ERROR + if response and response.status: + if status_count is not None: + status_count -= 1 + cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) + status = response.status + + history = self.history + ( + RequestHistory(method, url, error, status, redirect_location), + ) + + new_retry = self.new( + total=total, + connect=connect, + read=read, + redirect=redirect, + status=status_count, + other=other, + history=history, + ) + + if new_retry.is_exhausted(): + raise MaxRetryError(_pool, url, error or ResponseError(cause)) + + log.debug("Incremented Retry for (url='%s'): %r", url, new_retry) + + return new_retry + + def __repr__(self): + return ( + "{cls.__name__}(total={self.total}, connect={self.connect}, " + "read={self.read}, redirect={self.redirect}, status={self.status})" + ).format(cls=type(self), self=self) + + def __getattr__(self, item): + if item == "method_whitelist": + # TODO: Remove this deprecated alias in v2.0 + warnings.warn( + "Using 'method_whitelist' with Retry is deprecated and " + "will be removed in v2.0. Use 'allowed_methods' instead", + DeprecationWarning, + ) + return self.allowed_methods + try: + return getattr(super(Retry, self), item) + except AttributeError: + return getattr(Retry, item) + + +# For backwards compatibility (equivalent to pre-v1.9): +Retry.DEFAULT = Retry(3) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py new file mode 100644 index 0000000..0a6a0e0 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py @@ -0,0 +1,504 @@ +from __future__ import absolute_import + +import hashlib +import hmac +import os +import sys +import warnings +from binascii import hexlify, unhexlify + +from ..exceptions import ( + InsecurePlatformWarning, + ProxySchemeUnsupported, + SNIMissingWarning, + SSLError, +) +from ..packages import six +from .url import BRACELESS_IPV6_ADDRZ_RE, IPV4_RE + +SSLContext = None +SSLTransport = None +HAS_SNI = False +IS_PYOPENSSL = False +IS_SECURETRANSPORT = False +ALPN_PROTOCOLS = ["http/1.1"] + +# Maps the length of a digest to a possible hash function producing this digest +HASHFUNC_MAP = { + length: getattr(hashlib, algorithm, None) + for length, algorithm in ((32, "md5"), (40, "sha1"), (64, "sha256")) +} + + +def _const_compare_digest_backport(a, b): + """ + Compare two digests of equal length in constant time. + + The digests must be of type str/bytes. + Returns True if the digests match, and False otherwise. + """ + result = abs(len(a) - len(b)) + for left, right in zip(bytearray(a), bytearray(b)): + result |= left ^ right + return result == 0 + + +_const_compare_digest = getattr(hmac, "compare_digest", _const_compare_digest_backport) + +try: # Test for SSL features + import ssl + from ssl import CERT_REQUIRED, wrap_socket +except ImportError: + pass + +try: + from ssl import HAS_SNI # Has SNI? +except ImportError: + pass + +try: + from .ssltransport import SSLTransport +except ImportError: + pass + + +try: # Platform-specific: Python 3.6 + from ssl import PROTOCOL_TLS + + PROTOCOL_SSLv23 = PROTOCOL_TLS +except ImportError: + try: + from ssl import PROTOCOL_SSLv23 as PROTOCOL_TLS + + PROTOCOL_SSLv23 = PROTOCOL_TLS + except ImportError: + PROTOCOL_SSLv23 = PROTOCOL_TLS = 2 + +try: + from ssl import PROTOCOL_TLS_CLIENT +except ImportError: + PROTOCOL_TLS_CLIENT = PROTOCOL_TLS + + +try: + from ssl import OP_NO_COMPRESSION, OP_NO_SSLv2, OP_NO_SSLv3 +except ImportError: + OP_NO_SSLv2, OP_NO_SSLv3 = 0x1000000, 0x2000000 + OP_NO_COMPRESSION = 0x20000 + + +try: # OP_NO_TICKET was added in Python 3.6 + from ssl import OP_NO_TICKET +except ImportError: + OP_NO_TICKET = 0x4000 + + +# A secure default. +# Sources for more information on TLS ciphers: +# +# - https://wiki.mozilla.org/Security/Server_Side_TLS +# - https://www.ssllabs.com/projects/best-practices/index.html +# - https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/ +# +# The general intent is: +# - prefer cipher suites that offer perfect forward secrecy (DHE/ECDHE), +# - prefer ECDHE over DHE for better performance, +# - prefer any AES-GCM and ChaCha20 over any AES-CBC for better performance and +# security, +# - prefer AES-GCM over ChaCha20 because hardware-accelerated AES is common, +# - disable NULL authentication, MD5 MACs, DSS, and other +# insecure ciphers for security reasons. +# - NOTE: TLS 1.3 cipher suites are managed through a different interface +# not exposed by CPython (yet!) and are enabled by default if they're available. +DEFAULT_CIPHERS = ":".join( + [ + "ECDHE+AESGCM", + "ECDHE+CHACHA20", + "DHE+AESGCM", + "DHE+CHACHA20", + "ECDH+AESGCM", + "DH+AESGCM", + "ECDH+AES", + "DH+AES", + "RSA+AESGCM", + "RSA+AES", + "!aNULL", + "!eNULL", + "!MD5", + "!DSS", + ] +) + +try: + from ssl import SSLContext # Modern SSL? +except ImportError: + + class SSLContext(object): # Platform-specific: Python 2 + def __init__(self, protocol_version): + self.protocol = protocol_version + # Use default values from a real SSLContext + self.check_hostname = False + self.verify_mode = ssl.CERT_NONE + self.ca_certs = None + self.options = 0 + self.certfile = None + self.keyfile = None + self.ciphers = None + + def load_cert_chain(self, certfile, keyfile): + self.certfile = certfile + self.keyfile = keyfile + + def load_verify_locations(self, cafile=None, capath=None, cadata=None): + self.ca_certs = cafile + + if capath is not None: + raise SSLError("CA directories not supported in older Pythons") + + if cadata is not None: + raise SSLError("CA data not supported in older Pythons") + + def set_ciphers(self, cipher_suite): + self.ciphers = cipher_suite + + def wrap_socket(self, socket, server_hostname=None, server_side=False): + warnings.warn( + "A true SSLContext object is not available. This prevents " + "urllib3 from configuring SSL appropriately and may cause " + "certain SSL connections to fail. You can upgrade to a newer " + "version of Python to solve this. For more information, see " + "https://urllib3.readthedocs.io/en/1.26.x/advanced-usage.html" + "#ssl-warnings", + InsecurePlatformWarning, + ) + kwargs = { + "keyfile": self.keyfile, + "certfile": self.certfile, + "ca_certs": self.ca_certs, + "cert_reqs": self.verify_mode, + "ssl_version": self.protocol, + "server_side": server_side, + } + return wrap_socket(socket, ciphers=self.ciphers, **kwargs) + + +def assert_fingerprint(cert, fingerprint): + """ + Checks if given fingerprint matches the supplied certificate. + + :param cert: + Certificate as bytes object. + :param fingerprint: + Fingerprint as string of hexdigits, can be interspersed by colons. + """ + + fingerprint = fingerprint.replace(":", "").lower() + digest_length = len(fingerprint) + if digest_length not in HASHFUNC_MAP: + raise SSLError("Fingerprint of invalid length: {0}".format(fingerprint)) + hashfunc = HASHFUNC_MAP.get(digest_length) + if hashfunc is None: + raise SSLError( + "Hash function implementation unavailable for fingerprint length: {0}".format( + digest_length + ) + ) + + # We need encode() here for py32; works on py2 and p33. + fingerprint_bytes = unhexlify(fingerprint.encode()) + + cert_digest = hashfunc(cert).digest() + + if not _const_compare_digest(cert_digest, fingerprint_bytes): + raise SSLError( + 'Fingerprints did not match. Expected "{0}", got "{1}".'.format( + fingerprint, hexlify(cert_digest) + ) + ) + + +def resolve_cert_reqs(candidate): + """ + Resolves the argument to a numeric constant, which can be passed to + the wrap_socket function/method from the ssl module. + Defaults to :data:`ssl.CERT_REQUIRED`. + If given a string it is assumed to be the name of the constant in the + :mod:`ssl` module or its abbreviation. + (So you can specify `REQUIRED` instead of `CERT_REQUIRED`. + If it's neither `None` nor a string we assume it is already the numeric + constant which can directly be passed to wrap_socket. + """ + if candidate is None: + return CERT_REQUIRED + + if isinstance(candidate, str): + res = getattr(ssl, candidate, None) + if res is None: + res = getattr(ssl, "CERT_" + candidate) + return res + + return candidate + + +def resolve_ssl_version(candidate): + """ + like resolve_cert_reqs + """ + if candidate is None: + return PROTOCOL_TLS + + if isinstance(candidate, str): + res = getattr(ssl, candidate, None) + if res is None: + res = getattr(ssl, "PROTOCOL_" + candidate) + return res + + return candidate + + +def create_urllib3_context( + ssl_version=None, cert_reqs=None, options=None, ciphers=None +): + """All arguments have the same meaning as ``ssl_wrap_socket``. + + By default, this function does a lot of the same work that + ``ssl.create_default_context`` does on Python 3.4+. It: + + - Disables SSLv2, SSLv3, and compression + - Sets a restricted set of server ciphers + + If you wish to enable SSLv3, you can do:: + + from pip._vendor.urllib3.util import ssl_ + context = ssl_.create_urllib3_context() + context.options &= ~ssl_.OP_NO_SSLv3 + + You can do the same to enable compression (substituting ``COMPRESSION`` + for ``SSLv3`` in the last line above). + + :param ssl_version: + The desired protocol version to use. This will default to + PROTOCOL_SSLv23 which will negotiate the highest protocol that both + the server and your installation of OpenSSL support. + :param cert_reqs: + Whether to require the certificate verification. This defaults to + ``ssl.CERT_REQUIRED``. + :param options: + Specific OpenSSL options. These default to ``ssl.OP_NO_SSLv2``, + ``ssl.OP_NO_SSLv3``, ``ssl.OP_NO_COMPRESSION``, and ``ssl.OP_NO_TICKET``. + :param ciphers: + Which cipher suites to allow the server to select. + :returns: + Constructed SSLContext object with specified options + :rtype: SSLContext + """ + # PROTOCOL_TLS is deprecated in Python 3.10 + if not ssl_version or ssl_version == PROTOCOL_TLS: + ssl_version = PROTOCOL_TLS_CLIENT + + context = SSLContext(ssl_version) + + context.set_ciphers(ciphers or DEFAULT_CIPHERS) + + # Setting the default here, as we may have no ssl module on import + cert_reqs = ssl.CERT_REQUIRED if cert_reqs is None else cert_reqs + + if options is None: + options = 0 + # SSLv2 is easily broken and is considered harmful and dangerous + options |= OP_NO_SSLv2 + # SSLv3 has several problems and is now dangerous + options |= OP_NO_SSLv3 + # Disable compression to prevent CRIME attacks for OpenSSL 1.0+ + # (issue #309) + options |= OP_NO_COMPRESSION + # TLSv1.2 only. Unless set explicitly, do not request tickets. + # This may save some bandwidth on wire, and although the ticket is encrypted, + # there is a risk associated with it being on wire, + # if the server is not rotating its ticketing keys properly. + options |= OP_NO_TICKET + + context.options |= options + + # Enable post-handshake authentication for TLS 1.3, see GH #1634. PHA is + # necessary for conditional client cert authentication with TLS 1.3. + # The attribute is None for OpenSSL <= 1.1.0 or does not exist in older + # versions of Python. We only enable on Python 3.7.4+ or if certificate + # verification is enabled to work around Python issue #37428 + # See: https://bugs.python.org/issue37428 + if (cert_reqs == ssl.CERT_REQUIRED or sys.version_info >= (3, 7, 4)) and getattr( + context, "post_handshake_auth", None + ) is not None: + context.post_handshake_auth = True + + def disable_check_hostname(): + if ( + getattr(context, "check_hostname", None) is not None + ): # Platform-specific: Python 3.2 + # We do our own verification, including fingerprints and alternative + # hostnames. So disable it here + context.check_hostname = False + + # The order of the below lines setting verify_mode and check_hostname + # matter due to safe-guards SSLContext has to prevent an SSLContext with + # check_hostname=True, verify_mode=NONE/OPTIONAL. This is made even more + # complex because we don't know whether PROTOCOL_TLS_CLIENT will be used + # or not so we don't know the initial state of the freshly created SSLContext. + if cert_reqs == ssl.CERT_REQUIRED: + context.verify_mode = cert_reqs + disable_check_hostname() + else: + disable_check_hostname() + context.verify_mode = cert_reqs + + # Enable logging of TLS session keys via defacto standard environment variable + # 'SSLKEYLOGFILE', if the feature is available (Python 3.8+). Skip empty values. + if hasattr(context, "keylog_filename"): + sslkeylogfile = os.environ.get("SSLKEYLOGFILE") + if sslkeylogfile: + context.keylog_filename = sslkeylogfile + + return context + + +def ssl_wrap_socket( + sock, + keyfile=None, + certfile=None, + cert_reqs=None, + ca_certs=None, + server_hostname=None, + ssl_version=None, + ciphers=None, + ssl_context=None, + ca_cert_dir=None, + key_password=None, + ca_cert_data=None, + tls_in_tls=False, +): + """ + All arguments except for server_hostname, ssl_context, and ca_cert_dir have + the same meaning as they do when using :func:`ssl.wrap_socket`. + + :param server_hostname: + When SNI is supported, the expected hostname of the certificate + :param ssl_context: + A pre-made :class:`SSLContext` object. If none is provided, one will + be created using :func:`create_urllib3_context`. + :param ciphers: + A string of ciphers we wish the client to support. + :param ca_cert_dir: + A directory containing CA certificates in multiple separate files, as + supported by OpenSSL's -CApath flag or the capath argument to + SSLContext.load_verify_locations(). + :param key_password: + Optional password if the keyfile is encrypted. + :param ca_cert_data: + Optional string containing CA certificates in PEM format suitable for + passing as the cadata parameter to SSLContext.load_verify_locations() + :param tls_in_tls: + Use SSLTransport to wrap the existing socket. + """ + context = ssl_context + if context is None: + # Note: This branch of code and all the variables in it are no longer + # used by urllib3 itself. We should consider deprecating and removing + # this code. + context = create_urllib3_context(ssl_version, cert_reqs, ciphers=ciphers) + + if ca_certs or ca_cert_dir or ca_cert_data: + try: + context.load_verify_locations(ca_certs, ca_cert_dir, ca_cert_data) + except (IOError, OSError) as e: + raise SSLError(e) + + elif ssl_context is None and hasattr(context, "load_default_certs"): + # try to load OS default certs; works well on Windows (require Python3.4+) + context.load_default_certs() + + # Attempt to detect if we get the goofy behavior of the + # keyfile being encrypted and OpenSSL asking for the + # passphrase via the terminal and instead error out. + if keyfile and key_password is None and _is_key_file_encrypted(keyfile): + raise SSLError("Client private key is encrypted, password is required") + + if certfile: + if key_password is None: + context.load_cert_chain(certfile, keyfile) + else: + context.load_cert_chain(certfile, keyfile, key_password) + + try: + if hasattr(context, "set_alpn_protocols"): + context.set_alpn_protocols(ALPN_PROTOCOLS) + except NotImplementedError: # Defensive: in CI, we always have set_alpn_protocols + pass + + # If we detect server_hostname is an IP address then the SNI + # extension should not be used according to RFC3546 Section 3.1 + use_sni_hostname = server_hostname and not is_ipaddress(server_hostname) + # SecureTransport uses server_hostname in certificate verification. + send_sni = (use_sni_hostname and HAS_SNI) or ( + IS_SECURETRANSPORT and server_hostname + ) + # Do not warn the user if server_hostname is an invalid SNI hostname. + if not HAS_SNI and use_sni_hostname: + warnings.warn( + "An HTTPS request has been made, but the SNI (Server Name " + "Indication) extension to TLS is not available on this platform. " + "This may cause the server to present an incorrect TLS " + "certificate, which can cause validation failures. You can upgrade to " + "a newer version of Python to solve this. For more information, see " + "https://urllib3.readthedocs.io/en/1.26.x/advanced-usage.html" + "#ssl-warnings", + SNIMissingWarning, + ) + + if send_sni: + ssl_sock = _ssl_wrap_socket_impl( + sock, context, tls_in_tls, server_hostname=server_hostname + ) + else: + ssl_sock = _ssl_wrap_socket_impl(sock, context, tls_in_tls) + return ssl_sock + + +def is_ipaddress(hostname): + """Detects whether the hostname given is an IPv4 or IPv6 address. + Also detects IPv6 addresses with Zone IDs. + + :param str hostname: Hostname to examine. + :return: True if the hostname is an IP address, False otherwise. + """ + if not six.PY2 and isinstance(hostname, bytes): + # IDN A-label bytes are ASCII compatible. + hostname = hostname.decode("ascii") + return bool(IPV4_RE.match(hostname) or BRACELESS_IPV6_ADDRZ_RE.match(hostname)) + + +def _is_key_file_encrypted(key_file): + """Detects if a key file is encrypted or not.""" + with open(key_file, "r") as f: + for line in f: + # Look for Proc-Type: 4,ENCRYPTED + if "ENCRYPTED" in line: + return True + + return False + + +def _ssl_wrap_socket_impl(sock, ssl_context, tls_in_tls, server_hostname=None): + if tls_in_tls: + if not SSLTransport: + # Import error, ssl is not available. + raise ProxySchemeUnsupported( + "TLS in TLS requires support for the 'ssl' module" + ) + + SSLTransport._validate_ssl_context_for_tls_in_tls(ssl_context) + return SSLTransport(sock, ssl_context, server_hostname) + + if server_hostname: + return ssl_context.wrap_socket(sock, server_hostname=server_hostname) + else: + return ssl_context.wrap_socket(sock) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py new file mode 100644 index 0000000..1dd950c --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py @@ -0,0 +1,159 @@ +"""The match_hostname() function from Python 3.3.3, essential when using SSL.""" + +# Note: This file is under the PSF license as the code comes from the python +# stdlib. http://docs.python.org/3/license.html + +import re +import sys + +# ipaddress has been backported to 2.6+ in pypi. If it is installed on the +# system, use it to handle IPAddress ServerAltnames (this was added in +# python-3.5) otherwise only do DNS matching. This allows +# util.ssl_match_hostname to continue to be used in Python 2.7. +try: + import ipaddress +except ImportError: + ipaddress = None + +__version__ = "3.5.0.1" + + +class CertificateError(ValueError): + pass + + +def _dnsname_match(dn, hostname, max_wildcards=1): + """Matching according to RFC 6125, section 6.4.3 + + http://tools.ietf.org/html/rfc6125#section-6.4.3 + """ + pats = [] + if not dn: + return False + + # Ported from python3-syntax: + # leftmost, *remainder = dn.split(r'.') + parts = dn.split(r".") + leftmost = parts[0] + remainder = parts[1:] + + wildcards = leftmost.count("*") + if wildcards > max_wildcards: + # Issue #17980: avoid denials of service by refusing more + # than one wildcard per fragment. A survey of established + # policy among SSL implementations showed it to be a + # reasonable choice. + raise CertificateError( + "too many wildcards in certificate DNS name: " + repr(dn) + ) + + # speed up common case w/o wildcards + if not wildcards: + return dn.lower() == hostname.lower() + + # RFC 6125, section 6.4.3, subitem 1. + # The client SHOULD NOT attempt to match a presented identifier in which + # the wildcard character comprises a label other than the left-most label. + if leftmost == "*": + # When '*' is a fragment by itself, it matches a non-empty dotless + # fragment. + pats.append("[^.]+") + elif leftmost.startswith("xn--") or hostname.startswith("xn--"): + # RFC 6125, section 6.4.3, subitem 3. + # The client SHOULD NOT attempt to match a presented identifier + # where the wildcard character is embedded within an A-label or + # U-label of an internationalized domain name. + pats.append(re.escape(leftmost)) + else: + # Otherwise, '*' matches any dotless string, e.g. www* + pats.append(re.escape(leftmost).replace(r"\*", "[^.]*")) + + # add the remaining fragments, ignore any wildcards + for frag in remainder: + pats.append(re.escape(frag)) + + pat = re.compile(r"\A" + r"\.".join(pats) + r"\Z", re.IGNORECASE) + return pat.match(hostname) + + +def _to_unicode(obj): + if isinstance(obj, str) and sys.version_info < (3,): + # ignored flake8 # F821 to support python 2.7 function + obj = unicode(obj, encoding="ascii", errors="strict") # noqa: F821 + return obj + + +def _ipaddress_match(ipname, host_ip): + """Exact matching of IP addresses. + + RFC 6125 explicitly doesn't define an algorithm for this + (section 1.7.2 - "Out of Scope"). + """ + # OpenSSL may add a trailing newline to a subjectAltName's IP address + # Divergence from upstream: ipaddress can't handle byte str + ip = ipaddress.ip_address(_to_unicode(ipname).rstrip()) + return ip == host_ip + + +def match_hostname(cert, hostname): + """Verify that *cert* (in decoded format as returned by + SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 + rules are followed, but IP addresses are not accepted for *hostname*. + + CertificateError is raised on failure. On success, the function + returns nothing. + """ + if not cert: + raise ValueError( + "empty or no certificate, match_hostname needs a " + "SSL socket or SSL context with either " + "CERT_OPTIONAL or CERT_REQUIRED" + ) + try: + # Divergence from upstream: ipaddress can't handle byte str + host_ip = ipaddress.ip_address(_to_unicode(hostname)) + except (UnicodeError, ValueError): + # ValueError: Not an IP address (common case) + # UnicodeError: Divergence from upstream: Have to deal with ipaddress not taking + # byte strings. addresses should be all ascii, so we consider it not + # an ipaddress in this case + host_ip = None + except AttributeError: + # Divergence from upstream: Make ipaddress library optional + if ipaddress is None: + host_ip = None + else: # Defensive + raise + dnsnames = [] + san = cert.get("subjectAltName", ()) + for key, value in san: + if key == "DNS": + if host_ip is None and _dnsname_match(value, hostname): + return + dnsnames.append(value) + elif key == "IP Address": + if host_ip is not None and _ipaddress_match(value, host_ip): + return + dnsnames.append(value) + if not dnsnames: + # The subject is only checked when there is no dNSName entry + # in subjectAltName + for sub in cert.get("subject", ()): + for key, value in sub: + # XXX according to RFC 2818, the most specific Common Name + # must be used. + if key == "commonName": + if _dnsname_match(value, hostname): + return + dnsnames.append(value) + if len(dnsnames) > 1: + raise CertificateError( + "hostname %r " + "doesn't match either of %s" % (hostname, ", ".join(map(repr, dnsnames))) + ) + elif len(dnsnames) == 1: + raise CertificateError("hostname %r doesn't match %r" % (hostname, dnsnames[0])) + else: + raise CertificateError( + "no appropriate commonName or subjectAltName fields were found" + ) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/ssltransport.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/ssltransport.py new file mode 100644 index 0000000..4a7105d --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/ssltransport.py @@ -0,0 +1,221 @@ +import io +import socket +import ssl + +from ..exceptions import ProxySchemeUnsupported +from ..packages import six + +SSL_BLOCKSIZE = 16384 + + +class SSLTransport: + """ + The SSLTransport wraps an existing socket and establishes an SSL connection. + + Contrary to Python's implementation of SSLSocket, it allows you to chain + multiple TLS connections together. It's particularly useful if you need to + implement TLS within TLS. + + The class supports most of the socket API operations. + """ + + @staticmethod + def _validate_ssl_context_for_tls_in_tls(ssl_context): + """ + Raises a ProxySchemeUnsupported if the provided ssl_context can't be used + for TLS in TLS. + + The only requirement is that the ssl_context provides the 'wrap_bio' + methods. + """ + + if not hasattr(ssl_context, "wrap_bio"): + if six.PY2: + raise ProxySchemeUnsupported( + "TLS in TLS requires SSLContext.wrap_bio() which isn't " + "supported on Python 2" + ) + else: + raise ProxySchemeUnsupported( + "TLS in TLS requires SSLContext.wrap_bio() which isn't " + "available on non-native SSLContext" + ) + + def __init__( + self, socket, ssl_context, server_hostname=None, suppress_ragged_eofs=True + ): + """ + Create an SSLTransport around socket using the provided ssl_context. + """ + self.incoming = ssl.MemoryBIO() + self.outgoing = ssl.MemoryBIO() + + self.suppress_ragged_eofs = suppress_ragged_eofs + self.socket = socket + + self.sslobj = ssl_context.wrap_bio( + self.incoming, self.outgoing, server_hostname=server_hostname + ) + + # Perform initial handshake. + self._ssl_io_loop(self.sslobj.do_handshake) + + def __enter__(self): + return self + + def __exit__(self, *_): + self.close() + + def fileno(self): + return self.socket.fileno() + + def read(self, len=1024, buffer=None): + return self._wrap_ssl_read(len, buffer) + + def recv(self, len=1024, flags=0): + if flags != 0: + raise ValueError("non-zero flags not allowed in calls to recv") + return self._wrap_ssl_read(len) + + def recv_into(self, buffer, nbytes=None, flags=0): + if flags != 0: + raise ValueError("non-zero flags not allowed in calls to recv_into") + if buffer and (nbytes is None): + nbytes = len(buffer) + elif nbytes is None: + nbytes = 1024 + return self.read(nbytes, buffer) + + def sendall(self, data, flags=0): + if flags != 0: + raise ValueError("non-zero flags not allowed in calls to sendall") + count = 0 + with memoryview(data) as view, view.cast("B") as byte_view: + amount = len(byte_view) + while count < amount: + v = self.send(byte_view[count:]) + count += v + + def send(self, data, flags=0): + if flags != 0: + raise ValueError("non-zero flags not allowed in calls to send") + response = self._ssl_io_loop(self.sslobj.write, data) + return response + + def makefile( + self, mode="r", buffering=None, encoding=None, errors=None, newline=None + ): + """ + Python's httpclient uses makefile and buffered io when reading HTTP + messages and we need to support it. + + This is unfortunately a copy and paste of socket.py makefile with small + changes to point to the socket directly. + """ + if not set(mode) <= {"r", "w", "b"}: + raise ValueError("invalid mode %r (only r, w, b allowed)" % (mode,)) + + writing = "w" in mode + reading = "r" in mode or not writing + assert reading or writing + binary = "b" in mode + rawmode = "" + if reading: + rawmode += "r" + if writing: + rawmode += "w" + raw = socket.SocketIO(self, rawmode) + self.socket._io_refs += 1 + if buffering is None: + buffering = -1 + if buffering < 0: + buffering = io.DEFAULT_BUFFER_SIZE + if buffering == 0: + if not binary: + raise ValueError("unbuffered streams must be binary") + return raw + if reading and writing: + buffer = io.BufferedRWPair(raw, raw, buffering) + elif reading: + buffer = io.BufferedReader(raw, buffering) + else: + assert writing + buffer = io.BufferedWriter(raw, buffering) + if binary: + return buffer + text = io.TextIOWrapper(buffer, encoding, errors, newline) + text.mode = mode + return text + + def unwrap(self): + self._ssl_io_loop(self.sslobj.unwrap) + + def close(self): + self.socket.close() + + def getpeercert(self, binary_form=False): + return self.sslobj.getpeercert(binary_form) + + def version(self): + return self.sslobj.version() + + def cipher(self): + return self.sslobj.cipher() + + def selected_alpn_protocol(self): + return self.sslobj.selected_alpn_protocol() + + def selected_npn_protocol(self): + return self.sslobj.selected_npn_protocol() + + def shared_ciphers(self): + return self.sslobj.shared_ciphers() + + def compression(self): + return self.sslobj.compression() + + def settimeout(self, value): + self.socket.settimeout(value) + + def gettimeout(self): + return self.socket.gettimeout() + + def _decref_socketios(self): + self.socket._decref_socketios() + + def _wrap_ssl_read(self, len, buffer=None): + try: + return self._ssl_io_loop(self.sslobj.read, len, buffer) + except ssl.SSLError as e: + if e.errno == ssl.SSL_ERROR_EOF and self.suppress_ragged_eofs: + return 0 # eof, return 0. + else: + raise + + def _ssl_io_loop(self, func, *args): + """Performs an I/O loop between incoming/outgoing and the socket.""" + should_loop = True + ret = None + + while should_loop: + errno = None + try: + ret = func(*args) + except ssl.SSLError as e: + if e.errno not in (ssl.SSL_ERROR_WANT_READ, ssl.SSL_ERROR_WANT_WRITE): + # WANT_READ, and WANT_WRITE are expected, others are not. + raise e + errno = e.errno + + buf = self.outgoing.read() + self.socket.sendall(buf) + + if errno is None: + should_loop = False + elif errno == ssl.SSL_ERROR_WANT_READ: + buf = self.socket.recv(SSL_BLOCKSIZE) + if buf: + self.incoming.write(buf) + else: + self.incoming.write_eof() + return ret diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/timeout.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/timeout.py new file mode 100644 index 0000000..78e18a6 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/timeout.py @@ -0,0 +1,271 @@ +from __future__ import absolute_import + +import time + +# The default socket timeout, used by httplib to indicate that no timeout was; specified by the user +from socket import _GLOBAL_DEFAULT_TIMEOUT, getdefaulttimeout + +from ..exceptions import TimeoutStateError + +# A sentinel value to indicate that no timeout was specified by the user in +# urllib3 +_Default = object() + + +# Use time.monotonic if available. +current_time = getattr(time, "monotonic", time.time) + + +class Timeout(object): + """Timeout configuration. + + Timeouts can be defined as a default for a pool: + + .. code-block:: python + + timeout = Timeout(connect=2.0, read=7.0) + http = PoolManager(timeout=timeout) + response = http.request('GET', 'http://example.com/') + + Or per-request (which overrides the default for the pool): + + .. code-block:: python + + response = http.request('GET', 'http://example.com/', timeout=Timeout(10)) + + Timeouts can be disabled by setting all the parameters to ``None``: + + .. code-block:: python + + no_timeout = Timeout(connect=None, read=None) + response = http.request('GET', 'http://example.com/, timeout=no_timeout) + + + :param total: + This combines the connect and read timeouts into one; the read timeout + will be set to the time leftover from the connect attempt. In the + event that both a connect timeout and a total are specified, or a read + timeout and a total are specified, the shorter timeout will be applied. + + Defaults to None. + + :type total: int, float, or None + + :param connect: + The maximum amount of time (in seconds) to wait for a connection + attempt to a server to succeed. Omitting the parameter will default the + connect timeout to the system default, probably `the global default + timeout in socket.py + `_. + None will set an infinite timeout for connection attempts. + + :type connect: int, float, or None + + :param read: + The maximum amount of time (in seconds) to wait between consecutive + read operations for a response from the server. Omitting the parameter + will default the read timeout to the system default, probably `the + global default timeout in socket.py + `_. + None will set an infinite timeout. + + :type read: int, float, or None + + .. note:: + + Many factors can affect the total amount of time for urllib3 to return + an HTTP response. + + For example, Python's DNS resolver does not obey the timeout specified + on the socket. Other factors that can affect total request time include + high CPU load, high swap, the program running at a low priority level, + or other behaviors. + + In addition, the read and total timeouts only measure the time between + read operations on the socket connecting the client and the server, + not the total amount of time for the request to return a complete + response. For most requests, the timeout is raised because the server + has not sent the first byte in the specified time. This is not always + the case; if a server streams one byte every fifteen seconds, a timeout + of 20 seconds will not trigger, even though the request will take + several minutes to complete. + + If your goal is to cut off any request after a set amount of wall clock + time, consider having a second "watcher" thread to cut off a slow + request. + """ + + #: A sentinel object representing the default timeout value + DEFAULT_TIMEOUT = _GLOBAL_DEFAULT_TIMEOUT + + def __init__(self, total=None, connect=_Default, read=_Default): + self._connect = self._validate_timeout(connect, "connect") + self._read = self._validate_timeout(read, "read") + self.total = self._validate_timeout(total, "total") + self._start_connect = None + + def __repr__(self): + return "%s(connect=%r, read=%r, total=%r)" % ( + type(self).__name__, + self._connect, + self._read, + self.total, + ) + + # __str__ provided for backwards compatibility + __str__ = __repr__ + + @classmethod + def resolve_default_timeout(cls, timeout): + return getdefaulttimeout() if timeout is cls.DEFAULT_TIMEOUT else timeout + + @classmethod + def _validate_timeout(cls, value, name): + """Check that a timeout attribute is valid. + + :param value: The timeout value to validate + :param name: The name of the timeout attribute to validate. This is + used to specify in error messages. + :return: The validated and casted version of the given value. + :raises ValueError: If it is a numeric value less than or equal to + zero, or the type is not an integer, float, or None. + """ + if value is _Default: + return cls.DEFAULT_TIMEOUT + + if value is None or value is cls.DEFAULT_TIMEOUT: + return value + + if isinstance(value, bool): + raise ValueError( + "Timeout cannot be a boolean value. It must " + "be an int, float or None." + ) + try: + float(value) + except (TypeError, ValueError): + raise ValueError( + "Timeout value %s was %s, but it must be an " + "int, float or None." % (name, value) + ) + + try: + if value <= 0: + raise ValueError( + "Attempted to set %s timeout to %s, but the " + "timeout cannot be set to a value less " + "than or equal to 0." % (name, value) + ) + except TypeError: + # Python 3 + raise ValueError( + "Timeout value %s was %s, but it must be an " + "int, float or None." % (name, value) + ) + + return value + + @classmethod + def from_float(cls, timeout): + """Create a new Timeout from a legacy timeout value. + + The timeout value used by httplib.py sets the same timeout on the + connect(), and recv() socket requests. This creates a :class:`Timeout` + object that sets the individual timeouts to the ``timeout`` value + passed to this function. + + :param timeout: The legacy timeout value. + :type timeout: integer, float, sentinel default object, or None + :return: Timeout object + :rtype: :class:`Timeout` + """ + return Timeout(read=timeout, connect=timeout) + + def clone(self): + """Create a copy of the timeout object + + Timeout properties are stored per-pool but each request needs a fresh + Timeout object to ensure each one has its own start/stop configured. + + :return: a copy of the timeout object + :rtype: :class:`Timeout` + """ + # We can't use copy.deepcopy because that will also create a new object + # for _GLOBAL_DEFAULT_TIMEOUT, which socket.py uses as a sentinel to + # detect the user default. + return Timeout(connect=self._connect, read=self._read, total=self.total) + + def start_connect(self): + """Start the timeout clock, used during a connect() attempt + + :raises urllib3.exceptions.TimeoutStateError: if you attempt + to start a timer that has been started already. + """ + if self._start_connect is not None: + raise TimeoutStateError("Timeout timer has already been started.") + self._start_connect = current_time() + return self._start_connect + + def get_connect_duration(self): + """Gets the time elapsed since the call to :meth:`start_connect`. + + :return: Elapsed time in seconds. + :rtype: float + :raises urllib3.exceptions.TimeoutStateError: if you attempt + to get duration for a timer that hasn't been started. + """ + if self._start_connect is None: + raise TimeoutStateError( + "Can't get connect duration for timer that has not started." + ) + return current_time() - self._start_connect + + @property + def connect_timeout(self): + """Get the value to use when setting a connection timeout. + + This will be a positive float or integer, the value None + (never timeout), or the default system timeout. + + :return: Connect timeout. + :rtype: int, float, :attr:`Timeout.DEFAULT_TIMEOUT` or None + """ + if self.total is None: + return self._connect + + if self._connect is None or self._connect is self.DEFAULT_TIMEOUT: + return self.total + + return min(self._connect, self.total) + + @property + def read_timeout(self): + """Get the value for the read timeout. + + This assumes some time has elapsed in the connection timeout and + computes the read timeout appropriately. + + If self.total is set, the read timeout is dependent on the amount of + time taken by the connect timeout. If the connection time has not been + established, a :exc:`~urllib3.exceptions.TimeoutStateError` will be + raised. + + :return: Value to use for the read timeout. + :rtype: int, float, :attr:`Timeout.DEFAULT_TIMEOUT` or None + :raises urllib3.exceptions.TimeoutStateError: If :meth:`start_connect` + has not yet been called on this object. + """ + if ( + self.total is not None + and self.total is not self.DEFAULT_TIMEOUT + and self._read is not None + and self._read is not self.DEFAULT_TIMEOUT + ): + # In case the connect timeout has not yet been established. + if self._start_connect is None: + return self._read + return max(0, min(self.total - self.get_connect_duration(), self._read)) + elif self.total is not None and self.total is not self.DEFAULT_TIMEOUT: + return max(0, self.total - self.get_connect_duration()) + else: + return self._read diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/url.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/url.py new file mode 100644 index 0000000..a960b2f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/url.py @@ -0,0 +1,435 @@ +from __future__ import absolute_import + +import re +from collections import namedtuple + +from ..exceptions import LocationParseError +from ..packages import six + +url_attrs = ["scheme", "auth", "host", "port", "path", "query", "fragment"] + +# We only want to normalize urls with an HTTP(S) scheme. +# urllib3 infers URLs without a scheme (None) to be http. +NORMALIZABLE_SCHEMES = ("http", "https", None) + +# Almost all of these patterns were derived from the +# 'rfc3986' module: https://github.com/python-hyper/rfc3986 +PERCENT_RE = re.compile(r"%[a-fA-F0-9]{2}") +SCHEME_RE = re.compile(r"^(?:[a-zA-Z][a-zA-Z0-9+-]*:|/)") +URI_RE = re.compile( + r"^(?:([a-zA-Z][a-zA-Z0-9+.-]*):)?" + r"(?://([^\\/?#]*))?" + r"([^?#]*)" + r"(?:\?([^#]*))?" + r"(?:#(.*))?$", + re.UNICODE | re.DOTALL, +) + +IPV4_PAT = r"(?:[0-9]{1,3}\.){3}[0-9]{1,3}" +HEX_PAT = "[0-9A-Fa-f]{1,4}" +LS32_PAT = "(?:{hex}:{hex}|{ipv4})".format(hex=HEX_PAT, ipv4=IPV4_PAT) +_subs = {"hex": HEX_PAT, "ls32": LS32_PAT} +_variations = [ + # 6( h16 ":" ) ls32 + "(?:%(hex)s:){6}%(ls32)s", + # "::" 5( h16 ":" ) ls32 + "::(?:%(hex)s:){5}%(ls32)s", + # [ h16 ] "::" 4( h16 ":" ) ls32 + "(?:%(hex)s)?::(?:%(hex)s:){4}%(ls32)s", + # [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32 + "(?:(?:%(hex)s:)?%(hex)s)?::(?:%(hex)s:){3}%(ls32)s", + # [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32 + "(?:(?:%(hex)s:){0,2}%(hex)s)?::(?:%(hex)s:){2}%(ls32)s", + # [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32 + "(?:(?:%(hex)s:){0,3}%(hex)s)?::%(hex)s:%(ls32)s", + # [ *4( h16 ":" ) h16 ] "::" ls32 + "(?:(?:%(hex)s:){0,4}%(hex)s)?::%(ls32)s", + # [ *5( h16 ":" ) h16 ] "::" h16 + "(?:(?:%(hex)s:){0,5}%(hex)s)?::%(hex)s", + # [ *6( h16 ":" ) h16 ] "::" + "(?:(?:%(hex)s:){0,6}%(hex)s)?::", +] + +UNRESERVED_PAT = r"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._\-~" +IPV6_PAT = "(?:" + "|".join([x % _subs for x in _variations]) + ")" +ZONE_ID_PAT = "(?:%25|%)(?:[" + UNRESERVED_PAT + "]|%[a-fA-F0-9]{2})+" +IPV6_ADDRZ_PAT = r"\[" + IPV6_PAT + r"(?:" + ZONE_ID_PAT + r")?\]" +REG_NAME_PAT = r"(?:[^\[\]%:/?#]|%[a-fA-F0-9]{2})*" +TARGET_RE = re.compile(r"^(/[^?#]*)(?:\?([^#]*))?(?:#.*)?$") + +IPV4_RE = re.compile("^" + IPV4_PAT + "$") +IPV6_RE = re.compile("^" + IPV6_PAT + "$") +IPV6_ADDRZ_RE = re.compile("^" + IPV6_ADDRZ_PAT + "$") +BRACELESS_IPV6_ADDRZ_RE = re.compile("^" + IPV6_ADDRZ_PAT[2:-2] + "$") +ZONE_ID_RE = re.compile("(" + ZONE_ID_PAT + r")\]$") + +_HOST_PORT_PAT = ("^(%s|%s|%s)(?::0*?(|0|[1-9][0-9]{0,4}))?$") % ( + REG_NAME_PAT, + IPV4_PAT, + IPV6_ADDRZ_PAT, +) +_HOST_PORT_RE = re.compile(_HOST_PORT_PAT, re.UNICODE | re.DOTALL) + +UNRESERVED_CHARS = set( + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-~" +) +SUB_DELIM_CHARS = set("!$&'()*+,;=") +USERINFO_CHARS = UNRESERVED_CHARS | SUB_DELIM_CHARS | {":"} +PATH_CHARS = USERINFO_CHARS | {"@", "/"} +QUERY_CHARS = FRAGMENT_CHARS = PATH_CHARS | {"?"} + + +class Url(namedtuple("Url", url_attrs)): + """ + Data structure for representing an HTTP URL. Used as a return value for + :func:`parse_url`. Both the scheme and host are normalized as they are + both case-insensitive according to RFC 3986. + """ + + __slots__ = () + + def __new__( + cls, + scheme=None, + auth=None, + host=None, + port=None, + path=None, + query=None, + fragment=None, + ): + if path and not path.startswith("/"): + path = "/" + path + if scheme is not None: + scheme = scheme.lower() + return super(Url, cls).__new__( + cls, scheme, auth, host, port, path, query, fragment + ) + + @property + def hostname(self): + """For backwards-compatibility with urlparse. We're nice like that.""" + return self.host + + @property + def request_uri(self): + """Absolute path including the query string.""" + uri = self.path or "/" + + if self.query is not None: + uri += "?" + self.query + + return uri + + @property + def netloc(self): + """Network location including host and port""" + if self.port: + return "%s:%d" % (self.host, self.port) + return self.host + + @property + def url(self): + """ + Convert self into a url + + This function should more or less round-trip with :func:`.parse_url`. The + returned url may not be exactly the same as the url inputted to + :func:`.parse_url`, but it should be equivalent by the RFC (e.g., urls + with a blank port will have : removed). + + Example: :: + + >>> U = parse_url('http://google.com/mail/') + >>> U.url + 'http://google.com/mail/' + >>> Url('http', 'username:password', 'host.com', 80, + ... '/path', 'query', 'fragment').url + 'http://username:password@host.com:80/path?query#fragment' + """ + scheme, auth, host, port, path, query, fragment = self + url = u"" + + # We use "is not None" we want things to happen with empty strings (or 0 port) + if scheme is not None: + url += scheme + u"://" + if auth is not None: + url += auth + u"@" + if host is not None: + url += host + if port is not None: + url += u":" + str(port) + if path is not None: + url += path + if query is not None: + url += u"?" + query + if fragment is not None: + url += u"#" + fragment + + return url + + def __str__(self): + return self.url + + +def split_first(s, delims): + """ + .. deprecated:: 1.25 + + Given a string and an iterable of delimiters, split on the first found + delimiter. Return two split parts and the matched delimiter. + + If not found, then the first part is the full input string. + + Example:: + + >>> split_first('foo/bar?baz', '?/=') + ('foo', 'bar?baz', '/') + >>> split_first('foo/bar?baz', '123') + ('foo/bar?baz', '', None) + + Scales linearly with number of delims. Not ideal for large number of delims. + """ + min_idx = None + min_delim = None + for d in delims: + idx = s.find(d) + if idx < 0: + continue + + if min_idx is None or idx < min_idx: + min_idx = idx + min_delim = d + + if min_idx is None or min_idx < 0: + return s, "", None + + return s[:min_idx], s[min_idx + 1 :], min_delim + + +def _encode_invalid_chars(component, allowed_chars, encoding="utf-8"): + """Percent-encodes a URI component without reapplying + onto an already percent-encoded component. + """ + if component is None: + return component + + component = six.ensure_text(component) + + # Normalize existing percent-encoded bytes. + # Try to see if the component we're encoding is already percent-encoded + # so we can skip all '%' characters but still encode all others. + component, percent_encodings = PERCENT_RE.subn( + lambda match: match.group(0).upper(), component + ) + + uri_bytes = component.encode("utf-8", "surrogatepass") + is_percent_encoded = percent_encodings == uri_bytes.count(b"%") + encoded_component = bytearray() + + for i in range(0, len(uri_bytes)): + # Will return a single character bytestring on both Python 2 & 3 + byte = uri_bytes[i : i + 1] + byte_ord = ord(byte) + if (is_percent_encoded and byte == b"%") or ( + byte_ord < 128 and byte.decode() in allowed_chars + ): + encoded_component += byte + continue + encoded_component.extend(b"%" + (hex(byte_ord)[2:].encode().zfill(2).upper())) + + return encoded_component.decode(encoding) + + +def _remove_path_dot_segments(path): + # See http://tools.ietf.org/html/rfc3986#section-5.2.4 for pseudo-code + segments = path.split("/") # Turn the path into a list of segments + output = [] # Initialize the variable to use to store output + + for segment in segments: + # '.' is the current directory, so ignore it, it is superfluous + if segment == ".": + continue + # Anything other than '..', should be appended to the output + elif segment != "..": + output.append(segment) + # In this case segment == '..', if we can, we should pop the last + # element + elif output: + output.pop() + + # If the path starts with '/' and the output is empty or the first string + # is non-empty + if path.startswith("/") and (not output or output[0]): + output.insert(0, "") + + # If the path starts with '/.' or '/..' ensure we add one more empty + # string to add a trailing '/' + if path.endswith(("/.", "/..")): + output.append("") + + return "/".join(output) + + +def _normalize_host(host, scheme): + if host: + if isinstance(host, six.binary_type): + host = six.ensure_str(host) + + if scheme in NORMALIZABLE_SCHEMES: + is_ipv6 = IPV6_ADDRZ_RE.match(host) + if is_ipv6: + # IPv6 hosts of the form 'a::b%zone' are encoded in a URL as + # such per RFC 6874: 'a::b%25zone'. Unquote the ZoneID + # separator as necessary to return a valid RFC 4007 scoped IP. + match = ZONE_ID_RE.search(host) + if match: + start, end = match.span(1) + zone_id = host[start:end] + + if zone_id.startswith("%25") and zone_id != "%25": + zone_id = zone_id[3:] + else: + zone_id = zone_id[1:] + zone_id = "%" + _encode_invalid_chars(zone_id, UNRESERVED_CHARS) + return host[:start].lower() + zone_id + host[end:] + else: + return host.lower() + elif not IPV4_RE.match(host): + return six.ensure_str( + b".".join([_idna_encode(label) for label in host.split(".")]) + ) + return host + + +def _idna_encode(name): + if name and any(ord(x) >= 128 for x in name): + try: + from pip._vendor import idna + except ImportError: + six.raise_from( + LocationParseError("Unable to parse URL without the 'idna' module"), + None, + ) + try: + return idna.encode(name.lower(), strict=True, std3_rules=True) + except idna.IDNAError: + six.raise_from( + LocationParseError(u"Name '%s' is not a valid IDNA label" % name), None + ) + return name.lower().encode("ascii") + + +def _encode_target(target): + """Percent-encodes a request target so that there are no invalid characters""" + path, query = TARGET_RE.match(target).groups() + target = _encode_invalid_chars(path, PATH_CHARS) + query = _encode_invalid_chars(query, QUERY_CHARS) + if query is not None: + target += "?" + query + return target + + +def parse_url(url): + """ + Given a url, return a parsed :class:`.Url` namedtuple. Best-effort is + performed to parse incomplete urls. Fields not provided will be None. + This parser is RFC 3986 and RFC 6874 compliant. + + The parser logic and helper functions are based heavily on + work done in the ``rfc3986`` module. + + :param str url: URL to parse into a :class:`.Url` namedtuple. + + Partly backwards-compatible with :mod:`urlparse`. + + Example:: + + >>> parse_url('http://google.com/mail/') + Url(scheme='http', host='google.com', port=None, path='/mail/', ...) + >>> parse_url('google.com:80') + Url(scheme=None, host='google.com', port=80, path=None, ...) + >>> parse_url('/foo?bar') + Url(scheme=None, host=None, port=None, path='/foo', query='bar', ...) + """ + if not url: + # Empty + return Url() + + source_url = url + if not SCHEME_RE.search(url): + url = "//" + url + + try: + scheme, authority, path, query, fragment = URI_RE.match(url).groups() + normalize_uri = scheme is None or scheme.lower() in NORMALIZABLE_SCHEMES + + if scheme: + scheme = scheme.lower() + + if authority: + auth, _, host_port = authority.rpartition("@") + auth = auth or None + host, port = _HOST_PORT_RE.match(host_port).groups() + if auth and normalize_uri: + auth = _encode_invalid_chars(auth, USERINFO_CHARS) + if port == "": + port = None + else: + auth, host, port = None, None, None + + if port is not None: + port = int(port) + if not (0 <= port <= 65535): + raise LocationParseError(url) + + host = _normalize_host(host, scheme) + + if normalize_uri and path: + path = _remove_path_dot_segments(path) + path = _encode_invalid_chars(path, PATH_CHARS) + if normalize_uri and query: + query = _encode_invalid_chars(query, QUERY_CHARS) + if normalize_uri and fragment: + fragment = _encode_invalid_chars(fragment, FRAGMENT_CHARS) + + except (ValueError, AttributeError): + return six.raise_from(LocationParseError(source_url), None) + + # For the sake of backwards compatibility we put empty + # string values for path if there are any defined values + # beyond the path in the URL. + # TODO: Remove this when we break backwards compatibility. + if not path: + if query is not None or fragment is not None: + path = "" + else: + path = None + + # Ensure that each part of the URL is a `str` for + # backwards compatibility. + if isinstance(url, six.text_type): + ensure_func = six.ensure_text + else: + ensure_func = six.ensure_str + + def ensure_type(x): + return x if x is None else ensure_func(x) + + return Url( + scheme=ensure_type(scheme), + auth=ensure_type(auth), + host=ensure_type(host), + port=port, + path=ensure_type(path), + query=ensure_type(query), + fragment=ensure_type(fragment), + ) + + +def get_host(url): + """ + Deprecated. Use :func:`parse_url` instead. + """ + p = parse_url(url) + return p.scheme or "http", p.hostname, p.port diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/wait.py b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/wait.py new file mode 100644 index 0000000..21b4590 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/urllib3/util/wait.py @@ -0,0 +1,152 @@ +import errno +import select +import sys +from functools import partial + +try: + from time import monotonic +except ImportError: + from time import time as monotonic + +__all__ = ["NoWayToWaitForSocketError", "wait_for_read", "wait_for_write"] + + +class NoWayToWaitForSocketError(Exception): + pass + + +# How should we wait on sockets? +# +# There are two types of APIs you can use for waiting on sockets: the fancy +# modern stateful APIs like epoll/kqueue, and the older stateless APIs like +# select/poll. The stateful APIs are more efficient when you have a lots of +# sockets to keep track of, because you can set them up once and then use them +# lots of times. But we only ever want to wait on a single socket at a time +# and don't want to keep track of state, so the stateless APIs are actually +# more efficient. So we want to use select() or poll(). +# +# Now, how do we choose between select() and poll()? On traditional Unixes, +# select() has a strange calling convention that makes it slow, or fail +# altogether, for high-numbered file descriptors. The point of poll() is to fix +# that, so on Unixes, we prefer poll(). +# +# On Windows, there is no poll() (or at least Python doesn't provide a wrapper +# for it), but that's OK, because on Windows, select() doesn't have this +# strange calling convention; plain select() works fine. +# +# So: on Windows we use select(), and everywhere else we use poll(). We also +# fall back to select() in case poll() is somehow broken or missing. + +if sys.version_info >= (3, 5): + # Modern Python, that retries syscalls by default + def _retry_on_intr(fn, timeout): + return fn(timeout) + +else: + # Old and broken Pythons. + def _retry_on_intr(fn, timeout): + if timeout is None: + deadline = float("inf") + else: + deadline = monotonic() + timeout + + while True: + try: + return fn(timeout) + # OSError for 3 <= pyver < 3.5, select.error for pyver <= 2.7 + except (OSError, select.error) as e: + # 'e.args[0]' incantation works for both OSError and select.error + if e.args[0] != errno.EINTR: + raise + else: + timeout = deadline - monotonic() + if timeout < 0: + timeout = 0 + if timeout == float("inf"): + timeout = None + continue + + +def select_wait_for_socket(sock, read=False, write=False, timeout=None): + if not read and not write: + raise RuntimeError("must specify at least one of read=True, write=True") + rcheck = [] + wcheck = [] + if read: + rcheck.append(sock) + if write: + wcheck.append(sock) + # When doing a non-blocking connect, most systems signal success by + # marking the socket writable. Windows, though, signals success by marked + # it as "exceptional". We paper over the difference by checking the write + # sockets for both conditions. (The stdlib selectors module does the same + # thing.) + fn = partial(select.select, rcheck, wcheck, wcheck) + rready, wready, xready = _retry_on_intr(fn, timeout) + return bool(rready or wready or xready) + + +def poll_wait_for_socket(sock, read=False, write=False, timeout=None): + if not read and not write: + raise RuntimeError("must specify at least one of read=True, write=True") + mask = 0 + if read: + mask |= select.POLLIN + if write: + mask |= select.POLLOUT + poll_obj = select.poll() + poll_obj.register(sock, mask) + + # For some reason, poll() takes timeout in milliseconds + def do_poll(t): + if t is not None: + t *= 1000 + return poll_obj.poll(t) + + return bool(_retry_on_intr(do_poll, timeout)) + + +def null_wait_for_socket(*args, **kwargs): + raise NoWayToWaitForSocketError("no select-equivalent available") + + +def _have_working_poll(): + # Apparently some systems have a select.poll that fails as soon as you try + # to use it, either due to strange configuration or broken monkeypatching + # from libraries like eventlet/greenlet. + try: + poll_obj = select.poll() + _retry_on_intr(poll_obj.poll, 0) + except (AttributeError, OSError): + return False + else: + return True + + +def wait_for_socket(*args, **kwargs): + # We delay choosing which implementation to use until the first time we're + # called. We could do it at import time, but then we might make the wrong + # decision if someone goes wild with monkeypatching select.poll after + # we're imported. + global wait_for_socket + if _have_working_poll(): + wait_for_socket = poll_wait_for_socket + elif hasattr(select, "select"): + wait_for_socket = select_wait_for_socket + else: # Platform-specific: Appengine. + wait_for_socket = null_wait_for_socket + return wait_for_socket(*args, **kwargs) + + +def wait_for_read(sock, timeout=None): + """Waits for reading to be available on a given socket. + Returns True if the socket is readable, or False if the timeout expired. + """ + return wait_for_socket(sock, read=True, timeout=timeout) + + +def wait_for_write(sock, timeout=None): + """Waits for writing to be available on a given socket. + Returns True if the socket is readable, or False if the timeout expired. + """ + return wait_for_socket(sock, write=True, timeout=timeout) diff --git a/backend/.venv/Lib/site-packages/pip/_vendor/vendor.txt b/backend/.venv/Lib/site-packages/pip/_vendor/vendor.txt new file mode 100644 index 0000000..2ba053a --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/_vendor/vendor.txt @@ -0,0 +1,18 @@ +CacheControl==0.14.0 +distlib==0.3.9 +distro==1.9.0 +msgpack==1.0.8 +packaging==24.1 +platformdirs==4.2.2 +pyproject-hooks==1.0.0 +requests==2.32.3 + certifi==2024.8.30 + idna==3.7 + urllib3==1.26.20 +rich==13.7.1 + pygments==2.18.0 + typing_extensions==4.12.2 +resolvelib==1.0.1 +setuptools==70.3.0 +tomli==2.0.1 +truststore==0.10.0 diff --git a/backend/.venv/Lib/site-packages/pip/py.typed b/backend/.venv/Lib/site-packages/pip/py.typed new file mode 100644 index 0000000..493b53e --- /dev/null +++ b/backend/.venv/Lib/site-packages/pip/py.typed @@ -0,0 +1,4 @@ +pip is a command line program. While it is implemented in Python, and so is +available for import, you must not use pip's internal APIs in this way. Typing +information is provided as a convenience only and is not a guarantee. Expect +unannounced changes to the API and types in releases. diff --git a/backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/INSTALLER b/backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/LICENSE.txt b/backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/LICENSE.txt new file mode 100644 index 0000000..0a04128 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/METADATA b/backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/METADATA new file mode 100644 index 0000000..ba824e4 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/METADATA @@ -0,0 +1,109 @@ +Metadata-Version: 2.1 +Name: psycopg +Version: 3.2.3 +Summary: PostgreSQL database adapter for Python +Home-page: https://psycopg.org/psycopg3/ +Author: Daniele Varrazzo +Author-email: daniele.varrazzo@gmail.com +License: GNU Lesser General Public License v3 (LGPLv3) +Project-URL: Homepage, https://psycopg.org/ +Project-URL: Documentation, https://psycopg.org/psycopg3/docs/ +Project-URL: Changes, https://psycopg.org/psycopg3/docs/news.html +Project-URL: Code, https://github.com/psycopg/psycopg +Project-URL: Issue Tracker, https://github.com/psycopg/psycopg/issues +Project-URL: Download, https://pypi.org/project/psycopg/ +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3) +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Operating System :: Microsoft :: Windows +Classifier: Operating System :: POSIX +Classifier: Programming Language :: Python :: 3 +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 :: Database +Classifier: Topic :: Database :: Front-Ends +Classifier: Topic :: Software Development +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Requires-Python: >=3.8 +Description-Content-Type: text/x-rst +License-File: LICENSE.txt +Requires-Dist: typing-extensions>=4.6; python_version < "3.13" +Requires-Dist: backports.zoneinfo>=0.2.0; python_version < "3.9" +Requires-Dist: tzdata; sys_platform == "win32" +Provides-Extra: binary +Requires-Dist: psycopg-binary==3.2.3; implementation_name != "pypy" and extra == "binary" +Provides-Extra: c +Requires-Dist: psycopg-c==3.2.3; implementation_name != "pypy" and extra == "c" +Provides-Extra: dev +Requires-Dist: ast-comments>=1.1.2; extra == "dev" +Requires-Dist: black>=24.1.0; extra == "dev" +Requires-Dist: codespell>=2.2; extra == "dev" +Requires-Dist: dnspython>=2.1; extra == "dev" +Requires-Dist: flake8>=4.0; extra == "dev" +Requires-Dist: mypy>=1.11; extra == "dev" +Requires-Dist: types-setuptools>=57.4; extra == "dev" +Requires-Dist: wheel>=0.37; extra == "dev" +Provides-Extra: docs +Requires-Dist: Sphinx>=5.0; extra == "docs" +Requires-Dist: furo==2022.6.21; extra == "docs" +Requires-Dist: sphinx-autobuild>=2021.3.14; extra == "docs" +Requires-Dist: sphinx-autodoc-typehints>=1.12; extra == "docs" +Provides-Extra: pool +Requires-Dist: psycopg-pool; extra == "pool" +Provides-Extra: test +Requires-Dist: anyio>=4.0; extra == "test" +Requires-Dist: mypy>=1.11; extra == "test" +Requires-Dist: pproxy>=2.7; extra == "test" +Requires-Dist: pytest>=6.2.5; extra == "test" +Requires-Dist: pytest-cov>=3.0; extra == "test" +Requires-Dist: pytest-randomly>=3.5; extra == "test" + +Psycopg 3: PostgreSQL database adapter for Python +================================================= + +Psycopg 3 is a modern implementation of a PostgreSQL adapter for Python. + +This distribution contains the pure Python package ``psycopg``. + +.. Note:: + + Despite the lack of number in the package name, this package is the + successor of psycopg2_. + + Please use the psycopg2 package if you are maintaining an existing program + using psycopg2 as a dependency. If you are developing something new, + Psycopg 3 is the most current implementation of the adapter. + + .. _psycopg2: https://pypi.org/project/psycopg2/ + + +Installation +------------ + +In short, run the following:: + + pip install --upgrade pip # to upgrade pip + pip install "psycopg[binary,pool]" # to install package and dependencies + +If something goes wrong, and for more information about installation, please +check out the `Installation documentation`__. + +.. __: https://www.psycopg.org/psycopg3/docs/basic/install.html# + + +Hacking +------- + +For development information check out `the project readme`__. + +.. __: https://github.com/psycopg/psycopg#readme + + +Copyright (C) 2020 The Psycopg Team diff --git a/backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/RECORD b/backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/RECORD new file mode 100644 index 0000000..b809d4b --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/RECORD @@ -0,0 +1,165 @@ +psycopg-3.2.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +psycopg-3.2.3.dist-info/LICENSE.txt,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652 +psycopg-3.2.3.dist-info/METADATA,sha256=X9bT6pSFFvd5m10fZyTzxuofr9mhFKqKLtfByzHgaWQ,4262 +psycopg-3.2.3.dist-info/RECORD,, +psycopg-3.2.3.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +psycopg-3.2.3.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91 +psycopg-3.2.3.dist-info/top_level.txt,sha256=npthKx2_OEoahttYqdsIPlRUgjS_bQBmfpDCVxQcPGo,8 +psycopg/__init__.py,sha256=j9qjtzDMiRcEALAETV_zVM7HbvjOhG2TvBQYrYVB8KA,3436 +psycopg/__pycache__/__init__.cpython-312.pyc,, +psycopg/__pycache__/_acompat.cpython-312.pyc,, +psycopg/__pycache__/_adapters_map.cpython-312.pyc,, +psycopg/__pycache__/_capabilities.cpython-312.pyc,, +psycopg/__pycache__/_cmodule.cpython-312.pyc,, +psycopg/__pycache__/_column.cpython-312.pyc,, +psycopg/__pycache__/_compat.cpython-312.pyc,, +psycopg/__pycache__/_connection_base.cpython-312.pyc,, +psycopg/__pycache__/_connection_info.cpython-312.pyc,, +psycopg/__pycache__/_conninfo_attempts.cpython-312.pyc,, +psycopg/__pycache__/_conninfo_attempts_async.cpython-312.pyc,, +psycopg/__pycache__/_conninfo_utils.cpython-312.pyc,, +psycopg/__pycache__/_copy.cpython-312.pyc,, +psycopg/__pycache__/_copy_async.cpython-312.pyc,, +psycopg/__pycache__/_copy_base.cpython-312.pyc,, +psycopg/__pycache__/_cursor_base.cpython-312.pyc,, +psycopg/__pycache__/_dns.cpython-312.pyc,, +psycopg/__pycache__/_encodings.cpython-312.pyc,, +psycopg/__pycache__/_enums.cpython-312.pyc,, +psycopg/__pycache__/_oids.cpython-312.pyc,, +psycopg/__pycache__/_pipeline.cpython-312.pyc,, +psycopg/__pycache__/_preparing.cpython-312.pyc,, +psycopg/__pycache__/_py_transformer.cpython-312.pyc,, +psycopg/__pycache__/_queries.cpython-312.pyc,, +psycopg/__pycache__/_struct.cpython-312.pyc,, +psycopg/__pycache__/_tpc.cpython-312.pyc,, +psycopg/__pycache__/_transformer.cpython-312.pyc,, +psycopg/__pycache__/_typeinfo.cpython-312.pyc,, +psycopg/__pycache__/_typemod.cpython-312.pyc,, +psycopg/__pycache__/_tz.cpython-312.pyc,, +psycopg/__pycache__/_wrappers.cpython-312.pyc,, +psycopg/__pycache__/abc.cpython-312.pyc,, +psycopg/__pycache__/adapt.cpython-312.pyc,, +psycopg/__pycache__/client_cursor.cpython-312.pyc,, +psycopg/__pycache__/connection.cpython-312.pyc,, +psycopg/__pycache__/connection_async.cpython-312.pyc,, +psycopg/__pycache__/conninfo.cpython-312.pyc,, +psycopg/__pycache__/copy.cpython-312.pyc,, +psycopg/__pycache__/cursor.cpython-312.pyc,, +psycopg/__pycache__/cursor_async.cpython-312.pyc,, +psycopg/__pycache__/dbapi20.cpython-312.pyc,, +psycopg/__pycache__/errors.cpython-312.pyc,, +psycopg/__pycache__/generators.cpython-312.pyc,, +psycopg/__pycache__/postgres.cpython-312.pyc,, +psycopg/__pycache__/raw_cursor.cpython-312.pyc,, +psycopg/__pycache__/rows.cpython-312.pyc,, +psycopg/__pycache__/server_cursor.cpython-312.pyc,, +psycopg/__pycache__/sql.cpython-312.pyc,, +psycopg/__pycache__/transaction.cpython-312.pyc,, +psycopg/__pycache__/version.cpython-312.pyc,, +psycopg/__pycache__/waiting.cpython-312.pyc,, +psycopg/_acompat.py,sha256=A9YY7CCglIG9mFP7R3aC8QMz1QNIYmBEneuczEzpy9U,2684 +psycopg/_adapters_map.py,sha256=opAW8bqNxeExG-tp53tVHQk4fwkghx-DjdmPGhr2W9Q,10691 +psycopg/_capabilities.py,sha256=nl4hfpXu1EHWDJIyHuNstU1OdOOSeNs1h4EUsam0Spw,4689 +psycopg/_cmodule.py,sha256=KqJ2-lKl3MxLgs-W5L3g90FM2HHseiXtvEbHjKE0iaM,790 +psycopg/_column.py,sha256=evV2BrI325FLv1N5KGFODjwM3GZGuJpt2mXNkTNcc3w,3012 +psycopg/_compat.py,sha256=9Lj06nAprTtHlHnLXs-w_vifGoJSQhegoHhFKi-KKi0,1407 +psycopg/_connection_base.py,sha256=w0B5NDfW-AkKrAz0-o6KhxBYNsw_hqhwaFe3O96yQ2I,23575 +psycopg/_connection_info.py,sha256=CRriLvdmrMOC_g-wznsAMex6Pa0qclVgZs0sybtWcf8,5527 +psycopg/_conninfo_attempts.py,sha256=s1qzPzJfIwjLEyJ9EyLxSw-qbXF0ofRSVg5qUO8B8Pc,3100 +psycopg/_conninfo_attempts_async.py,sha256=FTOUWKF4FHSlC0untryRUkcxTdud3GQpRfoKdAjEMvo,3204 +psycopg/_conninfo_utils.py,sha256=1PaylxpzDyOR0F4Qi7jRtcwv7CYh9eMHnyOJ1lC2DFk,3014 +psycopg/_copy.py,sha256=HfWcYW4N7D9Ng0MJmKRMr7-05xHKVMRaX0iB_nuVcmI,9909 +psycopg/_copy_async.py,sha256=r_YJ6nAaAacCQvv9Du2JoF3suUIWO2WKZODlIpuLWTM,10142 +psycopg/_copy_base.py,sha256=bsyODfgPK97neC-B2fnSUZulowO1Z5ijau3CfvM_8Us,14030 +psycopg/_cursor_base.py,sha256=jBmzSIVtP8nOucDRD0ilmuZpXfqQaxB7z9hsoVZZZeE,21391 +psycopg/_dns.py,sha256=BNSMl8J6sGITtzjwTQKuFPi80Xws29SC_iJ-bOuA78Q,7905 +psycopg/_encodings.py,sha256=Y2m3CRgz0OxAnbqGK3d7-ru1F0OYkJG21yVqzHHJf9M,4082 +psycopg/_enums.py,sha256=5gCef_sYe9UdaE4n_RmDWeF4TfQOwQFeikjrkz9YivI,1691 +psycopg/_oids.py,sha256=mJI8HbRrTsbK0LIgnnG5xPH-3hxNUclotqUurmyo2s0,1875 +psycopg/_pipeline.py,sha256=z06iVQrW9FcLiVKt4oeVknNDnjTYfHaOaPV8eiHn3z8,9321 +psycopg/_preparing.py,sha256=ByZk-ZGK4CGSiQicDzYCoF9rWLD7JPPCmeBBHOozbtM,6368 +psycopg/_py_transformer.py,sha256=ULvLpTrppIYV8USaU_CugXRcf_KttRzfsMMl_WA5kt4,11738 +psycopg/_queries.py,sha256=UOgDqUoBRpzlapfzR6Kv3MHOnHCfqcacSbPmfvYzxVs,13558 +psycopg/_struct.py,sha256=f3fqdwOj-hZDwmNjOJqIIUMnpglz8Mea-fnf464RzDM,1997 +psycopg/_tpc.py,sha256=UCK60jv84btlCpEaNucWVDWVdJSGQSkX1pi9ehi7Mlk,3536 +psycopg/_transformer.py,sha256=mDkBLuSxbXDG1TckPgIyZJx00yn5UXU8DluOGmHWjAY,451 +psycopg/_typeinfo.py,sha256=FO6GHaOuXO1xXZwOsXcOJFIAsmtp8huyoCgidgX9Tfs,10662 +psycopg/_typemod.py,sha256=UZwHFfnWbXqxZ9UIVBrJh36599poZAaZj65v8EsbIJs,2498 +psycopg/_tz.py,sha256=mIa3blpVVnfLVEu0v0Q1-TZrJ0B9-A-dtFuDB-PlikU,1186 +psycopg/_wrappers.py,sha256=wKZt_ar8QuRgEKC6tuwamYXCwB1P7IZQsmgYdVOlAhU,3126 +psycopg/abc.py,sha256=1Uhev6TD8WXLsXjKwQF_xGvydBzac9M4HdHvPlm7mOA,7720 +psycopg/adapt.py,sha256=EnkYtMX78pKOAdORqInExFZBt-Rhy6HLnUFlgp8mziE,5206 +psycopg/client_cursor.py,sha256=l7dFcXHKTL55iS_0diPcX7Xmb_u9eEH0hcxXm8hBkcE,2681 +psycopg/connection.py,sha256=nRniudtUtKsy4dixy41N-FO-tNqmrhBhkxQVJSzmhlQ,15689 +psycopg/connection_async.py,sha256=yKL5O-sAh_eruo_LOIWLbhr3Qt2z9hCaPvcRinqp85I,17677 +psycopg/conninfo.py,sha256=77gn9yWXUwC_7zRxB2jJjyUe76cCBI4Vryhi9zNyp2g,4502 +psycopg/copy.py,sha256=C4WX5-BpU4u5KIH4N01M7PsvzTOHQrYrwb3C0_sJJF4,806 +psycopg/crdb/__init__.py,sha256=RnjfsEW16dsXqmfLTiy1wi1eqWDrpguyZr_ChyZlJqE,439 +psycopg/crdb/__pycache__/__init__.cpython-312.pyc,, +psycopg/crdb/__pycache__/_types.cpython-312.pyc,, +psycopg/crdb/__pycache__/connection.cpython-312.pyc,, +psycopg/crdb/_types.py,sha256=oTwDXvqDc-xLuawf4-3tl8SVsG5wf16J9bxVdAHtyC0,7293 +psycopg/crdb/connection.py,sha256=h-WNZh-mFBQUWtPC8Hn8qpUQZjqWQNzV3BwtOna9tLM,2784 +psycopg/cursor.py,sha256=dMADsPQYKfUkVE_41Fj0OtcHCtipcFJCINyGvj2NaSc,9380 +psycopg/cursor_async.py,sha256=I6muHBHYEgMr2yqLpqWmyxhBDb3ksRKyX-SHzriAZ1Q,9714 +psycopg/dbapi20.py,sha256=J2oSjtkQGNZ-iY3rhtN1aFQ0WYNEiuLBxaCnJFcdJwc,3446 +psycopg/errors.py,sha256=5l_ZRcg_ZVJtSWptRo7H_4vXXuBloYLExciaEika13s,45973 +psycopg/generators.py,sha256=NBvWWLQObZRHT40RoKHuRT6K76FspvvH9tNZql2LpmA,12464 +psycopg/postgres.py,sha256=cYF67L3LYbBpkDWtyY4IW1xkYo6TZTNEr2X5jS3FOxk,6413 +psycopg/pq/__init__.py,sha256=8cLOm20LKnTR2A1NkFFXqOQxQd-XRX8IJn0UxCyv9K8,4006 +psycopg/pq/__pycache__/__init__.cpython-312.pyc,, +psycopg/pq/__pycache__/_debug.cpython-312.pyc,, +psycopg/pq/__pycache__/_enums.cpython-312.pyc,, +psycopg/pq/__pycache__/_pq_ctypes.cpython-312.pyc,, +psycopg/pq/__pycache__/abc.cpython-312.pyc,, +psycopg/pq/__pycache__/misc.cpython-312.pyc,, +psycopg/pq/__pycache__/pq_ctypes.cpython-312.pyc,, +psycopg/pq/_debug.py,sha256=p6o6VmfSIbF3ZiOlbSmIktyITxmlBfJAjzHfkx74ryo,2952 +psycopg/pq/_enums.py,sha256=sSZ12nUMzvjXhUsLlX63FOKLqy-wCvdmWli0CgzWimw,6038 +psycopg/pq/_pq_ctypes.py,sha256=mJmxKIiRPP8EBG4VZfgtYYzqV3L6dtQ3YhDQmmvtdhI,22148 +psycopg/pq/_pq_ctypes.pyi,sha256=VcKZcsFA3idIr7wRpCzubWl2nZqmnox3yeUY5aSX2yg,10187 +psycopg/pq/abc.py,sha256=pOyTy0bUZiRfZtZSdqh4fHK5HVyTPcPoP0k5cuFYWwo,7935 +psycopg/pq/misc.py,sha256=vqr7YVmw0DkHEGQKFBmgsczcZaRRnFwbt1SI1iU_mSo,6235 +psycopg/pq/pq_ctypes.py,sha256=n0qRZln57FonUSqxPfu4xr6VA8g_QHlueEiInUraU_8,41842 +psycopg/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +psycopg/raw_cursor.py,sha256=G0pakVQ2BoVSSjyonI_irv_8kvYRT7r5INNNAMFbIAA,2166 +psycopg/rows.py,sha256=MbiZOH36bBBUTzv0E6YtJT2LUA5SBY1o-wLaAZpV92s,7889 +psycopg/server_cursor.py,sha256=fOSXnY6a5NQx3Vp60tTReMt0i4LPqhPl4vIQOVSY9a8,14719 +psycopg/sql.py,sha256=5htpVFfIcTlpXi_oPypRl3sh0Ejsh3N4immuhOJ4u90,16575 +psycopg/transaction.py,sha256=0nN6UyNlByRoPmVccyYuH_DaorDph_uLVOijJ8SNaxo,9258 +psycopg/types/__init__.py,sha256=JPAkV4EfkXwdsr76_U1DsQV19c8aQNSB6kgud4bhXeM,181 +psycopg/types/__pycache__/__init__.cpython-312.pyc,, +psycopg/types/__pycache__/array.cpython-312.pyc,, +psycopg/types/__pycache__/bool.cpython-312.pyc,, +psycopg/types/__pycache__/composite.cpython-312.pyc,, +psycopg/types/__pycache__/datetime.cpython-312.pyc,, +psycopg/types/__pycache__/enum.cpython-312.pyc,, +psycopg/types/__pycache__/hstore.cpython-312.pyc,, +psycopg/types/__pycache__/json.cpython-312.pyc,, +psycopg/types/__pycache__/multirange.cpython-312.pyc,, +psycopg/types/__pycache__/net.cpython-312.pyc,, +psycopg/types/__pycache__/none.cpython-312.pyc,, +psycopg/types/__pycache__/numeric.cpython-312.pyc,, +psycopg/types/__pycache__/numpy.cpython-312.pyc,, +psycopg/types/__pycache__/range.cpython-312.pyc,, +psycopg/types/__pycache__/shapely.cpython-312.pyc,, +psycopg/types/__pycache__/string.cpython-312.pyc,, +psycopg/types/__pycache__/uuid.cpython-312.pyc,, +psycopg/types/array.py,sha256=q9OzhlPMi0iyWKsF7i_-xPHiEkMQTdQWc8oXd1GtqyE,15463 +psycopg/types/bool.py,sha256=0GJQG-Cm5P5NgH8TfLNj9n_e5ckw42XnsRBinX0k45w,1163 +psycopg/types/composite.py,sha256=dCSt8UvwsLLavqAJuXRHI6fzeMVXbkcRuPRa9sdzzik,11923 +psycopg/types/datetime.py,sha256=RqAgiK9BejHkqNwVP-sX-B3y4fSFa3S5ml8lQzVe920,25664 +psycopg/types/enum.py,sha256=3ftaL3kAzZ71BvNuoBIyeqrYkMaYh4nsjRYGGqneHnw,7193 +psycopg/types/hstore.py,sha256=1cnWZD6r4LF4EiGRQpYzA4OUPnMboU24Ot_qxD9sRiE,4064 +psycopg/types/json.py,sha256=gmYEx9qUO7rU_0dm_tjeEI1TTuYUnsBqwgcOTftJ_Fw,7486 +psycopg/types/multirange.py,sha256=-WdGlILg3huG3X_h9SCa8mbB76E7mMuXQI54Od493L0,17637 +psycopg/types/net.py,sha256=tEhaVcWCOjw1GUGX7v0Q8Ja1DR3QVDtnAbnpctWAvYs,6883 +psycopg/types/none.py,sha256=4oc9Za4Uj7VK2sHvpVQKqXxksJGfAvt7V4ervA0eh8E,666 +psycopg/types/numeric.py,sha256=y4sc8LieL1zHoMjGrtBzgk5YCBI-06yyrLdlz0UIrtE,15435 +psycopg/types/numpy.py,sha256=6nkM5qJUgdtGkvGwjy-hVLHteJX7w0xaFL4Im1fRBKU,3274 +psycopg/types/range.py,sha256=W2CY44dM5p_HEMNgJFHexigBcDJGq0oTycbNUVUZi-c,21606 +psycopg/types/shapely.py,sha256=-d0aK5IWDJsvLXrgY5gcfa-F6_M7DdEwIWPkalG-8NQ,2448 +psycopg/types/string.py,sha256=Z1FCWkj-hDrgdJ0vgFJv_32aN2y-x1meuMuB7imCD5U,7642 +psycopg/types/uuid.py,sha256=Ek_g-V_fG9OSP4scMK0Az1taViLSFtMKebi1HQtEexY,1630 +psycopg/version.py,sha256=JLWoprIsC5HVclyhn7LzVfVpNtZYU-UoLQwAGMEBlYc,232 +psycopg/waiting.py,sha256=OhNpHRnI7Ra9WwoWgcHaTe9uqwPecAM955mgcVT2r9I,12892 diff --git a/backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/REQUESTED b/backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/WHEEL b/backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/WHEEL new file mode 100644 index 0000000..dcfdc6e --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: setuptools (75.1.0) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/top_level.txt b/backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/top_level.txt new file mode 100644 index 0000000..296ca87 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg-3.2.3.dist-info/top_level.txt @@ -0,0 +1 @@ +psycopg diff --git a/backend/.venv/Lib/site-packages/psycopg/__init__.py b/backend/.venv/Lib/site-packages/psycopg/__init__.py new file mode 100644 index 0000000..71e70a6 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/__init__.py @@ -0,0 +1,121 @@ +""" +psycopg -- PostgreSQL database adapter for Python +""" + +# Copyright (C) 2020 The Psycopg Team + +import logging + +from . import pq # noqa: F401 import early to stabilize side effects +from . import types +from . import postgres +from ._tpc import Xid +from .copy import Copy, AsyncCopy +from ._enums import IsolationLevel +from .cursor import Cursor +from .errors import Warning, Error, InterfaceError, DatabaseError +from .errors import DataError, OperationalError, IntegrityError +from .errors import InternalError, ProgrammingError, NotSupportedError +from ._column import Column +from ._pipeline import Pipeline, AsyncPipeline +from .connection import Connection +from .transaction import Rollback, Transaction, AsyncTransaction +from .cursor_async import AsyncCursor +from ._capabilities import Capabilities, capabilities +from .server_cursor import AsyncServerCursor, ServerCursor +from .client_cursor import AsyncClientCursor, ClientCursor +from .raw_cursor import AsyncRawCursor, RawCursor +from .raw_cursor import AsyncRawServerCursor, RawServerCursor +from ._connection_base import BaseConnection, Notify +from ._connection_info import ConnectionInfo +from .connection_async import AsyncConnection + +from . import dbapi20 +from .dbapi20 import BINARY, DATETIME, NUMBER, ROWID, STRING +from .dbapi20 import Binary, Date, DateFromTicks, Time, TimeFromTicks +from .dbapi20 import Timestamp, TimestampFromTicks + +from .version import __version__ as __version__ # noqa: F401 + +# Set the logger to a quiet default, can be enabled if needed +logger = logging.getLogger("psycopg") +if logger.level == logging.NOTSET: + logger.setLevel(logging.WARNING) + +# DBAPI compliance +connect = Connection.connect +apilevel = "2.0" +threadsafety = 2 +paramstyle = "pyformat" + +# register default adapters for PostgreSQL +adapters = postgres.adapters # exposed by the package +postgres.register_default_types(adapters.types) +postgres.register_default_adapters(adapters) + +# After the default ones, because these can deal with the bytea oid better +dbapi20.register_dbapi20_adapters(adapters) + +# Must come after all the types have been registered +types.array.register_all_arrays(adapters) + +# Note: defining the exported methods helps both Sphynx in documenting that +# this is the canonical place to obtain them and should be used by MyPy too, +# so that function signatures are consistent with the documentation. +__all__ = [ + "AsyncClientCursor", + "AsyncConnection", + "AsyncCopy", + "AsyncCursor", + "AsyncPipeline", + "AsyncRawCursor", + "AsyncRawServerCursor", + "AsyncServerCursor", + "AsyncTransaction", + "BaseConnection", + "Capabilities", + "capabilities", + "ClientCursor", + "Column", + "Connection", + "ConnectionInfo", + "Copy", + "Cursor", + "IsolationLevel", + "Notify", + "Pipeline", + "RawCursor", + "RawServerCursor", + "Rollback", + "ServerCursor", + "Transaction", + "Xid", + # DBAPI exports + "connect", + "apilevel", + "threadsafety", + "paramstyle", + "Warning", + "Error", + "InterfaceError", + "DatabaseError", + "DataError", + "OperationalError", + "IntegrityError", + "InternalError", + "ProgrammingError", + "NotSupportedError", + # DBAPI type constructors and singletons + "Binary", + "Date", + "DateFromTicks", + "Time", + "TimeFromTicks", + "Timestamp", + "TimestampFromTicks", + "BINARY", + "DATETIME", + "NUMBER", + "ROWID", + "STRING", +] diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..99c5a7d3959fa9fe11adcdad6f00d75de60d4e24 GIT binary patch literal 3121 zcmb7FNpBp-6|UKLa=43&#Nj4uEG`nY%iK4a22ILbprk^e(VT9Md)U=IscuRbpQw{^ z31DBMAP5k}mmmv*AV7XaPK;@gD1ewlpo4BsbjvC4RkPV+1Obx4;H&SwSFgJ2EmeQb z<Yuq&9fHT!dhu7Yol#ap9Ot8 zZD$>{gLTqQsmp<`i*~Uq^a|^y-BQsD|xfo$F9<=>>9l$<-FO?3bY`3i#fms z=^z`TLu{B1OI@ou!miWnlDC;3up9ISE7GEr+szNzO?s1!(ordQm}6|5j~f< z7Q0Pvvq?HB+%xiB_X zcxpRtnd@7htraxYRrgd!FQ}SYb#-3Yw|U`d&HdcA((iEH^>>)6Vn~FmKL(7swW{s_ zNmji@kVk%CXvMIIF517JZhy4af(ixH7Rg=foeRCO-bRm}$PGB@0sKRqYcv-}D9r`#@c zl`;6F=hCunyIY6Vs?A+p^Sp3>wt2`bI8O4ZQPoYu(nU@l$rs@e=|$VJ^b(#6_LbbU zO><8z9f-^}S1m`C29cLu4H|IFc){^P5Ej`*wW{tJrr{d8BeJCi2{zCoCvWNexz4?) ziEN{EIc3o_bj$UpG)gd~Nv^V~zPPZbE-4t>ePiRgq8X+%DsYtrD3ajRA`Y=L_GO9# z?W(nJ!y%i!Lk1xViG;SNR*lJ9#h8dMtgg>*{!k>B=C_x(S3g~bwRS#TSl$$|&5dWP zOCr9ty}7#nL{2p1^2B0?9!2*L*lJqQB`y$A^aktlhw6iEo8iH#((?&n-r zHAmgo-I_>ORj6#ot(iK{q8mJ}gf}5HBjgcU5Lyx15ZVzs5GE1sAlyZ`hj1U^0m4Is zF@$l134~h+w*iW~BB3anUBXzJcDaoGOn4OSF@!jPh$?QiaEy&u! zf)IH)jeprFcvX9ahPCs3n*rS?%S_}OJiJZI8Xm>X{I^X04^D-Ccu} z>s-V!^)SY~;*76vY;P@Zi=+cHWVt4u&2O$lQ}b!u!wkYK!W;lpwfFWoqLb@o!+}>o z(e!=w&~z2~+=%Y~&|kVVn7k`SxirO8&efV|yL47fQ;|9cs}?2Yx8yx+f&6P{@$v2p zn;$q;cz<@SitCK2rILMUxlqw#C7bKJc*ErgczR!|S^IMWXCvE4X^PF_l z$-p@oJSRPMGXD*kuanthGFvAr$7JQ4^w!BZSnFi&n9QA%kvh3oCy(X-cAZSu$=!1@ zdQQgP;yP2`lBqgb{+2A)$>duy@m-vxdwr`M_*o?NYU<_Gmk(ag zd^Pj8$iP`N{c7Xo#+OfCZ+x|J5*-GgOvh=u?>OCelsL=ekCJE2`J?PvuInfbwru-p zrtdh@2WrxPlsqN<$E5#F@;6PtZaN_oXJim{gU4j>&BGHi3J#&cqr@p0I3@#cZk&*t asENPIyv+EXC#3k#^utW}WrAxEtbYSAx<*m} literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/_acompat.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/_acompat.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c80f28a447f8d1478a4585eef89add0797970e8e GIT binary patch literal 4354 zcma(U{cjw_b!K<(ZtpASobA|-^RXd@9443qFjSb2TpX>|w_|6Wya*wJ#V7%QtqwHzJ6ema_Qi}D zV{NATG)$TC;#M(A;7B4YZ6>dPHQ0(-mf(AtJn=v{UJHvILMnw)Oxcv9Q*fk_!+Am? zgT&l2OUw-0c0~>~6}!Z28_cFQUxjsjx%GR4@zT!IWPQl#{+#RfgWqUx$ z%DU}>)(Nz2taAgcJ5J)n+<|cQXYMq+W+TO(O=-K#ZlG;9WwYn^)ZA@upN$rKn1X@xT6!SVe+apo{?_?9!iN^Y)~ zPkfIDn4>|`a2(eME-+#!rv!4rnGVze!?ul4n+5R!m%A0v!GiSgiPw(m11}yOcC z;P)7hIVp$_PfxOfZ5dt=L-b99^Ei-#=vyv7!}xMm*lM}?VZ%Ffa>#YqsUTJei2)rB zV*22(Dy+f+RWF2C2~BIYX4uokEX>RkMv4>?QZnf*DazAQP7X3J7-!fZ?$s*2!hEA7 zwPc}3afocXh-p1fs^oRp^w1Y*x#BT161rY?&5Dh9O4rX; z3_GOoZs6q|2r#dB7Xoye02&}d^DJ4EXuLb*LGtF_P61`r+tV~B@eE82eIfJh(DPmd zI}mJG5xE3wA0Uen0JEf_ro?&>Zt*gnkZpM0|GjP-=osR=Q16Ddkirq{Lu5As-1<7r z%|b;Nv0i?-W=|%C5-yucos2v;j6$3xi`njAr6uZ+Vb>7>1q(;9iZ~NoMQMG`8)p58lpn%uUU``+4VAvHH6= zGLK(V9}mw`8Xn3;#WI01>bkaAY&kV%yN0h-HB9s%%9&r`4&MS=fq8x8K<4YFTheuo zh6L%RnI&f1x}Kvv2eTgL@3Wz~djaJL9z+6$?!8&^gCs@Nf2&I5i604oFszZO1m8+q zDIz}&>mXVX9@sp>&?g+hVfegeG%ISj49>4RVx-G>#J>b&p7_mW37J@1l7NOyf?`yq zzlAXPlCC*wY36{4oug+f);Yswj*s_JtA>_1Gkm7|P)frPgOpM*{~-usO{O5Zh70N= zg(7G0agYB3R`tL>3<2TNAZkFRn{qhr?kS{VTGz-@8%ed_O76Oz-1X_%&-*@k=dyV- zdFYyQC`>O@(P~&$#g^X&2^*w4BaBI!LT4l(uqp*3;WbhFUg1Z${x zcpF+(y3&l=Dp@T-AHbvcT{z~C<$3uxkqFo`4F~zt**MG}Cg-=pr|u=Ig>6FJunY|Q z2$v~20TNT>9r*;AqJNgBXii=}yvb3w;(y$L*ALfRu7$^xpKvW_e@;jY@n=D8F2WB% z7eqtWK%FuyUmtUM5cN)5%r=A6a9B5wa_;h+92Ut4rj!>b$h|&CVn(Qm9|N_o!{_0? z{()6;NrgPQ*gx0*$z#`&duq=wNNOb0NM^4kciqnR+{)f}J$v6D5C5tE5B*>D-Pn8h z>#m#GW4BVruBDDGq)0ro5GU!Ur=$BCh6n!-ksF8|J+VyZzXqMPwxJa&`A0l zHMJl^|6dPt?APsuN9o586?)0l2rYCeSECBz2@2C!lM%$*XrV{Bx>d|?6Z2gZ=X(U~ zZ7)0`U(HL%|1d@T5gG7x;fG-Z&k(x!CLnNA(dWsjJ^}$&l_pk-8jzZ;m8~8<-vJyD zC>vXqw8Dy#^A9L+=g%Z5lIo^aqG*HmaCOdx>r`I#^*I+KU zlOKc*-;iS!xR~J$$?>p)$XR@Wi^So04?wY;o`h=1F%UQwBaXF#Lrf63w!@dLc;<8b zBhB&eBu^qSqw8z_P=Nk4lJNc)SGRZ>iYHs3z!EHcpyEX;?jVj;R3ut>%y?MgU5l^T zKz%xV`u6j;V2FX}V~Qdpg?Je zb}zoS5P-fZfEWmDTZ|*NoxDJg)4L>1GYcB&e~$i(#Ax{P{~x&N B&V~R0 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/_adapters_map.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/_adapters_map.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ccedb5a391616f62145dbac3a3b62dd0b1589bf3 GIT binary patch literal 12424 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/_cmodule.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/_cmodule.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..76152d47ad0c5a2137a9d42cd29cb20b113ae54e GIT binary patch literal 800 zcmaixL2DC17=~vyyPM5!l8V|OR?0#TCWpj>UbIyN5h_TrNH6Kau-TcUn`CF!*-2!B z2jit)gx)-eKS2Bw_2j`zXfI`#=%DPm z^s2C%KE-F*EEIm=M+8s0uzhM*@<|pU%sgprBGl}O9w!KK`By;#xF)x8!W=>~y~=6> zq4cd%kx{aTA$Fq^U!ZNkuOM90v)$SB4?6v4SD0C*1|Y3R>t}cFUgd2pix_X zPBIX}ABqCipLqb6zJYU}FE2i~Ue@=);)wxNeS3MhytA~InLku(N9v6OExWxr+}v5+ u)2JqI4N9N#_7a6$tROM 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/_compat.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/_compat.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..72e9855505cb32a15b50b671ec662bb95766b757 GIT binary patch literal 1794 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/_connection_info.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/_connection_info.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..16ebdfc1ac43c95c867a6740e26c39248245780d GIT binary patch literal 8975 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 EKShZd%K!iX literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/_conninfo_attempts.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/_conninfo_attempts.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2d2191339cb6f7355fb20195e02751c80e8d616e GIT binary patch literal 3657 zcmZu!Uu+b|8K1e^`+vSWu(9KdNtOnTuh>T#6aKhq9k5ZM1&lC?nyb-zeLH8?-rK#- z%wZedMOM`ZMTm}aFnK^q7OXufjqUzQ>DJxnAWf*3R0*l-b|rVOQovc%-ycR zWTl(G-+ce(o8R}{pIchu2)+-r@0ndmguWIN?+Z2t`0+9fK0*d6AOjl#3zq|h02bq* z6)Xg0uM`yM6)RK@7s9X?GQw7*94*A;IAX=ii9({BEF|STYPFP8g;Y6RNS8B(j9iPs z+P151Mu$Mauvz48LX1x9l?rgm1>M*r;hIpQ?6#OpGb@^I7?d#Pw)i`mK}x_a#VVG` zHBUb`QeksNr!rY=S}ARfLJRkRACJK*+ySoRNmLJTpQeU9uMDFLI}xe}W2hFGYTljX z(QJ6go7IBe8L!9a%Bu>TW8bP_7Wg6h8Rlt^dMe|MHhbRcjceHB;q`EKhrf#q<$9no zGeXln2+;)Z@OJ~=84R*V(QAl@y}jLtzEM}WuwQ;t32(I78-ZGIs%3NTjSSzunsVKX zVpLP=_+8;a^r0Y-kj<%OPtgRPf|YTBTpn2C7ItH(%DuQHG<*Q5lYo@8(d zG;_A-(v0F>U<#TDQj6$@pqn#^Wi+V0P?qetE;hue-ioy)boT&V?X=JHtH(s{k5N7Y?V1eyasWg|HW#UwMuR23in-HO( zRE83>T(L-**j&<4QXzm7hJS&1Np|M)&XR6g@|>rRbdb7-4yb#Ws|XLe+bu^ovMrOimK&h72-MopghM z5H2QeW~;m0ARrZu0bi;>lMA`wMl`xnOJ`govqd-RIp2*mM{a=3GV$g`II2&zp@Fd( zhfcGKUL<4o6lZ;U5qxiR2<5&a#N*h6UYrJ{$MTnmeQE5JIWfjePWs@$v_47LSQDW3 zYXV+PyX5%bm9NaX+g@0uyFhv;{MaYZ%%hDg%Cya&xRc&Cf8t*2uI28(w&oTh8v!Mj zy_0OaI`aO=?XLW_nYFG%e@PzR2%)xbKT4rw+ud}>LV98LK`OnTQdd*zuUnUY{K?L> z)c%#|{s)oFV*5&G-&!Ppqvuv+;9fMn7`+|syq{>DANlu_PL%2RCkn)}_mbPMo_hb( zO6TF5d;hTSvweRotqq+16TO{0cc-KCgA@PV2m#SkCZOpT*`u!qK7T!SY+vZ}BR$8u zLtk`HUQbWl?(v$!htf5If zik{;c_IUY>n zQ%Kb{Wy%L&j}D<(ND+{-qxB&7L3v6<{g$tWYe6o{3$Zbk+OiGPXLi3K$^0&MU4%P) z^-wJ|jIM@@fk{*hTmag7*taum#6^r53DF9hKMY*it^i#cfzUkYIeg*9RF-s#LEDwgglVuzryWfMeENQ_w(zcLM?j)boIkrd{bo~}R8xT6_R-}L0h^HPG3x@5Kjl@+MQ z0rVO7nL*BMsYw2M~N5J?xxLmjdbuxw;MaTmVm23&(B zFXq6LXF;a$8x^&Yi}zFU03V9-#>E3})XT1}QgJAEl{XLczX7#k2(00btMIuBc_;#! ziW9k*1avnJS426RG5JL*-U<~@%8eGCaz!K}H_RLWWvDYDIf%Fru57#$hE8JhcOz+UHPW_t{&pmLKhwK-a3#~bG_cH9GrcS6zLjX- zgGAf20`9e{%k68eJqyu0>5g0JzNHiEU45%veYetwZnQ5b58|2ic-LyY>rOPeVEn3k zJ=?pQ?fw11_5S0l{l}jK1Bvkb(4#1NYj7Y2 ztR?d|`&Sc#E6U)1ZY2hps5-wmxML`#NA{tF(Ba3FnC zGzX!{wYw2bGn}HPxp7S^RRK7Nrcp=}h~}YjBO={HWYKM6NkoE+s1QwG662sgQKXWm z6rSG9vQW`ktdaly5NVVd;_t>OSwv7#bIXJ)ukg3%G0c&?SU37s*)ggX`96Ic)&$D4 zA3(Da#27z{2C(w4B*L$KjavSOQeUF%-%;mRsQW84yo!duMEf?vDE{(7$9gQg8p|#n ZS&QwN4?hmSg4>=P!`=98Ob3D2{{gJI;Aa2; literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/_conninfo_attempts_async.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/_conninfo_attempts_async.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fa2a6c2d23229096759748c267773b08c81761ef GIT binary patch literal 3930 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/_copy.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/_copy.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b520a8bebb063d436ed8e5fd4b298d6e5c7cfa05 GIT binary patch literal 12284 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¨A^+?ap?g8ciBowKnx+U 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 Mn-9F+{XzTx0|saTr2qf` literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/_cursor_base.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/_cursor_base.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..420523cec905140d3db5b001750cf1bd1d9a757f GIT binary patch literal 28155 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 ami;!q>6-s$^_(wRu_09gV<(j`%>F+JZ(#TU literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/_dns.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/_dns.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2f1a9e365498d8ed160bbb1eac41fcbb4725cf55 GIT binary patch literal 11354 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/_encodings.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/_encodings.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..65f36a46dbc546cbfa3b1f5fb6e37d9826cdce11 GIT binary patch literal 6189 zcmbVQZ%iE5wZC_EXa6rO#$aP?GuUxpV=v}Ei|sgujj;h6|G|#yHDojF9blGab~`f* zhC)iLs9j5`Y|B+~l~(2Hy-Mzj`aS*B^yz(g(t97+hb8FLQBzfw+D~s|QYp!&ckZ2? z-G#c1)DfKdoipeDnRCuP=gj`M-|sD4(M?296cJ3g zB%bA>9H!Wov_);~Zjaj8osaTxw~ zeL(kpnKdVq#WFVIuuG|)5Tb)aX-8$i#IKA`<10`yIC9_RqM0Q4dm1Uf{9 zfnFk)ALE~6GD5D9tK=HFPDaU%pE!PwqkCi&ttL06z2vPk@bXf1;&{mh79zLaN79}| z$l^=)j|%WjWTB6+DFVB`e6DZ(Q*(X8>JQKZ9Jk3R&W+b1G{zycjF#~dUP6hJrQKS{ z+UsNPgZ*|Cw=Lsk6x~nWA-CVRN9%}4qHsSTRgejC=Y6}S9jymRoQ#!84iZ8nGX6dv zJ;Wi&mY^owb&nJ1zQ}>g}L{66r5b_@LU$t zX<3=lgb7KXmn22Fn$q+sRT{l^Ne~qxTwTzoQ;Hxd@f4wYEuO#7b%NONii(obMO{uQ z+DMQyY<iJmY;`zw%;K+r)P``qzCz4W>QP9n3z*UW;^wCT@ol+r#9^UgBQ9C`-D8zWjM~?jKm@%hGS}?y`!z&@KJtfa5UE5 z+S+OOq)a@PkTsKIxtV-9GCiT434ywhPN3`Q`EZXvG�UC?VU>9rR`9VJmmLDX3ibrwWr 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 t_N)uxk86K@=vRk6uKYw@w-3P%{oH%*ueL`ye*V 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 S@P(w9TEryz9cK;cqW%NCQsOZH literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/_pipeline.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/_pipeline.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0ec73576360b05471e5e50736b920f275f1246f9 GIT binary patch literal 15139 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 K8wNwV?*9wn?LV>r literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/_py_transformer.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/_py_transformer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..521dfd225e50e3b352d62bf26f25255c2ea5442e GIT binary patch literal 14417 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/_queries.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/_queries.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9b06bb3599279ed9c61553388486ec18c45ad8a6 GIT binary patch literal 16051 zcmdUWdvFtHo?v&YCF^b3viy=U4Yq6xY=gmMfRJQ}4dLlPFq0r4vaD_!89kitHef}r zbu!r-dqNI*lRM;vSxjB(0+(zJbG3EH?$%c2Zl>;L>+Wjp*cp^AQsb%3Ro&cQCgyf$ z^3UDx_qDnufeh^JR$bla^4H(<_dS2_PyfZ?uu>2{2)+>cyKaj5Tg+&|s3z#uDu$x2 zQYR^%3Q#=FGf_Im1Q;6AhNvN6fG-`uTXsDdlc^$ zET0|Ldi-u%@duvP(BZ6f8Edue=iY*k6C*+VENyMc-zfm#ljgKqlo=`Lz z8jK1`+0oGGXe2(Y7>|bJ@HxfW7m5jd|JZ0$@H2|}gaGj3VL@^9pE|ZL*mGcC&*6i8 zuK-+2R2&P2L*aA6Z*lLTgc*GcVv`_>2~mQSwI>l9O-MM5-=LUY9vd1GM8$X8NK%upjD= z;E{>9@+^GIcpGnouUWA0cHZJ&aAc!&-;*O2W=Mr&(2IE{P&U2%9(F9o#B@T`+!D)av_1HQIq~x3A zgFtcb#?@XDC&PV|axEpjNl?DT1uur;a!`dKaX}bGhL3hdxnM%%1yS!2&e1orL3lIa zpI-eFNL-~-bczb*b`I_&1-TqGgB;fBeMuemCV}KwEhpQwREi$4Yw7&=(;Q5ISEiMw zD4@^`l$f;=0#iTPamsJ#6Puut+z`K2F~HIl6WLNpF_PU;97S89l;!qBtcHGy6){%` zBl%G*`t~SBvdfA|-6p_%RuZB^icQX=wS>#&IMIh-0I?$Rh#U+itF`kZ7ok%t?|@d) zVTdNFth;fFy=-27ZZ~{v%Pnp2v96e?9lNI3C3Agt`}d&0{!LxW+}rnBUsz~;VX^K- zC~}vk0z!Hbrpt)7AmNy?N5P16(FWPZ(0nJ8#P6TCbEr8&?J*s)qAG zGQ_%qHjLf|$p;CfO_^M!+_9!5Nf^;PhUa|S)<>`1`S63o6=W9Q{(h)Cix31Vm*cvg3OJLa`HKqi#|p^@^q%t zs(0##)~@m5`HH7F>8nlam9Od?;F9My};UggD3j;_U}8oudhFNWMAJa{Rh^lJhu0> zy+=;~K9gB)8y!|E^kgueAX0(26-PzhD|X>nCY3}gEI$?-y=@ecUz0Wpdm$uBifK?K z3G|SJID?DI;eJ_;xFFTs1I>b-m@yJh>lefw1JlD%=R>SOP+*?z?`ZAmwOP_7ag zop``HbRu((5SbMH&NV9vtTea(A-LKTt#> zfF^(laxTFGec?e$mvp=)B1#Um3(%P`UB5-~UI;}a*aKunJ}3%Asz6Kv*;)KPESw;h zie?0*9f)2*DJQmzo3P1djF3UzHmGRVg9TV6A#>9ZP23BaWMwguA-F+onTBYRTCr1h z7a&R2Q+Lm^W5KiI4*&1Z|Lpwd-M_5*8}DCx7d_H&=~?D()0w2A(!y(A5NY3K%K%X|CM_UC6A*D9H?Y9bd*M zk>zQ?5#|I4X0m>JNI9dH%esJ+qGY1X!>E*Y@5TC}dY!$=`fVR#w6>ByR#6}QW^3(W zPTJV0a*)6qO08~0XUSSSin>PqL}z;M(tftDe}8f(p|*v>v2-pm7KK|Zz_r)z50?-j z7gJTlc5XN!bAFq`A}3PVXhZ__NJdo=sCpzUi{FDWMcf?Gi_uPua0gXoZXYU!;(EyY z4Pp-#)3RdLhAO&>N@YaK-E#ddCw0mFI7;Z9kGGHjrgRe`-~=YhQIW2C|Iiejwb?&n zr*~!O>nCTe*&6TEft6ayRXbI_QbRe*KWd&nm91%j!YWeu&`mjOGwk(qOODn*v)=9g zh3~(*KW|vt+Nbt(sg26jM#D>v7PYfoEw@nah82dcsJ&m?kmy;r+=p?33pP5X+0 zuIOAf7~IYk%HVK5E?FXhB^UP)kn|tXAX`F#8b+Y}(J)PG*IB$M>oR7(G+&m|FFsEv z;j*5GLlV1Wow$}Ftvs`K|7)N%=WFvLLOJ^rqc*E|>1kSQE6_H(R z%vsp23BxpxkMDyUWo%S zmP^(Yl9!8uC_rA41YSg`CAkglA)uZYb`ybbMWCHdbCB_p2@nN7`NC)dEFPdshN8tC z+kBEA#Bi;*MpTNs6Q-K1dxY|Fu?P{#cXLUmoeLLo6GXi2sHmeD`!DFjpe}>DPMrm0 zMJ_VUT%aZTGVqUoNnfRD>av5S#;HFwz_!z>+6;CtrgN)8M+m*kk+?}!rM2uC7UIIC zQSrs(o?@Q+1fJiyCkoOPG@;~ZF;Wa*G!c(u zYb582`LHlfnkei@A`(|jQbLpk9&BGmI44TVDIzgBA#3FZa>BfL5OPWXGq3lb zL33#foC&P#p^LKD-Lq|8ux-B8yJYLSUtXE+et-OW&z$kvp<5NReP5Jsx?f#$uexoa zx-DDX{PBrfo_`g%v*G5O^Ud8W6ukqevNzLv&60k5e&a5n$e!ncBG*&`MXsoPV5VGE z*ALB&-8z2r(kBx)C;lwF)Uf-0_4;|Pf3f=Hyz3;0HB*Nln6Q~4v+tU9?)V=&KTF>A zeNO**+vi<>zWEo@(w4)}AzO6<6aoaxR8+2*td7dB+_hhA-?`}B^|Kwfx--3VRo4#P z*|Ff=HD9%B*}Lxd-x{fg-M@Qirm7mgrC3L$z6RhVp4x0}!wt)<<>Qvcw&Qp9{oBKL zU%PV{l8YOUFV?;`UvmQ2agxq2WW@j=zLSv6{+u%Pc&VS8>^;@&&np>BR~s?*?k(%x zXz24ZBHV6DL>hG4q$+GkcgY!k=Qu{BOt5$MCE|i&5(Rloj4LeWZnLC~7{=B-Mgm0s zTq#moQktyo2T6e#aZjJfiKM5&{(SbV-z*M5tMAHDh&W9cIt(YDRlyPfA*fHfNIfXC zXLIvV;W~<-`Rzoi5IN`}Zh%NB3kLZ_7)-B5X%tN5ps5C>XhN2PL9rVf?Z;>@wzPx7 zEJwnsbgp6rUQt3S2$v?vs^SbHP80k~B1G>|4;aR1UNIXg?0*l^M&Xb&!}da9Q? zI|fwMQ~=5JY%nBMZ)Hmvq*JC5T|U=l2$DL`6AUyMsY>yf}4lTea`{V9N8 zECm7j>vDe{NWRzQi!7C<Wd3uylgd-xc< zf7Bk9+^baC1zMDOHZRDfbP+4Rj}zvUx%6HQF{!fBr+`kHlwplsFL7%5T`zswDRV)K z|GU%ttF`8elAJ2|mR=t{FcyP02*3RF73%VZ%Vsva&8+bfixOT zr<(Ak2b#Oo z9?jdJEvfA&7Cmz|UZ2#?`Q&!gn0

    TWCy9v~#j>31n!I8;rz5;<(mb<)knRB8d(R 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 HlGFGt! literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/_struct.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/_struct.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d752e2be9330f70229b06b13e8167f7bd259dd91 GIT binary patch literal 3633 zcmcImO>7&-6`uX!@}K&p7)h42mVaW#rsztHEGcG+#&HujiC`dhfzmP-%iW)oOiJgS0 z3L|P5kE)T2paT-yWYlN}8S{`>2O00NNqR`U$0pISnedPyim>P{qz>Oj>Ie=#;{06| zQY^v(9s$X1pZEKEr8@eE@!Q*rz5Txai1q8j)Bu*TBe6^mU>QFW%dr70$s@7M3}Bf! z63eW|k_7pD@1~B#GB<$br6aM39?RGZ*K!!?H~K_+egMm1r2Da)7{GEE>3%FH2e2GQ zx*yA_0W61+?#FW4W0?RsDAN5{ULL@580mg2XI{99r+zJ@y_uf5d2qV#8GpsINWrLI z_Q{WP>M?clE?>yJa1Dn!zx3Zc>QpzE@$mM|=it*_{MH48Ob%xXb9JuHrDt}|N3Ppt zt!&rDQcYLvvY}g|ZHOwCHSxo;y(JdQx@^`(%QkC@Z7oE;qx5NpL}gt!Y}vC|Pje)6 zN!B#EsA0k@vSpLdRnxEy#n8T^S0NY(*fb5(qS_m^QVE-&g|F4C_-9&KwoLkzklU)QUCHwjbx=b9ngJ28Jmi8gMMs6WPo6uQFh$NCC$Fb>Ln zgi(Qkmxxv2-2s1dbvDg+CwLd@O6P*_S|eyP2fSxmhfS>i5y4h@3u`69tFkSVfMv_3 zZBaW>6o0&SX>H>}!@Om|it&cNZCe>xQH+{ym-WqzVwiZN2wT9qy0LH@>$f-FEf+Ve zvW+uzi}EJ6HmX)#F{+zc$#?lewN65kq=0uNX=l{mCoFZL+n0i=ExN=8`m=QaHCj&# zW)f;MOvMCEg#^FG2bM4jwA z`Wz_tk^L0g?nI9c>V7KI&E?-PX?A_*Pl}g_qFSp|MKAujHSucQ-ZFGihBQ-btcu0D zSgdV|Czj6V7QhKM7VRzB27$$nyEBR?>*~{1C+oXG5oHsLknYbg+FNByEL&C$FNp7B zENDJ2KUZOzpF5IDf$LQDGnP0l^EzCJcdZ|EDCh zR9ZPtzcg!$Gt#pCPRFULnyQZ}v7;h*0yc7!vhs$s>$)8a{mw zlq0=RuGeaX#5-1g(4K9=5;~_^(y&fK-g>CkB`=vqg+w|G0C=$`LE62AKl+aoNJ1C= zR?VbBVTyCWr~a z^)KevT9dCeqW6B~qSt;980H;jH}nId_4gqZAK6Vg8RzuF%!AAx?@ndfQ;V&sMK`w8 z2tNVvWhd_}Kg>VK?~S|D3+?Hp*7TAa&ov@XV#EIz%f#sJs#9@F4=WEUdvCh4KWWb{ zw`P~!#DzxmNk8x(&jD9jvny_56)cCwcCR>hoZAoYJh-!W&7E6p&#kuRR^6esM(laC z{|n3E@!cEEO!M?-nNKsH^X~ks?fHwX`HSvwz7c=Y5BxeYeXsO~%I_-9n{MJbtUfxl z8*)xK$!5Sg)*3#&7j2(eX`NYdqpOV&jZ)gV(Voe*W^!)))kfq%2r$C_DB?#N%fHQk woZlUHxrsJ6-QuR5OD-oiFMsylr|*6KihDBuH!lBp^wh`i>~n~J-Mftb4eGr*e*gdg literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/_tpc.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/_tpc.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0e27a83c5d0e3a36d9885e9f4feb3b51238442ad GIT binary patch literal 5565 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/_transformer.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/_transformer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..76bc1a96ea5ada6a310df0c5b8a4be74afc24205 GIT binary patch literal 670 zcmZ`$F>ljA6uyfc$8i*;wZy`Ju0^VpAz?&9g@pyF6)K_(7^9Qpdr6$yckbOK#o77; z5F@{V-@(XKF%(%sDncE)Au1Lo&PfAVc*A?&d-uM(_r3enZhOesTlz5hh!Of;B`dR* z0AJ4yc#mEnh62PetED)r1vQMA#q89|?7&{&dRot%z%kf?25amZ7C5pE&SYbC<-ZuX zMbq$I!*2#njG+0yuC6zK=RJWm2T8SoW(cv%ackMT6J`m*%R7MLwF}(nSuhOtpWwni=HlvbC0( z{tnFx`d1Xlr(LgXP|8G1Y3Wfqoa(6rN@evcC6e_jxHMi$l1`O&C|w)K^fpXYy2gD# z*T$pYFCRY$PlP;DMhb*{qE#=7V=?7A;iFzGB!mMa5;zO{GvKpuKN*B7(a^imuEHBx z_tuB)=SAu6E=PGJH_c1cGSq$JepndepEVoXzcvuQdxYruSzC?OTRcN!3H5jL$u@7teC>cq_#n6ewSW-NgP?IMW`S8>G z#N_y>tlI5^r({*uUc^u|nm8*a6QUxABr#IddqhdZ#N;ViRL9k%923K#WGI?ADTd;b zII1L`iAb`&7#?E~bVv$~CS^qxBO_v5mL*y0wf~MjEx>0Tp?ExzWQ$V+rmS&yd^~G? z0??skLdjYa&&WzN5t6dj!}2%AyPrkut?HDvJhiO0Y=H9K2$HRpx^lti1gJgX{_*rg7 z{W)Z-2-_&xD#9)wwMnuUATgR%S}8e-YU~wO(kwZPARHASR!LPw5Kc*yS|s-irlBf~ z-zs^E+FYnw(iCvZC$s`aui_p3(L@o-}FWG@}Rn&q;5Pr#V9DDp|F z$l4@18i_@K5?KpX#1c|CcmA9aGw1&Jr6^uzxCwrO3+7IZ<0cGvBNSn2!icvVQ9+w< zj#ohtSq~aTgE0X{A0MPwE3n@xyJcyzq z0!(S4tQA?nk`+`rI-+z?O($htl!=t(p;QZAX%ms|f2D8xv9k%~j5-<$%g5rUlj_<~ zI1I!|0twfK6N-H7L@0blj!VaSpONFw9NQN;aZJT7two13p_8(DEVr%eg0yQymU>4) zTY|wzJdz9sQ{F*T6H4~#RkSemPmo>U7X93c`bptsTgF#|hc#2*iiayx+x*>cU2R9v znXCDzws}_l-o&KvigO7)xp027@nXXtHkMy{0fiZGo(b+WO6BQv{zwWfKjb7F-Rb;6 zl(gU&Pn!!hdI^05v{?1`!V@i~AK4Cb0rNnX-;pwG7gH9o8wZ6#RgcKdP1IfufnA`( zwqP(E4XJ7{m~{q&-xv!;>6nATvJ-rRSGqBaN*^sMV8tA5up*BtWgDzjZ6VlxWEZ$Q zF83v2#x?C)@T{5htVz3j7CC;cC*$$Y*rsih-<<8b+Wva?Pr9!*T-*7!{~w$GzB#@1 z@%IgjM!sqvzi2et?8+Jp6wcpUyij7>O}jS3jdMyn3U6?47_-K3RLu%u5N`GbDs{s( z)0S)+k(1$5DOdhNu=kw+VOJ8j!OHn-m(NGX_B_2ZP8kL_g=6hD-(s|3e;T3en zpu-$4UJ*Yb==BQq^?hOA6*`0@By06@VP&W5^t!_Hhun|ybn7`jU`lOeB7hhw7hWm} zIy%)R%F(OPUMjRmh1QYkkJ z2!=>{P->{!9#JE4H5r1CqtKC&pb;BQsG$>4aDk8-gd_msmo*33{RCpNr#6Hp%Fu-9)&6;3Angp?s;Zq8 zW)nB7deOAtYn$`6UG2YyZtK#{bstwZW~z7nD)~8@^GEYh0%wOrv+j>fGWai!q&1RnRGZX)rt_f>{Vr*@LIUY5}0j-*O7ybQUN9PZ#Zv~pxsDZ0lxel z^W{;eFzkm{*iGulSaM`5yT1WP){qwz}KS&O6=}3*MGFZ_9_?wx4|ETK}(3 zec18X`w!jniC6vezRqi1ANV$8{IxSrO+S?u`)>OCGalcJW7;v>x6rh1u4&y{!hF-_ zx6SVeZ#{d{^QBB}!_36=#P^=PBz$J$Iv?j3ylsmf&f{Bfi*s%ac{Mrj?nzsFKJ!v* zy5q6?fJl4W{{60<^LRC=PdVOJ_mQs_eAZTXUwstoeXeHDCT`Zfr`!1YZr`3J)4SWP zC|@^NQGLD1w5P*%y~RQ`-KISoEZ5gssD6{L&u+Y7B*xS6#(>>5@@!*WzdiPzfu_zyoxA|Lu1E`+$dkdwNoCajJR2jh$v4|`OB0&MOmJ3 zDEsJjKV<`y9iZ$WWltkpP7l}+hp7E9vSsApQB7~uH;`#qd1cMzHCMw6o!jO*x4qpy-}%Tpo$t55(>&jBaKV2t?LU}lX@9-x zCry9RywJGrQa`9gQy-7vKQnT5t1;(dbp@)i=tJYZOyiz=cj^Z2W&8(GUUzSi^}UDA z_&?XU=l&v%aSwyw|6Fb0-|spr)0Y3O{uZD89N*u?ztGU{;(pBc)tIjsQTnN`Z=3P& z_`W*p&y6VkeOq6v>D?y2ufh86%GD@exA1*U*6Y?jf%ra$vmckMMn4gd3cI@(rOH6W*xdsa(ec=0*dLzBe#F@@AHctiILUx5;*+o9|oW zx)HEYdA)_;x3Iq3%>53_jYs%?gY!Mkg7SM73&woU8F^9UKI#8j;a1K5bHfC=Z!f+S2zBGYPMo-jt`I75uA=b(}} zsf1!N$fivG3>Y>4SssKa=kG z%6#=#)6TClp>ZHg-=-%}DotwqTNKD(qSQiG)LV<5mGtuShIlnox=7K2oHJpp3PFqHi6&K*W_*J(ge+?eNfNW~KrW-EUe-xDiZ-Yske?x$<>pmL zDq_7@bD27lwd(U08Ef>am(f!tl74~v1XsnE@i#8`+voi43;xw}{?$`^f8%Vu<8PW7 zm>!tid&gRJ(Kcnf)c&&jj>CO%*NeMuJ0JSBvtf4A)!Gl8fkg}FY|zw;;)_D+1FkN= zM3tP+pkh2~8M7zIzJDo4}%~i0T%%n(_dE27>ONS2Z7e`MrW0{z= zfA#UbhxUreUW_H~6u+74eBOTGQ2*XT;+`W~lRdyIB0ef0Xd0^#E`=;e2)P@wj$kqY zA(}1Y4MRbQR%wrQjgz=+s%{V~)l6}vg8Glqs;)zJf&189eevwn*+qk;N?0=5JoeA3 zIfr+ubJlld)#X*!{PXp_lb!SSb&EcmZT<4Iq&eAH{y7SS^pz0)ya8xid;ss25Y?qf#o zOCY@hDKc3ztez5-eU~aLaFPV^r$YVFi7!+3=^IOoPuaTQDHsw8=Mo$li!-$;)lxWv z&jBIjMST((G#E4I@n0OD8lMz0z^8|&9-i&_z|jesyx{AcgX+>T$CUa^mG|P&siU*| zKd1^68Ue9B?OcDySGW9}h*hw2I)?(zi94NVkEqC{0^TSqzJLwpu@V+28k?ocr>K)= z4Fmm!P3rFGCd3PbvQ{wrZBjUX$z<1#8z{=)tiM*ca0ZbXJHb%Nh5 zIJ)K>UDt%0js=$znnak zkl?9{MnUjTj57`}+yb;@j-_Go>?v7e3kjzDiV+q5I=JWvP?38FG=^``=yr}EE91rA z2ZI#rQLOT^ig&RNM$%#KwK}y0=g$Cb#30#O_v4IbxRcy@BiL!B^X4jHmVRDfrG{@e z;-*x<&5BevPiy16#Ge-?1Z898c_o8nti;BX4y>G|WZt4$uxaY+B4O)CM*R(|B=bKh z8D%MFQmXjn1?3ZJoVn6kV291^815|$Ee~PzEZ?oHV$Z;R!_ni6H-l%JL!+Z08ch9R zewnP3$SoX7%-5L}PA4MqtT7fEg*!E=Fdm-c*vx5@6-EG?HG%OYRlp^ra)#}p@rdmN zrHDEj4UMPj^Vhz->7TH`oLw>Fsh%`tz@wd0&P#(cN2ZV5w64l**qq+5ds4a>or*5F zy5?Mj7p}GMD3ivI9IlMhdvV{?zS#}4hp&9?^4DGqzu9(8{fpTA%1!B}&2K%OuHSOg zx%H02b*X)(ce?ijhp2b(-*h(LaeIlETpD}n*|c@#a!jI2$}Z+s6c`c0vpk(HzRJ1A z0%1C=IUfQBZKK)7#NqN5yz=?eyH7~H;1ODg8+&(kLqB>WQSn-$g{m~#hU26nGY zTi5+Ztlvf}Qb7{s>wD#(fOUob^Dy+L>&fRfUns={BTi3942b>yir2wp9j1kU! zhDXYGs7|DewYKC-tth3c32BbfwEJ_|cpL!=W<^epDRI^#U}X~2edYr`I(VF!^Y6R+ z^1g+m2%R|2=D+XPLJJTQ(ffo14UVC=@~4>SzI71M1_Oz>oEuM>q=k^QaNl3%z$gr; zyhuRQUwH}H@~*zph=+^vVp4T_)W}f^`#6ei z=@Dt0ju$?L`RX9Q4imhuIA|odQ4BOIusstrC(0|d6t>hVl+c+;Tlw0oa3Yb2E~`#i z=s+MLqh%ER5Xpk`RuAP^u{PkJ(SU{lc-Gkkx{r7oiVvaL8Ld#J^K;XNVJM;?+U;U1 zqV_9ZKV>n>WXirl*|U^gpo~yoAso`YpKGWTpp2{+EF-?8{st`T1@04r!DNMRwYufP zldx3RHDv0WGMyVg@w!dzcU;~@6P}PXQL<2poUn^FDml686^m6=a#5X|N*=DdeTjN5 zwF)LXK+LX;$+L(lYBN>-MI$|%)@aX%9%IitHt(k<)Grx1vzId0qJURSRH^TJt?$-- zU)0yTXz-d`Y*KnQty?tGbIVigdB^7b)P#37DT7?>#PpvU+@`g;I+PY$QMX8SY#e$v zVFC2q`Y?O4#p8WhAFJtWJnO^?O{*4-tkCs{R$%?8CfAXQcl{pI>cw`p47+K4t_7vV zI#y>j)#st>5gI|uwdUcd2;{ zUWCA=;&39n)JVZYLw2c2a^dMfK$06zC+0`s&`{O5G0?1B!eUc<>|`JT#Z89bEmB12 zxlEiUeXKOVj;J}p-4JglN{Er8h#$?uqO8O~rRJ!-W*TK1G69zcOj2TH4HXeMfYK6$ zlN4fm@WvP3#z}KB>5zpd>2Q=_NFp*r>ZFZybfye|UL?-O;bsoOXJ!gVWyHhjfGb=k5R<4^{xo)!m<$+9d8y*KTtzDCk zf9PCw$LYEF> zl4)6k5#9`^%8lJ8)hpQof2wi-uC-%ys6dZrLmP+BU( zQ{*RFh*X!Q2aZ$$UK^>h!h{*DWy9k&H@AIxi?RVdD%4jV{Tcp&YppO&Zf4@MWvSSf znhW(ooS7FcV|7fC3pbhZQSCx>VF*ox5UE7GD|f+_(r!%Ne0qG&+CrAe9WU;f?Z2|`^1io(U%39pHP^H&vj*sr8*<0x9dpiZ zutZzcMaPumQvZk6`sMgSC*DS8%b%m5`B)3S0R2{;CuOw4t$YyC=;x02avZ{dEEt%j zg2!Tle}-52m%X?R73|)Xdgy8^sqf$CXLv*&tQU#{s3;s50RimjVD1V<#}FN9KyV=) z4a_d2KT%wv9MAGemG}y%b3O=-0wxiJ#?+9)2_n>w)q?X*h~%JQz5 zX`XIg@OI95JO7)vdvf;48R9xxZ;;q!BC-?@A)x^p-IehFbDpooS0hWMKNEz`Xi z%->RhITcLk%0m+fY?F))+<88}wq&$CJxk{4)JQ(eOsy@LW)Lctry2#lyfiG#Mr_hW z8&#Snc#>BsHl`5kg18nB0_(gwq-2`le`t`*1ryJ6d?Df`b&UxNxRLPCkP-)JU?h=? zzYj5&T92saJuxuMF&jT53Rv9j`M%p>YYD|f+>q@|)F=WH6Ctix8Hl`-U6A0ap(|X8x z6v{atD5xz}i%8t46z{@d5qJx!7h6WEhJ+sdRVAMTlPm%@g$Oy*@v>IfpwzRGnnC`)N*2O* zYh1fKxOY41ckeR(q2yuNhi8pI{c@Iss#Qg}`6t_!<0j_+JQB2Q4&`qETw#vZqB*wh zSUv|yF%18EP?&*bm%NsF973Iz^08qBOfjT>nZND-|1jmt@o40XEDje@-r*ixUxvA) ze18t|48Q^Q*Z8(Scq2P#Biqme7JrY?R)`>_)0ePBI4?-?5ScNEIP=t1iP{!^)KazL`cp^!w5)2!EdF} zfgCw2B1M%6*%wnV?F48t&D%*+;%7uUi4lpGh(t`p*5To!$A^boA4LAB8zZ6ca*V~# z#G&q#5kklne}(VYY<8U}9`3eaNK^b%6rK_ z_2eW^LgCJ-owNR%j^>QdKlAYP!)aKhQQADcc`~O0(fR6$P6hA$(g+GU^kM-a@R)Fw z4bkvuR5(kpO00+yV{Tdzc_qXQ-3Ms-v6pbMVN#=>0ACvx)v*)Id_*p$NKzH$s2ro% zks^k*{5BvcUt??N&G-jc+Hl?xIb6ckL`05KG)ie%RLLZM*nkOKUDw&b@o zy$B0EDfb?tTw5l7saDdxyhCg(nv7_@_UDVNYvG>cu5xb8+r>fsQh`ezc%onD%SGQr z*G}J%5>8EDKndP@qBPoA#XFF5%3)u$-9^MkR3)cf0*qasA)=OkQ%kO4xEH%g#A{eb z8GR90DIF5~P_}XS4PLoiFo2uSNE@*PrbNNmNHRCGLuW0yNi@xgt{Q!aCVso<_MaFJ z=0H+SbWcigqtLpCP=tPL0TijpQAEr1&dGkw$$W0=+^la_x^n9Bsaf~DyE|>|zIWHe zdFskSRT-@`wR5l8)*JttUvDh=Ar6V441Y+?`#gt^+V#h)L}eD3BE!TuR2k(}Oowe` zh6pCs;3p`fL;K) z(GN43r-IPpIPSzXjC|jwxg5yd!MYLe*V}xBUpK;Wk^6xogQ_b)DUB#E>#O`yuf3lS zsMeRQ&8+-NhtPZzx!S^L|Des$L0|`LIQPvFli~v7{5M3eN zP5W32l}HiO;=f1{RveTaK!!-L6JdoAQz1$=J>Y%$@P86_5FtP-sbB6nQOnz zHT*Nzb(?Fw&2{|R=(#O)-WE387S{h-a7^}HO5GG%FYuZAEf*Y;6J4RF!>ERS*;`ZEA2tC3$R`Oo2>}X7@Wp>Z(Nlq5R`9{fo(lBjTa8svpqKQ$A+;vywPC<5 z0X@EbGsE}hz3+Q7`upHuUV!H-?I-qM`vl>i_~Yo2LxptifwCo-!lGajQ>>76aZx0K zDEvY&Gxr5kdMJi77c<-@gDq=i9%dq|#H~57Dlx0ft$kq4$E;ay?FZ{X%$lnYs>gyq z=YQjR{wlK;=0Bl+y=u{Q*R)q`i+SaI{?;8UWu#S|c@{NvU$3~U)OJ=}wyyiO>rmgN z?y|4jprx1P-4&`+!>!cT9Xid&o!Yv^Yy-dNQy9LhGvkiVF3r5BQkPNFGVFD|a_P#{ z`)WD=6nCwXcE9d8uFu_hMwp3EM#&r$0O$dao`_yzT&zbP)n&WOz-KlqnAzc)n z+n%*jt6(xr%QKk09A?m?8@7LkI&LzbWxmFU!smNI9jZ(^C-_zxq#e7bG*1W22SWC{QzBjEKhFf!d+gY79TxKmT>&BYp zm`mlmmUDOM6MK2dvwdqC7Od&3mbX;(>V{igy{sV|01f48y{%}P?byDi1t;SfDj%7L zFa*H5a8EcG8g5EoDINGBBsPWyzA*`uE!YanfwCv;i40e^bCJJjD-2209$2+}?Ff>= z>4fw6&@fEyAh{rb!Vnt(?KPaUV=#{uKqQkjw-cV`RFT82ov|H%Phv$J#qGDV z%<^l@35NYzwPO7ahNoz`T>d?6&^gz!;&a& zTzW1J@h2}JU(&n1T!L?;+DkTSFS)3_OU+RuovFK3;^y5vY zoIowmC8W$E_uCLYC7`6926-4+KNDdFu1P(y8JULox!B0u6HQ@3Xn?jNE`&sc%61c} zN}Q6syzRa&>e@1ggogyiUKeH=3lY#BJ1xfvdJ$%MAAkUYmQFn>UED8S+}U_sy4>tL zD3-R4Jvg?#@whnAln+K|Yvj`Ijoq6~zopForSEUEt&itHdy!n-Ryhja-4YtaBx_4p za?r#8n#uwkunU5knPWKhDMxEh%JZ!U<1gDpHv{kDE=Iy#(23odZw8th+vmRctfgFe z^bUwu#CYX-j1UYXb&OXGpv#$=0161j6HO_KUo>SLK^w%MjpE0=KmGoDL9hi-Z2=lT zhrF73UM_Y4LqrgC3xw1N#$L8JUeYoyx(ouU(|=-f{>u*!hDQEz{M7c$gEKqX{o+Na zOMh|m#+TO)N~gDPJh<7saZo5V2l#&H80Md0Pf~Mi4E3`pczXdxZC{y;$YivWaI+vUZ$YW9g6+ z%=!?b=!}Da+7(MriWl~a7j{-37t2lg+cR`iZvL^QOzxNdMjAgWKZY+HG3e}t-Q!>jh6D> z?$1D^5x{-`^U^(I7Huf5!(X?|lif1Ugk{DVZ&c>uEqmQc)cJf=XCDTpnN`t!%jA{z zp8qS5$S7np%;@X4i_g>TLM8l!iZ}YUgr`!E%8#W(PLzHg^Yso0$b4bwNnw1yFupVK zxG>q24o1(mMkhBVEJciriOqE3(X(N|F_vl=li=wkNWt?UINLMW?s7%Q6rTOFcOC!532kGVc0-!Bi<%$~MWTO*hJb)5q-l#(*J!obow#=FT{Anb zYs*17AkkD*Z3R*)wTFrms1iqxh&CW0aY;m_gq0DXibHQE2~t%qyjgpj9FXWpp7-|s zeDnO?H}g|07D2GC>c{h6hzLDoAHfpZ3b*k!D2wPUvQP$DoW&Qp5})BYrVB+OBY+f( zVoAzKrBEgWcF77A!zDQ*`+B&jlp>i3hj@gA!j1rbOIq?>uKksXVyTec@&wv{TP@`_ zpNU%$oUpo%L8uk8q92QyWKGcG_5R42d+G4) zdfLjH^!#*1GIq(tWp>#-k=DxClXcyOBXnJpyihsEn!zp}vw4#13%;KBcznr~07Yf%$>ivf zY}FyNZrLz#)-F(Y*f33}VpBM6*mMZaP8;Sdwyo^QMQmTpj_0SdZl2;{NSHNp*v)n> z?n^qYkCba(B!?-eY%Zi9&S7+Ne}HWs{c-r{<@Z-(`&MH6?wo%Rd-=QG`8Qj9kCbXA z`fl!DNenE@1CN_sJ?p4jO8qjZT@NkBZp1!Md|A0HwfLyAr`b1fXXw`6g_Dn)$z8V( zEGJ%AM?9FLscRDp6U)!P^W)fq=v1@2Z*ljH-B(UF6T8+?_^E#_Ik}d6u9@t;KJ}Tr znjBb34y+|pn~D^RZ$?on&62L3{HK+Glqane+M|9Nx&F$EoL){ipQD0hsA3m zVV$YR+HYa!ee*)Zr#fL1(z?B{u3L_&>+sy^GZnZ5FkZr*M=#8n0WmT5o6jU?3n@#(@ivNa&{zU0tQUC8s`tr_ICB34gZ@&7o tGBh7*g-}<|wL=Ss)}p=F#uvu_l7tue`N(o~{{|8`elxm*OOb^c++ zsi;a-c!<JDIe?b33UqC!GTJ^1efXIm&^{MB~u8jc&l2ox7Y0u7lJDxe0 z@5~)pesBjRV?JgEnz=2cU_X6=G96le>!hW1llE zpQp@G#%-opg$c@Xy5dgdsgsHo_vD=^-OguIJ`gma@4hH4Vpz|GAPDxq->qW3$ zqB8WwbO@{u8?r&hRdbi|NpbX?@)FpQgO#t|6DX31AVx_N{oqn>=#a*r3U z#T00lY^GDiC`{yYR#wrJkEh(5wxx`==PY+r(Hw+q$IUW2^2wmm@7yu_N1X}HG~sy< zT*pUKe4P^UB#mXgFr#jPS-Ke5fj6`XV^ux~;zwbgxN!H|oH$MHL#(ICwD2(a%?K$8 zLnYA*IR)^f7g1G;gQ_+~nNX3(kXqD)sT<&!K3mn5ETuV z5(kzO?TgWNhUgmg(4SmAWE`qDO>RMNeY;f~(cs}vkdtnOv1AU7X(6Oy3_KNomLZzb zkSBC`Lb4=t{n0E-o1kDETFKCpY!8T9!#G-O3Eb{`;cb{xJ^}))depjiKJ`QD&(`Ep zYjSbdkzd)?v|VtAyfpA0EBM!B;*!z?n2l8J-=z!P&u3Z=TmI488w% zcJKsZO}HYwQ%L1_@B>oK<=#pzcj3gHC^jSpMvo_k0-YDiTh@jPZJ;tThUX{l%JcIm z&U+KZhFxEKIF*nSvq-!l~hTH-ab>>|loalM!kN zLHmjyy)r?^a#`Re^0TjT{Oqgnvmc#VFMi^#oS&y~*X_(t)YRwaSyXike!houP#nk3 zDnAjbJ3nJrEqBN-42#3B%+jEC>@ldGgL14fOl@5?rNY-i^l&}+x^{2Q+F{&#yRx=z zjjw#}eu@fj!QB%$2gL=roENGgx?iG(z?JKs0^v)ht+~Bh{RJ7vSSN5dTYzQ$2{kx-TcahWl<;(kH4u@(FLCvQ@$dbvbKCv;##aii0Q)f$%~+$h`Ju z?;={Qy&13D*4H5);2ab;;M$_zKIGTiS6(7laODQ&N?-Ad&0iJVQ=8^WUyorI#!RZ@ z8N4%`oNYDcrQ!3pTHxd{X7$UPYKi0EzS}!*R*RgwsBATF*clwIC;tF~C~jis9132s zBUE?RO2av$IIuZop~8M1VeOpJ7;-j)-jx&m8+2hkm>F!!kMnPF)9p&jxbGeRET2V9 zS2?NRa6KolAc&#}*NYV|hhE}9#+8SX%{8x$!?>Y@g8wJwg+G=!>?{iYe!zU-I{BX+ zc#iN-Y0;DZ*P+u4i&z0J2M>uANe~41Xd}ogyGe7$Oyo&8A)FUx-+w~z{^a0Rqwm|+ P%)GwIsPidblPB(fjyyj4 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/abc.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/abc.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2c7b0bc6b0b196bcc036a20239cc184e3f682552 GIT binary patch literal 10826 zcmcgyU2Gdyb{>*LilnGN%aUyQZ)EvLbY$9&9XpYeY#iIMT|0{WmrZDUsS)Q&VoY-A zJ3}jE(?E+jsJrN*LAPkMKp*r{)JFP{hdylIvTYw0Xdk4y1=K0hI7o_OQ4~-r1#R7z ze&^nq;ZXibHUT=e&fI(M&pGGbbIv{I4*#~TEvex7Y3_x>&{jqHf-2q)n=hY^Tv<^iHaxEiKym+_nT0 zSk}V!Fm*CaJtWLNCHifkexSSF*l6_s`KFJss`O-sS#(MWtoZF2pE6RDMp&bKZ=l4kn1puGIc6s>~Z-yB1SwV_=&QisgSoy z*=I$|u;d6c?Zr%)z)a7H`S$_4KY$$(*aN^m9l#zH*n_|x3SghFb*7)Gk0!^sX`6Yo zsF@RQvAk_*oK-lpSlKR=r!=E5ImtLGTA@@avJy(VT`L5~o<1aosk#)AFibsen*A;>0~pocKj{ zqsq#8=CoaUbL?d9`010!&z>1Ql@2@Vi9+6XqL<6y;n$?9AQrCN0E~~-UNLz|w=q@Q zxq=M>#fvt_+)mFGpO72!T;R~G?+j8Rd~qv$`b&WBd^0QI55lxzszGHish zk%VHX3D{5LpAj`8x1w3K7EZ^UI1zlMTF%!mCpA1&)y%R`w>(J7)z)UF3;AhnN~#hw zwDGa?sElh^2I#O|;N8ojGPX;q6A zC!Gl9bYhc*A}gCt9I`WhQ!iT7nRt6Jc6{XOjLENC6+O?cmfy0iy?Q>6%^~yIn>RVT zI-%#Uv$AnDbCZ>CUOiWsxN1Q?_hP_xeTrFED^@LUR;Kpp6ZuR9c9P5GVJW#>y~|sO zjE5qBV9_ZwtK4tvTtPwMdjZmMz8|l;+?OjCUcbfqeQX{JI>{tWG+`SjcSp~sa)UCu{SJ!q3Q-@Bp4F zj}HgYRc@Jld{|7@=q-q3E^)nVO~TDF^au=+t%92LPU9{&qo&PZIM{i6x?pMeuVWZ^ zhZq^p;bJPw^!>l@=+Q+oG0-fAVU~B>TA9J-Y*S-zSBiyv!7kR|8KxPBtxj^YBU~X;HyYl+ zm=#y{lqdV>-7qKHi!&o5dud6oOp$sIC$(DKTf!l1lG8U zmk3AT6#gvQIC2#UxQbpS*8ZPx8mW~CO3PGQjtgAW#eEe?kI2Z(P{}8_<&@E8wBY248tq2>mYR(j9YzB07NgTh;vF}-j8?o8wOD$c6O+ei z{Z+9K*rJ<|RU50>(@;?_exkq#Tdj=`~92DLapU_^dM2Wk&&?r zP8t!z@WT+oiI@drG!HXrdV*#ny}wxEbVOKz69HAH1=~$d%c8+h7uPCsxk9;M<7DZO zg5X?{h#Tl8&a_$OR}pCpZY=JT4w5BnEqdZp6zCe|_y7vuB(kr=BNYmHXzU0~$e#oY z2JUHP#o3I1QNz~cP? z+12N} zQi_cwbuZ%VAZCQwxOs(3gAS}>5rLd$BRscg8iOIEWAY3}4FdS&X_5wWR5Ns2pFotJ z(O_UWpe$QQUNNlcp4E=Oi!RJAlvsue<62%X`}0j8zoFx><_U`3M?_`P@Pn(~>zR1Ba2u;_TIqJ%&x<7p$7q zA`T$d*gNp2W5s*{aPA1^s6Rw6RqXmW9X9$}JVF2pTe(5u4FsH-X5bYoW(Vf7DlA`^ zEKt}3C9&&;@}w!IgD3&X18ifl8eCdP_#}fCgLxw=cNY=cO2O0!t?kn|LCf|b8UB!l zXjFf8SSwc%^c3U@edCJF2jnx!;cOlJH`8=a9P~hdh1e@Il|fX=!6eMa64@?P&BtKnENzGqB9SZwxVH**n93xr z?GKP4rW;BJy~Xqv0v)Nhy5}Qc7>!E+?Ee(AbMPob>86xRM_@SP6B6;?Fln6Sru0PA zy)GCAAq1v0FLYQ0Q;?}((AC4F^aymj;7{iIDt!v;B6g5gti9IsI1wn$PhTmrlL?gmB*(xBg@583#aAdm`kY zdJ$lP59)rlO9#fU5IB1W2JN1=;n)n^DIi7te?1XigMZe>1Bs51PA)d-+B6*81Y>2| zY;r~-0uQb{DV4vB-M`8jno86V<1a&BNki~AlVo0W2QjL^CTR$PiHxW1w@Sr=GQFw`fDz%g@ zL}Ug*k#+hZ>=wet0)0uXd51r05T(0MXg^EilaEX~I&!(dbt7&lF3_y66L^!rRRTXE zuqG9uIXM9xe-?$@@4L4aaiy*Ip4zjFd?UWxt|Z&uJH4cy|581>qEar>F2MF^YV~v| z)YiM@Ax|HNlMC2@f%Kay3Lc8?jb3tqti>oVnIOz&eTmXXbzcSh}kg24O`dd z7il-YP^n*2Sgzvo%&51zQc~rwX*FIUAa23LC7dePh!jaI6wjdqQ0nKHc{IAkvnxZ4$NjspnXgNm@Sk_`!2*vl9&x`692wj1m4?!?EMZoIn; ze4xU6oq>;2cz5GNO)uW-jon5c-aWNwddO)FoHF&^z>PQEnR|DSQ4yQgdntsw;wS2U zbBoMxtkEYXm%%(;Dw(vTKoTnrX?=ht-GO^fMamja}=ZU0`R#3ffV74L%ap955O@A+O-aH)pNBg$u*NqN|R36Od! zBS>Asr>j;A@i}=aT&4<#?<=Tx3-XwagToTHEcix1M0pkS%OI2-7X=yeHYr5}JSLh| zDA@8jvFBemc6Q6Pa9t4Et5~e2yS47x;0+gRTEgBD_O@4vZ(>;smV7yVZ+{D;SGke~67Xl0WCASM`m- z1!!ve4;m_^zrTH_PXi+wkx`RZ_QdMfs7n*`^!#uP~$QweGlH>s#(Re>i+i zQi>yYx|v=BztW)hiF=1h3LAVLBc7-6DmQ2LI|L6n@e=NvawrNB8d{&AJr($RPjIPy z^w%KhF7v|WH@?$mM?jYU9?e4w<{MnxqtWaKJnVnb0FoGYxUQ9b%kA~z9#}kG0X0QF zZDRUIt5;Lg|A6v$)^8a&J)G%^Z6`7agPV>H+IETm--g(qNU>%15^f5?=l~Sqm<+)R zR6Pv<(dn}Xehgr9PG2Nk#Dfm+R{&m~6X!ED=#L1HOLWu;(<}<7RPXfT0=KuERHbh= zNP5V7)!V!uHC#c|dQFUz!8p<9e++=0v&}u}W4|!@`Z|BK_cMoUg2sbBzoF@q>9vP4 zF#KeoW;2VA6Qwx+UA)9s27cQwk;*-2yWsv5;tC3qNIfBfAF6}L-*4*Ae@<1Bp`Jts zZ?#nZ2ZaC7Z|soa6(o{BNx(!Rp%B5c$OT1aA{HZ$QR&{bxt<>zJFVgZse~I!)8J(y zafZN20yhX8CtwqJo4{`qc$dJB3A{((eF8rr@KXXG5cop^YhrGpDFprwf7agsyss>^ z4%|}*mf8mIse@mtFWrxJI>-$1(W+}nJ$pae=BP)h*1n`36}9bdZM&%Lacg@-E#uZQ z%PD2cz|!FEuUcc#?)#nFmZNy%`&V!Oa)L@prE6fB+R!oCzS4%$N~aRN9Qs1Nw5*1s zyOw$f>2vz7rOZp>eLtbC;IsO!mADc;@P&H(3-ygJ)N|5 ziZlx!{yBLaCx!zRK@=yC!s*!HF#>dwbGl>V2?9w1tprj4j>6mN70WSP*IFXIcUll; zmMXfb2fprABsV6yGi?64857lF^B>WD7_fn;02EY6u9{Q+#1EJb-UWAn^=@s#{ z(&?l))(s?clo#@T>c5G=W&%QU=4g0=Y(QL(I>{0%nY?zhz-DA_h9CPW{AUCxv*H?o z?F0r12tD0FrJV$J5!g*&h(MaaQv_Zh@FIbi2%II5CqRq6M!B5$^YX_QFY-S_YY2bV zF9DY$p->24LPP4;DJ3-cZ_1&2%AwDcLyH8r{;SgYsWSALa(GcW{CTAFQ?=(ab?{SF z`%K;Osk-M=b^qsGJs%i9>z|F^-f>Uagzwuu{c}6#H{SWJh5o~f>yOOFZYS<3NA7oT znA>tEdZ+e_%)-Xgi`{2tqqDVp%9*A08|Q}R5B_}boxYE|KhA%=VKF_j&_A-c{-_*y z^q;ymENo0K9C+m)x=ziuFKyX5KXGTr{Pg0MeX|`OY`mxJTk6|9cWGg8WMRw5V&Bo( z#O>$qDMtx;aei>#p8L^a->^guFZK4%9h^_hy|~!B2kfTrDSMVSYV+Omh54Ah>S;ro5s!ob0guYL0J!oVwweW&C+r8!6m4P9!Ui6IF2{xkxr@S1ayFB1LlP z*`;CWLf)mxtWz(&*G66??W@y++=+lqo?WcY=%V`o0a*+W&Ja={Vx=^XSGI#+wvWF_6kekYh- zwq_tp8D^isAy8(0Pp?2WF{E2`*esW64oBq(lR0;GuJooVw0;HoB|?cRfcXRG!RV@J z1XRfoY0!|KgxWBnav{;(*i9EwUoBI^MiAP`ZaX7kB#qGJpc*k!M)gOT~JTRLD%53Fa4c4rzn9~KA zn_|vz1K70+Ri^gliq@0@HaTZn_AI00FO4dURv5Kt*)>6ycf|rQ07nG#Iii_2z6@6` zWZi{zWL#0*9?N-4#7BzikQZ8`kXRxOp+PiWfucbK(g?7=MxcOt_dTHLp_q^waO~dv zO<@d;55smMIp10t(UB}#oMAhmGp7eCYe#+d8V} za%Qz`=gYH4b0(vc(|T^6mW|2m0xd60j^?K)t-MW-LW6mImRge)tClk>vyXDzW-B!( zq-ptb-qy5w(p~gyy8!vw+6!Wltf#j(r8h$#gkm2&_QdkRwSgn614o+DTgg96plpE> z$@#N|4Ei3vZtp+>Jd9xbwGGl{_g1U+9x(!2>Uu1P?)(RI#Re&O-pntC1k^}&xLwlu zq7i&gGUQ)}$4RDV%n_b+glt__4gnHQ)_XFFZYz&nbOiW4l?gf$Ld%J0TFEr3MXG5| zOw%q@^IWjh(&TYk$gwGHt}|3 zEp=cub>Mb#a7F)}bYtRHWbM$Y)kCLlAAEW}(SL1X>6PoRTzh_b_P5hF`hPQbM}NWnKR)Ob%rXdC)cpb=OUYCxW?OwLZ&_$mHuWz4Nx z6+-Pcowxrzu^|?so$_|75ol|SlLvpZ?WZnbPw{s9&b!moCCT=EWJ6jISjY%8q&lb? z0hHqi(ysia;MP4FQhRKMG=GQ?a4W$=Z|95clpz_xTb{Y0uOL8KuKzOv?two;HN~Ja zdbMbS|Ff&C%$?*E8ud_SN?Fj0RjOR5nl?2Qy=*9!4&={U)HtG8rr(P_2UNiA4IC(T zmD9`0G*zmghfa37nlD0g1-&e6XW)FY%EVmWQn+(cUZ=&P-xYXOr36k{K{i?Zn>Div zn&pGGQq0fOVojOT7by0dFI9@P1Rfi{4ZXR0B)MCp>d}Ncw7Ycn~^!27{(+{kguyFLKC1@)pi1G!9u^pZQ{`^$d|ny^LWN{ z$3VyWBZx(^ks!U>mcrM=%lqC=G=uBWRP*F|df;v}dG*vUPJP(dzjXNe;br4}^Idao z_p#O8$L{nUZw}v0Z(mCvSWO>Tp?A_pZpV&nrbx2)>im`YH%d)$J<+?C*t440vl6_M z7;K80GKuvqr&ps7Z^)#7=kmVmCsw4@^#0qi{TtiKwuhF-uaB-ATkSvC46H{JYte^6 zbNT$8=)RTepQA_Cd(%q;*9VqIR-U-id$>8Yp6qRgUFQJKz<LdWR zf_?*3eaoJ08{dtlyzPDJN8XN=g+M6lE!`}&wRu`YK$mD~nldjK@cY`T)s#|UrfufT zVpbV7&3W|pdD}v|;0A~h9Aed=ww^BnzWmNOvVCZ}qjR}sx#V(#j|!j?=mBU&;sB%o zIMtkOvJOfmE$)o=!PO6nzrW^Esh?7DU zJYO3uQ+qMCo60I@XTW*3Jz2-=S^i>Abs;=&E1rP>ztj3OnAEq_)ZVTs+NRlo8pA+? zoy28FZh{~34CFQN4dms^sEM8t43q)`HKW`(Zs;I!)3XCm%^m{r_H>kXCkQ>xcmVjKtj|Lu0aG5cT*_b!GZ#vf@5pXFI9K$mZbL*F!`i& zptT2RGTc2gy%>yn5!)bkau9^mqiKejYX@;jP3t9vq2!=L7B-Oh(+)V#ubX|JRYNWsWPjL7|t^mt2zH|V#d!@<6mDnx@jHwQw& ze%Dwy;T-(^2Tc!;(3$~x|7nj(1%5@qReVv1`AI*a_80*gGDPom*JFf?Ae`>PG-8Ae zx$9IHtx1`PBafQEI#z#y;~5a*p58hqGw!$`TFBdT+!ZM=o;?j`I0(btGhFvM&)ex4 z++h%Ig#Xe3jUyjIW{mQA+>r4+A1~n6>?Rh6Mm_1y+&@D77#r_K@r_ZskO|bY?X}Xo z&#`XI1{(#GcCSo!jDxKm)=P$N>-Wa>MX*CX>Wv9AKZBuIJs^PPG6~1-;W(dI9}X60 z$A&-vfnUV*2#R48Naak7J&Wl<6i6p_1_hFaokj6H3Qk)*>A0-nggJ-V`xt^JYlfl* zf9pFSItm)gPZsqEmjoVdvQ}|?WS(fo4w~s z0fz&~5n3uFekm*w+Z`XsD{!2B3l<8l83OGXU-*WTO6Md37YyE1aV=fX9dv?L6>d^o z8z8lv*bFmE8pJ1fwcv=FeG#mTp_=RD(e_SQ)A;_cX*{}y-DA;pXXpUyJMUW>AMRJ7 zwzVI`7mMV>Q2a{IYG~(jdU^IQp}`N+yVuf(SJQ`YoVk-e2A2k*4))kH(B!7PC8+R& zPTU(#4h|NYc2i)lLMcCQKkW`{9P$jsoA7Vp{nQti$p_Nue@KDg@y`ed_iL!~AH{~t zt@;V~{UB^0{r<18!EiHbo1Sx@)1EIa;^=FQ?#|UW`V#0e#B!HGU&8EbD1HE<+fq|l zhypK$*bh%K}s(4EHI9gW~(HBSZWOYw3mu=*}GPR3~e+ zTrF8VT7cV{E{-ye{kX>Oz2LG`E9n)60jZNhE_k=4+B96AGCa?7mj`D#X0YR!#jTZl zDGoC}gZmtr6ME9UD0+$&Kp8?-V%0&wRgEBke-fn6V?@~Z3EB5oa^MrP?Q@w3nUBb^ zkI3aC7Uhq_vF5}ZyB6h5`87f4Z;oG8uc*uEO@g`2Mj$1`I%SaA W91IG_ugz={cx|S5`g2V4mHiiX3whlD literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/client_cursor.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/client_cursor.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0169f210a58b9fe9ab70fa0b352b9d87b93f9494 GIT binary patch literal 3978 zcmb7GO>7j&6|Vl7|DJ!_*v8;Cwt?Zt0XDD^uteZBEI*kLu%gg-)!XhaJ2Uij57j-u zSi{OhNQ+mA&`OC+q)729hXoNStDM+F6z;irf>vX-)(Wd=746N)=CY@}s-E$94M<6i z=GCiuKUH1zy?XB-@pu$L`;Gcep$go;>7dm@KEtgpa0tyK11ZSh4Bq5Qyux#o7fhif zDk9@WGf)aDLEr;M&WLln%yAW@o8O>0*4`+*0aRx*4A^drG}ZFXNNu)>5C+$000|4D2rj``e~$ zW3sflz0|MtGd^R=r2%CC^kT(#Tc6wRi>KRsi&F;Qp!;4+qunb*JUWAn>|JDZ;9i`< z9aDS{h#w2Sjxx;TognYR!^W1D9CzUkrYAP_b~3$g(CY!c-gUjcO?tbkTXTIg!_l%+ z)$Q`MteXXFx%-`hf#u19WfUx!s}RQ~PV`&qJI8r3&9ZD)a|^cRz%V|3<>Ht+`rg>+ z`Lp>mFcB(i#4Tv%w{ZC=$9wUMw&P9{?EI{PN!81?hNEmPHVIaI`8v>mW@u#>m>?zu z7R?D>V$`-QtkdPjt7Ys3d^f?18qrF01HvWyCbbx4`vfj@kzm*Z1~z(1bMU$#cG9U@ z`ub2fX;rCCdjS|FeVz3+b^ksVq zpp8ExVg&92%p=GMwdakf5d@o1mCMDvw0|Q0{(e%pRj~4Ub49j1y<8Y`t54YKE5!{*A3XE`!cv-nV|(6 z%*@x7U3-H&>evBi@=dJ@)0(^P=z{@#3+ojZ@6LT7-?S^HAshCFg>oT6-#0HdPBhDz zvI)5N1l7IeB~;zEZeZf7Y|CE2?}7%_Z3BB@Y(WoklM_AB!R8d%M*RfYS2>#?VIpGvs zydMm%Y17!5Xh!Z2{K!>x76c>ZsuwER)1)v}o#}Z6RwGT(5bVP_17sGhrBFvtBRf>j z4lRs7%kH@+{yMyr$TSiI^~Au!@WZZWi39h9rDW!Qb*|b-_ScjB3*u+tPs0uQU|l}= zEO}@#d}tM1q0SzK4tSy-HnrQL zm8c0M=(enp6>!&acU!E9ZOOIW2$4>A9pkS z3{k&tQ*sQ*Bg8(D9UP(04kPpnok<{f(NcP7_S~8n4ZO7?BYAjf`;Hf}?SX^OlYJ`z z=;8W%wyi`c7e(p56)IbiP&Ba`r`#zH9X+uk2!Vm6tnBxDkFfrEWcykG=KbaA$~yel zTeG6!R_T-4uD=XU;i^2;iqgg)0vz~NZT^u!PJ#hBMad{7W0X)V`k#1)a+LfW{ti8D z`iZ@F&iOi2GLvkViC3X;eE z*4BQgY^GyVp~^Ou&+UfyN;PcVzy7HT6j*Tmgoc6_bgN}3EC@}WUSz6b=`O&|@t?Uc zLqh>OKH3;U5TUEHN{G<?1-eRciHpU~XsrP>osWtt|v;Axfu$X;r>hY|)^ zcB%BJHl42*KJG`w333&r6jRP$fvgA|$GzZrPJAgLZtxo&U?pziRJ`Y7cs@|!7^x>TkXT_yR?0(N&Pb1P( zkMzt2*Mf(*fd|or6Q94eI0*0Q+iM6W){3y^*2V15;_#6t!s76;diMB}si&8}xVDBs kuof1$txIC(V%NTh`eN6?x_IdG^G}8P58r($fP|s*zo{LS>Hq)$ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/connection.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/connection.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9bdfcea55d73aa07642f7a03ba4fcc5777cbb629 GIT binary patch literal 22231 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 Q)>%GRz3NvS{b02Ce^Z_l_y7O^ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/connection_async.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/connection_async.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b726049cb2d005af7893b48fd5ec6c47cf21e1f8 GIT binary patch literal 27272 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/conninfo.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/conninfo.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e5d478e56381c83049d64bd39fef855c6e51c122 GIT binary patch literal 5279 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/copy.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/copy.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f2c361eb60340aee76dfa4f819299b98966e9338 GIT binary patch literal 1571 zcmZuxL2Khi6rPbKS$1s2sf{--sWV%;0e6W5Jtl2oyU?=Grfeyc3WHXb#;F`z@{Xhg znH*dQv^gy4E$MAyf-uYwOGs} zkSFFx?p6k&Ke>^LvH;gAM(6@L$UqKuq#o`|hJ=xmapYd6FB`JJN>AylhT6{>S&V45 zTT0U`wV?t3*3wRqkpsSxT1#!@fv+y@6d5a2?XIWRQX2)}-(K1&GK#=&q}Ea!I`H+S zog!mZLZ2Z=Jw;BI7N0|3xEQ5aYvhJ|`7eAY>QQoFh2K%;dItnFIkK4RM*$gFEDVU> z5v1)8ViH8{APz#>Z{}a{JPn*k559Z>J>^jSBnM)ek)15qTC6s-B>$<~qu($$q-^+0 zo`BpVkLLCx68hwrPZ6Co+dcP?62IN0cG%2|$XzJZ>WkT3Q7iW&$Iub_ zKdGAJK}h;h5Rx|J8BmXOd?wa|{)v2iH?Bw8u4l2B^nHgm1)s<~u`Q)t0L?K!lWTsJ zF3<@+K_;NN#ON8`Z(zo+H8fQYXs;uTfQJ$C_rv?Utz(}Z1_R5cEw38}+m>znkr%>N zwr!u$R@<@2i-Z6@g@HFf2O4bWZT+H!R)QzHon+yYV)|-nGJc?ksn{dbWBg z|E9ge_ycd`c=4Xqr>2?YO%u)yo(AB8X+Dmu-eM+envQRqCgWR9ly)4_fUN>%{2wFM zeuhNC`DS>x7$0uI7rYO{DS9a>iZ;`+QoH=>sq*u;*9hQD#Y+8hYX-Rf^y^n#&C~GU z{l*&Oe~Cm5;{hD*eD#dgw#BjuVk*qCEO*J>vH7YkOCy`bW0#!|?mz tNS@~O^Nq8Okvi4O6Mb{6Z$eO|HmTelSMFY+wO48Z*MF+MMxeyr{sGYja4!G= literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/cursor.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/cursor.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9e53b2e3669d450dd6a7d9484f4bb73c8c835f3c GIT binary patch literal 14910 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/cursor_async.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/cursor_async.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2f14fa2388e7a550c74099d0a3416305dd8ecabe GIT binary patch literal 17506 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 KD|eKg(tiN_PceT0 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/errors.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/errors.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..208ebcc092dee45dc156e03744da831d6ea53624 GIT binary patch literal 79169 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/postgres.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/postgres.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1057e2680458d0a06ea3a4fda197710f83ff858f GIT binary patch literal 7825 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/rows.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/rows.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5191675f5fc6a01fc9e6ad7e3e72b91bf613ea06 GIT binary patch literal 11421 zcmd5?TW}OtdhVW!G&hYTbVUNu0)!-13^rg)Sd75}V+_dHlAXs z4JE6hRs4TtBAl#_RwM6I{fU}nZM2r>1ITZP*71BWQJ-vxHY6LPjr@No(UfeCHj9Gh zXU*tWmDreUiMH^%aH2K2DY}X0s}q}(ZP7O5MYSfeB`HNE^r^l0l)cH~`{J=;-p)n0 zuG98uyG8LG-L_8KXNqm?Ty*<7ZJ)JU6yMPfm!LJOwd#g<>u%vB=!x#&W%cR?wc*{y zTW+hg(biK{M%1;es_W);t*G0ys%|H*+l;!lRdwIfsx+^< zWyD1@MSE09+od)fLf$WEAuXbLt(x7urroSjBkIo(OFns;mrJRI=bi_ubs*NaUA0r~!kA+Eb zsTn123z`rWAt_v{2+814U7)xJ6!#iF40J{r)0jdB8j$eV0IrQvbOBCOOk#Bm@4lwI9J-BO&d z9ps270S`VHZ_pzR=TMcElFGO=OvD-ID45k6teI$`_31;`t5$-_^3T(~Lr-4qDax|SF*YGr#4S?0&4>(pD4 z9zNfD@cflD8`CpNOgo>tnALYFu~<3>)TTyv#nMbWKdi*Yw3K>2a#>4VK7Tqsd|r=d zwO!~iri^O(d5dFrgE)F519p^U+L|oqYwcMhcF`Wps?!<^!u#$eyajME+lKeUDw`G0 zfu{$J3iB9Q3+iqHrm{@@D9c7bmXm2Um!Nz|mM`U$gjG{1%W66%%d7)^SUV*GBB`1$W##H4s;0+SJVVIEPO@1R2ODVJd{Y;+ zM24@)#=;OWSqxmAHAhpVSem#9)0MHv(<`QyhE&LBiv?E@Bd2R7pA!;v;x=M>2>4tw zh3WXJ!OQU!--JX1VXX=qm&Ua56511?*5XG{HXgfR3JN|LCgf9?%v9VF`j-q&)YBAn z#5tsy`fd1@NdOgjy3|;NpVURWEGqq8_gx5alad-o8=WtSfAX@D_S}*J5{8ODn@q;LRSWjJw1n-eZvv9btPxS-n$SCQf zacz)WR6k=;o$4d37O7E5RwL*bv&>;@$b<3`hxJ{uurWAy>WzN`kiD@9ih=4q@#D9r!PN!0k>JW61n3;v`BBf2+ zXYFQOxKJxHKWwFfgHOY%A<2mK$<~}h94{FK1{6d$vla<+)yr2+=B|kmorocEQDyiY zGm0HSsfM5KM^X@$>xEEl;WR(LGE#z!CMoGeUvq(&4xuN6TUP#c*R-opk+npPAoL5W zYsxhus^Znqq&Ojh?C$)ZeIwZ&(G8cwp}JNo(V;F#%0T$TWKNkzYl*5UQ$LPrYw974 zNXB*9<|?qKI>Jc=nYYB!&1Grh{FxT9QEO}VhWiDsC~m^QqeUC;d^`hdufo(vhLEM=Q}=UvmYE!eRR!cxEz2!7-SDT|B>0pi^ z^OkrD@{$f`5V)HZr(G8v4lmN8NVvZg-xfvTjV6yUF8s`WMdXY?a%Y5g24~+DdBhOo zh8vi(@MW{Wp;0ZRy_{i(^X)|n5l<8u!D%vsxpi_re*0g9!1<0-zvz4K(mS!A#{WA0 zp7_(mFZ#aXTIWw&+r;il! zFRuen5oZ{cDXWVsm1Qr`5{On18y1U%%h%1$qxMgz*#HtO^Fc@m*3Rsn-d*VZG#ECy ziMFK?lNE+Mh-vf;!>4euZQq^|2m?cX=wY<_RstpKJL4cP zkTCo~9`i8==C%}t{G_7i1?HAcA|O*bCuwYx&$u`Pd%*^yerBwNs(JW{)?lx|b}cM5 zevnbb=^(afyZPtNnU>~Y&k*-lOz-{txmN}T2l+H*_@+|;_{1eT{kO#5$*^(5v_T-R zXxfys4&5E_p~+%;3l@`0n1&@3FX7Q57f!oY8y9~kz6p!zrmN3%0DCbEph-I4aD(C{ zn!8|0)*z=pw=U%T9_LSyO`IZmtupxr#@06@fe8Dwu5qDm&-ME2v3ELdG%mJ1vbgb4 z6wHVAa4g?kX?-vXaI%v~EFsD+PysO!8%1JC&?DAT1I4A}H#_;YR`s{knVjpdU<%c= z%9G$PPx^bP zonntervA>P5#gf%NutPjy2(?VTS;S@Q7MZLsjtb1b_A1$L@@U6krPW+wSpPf<}8wL zWK*wp17C6J~K|YB$&}$Jiw*$WRYju_Rf5_B+GnTkY%`)Bl`0+IVt_ z{&oUx%e-%+4P1r>4>zpzn1NctF&m?#9SIZ`t%2!C%JA#6CuccSy+_sdbYYLT1(wM= zW;*Q#KXGY&g_QsI-vz$5$aa**|2=l?C4ojfK(&@L=-}}Gtx8}cI4ahQ#L@>Q6iC#X zn6&jlXzYrO25`k=#eYR$7RyRFqoh#&7aG;k2~7)id#`W5uD|oxjU9_y9$jqNgM#_c z-V$CZRRQC)P_6<9tSeMNuwxZ<_Zs@)=eMJkCF}=(C=aOYZA>PHxe+A}6%m$(?|q zF@}Y*hN8Q>mb0rmCikoO?m%^4^-Q`a+_3At`4_nLvkn8Bb{F>`xlzVo8k$xh@5PNk z9ZE`J=7pZ=O)?VI`AxXYOK1vuq!HM+Y)ANa@Pak9j6_6fZW57$O(ar9x;Z7^x{pyM z7i~91Zsh3X%2-M{XwGfMO|}&O6roZqlRrm4ezQ~%?o>C-D%0bLQP_we?NJPwFmj-} zy=;I=$zxm;oWfc?Xa{Emgd`^TnrzX_Z?Y6m}Mgn{!RGn!F;8j;69jIng(YA# zaYA7EZ>nfSg2-4{2!?J4S{4E=^Q})T1`f}A4zCsw6==&v1PRrz6%pdNP;?Gf2nN(4 z(nZK!@l3jl!U0Y_@eiJ3!i*>88Wm!$!L9JxJ@C~j*1O`F@YwAy23J(!?}QV7yXJah zy9Z-Udis%yJa@%3(7G#3J|Y%ke@Mv>D0z+&8437|%i|&kDO5%5p;M%f{6CYA*t1kY z$ud=vx&to`6>5|f7(CW z{^QVXU+aReb*}f{eA11`7u4W^;PO^{^&0_MzK)-F9&Puml3V=TKEO)8=G=s}SS{RP9judG$WI;{ewtr$+6xhVKPPOLu1x#k7#XLFWF<&wkT z6`RgV-Oq3dar({Z^=-{I(zmcYepAH==&c?rU5=mo#u`e=a9N8I z2vvV*CNLfNN&I8qmOH`l%)#k{*Ef9}>?qCO4^_`RJN@kSogas`-)y>H-8dD#Uu|A> z*~-CjIP)89S#)lINQQrds~b5VW}G`_-d?TIrrsH-kD|$Zv_X)Hc*k%f*l)(Eyu;&J zO*iiWYA7ahuC%#_yWsgsUSatX4{OVB^57X`g=DAYYkDEL=}WG2kw~ORvYn4NQMY;% z#T#q7)7zJ#Kl4(j_r-TPsS}4~>3ElAXdue`6%3AT)sFvlD zFY`d8H>lAeN{&!+nv(NK41a><@O@AWm&q?tVSUh*--593GokICu=PKM zntQ^=&xFoZIdAjd;I`3Ci&kRlv-mdCcsOl&L?u5cKXQt2G4sBZq zZ7cZiRM*Z-PEX#h?p~3)jPNE6OU97zwil_;VEq{dn5Wu#esr*xgsPU zntFN8Jw3TBAiLZa7LSRu&2!tXZC(~Azr58eo)l*<%<0#X%L3(>YrNtaarOsuv1@}= zaz=bmBQ$NA>wTwg?wM=pf^VvOQRsL;dxdq^*fO_mPM_<#_Q!?Fsf~-mwg)b+=vk@> zh_y>CA+cepty-*quw8I96gJ)#>leiO+5SawBay0O$t}2AXrPXzK)u+w6sbacsa9-S Y>Z(K1Qz<^VR38#6mfLDY^M>tz0Y$bV#sB~S literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/server_cursor.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/server_cursor.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..859afe373066a0814407d3cf9f39860d6ae2b87b GIT binary patch literal 25081 zcmeHv3s_v&o!`Clelar)ZxAp7Aq0|;goIwUB{P6zYz($QevIWzM$AY84Gg|Bvcwo! zSaBP$y|vR#8>O3mF*x~l+wFtVs2wtu8>Q=RHtlv72l=yBNx$~@ zKld@iaFG?~(f0d#CC>fdbI&>V+;jf#|NqWkYSR2v~=)AfCy;nbA@EQh;UgLntYZ@?n&FsD|WErq}t$_6b zL&!FeV{KF-jp zff{cOyO$eUJy7ed1?=*!3Fh?glb0ZU?(a#%GUTmartKqgi}cyM7HuC(U&~OxSBBDO z@A_rh9!R&5A#VfPenGxUpZmXW#7Ly_U$ z@X%p*Bq%%`6xK)j0zr50F(DEb+~I@$!QN=3!SZt&yN*v;{ey$ys6W~l9*oo(QrhOh z;Z#m@WO%T*JsK4J(Xfy*G3a0@C_z-0)ARU4ZN8TK+FBlH@7$X*h4G+J*dM@%y5oLf z@aMcZyk_VrRB0nmg>W(i1tBa%>U1f4OL%Y)6Twq^hKGVF{lmwC!f?v)kYDf*L{j>P z9^M-qtkb5n`@+Xl78HB@y?E?!%E6|VuAos{*sIZ#yMv)aI2(f}g1yJ0L4X#IKN3_L zSXpo7(vqG9nuc3>h^R)VKo1j2bIy@&cxe z8XG+&ke_}QyDkWrpVxbH0)+t!o@>Y1inAk76tLm!3={`)aLx^s1nfAw#<&x_H?Nzk zD^2BgGb9q%?7_YheS@)9c5+99;)>d{BS0;s{p7f)Nv=n&UWTJK z8A7eZ$vJMAtJ8GusWYYY>;+QRj5kP`l~+hv((jORwzlnQ-rv#VYwu~>*WK=IOPS=? zO6hvq9_vXNrMClZ=pw-4l#W&>Wl672$|SE&gjT?f&Y-y1wI*dL9o z_xJXOj}1oq1`n_A4GX~o2mQTAgM)zs4NnILpFYshckn<2k6w=sNBxI`kpmL1*dX!> zUoWGjhN0n<$>-}E?2Gz*vC_;fW_#Zt-&=>7L^hxp<>qZ%Vd0EY~m zGyiOCJT_}8`AsJHu7${hjz^CKF+m|?mhQfYJ55z?$VAA$28+_8{gC^MD?7u3!7sW) zLI2Z1vFnj=UoXHgyAo-o!M#5cMB5(W7~1w7au0`(xsUq?qiCj#c8r>ck6TmsMR#~G zVcik+cU15XMj)pl)ZIt?5qEERV4yD=4F(pyXf-Cg zStu$Bh7Hhm88)Z(OOL?hVLnM*fV3NejXxP34XJmHooW-xdn>K4Ms38fAN zqrFGmeF|y_keF^E7&#Wo#7h||foO!$LBiv~u+&Z&CcV^bZ941pDbvtlaj=vj0!e%f zyr*aXLmh41zODyScG@J!YM*pV=Nk$~WLBj`zmy?*3{pHIaVe3WQ)Wzk@Yuk?pb#rt zik`~N{aC3;3koJ49C>F4#s|i<^Cr$!a3!~Es`~Z%SL)v}$4fU|DeZi(JK3~1-n946 zH^-Yg#|%GSQ8gAlJ3Kx-Yg%_vheF(IWoIxb!N4YdVI%hN0ge~WJH^?E!juvod^`c(u@`ngN{<9RCTA`}=!7@gFijhZmh z1+?$z(jqIGBfl=%6OCjY{lp%!j<=;%%AVIr{fIuGC*z~vmDL58(R{h?=r#~>KAu-3 z*QC$#2=X&PJK9kf+7_qV$Pg4OW%h%4BU-@_T_N8a)JH31II|r_S}E73&&%)BFu#pE zlfvKk@h9NV`p4Sie4Qb-5jKWs;-ocI;$vUT#OMaemH_u|=-kr-JHZY;v^VGj0Yk3} z27dm(aMb0dihKk9qd_Qr5bHva(G$~sg;kg&w87p`I1=<74i2VlbW@1>o?4B9t%IjjJSViW#NqVBZ9JqfFog+6;{59z=kXE?`N$0w_bKS-L3Fqc9J%qo_ zd3N^;yXT6^CQnVAN))Y0+Sbh4*34B@kF}oZx}H~*%v%-DTXlYaB5!Tdw073CcFyif z+E>QyE6>+lEKJxpj%nviwxp>vZYrJHd@(v}D!ppja;<#T`JT7D7re=ut?`vz3! z*I4UI9Y3vE``Xs;^e2p^^U?;!Me#3w8%Y%Ik1Fg#u9X$ z0%-%##>jisQ)h))CX!q#pNKI{I749}>JN$9y&*W*8x91a(K7%XL?l`e_K{%kQHdZU zun{CON)>{%L-2l(wMD{Sy1{6bv5PtlBTC_MOd~>5a!YzNdC+2&s&odO5cV>W^mEjU z%qK=@AP6!AlBT-2sqW&cck3_JC+qKu*WY!y^#`5b>rB)?aMjcylE{Gz2NLCtNmnC? zgUF~XZYrDFd)2gRu9$4N99CH!H&vf+z8H8nbSX4zs=jKvYp%2cHl1VM%;jyq70JVc zPd68N%K7OM-czQVE^XG}LLF(J&XnBfn0=_pYBiK4jV`L_XG}U-P@@=otcD*Zqej{I z^s^$=Hr*R6QxMxK4uFidC!!AdN=>rD43%VSKdnU8k{tG7b?lwRCiKx8btRA&_k%bfHMOGAtlPp>A*OXiFK}JA3vucXkV4)f^*nftX!N z+x>6{V>T&c2YG~Ko+2s%kortHPZ^lYI8h2k0# z&F=eArDi{-m637k^tUKPUXhb~);sP^=2XOUDv~*y;yIhfG$aG>_4;Tk01JK_v8~3Pn^$x ztMo!?qF`OZzJ6ZM<ZG$i?yP@j^Siq)?Yg|`2ld~pPpoZAIQPK!kykXi zb7E&QZ*4qp?Zvi4USrbK7&kS}JGi`iZqC~|Gq_X@Uiq}AsdWcGvyE?U(#>pd-iC`G zZs1$D>3+D;Krn9X;CqSv$_McXCT#!3XYehdAgYL4HGY-m5}-e>U*SFSgRm(ZQLkbl zWaznz1SrI#sn|NBGf#&*-o4g~9xcmMT_7TEu6x`}Mh_v`>sX zs#qHRW$Cq*A#xD+tMH|?b#*(g2_-_21Q^FHkD5OB6SZd@Biexe9YflBTc#)BXVwug zf>W=~s>CHmASFNRkb_L!;CkoyGr8bQ&BmzSn9WZ`!L>)%*R_{TLH4=>aDD(q2y{JAFqzvM4DL$C8w-17^ z9fE(ljeG3{z9U=nhoY2IWDTWG}NowJ&SdL4=He((bQk_(prE>QVF?a-FS&3O%9cS-);jU}0 zyriot?y8!t-jQ(aoVD$|4o3%AAsopTi{r;eU!IlFg!@42=!o$o~6edf|Lmp3Oi?7n7mob4R%6kWOr z+v)|qHrE2X$;6dbyk7cBX|iNfykygRHSb6NY-D<5wq#SHq$g?b8Pi^OxW>rmJ9g@N zG2HJ=kvnS|HziHwaZ~wJ@5N*ArCl{O&0*s35GNfgF>xm0bytnGR4c~4^ zIGSfo>hk&f349v#q@eZ@*(de=D*bOLDrIZ!6=cwR~H?ZdzAFa2elLq?=yhDaFMH zTluyU-3Qy6D{%3nB5M1i5-NKY7KuT~eFAdf7Y<;3B|8RjwWoQ(5tURJc=_RI`zG}F z*A(V*n*R(&t5ehydP3H5`@SQZfSxHqnt)-D4;bZodc&Te>Qw*1kA>#CTzQ?@`3ROrt}G0#S#iN>KKJu;3!zClUy-1-inYwJngCStm9`^@t%6! zOpO8XBCUf=e4rA)a04<9fiZ;~V6`aPi7ZisGWfKqN7ex}QqeMGbUVo}8dX7SHN=&l z6e)-*`iUAUrwIY0-?n918_H;>;>pB2s8}HKI~>+9*{`BuJl8m)=`YAy5L{+FO@$Qk zG?lRgO+W)?ppcsUbm(87;~4>kJ!OoeY6S|bKG*nqd0hGYIp=AR`^)F$#!2rwoI$tW zb%mkc-f~6s#MGHGwzjo&H1BIm8M<5cb#-*a%$;3s5kv;a{(aqD`(oxt+k5VF-`CaA zn$kjr5jJ6u>vB?-z6heRQU72s5={;cM=7WQza+5}N)`|;G30^_AoM|b2qJGvYavx= zlrs2-hR7ca8N~@(X<#v)D{2*RhjWV}BtkoCVs$FqNZm_3O#^&_VwAgPEjSl^b^lds z^;~|*WXD7YET@VK6^Z=Df%RSpM-tlVQ>qV~=UF=D&zvs&OdoC2ee^;WU>#FS`DToa7?a_%x zryffbtiEchorBi1>xEs5x}Gmfl&rsMYgpW2|I1$>*O3&7-hb6p_7TjvKztd5VDy+U zD4anhoMmTm5?;!HzmkS;S^5x869+-&MrWN#+%n=M0%e)q$`P}U@6$H zMS6nf@TB~xKfqmxrxVoZoZK?z6kCS+BGD)Ig^xe^B;M#0?xwVufiOz#XujfXr6HK* z&Za`|5VIjsszJoWV4yCa@(L(Kj=Tbk&j$f`EJU!)huDEXB;7Ike1UK;5)igv1j;Lj zgu+qe6$lOVFv=%D2v7(kO(8nWR+ud=TTh{lns}*T+Bo?OgkdV4qk?c4;Q}#Hp*I)` z`Fx1&lgh_})c1-`hDvHmMJ?S(qPY1y_hVh>b!U6h*%fzoC7chBw$JOV`W4shx$}CQ zVfq)i=ZyrJxV)kTGoVjOb^1!El?MASG#Y*Bf)>y`L1;pCM!j3A12peqbvk{8R0l}v zYtgTl>Hy7Ga4T!(Dyrtq<@z<(9r^QmobmMBig_bJCN6gcyEkv)ECmZz)Gh2X=qneT z#rn+)TU>e%zp%!n-~4I5OTUI;DSOjiyrgnS9&~;oAA&h6D-5}wUTqKoyMQjBe^rx} zl~suBF2mc>KwkZF?N|m^5%Rt=+G0c+)AXu#@tCY_F|xf3UOlq8DBH^rC}CMV`jsII%;+@*>;Xsi{lJQV6JweK<$+v`X$e#WDg!R$lvx9AWH{=)w!q3j zKF&FTsz7z10C(&xi_8J`y((qPWP~ZBlyr27>)dlmlSW6yAds~hruESJPQrV4iSHC% z2Yg8{I=(Cv3lnn)v(P$1`VWg!i5Nf|9_L!mS0e3|K_UWEG>#crH6K&isNr z58(~m6K5jE&V)Cqg7GdZY)&7HUCLEVzgKqLj8Wz?6Z!~a$rEyM(u6K)g^TnI;);xL zm6f6yl3vGFY7{`GeyHX>AE7Xc7C8+zNN`@wH}wuL8y}G1iq5DWK7t2DH==)=mIeoz z8J9Gjh@a4G!63<-EwUjtea0!?Lfx;kAb&^giRX-RH(Z?Aan>>JK%nki{l&Fc>bowN zCULmY+optoDCmj0KXjqa3*co_XP!Yc}Vc3sIwsh4UQ0@gW{% z?nC@X&dN`Wx*YqwmUEUZU0wwrtFY*l$_GsvgJvIU*x3XeLTd@1GJ6OXur8kdWh^}T zPBR-xuv-5}-7;-e+yZE+Xs+quWk#LWfTOhN>=?&PUPAmuZi67>lDSrMn;TY)nWeLdp%o2gbI0Vb5JtPE!ZsZJxd;9!^N$|z7-9|dM z+`sdZk$KHhx=^_HC_@cO$nJ{@_hX_$BZ`!sArlyH9aS-LP7GJhKqMnM=30awtb-oA z86jPPqW31w?xIk^S>KC330L5t|5VS}%g1~Wu(G|o>Pp_KIcNT)Wx_J)m~foez2&&z zNVqp$bv9nJ<&N(ifACD#r&jbj>l^poicmy%%I?u?-)+u8IiuHm>_+Guq?0K;k4Tv; zR4duU-@+9zOed74E!aSYQ)oo7umTzikbRSTP4R3q-@6K~saeYK=qos(W)-I`!qX6~ zz#tnQmUXB(awLpbYpoLA#<(g`Mami)(aKyqjh|2u@Gng-BV0FpY>Tmw>O?%O&Papq zSMk5E;)FuV4^qqdN!zifkSZO z5gQF45O)wvF^$=`ijD?{k?b6xd`&mfZYc&I4D56>r}M4GrHq&I<1$)OhTTx#P%zXt z7-Vj)&Pz6=!r}7+=9vb?KyeoiV9!zxxt$cn69lTw?F>h|<>!jt>`v4R|BQ-%P6bg1 z6z0w@AEJFNZJy>9WY`f$_aQRa8>C$9OOnpO6n`>57;dKwNAcCf;YdmoJh4PL7Nb=b z!Y0vD6y$RQSv$p%laJzf_ z?xeN$inW$Gt!v`0nmK1H0(E)zc}@dt8Ug- z_se-Ls&7TMV&c>0LQgd}UAf*M zo=ZGZ5Sa-GDYu9*kj%y(&*a!=DMM+;(`jPE8y-Zma9Bhz<=X}DS)@{_$n{9Wt&P$? zAcJx^3)zqZtAdeWx`ax?G>S`N0GC;#DT|nQg~X7jgg?j4Y#(RFgJQ*tcyq>`dO`=% zxu7aJIfqkBjhe0MN!a(#n)csDQvVe?eGWN|UfIVozDE@)n_hgGW1YmuH1sdcu}<+q z=?F4#`-$IY9RWTDPjauur*QBQm|Mi-yP=R}^SLvtMJ@+Ljiv81t^rdbi-MW)>%kb3 zcueVpU~eQd2Pb7>@gTSZvNU+PdJFBs!x#culo(HELQ;%MPwt-BeSXVZyD#j1Z&RYW zDUr8ztQB-*FaN2PwA!=nFSJkPj(5J)jwtpNKe27B6KQXs<}k5(D*}nfO|EUO)lS#y zn>QL4d5IOR%Y^4+FQMV9Ydp*4z^Z9Yl5~>oF+5&AmPry*WTf0KGa#buvnG3=*&Zv} zRJw0EB791b+S0BoKJF3ZS1;M^I&rs|t#-+nGW!L=KTMwyExX|4zGk8%-qP3#(Ly)7neNmOr7sIbbq*+iH1}s~J zoE4UxLA+n*CwZPbQ?BFE#GVc!sL$mn7!swXoq1^q;kSr{PmxZzA{eWeOri`ujdA(a zSQLR+J;M!&@)^yi@Zm%6V#24d;gH7w%Xx_(iB&&9h!VkIVr0?o%2cC}&m5bGQBL#u z=v${QoO&<%-IL!wnW$|`6zw^uV`|i27L}dTlD=jB1M}3w6ZWr}=L$<+HX~80cm>=V z&b)J5UK~c`|DIRwx#Cze=PW=rlOyjZx$bk7zlxOOxu=VfWciIIPp)>_!4fWKa`m24 z<4mEEk}rvg$p?vIrXk$`@cZTwnIAaFm;_@vOY9@^&OWRW3YX&-BTIxok~?99re73<~oCHY36rZ{lGwM~mVOWx)s0C3*(8M6V$WXsn~lub`;2uwJ(^d*RFPCo_6o zWTPUEA$@u+j=GjcP#sJ7Yr0iW1$!#%UzpWjjG;f#=u$@o3jh^SpUmjazePpN*-m+t2Ltvhx=tD)hdmDdU$$NtgfI<8AHyUz$S5i@0zvfnI;Zee zs{I-jU#DV<3R0#-_vyC@BF79%Ef@YBL075xPgMM8Dn6p(XHxsr;HbBucH_5A92Jxj(|Qt^}ZO0mfw@Wq8o5q1Hxy@NSPF zB4pGT-*6f9`3p`R3Y$q^_$lft<~bD19AjI;NT(P3q8x=K(8nk0_ZACiiG@DWH@N5_*ip`##ZNcbak6zysZ&5n$- zTFgjz3$2#8cp6X{yUnx0^sGy0BqGf}2Bf?jJy6m6M{)64UXR~(2uOGblR)&R6sJ3n z{@mv6VFDF&McOodp*nEQ=Je zFTqY<+>?Dlli5jv)y9i#QujaHx#!?*X>?gp{1Rrz=A)gI-ema*%+j`>{cgyQK8L?! z_}hTLGW_L`fx*@REB1Bv+--;-E{fwwer_^3M3zDxS>ZAY(bgOlqtGP2V?|3*fCX31 z5sLotEiGw5^=At%RqR#+cZB^W5&6lmM~g=A3Qi&3UT6Ik}te z{3`N1X7Z)77CZkf-m}5*x)#tIcFzv&dsaYy%6m5HzOM%~&BN5#p`Fq4p3R0CT>-)P z=&Q*vQ>r7lf|}3N@t$qEnR)}kn|LZW^K`d~mD^a&4nvF8IJ28?(bzuVjDSBd8qret z9wwr2I;;^3{Jcoya06EoG5kLp{K+6r1*JhWHoRxnp_=deYXpN7a?r`7vkW<8%!581 zICDS#it%SzLF*~k;z$W!|*4Bl#JF&k&@<~_S@ zGxrz)f1sl=KQL1J56ld<<+U_vKd8)Y*{J1= zbYb!04_OuAe0Q1~si!2|xoE~TvX49W-KAG&IiZ>Dw_7UYKY!2#e4-bBoAFn(h+n7* z&NEGEU!5?EcNXGQWIJh@p{u4G%K?|mw0r&Nsv>!amc4gHNF!!@)(7pGB(N5`4^0)a^=?>`vzGR`79|0MNWq zL`7(AOHr}TvmS91kIV3m7SOv5o?`8EIq%6gOjqa#uCk(fdOhzc)J-?k0G`R`Q9o12 z6I^WY)Ej3ic+X1POr??F)kf5-+aaDbD*m5kb&8^}EV^ZdpO!&4m0-u6hNFH{bo-Fd zZ3)98f8MeT4^gRqMaUMEkxlyEnN)Y!3co7^EAvzmuhS8)t0Z1$VZ6@3cpYHyx=P0D zOyG4jfM*Om+RT`Ef-MHm3ge8E_vG1Ta>3<{GsQ;KFF`P^2Acg>6a@QqB45jJG^|qg zap%$$98m>1WOS3yif%3G&UYeV5h+{o>qg4{SSQ8GDn3`N>>mMHU&Pj>;`%p6mxT?gKUz z;m`cp7&V;jD1nc#6U&nkn0<~e{|dz-6k}nHSn*QvD@NRYOqlf$I;rS?uENRsiTcS6 z6C2L2N>(+-s~X>Hy1Xh;wL9UuH)*?f)^;yUFUcP=XS-KTw3c~zaK7f%#QAvs!iMH` z+G!`>yv8t{t0TC;it1@M-(0VoUTGkB4Nvtz8Nlld&AW`#jeK*HZF;kj;GIU)%VE2G z_EMiKcDJOfS^!UMlof@$O+--8VllI$cp_P64RV`Mp73+pMy5~wcY^+givK~y-%{~+ zRD6s=j+wdGA}k7=3BRC53)JYh5F0~+!R=yWpU|_YpkE7)JdXmgF}T=VWy?m#*8IlN zF^oX5E-}7F5CU5DcNQJnvVC!M3`40z$2Q$Tbj+Zy!taw&bgTd|E-^X=h=sVQMvRV$ z_b56>kQf~!NQ{mVw4FuAjB<300Q9Bk7z4%V7z4%V7=a5ewdj~e-;A#es1!pTY;OoD zJL{T+N$e4Q33uoizW&3PZ~}P`@C%j0L-er&`LqQ+6%-B;$aWG)e6u(zem+_JCL+Q< zl@LzS4RW-JKS5z9NI;R&`VaOB4!U$wkxPY(Zs-L1fr&i2&ZnY)Dh*ZZv;+__^UPKl|LX zqq;e>^=!#_Nzz;rHmep~~>QUnjLrBA~nX;VU_1@;$>aFqOZ8tcox$y=49t~eH zo40DVX6t3`Y|UNqyt^+SdcXU7M{jU+=f*zW2+ue3bGm}r!gUvWXA3vQb&c;m@V+*_ NrS%gnyT?}Pe*-by6}A8X literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/sql.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/sql.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b94644d6499b4eda2b2aa21bef5a8f47e1e4bdf4 GIT binary patch literal 22166 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/version.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/version.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cf71ab3274d2333314cc268d6116072363d5243a GIT binary patch literal 491 zcmYLFze@u#7)|c3JzFi};bujt9qiC*M@2;tT@-O}u^b%NORQ;omm^7A>!zb1xH$=~ z;^P0|Bo4~0F1o2jkWMCgrC%WLeeiySJY+IyAm_qaC2ta6)iM|(CcPs`t^fiRfFRPE z(AO#&1Sy~atkshP`4EwQ2miN<(M`-L)nCg{p;#WU1O&*a7zd!6=zwGW0CZp>d6G|u zyz9}hHj4-sj8t2K&|tQW8CQ5nnz)pHR}lpmjrdr&$Q5p6#;y}{vGjL#3(3fI97H|G ziBiN5DHBanWx8}mW*irdI!;WbYI4u@8g32mQn5u_0or7YvRlwoW&Qn)WxGRJgNLq% z?Vv7r(e*qj6C|h=J<70Mm3AB;yVS-(+uk8nn-hVH(x6hg9Y1j)ZY+h}Xk^8wsMW-4 zEF(+Qzwvc>edrLvPfdfy_ZWaPABGOIFIMhy{@KbsTDhC0C#!h6{qtguKb!eSGyesk Z5=@%aJwgv0;< literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/__pycache__/waiting.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/__pycache__/waiting.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a4feb2336dccaf226f956da8c714fb75909c9cb6 GIT binary patch literal 15193 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 T: + # Always specify a timeout to make the wait interruptible. + if timeout is None: + timeout = 24.0 * 60.0 * 60.0 + return super().get(block=block, timeout=timeout) + + +class AQueue(_AGQueue[T]): + pass + + +def aspawn( + f: Callable[..., Coroutine[Any, Any, None]], + args: tuple[Any, ...] = (), + name: str | None = None, +) -> asyncio.Task[None]: + """ + Equivalent to asyncio.create_task. + """ + return asyncio.create_task(f(*args), name=name) + + +def spawn( + f: Callable[..., Any], + args: tuple[Any, ...] = (), + name: str | None = None, +) -> threading.Thread: + """ + Equivalent to creating and running a daemon thread. + """ + t = threading.Thread(target=f, args=args, name=name, daemon=True) + t.start() + return t + + +async def agather(*tasks: asyncio.Task[Any], timeout: float | None = None) -> None: + """ + Equivalent to asyncio.gather or Thread.join() + """ + wait = asyncio.gather(*tasks) + try: + if timeout is not None: + await asyncio.wait_for(asyncio.shield(wait), timeout=timeout) + else: + await wait + except asyncio.TimeoutError: + pass + else: + return + + +def gather(*tasks: threading.Thread, timeout: float | None = None) -> None: + """ + Equivalent to asyncio.gather or Thread.join() + """ + for t in tasks: + if not t.is_alive(): + continue + t.join(timeout) diff --git a/backend/.venv/Lib/site-packages/psycopg/_adapters_map.py b/backend/.venv/Lib/site-packages/psycopg/_adapters_map.py new file mode 100644 index 0000000..c633b6b --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_adapters_map.py @@ -0,0 +1,296 @@ +""" +Mapping from types/oids to Dumpers/Loaders +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +from typing import Any, cast, TYPE_CHECKING + +from . import pq +from . import errors as e +from .abc import Dumper, Loader +from ._enums import PyFormat as PyFormat +from ._compat import TypeVar +from ._cmodule import _psycopg +from ._typeinfo import TypesRegistry + +if TYPE_CHECKING: + from ._connection_base import BaseConnection + +RV = TypeVar("RV") + + +class AdaptersMap: + r""" + Establish how types should be converted between Python and PostgreSQL in + an `~psycopg.abc.AdaptContext`. + + `!AdaptersMap` maps Python types to `~psycopg.adapt.Dumper` classes to + define how Python types are converted to PostgreSQL, and maps OIDs to + `~psycopg.adapt.Loader` classes to establish how query results are + converted to Python. + + Every `!AdaptContext` object has an underlying `!AdaptersMap` defining how + types are converted in that context, exposed as the + `~psycopg.abc.AdaptContext.adapters` attribute: changing such map allows + to customise adaptation in a context without changing separated contexts. + + When a context is created from another context (for instance when a + `~psycopg.Cursor` is created from a `~psycopg.Connection`), the parent's + `!adapters` are used as template for the child's `!adapters`, so that every + cursor created from the same connection use the connection's types + configuration, but separate connections have independent mappings. + + Once created, `!AdaptersMap` are independent. This means that objects + already created are not affected if a wider scope (e.g. the global one) is + changed. + + The connections adapters are initialised using a global `!AdptersMap` + template, exposed as `psycopg.adapters`: changing such mapping allows to + customise the type mapping for every connections created afterwards. + + The object can start empty or copy from another object of the same class. + Copies are copy-on-write: if the maps are updated make a copy. This way + extending e.g. global map by a connection or a connection map from a cursor + is cheap: a copy is only made on customisation. + """ + + __module__ = "psycopg.adapt" + + types: TypesRegistry + + _dumpers: dict[PyFormat, dict[type | str, type[Dumper]]] + _dumpers_by_oid: list[dict[int, type[Dumper]]] + _loaders: list[dict[int, type[Loader]]] + + # Record if a dumper or loader has an optimised version. + _optimised: dict[type, type] = {} + + def __init__( + self, + template: AdaptersMap | None = None, + types: TypesRegistry | None = None, + ): + if template: + self._dumpers = template._dumpers.copy() + self._own_dumpers = _dumpers_shared.copy() + template._own_dumpers = _dumpers_shared.copy() + + self._dumpers_by_oid = template._dumpers_by_oid[:] + self._own_dumpers_by_oid = [False, False] + template._own_dumpers_by_oid = [False, False] + + self._loaders = template._loaders[:] + self._own_loaders = [False, False] + template._own_loaders = [False, False] + + self.types = TypesRegistry(template.types) + + else: + self._dumpers = {fmt: {} for fmt in PyFormat} + self._own_dumpers = _dumpers_owned.copy() + + self._dumpers_by_oid = [{}, {}] + self._own_dumpers_by_oid = [True, True] + + self._loaders = [{}, {}] + self._own_loaders = [True, True] + + self.types = types or TypesRegistry() + + # implement the AdaptContext protocol too + @property + def adapters(self) -> AdaptersMap: + return self + + @property + def connection(self) -> BaseConnection[Any] | None: + return None + + def register_dumper(self, cls: type | str | None, dumper: type[Dumper]) -> None: + """ + Configure the context to use `!dumper` to convert objects of type `!cls`. + + If two dumpers with different `~Dumper.format` are registered for the + same type, the last one registered will be chosen when the query + doesn't specify a format (i.e. when the value is used with a ``%s`` + "`~PyFormat.AUTO`" placeholder). + + :param cls: The type to manage. + :param dumper: The dumper to register for `!cls`. + + If `!cls` is specified as string it will be lazy-loaded, so that it + will be possible to register it without importing it before. In this + case it should be the fully qualified name of the object (e.g. + ``"uuid.UUID"``). + + If `!cls` is None, only use the dumper when looking up using + `get_dumper_by_oid()`, which happens when we know the Postgres type to + adapt to, but not the Python type that will be adapted (e.g. in COPY + after using `~psycopg.Copy.set_types()`). + + """ + if not (cls is None or isinstance(cls, (str, type))): + raise TypeError( + f"dumpers should be registered on classes, got {cls} instead" + ) + + if _psycopg: + dumper = self._get_optimised(dumper) + + # Register the dumper both as its format and as auto + # so that the last dumper registered is used in auto (%s) format + if cls: + for fmt in (PyFormat.from_pq(dumper.format), PyFormat.AUTO): + if not self._own_dumpers[fmt]: + self._dumpers[fmt] = self._dumpers[fmt].copy() + self._own_dumpers[fmt] = True + + self._dumpers[fmt][cls] = dumper + + # Register the dumper by oid, if the oid of the dumper is fixed + if dumper.oid: + if not self._own_dumpers_by_oid[dumper.format]: + self._dumpers_by_oid[dumper.format] = self._dumpers_by_oid[ + dumper.format + ].copy() + self._own_dumpers_by_oid[dumper.format] = True + + self._dumpers_by_oid[dumper.format][dumper.oid] = dumper + + def register_loader(self, oid: int | str, loader: type[Loader]) -> None: + """ + Configure the context to use `!loader` to convert data of oid `!oid`. + + :param oid: The PostgreSQL OID or type name to manage. + :param loader: The loar to register for `!oid`. + + If `oid` is specified as string, it refers to a type name, which is + looked up in the `types` registry. + + """ + if isinstance(oid, str): + oid = self.types[oid].oid + if not isinstance(oid, int): + raise TypeError(f"loaders should be registered on oid, got {oid} instead") + + if _psycopg: + loader = self._get_optimised(loader) + + fmt = loader.format + if not self._own_loaders[fmt]: + self._loaders[fmt] = self._loaders[fmt].copy() + self._own_loaders[fmt] = True + + self._loaders[fmt][oid] = loader + + def get_dumper(self, cls: type, format: PyFormat) -> type[Dumper]: + """ + Return the dumper class for the given type and format. + + Raise `~psycopg.ProgrammingError` if a class is not available. + + :param cls: The class to adapt. + :param format: The format to dump to. If `~psycopg.adapt.PyFormat.AUTO`, + use the last one of the dumpers registered on `!cls`. + """ + try: + # Fast path: the class has a known dumper. + return self._dumpers[format][cls] + except KeyError: + if format not in self._dumpers: + raise ValueError(f"bad dumper format: {format}") + + # If the KeyError was caused by cls missing from dmap, let's + # look for different cases. + dmap = self._dumpers[format] + + # Look for the right class, including looking at superclasses + for scls in cls.__mro__: + if scls in dmap: + return dmap[scls] + + # If the adapter is not found, look for its name as a string + fqn = scls.__module__ + "." + scls.__qualname__ + if fqn in dmap: + # Replace the class name with the class itself + d = dmap[scls] = dmap.pop(fqn) + return d + + format = PyFormat(format) + raise e.ProgrammingError( + f"cannot adapt type {cls.__name__!r} using placeholder '%{format.value}'" + f" (format: {format.name})" + ) + + def get_dumper_by_oid(self, oid: int, format: pq.Format) -> type[Dumper]: + """ + Return the dumper class for the given oid and format. + + Raise `~psycopg.ProgrammingError` if a class is not available. + + :param oid: The oid of the type to dump to. + :param format: The format to dump to. + """ + try: + dmap = self._dumpers_by_oid[format] + except KeyError: + raise ValueError(f"bad dumper format: {format}") + + try: + return dmap[oid] + except KeyError: + info = self.types.get(oid) + if info: + msg = ( + f"cannot find a dumper for type {info.name} (oid {oid})" + f" format {pq.Format(format).name}" + ) + else: + msg = ( + f"cannot find a dumper for unknown type with oid {oid}" + f" format {pq.Format(format).name}" + ) + raise e.ProgrammingError(msg) + + def get_loader(self, oid: int, format: pq.Format) -> type[Loader] | None: + """ + Return the loader class for the given oid and format. + + Return `!None` if not found. + + :param oid: The oid of the type to load. + :param format: The format to load from. + """ + return self._loaders[format].get(oid) + + @classmethod + def _get_optimised(self, cls: type[RV]) -> type[RV]: + """Return the optimised version of a Dumper or Loader class. + + Return the input class itself if there is no optimised version. + """ + try: + return self._optimised[cls] + except KeyError: + pass + + # Check if the class comes from psycopg.types and there is a class + # with the same name in psycopg_c._psycopg. + from psycopg import types + + if cls.__module__.startswith(types.__name__): + new = cast("type[RV]", getattr(_psycopg, cls.__name__, None)) + if new: + self._optimised[cls] = new + return new + + self._optimised[cls] = cls + return cls + + +# Micro-optimization: copying these objects is faster than creating new dicts +_dumpers_owned = dict.fromkeys(PyFormat, True) +_dumpers_shared = dict.fromkeys(PyFormat, False) diff --git a/backend/.venv/Lib/site-packages/psycopg/_capabilities.py b/backend/.venv/Lib/site-packages/psycopg/_capabilities.py new file mode 100644 index 0000000..d1f6bb3 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_capabilities.py @@ -0,0 +1,132 @@ +""" +psycopg capabilities objects +""" + +# Copyright (C) 2024 The Psycopg Team + +from __future__ import annotations + +from . import pq +from . import _cmodule +from .errors import NotSupportedError + + +class Capabilities: + """ + An object to check if a feature is supported by the libpq available on the client. + """ + + def __init__(self) -> None: + self._cache: dict[str, str] = {} + + def has_encrypt_password(self, check: bool = False) -> bool: + """Check if the `PGconn.encrypt_password()` method is implemented. + + The feature requires libpq 10.0 and greater. + """ + return self._has_feature("pq.PGconn.encrypt_password()", 100000, check=check) + + def has_hostaddr(self, check: bool = False) -> bool: + """Check if the `ConnectionInfo.hostaddr` attribute is implemented. + + The feature requires libpq 12.0 and greater. + """ + return self._has_feature("Connection.info.hostaddr", 120000, check=check) + + def has_pipeline(self, check: bool = False) -> bool: + """Check if the :ref:`pipeline mode ` is supported. + + The feature requires libpq 14.0 and greater. + """ + return self._has_feature("Connection.pipeline()", 140000, check=check) + + def has_set_trace_flags(self, check: bool = False) -> bool: + """Check if the `pq.PGconn.set_trace_flags()` method is implemented. + + The feature requires libpq 14.0 and greater. + """ + return self._has_feature("PGconn.set_trace_flags()", 140000, check=check) + + def has_cancel_safe(self, check: bool = False) -> bool: + """Check if the `Connection.cancel_safe()` method is implemented. + + The feature requires libpq 17.0 and greater. + """ + return self._has_feature("Connection.cancel_safe()", 170000, check=check) + + def has_stream_chunked(self, check: bool = False) -> bool: + """Check if `Cursor.stream()` can handle a `size` parameter value + greater than 1 to retrieve results by chunks. + + The feature requires libpq 17.0 and greater. + """ + return self._has_feature( + "Cursor.stream() with 'size' parameter greater than 1", 170000, check=check + ) + + def has_send_close_prepared(self, check: bool = False) -> bool: + """Check if the `pq.PGconn.send_closed_prepared()` method is implemented. + + The feature requires libpq 17.0 and greater. + """ + return self._has_feature("PGconn.send_close_prepared()", 170000, check=check) + + def _has_feature(self, feature: str, want_version: int, check: bool) -> bool: + """ + Check is a version is supported. + + If `check` is true, raise an exception with an explicative message + explaining why the feature is not supported. + + The expletive messages, are left to the user. + """ + if feature in self._cache: + msg = self._cache[feature] + else: + msg = self._get_unsupported_message(feature, want_version) + self._cache[feature] = msg + + if not msg: + return True + elif check: + raise NotSupportedError(msg) + else: + return False + + def _get_unsupported_message(self, feature: str, want_version: int) -> str: + """ + Return a descriptinve message to describe why a feature is unsupported. + + Return an empty string if the feature is supported. + """ + if pq.version() < want_version: + return ( + f"the feature '{feature}' is not available:" + f" the client libpq version (imported from {self._libpq_source()})" + f" is {pq.version_pretty(pq.version())}; the feature" + f" requires libpq version {pq.version_pretty(want_version)}" + " or newer" + ) + + elif pq.__build_version__ < want_version: + return ( + f"the feature '{feature}' is not available:" + f" you are using a psycopg[{pq.__impl__}] libpq wrapper built" + f" with libpq version {pq.version_pretty(pq.__build_version__)};" + " the feature requires libpq version" + f" {pq.version_pretty(want_version)} or newer" + ) + else: + return "" + + def _libpq_source(self) -> str: + """Return a string reporting where the libpq comes from.""" + if pq.__impl__ == "binary": + version: str = _cmodule.__version__ or "unknown" + return f"the psycopg[binary] package version {version}" + else: + return "system libraries" + + +# The object that will be exposed by the module. +capabilities = Capabilities() diff --git a/backend/.venv/Lib/site-packages/psycopg/_cmodule.py b/backend/.venv/Lib/site-packages/psycopg/_cmodule.py new file mode 100644 index 0000000..33162bc --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_cmodule.py @@ -0,0 +1,24 @@ +""" +Simplify access to the _psycopg module +""" + +# Copyright (C) 2021 The Psycopg Team + +from __future__ import annotations + +from . import pq + +__version__: str | None = None + +# Note: "c" must the first attempt so that mypy associates the variable the +# right module interface. It will not result Optional, but hey. +if pq.__impl__ == "c": + from psycopg_c import _psycopg as _psycopg + from psycopg_c import __version__ as __version__ # noqa: F401 +elif pq.__impl__ == "binary": + from psycopg_binary import _psycopg as _psycopg # type: ignore + from psycopg_binary import __version__ as __version__ # type: ignore # noqa: F401 +elif pq.__impl__ == "python": + _psycopg = None # type: ignore +else: + raise ImportError(f"can't find _psycopg optimised module in {pq.__impl__!r}") diff --git a/backend/.venv/Lib/site-packages/psycopg/_column.py b/backend/.venv/Lib/site-packages/psycopg/_column.py new file mode 100644 index 0000000..9297382 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_column.py @@ -0,0 +1,104 @@ +""" +The Column object in Cursor.description +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +from typing import Any, Sequence, TYPE_CHECKING +from operator import attrgetter + +if TYPE_CHECKING: + from ._cursor_base import BaseCursor + + +class Column(Sequence[Any]): + __module__ = "psycopg" + + def __init__(self, cursor: BaseCursor[Any, Any], index: int): + res = cursor.pgresult + assert res + + fname = res.fname(index) + if fname: + self._name = fname.decode(cursor._encoding) + else: + # COPY_OUT results have columns but no name + self._name = f"column_{index + 1}" + + self._ftype = res.ftype(index) + self._type = cursor.adapters.types.get(self._ftype) + self._fmod = res.fmod(index) + self._fsize = res.fsize(index) + + _attrs = tuple( + attrgetter(attr) + for attr in """ + name type_code display_size internal_size precision scale null_ok + """.split() + ) + + def __repr__(self) -> str: + return ( + f"" + ) + + def __len__(self) -> int: + return 7 + + @property + def type_display(self) -> str: + """A pretty representation of the column type. + + It is composed by the type name, followed by eventual modifiers and + brackets to signify arrays, e.g. :sql:`text`, :sql:`varchar(42)`, + :sql:`date[]`. + """ + if not self._type: + return str(self.type_code) + + return self._type.get_type_display(oid=self.type_code, fmod=self._fmod) + + def __getitem__(self, index: Any) -> Any: + if isinstance(index, slice): + return tuple(getter(self) for getter in self._attrs[index]) + else: + return self._attrs[index](self) + + @property + def name(self) -> str: + """The name of the column.""" + return self._name + + @property + def type_code(self) -> int: + """The numeric OID of the column.""" + return self._ftype + + @property + def display_size(self) -> int | None: + """The field size, for string types such as :sql:`varchar(n)`.""" + return self._type.get_display_size(self._fmod) if self._type else None + + @property + def internal_size(self) -> int | None: + """The internal field size for fixed-size types, None otherwise.""" + fsize = self._fsize + return fsize if fsize >= 0 else None + + @property + def precision(self) -> int | None: + """The number of digits for fixed precision types.""" + return self._type.get_precision(self._fmod) if self._type else None + + @property + def scale(self) -> int | None: + """The number of digits after the decimal point if available.""" + return self._type.get_scale(self._fmod) if self._type else None + + @property + def null_ok(self) -> bool | None: + """Always `!None`""" + return None diff --git a/backend/.venv/Lib/site-packages/psycopg/_compat.py b/backend/.venv/Lib/site-packages/psycopg/_compat.py new file mode 100644 index 0000000..7ffd76b --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_compat.py @@ -0,0 +1,59 @@ +""" +compatibility functions for different Python versions +""" + +# Copyright (C) 2021 The Psycopg Team + +import sys +from functools import partial +from typing import Any + +if sys.version_info >= (3, 9): + from asyncio import to_thread + from zoneinfo import ZoneInfo + from functools import cache + from collections import Counter, deque as Deque + from collections.abc import Callable +else: + import asyncio + from typing import Callable, Counter, Deque, TypeVar + from functools import lru_cache + from backports.zoneinfo import ZoneInfo + + cache = lru_cache(maxsize=None) + + R = TypeVar("R") + + async def to_thread(func: Callable[..., R], /, *args: Any, **kwargs: Any) -> R: + loop = asyncio.get_running_loop() + func_call = partial(func, *args, **kwargs) + return await loop.run_in_executor(None, func_call) + + +if sys.version_info >= (3, 10): + from typing import TypeGuard, TypeAlias +else: + from typing_extensions import TypeGuard, TypeAlias + +if sys.version_info >= (3, 11): + from typing import LiteralString, Self +else: + from typing_extensions import LiteralString, Self + +if sys.version_info >= (3, 13): + from typing import TypeVar +else: + from typing_extensions import TypeVar + +__all__ = [ + "Counter", + "Deque", + "LiteralString", + "Self", + "TypeAlias", + "TypeGuard", + "TypeVar", + "ZoneInfo", + "cache", + "to_thread", +] diff --git a/backend/.venv/Lib/site-packages/psycopg/_connection_base.py b/backend/.venv/Lib/site-packages/psycopg/_connection_base.py new file mode 100644 index 0000000..5741b84 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_connection_base.py @@ -0,0 +1,691 @@ +""" +psycopg connection objects +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import sys +import logging +from typing import Callable, Generic, NamedTuple, TYPE_CHECKING +from weakref import ref, ReferenceType +from warnings import warn +from functools import partial + +from . import pq +from . import errors as e +from . import postgres +from . import generators +from .abc import PQGen, PQGenConn, Query +from .sql import Composable, SQL +from ._tpc import Xid +from .rows import Row +from .adapt import AdaptersMap +from ._enums import IsolationLevel +from ._compat import LiteralString, Self, TypeAlias, TypeVar +from .pq.misc import connection_summary +from ._pipeline import BasePipeline +from ._preparing import PrepareManager +from ._capabilities import capabilities +from ._connection_info import ConnectionInfo + +if TYPE_CHECKING: + from .pq.abc import PGconn, PGresult + from psycopg_pool.base import BasePool + +# Row Type variable for Cursor (when it needs to be distinguished from the +# connection's one) +CursorRow = TypeVar("CursorRow") + +TEXT = pq.Format.TEXT +BINARY = pq.Format.BINARY + +OK = pq.ConnStatus.OK +BAD = pq.ConnStatus.BAD + +COMMAND_OK = pq.ExecStatus.COMMAND_OK +TUPLES_OK = pq.ExecStatus.TUPLES_OK +FATAL_ERROR = pq.ExecStatus.FATAL_ERROR + +IDLE = pq.TransactionStatus.IDLE +INTRANS = pq.TransactionStatus.INTRANS + +_HAS_SEND_CLOSE = capabilities.has_send_close_prepared() + +logger = logging.getLogger("psycopg") + + +class Notify(NamedTuple): + """An asynchronous notification received from the database.""" + + channel: str + """The name of the channel on which the notification was received.""" + + payload: str + """The message attached to the notification.""" + + pid: int + """The PID of the backend process which sent the notification.""" + + +Notify.__module__ = "psycopg" + +NoticeHandler: TypeAlias = Callable[[e.Diagnostic], None] +NotifyHandler: TypeAlias = Callable[[Notify], None] + + +class BaseConnection(Generic[Row]): + """ + Base class for different types of connections. + + Share common functionalities such as access to the wrapped PGconn, but + allow different interfaces (sync/async). + """ + + # DBAPI2 exposed exceptions + Warning = e.Warning + Error = e.Error + InterfaceError = e.InterfaceError + DatabaseError = e.DatabaseError + DataError = e.DataError + OperationalError = e.OperationalError + IntegrityError = e.IntegrityError + InternalError = e.InternalError + ProgrammingError = e.ProgrammingError + NotSupportedError = e.NotSupportedError + + def __init__(self, pgconn: PGconn): + self.pgconn = pgconn + self._autocommit = False + + # None, but set to a copy of the global adapters map as soon as requested. + self._adapters: AdaptersMap | None = None + + self._notice_handlers: list[NoticeHandler] = [] + self._notify_handlers: list[NotifyHandler] = [] + + # Number of transaction blocks currently entered + self._num_transactions = 0 + + self._closed = False # closed by an explicit close() + self._prepared: PrepareManager = PrepareManager() + self._tpc: tuple[Xid, bool] | None = None # xid, prepared + + wself = ref(self) + pgconn.notice_handler = partial(BaseConnection._notice_handler, wself) + pgconn.notify_handler = partial(BaseConnection._notify_handler, wself) + + # Attribute is only set if the connection is from a pool so we can tell + # apart a connection in the pool too (when _pool = None) + self._pool: BasePool | None + + self._pipeline: BasePipeline | None = None + + # Time after which the connection should be closed + self._expire_at: float + + self._isolation_level: IsolationLevel | None = None + self._read_only: bool | None = None + self._deferrable: bool | None = None + self._begin_statement = b"" + + def __del__(self) -> None: + # If fails on connection we might not have this attribute yet + if not hasattr(self, "pgconn"): + return + + # Connection correctly closed + if self.closed: + return + + # Connection in a pool so terminating with the program is normal + if hasattr(self, "_pool"): + return + + warn( + f"connection {self} was deleted while still open." + " Please use 'with' or '.close()' to close the connection", + ResourceWarning, + ) + + def __repr__(self) -> str: + cls = f"{self.__class__.__module__}.{self.__class__.__qualname__}" + info = connection_summary(self.pgconn) + return f"<{cls} {info} at 0x{id(self):x}>" + + @property + def closed(self) -> bool: + """`!True` if the connection is closed.""" + return self.pgconn.status == BAD + + @property + def broken(self) -> bool: + """ + `!True` if the connection was interrupted. + + A broken connection is always `closed`, but wasn't closed in a clean + way, such as using `close()` or a `!with` block. + """ + return self.pgconn.status == BAD and not self._closed + + @property + def autocommit(self) -> bool: + """The autocommit state of the connection.""" + return self._autocommit + + @autocommit.setter + def autocommit(self, value: bool) -> None: + self._set_autocommit(value) + + def _set_autocommit(self, value: bool) -> None: + raise NotImplementedError + + def _set_autocommit_gen(self, value: bool) -> PQGen[None]: + yield from self._check_intrans_gen("autocommit") + self._autocommit = bool(value) + + @property + def isolation_level(self) -> IsolationLevel | None: + """ + The isolation level of the new transactions started on the connection. + """ + return self._isolation_level + + @isolation_level.setter + def isolation_level(self, value: IsolationLevel | None) -> None: + self._set_isolation_level(value) + + def _set_isolation_level(self, value: IsolationLevel | None) -> None: + raise NotImplementedError + + def _set_isolation_level_gen(self, value: IsolationLevel | None) -> PQGen[None]: + yield from self._check_intrans_gen("isolation_level") + self._isolation_level = IsolationLevel(value) if value is not None else None + self._begin_statement = b"" + + @property + def read_only(self) -> bool | None: + """ + The read-only state of the new transactions started on the connection. + """ + return self._read_only + + @read_only.setter + def read_only(self, value: bool | None) -> None: + self._set_read_only(value) + + def _set_read_only(self, value: bool | None) -> None: + raise NotImplementedError + + def _set_read_only_gen(self, value: bool | None) -> PQGen[None]: + yield from self._check_intrans_gen("read_only") + self._read_only = bool(value) if value is not None else None + self._begin_statement = b"" + + @property + def deferrable(self) -> bool | None: + """ + The deferrable state of the new transactions started on the connection. + """ + return self._deferrable + + @deferrable.setter + def deferrable(self, value: bool | None) -> None: + self._set_deferrable(value) + + def _set_deferrable(self, value: bool | None) -> None: + raise NotImplementedError + + def _set_deferrable_gen(self, value: bool | None) -> PQGen[None]: + yield from self._check_intrans_gen("deferrable") + self._deferrable = bool(value) if value is not None else None + self._begin_statement = b"" + + def _check_intrans_gen(self, attribute: str) -> PQGen[None]: + # Raise an exception if we are in a transaction + status = self.pgconn.transaction_status + if status == IDLE and self._pipeline: + yield from self._pipeline._sync_gen() + status = self.pgconn.transaction_status + if status != IDLE: + if self._num_transactions: + raise e.ProgrammingError( + f"can't change {attribute!r} now: " + "connection.transaction() context in progress" + ) + else: + raise e.ProgrammingError( + f"can't change {attribute!r} now: " + "connection in transaction status " + f"{pq.TransactionStatus(status).name}" + ) + + @property + def info(self) -> ConnectionInfo: + """A `ConnectionInfo` attribute to inspect connection properties.""" + return ConnectionInfo(self.pgconn) + + @property + def adapters(self) -> AdaptersMap: + if not self._adapters: + self._adapters = AdaptersMap(postgres.adapters) + + return self._adapters + + @property + def connection(self) -> BaseConnection[Row]: + # implement the AdaptContext protocol + return self + + def fileno(self) -> int: + """Return the file descriptor of the connection. + + This function allows to use the connection as file-like object in + functions waiting for readiness, such as the ones defined in the + `selectors` module. + """ + return self.pgconn.socket + + def cancel(self) -> None: + """Cancel the current operation on the connection.""" + if self._should_cancel(): + c = self.pgconn.get_cancel() + c.cancel() + + def _should_cancel(self) -> bool: + """Check whether the current command should actually be cancelled when + invoking cancel*(). + """ + # cancel() is a no-op if the connection is closed; + # this allows to use the method as callback handler without caring + # about its life. + if self.closed: + return False + if self._tpc and self._tpc[1]: + raise e.ProgrammingError( + "cancel() cannot be used with a prepared two-phase transaction" + ) + return True + + def _cancel_gen(self, *, timeout: float) -> PQGenConn[None]: + cancel_conn = self.pgconn.cancel_conn() + cancel_conn.start() + yield from generators.cancel(cancel_conn, timeout=timeout) + + def add_notice_handler(self, callback: NoticeHandler) -> None: + """ + Register a callable to be invoked when a notice message is received. + + :param callback: the callback to call upon message received. + :type callback: Callable[[~psycopg.errors.Diagnostic], None] + """ + self._notice_handlers.append(callback) + + def remove_notice_handler(self, callback: NoticeHandler) -> None: + """ + Unregister a notice message callable previously registered. + + :param callback: the callback to remove. + :type callback: Callable[[~psycopg.errors.Diagnostic], None] + """ + self._notice_handlers.remove(callback) + + @staticmethod + def _notice_handler( + wself: ReferenceType[BaseConnection[Row]], res: PGresult + ) -> None: + self = wself() + if not (self and self._notice_handlers): + return + + diag = e.Diagnostic(res, self.pgconn._encoding) + for cb in self._notice_handlers: + try: + cb(diag) + except Exception as ex: + logger.exception("error processing notice callback '%s': %s", cb, ex) + + def add_notify_handler(self, callback: NotifyHandler) -> None: + """ + Register a callable to be invoked whenever a notification is received. + + :param callback: the callback to call upon notification received. + :type callback: Callable[[~psycopg.Notify], None] + """ + self._notify_handlers.append(callback) + + def remove_notify_handler(self, callback: NotifyHandler) -> None: + """ + Unregister a notification callable previously registered. + + :param callback: the callback to remove. + :type callback: Callable[[~psycopg.Notify], None] + """ + self._notify_handlers.remove(callback) + + @staticmethod + def _notify_handler( + wself: ReferenceType[BaseConnection[Row]], pgn: pq.PGnotify + ) -> None: + self = wself() + if not (self and self._notify_handlers): + return + + enc = self.pgconn._encoding + n = Notify(pgn.relname.decode(enc), pgn.extra.decode(enc), pgn.be_pid) + for cb in self._notify_handlers: + cb(n) + + @property + def prepare_threshold(self) -> int | None: + """ + Number of times a query is executed before it is prepared. + + - If it is set to 0, every query is prepared the first time it is + executed. + - If it is set to `!None`, prepared statements are disabled on the + connection. + + Default value: 5 + """ + return self._prepared.prepare_threshold + + @prepare_threshold.setter + def prepare_threshold(self, value: int | None) -> None: + self._prepared.prepare_threshold = value + + @property + def prepared_max(self) -> int | None: + """ + Maximum number of prepared statements on the connection. + + `!None` means no max number of prepared statements. The default value + is 100. + """ + rv = self._prepared.prepared_max + return rv if rv != sys.maxsize else None + + @prepared_max.setter + def prepared_max(self, value: int | None) -> None: + if value is None: + value = sys.maxsize + self._prepared.prepared_max = value + + # Generators to perform high-level operations on the connection + # + # These operations are expressed in terms of non-blocking generators + # and the task of waiting when needed (when the generators yield) is left + # to the connections subclass, which might wait either in blocking mode + # or through asyncio. + # + # All these generators assume exclusive access to the connection: subclasses + # should have a lock and hold it before calling and consuming them. + + @classmethod + def _connect_gen( + cls, conninfo: str = "", *, timeout: float = 0.0 + ) -> PQGenConn[Self]: + """Generator to connect to the database and create a new instance.""" + pgconn = yield from generators.connect(conninfo, timeout=timeout) + conn = cls(pgconn) + return conn + + def _exec_command( + self, command: Query, result_format: pq.Format = TEXT + ) -> PQGen[PGresult | None]: + """ + Generator to send a command and receive the result to the backend. + + Only used to implement internal commands such as "commit", with eventual + arguments bound client-side. The cursor can do more complex stuff. + """ + self._check_connection_ok() + + if isinstance(command, str): + command = command.encode(self.pgconn._encoding) + elif isinstance(command, Composable): + command = command.as_bytes(self) + + if self._pipeline: + cmd = partial( + self.pgconn.send_query_params, + command, + None, + result_format=result_format, + ) + self._pipeline.command_queue.append(cmd) + self._pipeline.result_queue.append(None) + return None + + # Unless needed, use the simple query protocol, e.g. to interact with + # pgbouncer. In pipeline mode we always use the advanced query protocol + # instead, see #350 + if result_format == TEXT: + self.pgconn.send_query(command) + else: + self.pgconn.send_query_params(command, None, result_format=result_format) + + result = (yield from generators.execute(self.pgconn))[-1] + if result.status != COMMAND_OK and result.status != TUPLES_OK: + if result.status == FATAL_ERROR: + raise e.error_from_result(result, encoding=self.pgconn._encoding) + else: + raise e.InterfaceError( + f"unexpected result {pq.ExecStatus(result.status).name}" + f" from command {command.decode()!r}" + ) + return result + + def _deallocate(self, name: bytes | None) -> PQGen[None]: + """ + Deallocate one, or all, prepared statement in the session. + + ``name == None`` stands for DEALLOCATE ALL. + + If possible, use protocol-level commands; otherwise use SQL statements. + + Note that PgBouncer doesn't support DEALLOCATE name, but it supports + protocol-level Close from 1.21 and DEALLOCATE ALL from 1.22. + """ + if name is None or not _HAS_SEND_CLOSE: + stmt = b"DEALLOCATE " + name if name is not None else b"DEALLOCATE ALL" + yield from self._exec_command(stmt) + return + + self._check_connection_ok() + + if self._pipeline: + cmd = partial( + self.pgconn.send_close_prepared, + name, + ) + self._pipeline.command_queue.append(cmd) + self._pipeline.result_queue.append(None) + return + + self.pgconn.send_close_prepared(name) + + result = (yield from generators.execute(self.pgconn))[-1] + if result.status != COMMAND_OK: + if result.status == FATAL_ERROR: + raise e.error_from_result(result, encoding=self.pgconn._encoding) + else: + raise e.InterfaceError( + f"unexpected result {pq.ExecStatus(result.status).name}" + " from sending closing prepared statement message" + ) + + def _check_connection_ok(self) -> None: + if self.pgconn.status == OK: + return + + if self.pgconn.status == BAD: + raise e.OperationalError("the connection is closed") + raise e.InterfaceError( + "cannot execute operations: the connection is" + f" in status {self.pgconn.status}" + ) + + def _start_query(self) -> PQGen[None]: + """Generator to start a transaction if necessary.""" + if self._autocommit: + return + + if self.pgconn.transaction_status != IDLE: + return + + yield from self._exec_command(self._get_tx_start_command()) + if self._pipeline: + yield from self._pipeline._sync_gen() + + def _get_tx_start_command(self) -> bytes: + if self._begin_statement: + return self._begin_statement + + parts = [b"BEGIN"] + + if self.isolation_level is not None: + val = IsolationLevel(self.isolation_level) + parts.append(b"ISOLATION LEVEL") + parts.append(val.name.replace("_", " ").encode()) + + if self.read_only is not None: + parts.append(b"READ ONLY" if self.read_only else b"READ WRITE") + + if self.deferrable is not None: + parts.append(b"DEFERRABLE" if self.deferrable else b"NOT DEFERRABLE") + + self._begin_statement = b" ".join(parts) + return self._begin_statement + + def _commit_gen(self) -> PQGen[None]: + """Generator implementing `Connection.commit()`.""" + if self._num_transactions: + raise e.ProgrammingError( + "Explicit commit() forbidden within a Transaction " + "context. (Transaction will be automatically committed " + "on successful exit from context.)" + ) + if self._tpc: + raise e.ProgrammingError( + "commit() cannot be used during a two-phase transaction" + ) + if self.pgconn.transaction_status == IDLE: + return + + yield from self._exec_command(b"COMMIT") + + if self._pipeline: + yield from self._pipeline._sync_gen() + + def _rollback_gen(self) -> PQGen[None]: + """Generator implementing `Connection.rollback()`.""" + if self._num_transactions: + raise e.ProgrammingError( + "Explicit rollback() forbidden within a Transaction " + "context. (Either raise Rollback() or allow " + "an exception to propagate out of the context.)" + ) + if self._tpc: + raise e.ProgrammingError( + "rollback() cannot be used during a two-phase transaction" + ) + + # Get out of a "pipeline aborted" state + if self._pipeline: + yield from self._pipeline._sync_gen() + + if self.pgconn.transaction_status == IDLE: + return + + yield from self._exec_command(b"ROLLBACK") + self._prepared.clear() + yield from self._prepared.maintain_gen(self) + + if self._pipeline: + yield from self._pipeline._sync_gen() + + def xid(self, format_id: int, gtrid: str, bqual: str) -> Xid: + """ + Returns a `Xid` to pass to the `!tpc_*()` methods of this connection. + + The argument types and constraints are explained in + :ref:`two-phase-commit`. + + The values passed to the method will be available on the returned + object as the members `~Xid.format_id`, `~Xid.gtrid`, `~Xid.bqual`. + """ + self._check_tpc() + return Xid.from_parts(format_id, gtrid, bqual) + + def _tpc_begin_gen(self, xid: Xid | str) -> PQGen[None]: + self._check_tpc() + + if not isinstance(xid, Xid): + xid = Xid.from_string(xid) + + if self.pgconn.transaction_status != IDLE: + raise e.ProgrammingError( + "can't start two-phase transaction: connection in status" + f" {pq.TransactionStatus(self.pgconn.transaction_status).name}" + ) + + if self._autocommit: + raise e.ProgrammingError( + "can't use two-phase transactions in autocommit mode" + ) + + self._tpc = (xid, False) + yield from self._exec_command(self._get_tx_start_command()) + + def _tpc_prepare_gen(self) -> PQGen[None]: + if not self._tpc: + raise e.ProgrammingError( + "'tpc_prepare()' must be called inside a two-phase transaction" + ) + if self._tpc[1]: + raise e.ProgrammingError( + "'tpc_prepare()' cannot be used during a prepared two-phase transaction" + ) + xid = self._tpc[0] + self._tpc = (xid, True) + yield from self._exec_command(SQL("PREPARE TRANSACTION {}").format(str(xid))) + if self._pipeline: + yield from self._pipeline._sync_gen() + + def _tpc_finish_gen( + self, action: LiteralString, xid: Xid | str | None + ) -> PQGen[None]: + fname = f"tpc_{action.lower()}()" + if xid is None: + if not self._tpc: + raise e.ProgrammingError( + f"{fname} without xid must must be" + " called inside a two-phase transaction" + ) + xid = self._tpc[0] + else: + if self._tpc: + raise e.ProgrammingError( + f"{fname} with xid must must be called" + " outside a two-phase transaction" + ) + if not isinstance(xid, Xid): + xid = Xid.from_string(xid) + + if self._tpc and not self._tpc[1]: + meth: Callable[[], PQGen[None]] + meth = getattr(self, f"_{action.lower()}_gen") + self._tpc = None + yield from meth() + else: + yield from self._exec_command( + SQL("{} PREPARED {}").format(SQL(action), str(xid)) + ) + self._tpc = None + + def _check_tpc(self) -> None: + """Raise NotSupportedError if TPC is not supported.""" + # TPC supported on every supported PostgreSQL version. + pass diff --git a/backend/.venv/Lib/site-packages/psycopg/_connection_info.py b/backend/.venv/Lib/site-packages/psycopg/_connection_info.py new file mode 100644 index 0000000..0db5913 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_connection_info.py @@ -0,0 +1,173 @@ +""" +Objects to return information about a PostgreSQL connection. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +from pathlib import Path +from datetime import tzinfo + +from . import pq +from ._tz import get_tzinfo +from .conninfo import make_conninfo + + +class ConnectionInfo: + """Allow access to information about the connection.""" + + __module__ = "psycopg" + + def __init__(self, pgconn: pq.abc.PGconn): + self.pgconn = pgconn + + @property + def vendor(self) -> str: + """A string representing the database vendor connected to.""" + return "PostgreSQL" + + @property + def host(self) -> str: + """The server host name of the active connection. See :pq:`PQhost()`.""" + return self._get_pgconn_attr("host") + + @property + def hostaddr(self) -> str: + """The server IP address of the connection. See :pq:`PQhostaddr()`.""" + return self._get_pgconn_attr("hostaddr") + + @property + def port(self) -> int: + """The port of the active connection. See :pq:`PQport()`.""" + return int(self._get_pgconn_attr("port")) + + @property + def dbname(self) -> str: + """The database name of the connection. See :pq:`PQdb()`.""" + return self._get_pgconn_attr("db") + + @property + def user(self) -> str: + """The user name of the connection. See :pq:`PQuser()`.""" + return self._get_pgconn_attr("user") + + @property + def password(self) -> str: + """The password of the connection. See :pq:`PQpass()`.""" + return self._get_pgconn_attr("password") + + @property + def options(self) -> str: + """ + The command-line options passed in the connection request. + See :pq:`PQoptions`. + """ + return self._get_pgconn_attr("options") + + def get_parameters(self) -> dict[str, str]: + """Return the connection parameters values. + + Return all the parameters set to a non-default value, which might come + either from the connection string and parameters passed to + `~Connection.connect()` or from environment variables. The password + is never returned (you can read it using the `password` attribute). + """ + pyenc = self.encoding + + # Get the known defaults to avoid reporting them + defaults = { + i.keyword: i.compiled + for i in pq.Conninfo.get_defaults() + if i.compiled is not None + } + # Not returned by the libq. Bug? Bet we're using SSH. + defaults.setdefault(b"channel_binding", b"prefer") + defaults[b"passfile"] = str(Path.home() / ".pgpass").encode() + + return { + i.keyword.decode(pyenc): i.val.decode(pyenc) + for i in self.pgconn.info + if i.val is not None + and i.keyword != b"password" + and i.val != defaults.get(i.keyword) + } + + @property + def dsn(self) -> str: + """Return the connection string to connect to the database. + + The string contains all the parameters set to a non-default value, + which might come either from the connection string and parameters + passed to `~Connection.connect()` or from environment variables. The + password is never returned (you can read it using the `password` + attribute). + """ + return make_conninfo(**self.get_parameters()) + + @property + def status(self) -> pq.ConnStatus: + """The status of the connection. See :pq:`PQstatus()`.""" + return pq.ConnStatus(self.pgconn.status) + + @property + def transaction_status(self) -> pq.TransactionStatus: + """ + The current in-transaction status of the session. + See :pq:`PQtransactionStatus()`. + """ + return pq.TransactionStatus(self.pgconn.transaction_status) + + @property + def pipeline_status(self) -> pq.PipelineStatus: + """ + The current pipeline status of the client. + See :pq:`PQpipelineStatus()`. + """ + return pq.PipelineStatus(self.pgconn.pipeline_status) + + def parameter_status(self, param_name: str) -> str | None: + """ + Return a parameter setting of the connection. + + Return `None` is the parameter is unknown. + """ + res = self.pgconn.parameter_status(param_name.encode(self.encoding)) + return res.decode(self.encoding) if res is not None else None + + @property + def server_version(self) -> int: + """ + An integer representing the server version. See :pq:`PQserverVersion()`. + """ + return self.pgconn.server_version + + @property + def backend_pid(self) -> int: + """ + The process ID (PID) of the backend process handling this connection. + See :pq:`PQbackendPID()`. + """ + return self.pgconn.backend_pid + + @property + def error_message(self) -> str: + """ + The error message most recently generated by an operation on the connection. + See :pq:`PQerrorMessage()`. + """ + return self._get_pgconn_attr("error_message") + + @property + def timezone(self) -> tzinfo: + """The Python timezone info of the connection's timezone.""" + return get_tzinfo(self.pgconn) + + @property + def encoding(self) -> str: + """The Python codec name of the connection's client encoding.""" + return self.pgconn._encoding + + def _get_pgconn_attr(self, name: str) -> str: + value: bytes = getattr(self.pgconn, name) + return value.decode(self.encoding) diff --git a/backend/.venv/Lib/site-packages/psycopg/_conninfo_attempts.py b/backend/.venv/Lib/site-packages/psycopg/_conninfo_attempts.py new file mode 100644 index 0000000..8c75e60 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_conninfo_attempts.py @@ -0,0 +1,96 @@ +# WARNING: this file is auto-generated by 'async_to_sync.py' +# from the original file '_conninfo_attempts_async.py' +# DO NOT CHANGE! Change the original file instead. +""" +Separate connection attempts from a connection string. +""" + +# Copyright (C) 2024 The Psycopg Team + +from __future__ import annotations + +import socket +import logging +from random import shuffle + +from . import errors as e +from .abc import ConnDict, ConnMapping +from ._conninfo_utils import get_param, is_ip_address, get_param_def +from ._conninfo_utils import split_attempts + + +logger = logging.getLogger("psycopg") + + +def conninfo_attempts(params: ConnMapping) -> list[ConnDict]: + """Split a set of connection params on the single attempts to perform. + + A connection param can perform more than one attempt more than one ``host`` + is provided. + + Also perform async resolution of the hostname into hostaddr. Because a host + can resolve to more than one address, this can lead to yield more attempts + too. Raise `OperationalError` if no host could be resolved. + + Because the libpq async function doesn't honour the timeout, we need to + reimplement the repeated attempts. + """ + last_exc = None + attempts = [] + for attempt in split_attempts(params): + try: + attempts.extend(_resolve_hostnames(attempt)) + except OSError as ex: + logger.debug("failed to resolve host %r: %s", attempt.get("host"), ex) + last_exc = ex + + if not attempts: + assert last_exc + # We couldn't resolve anything + raise e.OperationalError(str(last_exc)) + + if get_param(params, "load_balance_hosts") == "random": + shuffle(attempts) + + return attempts + + +def _resolve_hostnames(params: ConnDict) -> list[ConnDict]: + """ + Perform async DNS lookup of the hosts and return a list of connection attempts. + + If a ``host`` param is present but not ``hostname``, resolve the host + addresses asynchronously. + + :param params: The input parameters, for instance as returned by + `~psycopg.conninfo.conninfo_to_dict()`. The function expects at most + a single entry for host, hostaddr because it is designed to further + process the input of split_attempts(). + + :return: A list of attempts to make (to include the case of a hostname + resolving to more than one IP). + """ + host = get_param(params, "host") + if not host or host.startswith("/") or host[1:2] == ":": + # Local path, or no host to resolve + return [params] + + hostaddr = get_param(params, "hostaddr") + if hostaddr: + # Already resolved + return [params] + + if is_ip_address(host): + # If the host is already an ip address don't try to resolve it + return [{**params, "hostaddr": host}] + + port = get_param(params, "port") + if not port: + port_def = get_param_def("port") + port = port_def and port_def.compiled or "5432" + + ans = socket.getaddrinfo( + host, port, proto=socket.IPPROTO_TCP, type=socket.SOCK_STREAM + ) + + return [{**params, "hostaddr": item[4][0]} for item in ans] diff --git a/backend/.venv/Lib/site-packages/psycopg/_conninfo_attempts_async.py b/backend/.venv/Lib/site-packages/psycopg/_conninfo_attempts_async.py new file mode 100644 index 0000000..ff8b15d --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_conninfo_attempts_async.py @@ -0,0 +1,101 @@ +""" +Separate connection attempts from a connection string. +""" + +# Copyright (C) 2024 The Psycopg Team + +from __future__ import annotations + +import socket +import logging +from random import shuffle + +from . import errors as e +from .abc import ConnDict, ConnMapping +from ._conninfo_utils import get_param, is_ip_address, get_param_def +from ._conninfo_utils import split_attempts + +if True: # ASYNC: + import asyncio + +logger = logging.getLogger("psycopg") + + +async def conninfo_attempts_async(params: ConnMapping) -> list[ConnDict]: + """Split a set of connection params on the single attempts to perform. + + A connection param can perform more than one attempt more than one ``host`` + is provided. + + Also perform async resolution of the hostname into hostaddr. Because a host + can resolve to more than one address, this can lead to yield more attempts + too. Raise `OperationalError` if no host could be resolved. + + Because the libpq async function doesn't honour the timeout, we need to + reimplement the repeated attempts. + """ + last_exc = None + attempts = [] + for attempt in split_attempts(params): + try: + attempts.extend(await _resolve_hostnames(attempt)) + except OSError as ex: + logger.debug("failed to resolve host %r: %s", attempt.get("host"), ex) + last_exc = ex + + if not attempts: + assert last_exc + # We couldn't resolve anything + raise e.OperationalError(str(last_exc)) + + if get_param(params, "load_balance_hosts") == "random": + shuffle(attempts) + + return attempts + + +async def _resolve_hostnames(params: ConnDict) -> list[ConnDict]: + """ + Perform async DNS lookup of the hosts and return a list of connection attempts. + + If a ``host`` param is present but not ``hostname``, resolve the host + addresses asynchronously. + + :param params: The input parameters, for instance as returned by + `~psycopg.conninfo.conninfo_to_dict()`. The function expects at most + a single entry for host, hostaddr because it is designed to further + process the input of split_attempts(). + + :return: A list of attempts to make (to include the case of a hostname + resolving to more than one IP). + """ + host = get_param(params, "host") + if not host or host.startswith("/") or host[1:2] == ":": + # Local path, or no host to resolve + return [params] + + hostaddr = get_param(params, "hostaddr") + if hostaddr: + # Already resolved + return [params] + + if is_ip_address(host): + # If the host is already an ip address don't try to resolve it + return [{**params, "hostaddr": host}] + + port = get_param(params, "port") + if not port: + port_def = get_param_def("port") + port = port_def and port_def.compiled or "5432" + + if True: # ASYNC: + loop = asyncio.get_running_loop() + ans = await loop.getaddrinfo( + host, port, proto=socket.IPPROTO_TCP, type=socket.SOCK_STREAM + ) + else: + ans = socket.getaddrinfo( + host, port, proto=socket.IPPROTO_TCP, type=socket.SOCK_STREAM + ) + + return [{**params, "hostaddr": item[4][0]} for item in ans] diff --git a/backend/.venv/Lib/site-packages/psycopg/_conninfo_utils.py b/backend/.venv/Lib/site-packages/psycopg/_conninfo_utils.py new file mode 100644 index 0000000..4e7025d --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_conninfo_utils.py @@ -0,0 +1,124 @@ +""" +Internal utilities to manipulate connection strings +""" + +# Copyright (C) 2024 The Psycopg Team + +from __future__ import annotations + +import os +from functools import lru_cache +from ipaddress import ip_address +from dataclasses import dataclass + +from . import pq +from .abc import ConnDict, ConnMapping +from . import errors as e + + +def split_attempts(params: ConnMapping) -> list[ConnDict]: + """ + Split connection parameters with a sequence of hosts into separate attempts. + """ + + def split_val(key: str) -> list[str]: + val = get_param(params, key) + return val.split(",") if val else [] + + hosts = split_val("host") + hostaddrs = split_val("hostaddr") + ports = split_val("port") + + if hosts and hostaddrs and len(hosts) != len(hostaddrs): + raise e.OperationalError( + f"could not match {len(hosts)} host names" + f" with {len(hostaddrs)} hostaddr values" + ) + + nhosts = max(len(hosts), len(hostaddrs)) + + if 1 < len(ports) != nhosts: + raise e.OperationalError( + f"could not match {len(ports)} port numbers to {len(hosts)} hosts" + ) + + # A single attempt to make. Don't mangle the conninfo string. + if nhosts <= 1: + return [{**params}] + + if len(ports) == 1: + ports *= nhosts + + # Now all lists are either empty or have the same length + rv = [] + for i in range(nhosts): + attempt = {**params} + if hosts: + attempt["host"] = hosts[i] + if hostaddrs: + attempt["hostaddr"] = hostaddrs[i] + if ports: + attempt["port"] = ports[i] + rv.append(attempt) + + return rv + + +def get_param(params: ConnMapping, name: str) -> str | None: + """ + Return a value from a connection string. + + The value may be also specified in a PG* env var. + """ + if name in params: + return str(params[name]) + + # TODO: check if in service + + paramdef = get_param_def(name) + if not paramdef: + return None + + env = os.environ.get(paramdef.envvar) + if env is not None: + return env + + return None + + +@dataclass +class ParamDef: + """ + Information about defaults and env vars for connection params + """ + + keyword: str + envvar: str + compiled: str | None + + +def get_param_def(keyword: str, _cache: dict[str, ParamDef] = {}) -> ParamDef | None: + """ + Return the ParamDef of a connection string parameter. + """ + if not _cache: + defs = pq.Conninfo.get_defaults() + for d in defs: + cd = ParamDef( + keyword=d.keyword.decode(), + envvar=d.envvar.decode() if d.envvar else "", + compiled=d.compiled.decode() if d.compiled is not None else None, + ) + _cache[cd.keyword] = cd + + return _cache.get(keyword) + + +@lru_cache +def is_ip_address(s: str) -> bool: + """Return True if the string represent a valid ip address.""" + try: + ip_address(s) + except ValueError: + return False + return True diff --git a/backend/.venv/Lib/site-packages/psycopg/_copy.py b/backend/.venv/Lib/site-packages/psycopg/_copy.py new file mode 100644 index 0000000..6d85066 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_copy.py @@ -0,0 +1,298 @@ +# WARNING: this file is auto-generated by 'async_to_sync.py' +# from the original file '_copy_async.py' +# DO NOT CHANGE! Change the original file instead. +""" +Objects to support the COPY protocol (sync version). +""" + +# Copyright (C) 2023 The Psycopg Team + +from __future__ import annotations + +from abc import ABC, abstractmethod +from types import TracebackType +from typing import Any, Iterator, Sequence, TYPE_CHECKING + +from . import pq +from . import errors as e +from ._compat import Self +from ._copy_base import BaseCopy, MAX_BUFFER_SIZE, QUEUE_SIZE, PREFER_FLUSH +from .generators import copy_to, copy_end +from ._acompat import spawn, gather, Queue, Worker + +if TYPE_CHECKING: + from .abc import Buffer + from .cursor import Cursor + from .connection import Connection # noqa: F401 + +COPY_IN = pq.ExecStatus.COPY_IN +COPY_OUT = pq.ExecStatus.COPY_OUT + +ACTIVE = pq.TransactionStatus.ACTIVE + + +class Copy(BaseCopy["Connection[Any]"]): + """Manage an asynchronous :sql:`COPY` operation. + + :param cursor: the cursor where the operation is performed. + :param binary: if `!True`, write binary format. + :param writer: the object to write to destination. If not specified, write + to the `!cursor` connection. + + Choosing `!binary` is not necessary if the cursor has executed a + :sql:`COPY` operation, because the operation result describes the format + too. The parameter is useful when a `!Copy` object is created manually and + no operation is performed on the cursor, such as when using ``writer=``\\ + `~psycopg.copy.FileWriter`. + """ + + __module__ = "psycopg" + + writer: Writer + + def __init__( + self, + cursor: Cursor[Any], + *, + binary: bool | None = None, + writer: Writer | None = None, + ): + super().__init__(cursor, binary=binary) + if not writer: + writer = LibpqWriter(cursor) + + self.writer = writer + self._write = writer.write + + def __enter__(self) -> Self: + self._enter() + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self.finish(exc_val) + + # End user sync interface + + def __iter__(self) -> Iterator[Buffer]: + """Implement block-by-block iteration on :sql:`COPY TO`.""" + while True: + data = self.read() + if not data: + break + yield data + + def read(self) -> Buffer: + """ + Read an unparsed row after a :sql:`COPY TO` operation. + + Return an empty string when the data is finished. + """ + return self.connection.wait(self._read_gen()) + + def rows(self) -> Iterator[tuple[Any, ...]]: + """ + Iterate on the result of a :sql:`COPY TO` operation record by record. + + Note that the records returned will be tuples of unparsed strings or + bytes, unless data types are specified using `set_types()`. + """ + while True: + record = self.read_row() + if record is None: + break + yield record + + def read_row(self) -> tuple[Any, ...] | None: + """ + Read a parsed row of data from a table after a :sql:`COPY TO` operation. + + Return `!None` when the data is finished. + + Note that the records returned will be tuples of unparsed strings or + bytes, unless data types are specified using `set_types()`. + """ + return self.connection.wait(self._read_row_gen()) + + def write(self, buffer: Buffer | str) -> None: + """ + Write a block of data to a table after a :sql:`COPY FROM` operation. + + If the :sql:`COPY` is in binary format `!buffer` must be `!bytes`. In + text mode it can be either `!bytes` or `!str`. + """ + data = self.formatter.write(buffer) + if data: + self._write(data) + + def write_row(self, row: Sequence[Any]) -> None: + """Write a record to a table after a :sql:`COPY FROM` operation.""" + data = self.formatter.write_row(row) + if data: + self._write(data) + + def finish(self, exc: BaseException | None) -> None: + """Terminate the copy operation and free the resources allocated. + + You shouldn't need to call this function yourself: it is usually called + by exit. It is available if, despite what is documented, you end up + using the `Copy` object outside a block. + """ + if self._direction == COPY_IN: + data = self.formatter.end() + if data: + self._write(data) + self.writer.finish(exc) + self._finished = True + else: + if not exc: + return + if self._pgconn.transaction_status != ACTIVE: + # The server has already finished to send copy data. The connection + # is already in a good state. + return + # Throw a cancel to the server, then consume the rest of the copy data + # (which might or might not have been already transferred entirely to + # the client, so we won't necessary see the exception associated with + # canceling). + self.connection._try_cancel() + self.connection.wait(self._end_copy_out_gen()) + + +class Writer(ABC): + """ + A class to write copy data somewhere (for async connections). + """ + + @abstractmethod + def write(self, data: Buffer) -> None: + """Write some data to destination.""" + ... + + def finish(self, exc: BaseException | None = None) -> None: + """ + Called when write operations are finished. + + If operations finished with an error, it will be passed to ``exc``. + """ + pass + + +class LibpqWriter(Writer): + """ + An `Writer` to write copy data to a Postgres database. + """ + + __module__ = "psycopg.copy" + + def __init__(self, cursor: Cursor[Any]): + self.cursor = cursor + self.connection = cursor.connection + self._pgconn = self.connection.pgconn + + def write(self, data: Buffer) -> None: + if len(data) <= MAX_BUFFER_SIZE: + # Most used path: we don't need to split the buffer in smaller + # bits, so don't make a copy. + self.connection.wait(copy_to(self._pgconn, data, flush=PREFER_FLUSH)) + else: + # Copy a buffer too large in chunks to avoid causing a memory + # error in the libpq, which may cause an infinite loop (#255). + for i in range(0, len(data), MAX_BUFFER_SIZE): + self.connection.wait( + copy_to( + self._pgconn, data[i : i + MAX_BUFFER_SIZE], flush=PREFER_FLUSH + ) + ) + + def finish(self, exc: BaseException | None = None) -> None: + bmsg: bytes | None + if exc: + msg = f"error from Python: {type(exc).__qualname__} - {exc}" + bmsg = msg.encode(self._pgconn._encoding, "replace") + else: + bmsg = None + + try: + res = self.connection.wait(copy_end(self._pgconn, bmsg)) + # The QueryCanceled is expected if we sent an exception message to + # pgconn.put_copy_end(). The Python exception that generated that + # cancelling is more important, so don't clobber it. + except e.QueryCanceled: + if not bmsg: + raise + else: + self.cursor._results = [res] + + +class QueuedLibpqWriter(LibpqWriter): + """ + `Writer` using a buffer to queue data to write. + + `write()` returns immediately, so that the main thread can be CPU-bound + formatting messages, while a worker thread can be IO-bound waiting to write + on the connection. + """ + + __module__ = "psycopg.copy" + + def __init__(self, cursor: Cursor[Any]): + super().__init__(cursor) + + self._queue: Queue[Buffer] = Queue(maxsize=QUEUE_SIZE) + self._worker: Worker | None = None + self._worker_error: BaseException | None = None + + def worker(self) -> None: + """Push data to the server when available from the copy queue. + + Terminate reading when the queue receives a false-y value, or in case + of error. + + The function is designed to be run in a separate task. + """ + try: + while True: + data = self._queue.get() + if not data: + break + self.connection.wait(copy_to(self._pgconn, data, flush=PREFER_FLUSH)) + except BaseException as ex: + # Propagate the error to the main thread. + self._worker_error = ex + + def write(self, data: Buffer) -> None: + if not self._worker: + # warning: reference loop, broken by _write_end + self._worker = spawn(self.worker) + + # If the worker thread raies an exception, re-raise it to the caller. + if self._worker_error: + raise self._worker_error + + if len(data) <= MAX_BUFFER_SIZE: + # Most used path: we don't need to split the buffer in smaller + # bits, so don't make a copy. + self._queue.put(data) + else: + # Copy a buffer too large in chunks to avoid causing a memory + # error in the libpq, which may cause an infinite loop (#255). + for i in range(0, len(data), MAX_BUFFER_SIZE): + self._queue.put(data[i : i + MAX_BUFFER_SIZE]) + + def finish(self, exc: BaseException | None = None) -> None: + self._queue.put(b"") + + if self._worker: + gather(self._worker) + self._worker = None # break reference loops if any + + # Check if the worker thread raised any exception before terminating. + if self._worker_error: + raise self._worker_error + + super().finish(exc) diff --git a/backend/.venv/Lib/site-packages/psycopg/_copy_async.py b/backend/.venv/Lib/site-packages/psycopg/_copy_async.py new file mode 100644 index 0000000..02d27ba --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_copy_async.py @@ -0,0 +1,299 @@ +""" +Objects to support the COPY protocol (async version). +""" + +# Copyright (C) 2023 The Psycopg Team + +from __future__ import annotations + +from abc import ABC, abstractmethod +from types import TracebackType +from typing import Any, AsyncIterator, Sequence, TYPE_CHECKING + +from . import pq +from . import errors as e +from ._compat import Self +from ._copy_base import BaseCopy, MAX_BUFFER_SIZE, QUEUE_SIZE, PREFER_FLUSH +from .generators import copy_to, copy_end +from ._acompat import aspawn, agather, AQueue, AWorker + +if TYPE_CHECKING: + from .abc import Buffer + from .cursor_async import AsyncCursor + from .connection_async import AsyncConnection # noqa: F401 + +COPY_IN = pq.ExecStatus.COPY_IN +COPY_OUT = pq.ExecStatus.COPY_OUT + +ACTIVE = pq.TransactionStatus.ACTIVE + + +class AsyncCopy(BaseCopy["AsyncConnection[Any]"]): + """Manage an asynchronous :sql:`COPY` operation. + + :param cursor: the cursor where the operation is performed. + :param binary: if `!True`, write binary format. + :param writer: the object to write to destination. If not specified, write + to the `!cursor` connection. + + Choosing `!binary` is not necessary if the cursor has executed a + :sql:`COPY` operation, because the operation result describes the format + too. The parameter is useful when a `!Copy` object is created manually and + no operation is performed on the cursor, such as when using ``writer=``\\ + `~psycopg.copy.FileWriter`. + """ + + __module__ = "psycopg" + + writer: AsyncWriter + + def __init__( + self, + cursor: AsyncCursor[Any], + *, + binary: bool | None = None, + writer: AsyncWriter | None = None, + ): + super().__init__(cursor, binary=binary) + if not writer: + writer = AsyncLibpqWriter(cursor) + + self.writer = writer + self._write = writer.write + + async def __aenter__(self) -> Self: + self._enter() + return self + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + await self.finish(exc_val) + + # End user sync interface + + async def __aiter__(self) -> AsyncIterator[Buffer]: + """Implement block-by-block iteration on :sql:`COPY TO`.""" + while True: + data = await self.read() + if not data: + break + yield data + + async def read(self) -> Buffer: + """ + Read an unparsed row after a :sql:`COPY TO` operation. + + Return an empty string when the data is finished. + """ + return await self.connection.wait(self._read_gen()) + + async def rows(self) -> AsyncIterator[tuple[Any, ...]]: + """ + Iterate on the result of a :sql:`COPY TO` operation record by record. + + Note that the records returned will be tuples of unparsed strings or + bytes, unless data types are specified using `set_types()`. + """ + while True: + record = await self.read_row() + if record is None: + break + yield record + + async def read_row(self) -> tuple[Any, ...] | None: + """ + Read a parsed row of data from a table after a :sql:`COPY TO` operation. + + Return `!None` when the data is finished. + + Note that the records returned will be tuples of unparsed strings or + bytes, unless data types are specified using `set_types()`. + """ + return await self.connection.wait(self._read_row_gen()) + + async def write(self, buffer: Buffer | str) -> None: + """ + Write a block of data to a table after a :sql:`COPY FROM` operation. + + If the :sql:`COPY` is in binary format `!buffer` must be `!bytes`. In + text mode it can be either `!bytes` or `!str`. + """ + data = self.formatter.write(buffer) + if data: + await self._write(data) + + async def write_row(self, row: Sequence[Any]) -> None: + """Write a record to a table after a :sql:`COPY FROM` operation.""" + data = self.formatter.write_row(row) + if data: + await self._write(data) + + async def finish(self, exc: BaseException | None) -> None: + """Terminate the copy operation and free the resources allocated. + + You shouldn't need to call this function yourself: it is usually called + by exit. It is available if, despite what is documented, you end up + using the `Copy` object outside a block. + """ + if self._direction == COPY_IN: + data = self.formatter.end() + if data: + await self._write(data) + await self.writer.finish(exc) + self._finished = True + else: + if not exc: + return + + if self._pgconn.transaction_status != ACTIVE: + # The server has already finished to send copy data. The connection + # is already in a good state. + return + + # Throw a cancel to the server, then consume the rest of the copy data + # (which might or might not have been already transferred entirely to + # the client, so we won't necessary see the exception associated with + # canceling). + await self.connection._try_cancel() + await self.connection.wait(self._end_copy_out_gen()) + + +class AsyncWriter(ABC): + """ + A class to write copy data somewhere (for async connections). + """ + + @abstractmethod + async def write(self, data: Buffer) -> None: + """Write some data to destination.""" + ... + + async def finish(self, exc: BaseException | None = None) -> None: + """ + Called when write operations are finished. + + If operations finished with an error, it will be passed to ``exc``. + """ + pass + + +class AsyncLibpqWriter(AsyncWriter): + """ + An `AsyncWriter` to write copy data to a Postgres database. + """ + + __module__ = "psycopg.copy" + + def __init__(self, cursor: AsyncCursor[Any]): + self.cursor = cursor + self.connection = cursor.connection + self._pgconn = self.connection.pgconn + + async def write(self, data: Buffer) -> None: + if len(data) <= MAX_BUFFER_SIZE: + # Most used path: we don't need to split the buffer in smaller + # bits, so don't make a copy. + await self.connection.wait(copy_to(self._pgconn, data, flush=PREFER_FLUSH)) + else: + # Copy a buffer too large in chunks to avoid causing a memory + # error in the libpq, which may cause an infinite loop (#255). + for i in range(0, len(data), MAX_BUFFER_SIZE): + await self.connection.wait( + copy_to( + self._pgconn, data[i : i + MAX_BUFFER_SIZE], flush=PREFER_FLUSH + ) + ) + + async def finish(self, exc: BaseException | None = None) -> None: + bmsg: bytes | None + if exc: + msg = f"error from Python: {type(exc).__qualname__} - {exc}" + bmsg = msg.encode(self._pgconn._encoding, "replace") + else: + bmsg = None + + try: + res = await self.connection.wait(copy_end(self._pgconn, bmsg)) + # The QueryCanceled is expected if we sent an exception message to + # pgconn.put_copy_end(). The Python exception that generated that + # cancelling is more important, so don't clobber it. + except e.QueryCanceled: + if not bmsg: + raise + else: + self.cursor._results = [res] + + +class AsyncQueuedLibpqWriter(AsyncLibpqWriter): + """ + `AsyncWriter` using a buffer to queue data to write. + + `write()` returns immediately, so that the main thread can be CPU-bound + formatting messages, while a worker thread can be IO-bound waiting to write + on the connection. + """ + + __module__ = "psycopg.copy" + + def __init__(self, cursor: AsyncCursor[Any]): + super().__init__(cursor) + + self._queue: AQueue[Buffer] = AQueue(maxsize=QUEUE_SIZE) + self._worker: AWorker | None = None + self._worker_error: BaseException | None = None + + async def worker(self) -> None: + """Push data to the server when available from the copy queue. + + Terminate reading when the queue receives a false-y value, or in case + of error. + + The function is designed to be run in a separate task. + """ + try: + while True: + data = await self._queue.get() + if not data: + break + await self.connection.wait( + copy_to(self._pgconn, data, flush=PREFER_FLUSH) + ) + except BaseException as ex: + # Propagate the error to the main thread. + self._worker_error = ex + + async def write(self, data: Buffer) -> None: + if not self._worker: + # warning: reference loop, broken by _write_end + self._worker = aspawn(self.worker) + + # If the worker thread raies an exception, re-raise it to the caller. + if self._worker_error: + raise self._worker_error + + if len(data) <= MAX_BUFFER_SIZE: + # Most used path: we don't need to split the buffer in smaller + # bits, so don't make a copy. + await self._queue.put(data) + else: + # Copy a buffer too large in chunks to avoid causing a memory + # error in the libpq, which may cause an infinite loop (#255). + for i in range(0, len(data), MAX_BUFFER_SIZE): + await self._queue.put(data[i : i + MAX_BUFFER_SIZE]) + + async def finish(self, exc: BaseException | None = None) -> None: + await self._queue.put(b"") + + if self._worker: + await agather(self._worker) + self._worker = None # break reference loops if any + + # Check if the worker thread raised any exception before terminating. + if self._worker_error: + raise self._worker_error + + await super().finish(exc) diff --git a/backend/.venv/Lib/site-packages/psycopg/_copy_base.py b/backend/.venv/Lib/site-packages/psycopg/_copy_base.py new file mode 100644 index 0000000..9217a90 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_copy_base.py @@ -0,0 +1,438 @@ +""" +psycopg copy support +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import re +import sys +import struct +from abc import ABC, abstractmethod +from typing import Any, Generic, Match, Sequence, TYPE_CHECKING + +from . import pq +from . import adapt +from . import errors as e +from .abc import Buffer, ConnectionType, PQGen, Transformer +from .pq.misc import connection_summary +from ._cmodule import _psycopg +from .generators import copy_from + +if TYPE_CHECKING: + from ._cursor_base import BaseCursor + +PY_TEXT = adapt.PyFormat.TEXT +PY_BINARY = adapt.PyFormat.BINARY + +TEXT = pq.Format.TEXT +BINARY = pq.Format.BINARY + +COPY_IN = pq.ExecStatus.COPY_IN +COPY_OUT = pq.ExecStatus.COPY_OUT + +# Size of data to accumulate before sending it down the network. We fill a +# buffer this size field by field, and when it passes the threshold size +# we ship it, so it may end up being bigger than this. +BUFFER_SIZE = 32 * 1024 + +# Maximum data size we want to queue to send to the libpq copy. Sending a +# buffer too big to be handled can cause an infinite loop in the libpq +# (#255) so we want to split it in more digestable chunks. +MAX_BUFFER_SIZE = 4 * BUFFER_SIZE +# Note: making this buffer too large, e.g. +# MAX_BUFFER_SIZE = 1024 * 1024 +# makes operations *way* slower! Probably triggering some quadraticity +# in the libpq memory management and data sending. + +# Max size of the write queue of buffers. More than that copy will block +# Each buffer should be around BUFFER_SIZE size. +QUEUE_SIZE = 1024 + +# On certain systems, memmove seems particularly slow and flushing often is +# more performing than accumulating a larger buffer. See #746 for details. +PREFER_FLUSH = sys.platform == "darwin" + + +class BaseCopy(Generic[ConnectionType]): + """ + Base implementation for the copy user interface. + + Two subclasses expose real methods with the sync/async differences. + + The difference between the text and binary format is managed by two + different `Formatter` subclasses. + + Writing (the I/O part) is implemented in the subclasses by a `Writer` or + `AsyncWriter` instance. Normally writing implies sending copy data to a + database, but a different writer might be chosen, e.g. to stream data into + a file for later use. + """ + + formatter: Formatter + + def __init__( + self, + cursor: BaseCursor[ConnectionType, Any], + *, + binary: bool | None = None, + ): + self.cursor = cursor + self.connection = cursor.connection + self._pgconn = self.connection.pgconn + + result = cursor.pgresult + if result: + self._direction = result.status + if self._direction != COPY_IN and self._direction != COPY_OUT: + raise e.ProgrammingError( + "the cursor should have performed a COPY operation;" + f" its status is {pq.ExecStatus(self._direction).name} instead" + ) + else: + self._direction = COPY_IN + + if binary is None: + binary = bool(result and result.binary_tuples) + + tx: Transformer = getattr(cursor, "_tx", None) or adapt.Transformer(cursor) + if binary: + self.formatter = BinaryFormatter(tx) + else: + self.formatter = TextFormatter(tx, encoding=self._pgconn._encoding) + + self._finished = False + + def __repr__(self) -> str: + cls = f"{self.__class__.__module__}.{self.__class__.__qualname__}" + info = connection_summary(self._pgconn) + return f"<{cls} {info} at 0x{id(self):x}>" + + def _enter(self) -> None: + if self._finished: + raise TypeError("copy blocks can be used only once") + + def set_types(self, types: Sequence[int | str]) -> None: + """ + Set the types expected in a COPY operation. + + The types must be specified as a sequence of oid or PostgreSQL type + names (e.g. ``int4``, ``timestamptz[]``). + + This operation overcomes the lack of metadata returned by PostgreSQL + when a COPY operation begins: + + - On :sql:`COPY TO`, `!set_types()` allows to specify what types the + operation returns. If `!set_types()` is not used, the data will be + returned as unparsed strings or bytes instead of Python objects. + + - On :sql:`COPY FROM`, `!set_types()` allows to choose what type the + database expects. This is especially useful in binary copy, because + PostgreSQL will apply no cast rule. + + """ + registry = self.cursor.adapters.types + oids = [t if isinstance(t, int) else registry.get_oid(t) for t in types] + + if self._direction == COPY_IN: + self.formatter.transformer.set_dumper_types(oids, self.formatter.format) + else: + self.formatter.transformer.set_loader_types(oids, self.formatter.format) + + # High level copy protocol generators (state change of the Copy object) + + def _read_gen(self) -> PQGen[Buffer]: + if self._finished: + return memoryview(b"") + + res = yield from copy_from(self._pgconn) + if isinstance(res, memoryview): + return res + + # res is the final PGresult + self._finished = True + + # This result is a COMMAND_OK which has info about the number of rows + # returned, but not about the columns, which is instead an information + # that was received on the COPY_OUT result at the beginning of COPY. + # So, don't replace the results in the cursor, just update the rowcount. + nrows = res.command_tuples + self.cursor._rowcount = nrows if nrows is not None else -1 + return memoryview(b"") + + def _read_row_gen(self) -> PQGen[tuple[Any, ...] | None]: + data = yield from self._read_gen() + if not data: + return None + + row = self.formatter.parse_row(data) + if row is None: + # Get the final result to finish the copy operation + yield from self._read_gen() + self._finished = True + return None + + return row + + def _end_copy_out_gen(self) -> PQGen[None]: + try: + while (yield from self._read_gen()): + pass + except e.QueryCanceled: + pass + + +class Formatter(ABC): + """ + A class which understand a copy format (text, binary). + """ + + format: pq.Format + + def __init__(self, transformer: Transformer): + self.transformer = transformer + self._write_buffer = bytearray() + self._row_mode = False # true if the user is using write_row() + + @abstractmethod + def parse_row(self, data: Buffer) -> tuple[Any, ...] | None: ... + + @abstractmethod + def write(self, buffer: Buffer | str) -> Buffer: ... + + @abstractmethod + def write_row(self, row: Sequence[Any]) -> Buffer: ... + + @abstractmethod + def end(self) -> Buffer: ... + + +class TextFormatter(Formatter): + format = TEXT + + def __init__(self, transformer: Transformer, encoding: str = "utf-8"): + super().__init__(transformer) + self._encoding = encoding + + def parse_row(self, data: Buffer) -> tuple[Any, ...] | None: + if data: + return parse_row_text(data, self.transformer) + else: + return None + + def write(self, buffer: Buffer | str) -> Buffer: + data = self._ensure_bytes(buffer) + self._signature_sent = True + return data + + def write_row(self, row: Sequence[Any]) -> Buffer: + # Note down that we are writing in row mode: it means we will have + # to take care of the end-of-copy marker too + self._row_mode = True + + format_row_text(row, self.transformer, self._write_buffer) + if len(self._write_buffer) > BUFFER_SIZE: + buffer, self._write_buffer = self._write_buffer, bytearray() + return buffer + else: + return b"" + + def end(self) -> Buffer: + buffer, self._write_buffer = self._write_buffer, bytearray() + return buffer + + def _ensure_bytes(self, data: Buffer | str) -> Buffer: + if isinstance(data, str): + return data.encode(self._encoding) + else: + # Assume, for simplicity, that the user is not passing stupid + # things to the write function. If that's the case, things + # will fail downstream. + return data + + +class BinaryFormatter(Formatter): + format = BINARY + + def __init__(self, transformer: Transformer): + super().__init__(transformer) + self._signature_sent = False + + def parse_row(self, data: Buffer) -> tuple[Any, ...] | None: + if not self._signature_sent: + if data[: len(_binary_signature)] != _binary_signature: + raise e.DataError( + "binary copy doesn't start with the expected signature" + ) + self._signature_sent = True + data = data[len(_binary_signature) :] + + elif data == _binary_trailer: + return None + + return parse_row_binary(data, self.transformer) + + def write(self, buffer: Buffer | str) -> Buffer: + data = self._ensure_bytes(buffer) + self._signature_sent = True + return data + + def write_row(self, row: Sequence[Any]) -> Buffer: + # Note down that we are writing in row mode: it means we will have + # to take care of the end-of-copy marker too + self._row_mode = True + + if not self._signature_sent: + self._write_buffer += _binary_signature + self._signature_sent = True + + format_row_binary(row, self.transformer, self._write_buffer) + if len(self._write_buffer) > BUFFER_SIZE: + buffer, self._write_buffer = self._write_buffer, bytearray() + return buffer + else: + return b"" + + def end(self) -> Buffer: + # If we have sent no data we need to send the signature + # and the trailer + if not self._signature_sent: + self._write_buffer += _binary_signature + self._write_buffer += _binary_trailer + + elif self._row_mode: + # if we have sent data already, we have sent the signature + # too (either with the first row, or we assume that in + # block mode the signature is included). + # Write the trailer only if we are sending rows (with the + # assumption that who is copying binary data is sending the + # whole format). + self._write_buffer += _binary_trailer + + buffer, self._write_buffer = self._write_buffer, bytearray() + return buffer + + def _ensure_bytes(self, data: Buffer | str) -> Buffer: + if isinstance(data, str): + raise TypeError("cannot copy str data in binary mode: use bytes instead") + else: + # Assume, for simplicity, that the user is not passing stupid + # things to the write function. If that's the case, things + # will fail downstream. + return data + + +def _format_row_text( + row: Sequence[Any], tx: Transformer, out: bytearray | None = None +) -> bytearray: + """Convert a row of objects to the data to send for copy.""" + if out is None: + out = bytearray() + + if not row: + out += b"\n" + return out + + adapted = tx.dump_sequence(row, [PY_TEXT] * len(row)) + for b in adapted: + out += _dump_re.sub(_dump_sub, b) if b is not None else rb"\N" + out += b"\t" + + out[-1:] = b"\n" + return out + + +def _format_row_binary( + row: Sequence[Any], tx: Transformer, out: bytearray | None = None +) -> bytearray: + """Convert a row of objects to the data to send for binary copy.""" + if out is None: + out = bytearray() + + out += _pack_int2(len(row)) + adapted = tx.dump_sequence(row, [PY_BINARY] * len(row)) + for b in adapted: + if b is not None: + out += _pack_int4(len(b)) + out += b + else: + out += _binary_null + + return out + + +def _parse_row_text(data: Buffer, tx: Transformer) -> tuple[Any, ...]: + if not isinstance(data, bytes): + data = bytes(data) + fields = data.split(b"\t") + fields[-1] = fields[-1][:-1] # drop \n + row = [None if f == b"\\N" else _load_re.sub(_load_sub, f) for f in fields] + return tx.load_sequence(row) + + +def _parse_row_binary(data: Buffer, tx: Transformer) -> tuple[Any, ...]: + row: list[Buffer | None] = [] + nfields = _unpack_int2(data, 0)[0] + pos = 2 + for i in range(nfields): + length = _unpack_int4(data, pos)[0] + pos += 4 + if length >= 0: + row.append(data[pos : pos + length]) + pos += length + else: + row.append(None) + + return tx.load_sequence(row) + + +_pack_int2 = struct.Struct("!h").pack +_pack_int4 = struct.Struct("!i").pack +_unpack_int2 = struct.Struct("!h").unpack_from +_unpack_int4 = struct.Struct("!i").unpack_from + +_binary_signature = ( + b"PGCOPY\n\xff\r\n\0" # Signature + b"\x00\x00\x00\x00" # flags + b"\x00\x00\x00\x00" # extra length +) +_binary_trailer = b"\xff\xff" +_binary_null = b"\xff\xff\xff\xff" + +_dump_re = re.compile(b"[\b\t\n\v\f\r\\\\]") +_dump_repl = { + b"\b": b"\\b", + b"\t": b"\\t", + b"\n": b"\\n", + b"\v": b"\\v", + b"\f": b"\\f", + b"\r": b"\\r", + b"\\": b"\\\\", +} + + +def _dump_sub(m: Match[bytes], __map: dict[bytes, bytes] = _dump_repl) -> bytes: + return __map[m.group(0)] + + +_load_re = re.compile(b"\\\\[btnvfr\\\\]") +_load_repl = {v: k for k, v in _dump_repl.items()} + + +def _load_sub(m: Match[bytes], __map: dict[bytes, bytes] = _load_repl) -> bytes: + return __map[m.group(0)] + + +# Override functions with fast versions if available +if _psycopg: + format_row_text = _psycopg.format_row_text + format_row_binary = _psycopg.format_row_binary + parse_row_text = _psycopg.parse_row_text + parse_row_binary = _psycopg.parse_row_binary + +else: + format_row_text = _format_row_text + format_row_binary = _format_row_binary + parse_row_text = _parse_row_text + parse_row_binary = _parse_row_binary diff --git a/backend/.venv/Lib/site-packages/psycopg/_cursor_base.py b/backend/.venv/Lib/site-packages/psycopg/_cursor_base.py new file mode 100644 index 0000000..e09f17a --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_cursor_base.py @@ -0,0 +1,627 @@ +""" +Psycopg BaseCursor object +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +from functools import partial +from typing import Any, Generic, Iterable, NoReturn, Sequence +from typing import TYPE_CHECKING + +from . import pq +from . import adapt +from . import errors as e +from .abc import ConnectionType, Query, Params, PQGen +from .rows import Row, RowMaker +from ._capabilities import capabilities +from ._column import Column +from .pq.misc import connection_summary +from ._queries import PostgresQuery, PostgresClientQuery +from ._preparing import Prepare +from .generators import execute, fetch, send + +if TYPE_CHECKING: + from .abc import Transformer + from .pq.abc import PGconn, PGresult + +TEXT = pq.Format.TEXT +BINARY = pq.Format.BINARY + +EMPTY_QUERY = pq.ExecStatus.EMPTY_QUERY +COMMAND_OK = pq.ExecStatus.COMMAND_OK +TUPLES_OK = pq.ExecStatus.TUPLES_OK +COPY_OUT = pq.ExecStatus.COPY_OUT +COPY_IN = pq.ExecStatus.COPY_IN +COPY_BOTH = pq.ExecStatus.COPY_BOTH +FATAL_ERROR = pq.ExecStatus.FATAL_ERROR +SINGLE_TUPLE = pq.ExecStatus.SINGLE_TUPLE +TUPLES_CHUNK = pq.ExecStatus.TUPLES_CHUNK +PIPELINE_ABORTED = pq.ExecStatus.PIPELINE_ABORTED + +ACTIVE = pq.TransactionStatus.ACTIVE + + +class BaseCursor(Generic[ConnectionType, Row]): + __slots__ = """ + _conn format _adapters arraysize _closed _results pgresult _pos + _iresult _rowcount _query _tx _last_query _row_factory _make_row + _pgconn _execmany_returning + __weakref__ + """.split() + + _tx: Transformer + _make_row: RowMaker[Row] + _pgconn: PGconn + _query_cls: type[PostgresQuery] = PostgresQuery + + def __init__(self, connection: ConnectionType): + self._conn = connection + self.format = TEXT + self._pgconn = connection.pgconn + self._adapters = adapt.AdaptersMap(connection.adapters) + self.arraysize = 1 + self._closed = False + self._last_query: Query | None = None + self._reset() + + def _reset(self, reset_query: bool = True) -> None: + self._results: list[PGresult] = [] + self.pgresult: PGresult | None = None + self._pos = 0 + self._iresult = 0 + self._rowcount = -1 + self._query: PostgresQuery | None + # None if executemany() not executing, True/False according to returning state + self._execmany_returning: bool | None = None + if reset_query: + self._query = None + + def __repr__(self) -> str: + cls = f"{self.__class__.__module__}.{self.__class__.__qualname__}" + info = connection_summary(self._pgconn) + if self._closed: + status = "closed" + elif self.pgresult: + status = pq.ExecStatus(self.pgresult.status).name + else: + status = "no result" + return f"<{cls} [{status}] {info} at 0x{id(self):x}>" + + @property + def connection(self) -> ConnectionType: + """The connection this cursor is using.""" + return self._conn + + @property + def adapters(self) -> adapt.AdaptersMap: + return self._adapters + + @property + def closed(self) -> bool: + """`True` if the cursor is closed.""" + return self._closed + + @property + def description(self) -> list[Column] | None: + """ + A list of `Column` objects describing the current resultset. + + `!None` if the current resultset didn't return tuples. + """ + res = self.pgresult + + # We return columns if we have nfields, but also if we don't but + # the query said we got tuples (mostly to handle the super useful + # query "SELECT ;" + if res and ( + res.nfields + or res.status == TUPLES_OK + or res.status == SINGLE_TUPLE + or res.status == TUPLES_CHUNK + ): + return [Column(self, i) for i in range(res.nfields)] + else: + return None + + @property + def rowcount(self) -> int: + """Number of records affected by the precedent operation.""" + return self._rowcount + + @property + def rownumber(self) -> int | None: + """Index of the next row to fetch in the current result. + + `!None` if there is no result to fetch. + """ + tuples = self.pgresult and self.pgresult.status == TUPLES_OK + return self._pos if tuples else None + + def setinputsizes(self, sizes: Sequence[Any]) -> None: + # no-op + pass + + def setoutputsize(self, size: Any, column: int | None = None) -> None: + # no-op + pass + + def nextset(self) -> bool | None: + """ + Move to the result set of the next query executed through `executemany()` + or to the next result set if `execute()` returned more than one. + + Return `!True` if a new result is available, which will be the one + methods `!fetch*()` will operate on. + """ + if self._iresult < len(self._results) - 1: + self._select_current_result(self._iresult + 1) + return True + else: + return None + + @property + def statusmessage(self) -> str | None: + """ + The command status tag from the last SQL command executed. + + `!None` if the cursor doesn't have a result available. + """ + msg = self.pgresult.command_status if self.pgresult else None + return msg.decode() if msg else None + + def _make_row_maker(self) -> RowMaker[Row]: + raise NotImplementedError + + # + # Generators for the high level operations on the cursor + # + # Like for sync/async connections, these are implemented as generators + # so that different concurrency strategies (threads,asyncio) can use their + # own way of waiting (or better, `connection.wait()`). + # + + def _execute_gen( + self, + query: Query, + params: Params | None = None, + *, + prepare: bool | None = None, + binary: bool | None = None, + ) -> PQGen[None]: + """Generator implementing `Cursor.execute()`.""" + yield from self._start_query(query) + pgq = self._convert_query(query, params) + yield from self._maybe_prepare_gen(pgq, prepare=prepare, binary=binary) + if self._conn._pipeline: + yield from self._conn._pipeline._communicate_gen() + + self._last_query = query + yield from self._conn._prepared.maintain_gen(self._conn) + + def _executemany_gen_pipeline( + self, query: Query, params_seq: Iterable[Params], returning: bool + ) -> PQGen[None]: + """ + Generator implementing `Cursor.executemany()` with pipelines available. + """ + pipeline = self._conn._pipeline + assert pipeline + + yield from self._start_query(query) + if not returning: + self._rowcount = 0 + + assert self._execmany_returning is None + self._execmany_returning = returning + + first = True + for params in params_seq: + if first: + pgq = self._convert_query(query, params) + self._query = pgq + first = False + else: + pgq.dump(params) + + yield from self._maybe_prepare_gen(pgq, prepare=True) + yield from pipeline._communicate_gen() + + self._last_query = query + + if returning: + yield from pipeline._fetch_gen(flush=True) + + yield from self._conn._prepared.maintain_gen(self._conn) + + def _executemany_gen_no_pipeline( + self, query: Query, params_seq: Iterable[Params], returning: bool + ) -> PQGen[None]: + """ + Generator implementing `Cursor.executemany()` with pipelines not available. + """ + yield from self._start_query(query) + if not returning: + self._rowcount = 0 + + assert self._execmany_returning is None + self._execmany_returning = returning + + first = True + for params in params_seq: + if first: + pgq = self._convert_query(query, params) + self._query = pgq + first = False + else: + pgq.dump(params) + + yield from self._maybe_prepare_gen(pgq, prepare=True) + + self._last_query = query + yield from self._conn._prepared.maintain_gen(self._conn) + + def _maybe_prepare_gen( + self, + pgq: PostgresQuery, + *, + prepare: bool | None = None, + binary: bool | None = None, + ) -> PQGen[None]: + # Check if the query is prepared or needs preparing + prep, name = self._get_prepared(pgq, prepare) + if prep is Prepare.NO: + # The query must be executed without preparing + self._execute_send(pgq, binary=binary) + else: + # If the query is not already prepared, prepare it. + if prep is Prepare.SHOULD: + self._send_prepare(name, pgq) + if not self._conn._pipeline: + (result,) = yield from execute(self._pgconn) + if result.status == FATAL_ERROR: + raise e.error_from_result(result, encoding=self._encoding) + # Then execute it. + self._send_query_prepared(name, pgq, binary=binary) + + # Update the prepare state of the query. + # If an operation requires to flush our prepared statements cache, + # it will be added to the maintenance commands to execute later. + key = self._conn._prepared.maybe_add_to_cache(pgq, prep, name) + + if self._conn._pipeline: + queued = None + if key is not None: + queued = (key, prep, name) + self._conn._pipeline.result_queue.append((self, queued)) + return + + # run the query + results = yield from execute(self._pgconn) + + if key is not None: + self._conn._prepared.validate(key, prep, name, results) + + self._check_results(results) + self._set_results(results) + + def _get_prepared( + self, pgq: PostgresQuery, prepare: bool | None = None + ) -> tuple[Prepare, bytes]: + return self._conn._prepared.get(pgq, prepare) + + def _stream_send_gen( + self, + query: Query, + params: Params | None = None, + *, + binary: bool | None = None, + size: int, + ) -> PQGen[None]: + """Generator to send the query for `Cursor.stream()`.""" + yield from self._start_query(query) + pgq = self._convert_query(query, params) + self._execute_send(pgq, binary=binary, force_extended=True) + if size < 1: + raise ValueError("size must be >= 1") + elif size == 1: + self._pgconn.set_single_row_mode() + else: + capabilities.has_stream_chunked(check=True) + self._pgconn.set_chunked_rows_mode(size) + self._last_query = query + yield from send(self._pgconn) + + def _stream_fetchone_gen(self, first: bool) -> PQGen[PGresult | None]: + res = yield from fetch(self._pgconn) + if res is None: + return None + + status = res.status + if status == SINGLE_TUPLE or status == TUPLES_CHUNK: + self.pgresult = res + self._tx.set_pgresult(res, set_loaders=first) + if first: + self._make_row = self._make_row_maker() + return res + + elif status == TUPLES_OK or status == COMMAND_OK: + # End of single row results + while res: + res = yield from fetch(self._pgconn) + if status != TUPLES_OK: + raise e.ProgrammingError( + "the operation in stream() didn't produce a result" + ) + return None + + else: + # Errors, unexpected values + return self._raise_for_result(res) + + def _start_query(self, query: Query | None = None) -> PQGen[None]: + """Generator to start the processing of a query. + + It is implemented as generator because it may send additional queries, + such as `begin`. + """ + if self.closed: + raise e.InterfaceError("the cursor is closed") + + self._reset() + if not self._last_query or (self._last_query is not query): + self._last_query = None + self._tx = adapt.Transformer(self) + yield from self._conn._start_query() + + def _start_copy_gen( + self, statement: Query, params: Params | None = None + ) -> PQGen[None]: + """Generator implementing sending a command for `Cursor.copy().""" + + # The connection gets in an unrecoverable state if we attempt COPY in + # pipeline mode. Forbid it explicitly. + if self._conn._pipeline: + raise e.NotSupportedError("COPY cannot be used in pipeline mode") + + yield from self._start_query() + + # Merge the params client-side + if params: + pgq = PostgresClientQuery(self._tx) + pgq.convert(statement, params) + statement = pgq.query + + query = self._convert_query(statement) + + self._execute_send(query, binary=False) + results = yield from execute(self._pgconn) + if len(results) != 1: + raise e.ProgrammingError("COPY cannot be mixed with other operations") + + self._check_copy_result(results[0]) + self._set_results(results) + + def _execute_send( + self, + query: PostgresQuery, + *, + force_extended: bool = False, + binary: bool | None = None, + ) -> None: + """ + Implement part of execute() before waiting common to sync and async. + + This is not a generator, but a normal non-blocking function. + """ + if binary is None: + fmt = self.format + else: + fmt = BINARY if binary else TEXT + + self._query = query + + if self._conn._pipeline: + # In pipeline mode always use PQsendQueryParams - see #314 + # Multiple statements in the same query are not allowed anyway. + self._conn._pipeline.command_queue.append( + partial( + self._pgconn.send_query_params, + query.query, + query.params, + param_formats=query.formats, + param_types=query.types, + result_format=fmt, + ) + ) + elif force_extended or query.params or fmt == BINARY: + self._pgconn.send_query_params( + query.query, + query.params, + param_formats=query.formats, + param_types=query.types, + result_format=fmt, + ) + else: + # If we can, let's use simple query protocol, + # as it can execute more than one statement in a single query. + self._pgconn.send_query(query.query) + + def _convert_query( + self, query: Query, params: Params | None = None + ) -> PostgresQuery: + pgq = self._query_cls(self._tx) + pgq.convert(query, params) + return pgq + + def _check_results(self, results: list[PGresult]) -> None: + """ + Verify that the results of a query are valid. + + Verify that the query returned at least one result and that they all + represent a valid result from the database. + """ + if not results: + raise e.InternalError("got no result from the query") + + for res in results: + status = res.status + if status != TUPLES_OK and status != COMMAND_OK and status != EMPTY_QUERY: + self._raise_for_result(res) + + def _raise_for_result(self, result: PGresult) -> NoReturn: + """ + Raise an appropriate error message for an unexpected database result + """ + status = result.status + if status == FATAL_ERROR: + raise e.error_from_result(result, encoding=self._encoding) + elif status == PIPELINE_ABORTED: + raise e.PipelineAborted("pipeline aborted") + elif status == COPY_IN or status == COPY_OUT or status == COPY_BOTH: + raise e.ProgrammingError( + "COPY cannot be used with this method; use copy() instead" + ) + else: + raise e.InternalError( + "unexpected result status from query:" f" {pq.ExecStatus(status).name}" + ) + + def _select_current_result(self, i: int, format: pq.Format | None = None) -> None: + """ + Select one of the results in the cursor as the active one. + """ + self._iresult = i + res = self.pgresult = self._results[i] + + # Note: the only reason to override format is to correctly set + # binary loaders on server-side cursors, because send_describe_portal + # only returns a text result. + self._tx.set_pgresult(res, format=format) + + self._pos = 0 + + if res.status == TUPLES_OK: + self._rowcount = self.pgresult.ntuples + + # COPY_OUT has never info about nrows. We need such result for the + # columns in order to return a `description`, but not overwrite the + # cursor rowcount (which was set by the Copy object). + elif res.status != COPY_OUT: + nrows = self.pgresult.command_tuples + self._rowcount = nrows if nrows is not None else -1 + + self._make_row = self._make_row_maker() + + def _set_results(self, results: list[PGresult]) -> None: + if self._execmany_returning is None: + # Received from execute() + self._results[:] = results + self._select_current_result(0) + + else: + # Received from executemany() + if self._execmany_returning: + first_batch = not self._results + self._results.extend(results) + if first_batch: + self._select_current_result(0) + else: + # In non-returning case, set rowcount to the cumulated number of + # rows of executed queries. + for res in results: + self._rowcount += res.command_tuples or 0 + + def _send_prepare(self, name: bytes, query: PostgresQuery) -> None: + if self._conn._pipeline: + self._conn._pipeline.command_queue.append( + partial( + self._pgconn.send_prepare, + name, + query.query, + param_types=query.types, + ) + ) + self._conn._pipeline.result_queue.append(None) + else: + self._pgconn.send_prepare(name, query.query, param_types=query.types) + + def _send_query_prepared( + self, name: bytes, pgq: PostgresQuery, *, binary: bool | None = None + ) -> None: + if binary is None: + fmt = self.format + else: + fmt = BINARY if binary else TEXT + + if self._conn._pipeline: + self._conn._pipeline.command_queue.append( + partial( + self._pgconn.send_query_prepared, + name, + pgq.params, + param_formats=pgq.formats, + result_format=fmt, + ) + ) + else: + self._pgconn.send_query_prepared( + name, pgq.params, param_formats=pgq.formats, result_format=fmt + ) + + def _check_result_for_fetch(self) -> None: + if self.closed: + raise e.InterfaceError("the cursor is closed") + res = self.pgresult + if not res: + raise e.ProgrammingError("no result available") + + status = res.status + if status == TUPLES_OK: + return + elif status == FATAL_ERROR: + raise e.error_from_result(res, encoding=self._encoding) + elif status == PIPELINE_ABORTED: + raise e.PipelineAborted("pipeline aborted") + else: + raise e.ProgrammingError("the last operation didn't produce a result") + + def _check_copy_result(self, result: PGresult) -> None: + """ + Check that the value returned in a copy() operation is a legit COPY. + """ + status = result.status + if status == COPY_IN or status == COPY_OUT: + return + elif status == FATAL_ERROR: + raise e.error_from_result(result, encoding=self._encoding) + else: + raise e.ProgrammingError( + "copy() should be used only with COPY ... TO STDOUT or COPY ..." + f" FROM STDIN statements, got {pq.ExecStatus(status).name}" + ) + + def _scroll(self, value: int, mode: str) -> None: + self._check_result_for_fetch() + assert self.pgresult + if mode == "relative": + newpos = self._pos + value + elif mode == "absolute": + newpos = value + else: + raise ValueError(f"bad mode: {mode}. It should be 'relative' or 'absolute'") + if not 0 <= newpos < self.pgresult.ntuples: + raise IndexError("position out of bound") + self._pos = newpos + + def _close(self) -> None: + """Non-blocking part of closing. Common to sync/async.""" + # Don't reset the query because it may be useful to investigate after + # an error. + self._reset(reset_query=False) + self._closed = True + + @property + def _encoding(self) -> str: + return self._pgconn._encoding diff --git a/backend/.venv/Lib/site-packages/psycopg/_dns.py b/backend/.venv/Lib/site-packages/psycopg/_dns.py new file mode 100644 index 0000000..9dd67f0 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_dns.py @@ -0,0 +1,247 @@ +# type: ignore # dnspython is currently optional and mypy fails if missing +""" +DNS query support +""" + +# Copyright (C) 2021 The Psycopg Team + +from __future__ import annotations + +import os +import re +import warnings +from random import randint +from typing import Any, DefaultDict, NamedTuple, Sequence, TYPE_CHECKING +from collections import defaultdict + +try: + from dns.resolver import Resolver, Cache + from dns.asyncresolver import Resolver as AsyncResolver + from dns.exception import DNSException +except ImportError: + raise ImportError( + "the module psycopg._dns requires the package 'dnspython' installed" + ) + +from . import errors as e +from . import conninfo + +if TYPE_CHECKING: + from dns.rdtypes.IN.SRV import SRV + +resolver = Resolver() +resolver.cache = Cache() + +async_resolver = AsyncResolver() +async_resolver.cache = Cache() + + +async def resolve_hostaddr_async(params: dict[str, Any]) -> dict[str, Any]: + """ + Perform async DNS lookup of the hosts and return a new params dict. + + .. deprecated:: 3.1 + The use of this function is not necessary anymore, because + `psycopg.AsyncConnection.connect()` performs non-blocking name + resolution automatically. + """ + warnings.warn( + "from psycopg 3.1, resolve_hostaddr_async() is not needed anymore", + DeprecationWarning, + ) + hosts: list[str] = [] + hostaddrs: list[str] = [] + ports: list[str] = [] + + for attempt in await conninfo.conninfo_attempts_async(params): + if attempt.get("host") is not None: + hosts.append(attempt["host"]) + if attempt.get("hostaddr") is not None: + hostaddrs.append(attempt["hostaddr"]) + if attempt.get("port") is not None: + ports.append(str(attempt["port"])) + + out = params.copy() + shosts = ",".join(hosts) + if shosts: + out["host"] = shosts + shostaddrs = ",".join(hostaddrs) + if shostaddrs: + out["hostaddr"] = shostaddrs + sports = ",".join(ports) + if ports: + out["port"] = sports + + return out + + +def resolve_srv(params: dict[str, Any]) -> dict[str, Any]: + """Apply SRV DNS lookup as defined in :RFC:`2782`.""" + return Rfc2782Resolver().resolve(params) + + +async def resolve_srv_async(params: dict[str, Any]) -> dict[str, Any]: + """Async equivalent of `resolve_srv()`.""" + return await Rfc2782Resolver().resolve_async(params) + + +class HostPort(NamedTuple): + host: str + port: str + totry: bool = False + target: str | None = None + + +class Rfc2782Resolver: + """Implement SRV RR Resolution as per RFC 2782 + + The class is organised to minimise code duplication between the sync and + the async paths. + """ + + re_srv_rr = re.compile(r"^(?P_[^\.]+)\.(?P_[^\.]+)\.(?P.+)") + + def resolve(self, params: dict[str, Any]) -> dict[str, Any]: + """Update the parameters host and port after SRV lookup.""" + attempts = self._get_attempts(params) + if not attempts: + return params + + hps = [] + for hp in attempts: + if hp.totry: + hps.extend(self._resolve_srv(hp)) + else: + hps.append(hp) + + return self._return_params(params, hps) + + async def resolve_async(self, params: dict[str, Any]) -> dict[str, Any]: + """Update the parameters host and port after SRV lookup.""" + attempts = self._get_attempts(params) + if not attempts: + return params + + hps = [] + for hp in attempts: + if hp.totry: + hps.extend(await self._resolve_srv_async(hp)) + else: + hps.append(hp) + + return self._return_params(params, hps) + + def _get_attempts(self, params: dict[str, Any]) -> list[HostPort]: + """ + Return the list of host, and for each host if SRV lookup must be tried. + + Return an empty list if no lookup is requested. + """ + # If hostaddr is defined don't do any resolution. + if params.get("hostaddr", os.environ.get("PGHOSTADDR", "")): + return [] + + host_arg: str = params.get("host", os.environ.get("PGHOST", "")) + hosts_in = host_arg.split(",") + port_arg: str = str(params.get("port", os.environ.get("PGPORT", ""))) + ports_in = port_arg.split(",") + + if len(ports_in) == 1: + # If only one port is specified, it applies to all the hosts. + ports_in *= len(hosts_in) + if len(ports_in) != len(hosts_in): + # ProgrammingError would have been more appropriate, but this is + # what the raise if the libpq fails connect in the same case. + raise e.OperationalError( + f"cannot match {len(hosts_in)} hosts with {len(ports_in)} port numbers" + ) + + out = [] + srv_found = False + for host, port in zip(hosts_in, ports_in): + m = self.re_srv_rr.match(host) + if m or port.lower() == "srv": + srv_found = True + target = m.group("target") if m else None + hp = HostPort(host=host, port=port, totry=True, target=target) + else: + hp = HostPort(host=host, port=port) + out.append(hp) + + return out if srv_found else [] + + def _resolve_srv(self, hp: HostPort) -> list[HostPort]: + try: + ans = resolver.resolve(hp.host, "SRV") + except DNSException: + ans = () + return self._get_solved_entries(hp, ans) + + async def _resolve_srv_async(self, hp: HostPort) -> list[HostPort]: + try: + ans = await async_resolver.resolve(hp.host, "SRV") + except DNSException: + ans = () + return self._get_solved_entries(hp, ans) + + def _get_solved_entries( + self, hp: HostPort, entries: Sequence[SRV] + ) -> list[HostPort]: + if not entries: + # No SRV entry found. Delegate the libpq a QNAME=target lookup + if hp.target and hp.port.lower() != "srv": + return [HostPort(host=hp.target, port=hp.port)] + else: + return [] + + # If there is precisely one SRV RR, and its Target is "." (the root + # domain), abort. + if len(entries) == 1 and str(entries[0].target) == ".": + return [] + + return [ + HostPort(host=str(entry.target).rstrip("."), port=str(entry.port)) + for entry in self.sort_rfc2782(entries) + ] + + def _return_params( + self, params: dict[str, Any], hps: list[HostPort] + ) -> dict[str, Any]: + if not hps: + # Nothing found, we ended up with an empty list + raise e.OperationalError("no host found after SRV RR lookup") + + out = params.copy() + out["host"] = ",".join(hp.host for hp in hps) + out["port"] = ",".join(str(hp.port) for hp in hps) + return out + + def sort_rfc2782(self, ans: Sequence[SRV]) -> list[SRV]: + """ + Implement the priority/weight ordering defined in RFC 2782. + """ + # Divide the entries by priority: + priorities: DefaultDict[int, list[SRV]] = defaultdict(list) + out: list[SRV] = [] + for entry in ans: + priorities[entry.priority].append(entry) + + for pri, entries in sorted(priorities.items()): + if len(entries) == 1: + out.append(entries[0]) + continue + + entries.sort(key=lambda ent: ent.weight) + total_weight = sum(ent.weight for ent in entries) + while entries: + r = randint(0, total_weight) + csum = 0 + for i, ent in enumerate(entries): + csum += ent.weight + if csum >= r: + break + out.append(ent) + total_weight -= ent.weight + del entries[i] + + return out diff --git a/backend/.venv/Lib/site-packages/psycopg/_encodings.py b/backend/.venv/Lib/site-packages/psycopg/_encodings.py new file mode 100644 index 0000000..42da2c5 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_encodings.py @@ -0,0 +1,154 @@ +""" +Mappings between PostgreSQL and Python encodings. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import re +import string +import codecs +from typing import Any, TYPE_CHECKING + +from .pq._enums import ConnStatus +from .errors import NotSupportedError +from ._compat import cache + +if TYPE_CHECKING: + from ._connection_base import BaseConnection + +OK = ConnStatus.OK + + +_py_codecs = { + "BIG5": "big5", + "EUC_CN": "gb2312", + "EUC_JIS_2004": "euc_jis_2004", + "EUC_JP": "euc_jp", + "EUC_KR": "euc_kr", + # "EUC_TW": not available in Python + "GB18030": "gb18030", + "GBK": "gbk", + "ISO_8859_5": "iso8859-5", + "ISO_8859_6": "iso8859-6", + "ISO_8859_7": "iso8859-7", + "ISO_8859_8": "iso8859-8", + "JOHAB": "johab", + "KOI8R": "koi8-r", + "KOI8U": "koi8-u", + "LATIN1": "iso8859-1", + "LATIN10": "iso8859-16", + "LATIN2": "iso8859-2", + "LATIN3": "iso8859-3", + "LATIN4": "iso8859-4", + "LATIN5": "iso8859-9", + "LATIN6": "iso8859-10", + "LATIN7": "iso8859-13", + "LATIN8": "iso8859-14", + "LATIN9": "iso8859-15", + # "MULE_INTERNAL": not available in Python + "SHIFT_JIS_2004": "shift_jis_2004", + "SJIS": "shift_jis", + # this actually means no encoding, see PostgreSQL docs + # it is special-cased by the text loader. + "SQL_ASCII": "ascii", + "UHC": "cp949", + "UTF8": "utf-8", + "WIN1250": "cp1250", + "WIN1251": "cp1251", + "WIN1252": "cp1252", + "WIN1253": "cp1253", + "WIN1254": "cp1254", + "WIN1255": "cp1255", + "WIN1256": "cp1256", + "WIN1257": "cp1257", + "WIN1258": "cp1258", + "WIN866": "cp866", + "WIN874": "cp874", +} + +py_codecs: dict[bytes, str] = {} +py_codecs.update((k.encode(), v) for k, v in _py_codecs.items()) + +# Add an alias without underscore, for lenient lookups +py_codecs.update( + (k.replace("_", "").encode(), v) for k, v in _py_codecs.items() if "_" in k +) + +pg_codecs = {v: k.encode() for k, v in _py_codecs.items()} + + +def conn_encoding(conn: BaseConnection[Any] | None) -> str: + """ + Return the Python encoding name of a psycopg connection. + + Default to utf8 if the connection has no encoding info. + """ + return conn.pgconn._encoding if conn else "utf-8" + + +def conninfo_encoding(conninfo: str) -> str: + """ + Return the Python encoding name passed in a conninfo string. Default to utf8. + + Because the input is likely to come from the user and not normalised by the + server, be somewhat lenient (non-case-sensitive lookup, ignore noise chars). + """ + from .conninfo import conninfo_to_dict + + params = conninfo_to_dict(conninfo) + pgenc = params.get("client_encoding") + if pgenc: + try: + return pg2pyenc(str(pgenc).encode()) + except NotSupportedError: + pass + + return "utf-8" + + +@cache +def py2pgenc(name: str) -> bytes: + """Convert a Python encoding name to PostgreSQL encoding name. + + Raise LookupError if the Python encoding is unknown. + """ + return pg_codecs[codecs.lookup(name).name] + + +@cache +def pg2pyenc(name: bytes) -> str: + """Convert a PostgreSQL encoding name to Python encoding name. + + Raise NotSupportedError if the PostgreSQL encoding is not supported by + Python. + """ + try: + return py_codecs[name.replace(b"-", b"").replace(b"_", b"").upper()] + except KeyError: + sname = name.decode("utf8", "replace") + raise NotSupportedError(f"codec not available in Python: {sname!r}") + + +def _as_python_identifier(s: str, prefix: str = "f") -> str: + """ + Reduce a string to a valid Python identifier. + + Replace all non-valid chars with '_' and prefix the value with `!prefix` if + the first letter is an '_'. + """ + if not s.isidentifier(): + if s[0] in "1234567890": + s = prefix + s + if not s.isidentifier(): + s = _re_clean.sub("_", s) + # namedtuple fields cannot start with underscore. So... + if s[0] == "_": + s = prefix + s + return s + + +_re_clean = re.compile( + f"[^{string.ascii_lowercase}{string.ascii_uppercase}{string.digits}_]" +) diff --git a/backend/.venv/Lib/site-packages/psycopg/_enums.py b/backend/.venv/Lib/site-packages/psycopg/_enums.py new file mode 100644 index 0000000..1975650 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_enums.py @@ -0,0 +1,80 @@ +""" +Enum values for psycopg + +These values are defined by us and are not necessarily dependent on +libpq-defined enums. +""" + +# Copyright (C) 2020 The Psycopg Team + +from enum import Enum, IntEnum +from selectors import EVENT_READ, EVENT_WRITE + +from . import pq + + +class Wait(IntEnum): + R = EVENT_READ + W = EVENT_WRITE + RW = EVENT_READ | EVENT_WRITE + + +class Ready(IntEnum): + NONE = 0 + R = EVENT_READ + W = EVENT_WRITE + RW = EVENT_READ | EVENT_WRITE + + +class PyFormat(str, Enum): + """ + Enum representing the format wanted for a query argument. + + The value `AUTO` allows psycopg to choose the best format for a certain + parameter. + """ + + __module__ = "psycopg.adapt" + + AUTO = "s" + """Automatically chosen (``%s`` placeholder).""" + TEXT = "t" + """Text parameter (``%t`` placeholder).""" + BINARY = "b" + """Binary parameter (``%b`` placeholder).""" + + @classmethod + def from_pq(cls, fmt: pq.Format) -> "PyFormat": + return _pg2py[fmt] + + @classmethod + def as_pq(cls, fmt: "PyFormat") -> pq.Format: + return _py2pg[fmt] + + +class IsolationLevel(IntEnum): + """ + Enum representing the isolation level for a transaction. + """ + + __module__ = "psycopg" + + READ_UNCOMMITTED = 1 + """:sql:`READ UNCOMMITTED` isolation level.""" + READ_COMMITTED = 2 + """:sql:`READ COMMITTED` isolation level.""" + REPEATABLE_READ = 3 + """:sql:`REPEATABLE READ` isolation level.""" + SERIALIZABLE = 4 + """:sql:`SERIALIZABLE` isolation level.""" + + +_py2pg = { + PyFormat.TEXT: pq.Format.TEXT, + PyFormat.BINARY: pq.Format.BINARY, +} + +_pg2py = { + pq.Format.TEXT: PyFormat.TEXT, + pq.Format.BINARY: PyFormat.BINARY, +} diff --git a/backend/.venv/Lib/site-packages/psycopg/_oids.py b/backend/.venv/Lib/site-packages/psycopg/_oids.py new file mode 100644 index 0000000..350338b --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_oids.py @@ -0,0 +1,97 @@ +""" +PostgreSQL known type OIDs + +This is an internal module. Types are publicly exposed by +`psycopg.postgres.types`. This module is only used to know the OIDs at import +time and avoid circular import problems. +""" + +# Copyright (C) 2020 The Psycopg Team + +# A couple of special cases used a bit everywhere. +INVALID_OID = 0 +TEXT_ARRAY_OID = 1009 + +# Use tools/update_oids.py to update this data. +# autogenerated: start + +# Generated from PostgreSQL 17.0 + +ACLITEM_OID = 1033 +BIT_OID = 1560 +BOOL_OID = 16 +BOX_OID = 603 +BPCHAR_OID = 1042 +BYTEA_OID = 17 +CHAR_OID = 18 +CID_OID = 29 +CIDR_OID = 650 +CIRCLE_OID = 718 +DATE_OID = 1082 +DATEMULTIRANGE_OID = 4535 +DATERANGE_OID = 3912 +FLOAT4_OID = 700 +FLOAT8_OID = 701 +GTSVECTOR_OID = 3642 +INET_OID = 869 +INT2_OID = 21 +INT2VECTOR_OID = 22 +INT4_OID = 23 +INT4MULTIRANGE_OID = 4451 +INT4RANGE_OID = 3904 +INT8_OID = 20 +INT8MULTIRANGE_OID = 4536 +INT8RANGE_OID = 3926 +INTERVAL_OID = 1186 +JSON_OID = 114 +JSONB_OID = 3802 +JSONPATH_OID = 4072 +LINE_OID = 628 +LSEG_OID = 601 +MACADDR_OID = 829 +MACADDR8_OID = 774 +MONEY_OID = 790 +NAME_OID = 19 +NUMERIC_OID = 1700 +NUMMULTIRANGE_OID = 4532 +NUMRANGE_OID = 3906 +OID_OID = 26 +OIDVECTOR_OID = 30 +PATH_OID = 602 +PG_LSN_OID = 3220 +POINT_OID = 600 +POLYGON_OID = 604 +RECORD_OID = 2249 +REFCURSOR_OID = 1790 +REGCLASS_OID = 2205 +REGCOLLATION_OID = 4191 +REGCONFIG_OID = 3734 +REGDICTIONARY_OID = 3769 +REGNAMESPACE_OID = 4089 +REGOPER_OID = 2203 +REGOPERATOR_OID = 2204 +REGPROC_OID = 24 +REGPROCEDURE_OID = 2202 +REGROLE_OID = 4096 +REGTYPE_OID = 2206 +TEXT_OID = 25 +TID_OID = 27 +TIME_OID = 1083 +TIMESTAMP_OID = 1114 +TIMESTAMPTZ_OID = 1184 +TIMETZ_OID = 1266 +TSMULTIRANGE_OID = 4533 +TSQUERY_OID = 3615 +TSRANGE_OID = 3908 +TSTZMULTIRANGE_OID = 4534 +TSTZRANGE_OID = 3910 +TSVECTOR_OID = 3614 +TXID_SNAPSHOT_OID = 2970 +UUID_OID = 2950 +VARBIT_OID = 1562 +VARCHAR_OID = 1043 +XID_OID = 28 +XID8_OID = 5069 +XML_OID = 142 + +# autogenerated: end diff --git a/backend/.venv/Lib/site-packages/psycopg/_pipeline.py b/backend/.venv/Lib/site-packages/psycopg/_pipeline.py new file mode 100644 index 0000000..6ad3b30 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_pipeline.py @@ -0,0 +1,268 @@ +""" +commands pipeline management +""" + +# Copyright (C) 2021 The Psycopg Team + +from __future__ import annotations + +import logging +from types import TracebackType +from typing import Any, TYPE_CHECKING + +from . import pq +from . import errors as e +from .abc import PipelineCommand, PQGen +from ._compat import Deque, Self, TypeAlias +from .pq.misc import connection_summary +from .generators import pipeline_communicate, fetch_many, send +from ._capabilities import capabilities + +if TYPE_CHECKING: + from .pq.abc import PGresult + from .connection import Connection + from ._preparing import Key, Prepare # noqa: F401 + from ._cursor_base import BaseCursor # noqa: F401 + from ._connection_base import BaseConnection + from .connection_async import AsyncConnection + + +PendingResult: TypeAlias = ( + "tuple[BaseCursor[Any, Any], tuple[Key, Prepare, bytes] | None] | None" +) + +FATAL_ERROR = pq.ExecStatus.FATAL_ERROR +PIPELINE_ABORTED = pq.ExecStatus.PIPELINE_ABORTED +BAD = pq.ConnStatus.BAD + +ACTIVE = pq.TransactionStatus.ACTIVE + +logger = logging.getLogger("psycopg") + + +class BasePipeline: + command_queue: Deque[PipelineCommand] + result_queue: Deque[PendingResult] + + def __init__(self, conn: BaseConnection[Any]) -> None: + self._conn = conn + self.pgconn = conn.pgconn + self.command_queue = Deque[PipelineCommand]() + self.result_queue = Deque[PendingResult]() + self.level = 0 + + def __repr__(self) -> str: + cls = f"{self.__class__.__module__}.{self.__class__.__qualname__}" + info = connection_summary(self._conn.pgconn) + return f"<{cls} {info} at 0x{id(self):x}>" + + @property + def status(self) -> pq.PipelineStatus: + return pq.PipelineStatus(self.pgconn.pipeline_status) + + @classmethod + def is_supported(cls) -> bool: + """Return `!True` if the psycopg libpq wrapper supports pipeline mode.""" + return capabilities.has_pipeline() + + def _enter_gen(self) -> PQGen[None]: + capabilities.has_pipeline(check=True) + if self.level == 0: + self.pgconn.enter_pipeline_mode() + elif self.command_queue or self.pgconn.transaction_status == ACTIVE: + # Nested pipeline case. + # Transaction might be ACTIVE when the pipeline uses an "implicit + # transaction", typically in autocommit mode. But when entering a + # Psycopg transaction(), we expect the IDLE state. By sync()-ing, + # we make sure all previous commands are completed and the + # transaction gets back to IDLE. + yield from self._sync_gen() + self.level += 1 + + def _exit(self, exc: BaseException | None) -> None: + self.level -= 1 + if self.level == 0 and self.pgconn.status != BAD: + try: + self.pgconn.exit_pipeline_mode() + except e.OperationalError as exc2: + # Notice that this error might be pretty irrecoverable. It + # happens on COPY, for instance: even if sync succeeds, exiting + # fails with "cannot exit pipeline mode with uncollected results" + if exc: + logger.warning("error ignored exiting %r: %s", self, exc2) + else: + raise exc2.with_traceback(None) + + def _sync_gen(self) -> PQGen[None]: + self._enqueue_sync() + yield from self._communicate_gen() + yield from self._fetch_gen(flush=False) + + def _exit_gen(self) -> PQGen[None]: + """ + Exit current pipeline by sending a Sync and fetch back all remaining results. + """ + try: + self._enqueue_sync() + yield from self._communicate_gen() + finally: + yield from self._fetch_gen(flush=True) + + def _communicate_gen(self) -> PQGen[None]: + """Communicate with pipeline to send commands and possibly fetch + results, which are then processed. + """ + fetched = yield from pipeline_communicate(self.pgconn, self.command_queue) + exception = None + for results in fetched: + queued = self.result_queue.popleft() + try: + self._process_results(queued, results) + except e.Error as exc: + if exception is None: + exception = exc + if exception is not None: + raise exception + + def _fetch_gen(self, *, flush: bool) -> PQGen[None]: + """Fetch available results from the connection and process them with + pipeline queued items. + + If 'flush' is True, a PQsendFlushRequest() is issued in order to make + sure results can be fetched. Otherwise, the caller may emit a + PQpipelineSync() call to ensure the output buffer gets flushed before + fetching. + """ + if not self.result_queue: + return + + if flush: + self.pgconn.send_flush_request() + yield from send(self.pgconn) + + exception = None + while self.result_queue: + results = yield from fetch_many(self.pgconn) + if not results: + # No more results to fetch, but there may still be pending + # commands. + break + queued = self.result_queue.popleft() + try: + self._process_results(queued, results) + except e.Error as exc: + if exception is None: + exception = exc + if exception is not None: + raise exception + + def _process_results(self, queued: PendingResult, results: list[PGresult]) -> None: + """Process a results set fetched from the current pipeline. + + This matches 'results' with its respective element in the pipeline + queue. For commands (None value in the pipeline queue), results are + checked directly. For prepare statement creation requests, update the + cache. Otherwise, results are attached to their respective cursor. + """ + if queued is None: + (result,) = results + if result.status == FATAL_ERROR: + raise e.error_from_result(result, encoding=self.pgconn._encoding) + elif result.status == PIPELINE_ABORTED: + raise e.PipelineAborted("pipeline aborted") + else: + cursor, prepinfo = queued + if prepinfo: + key, prep, name = prepinfo + # Update the prepare state of the query. + cursor._conn._prepared.validate(key, prep, name, results) + cursor._check_results(results) + cursor._set_results(results) + + def _enqueue_sync(self) -> None: + """Enqueue a PQpipelineSync() command.""" + self.command_queue.append(self.pgconn.pipeline_sync) + self.result_queue.append(None) + + +class Pipeline(BasePipeline): + """Handler for connection in pipeline mode.""" + + __module__ = "psycopg" + _conn: Connection[Any] + + def __init__(self, conn: Connection[Any]) -> None: + super().__init__(conn) + + def sync(self) -> None: + """Sync the pipeline, send any pending command and receive and process + all available results. + """ + try: + with self._conn.lock: + self._conn.wait(self._sync_gen()) + except e._NO_TRACEBACK as ex: + raise ex.with_traceback(None) + + def __enter__(self) -> Self: + with self._conn.lock: + self._conn.wait(self._enter_gen()) + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + try: + with self._conn.lock: + self._conn.wait(self._exit_gen()) + except Exception as exc2: + # Don't clobber an exception raised in the block with this one + if exc_val: + logger.warning("error ignored terminating %r: %s", self, exc2) + else: + raise exc2.with_traceback(None) + finally: + self._exit(exc_val) + + +class AsyncPipeline(BasePipeline): + """Handler for async connection in pipeline mode.""" + + __module__ = "psycopg" + _conn: AsyncConnection[Any] + + def __init__(self, conn: AsyncConnection[Any]) -> None: + super().__init__(conn) + + async def sync(self) -> None: + try: + async with self._conn.lock: + await self._conn.wait(self._sync_gen()) + except e._NO_TRACEBACK as ex: + raise ex.with_traceback(None) + + async def __aenter__(self) -> Self: + async with self._conn.lock: + await self._conn.wait(self._enter_gen()) + return self + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + try: + async with self._conn.lock: + await self._conn.wait(self._exit_gen()) + except Exception as exc2: + # Don't clobber an exception raised in the block with this one + if exc_val: + logger.warning("error ignored terminating %r: %s", self, exc2) + else: + raise exc2.with_traceback(None) + finally: + self._exit(exc_val) diff --git a/backend/.venv/Lib/site-packages/psycopg/_preparing.py b/backend/.venv/Lib/site-packages/psycopg/_preparing.py new file mode 100644 index 0000000..c48c86c --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_preparing.py @@ -0,0 +1,201 @@ +""" +Support for prepared statements +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +from enum import IntEnum, auto +from typing import Any, Sequence, TYPE_CHECKING +from collections import OrderedDict + +from . import pq +from .abc import PQGen +from ._compat import Deque, TypeAlias +from ._queries import PostgresQuery + +if TYPE_CHECKING: + from .pq.abc import PGresult + from ._connection_base import BaseConnection + +Key: TypeAlias = "tuple[bytes, tuple[int, ...]]" + +COMMAND_OK = pq.ExecStatus.COMMAND_OK +TUPLES_OK = pq.ExecStatus.TUPLES_OK + + +class Prepare(IntEnum): + NO = auto() + YES = auto() + SHOULD = auto() + + +class PrepareManager: + # Number of times a query is executed before it is prepared. + prepare_threshold: int | None = 5 + + # Maximum number of prepared statements on the connection. + prepared_max: int = 100 + + def __init__(self) -> None: + # Map (query, types) to the number of times the query was seen. + self._counts: OrderedDict[Key, int] = OrderedDict() + + # Map (query, types) to the name of the statement if prepared. + self._names: OrderedDict[Key, bytes] = OrderedDict() + + # Counter to generate prepared statements names + self._prepared_idx = 0 + + self._to_flush = Deque["bytes | None"]() + + @staticmethod + def key(query: PostgresQuery) -> Key: + return (query.query, query.types) + + def get( + self, query: PostgresQuery, prepare: bool | None = None + ) -> tuple[Prepare, bytes]: + """ + Check if a query is prepared, tell back whether to prepare it. + """ + if prepare is False or self.prepare_threshold is None: + # The user doesn't want this query to be prepared + return Prepare.NO, b"" + + key = self.key(query) + name = self._names.get(key) + if name: + # The query was already prepared in this session + return Prepare.YES, name + + count = self._counts.get(key, 0) + if count >= self.prepare_threshold or prepare: + # The query has been executed enough times and needs to be prepared + name = f"_pg3_{self._prepared_idx}".encode() + self._prepared_idx += 1 + return Prepare.SHOULD, name + else: + # The query is not to be prepared yet + return Prepare.NO, b"" + + def _should_discard(self, prep: Prepare, results: Sequence[PGresult]) -> bool: + """Check if we need to discard our entire state: it should happen on + rollback or on dropping objects, because the same object may get + recreated and postgres would fail internal lookups. + """ + if self._names or prep == Prepare.SHOULD: + for result in results: + if result.status != COMMAND_OK: + continue + cmdstat = result.command_status + if cmdstat and (cmdstat.startswith(b"DROP ") or cmdstat == b"ROLLBACK"): + return self.clear() + return False + + @staticmethod + def _check_results(results: Sequence[PGresult]) -> bool: + """Return False if 'results' are invalid for prepared statement cache.""" + if len(results) != 1: + # We cannot prepare a multiple statement + return False + + status = results[0].status + if COMMAND_OK != status != TUPLES_OK: + # We don't prepare failed queries or other weird results + return False + + return True + + def _rotate(self) -> None: + """Evict an old value from the cache. + + If it was prepared, deallocate it. Do it only once: if the cache was + resized, deallocate gradually. + """ + if len(self._counts) > self.prepared_max: + self._counts.popitem(last=False) + + if len(self._names) > self.prepared_max: + name = self._names.popitem(last=False)[1] + self._to_flush.append(name) + + def maybe_add_to_cache( + self, query: PostgresQuery, prep: Prepare, name: bytes + ) -> Key | None: + """Handle 'query' for possible addition to the cache. + + If a new entry has been added, return its key. Return None otherwise + (meaning the query is already in cache or cache is not enabled). + """ + # don't do anything if prepared statements are disabled + if self.prepare_threshold is None: + return None + + key = self.key(query) + if key in self._counts: + if prep is Prepare.SHOULD: + del self._counts[key] + self._names[key] = name + else: + self._counts[key] += 1 + self._counts.move_to_end(key) + return None + + elif key in self._names: + self._names.move_to_end(key) + return None + + else: + if prep is Prepare.SHOULD: + self._names[key] = name + else: + self._counts[key] = 1 + return key + + def validate( + self, + key: Key, + prep: Prepare, + name: bytes, + results: Sequence[PGresult], + ) -> None: + """Validate cached entry with 'key' by checking query 'results'. + + Possibly record a command to perform maintenance on database side. + """ + if self._should_discard(prep, results): + return + + if not self._check_results(results): + self._names.pop(key, None) + self._counts.pop(key, None) + else: + self._rotate() + + def clear(self) -> bool: + """Clear the cache of the maintenance commands. + + Clear the internal state and prepare a command to clear the state of + the server. + """ + self._counts.clear() + if self._names: + self._names.clear() + self._to_flush.clear() + self._to_flush.append(None) + return True + else: + return False + + def maintain_gen(self, conn: BaseConnection[Any]) -> PQGen[None]: + """ + Generator to send the commands to perform periodic maintenance + + Deallocate unneeded command in the server, or flush the prepared + statements server state entirely if necessary. + """ + while self._to_flush: + name = self._to_flush.popleft() + yield from conn._deallocate(name) diff --git a/backend/.venv/Lib/site-packages/psycopg/_py_transformer.py b/backend/.venv/Lib/site-packages/psycopg/_py_transformer.py new file mode 100644 index 0000000..5300894 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_py_transformer.py @@ -0,0 +1,361 @@ +""" +Helper object to transform values between Python and PostgreSQL + +Python implementation of the object. Use the `_transformer module to import +the right implementation (Python or C). The public place where the object +is exported is `psycopg.adapt` (which we may not use to avoid circular +dependencies problems). +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +from typing import Any, Sequence, DefaultDict, TYPE_CHECKING +from collections import defaultdict + +from . import pq +from . import abc +from . import errors as e +from .abc import Buffer, LoadFunc, AdaptContext, PyFormat, NoneType +from .rows import Row, RowMaker +from ._oids import INVALID_OID, TEXT_OID +from ._compat import TypeAlias +from ._encodings import conn_encoding + +if TYPE_CHECKING: + from .abc import DumperKey # noqa: F401 + from .adapt import AdaptersMap + from .pq.abc import PGresult + from ._connection_base import BaseConnection + +DumperCache: TypeAlias = "dict[DumperKey, abc.Dumper]" +OidDumperCache: TypeAlias = "dict[int, abc.Dumper]" +LoaderCache: TypeAlias = "dict[int, abc.Loader]" + +TEXT = pq.Format.TEXT +PY_TEXT = PyFormat.TEXT + + +class Transformer(AdaptContext): + """ + An object that can adapt efficiently between Python and PostgreSQL. + + The life cycle of the object is the query, so it is assumed that attributes + such as the server version or the connection encoding will not change. The + object have its state so adapting several values of the same type can be + optimised. + + """ + + __module__ = "psycopg.adapt" + + __slots__ = """ + types formats + _conn _adapters _pgresult _dumpers _loaders _encoding _none_oid + _oid_dumpers _oid_types _row_dumpers _row_loaders + """.split() + + types: tuple[int, ...] | None + formats: list[pq.Format] | None + + _adapters: AdaptersMap + _pgresult: PGresult | None + _none_oid: int + + def __init__(self, context: AdaptContext | None = None): + self._pgresult = self.types = self.formats = None + + # WARNING: don't store context, or you'll create a loop with the Cursor + if context: + self._adapters = context.adapters + self._conn = context.connection + else: + from . import postgres + + self._adapters = postgres.adapters + self._conn = None + + # mapping fmt, class -> Dumper instance + self._dumpers: DefaultDict[PyFormat, DumperCache] + self._dumpers = defaultdict(dict) + + # mapping fmt, oid -> Dumper instance + # Not often used, so create it only if needed. + self._oid_dumpers: tuple[OidDumperCache, OidDumperCache] | None + self._oid_dumpers = None + + # mapping fmt, oid -> Loader instance + self._loaders: tuple[LoaderCache, LoaderCache] = ({}, {}) + + self._row_dumpers: list[abc.Dumper] | None = None + + # sequence of load functions from value to python + # the length of the result columns + self._row_loaders: list[LoadFunc] = [] + + # mapping oid -> type sql representation + self._oid_types: dict[int, bytes] = {} + + self._encoding = "" + + @classmethod + def from_context(cls, context: AdaptContext | None) -> Transformer: + """ + Return a Transformer from an AdaptContext. + + If the context is a Transformer instance, just return it. + """ + if isinstance(context, Transformer): + return context + else: + return cls(context) + + @property + def connection(self) -> BaseConnection[Any] | None: + return self._conn + + @property + def encoding(self) -> str: + if not self._encoding: + self._encoding = conn_encoding(self.connection) + return self._encoding + + @property + def adapters(self) -> AdaptersMap: + return self._adapters + + @property + def pgresult(self) -> PGresult | None: + return self._pgresult + + def set_pgresult( + self, + result: PGresult | None, + *, + set_loaders: bool = True, + format: pq.Format | None = None, + ) -> None: + self._pgresult = result + + if not result: + self._nfields = self._ntuples = 0 + if set_loaders: + self._row_loaders = [] + return + + self._ntuples = result.ntuples + nf = self._nfields = result.nfields + + if not set_loaders: + return + + if not nf: + self._row_loaders = [] + return + + fmt: pq.Format + fmt = result.fformat(0) if format is None else format # type: ignore + self._row_loaders = [ + self.get_loader(result.ftype(i), fmt).load for i in range(nf) + ] + + def set_dumper_types(self, types: Sequence[int], format: pq.Format) -> None: + self._row_dumpers = [self.get_dumper_by_oid(oid, format) for oid in types] + self.types = tuple(types) + self.formats = [format] * len(types) + + def set_loader_types(self, types: Sequence[int], format: pq.Format) -> None: + self._row_loaders = [self.get_loader(oid, format).load for oid in types] + + def dump_sequence( + self, params: Sequence[Any], formats: Sequence[PyFormat] + ) -> Sequence[Buffer | None]: + nparams = len(params) + out: list[Buffer | None] = [None] * nparams + + # If we have dumpers, it means set_dumper_types had been called, in + # which case self.types and self.formats are set to sequences of the + # right size. + if self._row_dumpers: + for i in range(nparams): + param = params[i] + if param is not None: + out[i] = self._row_dumpers[i].dump(param) + return out + + types = [self._get_none_oid()] * nparams + pqformats = [TEXT] * nparams + + for i in range(nparams): + param = params[i] + if param is None: + continue + dumper = self.get_dumper(param, formats[i]) + out[i] = dumper.dump(param) + types[i] = dumper.oid + pqformats[i] = dumper.format + + self.types = tuple(types) + self.formats = pqformats + + return out + + def as_literal(self, obj: Any) -> bytes: + dumper = self.get_dumper(obj, PY_TEXT) + rv = dumper.quote(obj) + # If the result is quoted, and the oid not unknown or text, + # add an explicit type cast. + # Check the last char because the first one might be 'E'. + oid = dumper.oid + if oid and rv and rv[-1] == b"'"[0] and oid != TEXT_OID: + try: + type_sql = self._oid_types[oid] + except KeyError: + ti = self.adapters.types.get(oid) + if ti: + if oid < 8192: + # builtin: prefer "timestamptz" to "timestamp with time zone" + type_sql = ti.name.encode(self.encoding) + else: + type_sql = ti.regtype.encode(self.encoding) + if oid == ti.array_oid: + type_sql += b"[]" + else: + type_sql = b"" + self._oid_types[oid] = type_sql + + if type_sql: + rv = b"%s::%s" % (rv, type_sql) + + if not isinstance(rv, bytes): + rv = bytes(rv) + return rv + + def get_dumper(self, obj: Any, format: PyFormat) -> abc.Dumper: + """ + Return a Dumper instance to dump `!obj`. + """ + # Normally, the type of the object dictates how to dump it + key = type(obj) + + # Reuse an existing Dumper class for objects of the same type + cache = self._dumpers[format] + try: + dumper = cache[key] + except KeyError: + # If it's the first time we see this type, look for a dumper + # configured for it. + try: + dcls = self.adapters.get_dumper(key, format) + except e.ProgrammingError as ex: + raise ex from None + else: + cache[key] = dumper = dcls(key, self) + + # Check if the dumper requires an upgrade to handle this specific value + key1 = dumper.get_key(obj, format) + if key1 is key: + return dumper + + # If it does, ask the dumper to create its own upgraded version + try: + return cache[key1] + except KeyError: + dumper = cache[key1] = dumper.upgrade(obj, format) + return dumper + + def _get_none_oid(self) -> int: + try: + return self._none_oid + except AttributeError: + pass + + try: + rv = self._none_oid = self._adapters.get_dumper(NoneType, PY_TEXT).oid + except KeyError: + raise e.InterfaceError("None dumper not found") + + return rv + + def get_dumper_by_oid(self, oid: int, format: pq.Format) -> abc.Dumper: + """ + Return a Dumper to dump an object to the type with given oid. + """ + if not self._oid_dumpers: + self._oid_dumpers = ({}, {}) + + # Reuse an existing Dumper class for objects of the same type + cache = self._oid_dumpers[format] + try: + return cache[oid] + except KeyError: + # If it's the first time we see this type, look for a dumper + # configured for it. + dcls = self.adapters.get_dumper_by_oid(oid, format) + cache[oid] = dumper = dcls(NoneType, self) + + return dumper + + def load_rows(self, row0: int, row1: int, make_row: RowMaker[Row]) -> list[Row]: + res = self._pgresult + if not res: + raise e.InterfaceError("result not set") + + if not (0 <= row0 <= self._ntuples and 0 <= row1 <= self._ntuples): + raise e.InterfaceError( + f"rows must be included between 0 and {self._ntuples}" + ) + + records = [] + for row in range(row0, row1): + record: list[Any] = [None] * self._nfields + for col in range(self._nfields): + val = res.get_value(row, col) + if val is not None: + record[col] = self._row_loaders[col](val) + records.append(make_row(record)) + + return records + + def load_row(self, row: int, make_row: RowMaker[Row]) -> Row | None: + res = self._pgresult + if not res: + return None + + if not 0 <= row < self._ntuples: + return None + + record: list[Any] = [None] * self._nfields + for col in range(self._nfields): + val = res.get_value(row, col) + if val is not None: + record[col] = self._row_loaders[col](val) + + return make_row(record) + + def load_sequence(self, record: Sequence[Buffer | None]) -> tuple[Any, ...]: + if len(self._row_loaders) != len(record): + raise e.ProgrammingError( + f"cannot load sequence of {len(record)} items:" + f" {len(self._row_loaders)} loaders registered" + ) + + return tuple( + (self._row_loaders[i](val) if val is not None else None) + for i, val in enumerate(record) + ) + + def get_loader(self, oid: int, format: pq.Format) -> abc.Loader: + try: + return self._loaders[format][oid] + except KeyError: + pass + + loader_cls = self._adapters.get_loader(oid, format) + if not loader_cls: + loader_cls = self._adapters.get_loader(INVALID_OID, format) + if not loader_cls: + raise e.InterfaceError("unknown oid loader not found") + loader = self._loaders[format][oid] = loader_cls(oid, self) + return loader diff --git a/backend/.venv/Lib/site-packages/psycopg/_queries.py b/backend/.venv/Lib/site-packages/psycopg/_queries.py new file mode 100644 index 0000000..3368e79 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_queries.py @@ -0,0 +1,425 @@ +""" +Utility module to manipulate queries +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import re +from typing import Any, Callable, Mapping, Match, NamedTuple +from typing import Sequence, TYPE_CHECKING +from functools import lru_cache + +from . import pq +from . import errors as e +from .sql import Composable +from .abc import Buffer, Query, Params +from ._enums import PyFormat +from ._compat import TypeAlias, TypeGuard +from ._encodings import conn_encoding + +if TYPE_CHECKING: + from .abc import Transformer + +MAX_CACHED_STATEMENT_LENGTH = 4096 +MAX_CACHED_STATEMENT_PARAMS = 50 + + +class QueryPart(NamedTuple): + pre: bytes + item: int | str + format: PyFormat + + +class PostgresQuery: + """ + Helper to convert a Python query and parameters into Postgres format. + """ + + __slots__ = """ + query params types formats + _tx _want_formats _parts _encoding _order + """.split() + + def __init__(self, transformer: Transformer): + self._tx = transformer + + self.params: Sequence[Buffer | None] | None = None + # these are tuples so they can be used as keys e.g. in prepared stmts + self.types: tuple[int, ...] = () + + # The format requested by the user and the ones to really pass Postgres + self._want_formats: list[PyFormat] | None = None + self.formats: Sequence[pq.Format] | None = None + + self._encoding = conn_encoding(transformer.connection) + self._parts: list[QueryPart] + self.query = b"" + self._order: list[str] | None = None + + def convert(self, query: Query, vars: Params | None) -> None: + """ + Set up the query and parameters to convert. + + The results of this function can be obtained accessing the object + attributes (`query`, `params`, `types`, `formats`). + """ + if isinstance(query, str): + bquery = query.encode(self._encoding) + elif isinstance(query, Composable): + bquery = query.as_bytes(self._tx) + else: + bquery = query + + if vars is not None: + # Avoid caching queries extremely long or with a huge number of + # parameters. They are usually generated by ORMs and have poor + # cacheablility (e.g. INSERT ... VALUES (...), (...) with varying + # numbers of tuples. + # see https://github.com/psycopg/psycopg/discussions/628 + if ( + len(bquery) <= MAX_CACHED_STATEMENT_LENGTH + and len(vars) <= MAX_CACHED_STATEMENT_PARAMS + ): + f: _Query2Pg = _query2pg + else: + f = _query2pg_nocache + + (self.query, self._want_formats, self._order, self._parts) = f( + bquery, self._encoding + ) + else: + self.query = bquery + self._want_formats = self._order = None + + self.dump(vars) + + def dump(self, vars: Params | None) -> None: + """ + Process a new set of variables on the query processed by `convert()`. + + This method updates `params` and `types`. + """ + if vars is not None: + params = self.validate_and_reorder_params(self._parts, vars, self._order) + assert self._want_formats is not None + self.params = self._tx.dump_sequence(params, self._want_formats) + self.types = self._tx.types or () + self.formats = self._tx.formats + else: + self.params = None + self.types = () + self.formats = None + + @staticmethod + def is_params_sequence(vars: Params) -> TypeGuard[Sequence[Any]]: + # Try concrete types, then abstract types + t = type(vars) + if t is list or t is tuple: + sequence = True + elif t is dict: + sequence = False + elif isinstance(vars, Sequence) and not isinstance(vars, (bytes, str)): + sequence = True + elif isinstance(vars, Mapping): + sequence = False + else: + raise TypeError( + "query parameters should be a sequence or a mapping," + f" got {type(vars).__name__}" + ) + return sequence + + @staticmethod + def validate_and_reorder_params( + parts: list[QueryPart], vars: Params, order: list[str] | None + ) -> Sequence[Any]: + """ + Verify the compatibility between a query and a set of params. + """ + + if PostgresQuery.is_params_sequence(vars): + if len(vars) != len(parts) - 1: + raise e.ProgrammingError( + f"the query has {len(parts) - 1} placeholders but" + f" {len(vars)} parameters were passed" + ) + if vars and not isinstance(parts[0].item, int): + raise TypeError("named placeholders require a mapping of parameters") + return vars + + else: + if vars and len(parts) > 1 and not isinstance(parts[0][1], str): + raise TypeError( + "positional placeholders (%s) require a sequence of parameters" + ) + try: + if order: + return [vars[item] for item in order] # type: ignore[call-overload] + else: + return () + + except KeyError: + raise e.ProgrammingError( + "query parameter missing:" + f" {', '.join(sorted(i for i in order or () if i not in vars))}" + ) + + +# The type of the _query2pg() and _query2pg_nocache() methods +_Query2Pg: TypeAlias = Callable[ + [bytes, str], "tuple[bytes, list[PyFormat], list[str] | None, list[QueryPart]]" +] + + +def _query2pg_nocache( + query: bytes, encoding: str +) -> tuple[bytes, list[PyFormat], list[str] | None, list[QueryPart]]: + """ + Convert Python query and params into something Postgres understands. + + - Convert Python placeholders (``%s``, ``%(name)s``) into Postgres + format (``$1``, ``$2``) + - placeholders can be %s, %t, or %b (auto, text or binary) + - return ``query`` (bytes), ``formats`` (list of formats) ``order`` + (sequence of names used in the query, in the position they appear) + ``parts`` (splits of queries and placeholders). + """ + parts = _split_query(query, encoding) + order: list[str] | None = None + chunks: list[bytes] = [] + formats = [] + + if isinstance(parts[0].item, int): + for part in parts[:-1]: + assert isinstance(part.item, int) + chunks.append(part.pre) + chunks.append(b"$%d" % (part.item + 1)) + formats.append(part.format) + + elif isinstance(parts[0].item, str): + seen: dict[str, tuple[bytes, PyFormat]] = {} + order = [] + for part in parts[:-1]: + assert isinstance(part.item, str) + chunks.append(part.pre) + if part.item not in seen: + ph = b"$%d" % (len(seen) + 1) + seen[part.item] = (ph, part.format) + order.append(part.item) + chunks.append(ph) + formats.append(part.format) + else: + if seen[part.item][1] != part.format: + raise e.ProgrammingError( + f"placeholder '{part.item}' cannot have different formats" + ) + chunks.append(seen[part.item][0]) + + # last part + chunks.append(parts[-1].pre) + + return b"".join(chunks), formats, order, parts + + +# Note: the cache size is 128 items, but someone has reported throwing ~12k +# queries (of type `INSERT ... VALUES (...), (...)` with a varying amount of +# records), and the resulting cache size is >100Mb. So, we will avoid to cache +# large queries or queries with a large number of params. See +# https://github.com/sqlalchemy/sqlalchemy/discussions/10270 +_query2pg = lru_cache(_query2pg_nocache) + + +class PostgresClientQuery(PostgresQuery): + """ + PostgresQuery subclass merging query and arguments client-side. + """ + + __slots__ = ("template",) + + def convert(self, query: Query, vars: Params | None) -> None: + """ + Set up the query and parameters to convert. + + The results of this function can be obtained accessing the object + attributes (`query`, `params`, `types`, `formats`). + """ + if isinstance(query, str): + bquery = query.encode(self._encoding) + elif isinstance(query, Composable): + bquery = query.as_bytes(self._tx) + else: + bquery = query + + if vars is not None: + if ( + len(bquery) <= MAX_CACHED_STATEMENT_LENGTH + and len(vars) <= MAX_CACHED_STATEMENT_PARAMS + ): + f: _Query2PgClient = _query2pg_client + else: + f = _query2pg_client_nocache + + (self.template, self._order, self._parts) = f(bquery, self._encoding) + else: + self.query = bquery + self._order = None + + self.dump(vars) + + def dump(self, vars: Params | None) -> None: + """ + Process a new set of variables on the query processed by `convert()`. + + This method updates `params` and `types`. + """ + if vars is not None: + params = self.validate_and_reorder_params(self._parts, vars, self._order) + self.params = tuple( + self._tx.as_literal(p) if p is not None else b"NULL" for p in params + ) + self.query = self.template % self.params + else: + self.params = None + + +_Query2PgClient: TypeAlias = Callable[ + [bytes, str], "tuple[bytes, list[str] | None, list[QueryPart]]" +] + + +def _query2pg_client_nocache( + query: bytes, encoding: str +) -> tuple[bytes, list[str] | None, list[QueryPart]]: + """ + Convert Python query and params into a template to perform client-side binding + """ + parts = _split_query(query, encoding, collapse_double_percent=False) + order: list[str] | None = None + chunks: list[bytes] = [] + + if isinstance(parts[0].item, int): + for part in parts[:-1]: + assert isinstance(part.item, int) + chunks.append(part.pre) + chunks.append(b"%s") + + elif isinstance(parts[0].item, str): + seen: dict[str, tuple[bytes, PyFormat]] = {} + order = [] + for part in parts[:-1]: + assert isinstance(part.item, str) + chunks.append(part.pre) + if part.item not in seen: + ph = b"%s" + seen[part.item] = (ph, part.format) + order.append(part.item) + chunks.append(ph) + else: + chunks.append(seen[part.item][0]) + order.append(part.item) + + # last part + chunks.append(parts[-1].pre) + + return b"".join(chunks), order, parts + + +_query2pg_client = lru_cache(_query2pg_client_nocache) + + +_re_placeholder = re.compile( + rb"""(?x) + % # a literal % + (?: + (?: + \( ([^)]+) \) # or a name in (braces) + . # followed by a format + ) + | + (?:.) # or any char, really + ) + """ +) + + +def _split_query( + query: bytes, encoding: str = "ascii", collapse_double_percent: bool = True +) -> list[QueryPart]: + parts: list[tuple[bytes, Match[bytes] | None]] = [] + cur = 0 + + # pairs [(fragment, match], with the last match None + m = None + for m in _re_placeholder.finditer(query): + pre = query[cur : m.span(0)[0]] + parts.append((pre, m)) + cur = m.span(0)[1] + if m: + parts.append((query[cur:], None)) + else: + parts.append((query, None)) + + rv = [] + + # drop the "%%", validate + i = 0 + phtype = None + while i < len(parts): + pre, m = parts[i] + if m is None: + # last part + rv.append(QueryPart(pre, 0, PyFormat.AUTO)) + break + + ph = m.group(0) + if ph == b"%%": + # unescape '%%' to '%' if necessary, then merge the parts + if collapse_double_percent: + ph = b"%" + pre1, m1 = parts[i + 1] + parts[i + 1] = (pre + ph + pre1, m1) + del parts[i] + continue + + if ph == b"%(": + raise e.ProgrammingError( + "incomplete placeholder:" + f" '{query[m.span(0)[0]:].split()[0].decode(encoding)}'" + ) + elif ph == b"% ": + # explicit message for a typical error + raise e.ProgrammingError( + "incomplete placeholder: '%'; if you want to use '%' as an" + " operator you can double it up, i.e. use '%%'" + ) + elif ph[-1:] not in b"sbt": + raise e.ProgrammingError( + "only '%s', '%b', '%t' are allowed as placeholders, got" + f" '{m.group(0).decode(encoding)}'" + ) + + # Index or name + item: int | str + item = m.group(1).decode(encoding) if m.group(1) else i + + if not phtype: + phtype = type(item) + elif phtype is not type(item): + raise e.ProgrammingError( + "positional and named placeholders cannot be mixed" + ) + + format = _ph_to_fmt[ph[-1:]] + rv.append(QueryPart(pre, item, format)) + i += 1 + + return rv + + +_ph_to_fmt = { + b"s": PyFormat.AUTO, + b"t": PyFormat.TEXT, + b"b": PyFormat.BINARY, +} diff --git a/backend/.venv/Lib/site-packages/psycopg/_struct.py b/backend/.venv/Lib/site-packages/psycopg/_struct.py new file mode 100644 index 0000000..01978a5 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_struct.py @@ -0,0 +1,57 @@ +""" +Utility functions to deal with binary structs. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import struct +from typing import Callable, cast, Protocol + +from . import errors as e +from .abc import Buffer +from ._compat import TypeAlias + +PackInt: TypeAlias = Callable[[int], bytes] +UnpackInt: TypeAlias = Callable[[Buffer], "tuple[int]"] +PackFloat: TypeAlias = Callable[[float], bytes] +UnpackFloat: TypeAlias = Callable[[Buffer], "tuple[float]"] + + +class UnpackLen(Protocol): + def __call__(self, data: Buffer, start: int | None) -> tuple[int]: ... + + +pack_int2 = cast(PackInt, struct.Struct("!h").pack) +pack_uint2 = cast(PackInt, struct.Struct("!H").pack) +pack_int4 = cast(PackInt, struct.Struct("!i").pack) +pack_uint4 = cast(PackInt, struct.Struct("!I").pack) +pack_int8 = cast(PackInt, struct.Struct("!q").pack) +pack_float4 = cast(PackFloat, struct.Struct("!f").pack) +pack_float8 = cast(PackFloat, struct.Struct("!d").pack) + +unpack_int2 = cast(UnpackInt, struct.Struct("!h").unpack) +unpack_uint2 = cast(UnpackInt, struct.Struct("!H").unpack) +unpack_int4 = cast(UnpackInt, struct.Struct("!i").unpack) +unpack_uint4 = cast(UnpackInt, struct.Struct("!I").unpack) +unpack_int8 = cast(UnpackInt, struct.Struct("!q").unpack) +unpack_float4 = cast(UnpackFloat, struct.Struct("!f").unpack) +unpack_float8 = cast(UnpackFloat, struct.Struct("!d").unpack) + +_struct_len = struct.Struct("!i") +pack_len = cast(Callable[[int], bytes], _struct_len.pack) +unpack_len = cast(UnpackLen, _struct_len.unpack_from) + + +def pack_float4_bug_304(x: float) -> bytes: + raise e.InterfaceError( + "cannot dump Float4: Python affected by bug #304. Note that the psycopg-c" + " and psycopg-binary packages are not affected by this issue." + " See https://github.com/psycopg/psycopg/issues/304" + ) + + +# If issue #304 is detected, raise an error instead of dumping wrong data. +if struct.Struct("!f").pack(1.0) != bytes.fromhex("3f800000"): + pack_float4 = pack_float4_bug_304 diff --git a/backend/.venv/Lib/site-packages/psycopg/_tpc.py b/backend/.venv/Lib/site-packages/psycopg/_tpc.py new file mode 100644 index 0000000..880feff --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_tpc.py @@ -0,0 +1,115 @@ +""" +psycopg two-phase commit support +""" + +# Copyright (C) 2021 The Psycopg Team + +from __future__ import annotations + +import re +import datetime as dt +from base64 import b64encode, b64decode +from dataclasses import dataclass, replace + +_re_xid = re.compile(r"^(\d+)_([^_]*)_([^_]*)$") + + +@dataclass(frozen=True) +class Xid: + """A two-phase commit transaction identifier. + + The object can also be unpacked as a 3-item tuple (`format_id`, `gtrid`, + `bqual`). + + """ + + format_id: int | None + gtrid: str + bqual: str | None + prepared: dt.datetime | None = None + owner: str | None = None + database: str | None = None + + @classmethod + def from_string(cls, s: str) -> Xid: + """Try to parse an XA triple from the string. + + This may fail for several reasons. In such case return an unparsed Xid. + """ + try: + return cls._parse_string(s) + except Exception: + return Xid(None, s, None) + + def __str__(self) -> str: + return self._as_tid() + + def __len__(self) -> int: + return 3 + + def __getitem__(self, index: int) -> int | str | None: + return (self.format_id, self.gtrid, self.bqual)[index] + + @classmethod + def _parse_string(cls, s: str) -> Xid: + m = _re_xid.match(s) + if not m: + raise ValueError("bad Xid format") + + format_id = int(m.group(1)) + gtrid = b64decode(m.group(2)).decode() + bqual = b64decode(m.group(3)).decode() + return cls.from_parts(format_id, gtrid, bqual) + + @classmethod + def from_parts(cls, format_id: int | None, gtrid: str, bqual: str | None) -> Xid: + if format_id is not None: + if bqual is None: + raise TypeError("if format_id is specified, bqual must be too") + if not 0 <= format_id < 0x80000000: + raise ValueError("format_id must be a non-negative 32-bit integer") + if len(bqual) > 64: + raise ValueError("bqual must be not longer than 64 chars") + if len(gtrid) > 64: + raise ValueError("gtrid must be not longer than 64 chars") + + elif bqual is None: + raise TypeError("if format_id is None, bqual must be None too") + + return Xid(format_id, gtrid, bqual) + + def _as_tid(self) -> str: + """ + Return the PostgreSQL transaction_id for this XA xid. + + PostgreSQL wants just a string, while the DBAPI supports the XA + standard and thus a triple. We use the same conversion algorithm + implemented by JDBC in order to allow some form of interoperation. + + see also: the pgjdbc implementation + http://cvs.pgfoundry.org/cgi-bin/cvsweb.cgi/jdbc/pgjdbc/org/ + postgresql/xa/RecoveredXid.java?rev=1.2 + """ + if self.format_id is None or self.bqual is None: + # Unparsed xid: return the gtrid. + return self.gtrid + + # XA xid: mash together the components. + egtrid = b64encode(self.gtrid.encode()).decode() + ebqual = b64encode(self.bqual.encode()).decode() + + return f"{self.format_id}_{egtrid}_{ebqual}" + + @classmethod + def _get_recover_query(cls) -> str: + return "SELECT gid, prepared, owner, database FROM pg_prepared_xacts" + + @classmethod + def _from_record( + cls, gid: str, prepared: dt.datetime, owner: str, database: str + ) -> Xid: + xid = Xid.from_string(gid) + return replace(xid, prepared=prepared, owner=owner, database=database) + + +Xid.__module__ = "psycopg" diff --git a/backend/.venv/Lib/site-packages/psycopg/_transformer.py b/backend/.venv/Lib/site-packages/psycopg/_transformer.py new file mode 100644 index 0000000..d5a0aac --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_transformer.py @@ -0,0 +1,21 @@ +""" +Helper object to transform values between Python and PostgreSQL + +This module exports the requested implementation to the rest of the package. +""" + +# Copyright (C) 2023 The Psycopg Team + +from __future__ import annotations + +from . import abc +from ._cmodule import _psycopg + +Transformer: type[abc.Transformer] + +if _psycopg: + Transformer = _psycopg.Transformer +else: + from . import _py_transformer + + Transformer = _py_transformer.Transformer diff --git a/backend/.venv/Lib/site-packages/psycopg/_typeinfo.py b/backend/.venv/Lib/site-packages/psycopg/_typeinfo.py new file mode 100644 index 0000000..27a41a7 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_typeinfo.py @@ -0,0 +1,343 @@ +""" +Information about PostgreSQL types + +These types allow to read information from the system catalog and provide +information to the adapters if needed. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +from typing import Any, Iterator, overload, Sequence, TYPE_CHECKING + +from . import sql +from . import errors as e +from .abc import AdaptContext, Query +from .rows import dict_row +from ._compat import TypeAlias, TypeVar +from ._typemod import TypeModifier +from ._encodings import conn_encoding + +if TYPE_CHECKING: + from .connection import Connection + from .connection_async import AsyncConnection + from ._connection_base import BaseConnection + +T = TypeVar("T", bound="TypeInfo") +RegistryKey: TypeAlias = "str | int | tuple[type, int]" + + +class TypeInfo: + """ + Hold information about a PostgreSQL base type. + """ + + __module__ = "psycopg.types" + + def __init__( + self, + name: str, + oid: int, + array_oid: int, + *, + regtype: str = "", + delimiter: str = ",", + typemod: type[TypeModifier] = TypeModifier, + ): + self.name = name + self.oid = oid + self.array_oid = array_oid + self.regtype = regtype or name + self.delimiter = delimiter + self.typemod = typemod(oid) + + def __repr__(self) -> str: + return ( + f"<{self.__class__.__qualname__}:" + f" {self.name} (oid: {self.oid}, array oid: {self.array_oid})>" + ) + + @overload + @classmethod + def fetch( + cls: type[T], conn: Connection[Any], name: str | sql.Identifier + ) -> T | None: ... + + @overload + @classmethod + async def fetch( + cls: type[T], conn: AsyncConnection[Any], name: str | sql.Identifier + ) -> T | None: ... + + @classmethod + def fetch( + cls: type[T], conn: BaseConnection[Any], name: str | sql.Identifier + ) -> Any: + """Query a system catalog to read information about a type.""" + from .connection import Connection + from .connection_async import AsyncConnection + + if isinstance(name, sql.Composable): + name = name.as_string(conn) + + if isinstance(conn, Connection): + return cls._fetch(conn, name) + elif isinstance(conn, AsyncConnection): + return cls._fetch_async(conn, name) + else: + raise TypeError( + f"expected Connection or AsyncConnection, got {type(conn).__name__}" + ) + + @classmethod + def _fetch(cls: type[T], conn: Connection[Any], name: str) -> T | None: + # This might result in a nested transaction. What we want is to leave + # the function with the connection in the state we found (either idle + # or intrans) + try: + from psycopg import Cursor + + with conn.transaction(), Cursor(conn, row_factory=dict_row) as cur: + if conn_encoding(conn) == "ascii": + cur.execute("set local client_encoding to utf8") + cur.execute(cls._get_info_query(conn), {"name": name}) + recs = cur.fetchall() + except e.UndefinedObject: + return None + + return cls._from_records(name, recs) + + @classmethod + async def _fetch_async( + cls: type[T], conn: AsyncConnection[Any], name: str + ) -> T | None: + try: + from psycopg import AsyncCursor + + async with conn.transaction(): + async with AsyncCursor(conn, row_factory=dict_row) as cur: + if conn_encoding(conn) == "ascii": + await cur.execute("set local client_encoding to utf8") + await cur.execute(cls._get_info_query(conn), {"name": name}) + recs = await cur.fetchall() + except e.UndefinedObject: + return None + + return cls._from_records(name, recs) + + @classmethod + def _from_records( + cls: type[T], name: str, recs: Sequence[dict[str, Any]] + ) -> T | None: + if len(recs) == 1: + return cls(**recs[0]) + elif not recs: + return None + else: + raise e.ProgrammingError(f"found {len(recs)} different types named {name}") + + def register(self, context: AdaptContext | None = None) -> None: + """ + Register the type information, globally or in the specified `!context`. + """ + if context: + types = context.adapters.types + else: + from . import postgres + + types = postgres.types + + types.add(self) + + if self.array_oid: + from .types.array import register_array + + register_array(self, context) + + @classmethod + def _get_info_query(cls, conn: BaseConnection[Any]) -> Query: + return sql.SQL( + """\ +SELECT + typname AS name, oid, typarray AS array_oid, + oid::regtype::text AS regtype, typdelim AS delimiter +FROM pg_type t +WHERE t.oid = {regtype} +ORDER BY t.oid +""" + ).format(regtype=cls._to_regtype(conn)) + + @classmethod + def _has_to_regtype_function(cls, conn: BaseConnection[Any]) -> bool: + # to_regtype() introduced in PostgreSQL 9.4 and CockroachDB 22.2 + info = conn.info + if info.vendor == "PostgreSQL": + return info.server_version >= 90400 + elif info.vendor == "CockroachDB": + return info.server_version >= 220200 + else: + return False + + @classmethod + def _to_regtype(cls, conn: BaseConnection[Any]) -> sql.SQL: + # `to_regtype()` returns the type oid or NULL, unlike the :: operator, + # which returns the type or raises an exception, which requires + # a transaction rollback and leaves traces in the server logs. + + if cls._has_to_regtype_function(conn): + return sql.SQL("to_regtype(%(name)s)") + else: + return sql.SQL("%(name)s::regtype") + + def _added(self, registry: TypesRegistry) -> None: + """Method called by the `!registry` when the object is added there.""" + pass + + def get_type_display(self, oid: int | None = None, fmod: int | None = None) -> str: + parts = [] + parts.append(self.name) + mod = self.typemod.get_modifier(fmod) if fmod is not None else () + if mod: + parts.append(f"({','.join(map(str, mod))})") + + if oid == self.array_oid: + parts.append("[]") + + return "".join(parts) + + def get_display_size(self, fmod: int) -> int | None: + return self.typemod.get_display_size(fmod) + + def get_precision(self, fmod: int) -> int | None: + return self.typemod.get_precision(fmod) + + def get_scale(self, fmod: int) -> int | None: + return self.typemod.get_scale(fmod) + + +class TypesRegistry: + """ + Container for the information about types in a database. + """ + + __module__ = "psycopg.types" + + def __init__(self, template: TypesRegistry | None = None): + self._registry: dict[RegistryKey, TypeInfo] + + # Make a shallow copy: it will become a proper copy if the registry + # is edited. + if template: + self._registry = template._registry + self._own_state = False + template._own_state = False + else: + self.clear() + + def clear(self) -> None: + self._registry = {} + self._own_state = True + + def add(self, info: TypeInfo) -> None: + self._ensure_own_state() + if info.oid: + self._registry[info.oid] = info + if info.array_oid: + self._registry[info.array_oid] = info + self._registry[info.name] = info + + if info.regtype and info.regtype not in self._registry: + self._registry[info.regtype] = info + + # Allow info to customise further their relation with the registry + info._added(self) + + def __iter__(self) -> Iterator[TypeInfo]: + seen = set() + for t in self._registry.values(): + if id(t) not in seen: + seen.add(id(t)) + yield t + + @overload + def __getitem__(self, key: str | int) -> TypeInfo: ... + + @overload + def __getitem__(self, key: tuple[type[T], int]) -> T: ... + + def __getitem__(self, key: RegistryKey) -> TypeInfo: + """ + Return info about a type, specified by name or oid + + :param key: the name or oid of the type to look for. + + Raise KeyError if not found. + """ + if isinstance(key, str): + if key.endswith("[]"): + key = key[:-2] + elif not isinstance(key, (int, tuple)): + raise TypeError(f"the key must be an oid or a name, got {type(key)}") + try: + return self._registry[key] + except KeyError: + raise KeyError(f"couldn't find the type {key!r} in the types registry") + + @overload + def get(self, key: str | int) -> TypeInfo | None: ... + + @overload + def get(self, key: tuple[type[T], int]) -> T | None: ... + + def get(self, key: RegistryKey) -> TypeInfo | None: + """ + Return info about a type, specified by name or oid + + :param key: the name or oid of the type to look for. + + Unlike `__getitem__`, return None if not found. + """ + try: + return self[key] + except KeyError: + return None + + def get_oid(self, name: str) -> int: + """ + Return the oid of a PostgreSQL type by name. + + :param key: the name of the type to look for. + + Return the array oid if the type ends with "``[]``" + + Raise KeyError if the name is unknown. + """ + t = self[name] + if name.endswith("[]"): + return t.array_oid + else: + return t.oid + + def get_by_subtype(self, cls: type[T], subtype: int | str) -> T | None: + """ + Return info about a `TypeInfo` subclass by its element name or oid. + + :param cls: the subtype of `!TypeInfo` to look for. Currently + supported are `~psycopg.types.range.RangeInfo` and + `~psycopg.types.multirange.MultirangeInfo`. + :param subtype: The name or OID of the subtype of the element to look for. + :return: The `!TypeInfo` object of class `!cls` whose subtype is + `!subtype`. `!None` if the element or its range are not found. + """ + try: + info = self[subtype] + except KeyError: + return None + return self.get((cls, info.oid)) + + def _ensure_own_state(self) -> None: + # Time to write! so, copy. + if not self._own_state: + self._registry = self._registry.copy() + self._own_state = True diff --git a/backend/.venv/Lib/site-packages/psycopg/_typemod.py b/backend/.venv/Lib/site-packages/psycopg/_typemod.py new file mode 100644 index 0000000..a558b08 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_typemod.py @@ -0,0 +1,86 @@ +""" +PostgreSQL type modifiers. + +The type modifiers parse catalog information to obtain the type modifier +of a column - the numeric part of varchar(10) or decimal(6,2). +""" + +# Copyright (C) 2024 The Psycopg Team + +from __future__ import annotations + + +class TypeModifier: + """Type modifier that doesn't know any modifier. + + Useful to describe types with no type modifier. + """ + + def __init__(self, oid: int): + self.oid = oid + + def get_modifier(self, typemod: int) -> tuple[int, ...] | None: + return None + + def get_display_size(self, typemod: int) -> int | None: + return None + + def get_precision(self, typemod: int) -> int | None: + return None + + def get_scale(self, typemod: int) -> int | None: + return None + + +class NumericTypeModifier(TypeModifier): + """Handle numeric type modifier.""" + + def get_modifier(self, typemod: int) -> tuple[int, ...] | None: + precision = self.get_precision(typemod) + scale = self.get_scale(typemod) + return None if precision is None or scale is None else (precision, scale) + + def get_precision(self, typemod: int) -> int | None: + return typemod >> 16 if typemod >= 0 else None + + def get_scale(self, typemod: int) -> int | None: + if typemod < 0: + return None + + scale = (typemod - 4) & 0xFFFF + if scale >= 0x400: + scale = scale - 0x800 + return scale + + +class CharTypeModifier(TypeModifier): + """Handle char/varchar type modifier.""" + + def get_modifier(self, typemod: int) -> tuple[int, ...] | None: + dsize = self.get_display_size(typemod) + return (dsize,) if dsize else None + + def get_display_size(self, typemod: int) -> int | None: + return typemod - 4 if typemod >= 0 else None + + +class BitTypeModifier(TypeModifier): + """Handle bit/varbit type modifier.""" + + def get_modifier(self, typemod: int) -> tuple[int, ...] | None: + dsize = self.get_display_size(typemod) + return (dsize,) if dsize else None + + def get_display_size(self, typemod: int) -> int | None: + return typemod if typemod >= 0 else None + + +class TimeTypeModifier(TypeModifier): + """Handle time-related types modifier.""" + + def get_modifier(self, typemod: int) -> tuple[int, ...] | None: + prec = self.get_precision(typemod) + return (prec,) if prec is not None else None + + def get_precision(self, typemod: int) -> int | None: + return typemod & 0xFFFF if typemod >= 0 else None diff --git a/backend/.venv/Lib/site-packages/psycopg/_tz.py b/backend/.venv/Lib/site-packages/psycopg/_tz.py new file mode 100644 index 0000000..c6f400d --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_tz.py @@ -0,0 +1,45 @@ +""" +Timezone utility functions. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import logging +from datetime import timezone, tzinfo + +from .pq.abc import PGconn +from ._compat import ZoneInfo + +logger = logging.getLogger("psycopg") + +_timezones: dict[bytes | None, tzinfo] = { + None: timezone.utc, + b"UTC": timezone.utc, +} + + +def get_tzinfo(pgconn: PGconn | None) -> tzinfo: + """Return the Python timezone info of the connection's timezone.""" + tzname = pgconn.parameter_status(b"TimeZone") if pgconn else None + try: + return _timezones[tzname] + except KeyError: + sname = tzname.decode() if tzname else "UTC" + try: + zi: tzinfo = ZoneInfo(sname) + except (KeyError, OSError): + logger.warning("unknown PostgreSQL timezone: %r; will use UTC", sname) + zi = timezone.utc + except Exception as ex: + logger.warning( + "error handling PostgreSQL timezone: %r; will use UTC (%s - %s)", + sname, + type(ex).__name__, + ex, + ) + zi = timezone.utc + + _timezones[tzname] = zi + return zi diff --git a/backend/.venv/Lib/site-packages/psycopg/_wrappers.py b/backend/.venv/Lib/site-packages/psycopg/_wrappers.py new file mode 100644 index 0000000..f861741 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/_wrappers.py @@ -0,0 +1,137 @@ +""" +Wrappers for numeric types. +""" + +# Copyright (C) 2020 The Psycopg Team + +# Wrappers to force numbers to be cast as specific PostgreSQL types + +# These types are implemented here but exposed by `psycopg.types.numeric`. +# They are defined here to avoid a circular import. +_MODULE = "psycopg.types.numeric" + + +class Int2(int): + """ + Force dumping a Python `!int` as a PostgreSQL :sql:`smallint/int2`. + """ + + __module__ = _MODULE + __slots__ = () + + def __new__(cls, arg: int) -> "Int2": + return super().__new__(cls, arg) + + def __str__(self) -> str: + return super().__repr__() + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({super().__repr__()})" + + +class Int4(int): + """ + Force dumping a Python `!int` as a PostgreSQL :sql:`integer/int4`. + """ + + __module__ = _MODULE + __slots__ = () + + def __new__(cls, arg: int) -> "Int4": + return super().__new__(cls, arg) + + def __str__(self) -> str: + return super().__repr__() + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({super().__repr__()})" + + +class Int8(int): + """ + Force dumping a Python `!int` as a PostgreSQL :sql:`bigint/int8`. + """ + + __module__ = _MODULE + __slots__ = () + + def __new__(cls, arg: int) -> "Int8": + return super().__new__(cls, arg) + + def __str__(self) -> str: + return super().__repr__() + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({super().__repr__()})" + + +class IntNumeric(int): + """ + Force dumping a Python `!int` as a PostgreSQL :sql:`numeric/decimal`. + """ + + __module__ = _MODULE + __slots__ = () + + def __new__(cls, arg: int) -> "IntNumeric": + return super().__new__(cls, arg) + + def __str__(self) -> str: + return super().__repr__() + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({super().__repr__()})" + + +class Float4(float): + """ + Force dumping a Python `!float` as a PostgreSQL :sql:`float4/real`. + """ + + __module__ = _MODULE + __slots__ = () + + def __new__(cls, arg: float) -> "Float4": + return super().__new__(cls, arg) + + def __str__(self) -> str: + return super().__repr__() + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({super().__repr__()})" + + +class Float8(float): + """ + Force dumping a Python `!float` as a PostgreSQL :sql:`float8/double precision`. + """ + + __module__ = _MODULE + __slots__ = () + + def __new__(cls, arg: float) -> "Float8": + return super().__new__(cls, arg) + + def __str__(self) -> str: + return super().__repr__() + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({super().__repr__()})" + + +class Oid(int): + """ + Force dumping a Python `!int` as a PostgreSQL :sql:`oid`. + """ + + __module__ = _MODULE + __slots__ = () + + def __new__(cls, arg: int) -> "Oid": + return super().__new__(cls, arg) + + def __str__(self) -> str: + return super().__repr__() + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({super().__repr__()})" diff --git a/backend/.venv/Lib/site-packages/psycopg/abc.py b/backend/.venv/Lib/site-packages/psycopg/abc.py new file mode 100644 index 0000000..b1e4031 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/abc.py @@ -0,0 +1,251 @@ +""" +Protocol objects representing different implementations of the same classes. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +from typing import Any, Callable, Generator, Mapping +from typing import Protocol, Sequence, TYPE_CHECKING +from typing import Dict, Union # drop with Python 3.8 + +from . import pq +from ._enums import PyFormat as PyFormat +from ._compat import LiteralString, TypeAlias, TypeVar + +if TYPE_CHECKING: + from . import sql # noqa: F401 + from .rows import Row, RowMaker + from .pq.abc import PGresult + from .waiting import Wait, Ready # noqa: F401 + from ._adapters_map import AdaptersMap + from ._connection_base import BaseConnection + +NoneType: type = type(None) + +# An object implementing the buffer protocol +Buffer: TypeAlias = Union[bytes, bytearray, memoryview] + +Query: TypeAlias = Union[LiteralString, bytes, "sql.SQL", "sql.Composed"] +Params: TypeAlias = Union[Sequence[Any], Mapping[str, Any]] +ConnectionType = TypeVar("ConnectionType", bound="BaseConnection[Any]") +PipelineCommand: TypeAlias = Callable[[], None] +DumperKey: TypeAlias = Union[type, "tuple[DumperKey, ...]"] +ConnParam: TypeAlias = Union[str, int, None] +ConnDict: TypeAlias = Dict[str, ConnParam] +ConnMapping: TypeAlias = Mapping[str, ConnParam] + + +# Waiting protocol types + +RV = TypeVar("RV") + +PQGenConn: TypeAlias = Generator["tuple[int, Wait]", "Ready | int", RV] +"""Generator for processes where the connection file number can change. + +This can happen in connection and reset, but not in normal querying. +""" + +PQGen: TypeAlias = Generator["Wait", "Ready | int", RV] +"""Generator for processes where the connection file number won't change. +""" + + +class WaitFunc(Protocol): + """ + Wait on the connection which generated `PQgen` and return its final result. + """ + + def __call__( + self, gen: PQGen[RV], fileno: int, interval: float | None = None + ) -> RV: ... + + +# Adaptation types + +DumpFunc: TypeAlias = Callable[[Any], "Buffer | None"] +LoadFunc: TypeAlias = Callable[[Buffer], Any] + + +class AdaptContext(Protocol): + """ + A context describing how types are adapted. + + Example of `~AdaptContext` are `~psycopg.Connection`, `~psycopg.Cursor`, + `~psycopg.adapt.Transformer`, `~psycopg.adapt.AdaptersMap`. + + Note that this is a `~typing.Protocol`, so objects implementing + `!AdaptContext` don't need to explicitly inherit from this class. + + """ + + @property + def adapters(self) -> AdaptersMap: + """The adapters configuration that this object uses.""" + ... + + @property + def connection(self) -> BaseConnection[Any] | None: + """The connection used by this object, if available. + + :rtype: `~psycopg.Connection` or `~psycopg.AsyncConnection` or `!None` + """ + ... + + +class Dumper(Protocol): + """ + Convert Python objects of type `!cls` to PostgreSQL representation. + """ + + format: pq.Format + """ + The format that this class `dump()` method produces, + `~psycopg.pq.Format.TEXT` or `~psycopg.pq.Format.BINARY`. + + This is a class attribute. + """ + + oid: int + """The oid to pass to the server, if known; 0 otherwise (class attribute).""" + + def __init__(self, cls: type, context: AdaptContext | None = None): ... + + def dump(self, obj: Any) -> Buffer | None: + """Convert the object `!obj` to PostgreSQL representation. + + :param obj: the object to convert. + """ + ... + + def quote(self, obj: Any) -> Buffer: + """Convert the object `!obj` to escaped representation. + + :param obj: the object to convert. + """ + ... + + def get_key(self, obj: Any, format: PyFormat) -> DumperKey: + """Return an alternative key to upgrade the dumper to represent `!obj`. + + :param obj: The object to convert + :param format: The format to convert to + + Normally the type of the object is all it takes to define how to dump + the object to the database. For instance, a Python `~datetime.date` can + be simply converted into a PostgreSQL :sql:`date`. + + In a few cases, just the type is not enough. For example: + + - A Python `~datetime.datetime` could be represented as a + :sql:`timestamptz` or a :sql:`timestamp`, according to whether it + specifies a `!tzinfo` or not. + + - A Python int could be stored as several Postgres types: int2, int4, + int8, numeric. If a type too small is used, it may result in an + overflow. If a type too large is used, PostgreSQL may not want to + cast it to a smaller type. + + - Python lists should be dumped according to the type they contain to + convert them to e.g. array of strings, array of ints (and which + size of int?...) + + In these cases, a dumper can implement `!get_key()` and return a new + class, or sequence of classes, that can be used to identify the same + dumper again. If the mechanism is not needed, the method should return + the same `!cls` object passed in the constructor. + + If a dumper implements `get_key()` it should also implement + `upgrade()`. + + """ + ... + + def upgrade(self, obj: Any, format: PyFormat) -> Dumper: + """Return a new dumper to manage `!obj`. + + :param obj: The object to convert + :param format: The format to convert to + + Once `Transformer.get_dumper()` has been notified by `get_key()` that + this Dumper class cannot handle `!obj` itself, it will invoke + `!upgrade()`, which should return a new `Dumper` instance, which will + be reused for every objects for which `!get_key()` returns the same + result. + """ + ... + + +class Loader(Protocol): + """ + Convert PostgreSQL values with type OID `!oid` to Python objects. + """ + + format: pq.Format + """ + The format that this class `load()` method can convert, + `~psycopg.pq.Format.TEXT` or `~psycopg.pq.Format.BINARY`. + + This is a class attribute. + """ + + def __init__(self, oid: int, context: AdaptContext | None = None): ... + + def load(self, data: Buffer) -> Any: + """ + Convert the data returned by the database into a Python object. + + :param data: the data to convert. + """ + ... + + +class Transformer(Protocol): + types: tuple[int, ...] | None + formats: list[pq.Format] | None + + def __init__(self, context: AdaptContext | None = None): ... + + @classmethod + def from_context(cls, context: AdaptContext | None) -> Transformer: ... + + @property + def connection(self) -> BaseConnection[Any] | None: ... + + @property + def encoding(self) -> str: ... + + @property + def adapters(self) -> AdaptersMap: ... + + @property + def pgresult(self) -> PGresult | None: ... + + def set_pgresult( + self, + result: PGresult | None, + *, + set_loaders: bool = True, + format: pq.Format | None = None, + ) -> None: ... + + def set_dumper_types(self, types: Sequence[int], format: pq.Format) -> None: ... + + def set_loader_types(self, types: Sequence[int], format: pq.Format) -> None: ... + + def dump_sequence( + self, params: Sequence[Any], formats: Sequence[PyFormat] + ) -> Sequence[Buffer | None]: ... + + def as_literal(self, obj: Any) -> bytes: ... + + def get_dumper(self, obj: Any, format: PyFormat) -> Dumper: ... + + def load_rows(self, row0: int, row1: int, make_row: RowMaker[Row]) -> list[Row]: ... + + def load_row(self, row: int, make_row: RowMaker[Row]) -> Row | None: ... + + def load_sequence(self, record: Sequence[Buffer | None]) -> tuple[Any, ...]: ... + + def get_loader(self, oid: int, format: pq.Format) -> Loader: ... diff --git a/backend/.venv/Lib/site-packages/psycopg/adapt.py b/backend/.venv/Lib/site-packages/psycopg/adapt.py new file mode 100644 index 0000000..428042f --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/adapt.py @@ -0,0 +1,153 @@ +""" +Entry point into the adaptation system. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +from abc import ABC, abstractmethod +from typing import Any, TYPE_CHECKING + +from . import pq, abc + +# Objects exported here +from ._enums import PyFormat as PyFormat +from ._transformer import Transformer as Transformer +from ._adapters_map import AdaptersMap as AdaptersMap # noqa: F401 # reexport + +if TYPE_CHECKING: + from ._connection_base import BaseConnection + +Buffer = abc.Buffer + +ORD_BS = ord("\\") + + +class Dumper(abc.Dumper, ABC): + """ + Convert Python object of the type `!cls` to PostgreSQL representation. + """ + + oid: int = 0 + """The oid to pass to the server, if known.""" + + format: pq.Format = pq.Format.TEXT + """The format of the data dumped.""" + + def __init__(self, cls: type, context: abc.AdaptContext | None = None): + self.cls = cls + self.connection: BaseConnection[Any] | None + self.connection = context.connection if context else None + + def __repr__(self) -> str: + return ( + f"<{type(self).__module__}.{type(self).__qualname__}" + f" (oid={self.oid}) at 0x{id(self):x}>" + ) + + @abstractmethod + def dump(self, obj: Any) -> Buffer | None: ... + + def quote(self, obj: Any) -> Buffer: + """ + By default return the `dump()` value quoted and sanitised, so + that the result can be used to build a SQL string. This works well + for most types and you won't likely have to implement this method in a + subclass. + """ + value = self.dump(obj) + if value is None: + return b"NULL" + + if self.connection: + esc = pq.Escaping(self.connection.pgconn) + # escaping and quoting + return esc.escape_literal(value) + + # This path is taken when quote is asked without a connection, + # usually it means by psycopg.sql.quote() or by + # 'Composible.as_string(None)'. Most often than not this is done by + # someone generating a SQL file to consume elsewhere. + + # No quoting, only quote escaping, random bs escaping. See further. + esc = pq.Escaping() + out = esc.escape_string(value) + + # b"\\" in memoryview doesn't work so search for the ascii value + if ORD_BS not in out: + # If the string has no backslash, the result is correct and we + # don't need to bother with standard_conforming_strings. + return b"'" + out + b"'" + + # The libpq has a crazy behaviour: PQescapeString uses the last + # standard_conforming_strings setting seen on a connection. This + # means that backslashes might be escaped or might not. + # + # A syntax E'\\' works everywhere, whereas E'\' is an error. OTOH, + # if scs is off, '\\' raises a warning and '\' is an error. + # + # Check what the libpq does, and if it doesn't escape the backslash + # let's do it on our own. Never mind the race condition. + rv: bytes = b" E'" + out + b"'" + if esc.escape_string(b"\\") == b"\\": + rv = rv.replace(b"\\", b"\\\\") + return rv + + def get_key(self, obj: Any, format: PyFormat) -> abc.DumperKey: + """ + Implementation of the `~psycopg.abc.Dumper.get_key()` member of the + `~psycopg.abc.Dumper` protocol. Look at its definition for details. + + This implementation returns the `!cls` passed in the constructor. + Subclasses needing to specialise the PostgreSQL type according to the + *value* of the object dumped (not only according to to its type) + should override this class. + + """ + return self.cls + + def upgrade(self, obj: Any, format: PyFormat) -> Dumper: + """ + Implementation of the `~psycopg.abc.Dumper.upgrade()` member of the + `~psycopg.abc.Dumper` protocol. Look at its definition for details. + + This implementation just returns `!self`. If a subclass implements + `get_key()` it should probably override `!upgrade()` too. + """ + return self + + +class Loader(abc.Loader, ABC): + """ + Convert PostgreSQL values with type OID `!oid` to Python objects. + """ + + format: pq.Format = pq.Format.TEXT + """The format of the data loaded.""" + + def __init__(self, oid: int, context: abc.AdaptContext | None = None): + self.oid = oid + self.connection: BaseConnection[Any] | None + self.connection = context.connection if context else None + + @abstractmethod + def load(self, data: Buffer) -> Any: + """Convert a PostgreSQL value to a Python object.""" + ... + + +class RecursiveDumper(Dumper): + """Dumper with a transformer to help dumping recursive types.""" + + def __init__(self, cls: type, context: abc.AdaptContext | None = None): + super().__init__(cls, context) + self._tx = Transformer.from_context(context) + + +class RecursiveLoader(Loader): + """Loader with a transformer to help loading recursive types.""" + + def __init__(self, oid: int, context: abc.AdaptContext | None = None): + super().__init__(oid, context) + self._tx = Transformer.from_context(context) diff --git a/backend/.venv/Lib/site-packages/psycopg/client_cursor.py b/backend/.venv/Lib/site-packages/psycopg/client_cursor.py new file mode 100644 index 0000000..5a64e5f --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/client_cursor.py @@ -0,0 +1,93 @@ +""" +psycopg client-side binding cursors +""" + +# Copyright (C) 2022 The Psycopg Team + +from __future__ import annotations + +from typing import TYPE_CHECKING +from functools import partial + +from ._queries import PostgresQuery, PostgresClientQuery + +from . import pq +from . import adapt +from . import errors as e +from .abc import ConnectionType, Query, Params +from .rows import Row +from .cursor import Cursor +from ._preparing import Prepare +from ._cursor_base import BaseCursor +from .cursor_async import AsyncCursor + +if TYPE_CHECKING: + from typing import Any # noqa: F401 + from .connection import Connection # noqa: F401 + from .connection_async import AsyncConnection # noqa: F401 + +TEXT = pq.Format.TEXT +BINARY = pq.Format.BINARY + + +class ClientCursorMixin(BaseCursor[ConnectionType, Row]): + _query_cls = PostgresClientQuery + + def mogrify(self, query: Query, params: Params | None = None) -> str: + """ + Return the query and parameters merged. + + Parameters are adapted and merged to the query the same way that + `!execute()` would do. + + """ + self._tx = adapt.Transformer(self) + pgq = self._convert_query(query, params) + return pgq.query.decode(self._tx.encoding) + + def _execute_send( + self, + query: PostgresQuery, + *, + force_extended: bool = False, + binary: bool | None = None, + ) -> None: + if binary is None: + fmt = self.format + else: + fmt = BINARY if binary else TEXT + + if fmt == BINARY: + raise e.NotSupportedError( + "client-side cursors don't support binary results" + ) + + self._query = query + + if self._conn._pipeline: + # In pipeline mode always use PQsendQueryParams - see #314 + # Multiple statements in the same query are not allowed anyway. + self._conn._pipeline.command_queue.append( + partial(self._pgconn.send_query_params, query.query, None) + ) + elif force_extended: + self._pgconn.send_query_params(query.query, None) + else: + # If we can, let's use simple query protocol, + # as it can execute more than one statement in a single query. + self._pgconn.send_query(query.query) + + def _get_prepared( + self, pgq: PostgresQuery, prepare: bool | None = None + ) -> tuple[Prepare, bytes]: + return (Prepare.NO, b"") + + +class ClientCursor(ClientCursorMixin["Connection[Any]", Row], Cursor[Row]): + __module__ = "psycopg" + + +class AsyncClientCursor( + ClientCursorMixin["AsyncConnection[Any]", Row], AsyncCursor[Row] +): + __module__ = "psycopg" diff --git a/backend/.venv/Lib/site-packages/psycopg/connection.py b/backend/.venv/Lib/site-packages/psycopg/connection.py new file mode 100644 index 0000000..9558e29 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/connection.py @@ -0,0 +1,479 @@ +# WARNING: this file is auto-generated by 'async_to_sync.py' +# from the original file 'connection_async.py' +# DO NOT CHANGE! Change the original file instead. +""" +Psycopg connection object (sync version) +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import logging +from time import monotonic +from types import TracebackType +from typing import Any, Generator, Iterator, cast, overload, TYPE_CHECKING +from contextlib import contextmanager + +from . import pq +from . import errors as e +from . import waiting +from .abc import AdaptContext, ConnDict, ConnParam, Params, PQGen, Query, RV +from ._tpc import Xid +from .rows import Row, RowFactory, tuple_row, args_row +from .adapt import AdaptersMap +from ._enums import IsolationLevel +from ._compat import Self +from .conninfo import make_conninfo, conninfo_to_dict +from .conninfo import conninfo_attempts, timeout_from_conninfo +from ._pipeline import Pipeline +from .generators import notifies +from .transaction import Transaction +from .cursor import Cursor +from ._capabilities import capabilities +from .server_cursor import ServerCursor +from ._connection_base import BaseConnection, CursorRow, Notify + +from threading import Lock + +if TYPE_CHECKING: + from .pq.abc import PGconn + +_WAIT_INTERVAL = 0.1 + +TEXT = pq.Format.TEXT +BINARY = pq.Format.BINARY + +IDLE = pq.TransactionStatus.IDLE +ACTIVE = pq.TransactionStatus.ACTIVE +INTRANS = pq.TransactionStatus.INTRANS + +_INTERRUPTED = KeyboardInterrupt + +logger = logging.getLogger("psycopg") + + +class Connection(BaseConnection[Row]): + """ + Wrapper for a connection to the database. + """ + + __module__ = "psycopg" + + cursor_factory: type[Cursor[Row]] + server_cursor_factory: type[ServerCursor[Row]] + row_factory: RowFactory[Row] + _pipeline: Pipeline | None + + def __init__( + self, + pgconn: PGconn, + row_factory: RowFactory[Row] = cast(RowFactory[Row], tuple_row), + ): + super().__init__(pgconn) + self.row_factory = row_factory + self.lock = Lock() + self.cursor_factory = Cursor + self.server_cursor_factory = ServerCursor + + @classmethod + def connect( + cls, + conninfo: str = "", + *, + autocommit: bool = False, + prepare_threshold: int | None = 5, + context: AdaptContext | None = None, + row_factory: RowFactory[Row] | None = None, + cursor_factory: type[Cursor[Row]] | None = None, + **kwargs: ConnParam, + ) -> Self: + """ + Connect to a database server and return a new `Connection` instance. + """ + + params = cls._get_connection_params(conninfo, **kwargs) + timeout = timeout_from_conninfo(params) + rv = None + attempts = conninfo_attempts(params) + for attempt in attempts: + try: + conninfo = make_conninfo("", **attempt) + gen = cls._connect_gen(conninfo, timeout=timeout) + rv = waiting.wait_conn(gen, interval=_WAIT_INTERVAL) + except e._NO_TRACEBACK as ex: + if len(attempts) > 1: + logger.debug( + "connection attempt failed: host: %r port: %r, hostaddr %r: %s", + attempt.get("host"), + attempt.get("port"), + attempt.get("hostaddr"), + str(ex), + ) + last_ex = ex + else: + break + + if not rv: + assert last_ex + raise last_ex.with_traceback(None) + + rv._autocommit = bool(autocommit) + if row_factory: + rv.row_factory = row_factory + if cursor_factory: + rv.cursor_factory = cursor_factory + if context: + rv._adapters = AdaptersMap(context.adapters) + rv.prepare_threshold = prepare_threshold + return rv + + def __enter__(self) -> Self: + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + if self.closed: + return + + if exc_type: + # try to rollback, but if there are problems (connection in a bad + # state) just warn without clobbering the exception bubbling up. + try: + self.rollback() + except Exception as exc2: + logger.warning("error ignored in rollback on %s: %s", self, exc2) + else: + self.commit() + + # Close the connection only if it doesn't belong to a pool. + if not getattr(self, "_pool", None): + self.close() + + @classmethod + def _get_connection_params(cls, conninfo: str, **kwargs: Any) -> ConnDict: + """Manipulate connection parameters before connecting.""" + return conninfo_to_dict(conninfo, **kwargs) + + def close(self) -> None: + """Close the database connection.""" + if self.closed: + return + self._closed = True + + # TODO: maybe send a cancel on close, if the connection is ACTIVE? + + self.pgconn.finish() + + @overload + def cursor(self, *, binary: bool = False) -> Cursor[Row]: ... + + @overload + def cursor( + self, *, binary: bool = False, row_factory: RowFactory[CursorRow] + ) -> Cursor[CursorRow]: ... + + @overload + def cursor( + self, + name: str, + *, + binary: bool = False, + scrollable: bool | None = None, + withhold: bool = False, + ) -> ServerCursor[Row]: ... + + @overload + def cursor( + self, + name: str, + *, + binary: bool = False, + row_factory: RowFactory[CursorRow], + scrollable: bool | None = None, + withhold: bool = False, + ) -> ServerCursor[CursorRow]: ... + + def cursor( + self, + name: str = "", + *, + binary: bool = False, + row_factory: RowFactory[Any] | None = None, + scrollable: bool | None = None, + withhold: bool = False, + ) -> Cursor[Any] | ServerCursor[Any]: + """ + Return a new `Cursor` to send commands and queries to the connection. + """ + self._check_connection_ok() + + if not row_factory: + row_factory = self.row_factory + + cur: Cursor[Any] | ServerCursor[Any] + if name: + cur = self.server_cursor_factory( + self, + name=name, + row_factory=row_factory, + scrollable=scrollable, + withhold=withhold, + ) + else: + cur = self.cursor_factory(self, row_factory=row_factory) + + if binary: + cur.format = BINARY + + return cur + + def execute( + self, + query: Query, + params: Params | None = None, + *, + prepare: bool | None = None, + binary: bool = False, + ) -> Cursor[Row]: + """Execute a query and return a cursor to read its results.""" + try: + cur = self.cursor() + if binary: + cur.format = BINARY + + return cur.execute(query, params, prepare=prepare) + except e._NO_TRACEBACK as ex: + raise ex.with_traceback(None) + + def commit(self) -> None: + """Commit any pending transaction to the database.""" + with self.lock: + self.wait(self._commit_gen()) + + def rollback(self) -> None: + """Roll back to the start of any pending transaction.""" + with self.lock: + self.wait(self._rollback_gen()) + + def cancel_safe(self, *, timeout: float = 30.0) -> None: + """Cancel the current operation on the connection. + + :param timeout: raise a `~errors.CancellationTimeout` if the + cancellation request does not succeed within `timeout` seconds. + + Note that a successful cancel attempt on the client is not a guarantee + that the server will successfully manage to cancel the operation. + + This is a non-blocking version of `~Connection.cancel()` which + leverages a more secure and improved cancellation feature of the libpq, + which is only available from version 17. + + If the underlying libpq is older than version 17, the method will fall + back to using the same implementation of `!cancel()`. + """ + if not self._should_cancel(): + return + + if capabilities.has_cancel_safe(): + waiting.wait_conn( + self._cancel_gen(timeout=timeout), interval=_WAIT_INTERVAL + ) + else: + self.cancel() + + def _try_cancel(self, *, timeout: float = 5.0) -> None: + try: + self.cancel_safe(timeout=timeout) + except Exception as ex: + logger.warning("query cancellation failed: %s", ex) + + @contextmanager + def transaction( + self, savepoint_name: str | None = None, force_rollback: bool = False + ) -> Iterator[Transaction]: + """ + Start a context block with a new transaction or nested transaction. + + :param savepoint_name: Name of the savepoint used to manage a nested + transaction. If `!None`, one will be chosen automatically. + :param force_rollback: Roll back the transaction at the end of the + block even if there were no error (e.g. to try a no-op process). + :rtype: Transaction + """ + tx = Transaction(self, savepoint_name, force_rollback) + if self._pipeline: + with self.pipeline(), tx, self.pipeline(): + yield tx + else: + with tx: + yield tx + + def notifies( + self, *, timeout: float | None = None, stop_after: int | None = None + ) -> Generator[Notify, None, None]: + """ + Yield `Notify` objects as soon as they are received from the database. + + :param timeout: maximum amount of time to wait for notifications. + `!None` means no timeout. + :param stop_after: stop after receiving this number of notifications. + You might actually receive more than this number if more than one + notifications arrives in the same packet. + """ + # Allow interrupting the wait with a signal by reducing a long timeout + # into shorter intervals. + if timeout is not None: + deadline = monotonic() + timeout + interval = min(timeout, _WAIT_INTERVAL) + else: + deadline = None + interval = _WAIT_INTERVAL + + nreceived = 0 + + with self.lock: + enc = self.pgconn._encoding + while True: + try: + ns = self.wait(notifies(self.pgconn), interval=interval) + except e._NO_TRACEBACK as ex: + raise ex.with_traceback(None) + + # Emit the notifications received. + for pgn in ns: + n = Notify( + pgn.relname.decode(enc), pgn.extra.decode(enc), pgn.be_pid + ) + yield n + nreceived += 1 + + # Stop if we have received enough notifications. + if stop_after is not None and nreceived >= stop_after: + break + + # Check the deadline after the loop to ensure that timeout=0 + # polls at least once. + if deadline: + interval = min(_WAIT_INTERVAL, deadline - monotonic()) + if interval < 0.0: + break + + @contextmanager + def pipeline(self) -> Iterator[Pipeline]: + """Context manager to switch the connection into pipeline mode.""" + with self.lock: + self._check_connection_ok() + + pipeline = self._pipeline + if pipeline is None: + # WARNING: reference loop, broken ahead. + pipeline = self._pipeline = Pipeline(self) + + try: + with pipeline: + yield pipeline + finally: + if pipeline.level == 0: + with self.lock: + assert pipeline is self._pipeline + self._pipeline = None + + def wait(self, gen: PQGen[RV], interval: float | None = _WAIT_INTERVAL) -> RV: + """ + Consume a generator operating on the connection. + + The function must be used on generators that don't change connection + fd (i.e. not on connect and reset). + """ + try: + return waiting.wait(gen, self.pgconn.socket, interval=interval) + except _INTERRUPTED: + if self.pgconn.transaction_status == ACTIVE: + # On Ctrl-C, try to cancel the query in the server, otherwise + # the connection will remain stuck in ACTIVE state. + self._try_cancel(timeout=5.0) + try: + waiting.wait(gen, self.pgconn.socket, interval=interval) + except e.QueryCanceled: + pass # as expected + raise + + def _set_autocommit(self, value: bool) -> None: + self.set_autocommit(value) + + def set_autocommit(self, value: bool) -> None: + """Method version of the `~Connection.autocommit` setter.""" + with self.lock: + self.wait(self._set_autocommit_gen(value)) + + def _set_isolation_level(self, value: IsolationLevel | None) -> None: + self.set_isolation_level(value) + + def set_isolation_level(self, value: IsolationLevel | None) -> None: + """Method version of the `~Connection.isolation_level` setter.""" + with self.lock: + self.wait(self._set_isolation_level_gen(value)) + + def _set_read_only(self, value: bool | None) -> None: + self.set_read_only(value) + + def set_read_only(self, value: bool | None) -> None: + """Method version of the `~Connection.read_only` setter.""" + with self.lock: + self.wait(self._set_read_only_gen(value)) + + def _set_deferrable(self, value: bool | None) -> None: + self.set_deferrable(value) + + def set_deferrable(self, value: bool | None) -> None: + """Method version of the `~Connection.deferrable` setter.""" + with self.lock: + self.wait(self._set_deferrable_gen(value)) + + def tpc_begin(self, xid: Xid | str) -> None: + """ + Begin a TPC transaction with the given transaction ID `!xid`. + """ + with self.lock: + self.wait(self._tpc_begin_gen(xid)) + + def tpc_prepare(self) -> None: + """ + Perform the first phase of a transaction started with `tpc_begin()`. + """ + try: + with self.lock: + self.wait(self._tpc_prepare_gen()) + except e.ObjectNotInPrerequisiteState as ex: + raise e.NotSupportedError(str(ex)) from None + + def tpc_commit(self, xid: Xid | str | None = None) -> None: + """ + Commit a prepared two-phase transaction. + """ + with self.lock: + self.wait(self._tpc_finish_gen("COMMIT", xid)) + + def tpc_rollback(self, xid: Xid | str | None = None) -> None: + """ + Roll back a prepared two-phase transaction. + """ + with self.lock: + self.wait(self._tpc_finish_gen("ROLLBACK", xid)) + + def tpc_recover(self) -> list[Xid]: + self._check_tpc() + status = self.info.transaction_status + with self.cursor(row_factory=args_row(Xid._from_record)) as cur: + cur.execute(Xid._get_recover_query()) + res = cur.fetchall() + + if status == IDLE and self.info.transaction_status == INTRANS: + self.rollback() + + return res diff --git a/backend/.venv/Lib/site-packages/psycopg/connection_async.py b/backend/.venv/Lib/site-packages/psycopg/connection_async.py new file mode 100644 index 0000000..f82704e --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/connection_async.py @@ -0,0 +1,519 @@ +""" +Psycopg connection object (async version) +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import logging +from time import monotonic +from types import TracebackType +from typing import Any, AsyncGenerator, AsyncIterator, cast, overload, TYPE_CHECKING +from contextlib import asynccontextmanager + +from . import pq +from . import errors as e +from . import waiting +from .abc import AdaptContext, ConnDict, ConnParam, Params, PQGen, Query, RV +from ._tpc import Xid +from .rows import Row, AsyncRowFactory, tuple_row, args_row +from .adapt import AdaptersMap +from ._enums import IsolationLevel +from ._compat import Self +from .conninfo import make_conninfo, conninfo_to_dict +from .conninfo import conninfo_attempts_async, timeout_from_conninfo +from ._pipeline import AsyncPipeline +from .generators import notifies +from .transaction import AsyncTransaction +from .cursor_async import AsyncCursor +from ._capabilities import capabilities +from .server_cursor import AsyncServerCursor +from ._connection_base import BaseConnection, CursorRow, Notify + +if True: # ASYNC + import sys + import asyncio + from asyncio import Lock + from ._compat import to_thread +else: + from threading import Lock + +if TYPE_CHECKING: + from .pq.abc import PGconn + +_WAIT_INTERVAL = 0.1 + +TEXT = pq.Format.TEXT +BINARY = pq.Format.BINARY + +IDLE = pq.TransactionStatus.IDLE +ACTIVE = pq.TransactionStatus.ACTIVE +INTRANS = pq.TransactionStatus.INTRANS + +if True: # ASYNC + _INTERRUPTED = (asyncio.CancelledError, KeyboardInterrupt) +else: + _INTERRUPTED = KeyboardInterrupt + +logger = logging.getLogger("psycopg") + + +class AsyncConnection(BaseConnection[Row]): + """ + Wrapper for a connection to the database. + """ + + __module__ = "psycopg" + + cursor_factory: type[AsyncCursor[Row]] + server_cursor_factory: type[AsyncServerCursor[Row]] + row_factory: AsyncRowFactory[Row] + _pipeline: AsyncPipeline | None + + def __init__( + self, + pgconn: PGconn, + row_factory: AsyncRowFactory[Row] = cast(AsyncRowFactory[Row], tuple_row), + ): + super().__init__(pgconn) + self.row_factory = row_factory + self.lock = Lock() + self.cursor_factory = AsyncCursor + self.server_cursor_factory = AsyncServerCursor + + @classmethod + async def connect( + cls, + conninfo: str = "", + *, + autocommit: bool = False, + prepare_threshold: int | None = 5, + context: AdaptContext | None = None, + row_factory: AsyncRowFactory[Row] | None = None, + cursor_factory: type[AsyncCursor[Row]] | None = None, + **kwargs: ConnParam, + ) -> Self: + """ + Connect to a database server and return a new `AsyncConnection` instance. + """ + if True: # ASYNC + if sys.platform == "win32": + loop = asyncio.get_running_loop() + if isinstance(loop, asyncio.ProactorEventLoop): + raise e.InterfaceError( + "Psycopg cannot use the 'ProactorEventLoop' to run in async" + " mode. Please use a compatible event loop, for instance by" + " setting 'asyncio.set_event_loop_policy" + "(WindowsSelectorEventLoopPolicy())'" + ) + + params = await cls._get_connection_params(conninfo, **kwargs) + timeout = timeout_from_conninfo(params) + rv = None + attempts = await conninfo_attempts_async(params) + for attempt in attempts: + try: + conninfo = make_conninfo("", **attempt) + gen = cls._connect_gen(conninfo, timeout=timeout) + rv = await waiting.wait_conn_async(gen, interval=_WAIT_INTERVAL) + except e._NO_TRACEBACK as ex: + if len(attempts) > 1: + logger.debug( + "connection attempt failed: host: %r port: %r, hostaddr %r: %s", + attempt.get("host"), + attempt.get("port"), + attempt.get("hostaddr"), + str(ex), + ) + last_ex = ex + else: + break + + if not rv: + assert last_ex + raise last_ex.with_traceback(None) + + rv._autocommit = bool(autocommit) + if row_factory: + rv.row_factory = row_factory + if cursor_factory: + rv.cursor_factory = cursor_factory + if context: + rv._adapters = AdaptersMap(context.adapters) + rv.prepare_threshold = prepare_threshold + return rv + + async def __aenter__(self) -> Self: + return self + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + if self.closed: + return + + if exc_type: + # try to rollback, but if there are problems (connection in a bad + # state) just warn without clobbering the exception bubbling up. + try: + await self.rollback() + except Exception as exc2: + logger.warning("error ignored in rollback on %s: %s", self, exc2) + else: + await self.commit() + + # Close the connection only if it doesn't belong to a pool. + if not getattr(self, "_pool", None): + await self.close() + + @classmethod + async def _get_connection_params(cls, conninfo: str, **kwargs: Any) -> ConnDict: + """Manipulate connection parameters before connecting.""" + return conninfo_to_dict(conninfo, **kwargs) + + async def close(self) -> None: + """Close the database connection.""" + if self.closed: + return + self._closed = True + + # TODO: maybe send a cancel on close, if the connection is ACTIVE? + + self.pgconn.finish() + + @overload + def cursor(self, *, binary: bool = False) -> AsyncCursor[Row]: ... + + @overload + def cursor( + self, *, binary: bool = False, row_factory: AsyncRowFactory[CursorRow] + ) -> AsyncCursor[CursorRow]: ... + + @overload + def cursor( + self, + name: str, + *, + binary: bool = False, + scrollable: bool | None = None, + withhold: bool = False, + ) -> AsyncServerCursor[Row]: ... + + @overload + def cursor( + self, + name: str, + *, + binary: bool = False, + row_factory: AsyncRowFactory[CursorRow], + scrollable: bool | None = None, + withhold: bool = False, + ) -> AsyncServerCursor[CursorRow]: ... + + def cursor( + self, + name: str = "", + *, + binary: bool = False, + row_factory: AsyncRowFactory[Any] | None = None, + scrollable: bool | None = None, + withhold: bool = False, + ) -> AsyncCursor[Any] | AsyncServerCursor[Any]: + """ + Return a new `AsyncCursor` to send commands and queries to the connection. + """ + self._check_connection_ok() + + if not row_factory: + row_factory = self.row_factory + + cur: AsyncCursor[Any] | AsyncServerCursor[Any] + if name: + cur = self.server_cursor_factory( + self, + name=name, + row_factory=row_factory, + scrollable=scrollable, + withhold=withhold, + ) + else: + cur = self.cursor_factory(self, row_factory=row_factory) + + if binary: + cur.format = BINARY + + return cur + + async def execute( + self, + query: Query, + params: Params | None = None, + *, + prepare: bool | None = None, + binary: bool = False, + ) -> AsyncCursor[Row]: + """Execute a query and return a cursor to read its results.""" + try: + cur = self.cursor() + if binary: + cur.format = BINARY + + return await cur.execute(query, params, prepare=prepare) + + except e._NO_TRACEBACK as ex: + raise ex.with_traceback(None) + + async def commit(self) -> None: + """Commit any pending transaction to the database.""" + async with self.lock: + await self.wait(self._commit_gen()) + + async def rollback(self) -> None: + """Roll back to the start of any pending transaction.""" + async with self.lock: + await self.wait(self._rollback_gen()) + + async def cancel_safe(self, *, timeout: float = 30.0) -> None: + """Cancel the current operation on the connection. + + :param timeout: raise a `~errors.CancellationTimeout` if the + cancellation request does not succeed within `timeout` seconds. + + Note that a successful cancel attempt on the client is not a guarantee + that the server will successfully manage to cancel the operation. + + This is a non-blocking version of `~Connection.cancel()` which + leverages a more secure and improved cancellation feature of the libpq, + which is only available from version 17. + + If the underlying libpq is older than version 17, the method will fall + back to using the same implementation of `!cancel()`. + """ + if not self._should_cancel(): + return + + if capabilities.has_cancel_safe(): + await waiting.wait_conn_async( + self._cancel_gen(timeout=timeout), interval=_WAIT_INTERVAL + ) + else: + if True: # ASYNC + await to_thread(self.cancel) + else: + self.cancel() + + async def _try_cancel(self, *, timeout: float = 5.0) -> None: + try: + await self.cancel_safe(timeout=timeout) + except Exception as ex: + logger.warning("query cancellation failed: %s", ex) + + @asynccontextmanager + async def transaction( + self, savepoint_name: str | None = None, force_rollback: bool = False + ) -> AsyncIterator[AsyncTransaction]: + """ + Start a context block with a new transaction or nested transaction. + + :param savepoint_name: Name of the savepoint used to manage a nested + transaction. If `!None`, one will be chosen automatically. + :param force_rollback: Roll back the transaction at the end of the + block even if there were no error (e.g. to try a no-op process). + :rtype: AsyncTransaction + """ + tx = AsyncTransaction(self, savepoint_name, force_rollback) + if self._pipeline: + async with self.pipeline(), tx, self.pipeline(): + yield tx + else: + async with tx: + yield tx + + async def notifies( + self, *, timeout: float | None = None, stop_after: int | None = None + ) -> AsyncGenerator[Notify, None]: + """ + Yield `Notify` objects as soon as they are received from the database. + + :param timeout: maximum amount of time to wait for notifications. + `!None` means no timeout. + :param stop_after: stop after receiving this number of notifications. + You might actually receive more than this number if more than one + notifications arrives in the same packet. + """ + # Allow interrupting the wait with a signal by reducing a long timeout + # into shorter intervals. + if timeout is not None: + deadline = monotonic() + timeout + interval = min(timeout, _WAIT_INTERVAL) + else: + deadline = None + interval = _WAIT_INTERVAL + + nreceived = 0 + + async with self.lock: + enc = self.pgconn._encoding + while True: + try: + ns = await self.wait(notifies(self.pgconn), interval=interval) + except e._NO_TRACEBACK as ex: + raise ex.with_traceback(None) + + # Emit the notifications received. + for pgn in ns: + n = Notify( + pgn.relname.decode(enc), pgn.extra.decode(enc), pgn.be_pid + ) + yield n + nreceived += 1 + + # Stop if we have received enough notifications. + if stop_after is not None and nreceived >= stop_after: + break + + # Check the deadline after the loop to ensure that timeout=0 + # polls at least once. + if deadline: + interval = min(_WAIT_INTERVAL, deadline - monotonic()) + if interval < 0.0: + break + + @asynccontextmanager + async def pipeline(self) -> AsyncIterator[AsyncPipeline]: + """Context manager to switch the connection into pipeline mode.""" + async with self.lock: + self._check_connection_ok() + + pipeline = self._pipeline + if pipeline is None: + # WARNING: reference loop, broken ahead. + pipeline = self._pipeline = AsyncPipeline(self) + + try: + async with pipeline: + yield pipeline + finally: + if pipeline.level == 0: + async with self.lock: + assert pipeline is self._pipeline + self._pipeline = None + + async def wait(self, gen: PQGen[RV], interval: float | None = _WAIT_INTERVAL) -> RV: + """ + Consume a generator operating on the connection. + + The function must be used on generators that don't change connection + fd (i.e. not on connect and reset). + """ + try: + return await waiting.wait_async(gen, self.pgconn.socket, interval=interval) + except _INTERRUPTED: + if self.pgconn.transaction_status == ACTIVE: + # On Ctrl-C, try to cancel the query in the server, otherwise + # the connection will remain stuck in ACTIVE state. + await self._try_cancel(timeout=5.0) + try: + await waiting.wait_async(gen, self.pgconn.socket, interval=interval) + except e.QueryCanceled: + pass # as expected + raise + + def _set_autocommit(self, value: bool) -> None: + if True: # ASYNC + self._no_set_async("autocommit") + else: + self.set_autocommit(value) + + async def set_autocommit(self, value: bool) -> None: + """Method version of the `~Connection.autocommit` setter.""" + async with self.lock: + await self.wait(self._set_autocommit_gen(value)) + + def _set_isolation_level(self, value: IsolationLevel | None) -> None: + if True: # ASYNC + self._no_set_async("isolation_level") + else: + self.set_isolation_level(value) + + async def set_isolation_level(self, value: IsolationLevel | None) -> None: + """Method version of the `~Connection.isolation_level` setter.""" + async with self.lock: + await self.wait(self._set_isolation_level_gen(value)) + + def _set_read_only(self, value: bool | None) -> None: + if True: # ASYNC + self._no_set_async("read_only") + else: + self.set_read_only(value) + + async def set_read_only(self, value: bool | None) -> None: + """Method version of the `~Connection.read_only` setter.""" + async with self.lock: + await self.wait(self._set_read_only_gen(value)) + + def _set_deferrable(self, value: bool | None) -> None: + if True: # ASYNC + self._no_set_async("deferrable") + else: + self.set_deferrable(value) + + async def set_deferrable(self, value: bool | None) -> None: + """Method version of the `~Connection.deferrable` setter.""" + async with self.lock: + await self.wait(self._set_deferrable_gen(value)) + + if True: # ASYNC + + def _no_set_async(self, attribute: str) -> None: + raise AttributeError( + f"'the {attribute!r} property is read-only on async connections:" + f" please use 'await .set_{attribute}()' instead." + ) + + async def tpc_begin(self, xid: Xid | str) -> None: + """ + Begin a TPC transaction with the given transaction ID `!xid`. + """ + async with self.lock: + await self.wait(self._tpc_begin_gen(xid)) + + async def tpc_prepare(self) -> None: + """ + Perform the first phase of a transaction started with `tpc_begin()`. + """ + try: + async with self.lock: + await self.wait(self._tpc_prepare_gen()) + except e.ObjectNotInPrerequisiteState as ex: + raise e.NotSupportedError(str(ex)) from None + + async def tpc_commit(self, xid: Xid | str | None = None) -> None: + """ + Commit a prepared two-phase transaction. + """ + async with self.lock: + await self.wait(self._tpc_finish_gen("COMMIT", xid)) + + async def tpc_rollback(self, xid: Xid | str | None = None) -> None: + """ + Roll back a prepared two-phase transaction. + """ + async with self.lock: + await self.wait(self._tpc_finish_gen("ROLLBACK", xid)) + + async def tpc_recover(self) -> list[Xid]: + self._check_tpc() + status = self.info.transaction_status + async with self.cursor(row_factory=args_row(Xid._from_record)) as cur: + await cur.execute(Xid._get_recover_query()) + res = await cur.fetchall() + + if status == IDLE and self.info.transaction_status == INTRANS: + await self.rollback() + + return res diff --git a/backend/.venv/Lib/site-packages/psycopg/conninfo.py b/backend/.venv/Lib/site-packages/psycopg/conninfo.py new file mode 100644 index 0000000..f40b58a --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/conninfo.py @@ -0,0 +1,154 @@ +""" +Functions to manipulate conninfo strings +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import re + +from . import pq +from . import errors as e +from . import _conninfo_utils +from . import _conninfo_attempts +from . import _conninfo_attempts_async +from .abc import ConnParam, ConnDict + +# re-exoprts +conninfo_attempts = _conninfo_attempts.conninfo_attempts +conninfo_attempts_async = _conninfo_attempts_async.conninfo_attempts_async + +# Default timeout for connection a attempt. +# Arbitrary timeout, what applied by the libpq on my computer. +# Your mileage won't vary. +_DEFAULT_CONNECT_TIMEOUT = 130 + + +def make_conninfo(conninfo: str = "", **kwargs: ConnParam) -> str: + """ + Merge a string and keyword params into a single conninfo string. + + :param conninfo: A `connection string`__ as accepted by PostgreSQL. + :param kwargs: Parameters overriding the ones specified in `!conninfo`. + :return: A connection string valid for PostgreSQL, with the `!kwargs` + parameters merged. + + Raise `~psycopg.ProgrammingError` if the input doesn't make a valid + conninfo string. + + .. __: https://www.postgresql.org/docs/current/libpq-connect.html + #LIBPQ-CONNSTRING + """ + if not conninfo and not kwargs: + return "" + + # If no kwarg specified don't mung the conninfo but check if it's correct. + # Make sure to return a string, not a subtype, to avoid making Liskov sad. + if not kwargs: + _parse_conninfo(conninfo) + return str(conninfo) + + # Override the conninfo with the parameters + # Drop the None arguments + kwargs = {k: v for (k, v) in kwargs.items() if v is not None} + + if conninfo: + tmp = conninfo_to_dict(conninfo) + tmp.update(kwargs) + kwargs = tmp + + conninfo = " ".join(f"{k}={_param_escape(str(v))}" for (k, v) in kwargs.items()) + + # Verify the result is valid + _parse_conninfo(conninfo) + + return conninfo + + +def conninfo_to_dict(conninfo: str = "", **kwargs: ConnParam) -> ConnDict: + """ + Convert the `!conninfo` string into a dictionary of parameters. + + :param conninfo: A `connection string`__ as accepted by PostgreSQL. + :param kwargs: Parameters overriding the ones specified in `!conninfo`. + :return: Dictionary with the parameters parsed from `!conninfo` and + `!kwargs`. + + Raise `~psycopg.ProgrammingError` if `!conninfo` is not a a valid connection + string. + + .. __: https://www.postgresql.org/docs/current/libpq-connect.html + #LIBPQ-CONNSTRING + """ + opts = _parse_conninfo(conninfo) + rv: ConnDict = { + opt.keyword.decode(): opt.val.decode() for opt in opts if opt.val is not None + } + for k, v in kwargs.items(): + if v is not None: + rv[k] = v + return rv + + +def _parse_conninfo(conninfo: str) -> list[pq.ConninfoOption]: + """ + Verify that `!conninfo` is a valid connection string. + + Raise ProgrammingError if the string is not valid. + + Return the result of pq.Conninfo.parse() on success. + """ + try: + return pq.Conninfo.parse(conninfo.encode()) + except e.OperationalError as ex: + raise e.ProgrammingError(str(ex)) from None + + +re_escape = re.compile(r"([\\'])") +re_space = re.compile(r"\s") + + +def _param_escape(s: str) -> str: + """ + Apply the escaping rule required by PQconnectdb + """ + if not s: + return "''" + + s = re_escape.sub(r"\\\1", s) + if re_space.search(s): + s = "'" + s + "'" + + return s + + +def timeout_from_conninfo(params: ConnDict) -> int: + """ + Return the timeout in seconds from the connection parameters. + """ + # Follow the libpq convention: + # + # - 0 or less means no timeout (but we will use a default to simulate + # the socket timeout) + # - at least 2 seconds. + # + # See connectDBComplete in fe-connect.c + value: str | int | None = _conninfo_utils.get_param(params, "connect_timeout") + if value is None: + value = _DEFAULT_CONNECT_TIMEOUT + try: + timeout = int(float(value)) + except ValueError: + raise e.ProgrammingError(f"bad value for connect_timeout: {value!r}") from None + + if timeout <= 0: + # The sync connect function will stop on the default socket timeout + # Because in async connection mode we need to enforce the timeout + # ourselves, we need a finite value. + timeout = _DEFAULT_CONNECT_TIMEOUT + elif timeout < 2: + # Enforce a 2s min + timeout = 2 + + return timeout diff --git a/backend/.venv/Lib/site-packages/psycopg/copy.py b/backend/.venv/Lib/site-packages/psycopg/copy.py new file mode 100644 index 0000000..b43d25c --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/copy.py @@ -0,0 +1,35 @@ +""" +Module gathering the various parts of the copy subsystem. +""" + +from typing import IO + +from .abc import Buffer +from . import _copy, _copy_async + +# re-exports + +AsyncCopy = _copy_async.AsyncCopy +AsyncWriter = _copy_async.AsyncWriter +AsyncLibpqWriter = _copy_async.AsyncLibpqWriter +AsyncQueuedLibpqWriter = _copy_async.AsyncQueuedLibpqWriter + +Copy = _copy.Copy +Writer = _copy.Writer +LibpqWriter = _copy.LibpqWriter +QueuedLibpqWriter = _copy.QueuedLibpqWriter + + +class FileWriter(Writer): + """ + A `Writer` to write copy data to a file-like object. + + :param file: the file where to write copy data. It must be open for writing + in binary mode. + """ + + def __init__(self, file: IO[bytes]): + self.file = file + + def write(self, data: Buffer) -> None: + self.file.write(data) diff --git a/backend/.venv/Lib/site-packages/psycopg/crdb/__init__.py b/backend/.venv/Lib/site-packages/psycopg/crdb/__init__.py new file mode 100644 index 0000000..11e1dc3 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/crdb/__init__.py @@ -0,0 +1,20 @@ +""" +CockroachDB support package. +""" + +# Copyright (C) 2022 The Psycopg Team + +from . import _types +from .connection import CrdbConnection, AsyncCrdbConnection, CrdbConnectionInfo + +adapters = _types.adapters # exposed by the package +connect = CrdbConnection.connect + +_types.register_crdb_types(adapters.types) +_types.register_crdb_adapters(adapters) + +__all__ = [ + "AsyncCrdbConnection", + "CrdbConnection", + "CrdbConnectionInfo", +] diff --git a/backend/.venv/Lib/site-packages/psycopg/crdb/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/crdb/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fae9b690fc2dd5258569d2b277151aec83fb2c47 GIT binary patch literal 693 zcmZ8dJ#Q015S_g{-&vP9A~8hBl94-PBs(oa#1WVV36X~Cbkgd)w>amI-P7(l=u(-I z0#OnwBs#v^f^9^LS}oD2nz$iajA4LM0uF0w`% zkzv%QZU38bZX)I4EKjLy+G?XK;$D|CMoE@%rmFX3&d7hot;_r&d&--(C}}U@nB?m8 zxLHvi#xW-tD-dR>$|rw~7mag?=~m?^j?#<@sk~*AstVdqq^@D2XIf0CO7lV0_T{@m zjBzv?Vf-F0v@84$x_827TnwfDG7Z@vldXslK4DqH`Ypl*4SRYSl*M8Dkg~(@QPK-# zlF`<3M>0%hPI%hiF+=QNoUkOrxSi&ze0R*_$%uADRX=4mDWB-{-9`xguq@>KS_gFP z3+&He|9oxp)!vJ}Y5B~*e(E=7eq-vLLv8AwLTv`MkR6qR-Zxr_}~O? O{&bu*>$xX3wecUtsj*Z5 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/crdb/__pycache__/_types.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/crdb/__pycache__/_types.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e0d05fee0d6f8f5a641d46bc72824edee160450b GIT binary patch literal 9477 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/crdb/__pycache__/connection.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/crdb/__pycache__/connection.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ea27357e41850595532355eff62f39b01c9960c9 GIT binary patch literal 4774 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/crdb/_types.py b/backend/.venv/Lib/site-packages/psycopg/crdb/_types.py new file mode 100644 index 0000000..2b07fbe --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/crdb/_types.py @@ -0,0 +1,201 @@ +""" +Types configuration specific for CockroachDB. +""" + +# Copyright (C) 2022 The Psycopg Team + +from enum import Enum +from .._typeinfo import TypeInfo, TypesRegistry + +from ..abc import AdaptContext, NoneType +from .._oids import TEXT_OID +from .._typemod import BitTypeModifier, CharTypeModifier, NumericTypeModifier +from .._typemod import TimeTypeModifier +from .._adapters_map import AdaptersMap +from ..types.enum import EnumDumper, EnumBinaryDumper +from ..types.none import NoneDumper + +types = TypesRegistry() + +# Global adapter maps with PostgreSQL types configuration +adapters = AdaptersMap(types=types) + + +class CrdbEnumDumper(EnumDumper): + oid = TEXT_OID + + +class CrdbEnumBinaryDumper(EnumBinaryDumper): + oid = TEXT_OID + + +class CrdbNoneDumper(NoneDumper): + oid = TEXT_OID + + +def register_crdb_adapters(context: AdaptContext) -> None: + from .. import dbapi20 + from ..types import array + + _register_postgres_adapters(context) + + # String must come after enum and none to map text oid -> string dumper + _register_crdb_none_adapters(context) + _register_crdb_enum_adapters(context) + _register_crdb_string_adapters(context) + _register_crdb_json_adapters(context) + _register_crdb_net_adapters(context) + + dbapi20.register_dbapi20_adapters(adapters) + + array.register_all_arrays(adapters) + + +def _register_postgres_adapters(context: AdaptContext) -> None: + # Same adapters used by PostgreSQL, or a good starting point for customization + + from ..types import array, bool, composite, datetime + from ..types import numeric, numpy, string, uuid + + array.register_default_adapters(context) + composite.register_default_adapters(context) + datetime.register_default_adapters(context) + string.register_default_adapters(context) + uuid.register_default_adapters(context) + + # Both numpy Decimal and uint64 dumpers use the numeric oid, but the former + # covers the entire numeric domain, whereas the latter only deals with + # integers. For this reason, if we specify dumpers by oid, we want to make + # sure to get the Decimal dumper. We enforce that by registering the + # numeric dumpers last. + numpy.register_default_adapters(context) + bool.register_default_adapters(context) + numeric.register_default_adapters(context) + + +def _register_crdb_string_adapters(context: AdaptContext) -> None: + from ..types import string + + # Dump strings with text oid instead of unknown. + # Unlike PostgreSQL, CRDB seems able to cast text to most types. + context.adapters.register_dumper(str, string.StrDumper) + context.adapters.register_dumper(str, string.StrBinaryDumper) + + +def _register_crdb_enum_adapters(context: AdaptContext) -> None: + context.adapters.register_dumper(Enum, CrdbEnumBinaryDumper) + context.adapters.register_dumper(Enum, CrdbEnumDumper) + + +def _register_crdb_json_adapters(context: AdaptContext) -> None: + from ..types import json + + adapters = context.adapters + + # CRDB doesn't have json/jsonb: both names map to the jsonb oid + adapters.register_dumper(json.Json, json.JsonbBinaryDumper) + adapters.register_dumper(json.Json, json.JsonbDumper) + + adapters.register_dumper(json.Jsonb, json.JsonbBinaryDumper) + adapters.register_dumper(json.Jsonb, json.JsonbDumper) + + adapters.register_loader("json", json.JsonLoader) + adapters.register_loader("jsonb", json.JsonbLoader) + adapters.register_loader("json", json.JsonBinaryLoader) + adapters.register_loader("jsonb", json.JsonbBinaryLoader) + + +def _register_crdb_net_adapters(context: AdaptContext) -> None: + from ..types import net + + adapters = context.adapters + + adapters.register_dumper("ipaddress.IPv4Address", net.InterfaceDumper) + adapters.register_dumper("ipaddress.IPv6Address", net.InterfaceDumper) + adapters.register_dumper("ipaddress.IPv4Interface", net.InterfaceDumper) + adapters.register_dumper("ipaddress.IPv6Interface", net.InterfaceDumper) + adapters.register_dumper("ipaddress.IPv4Address", net.AddressBinaryDumper) + adapters.register_dumper("ipaddress.IPv6Address", net.AddressBinaryDumper) + adapters.register_dumper("ipaddress.IPv4Interface", net.InterfaceBinaryDumper) + adapters.register_dumper("ipaddress.IPv6Interface", net.InterfaceBinaryDumper) + adapters.register_dumper(None, net.InetBinaryDumper) + adapters.register_loader("inet", net.InetLoader) + adapters.register_loader("inet", net.InetBinaryLoader) + + +def _register_crdb_none_adapters(context: AdaptContext) -> None: + context.adapters.register_dumper(NoneType, CrdbNoneDumper) + + +def register_crdb_types(types: TypesRegistry) -> None: + for t in [ + TypeInfo("json", 3802, 3807, regtype="jsonb"), # Alias json -> jsonb. + TypeInfo("int8", 20, 1016, regtype="integer"), # Alias integer -> int8 + TypeInfo('"char"', 18, 1002), # special case, not generated + # autogenerated: start + # Generated from CockroachDB 23.1.10 + TypeInfo("bit", 1560, 1561, typemod=BitTypeModifier), + TypeInfo("bool", 16, 1000, regtype="boolean"), + TypeInfo("bpchar", 1042, 1014, regtype="character", typemod=CharTypeModifier), + TypeInfo("bytea", 17, 1001), + TypeInfo("date", 1082, 1182), + TypeInfo("float4", 700, 1021, regtype="real"), + TypeInfo("float8", 701, 1022, regtype="double precision"), + TypeInfo("inet", 869, 1041), + TypeInfo("int2", 21, 1005, regtype="smallint"), + TypeInfo("int2vector", 22, 1006), + TypeInfo("int4", 23, 1007), + TypeInfo("int8", 20, 1016, regtype="bigint"), + TypeInfo("interval", 1186, 1187, typemod=TimeTypeModifier), + TypeInfo("jsonb", 3802, 3807), + TypeInfo("name", 19, 1003), + TypeInfo("numeric", 1700, 1231, typemod=NumericTypeModifier), + TypeInfo("oid", 26, 1028), + TypeInfo("oidvector", 30, 1013), + TypeInfo("record", 2249, 2287), + TypeInfo("regclass", 2205, 2210), + TypeInfo("regnamespace", 4089, 4090), + TypeInfo("regproc", 24, 1008), + TypeInfo("regprocedure", 2202, 2207), + TypeInfo("regrole", 4096, 4097), + TypeInfo("regtype", 2206, 2211), + TypeInfo("text", 25, 1009), + TypeInfo( + "time", + 1083, + 1183, + regtype="time without time zone", + typemod=TimeTypeModifier, + ), + TypeInfo( + "timestamp", + 1114, + 1115, + regtype="timestamp without time zone", + typemod=TimeTypeModifier, + ), + TypeInfo( + "timestamptz", + 1184, + 1185, + regtype="timestamp with time zone", + typemod=TimeTypeModifier, + ), + TypeInfo( + "timetz", + 1266, + 1270, + regtype="time with time zone", + typemod=TimeTypeModifier, + ), + TypeInfo("tsquery", 3615, 3645), + TypeInfo("tsvector", 3614, 3643), + TypeInfo("unknown", 705, 0), + TypeInfo("uuid", 2950, 2951), + TypeInfo("varbit", 1562, 1563, regtype="bit varying", typemod=BitTypeModifier), + TypeInfo( + "varchar", 1043, 1015, regtype="character varying", typemod=CharTypeModifier + ), + # autogenerated: end + ]: + types.add(t) diff --git a/backend/.venv/Lib/site-packages/psycopg/crdb/connection.py b/backend/.venv/Lib/site-packages/psycopg/crdb/connection.py new file mode 100644 index 0000000..9ca1c64 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/crdb/connection.py @@ -0,0 +1,105 @@ +""" +CockroachDB-specific connections. +""" + +# Copyright (C) 2022 The Psycopg Team + +from __future__ import annotations + +import re +from typing import Any, TYPE_CHECKING + +from .. import errors as e +from ..rows import Row +from ..connection import Connection +from .._adapters_map import AdaptersMap +from .._connection_info import ConnectionInfo +from ..connection_async import AsyncConnection +from ._types import adapters + +if TYPE_CHECKING: + from ..pq.abc import PGconn + + +class _CrdbConnectionMixin: + _adapters: AdaptersMap | None + pgconn: PGconn + + @classmethod + def is_crdb(cls, conn: Connection[Any] | AsyncConnection[Any] | PGconn) -> bool: + """ + Return `!True` if the server connected to `!conn` is CockroachDB. + """ + if isinstance(conn, (Connection, AsyncConnection)): + conn = conn.pgconn + + return bool(conn.parameter_status(b"crdb_version")) + + @property + def adapters(self) -> AdaptersMap: + if not self._adapters: + # By default, use CockroachDB adapters map + self._adapters = AdaptersMap(adapters) + + return self._adapters + + @property + def info(self) -> CrdbConnectionInfo: + return CrdbConnectionInfo(self.pgconn) + + def _check_tpc(self) -> None: + if self.is_crdb(self.pgconn): + raise e.NotSupportedError("CockroachDB doesn't support prepared statements") + + +class CrdbConnection(_CrdbConnectionMixin, Connection[Row]): + """ + Wrapper for a connection to a CockroachDB database. + """ + + __module__ = "psycopg.crdb" + + +class AsyncCrdbConnection(_CrdbConnectionMixin, AsyncConnection[Row]): + """ + Wrapper for an async connection to a CockroachDB database. + """ + + __module__ = "psycopg.crdb" + + +class CrdbConnectionInfo(ConnectionInfo): + """ + `~psycopg.ConnectionInfo` subclass to get info about a CockroachDB database. + """ + + __module__ = "psycopg.crdb" + + @property + def vendor(self) -> str: + return "CockroachDB" + + @property + def server_version(self) -> int: + """ + Return the CockroachDB server version connected. + + Return a number in the PostgreSQL format (e.g. 21.2.10 -> 210210). + """ + sver = self.parameter_status("crdb_version") + if not sver: + raise e.InternalError("'crdb_version' parameter status not set") + + ver = self.parse_crdb_version(sver) + if ver is None: + raise e.InterfaceError(f"couldn't parse CockroachDB version from: {sver!r}") + + return ver + + @classmethod + def parse_crdb_version(self, sver: str) -> int | None: + m = re.search(r"\bv(\d+)\.(\d+)\.(\d+)", sver) + if not m: + return None + + return int(m.group(1)) * 10000 + int(m.group(2)) * 100 + int(m.group(3)) diff --git a/backend/.venv/Lib/site-packages/psycopg/cursor.py b/backend/.venv/Lib/site-packages/psycopg/cursor.py new file mode 100644 index 0000000..0415ff3 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/cursor.py @@ -0,0 +1,288 @@ +# WARNING: this file is auto-generated by 'async_to_sync.py' +# from the original file 'cursor_async.py' +# DO NOT CHANGE! Change the original file instead. +""" +Psycopg Cursor object. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +from types import TracebackType +from typing import Any, Iterator, Iterable, TYPE_CHECKING, overload +from contextlib import contextmanager + +from . import pq +from . import errors as e +from .abc import Query, Params +from .copy import Copy, Writer +from .rows import Row, RowMaker, RowFactory +from ._compat import Self +from ._pipeline import Pipeline +from ._cursor_base import BaseCursor + +if TYPE_CHECKING: + from .connection import Connection + +ACTIVE = pq.TransactionStatus.ACTIVE + + +class Cursor(BaseCursor["Connection[Any]", Row]): + __module__ = "psycopg" + __slots__ = () + + @overload + def __init__(self, connection: Connection[Row]): ... + + @overload + def __init__( + self, connection: Connection[Any], *, row_factory: RowFactory[Row] + ): ... + + def __init__( + self, connection: Connection[Any], *, row_factory: RowFactory[Row] | None = None + ): + super().__init__(connection) + self._row_factory = row_factory or connection.row_factory + + def __enter__(self) -> Self: + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self.close() + + def close(self) -> None: + """ + Close the current cursor and free associated resources. + """ + self._close() + + @property + def row_factory(self) -> RowFactory[Row]: + """Writable attribute to control how result rows are formed.""" + return self._row_factory + + @row_factory.setter + def row_factory(self, row_factory: RowFactory[Row]) -> None: + self._row_factory = row_factory + if self.pgresult: + self._make_row = row_factory(self) + + def _make_row_maker(self) -> RowMaker[Row]: + return self._row_factory(self) + + def execute( + self, + query: Query, + params: Params | None = None, + *, + prepare: bool | None = None, + binary: bool | None = None, + ) -> Self: + """ + Execute a query or command to the database. + """ + try: + with self._conn.lock: + self._conn.wait( + self._execute_gen(query, params, prepare=prepare, binary=binary) + ) + except e._NO_TRACEBACK as ex: + raise ex.with_traceback(None) + return self + + def executemany( + self, query: Query, params_seq: Iterable[Params], *, returning: bool = False + ) -> None: + """ + Execute the same command with a sequence of input data. + """ + try: + if Pipeline.is_supported(): + # If there is already a pipeline, ride it, in order to avoid + # sending unnecessary Sync. + with self._conn.lock: + p = self._conn._pipeline + if p: + self._conn.wait( + self._executemany_gen_pipeline(query, params_seq, returning) + ) + # Otherwise, make a new one + if not p: + with self._conn.pipeline(), self._conn.lock: + self._conn.wait( + self._executemany_gen_pipeline(query, params_seq, returning) + ) + else: + with self._conn.lock: + self._conn.wait( + self._executemany_gen_no_pipeline(query, params_seq, returning) + ) + except e._NO_TRACEBACK as ex: + raise ex.with_traceback(None) + + def stream( + self, + query: Query, + params: Params | None = None, + *, + binary: bool | None = None, + size: int = 1, + ) -> Iterator[Row]: + """ + Iterate row-by-row on a result from the database. + + :param size: if greater than 1, results will be retrieved by chunks of + this size from the server (but still yielded row-by-row); this is only + available from version 17 of the libpq. + """ + if self._pgconn.pipeline_status: + raise e.ProgrammingError("stream() cannot be used in pipeline mode") + + with self._conn.lock: + try: + self._conn.wait( + self._stream_send_gen(query, params, binary=binary, size=size) + ) + first = True + while self._conn.wait(self._stream_fetchone_gen(first)): + for pos in range(size): + rec = self._tx.load_row(pos, self._make_row) + if rec is None: + break + yield rec + first = False + except e._NO_TRACEBACK as ex: + raise ex.with_traceback(None) + finally: + if self._pgconn.transaction_status == ACTIVE: + # Try to cancel the query, then consume the results + # already received. + self._conn._try_cancel() + try: + while self._conn.wait(self._stream_fetchone_gen(first=False)): + pass + except Exception: + pass + + # Try to get out of ACTIVE state. Just do a single attempt, which + # should work to recover from an error or query cancelled. + try: + self._conn.wait(self._stream_fetchone_gen(first=False)) + except Exception: + pass + + def fetchone(self) -> Row | None: + """ + Return the next record from the current recordset. + + Return `!None` the recordset is finished. + + :rtype: Row | None, with Row defined by `row_factory` + """ + self._fetch_pipeline() + self._check_result_for_fetch() + record = self._tx.load_row(self._pos, self._make_row) + if record is not None: + self._pos += 1 + return record + + def fetchmany(self, size: int = 0) -> list[Row]: + """ + Return the next `!size` records from the current recordset. + + `!size` default to `!self.arraysize` if not specified. + + :rtype: Sequence[Row], with Row defined by `row_factory` + """ + self._fetch_pipeline() + self._check_result_for_fetch() + assert self.pgresult + + if not size: + size = self.arraysize + records = self._tx.load_rows( + self._pos, min(self._pos + size, self.pgresult.ntuples), self._make_row + ) + self._pos += len(records) + return records + + def fetchall(self) -> list[Row]: + """ + Return all the remaining records from the current recordset. + + :rtype: Sequence[Row], with Row defined by `row_factory` + """ + self._fetch_pipeline() + self._check_result_for_fetch() + assert self.pgresult + records = self._tx.load_rows(self._pos, self.pgresult.ntuples, self._make_row) + self._pos = self.pgresult.ntuples + return records + + def __iter__(self) -> Iterator[Row]: + self._fetch_pipeline() + self._check_result_for_fetch() + + def load(pos: int) -> Row | None: + return self._tx.load_row(pos, self._make_row) + + while True: + row = load(self._pos) + if row is None: + break + self._pos += 1 + yield row + + def scroll(self, value: int, mode: str = "relative") -> None: + """ + Move the cursor in the result set to a new position according to mode. + + If `!mode` is ``'relative'`` (default), `!value` is taken as offset to + the current position in the result set; if set to ``'absolute'``, + `!value` states an absolute target position. + + Raise `!IndexError` in case a scroll operation would leave the result + set. In this case the position will not change. + """ + self._fetch_pipeline() + self._scroll(value, mode) + + @contextmanager + def copy( + self, + statement: Query, + params: Params | None = None, + *, + writer: Writer | None = None, + ) -> Iterator[Copy]: + """ + Initiate a :sql:`COPY` operation and return an object to manage it. + """ + try: + with self._conn.lock: + self._conn.wait(self._start_copy_gen(statement, params)) + + with Copy(self, writer=writer) as copy: + yield copy + except e._NO_TRACEBACK as ex: + raise ex.with_traceback(None) + + # If a fresher result has been set on the cursor by the Copy object, + # read its properties (especially rowcount). + self._select_current_result(0) + + def _fetch_pipeline(self) -> None: + if ( + self._execmany_returning is not False + and (not self.pgresult) + and self._conn._pipeline + ): + with self._conn.lock: + self._conn.wait(self._conn._pipeline._fetch_gen(flush=True)) diff --git a/backend/.venv/Lib/site-packages/psycopg/cursor_async.py b/backend/.venv/Lib/site-packages/psycopg/cursor_async.py new file mode 100644 index 0000000..7fddd62 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/cursor_async.py @@ -0,0 +1,298 @@ +""" +Psycopg AsyncCursor object. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +from types import TracebackType +from typing import Any, AsyncIterator, Iterable, TYPE_CHECKING, overload +from contextlib import asynccontextmanager + +from . import pq +from . import errors as e +from .abc import Query, Params +from .copy import AsyncCopy, AsyncWriter +from .rows import Row, RowMaker, AsyncRowFactory +from ._compat import Self +from ._pipeline import Pipeline +from ._cursor_base import BaseCursor + +if TYPE_CHECKING: + from .connection_async import AsyncConnection + +ACTIVE = pq.TransactionStatus.ACTIVE + + +class AsyncCursor(BaseCursor["AsyncConnection[Any]", Row]): + __module__ = "psycopg" + __slots__ = () + + @overload + def __init__(self, connection: AsyncConnection[Row]): ... + + @overload + def __init__( + self, connection: AsyncConnection[Any], *, row_factory: AsyncRowFactory[Row] + ): ... + + def __init__( + self, + connection: AsyncConnection[Any], + *, + row_factory: AsyncRowFactory[Row] | None = None, + ): + super().__init__(connection) + self._row_factory = row_factory or connection.row_factory + + async def __aenter__(self) -> Self: + return self + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + await self.close() + + async def close(self) -> None: + """ + Close the current cursor and free associated resources. + """ + self._close() + + @property + def row_factory(self) -> AsyncRowFactory[Row]: + """Writable attribute to control how result rows are formed.""" + return self._row_factory + + @row_factory.setter + def row_factory(self, row_factory: AsyncRowFactory[Row]) -> None: + self._row_factory = row_factory + if self.pgresult: + self._make_row = row_factory(self) + + def _make_row_maker(self) -> RowMaker[Row]: + return self._row_factory(self) + + async def execute( + self, + query: Query, + params: Params | None = None, + *, + prepare: bool | None = None, + binary: bool | None = None, + ) -> Self: + """ + Execute a query or command to the database. + """ + try: + async with self._conn.lock: + await self._conn.wait( + self._execute_gen(query, params, prepare=prepare, binary=binary) + ) + except e._NO_TRACEBACK as ex: + raise ex.with_traceback(None) + return self + + async def executemany( + self, + query: Query, + params_seq: Iterable[Params], + *, + returning: bool = False, + ) -> None: + """ + Execute the same command with a sequence of input data. + """ + try: + if Pipeline.is_supported(): + # If there is already a pipeline, ride it, in order to avoid + # sending unnecessary Sync. + async with self._conn.lock: + p = self._conn._pipeline + if p: + await self._conn.wait( + self._executemany_gen_pipeline(query, params_seq, returning) + ) + # Otherwise, make a new one + if not p: + async with self._conn.pipeline(), self._conn.lock: + await self._conn.wait( + self._executemany_gen_pipeline(query, params_seq, returning) + ) + else: + async with self._conn.lock: + await self._conn.wait( + self._executemany_gen_no_pipeline(query, params_seq, returning) + ) + except e._NO_TRACEBACK as ex: + raise ex.with_traceback(None) + + async def stream( + self, + query: Query, + params: Params | None = None, + *, + binary: bool | None = None, + size: int = 1, + ) -> AsyncIterator[Row]: + """ + Iterate row-by-row on a result from the database. + + :param size: if greater than 1, results will be retrieved by chunks of + this size from the server (but still yielded row-by-row); this is only + available from version 17 of the libpq. + """ + if self._pgconn.pipeline_status: + raise e.ProgrammingError("stream() cannot be used in pipeline mode") + + async with self._conn.lock: + try: + await self._conn.wait( + self._stream_send_gen(query, params, binary=binary, size=size) + ) + first = True + while await self._conn.wait(self._stream_fetchone_gen(first)): + for pos in range(size): + rec = self._tx.load_row(pos, self._make_row) + if rec is None: + break + yield rec + first = False + + except e._NO_TRACEBACK as ex: + raise ex.with_traceback(None) + + finally: + if self._pgconn.transaction_status == ACTIVE: + # Try to cancel the query, then consume the results + # already received. + await self._conn._try_cancel() + try: + while await self._conn.wait( + self._stream_fetchone_gen(first=False) + ): + pass + except Exception: + pass + + # Try to get out of ACTIVE state. Just do a single attempt, which + # should work to recover from an error or query cancelled. + try: + await self._conn.wait(self._stream_fetchone_gen(first=False)) + except Exception: + pass + + async def fetchone(self) -> Row | None: + """ + Return the next record from the current recordset. + + Return `!None` the recordset is finished. + + :rtype: Row | None, with Row defined by `row_factory` + """ + await self._fetch_pipeline() + self._check_result_for_fetch() + record = self._tx.load_row(self._pos, self._make_row) + if record is not None: + self._pos += 1 + return record + + async def fetchmany(self, size: int = 0) -> list[Row]: + """ + Return the next `!size` records from the current recordset. + + `!size` default to `!self.arraysize` if not specified. + + :rtype: Sequence[Row], with Row defined by `row_factory` + """ + await self._fetch_pipeline() + self._check_result_for_fetch() + assert self.pgresult + + if not size: + size = self.arraysize + records = self._tx.load_rows( + self._pos, + min(self._pos + size, self.pgresult.ntuples), + self._make_row, + ) + self._pos += len(records) + return records + + async def fetchall(self) -> list[Row]: + """ + Return all the remaining records from the current recordset. + + :rtype: Sequence[Row], with Row defined by `row_factory` + """ + await self._fetch_pipeline() + self._check_result_for_fetch() + assert self.pgresult + records = self._tx.load_rows(self._pos, self.pgresult.ntuples, self._make_row) + self._pos = self.pgresult.ntuples + return records + + async def __aiter__(self) -> AsyncIterator[Row]: + await self._fetch_pipeline() + self._check_result_for_fetch() + + def load(pos: int) -> Row | None: + return self._tx.load_row(pos, self._make_row) + + while True: + row = load(self._pos) + if row is None: + break + self._pos += 1 + yield row + + async def scroll(self, value: int, mode: str = "relative") -> None: + """ + Move the cursor in the result set to a new position according to mode. + + If `!mode` is ``'relative'`` (default), `!value` is taken as offset to + the current position in the result set; if set to ``'absolute'``, + `!value` states an absolute target position. + + Raise `!IndexError` in case a scroll operation would leave the result + set. In this case the position will not change. + """ + await self._fetch_pipeline() + self._scroll(value, mode) + + @asynccontextmanager + async def copy( + self, + statement: Query, + params: Params | None = None, + *, + writer: AsyncWriter | None = None, + ) -> AsyncIterator[AsyncCopy]: + """ + Initiate a :sql:`COPY` operation and return an object to manage it. + """ + try: + async with self._conn.lock: + await self._conn.wait(self._start_copy_gen(statement, params)) + + async with AsyncCopy(self, writer=writer) as copy: + yield copy + except e._NO_TRACEBACK as ex: + raise ex.with_traceback(None) + + # If a fresher result has been set on the cursor by the Copy object, + # read its properties (especially rowcount). + self._select_current_result(0) + + async def _fetch_pipeline(self) -> None: + if ( + self._execmany_returning is not False + and not self.pgresult + and self._conn._pipeline + ): + async with self._conn.lock: + await self._conn.wait(self._conn._pipeline._fetch_gen(flush=True)) diff --git a/backend/.venv/Lib/site-packages/psycopg/dbapi20.py b/backend/.venv/Lib/site-packages/psycopg/dbapi20.py new file mode 100644 index 0000000..204e571 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/dbapi20.py @@ -0,0 +1,134 @@ +""" +Compatibility objects with DBAPI 2.0 +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import time +import datetime as dt +from math import floor +from typing import Any, Sequence + +from . import _oids +from .abc import AdaptContext, Buffer +from .types.string import BytesDumper, BytesBinaryDumper + + +class DBAPITypeObject: + def __init__(self, name: str, oids: Sequence[int]): + self.name = name + self.values = tuple(oids) + + def __repr__(self) -> str: + return f"psycopg.{self.name}" + + def __eq__(self, other: Any) -> bool: + if isinstance(other, int): + return other in self.values + else: + return NotImplemented + + def __ne__(self, other: Any) -> bool: + if isinstance(other, int): + return other not in self.values + else: + return NotImplemented + + +BINARY = DBAPITypeObject("BINARY", (_oids.BYTEA_OID,)) +DATETIME = DBAPITypeObject( + "DATETIME", + ( + _oids.TIMESTAMP_OID, + _oids.TIMESTAMPTZ_OID, + _oids.DATE_OID, + _oids.TIME_OID, + _oids.TIMETZ_OID, + _oids.INTERVAL_OID, + ), +) +NUMBER = DBAPITypeObject( + "NUMBER", + ( + _oids.INT2_OID, + _oids.INT4_OID, + _oids.INT8_OID, + _oids.FLOAT4_OID, + _oids.FLOAT8_OID, + _oids.NUMERIC_OID, + ), +) +ROWID = DBAPITypeObject("ROWID", (_oids.OID_OID,)) +STRING = DBAPITypeObject( + "STRING", (_oids.TEXT_OID, _oids.VARCHAR_OID, _oids.BPCHAR_OID) +) + + +class Binary: + def __init__(self, obj: Any): + self.obj = obj + + def __repr__(self) -> str: + sobj = repr(self.obj) + if len(sobj) > 40: + sobj = f"{sobj[:35]} ... ({len(sobj)} byteschars)" + return f"{self.__class__.__name__}({sobj})" + + +class BinaryBinaryDumper(BytesBinaryDumper): + def dump(self, obj: Buffer | Binary) -> Buffer | None: + if isinstance(obj, Binary): + return super().dump(obj.obj) + else: + return super().dump(obj) + + +class BinaryTextDumper(BytesDumper): + def dump(self, obj: Buffer | Binary) -> Buffer | None: + if isinstance(obj, Binary): + return super().dump(obj.obj) + else: + return super().dump(obj) + + +def Date(year: int, month: int, day: int) -> dt.date: + return dt.date(year, month, day) + + +def DateFromTicks(ticks: float) -> dt.date: + return TimestampFromTicks(ticks).date() + + +def Time(hour: int, minute: int, second: int) -> dt.time: + return dt.time(hour, minute, second) + + +def TimeFromTicks(ticks: float) -> dt.time: + return TimestampFromTicks(ticks).time() + + +def Timestamp( + year: int, month: int, day: int, hour: int, minute: int, second: int +) -> dt.datetime: + return dt.datetime(year, month, day, hour, minute, second) + + +def TimestampFromTicks(ticks: float) -> dt.datetime: + secs = floor(ticks) + frac = ticks - secs + t = time.localtime(ticks) + tzinfo = dt.timezone(dt.timedelta(seconds=t.tm_gmtoff)) + rv = dt.datetime(*t[:6], round(frac * 1_000_000), tzinfo=tzinfo) + return rv + + +def register_dbapi20_adapters(context: AdaptContext) -> None: + adapters = context.adapters + adapters.register_dumper(Binary, BinaryTextDumper) + adapters.register_dumper(Binary, BinaryBinaryDumper) + + # Make them also the default dumpers when dumping by bytea oid + adapters.register_dumper(None, BinaryTextDumper) + adapters.register_dumper(None, BinaryBinaryDumper) diff --git a/backend/.venv/Lib/site-packages/psycopg/errors.py b/backend/.venv/Lib/site-packages/psycopg/errors.py new file mode 100644 index 0000000..4be182e --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/errors.py @@ -0,0 +1,1759 @@ +""" +psycopg exceptions + +DBAPI-defined Exceptions are defined in the following hierarchy:: + + Exceptions + |__Warning + |__Error + |__InterfaceError + |__DatabaseError + |__DataError + |__OperationalError + |__IntegrityError + |__InternalError + |__ProgrammingError + |__NotSupportedError +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +from dataclasses import dataclass, field, fields +from typing import Any, Callable, NoReturn, Sequence, TYPE_CHECKING +from asyncio import CancelledError + +from .pq.abc import PGconn, PGresult +from .pq._enums import ConnStatus, DiagnosticField, PipelineStatus, TransactionStatus +from ._compat import TypeAlias, TypeGuard + +if TYPE_CHECKING: + from .pq.misc import PGnotify, ConninfoOption + +ErrorInfo: TypeAlias = "PGresult | dict[int, bytes | None] | None" + +_sqlcodes: dict[str, type[Error]] = {} + + +@dataclass +class FinishedPGconn: + """Finished libpq connection. + + Attributes are set from a real `~psycopg.pq.PGconn` but any operations will + raise an `~psycopg.OperationalError`. + """ + + info: list[ConninfoOption] = field(default_factory=list) + + db: bytes = b"" + user: bytes = b"" + password: bytes = b"" + host: bytes = b"" + hostaddr: bytes = b"" + port: bytes = b"" + tty: bytes = b"" + options: bytes = b"" + status: int = ConnStatus.BAD.value + transaction_status: int = TransactionStatus.UNKNOWN.value + pipeline_status: int = PipelineStatus.OFF.value + + error_message: bytes = b"" + _encoding: str = "utf-8" + server_version: int = 0 + + backend_pid: int = 0 + needs_password: bool = False + used_password: bool = False + ssl_in_use: bool = False + + nonblocking: int = 0 + + notice_handler: Callable[[PGresult], None] | None = None + notify_handler: Callable[[PGnotify], None] | None = None + + @staticmethod + def _raise() -> NoReturn: + raise OperationalError("the connection is closed") + + @classmethod + def connect(cls, *args: Any) -> NoReturn: + raise TypeError(f"{cls} is unusable") + + @classmethod + def connect_start(cls, *args: Any) -> NoReturn: + raise TypeError(f"{cls} is unusable") + + def connect_poll(self) -> NoReturn: + self._raise() + + def finish(self) -> None: + pass + + def reset(self) -> NoReturn: + self._raise() + + def get_error_message(self, encoding: str = "") -> str: + return "the connection is closed" + + def reset_start(self) -> NoReturn: + self._raise() + + def reset_poll(self) -> NoReturn: + self._raise() + + @classmethod + def ping(cls, *args: Any) -> NoReturn: + raise TypeError(f"{cls} is unusable") + + def parameter_status(self, *args: Any) -> NoReturn: + self._raise() + + @property + def socket(self) -> NoReturn: + self._raise() + + def exec_(self, *args: Any) -> NoReturn: + self._raise() + + def send_query(self, *args: Any) -> None: + self._raise() + + def exec_params(self, *args: Any) -> NoReturn: + self._raise() + + def send_query_params(self, *args: Any) -> NoReturn: + self._raise() + + def send_prepare(self, *args: Any) -> NoReturn: + self._raise() + + def send_query_prepared(self, *args: Any) -> NoReturn: + self._raise() + + def prepare(self, *args: Any) -> NoReturn: + self._raise() + + def exec_prepared(self, *args: Any) -> NoReturn: + self._raise() + + def describe_prepared(self, *args: Any) -> NoReturn: + self._raise() + + def send_describe_prepared(self, *args: Any) -> NoReturn: + self._raise() + + def describe_portal(self, *args: Any) -> NoReturn: + self._raise() + + def send_describe_portal(self, *args: Any) -> NoReturn: + self._raise() + + def close_prepared(self, *args: Any) -> NoReturn: + self._raise() + + def send_close_prepared(self, *args: Any) -> NoReturn: + self._raise() + + def close_portal(self, *args: Any) -> NoReturn: + self._raise() + + def send_close_portal(self, *args: Any) -> NoReturn: + self._raise() + + def get_result(self) -> NoReturn: + self._raise() + + def consume_input(self) -> NoReturn: + self._raise() + + def is_busy(self) -> NoReturn: + self._raise() + + def flush(self) -> NoReturn: + self._raise() + + def set_single_row_mode(self) -> NoReturn: + self._raise() + + def set_chunked_rows_mode(self, size: int) -> NoReturn: + self._raise() + + def cancel_conn(self) -> NoReturn: + self._raise() + + def get_cancel(self) -> NoReturn: + self._raise() + + def notifies(self) -> NoReturn: + self._raise() + + def put_copy_data(self, *args: Any) -> NoReturn: + self._raise() + + def put_copy_end(self, *args: Any) -> NoReturn: + self._raise() + + def get_copy_data(self, *args: Any) -> NoReturn: + self._raise() + + def trace(self, *args: Any) -> NoReturn: + self._raise() + + def set_trace_flags(self, *args: Any) -> NoReturn: + self._raise() + + def untrace(self) -> NoReturn: + self._raise() + + def encrypt_password(self, *args: Any) -> NoReturn: + self._raise() + + def change_password(self, *args: Any) -> NoReturn: + self._raise() + + def make_empty_result(self, *args: Any) -> NoReturn: + self._raise() + + def enter_pipeline_mode(self) -> NoReturn: + self._raise() + + def exit_pipeline_mode(self) -> NoReturn: + self._raise() + + def pipeline_sync(self) -> NoReturn: + self._raise() + + def send_flush_request(self) -> NoReturn: + self._raise() + + +def finish_pgconn(pgconn: PGconn) -> PGconn: + args = {} + for f in fields(FinishedPGconn): + try: + args[f.name] = getattr(pgconn, f.name) + except Exception: + pass + pgconn.finish() + return FinishedPGconn(**args) + + +class Warning(Exception): + """ + Exception raised for important warnings. + + Defined for DBAPI compatibility, but never raised by ``psycopg``. + """ + + __module__ = "psycopg" + + +class Error(Exception): + """ + Base exception for all the errors psycopg will raise. + + Exception that is the base class of all other error exceptions. You can + use this to catch all errors with one single `!except` statement. + + This exception is guaranteed to be picklable. + """ + + __module__ = "psycopg" + + sqlstate: str | None = None + + def __init__( + self, + *args: Sequence[Any], + info: ErrorInfo = None, + encoding: str = "utf-8", + pgconn: PGconn | None = None, + ): + super().__init__(*args) + self._info = info + self._encoding = encoding + self._pgconn = pgconn + + # Handle sqlstate codes for which we don't have a class. + if not self.sqlstate and info: + self.sqlstate = self.diag.sqlstate + + @property + def pgconn(self) -> PGconn | None: + """The connection object, if the error was raised from a connection attempt. + + :rtype: psycopg.pq.PGconn | None + """ + return self._pgconn if self._pgconn else None + + @property + def pgresult(self) -> PGresult | None: + """The result object, if the exception was raised after a failed query. + + :rtype: psycopg.pq.PGresult | None + """ + return self._info if _is_pgresult(self._info) else None + + @property + def diag(self) -> Diagnostic: + """ + A `Diagnostic` object to inspect details of the errors from the database. + """ + return Diagnostic(self._info, encoding=self._encoding) + + def __reduce__(self) -> str | tuple[Any, ...]: + res = super().__reduce__() + if isinstance(res, tuple) and len(res) >= 3: + # To make the exception picklable + res[2]["_info"] = _info_to_dict(self._info) + res[2]["_pgconn"] = None + + return res + + +class InterfaceError(Error): + """ + An error related to the database interface rather than the database itself. + """ + + __module__ = "psycopg" + + +class DatabaseError(Error): + """ + Exception raised for errors that are related to the database. + """ + + __module__ = "psycopg" + + def __init_subclass__(cls, code: str | None = None, name: str | None = None): + if code: + _sqlcodes[code] = cls + cls.sqlstate = code + if name: + _sqlcodes[name] = cls + + +class DataError(DatabaseError): + """ + An error caused by problems with the processed data. + + Examples may be division by zero, numeric value out of range, etc. + """ + + __module__ = "psycopg" + + +class OperationalError(DatabaseError): + """ + An error related to the database's operation. + + These errors are not necessarily under the control of the programmer, e.g. + an unexpected disconnect occurs, the data source name is not found, a + transaction could not be processed, a memory allocation error occurred + during processing, etc. + """ + + __module__ = "psycopg" + + +class IntegrityError(DatabaseError): + """ + An error caused when the relational integrity of the database is affected. + + An example may be a foreign key check failed. + """ + + __module__ = "psycopg" + + +class InternalError(DatabaseError): + """ + An error generated when the database encounters an internal error, + + Examples could be the cursor is not valid anymore, the transaction is out + of sync, etc. + """ + + __module__ = "psycopg" + + +class ProgrammingError(DatabaseError): + """ + Exception raised for programming errors + + Examples may be table not found or already exists, syntax error in the SQL + statement, wrong number of parameters specified, etc. + """ + + __module__ = "psycopg" + + +class NotSupportedError(DatabaseError): + """ + A method or database API was used which is not supported by the database. + """ + + __module__ = "psycopg" + + +class ConnectionTimeout(OperationalError): + """ + Exception raised on timeout of the `~psycopg.Connection.connect()` method. + + The error is raised if the ``connect_timeout`` is specified and a + connection is not obtained in useful time. + + Subclass of `~psycopg.OperationalError`. + """ + + +class CancellationTimeout(OperationalError): + """ + Exception raised on timeout of connection's + `~psycopg.Connection.cancel_safe()` method. + + Subclass of `~psycopg.OperationalError`. + """ + + +class PipelineAborted(OperationalError): + """ + Raised when a operation fails because the current pipeline is in aborted state. + + Subclass of `~psycopg.OperationalError`. + """ + + +class Diagnostic: + """Details from a database error report.""" + + def __init__(self, info: ErrorInfo, encoding: str = "utf-8"): + self._info = info + self._encoding = encoding + + @property + def severity(self) -> str | None: + return self._error_message(DiagnosticField.SEVERITY) + + @property + def severity_nonlocalized(self) -> str | None: + return self._error_message(DiagnosticField.SEVERITY_NONLOCALIZED) + + @property + def sqlstate(self) -> str | None: + return self._error_message(DiagnosticField.SQLSTATE) + + @property + def message_primary(self) -> str | None: + return self._error_message(DiagnosticField.MESSAGE_PRIMARY) + + @property + def message_detail(self) -> str | None: + return self._error_message(DiagnosticField.MESSAGE_DETAIL) + + @property + def message_hint(self) -> str | None: + return self._error_message(DiagnosticField.MESSAGE_HINT) + + @property + def statement_position(self) -> str | None: + return self._error_message(DiagnosticField.STATEMENT_POSITION) + + @property + def internal_position(self) -> str | None: + return self._error_message(DiagnosticField.INTERNAL_POSITION) + + @property + def internal_query(self) -> str | None: + return self._error_message(DiagnosticField.INTERNAL_QUERY) + + @property + def context(self) -> str | None: + return self._error_message(DiagnosticField.CONTEXT) + + @property + def schema_name(self) -> str | None: + return self._error_message(DiagnosticField.SCHEMA_NAME) + + @property + def table_name(self) -> str | None: + return self._error_message(DiagnosticField.TABLE_NAME) + + @property + def column_name(self) -> str | None: + return self._error_message(DiagnosticField.COLUMN_NAME) + + @property + def datatype_name(self) -> str | None: + return self._error_message(DiagnosticField.DATATYPE_NAME) + + @property + def constraint_name(self) -> str | None: + return self._error_message(DiagnosticField.CONSTRAINT_NAME) + + @property + def source_file(self) -> str | None: + return self._error_message(DiagnosticField.SOURCE_FILE) + + @property + def source_line(self) -> str | None: + return self._error_message(DiagnosticField.SOURCE_LINE) + + @property + def source_function(self) -> str | None: + return self._error_message(DiagnosticField.SOURCE_FUNCTION) + + def _error_message(self, field: DiagnosticField) -> str | None: + if self._info: + if isinstance(self._info, dict): + val = self._info.get(field) + else: + val = self._info.error_field(field) + + if val is not None: + return val.decode(self._encoding, "replace") + + return None + + def __reduce__(self) -> str | tuple[Any, ...]: + res = super().__reduce__() + if isinstance(res, tuple) and len(res) >= 3: + res[2]["_info"] = _info_to_dict(self._info) + + return res + + +def _info_to_dict(info: ErrorInfo) -> ErrorInfo: + """ + Convert a PGresult to a dictionary to make the info picklable. + """ + # PGresult is a protocol, can't use isinstance + if _is_pgresult(info): + return {v: info.error_field(v) for v in DiagnosticField} + else: + return info + + +def lookup(sqlstate: str) -> type[Error]: + """Lookup an error code or `constant name`__ and return its exception class. + + Raise `!KeyError` if the code is not found. + + .. __: https://www.postgresql.org/docs/current/errcodes-appendix.html + #ERRCODES-TABLE + """ + return _sqlcodes[sqlstate.upper()] + + +def error_from_result(result: PGresult, encoding: str = "utf-8") -> Error: + state = result.error_field(DiagnosticField.SQLSTATE) or b"" + cls = _class_for_state(state.decode("utf-8", "replace")) + return cls(result.get_error_message(encoding), info=result, encoding=encoding) + + +def _is_pgresult(info: ErrorInfo) -> TypeGuard[PGresult]: + """Return True if an ErrorInfo is a PGresult instance.""" + # PGresult is a protocol, can't use isinstance + return hasattr(info, "error_field") + + +def _class_for_state(sqlstate: str) -> type[Error]: + try: + return lookup(sqlstate) + except KeyError: + return get_base_exception(sqlstate) + + +def get_base_exception(sqlstate: str) -> type[Error]: + return ( + _base_exc_map.get(sqlstate[:2]) + or _base_exc_map.get(sqlstate[:1]) + or DatabaseError + ) + + +_base_exc_map = { + "08": OperationalError, # Connection Exception + "0A": NotSupportedError, # Feature Not Supported + "20": ProgrammingError, # Case Not Foud + "21": ProgrammingError, # Cardinality Violation + "22": DataError, # Data Exception + "23": IntegrityError, # Integrity Constraint Violation + "24": InternalError, # Invalid Cursor State + "25": InternalError, # Invalid Transaction State + "26": ProgrammingError, # Invalid SQL Statement Name * + "27": OperationalError, # Triggered Data Change Violation + "28": OperationalError, # Invalid Authorization Specification + "2B": InternalError, # Dependent Privilege Descriptors Still Exist + "2D": InternalError, # Invalid Transaction Termination + "2F": OperationalError, # SQL Routine Exception * + "34": ProgrammingError, # Invalid Cursor Name * + "38": OperationalError, # External Routine Exception * + "39": OperationalError, # External Routine Invocation Exception * + "3B": OperationalError, # Savepoint Exception * + "3D": ProgrammingError, # Invalid Catalog Name + "3F": ProgrammingError, # Invalid Schema Name + "40": OperationalError, # Transaction Rollback + "42": ProgrammingError, # Syntax Error or Access Rule Violation + "44": ProgrammingError, # WITH CHECK OPTION Violation + "53": OperationalError, # Insufficient Resources + "54": OperationalError, # Program Limit Exceeded + "55": OperationalError, # Object Not In Prerequisite State + "57": OperationalError, # Operator Intervention + "58": OperationalError, # System Error (errors external to PostgreSQL itself) + "F": OperationalError, # Configuration File Error + "H": OperationalError, # Foreign Data Wrapper Error (SQL/MED) + "P": ProgrammingError, # PL/pgSQL Error + "X": InternalError, # Internal Error +} + + +# Error classes generated by tools/update_errors.py + +# fmt: off +# autogenerated: start + + +# Class 02 - No Data (this is also a warning class per the SQL standard) + +class NoData(DatabaseError, + code='02000', name='NO_DATA'): + pass + +class NoAdditionalDynamicResultSetsReturned(DatabaseError, + code='02001', name='NO_ADDITIONAL_DYNAMIC_RESULT_SETS_RETURNED'): + pass + + +# Class 03 - SQL Statement Not Yet Complete + +class SqlStatementNotYetComplete(DatabaseError, + code='03000', name='SQL_STATEMENT_NOT_YET_COMPLETE'): + pass + + +# Class 08 - Connection Exception + +class ConnectionException(OperationalError, + code='08000', name='CONNECTION_EXCEPTION'): + pass + +class SqlclientUnableToEstablishSqlconnection(OperationalError, + code='08001', name='SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION'): + pass + +class ConnectionDoesNotExist(OperationalError, + code='08003', name='CONNECTION_DOES_NOT_EXIST'): + pass + +class SqlserverRejectedEstablishmentOfSqlconnection(OperationalError, + code='08004', name='SQLSERVER_REJECTED_ESTABLISHMENT_OF_SQLCONNECTION'): + pass + +class ConnectionFailure(OperationalError, + code='08006', name='CONNECTION_FAILURE'): + pass + +class TransactionResolutionUnknown(OperationalError, + code='08007', name='TRANSACTION_RESOLUTION_UNKNOWN'): + pass + +class ProtocolViolation(OperationalError, + code='08P01', name='PROTOCOL_VIOLATION'): + pass + + +# Class 09 - Triggered Action Exception + +class TriggeredActionException(DatabaseError, + code='09000', name='TRIGGERED_ACTION_EXCEPTION'): + pass + + +# Class 0A - Feature Not Supported + +class FeatureNotSupported(NotSupportedError, + code='0A000', name='FEATURE_NOT_SUPPORTED'): + pass + + +# Class 0B - Invalid Transaction Initiation + +class InvalidTransactionInitiation(DatabaseError, + code='0B000', name='INVALID_TRANSACTION_INITIATION'): + pass + + +# Class 0F - Locator Exception + +class LocatorException(DatabaseError, + code='0F000', name='LOCATOR_EXCEPTION'): + pass + +class InvalidLocatorSpecification(DatabaseError, + code='0F001', name='INVALID_LOCATOR_SPECIFICATION'): + pass + + +# Class 0L - Invalid Grantor + +class InvalidGrantor(DatabaseError, + code='0L000', name='INVALID_GRANTOR'): + pass + +class InvalidGrantOperation(DatabaseError, + code='0LP01', name='INVALID_GRANT_OPERATION'): + pass + + +# Class 0P - Invalid Role Specification + +class InvalidRoleSpecification(DatabaseError, + code='0P000', name='INVALID_ROLE_SPECIFICATION'): + pass + + +# Class 0Z - Diagnostics Exception + +class DiagnosticsException(DatabaseError, + code='0Z000', name='DIAGNOSTICS_EXCEPTION'): + pass + +class StackedDiagnosticsAccessedWithoutActiveHandler(DatabaseError, + code='0Z002', name='STACKED_DIAGNOSTICS_ACCESSED_WITHOUT_ACTIVE_HANDLER'): + pass + + +# Class 20 - Case Not Found + +class CaseNotFound(ProgrammingError, + code='20000', name='CASE_NOT_FOUND'): + pass + + +# Class 21 - Cardinality Violation + +class CardinalityViolation(ProgrammingError, + code='21000', name='CARDINALITY_VIOLATION'): + pass + + +# Class 22 - Data Exception + +class DataException(DataError, + code='22000', name='DATA_EXCEPTION'): + pass + +class StringDataRightTruncation(DataError, + code='22001', name='STRING_DATA_RIGHT_TRUNCATION'): + pass + +class NullValueNoIndicatorParameter(DataError, + code='22002', name='NULL_VALUE_NO_INDICATOR_PARAMETER'): + pass + +class NumericValueOutOfRange(DataError, + code='22003', name='NUMERIC_VALUE_OUT_OF_RANGE'): + pass + +class NullValueNotAllowed(DataError, + code='22004', name='NULL_VALUE_NOT_ALLOWED'): + pass + +class ErrorInAssignment(DataError, + code='22005', name='ERROR_IN_ASSIGNMENT'): + pass + +class InvalidDatetimeFormat(DataError, + code='22007', name='INVALID_DATETIME_FORMAT'): + pass + +class DatetimeFieldOverflow(DataError, + code='22008', name='DATETIME_FIELD_OVERFLOW'): + pass + +class InvalidTimeZoneDisplacementValue(DataError, + code='22009', name='INVALID_TIME_ZONE_DISPLACEMENT_VALUE'): + pass + +class EscapeCharacterConflict(DataError, + code='2200B', name='ESCAPE_CHARACTER_CONFLICT'): + pass + +class InvalidUseOfEscapeCharacter(DataError, + code='2200C', name='INVALID_USE_OF_ESCAPE_CHARACTER'): + pass + +class InvalidEscapeOctet(DataError, + code='2200D', name='INVALID_ESCAPE_OCTET'): + pass + +class ZeroLengthCharacterString(DataError, + code='2200F', name='ZERO_LENGTH_CHARACTER_STRING'): + pass + +class MostSpecificTypeMismatch(DataError, + code='2200G', name='MOST_SPECIFIC_TYPE_MISMATCH'): + pass + +class SequenceGeneratorLimitExceeded(DataError, + code='2200H', name='SEQUENCE_GENERATOR_LIMIT_EXCEEDED'): + pass + +class NotAnXmlDocument(DataError, + code='2200L', name='NOT_AN_XML_DOCUMENT'): + pass + +class InvalidXmlDocument(DataError, + code='2200M', name='INVALID_XML_DOCUMENT'): + pass + +class InvalidXmlContent(DataError, + code='2200N', name='INVALID_XML_CONTENT'): + pass + +class InvalidXmlComment(DataError, + code='2200S', name='INVALID_XML_COMMENT'): + pass + +class InvalidXmlProcessingInstruction(DataError, + code='2200T', name='INVALID_XML_PROCESSING_INSTRUCTION'): + pass + +class InvalidIndicatorParameterValue(DataError, + code='22010', name='INVALID_INDICATOR_PARAMETER_VALUE'): + pass + +class SubstringError(DataError, + code='22011', name='SUBSTRING_ERROR'): + pass + +class DivisionByZero(DataError, + code='22012', name='DIVISION_BY_ZERO'): + pass + +class InvalidPrecedingOrFollowingSize(DataError, + code='22013', name='INVALID_PRECEDING_OR_FOLLOWING_SIZE'): + pass + +class InvalidArgumentForNtileFunction(DataError, + code='22014', name='INVALID_ARGUMENT_FOR_NTILE_FUNCTION'): + pass + +class IntervalFieldOverflow(DataError, + code='22015', name='INTERVAL_FIELD_OVERFLOW'): + pass + +class InvalidArgumentForNthValueFunction(DataError, + code='22016', name='INVALID_ARGUMENT_FOR_NTH_VALUE_FUNCTION'): + pass + +class InvalidCharacterValueForCast(DataError, + code='22018', name='INVALID_CHARACTER_VALUE_FOR_CAST'): + pass + +class InvalidEscapeCharacter(DataError, + code='22019', name='INVALID_ESCAPE_CHARACTER'): + pass + +class InvalidRegularExpression(DataError, + code='2201B', name='INVALID_REGULAR_EXPRESSION'): + pass + +class InvalidArgumentForLogarithm(DataError, + code='2201E', name='INVALID_ARGUMENT_FOR_LOGARITHM'): + pass + +class InvalidArgumentForPowerFunction(DataError, + code='2201F', name='INVALID_ARGUMENT_FOR_POWER_FUNCTION'): + pass + +class InvalidArgumentForWidthBucketFunction(DataError, + code='2201G', name='INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION'): + pass + +class InvalidRowCountInLimitClause(DataError, + code='2201W', name='INVALID_ROW_COUNT_IN_LIMIT_CLAUSE'): + pass + +class InvalidRowCountInResultOffsetClause(DataError, + code='2201X', name='INVALID_ROW_COUNT_IN_RESULT_OFFSET_CLAUSE'): + pass + +class CharacterNotInRepertoire(DataError, + code='22021', name='CHARACTER_NOT_IN_REPERTOIRE'): + pass + +class IndicatorOverflow(DataError, + code='22022', name='INDICATOR_OVERFLOW'): + pass + +class InvalidParameterValue(DataError, + code='22023', name='INVALID_PARAMETER_VALUE'): + pass + +class UnterminatedCString(DataError, + code='22024', name='UNTERMINATED_C_STRING'): + pass + +class InvalidEscapeSequence(DataError, + code='22025', name='INVALID_ESCAPE_SEQUENCE'): + pass + +class StringDataLengthMismatch(DataError, + code='22026', name='STRING_DATA_LENGTH_MISMATCH'): + pass + +class TrimError(DataError, + code='22027', name='TRIM_ERROR'): + pass + +class ArraySubscriptError(DataError, + code='2202E', name='ARRAY_SUBSCRIPT_ERROR'): + pass + +class InvalidTablesampleRepeat(DataError, + code='2202G', name='INVALID_TABLESAMPLE_REPEAT'): + pass + +class InvalidTablesampleArgument(DataError, + code='2202H', name='INVALID_TABLESAMPLE_ARGUMENT'): + pass + +class DuplicateJsonObjectKeyValue(DataError, + code='22030', name='DUPLICATE_JSON_OBJECT_KEY_VALUE'): + pass + +class InvalidArgumentForSqlJsonDatetimeFunction(DataError, + code='22031', name='INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION'): + pass + +class InvalidJsonText(DataError, + code='22032', name='INVALID_JSON_TEXT'): + pass + +class InvalidSqlJsonSubscript(DataError, + code='22033', name='INVALID_SQL_JSON_SUBSCRIPT'): + pass + +class MoreThanOneSqlJsonItem(DataError, + code='22034', name='MORE_THAN_ONE_SQL_JSON_ITEM'): + pass + +class NoSqlJsonItem(DataError, + code='22035', name='NO_SQL_JSON_ITEM'): + pass + +class NonNumericSqlJsonItem(DataError, + code='22036', name='NON_NUMERIC_SQL_JSON_ITEM'): + pass + +class NonUniqueKeysInAJsonObject(DataError, + code='22037', name='NON_UNIQUE_KEYS_IN_A_JSON_OBJECT'): + pass + +class SingletonSqlJsonItemRequired(DataError, + code='22038', name='SINGLETON_SQL_JSON_ITEM_REQUIRED'): + pass + +class SqlJsonArrayNotFound(DataError, + code='22039', name='SQL_JSON_ARRAY_NOT_FOUND'): + pass + +class SqlJsonMemberNotFound(DataError, + code='2203A', name='SQL_JSON_MEMBER_NOT_FOUND'): + pass + +class SqlJsonNumberNotFound(DataError, + code='2203B', name='SQL_JSON_NUMBER_NOT_FOUND'): + pass + +class SqlJsonObjectNotFound(DataError, + code='2203C', name='SQL_JSON_OBJECT_NOT_FOUND'): + pass + +class TooManyJsonArrayElements(DataError, + code='2203D', name='TOO_MANY_JSON_ARRAY_ELEMENTS'): + pass + +class TooManyJsonObjectMembers(DataError, + code='2203E', name='TOO_MANY_JSON_OBJECT_MEMBERS'): + pass + +class SqlJsonScalarRequired(DataError, + code='2203F', name='SQL_JSON_SCALAR_REQUIRED'): + pass + +class SqlJsonItemCannotBeCastToTargetType(DataError, + code='2203G', name='SQL_JSON_ITEM_CANNOT_BE_CAST_TO_TARGET_TYPE'): + pass + +class FloatingPointException(DataError, + code='22P01', name='FLOATING_POINT_EXCEPTION'): + pass + +class InvalidTextRepresentation(DataError, + code='22P02', name='INVALID_TEXT_REPRESENTATION'): + pass + +class InvalidBinaryRepresentation(DataError, + code='22P03', name='INVALID_BINARY_REPRESENTATION'): + pass + +class BadCopyFileFormat(DataError, + code='22P04', name='BAD_COPY_FILE_FORMAT'): + pass + +class UntranslatableCharacter(DataError, + code='22P05', name='UNTRANSLATABLE_CHARACTER'): + pass + +class NonstandardUseOfEscapeCharacter(DataError, + code='22P06', name='NONSTANDARD_USE_OF_ESCAPE_CHARACTER'): + pass + + +# Class 23 - Integrity Constraint Violation + +class IntegrityConstraintViolation(IntegrityError, + code='23000', name='INTEGRITY_CONSTRAINT_VIOLATION'): + pass + +class RestrictViolation(IntegrityError, + code='23001', name='RESTRICT_VIOLATION'): + pass + +class NotNullViolation(IntegrityError, + code='23502', name='NOT_NULL_VIOLATION'): + pass + +class ForeignKeyViolation(IntegrityError, + code='23503', name='FOREIGN_KEY_VIOLATION'): + pass + +class UniqueViolation(IntegrityError, + code='23505', name='UNIQUE_VIOLATION'): + pass + +class CheckViolation(IntegrityError, + code='23514', name='CHECK_VIOLATION'): + pass + +class ExclusionViolation(IntegrityError, + code='23P01', name='EXCLUSION_VIOLATION'): + pass + + +# Class 24 - Invalid Cursor State + +class InvalidCursorState(InternalError, + code='24000', name='INVALID_CURSOR_STATE'): + pass + + +# Class 25 - Invalid Transaction State + +class InvalidTransactionState(InternalError, + code='25000', name='INVALID_TRANSACTION_STATE'): + pass + +class ActiveSqlTransaction(InternalError, + code='25001', name='ACTIVE_SQL_TRANSACTION'): + pass + +class BranchTransactionAlreadyActive(InternalError, + code='25002', name='BRANCH_TRANSACTION_ALREADY_ACTIVE'): + pass + +class InappropriateAccessModeForBranchTransaction(InternalError, + code='25003', name='INAPPROPRIATE_ACCESS_MODE_FOR_BRANCH_TRANSACTION'): + pass + +class InappropriateIsolationLevelForBranchTransaction(InternalError, + code='25004', name='INAPPROPRIATE_ISOLATION_LEVEL_FOR_BRANCH_TRANSACTION'): + pass + +class NoActiveSqlTransactionForBranchTransaction(InternalError, + code='25005', name='NO_ACTIVE_SQL_TRANSACTION_FOR_BRANCH_TRANSACTION'): + pass + +class ReadOnlySqlTransaction(InternalError, + code='25006', name='READ_ONLY_SQL_TRANSACTION'): + pass + +class SchemaAndDataStatementMixingNotSupported(InternalError, + code='25007', name='SCHEMA_AND_DATA_STATEMENT_MIXING_NOT_SUPPORTED'): + pass + +class HeldCursorRequiresSameIsolationLevel(InternalError, + code='25008', name='HELD_CURSOR_REQUIRES_SAME_ISOLATION_LEVEL'): + pass + +class NoActiveSqlTransaction(InternalError, + code='25P01', name='NO_ACTIVE_SQL_TRANSACTION'): + pass + +class InFailedSqlTransaction(InternalError, + code='25P02', name='IN_FAILED_SQL_TRANSACTION'): + pass + +class IdleInTransactionSessionTimeout(InternalError, + code='25P03', name='IDLE_IN_TRANSACTION_SESSION_TIMEOUT'): + pass + +class TransactionTimeout(InternalError, + code='25P04', name='TRANSACTION_TIMEOUT'): + pass + + +# Class 26 - Invalid SQL Statement Name + +class InvalidSqlStatementName(ProgrammingError, + code='26000', name='INVALID_SQL_STATEMENT_NAME'): + pass + + +# Class 27 - Triggered Data Change Violation + +class TriggeredDataChangeViolation(OperationalError, + code='27000', name='TRIGGERED_DATA_CHANGE_VIOLATION'): + pass + + +# Class 28 - Invalid Authorization Specification + +class InvalidAuthorizationSpecification(OperationalError, + code='28000', name='INVALID_AUTHORIZATION_SPECIFICATION'): + pass + +class InvalidPassword(OperationalError, + code='28P01', name='INVALID_PASSWORD'): + pass + + +# Class 2B - Dependent Privilege Descriptors Still Exist + +class DependentPrivilegeDescriptorsStillExist(InternalError, + code='2B000', name='DEPENDENT_PRIVILEGE_DESCRIPTORS_STILL_EXIST'): + pass + +class DependentObjectsStillExist(InternalError, + code='2BP01', name='DEPENDENT_OBJECTS_STILL_EXIST'): + pass + + +# Class 2D - Invalid Transaction Termination + +class InvalidTransactionTermination(InternalError, + code='2D000', name='INVALID_TRANSACTION_TERMINATION'): + pass + + +# Class 2F - SQL Routine Exception + +class SqlRoutineException(OperationalError, + code='2F000', name='SQL_ROUTINE_EXCEPTION'): + pass + +class ModifyingSqlDataNotPermitted(OperationalError, + code='2F002', name='MODIFYING_SQL_DATA_NOT_PERMITTED'): + pass + +class ProhibitedSqlStatementAttempted(OperationalError, + code='2F003', name='PROHIBITED_SQL_STATEMENT_ATTEMPTED'): + pass + +class ReadingSqlDataNotPermitted(OperationalError, + code='2F004', name='READING_SQL_DATA_NOT_PERMITTED'): + pass + +class FunctionExecutedNoReturnStatement(OperationalError, + code='2F005', name='FUNCTION_EXECUTED_NO_RETURN_STATEMENT'): + pass + + +# Class 34 - Invalid Cursor Name + +class InvalidCursorName(ProgrammingError, + code='34000', name='INVALID_CURSOR_NAME'): + pass + + +# Class 38 - External Routine Exception + +class ExternalRoutineException(OperationalError, + code='38000', name='EXTERNAL_ROUTINE_EXCEPTION'): + pass + +class ContainingSqlNotPermitted(OperationalError, + code='38001', name='CONTAINING_SQL_NOT_PERMITTED'): + pass + +class ModifyingSqlDataNotPermittedExt(OperationalError, + code='38002', name='MODIFYING_SQL_DATA_NOT_PERMITTED'): + pass + +class ProhibitedSqlStatementAttemptedExt(OperationalError, + code='38003', name='PROHIBITED_SQL_STATEMENT_ATTEMPTED'): + pass + +class ReadingSqlDataNotPermittedExt(OperationalError, + code='38004', name='READING_SQL_DATA_NOT_PERMITTED'): + pass + + +# Class 39 - External Routine Invocation Exception + +class ExternalRoutineInvocationException(OperationalError, + code='39000', name='EXTERNAL_ROUTINE_INVOCATION_EXCEPTION'): + pass + +class InvalidSqlstateReturned(OperationalError, + code='39001', name='INVALID_SQLSTATE_RETURNED'): + pass + +class NullValueNotAllowedExt(OperationalError, + code='39004', name='NULL_VALUE_NOT_ALLOWED'): + pass + +class TriggerProtocolViolated(OperationalError, + code='39P01', name='TRIGGER_PROTOCOL_VIOLATED'): + pass + +class SrfProtocolViolated(OperationalError, + code='39P02', name='SRF_PROTOCOL_VIOLATED'): + pass + +class EventTriggerProtocolViolated(OperationalError, + code='39P03', name='EVENT_TRIGGER_PROTOCOL_VIOLATED'): + pass + + +# Class 3B - Savepoint Exception + +class SavepointException(OperationalError, + code='3B000', name='SAVEPOINT_EXCEPTION'): + pass + +class InvalidSavepointSpecification(OperationalError, + code='3B001', name='INVALID_SAVEPOINT_SPECIFICATION'): + pass + + +# Class 3D - Invalid Catalog Name + +class InvalidCatalogName(ProgrammingError, + code='3D000', name='INVALID_CATALOG_NAME'): + pass + + +# Class 3F - Invalid Schema Name + +class InvalidSchemaName(ProgrammingError, + code='3F000', name='INVALID_SCHEMA_NAME'): + pass + + +# Class 40 - Transaction Rollback + +class TransactionRollback(OperationalError, + code='40000', name='TRANSACTION_ROLLBACK'): + pass + +class SerializationFailure(OperationalError, + code='40001', name='SERIALIZATION_FAILURE'): + pass + +class TransactionIntegrityConstraintViolation(OperationalError, + code='40002', name='TRANSACTION_INTEGRITY_CONSTRAINT_VIOLATION'): + pass + +class StatementCompletionUnknown(OperationalError, + code='40003', name='STATEMENT_COMPLETION_UNKNOWN'): + pass + +class DeadlockDetected(OperationalError, + code='40P01', name='DEADLOCK_DETECTED'): + pass + + +# Class 42 - Syntax Error or Access Rule Violation + +class SyntaxErrorOrAccessRuleViolation(ProgrammingError, + code='42000', name='SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION'): + pass + +class InsufficientPrivilege(ProgrammingError, + code='42501', name='INSUFFICIENT_PRIVILEGE'): + pass + +class SyntaxError(ProgrammingError, + code='42601', name='SYNTAX_ERROR'): + pass + +class InvalidName(ProgrammingError, + code='42602', name='INVALID_NAME'): + pass + +class InvalidColumnDefinition(ProgrammingError, + code='42611', name='INVALID_COLUMN_DEFINITION'): + pass + +class NameTooLong(ProgrammingError, + code='42622', name='NAME_TOO_LONG'): + pass + +class DuplicateColumn(ProgrammingError, + code='42701', name='DUPLICATE_COLUMN'): + pass + +class AmbiguousColumn(ProgrammingError, + code='42702', name='AMBIGUOUS_COLUMN'): + pass + +class UndefinedColumn(ProgrammingError, + code='42703', name='UNDEFINED_COLUMN'): + pass + +class UndefinedObject(ProgrammingError, + code='42704', name='UNDEFINED_OBJECT'): + pass + +class DuplicateObject(ProgrammingError, + code='42710', name='DUPLICATE_OBJECT'): + pass + +class DuplicateAlias(ProgrammingError, + code='42712', name='DUPLICATE_ALIAS'): + pass + +class DuplicateFunction(ProgrammingError, + code='42723', name='DUPLICATE_FUNCTION'): + pass + +class AmbiguousFunction(ProgrammingError, + code='42725', name='AMBIGUOUS_FUNCTION'): + pass + +class GroupingError(ProgrammingError, + code='42803', name='GROUPING_ERROR'): + pass + +class DatatypeMismatch(ProgrammingError, + code='42804', name='DATATYPE_MISMATCH'): + pass + +class WrongObjectType(ProgrammingError, + code='42809', name='WRONG_OBJECT_TYPE'): + pass + +class InvalidForeignKey(ProgrammingError, + code='42830', name='INVALID_FOREIGN_KEY'): + pass + +class CannotCoerce(ProgrammingError, + code='42846', name='CANNOT_COERCE'): + pass + +class UndefinedFunction(ProgrammingError, + code='42883', name='UNDEFINED_FUNCTION'): + pass + +class GeneratedAlways(ProgrammingError, + code='428C9', name='GENERATED_ALWAYS'): + pass + +class ReservedName(ProgrammingError, + code='42939', name='RESERVED_NAME'): + pass + +class UndefinedTable(ProgrammingError, + code='42P01', name='UNDEFINED_TABLE'): + pass + +class UndefinedParameter(ProgrammingError, + code='42P02', name='UNDEFINED_PARAMETER'): + pass + +class DuplicateCursor(ProgrammingError, + code='42P03', name='DUPLICATE_CURSOR'): + pass + +class DuplicateDatabase(ProgrammingError, + code='42P04', name='DUPLICATE_DATABASE'): + pass + +class DuplicatePreparedStatement(ProgrammingError, + code='42P05', name='DUPLICATE_PREPARED_STATEMENT'): + pass + +class DuplicateSchema(ProgrammingError, + code='42P06', name='DUPLICATE_SCHEMA'): + pass + +class DuplicateTable(ProgrammingError, + code='42P07', name='DUPLICATE_TABLE'): + pass + +class AmbiguousParameter(ProgrammingError, + code='42P08', name='AMBIGUOUS_PARAMETER'): + pass + +class AmbiguousAlias(ProgrammingError, + code='42P09', name='AMBIGUOUS_ALIAS'): + pass + +class InvalidColumnReference(ProgrammingError, + code='42P10', name='INVALID_COLUMN_REFERENCE'): + pass + +class InvalidCursorDefinition(ProgrammingError, + code='42P11', name='INVALID_CURSOR_DEFINITION'): + pass + +class InvalidDatabaseDefinition(ProgrammingError, + code='42P12', name='INVALID_DATABASE_DEFINITION'): + pass + +class InvalidFunctionDefinition(ProgrammingError, + code='42P13', name='INVALID_FUNCTION_DEFINITION'): + pass + +class InvalidPreparedStatementDefinition(ProgrammingError, + code='42P14', name='INVALID_PREPARED_STATEMENT_DEFINITION'): + pass + +class InvalidSchemaDefinition(ProgrammingError, + code='42P15', name='INVALID_SCHEMA_DEFINITION'): + pass + +class InvalidTableDefinition(ProgrammingError, + code='42P16', name='INVALID_TABLE_DEFINITION'): + pass + +class InvalidObjectDefinition(ProgrammingError, + code='42P17', name='INVALID_OBJECT_DEFINITION'): + pass + +class IndeterminateDatatype(ProgrammingError, + code='42P18', name='INDETERMINATE_DATATYPE'): + pass + +class InvalidRecursion(ProgrammingError, + code='42P19', name='INVALID_RECURSION'): + pass + +class WindowingError(ProgrammingError, + code='42P20', name='WINDOWING_ERROR'): + pass + +class CollationMismatch(ProgrammingError, + code='42P21', name='COLLATION_MISMATCH'): + pass + +class IndeterminateCollation(ProgrammingError, + code='42P22', name='INDETERMINATE_COLLATION'): + pass + + +# Class 44 - WITH CHECK OPTION Violation + +class WithCheckOptionViolation(ProgrammingError, + code='44000', name='WITH_CHECK_OPTION_VIOLATION'): + pass + + +# Class 53 - Insufficient Resources + +class InsufficientResources(OperationalError, + code='53000', name='INSUFFICIENT_RESOURCES'): + pass + +class DiskFull(OperationalError, + code='53100', name='DISK_FULL'): + pass + +class OutOfMemory(OperationalError, + code='53200', name='OUT_OF_MEMORY'): + pass + +class TooManyConnections(OperationalError, + code='53300', name='TOO_MANY_CONNECTIONS'): + pass + +class ConfigurationLimitExceeded(OperationalError, + code='53400', name='CONFIGURATION_LIMIT_EXCEEDED'): + pass + + +# Class 54 - Program Limit Exceeded + +class ProgramLimitExceeded(OperationalError, + code='54000', name='PROGRAM_LIMIT_EXCEEDED'): + pass + +class StatementTooComplex(OperationalError, + code='54001', name='STATEMENT_TOO_COMPLEX'): + pass + +class TooManyColumns(OperationalError, + code='54011', name='TOO_MANY_COLUMNS'): + pass + +class TooManyArguments(OperationalError, + code='54023', name='TOO_MANY_ARGUMENTS'): + pass + + +# Class 55 - Object Not In Prerequisite State + +class ObjectNotInPrerequisiteState(OperationalError, + code='55000', name='OBJECT_NOT_IN_PREREQUISITE_STATE'): + pass + +class ObjectInUse(OperationalError, + code='55006', name='OBJECT_IN_USE'): + pass + +class CantChangeRuntimeParam(OperationalError, + code='55P02', name='CANT_CHANGE_RUNTIME_PARAM'): + pass + +class LockNotAvailable(OperationalError, + code='55P03', name='LOCK_NOT_AVAILABLE'): + pass + +class UnsafeNewEnumValueUsage(OperationalError, + code='55P04', name='UNSAFE_NEW_ENUM_VALUE_USAGE'): + pass + + +# Class 57 - Operator Intervention + +class OperatorIntervention(OperationalError, + code='57000', name='OPERATOR_INTERVENTION'): + pass + +class QueryCanceled(OperationalError, + code='57014', name='QUERY_CANCELED'): + pass + +class AdminShutdown(OperationalError, + code='57P01', name='ADMIN_SHUTDOWN'): + pass + +class CrashShutdown(OperationalError, + code='57P02', name='CRASH_SHUTDOWN'): + pass + +class CannotConnectNow(OperationalError, + code='57P03', name='CANNOT_CONNECT_NOW'): + pass + +class DatabaseDropped(OperationalError, + code='57P04', name='DATABASE_DROPPED'): + pass + +class IdleSessionTimeout(OperationalError, + code='57P05', name='IDLE_SESSION_TIMEOUT'): + pass + + +# Class 58 - System Error (errors external to PostgreSQL itself) + +class SystemError(OperationalError, + code='58000', name='SYSTEM_ERROR'): + pass + +class IoError(OperationalError, + code='58030', name='IO_ERROR'): + pass + +class UndefinedFile(OperationalError, + code='58P01', name='UNDEFINED_FILE'): + pass + +class DuplicateFile(OperationalError, + code='58P02', name='DUPLICATE_FILE'): + pass + + +# Class 72 - Snapshot Failure + +class SnapshotTooOld(DatabaseError, + code='72000', name='SNAPSHOT_TOO_OLD'): + pass + + +# Class F0 - Configuration File Error + +class ConfigFileError(OperationalError, + code='F0000', name='CONFIG_FILE_ERROR'): + pass + +class LockFileExists(OperationalError, + code='F0001', name='LOCK_FILE_EXISTS'): + pass + + +# Class HV - Foreign Data Wrapper Error (SQL/MED) + +class FdwError(OperationalError, + code='HV000', name='FDW_ERROR'): + pass + +class FdwOutOfMemory(OperationalError, + code='HV001', name='FDW_OUT_OF_MEMORY'): + pass + +class FdwDynamicParameterValueNeeded(OperationalError, + code='HV002', name='FDW_DYNAMIC_PARAMETER_VALUE_NEEDED'): + pass + +class FdwInvalidDataType(OperationalError, + code='HV004', name='FDW_INVALID_DATA_TYPE'): + pass + +class FdwColumnNameNotFound(OperationalError, + code='HV005', name='FDW_COLUMN_NAME_NOT_FOUND'): + pass + +class FdwInvalidDataTypeDescriptors(OperationalError, + code='HV006', name='FDW_INVALID_DATA_TYPE_DESCRIPTORS'): + pass + +class FdwInvalidColumnName(OperationalError, + code='HV007', name='FDW_INVALID_COLUMN_NAME'): + pass + +class FdwInvalidColumnNumber(OperationalError, + code='HV008', name='FDW_INVALID_COLUMN_NUMBER'): + pass + +class FdwInvalidUseOfNullPointer(OperationalError, + code='HV009', name='FDW_INVALID_USE_OF_NULL_POINTER'): + pass + +class FdwInvalidStringFormat(OperationalError, + code='HV00A', name='FDW_INVALID_STRING_FORMAT'): + pass + +class FdwInvalidHandle(OperationalError, + code='HV00B', name='FDW_INVALID_HANDLE'): + pass + +class FdwInvalidOptionIndex(OperationalError, + code='HV00C', name='FDW_INVALID_OPTION_INDEX'): + pass + +class FdwInvalidOptionName(OperationalError, + code='HV00D', name='FDW_INVALID_OPTION_NAME'): + pass + +class FdwOptionNameNotFound(OperationalError, + code='HV00J', name='FDW_OPTION_NAME_NOT_FOUND'): + pass + +class FdwReplyHandle(OperationalError, + code='HV00K', name='FDW_REPLY_HANDLE'): + pass + +class FdwUnableToCreateExecution(OperationalError, + code='HV00L', name='FDW_UNABLE_TO_CREATE_EXECUTION'): + pass + +class FdwUnableToCreateReply(OperationalError, + code='HV00M', name='FDW_UNABLE_TO_CREATE_REPLY'): + pass + +class FdwUnableToEstablishConnection(OperationalError, + code='HV00N', name='FDW_UNABLE_TO_ESTABLISH_CONNECTION'): + pass + +class FdwNoSchemas(OperationalError, + code='HV00P', name='FDW_NO_SCHEMAS'): + pass + +class FdwSchemaNotFound(OperationalError, + code='HV00Q', name='FDW_SCHEMA_NOT_FOUND'): + pass + +class FdwTableNotFound(OperationalError, + code='HV00R', name='FDW_TABLE_NOT_FOUND'): + pass + +class FdwFunctionSequenceError(OperationalError, + code='HV010', name='FDW_FUNCTION_SEQUENCE_ERROR'): + pass + +class FdwTooManyHandles(OperationalError, + code='HV014', name='FDW_TOO_MANY_HANDLES'): + pass + +class FdwInconsistentDescriptorInformation(OperationalError, + code='HV021', name='FDW_INCONSISTENT_DESCRIPTOR_INFORMATION'): + pass + +class FdwInvalidAttributeValue(OperationalError, + code='HV024', name='FDW_INVALID_ATTRIBUTE_VALUE'): + pass + +class FdwInvalidStringLengthOrBufferLength(OperationalError, + code='HV090', name='FDW_INVALID_STRING_LENGTH_OR_BUFFER_LENGTH'): + pass + +class FdwInvalidDescriptorFieldIdentifier(OperationalError, + code='HV091', name='FDW_INVALID_DESCRIPTOR_FIELD_IDENTIFIER'): + pass + + +# Class P0 - PL/pgSQL Error + +class PlpgsqlError(ProgrammingError, + code='P0000', name='PLPGSQL_ERROR'): + pass + +class RaiseException(ProgrammingError, + code='P0001', name='RAISE_EXCEPTION'): + pass + +class NoDataFound(ProgrammingError, + code='P0002', name='NO_DATA_FOUND'): + pass + +class TooManyRows(ProgrammingError, + code='P0003', name='TOO_MANY_ROWS'): + pass + +class AssertFailure(ProgrammingError, + code='P0004', name='ASSERT_FAILURE'): + pass + + +# Class XX - Internal Error + +class InternalError_(InternalError, + code='XX000', name='INTERNAL_ERROR'): + pass + +class DataCorrupted(InternalError, + code='XX001', name='DATA_CORRUPTED'): + pass + +class IndexCorrupted(InternalError, + code='XX002', name='INDEX_CORRUPTED'): + pass + + +# autogenerated: end +# fmt: on + +# Don't show a complete traceback upon raising these exception. +# Usually the traceback starts from internal functions (for instance in the +# server communication callbacks) but, for the end user, it's more important +# to get the high level information about where the exception was raised, for +# instance in a certain `Cursor.execute()`. + +_NO_TRACEBACK = (Error, KeyboardInterrupt, CancelledError) diff --git a/backend/.venv/Lib/site-packages/psycopg/generators.py b/backend/.venv/Lib/site-packages/psycopg/generators.py new file mode 100644 index 0000000..682d7ce --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/generators.py @@ -0,0 +1,407 @@ +""" +Generators implementing communication protocols with the libpq + +Certain operations (connection, querying) are an interleave of libpq calls and +waiting for the socket to be ready. This module contains the code to execute +the operations, yielding a polling state whenever there is to wait. The +functions in the `waiting` module are the ones who wait more or less +cooperatively for the socket to be ready and make these generators continue. + +These generators yield `Wait` objects whenever an operation would block. These +generators assume the connection fileno will not change. In case of the +connection function, where the fileno may change, the generators yield pairs +(fileno, `Wait`). + +The generator can be restarted sending the appropriate `Ready` state when the +file descriptor is ready. If a None value is sent, it means that the wait +function timed out without any file descriptor becoming ready; in this case the +generator should probably yield the same value again in order to wait more. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import logging +from time import monotonic + +from . import pq +from . import errors as e +from .abc import Buffer, PipelineCommand, PQGen, PQGenConn +from .pq.abc import PGcancelConn, PGconn, PGresult +from .waiting import Wait, Ready +from ._compat import Deque +from ._cmodule import _psycopg +from ._encodings import conninfo_encoding + +OK = pq.ConnStatus.OK +BAD = pq.ConnStatus.BAD + +POLL_OK = pq.PollingStatus.OK +POLL_READING = pq.PollingStatus.READING +POLL_WRITING = pq.PollingStatus.WRITING +POLL_FAILED = pq.PollingStatus.FAILED + +COMMAND_OK = pq.ExecStatus.COMMAND_OK +COPY_OUT = pq.ExecStatus.COPY_OUT +COPY_IN = pq.ExecStatus.COPY_IN +COPY_BOTH = pq.ExecStatus.COPY_BOTH +PIPELINE_SYNC = pq.ExecStatus.PIPELINE_SYNC + +WAIT_R = Wait.R +WAIT_W = Wait.W +WAIT_RW = Wait.RW +READY_R = Ready.R +READY_W = Ready.W +READY_RW = Ready.RW + +logger = logging.getLogger(__name__) + + +def _connect(conninfo: str, *, timeout: float = 0.0) -> PQGenConn[PGconn]: + """ + Generator to create a database connection without blocking. + """ + deadline = monotonic() + timeout if timeout else 0.0 + + conn = pq.PGconn.connect_start(conninfo.encode()) + while True: + if conn.status == BAD: + encoding = conninfo_encoding(conninfo) + raise e.OperationalError( + f"connection is bad: {conn.get_error_message(encoding)}", + pgconn=conn, + ) + + status = conn.connect_poll() + + if status == POLL_READING or status == POLL_WRITING: + wait = WAIT_R if status == POLL_READING else WAIT_W + while True: + ready = yield conn.socket, wait + if deadline and monotonic() > deadline: + raise e.ConnectionTimeout("connection timeout expired") + if ready: + break + + elif status == POLL_OK: + break + elif status == POLL_FAILED: + encoding = conninfo_encoding(conninfo) + raise e.OperationalError( + f"connection failed: {conn.get_error_message(encoding)}", + pgconn=e.finish_pgconn(conn), + ) + else: + raise e.InternalError( + f"unexpected poll status: {status}", pgconn=e.finish_pgconn(conn) + ) + + conn.nonblocking = 1 + return conn + + +def _cancel(cancel_conn: PGcancelConn, *, timeout: float = 0.0) -> PQGenConn[None]: + deadline = monotonic() + timeout if timeout else 0.0 + while True: + if deadline and monotonic() > deadline: + raise e.CancellationTimeout("cancellation timeout expired") + status = cancel_conn.poll() + if status == POLL_OK: + break + elif status == POLL_READING: + yield cancel_conn.socket, WAIT_R + elif status == POLL_WRITING: + yield cancel_conn.socket, WAIT_W + elif status == POLL_FAILED: + raise e.OperationalError( + f"cancellation failed: {cancel_conn.get_error_message()}" + ) + else: + raise e.InternalError(f"unexpected poll status: {status}") + + +def _execute(pgconn: PGconn) -> PQGen[list[PGresult]]: + """ + Generator sending a query and returning results without blocking. + + The query must have already been sent using `pgconn.send_query()` or + similar. Flush the query and then return the result using nonblocking + functions. + + Return the list of results returned by the database (whether success + or error). + """ + yield from _send(pgconn) + rv = yield from _fetch_many(pgconn) + return rv + + +def _send(pgconn: PGconn) -> PQGen[None]: + """ + Generator to send a query to the server without blocking. + + The query must have already been sent using `pgconn.send_query()` or + similar. Flush the query and then return the result using nonblocking + functions. + + After this generator has finished you may want to cycle using `fetch()` + to retrieve the results available. + """ + while True: + f = pgconn.flush() + if f == 0: + break + + while True: + ready = yield WAIT_RW + if ready: + break + + if ready & READY_R: + # This call may read notifies: they will be saved in the + # PGconn buffer and passed to Python later, in `fetch()`. + pgconn.consume_input() + + +def _fetch_many(pgconn: PGconn) -> PQGen[list[PGresult]]: + """ + Generator retrieving results from the database without blocking. + + The query must have already been sent to the server, so pgconn.flush() has + already returned 0. + + Return the list of results returned by the database (whether success + or error). + """ + results: list[PGresult] = [] + while True: + res = yield from _fetch(pgconn) + if not res: + break + + results.append(res) + status = res.status + if status == COPY_IN or status == COPY_OUT or status == COPY_BOTH: + # After entering copy mode the libpq will create a phony result + # for every request so let's break the endless loop. + break + + if status == PIPELINE_SYNC: + # PIPELINE_SYNC is not followed by a NULL, but we return it alone + # similarly to other result sets. + assert len(results) == 1, results + break + + return results + + +def _fetch(pgconn: PGconn) -> PQGen[PGresult | None]: + """ + Generator retrieving a single result from the database without blocking. + + The query must have already been sent to the server, so pgconn.flush() has + already returned 0. + + Return a result from the database (whether success or error). + """ + if pgconn.is_busy(): + while True: + ready = yield WAIT_R + if ready: + break + + while True: + pgconn.consume_input() + if not pgconn.is_busy(): + break + while True: + ready = yield WAIT_R + if ready: + break + + _consume_notifies(pgconn) + + return pgconn.get_result() + + +def _pipeline_communicate( + pgconn: PGconn, commands: Deque[PipelineCommand] +) -> PQGen[list[list[PGresult]]]: + """Generator to send queries from a connection in pipeline mode while also + receiving results. + + Return a list results, including single PIPELINE_SYNC elements. + """ + results = [] + + while True: + while True: + ready = yield WAIT_RW + if ready: + break + + if ready & READY_R: + pgconn.consume_input() + _consume_notifies(pgconn) + + res: list[PGresult] = [] + while not pgconn.is_busy(): + r = pgconn.get_result() + if r is None: + if not res: + break + results.append(res) + res = [] + else: + status = r.status + if status == PIPELINE_SYNC: + assert not res + results.append([r]) + elif status == COPY_IN or status == COPY_OUT or status == COPY_BOTH: + # This shouldn't happen, but insisting hard enough, it will. + # For instance, in test_executemany_badquery(), with the COPY + # statement and the AsyncClientCursor, which disables + # prepared statements). + # Bail out from the resulting infinite loop. + raise e.NotSupportedError( + "COPY cannot be used in pipeline mode" + ) + else: + res.append(r) + + if ready & READY_W: + pgconn.flush() + if not commands: + break + commands.popleft()() + + return results + + +def _consume_notifies(pgconn: PGconn) -> None: + # Consume notifies + while True: + n = pgconn.notifies() + if not n: + break + if pgconn.notify_handler: + pgconn.notify_handler(n) + + +def notifies(pgconn: PGconn) -> PQGen[list[pq.PGnotify]]: + yield WAIT_R + pgconn.consume_input() + + ns = [] + while True: + n = pgconn.notifies() + if n: + ns.append(n) + else: + break + + return ns + + +def copy_from(pgconn: PGconn) -> PQGen[memoryview | PGresult]: + while True: + nbytes, data = pgconn.get_copy_data(1) + if nbytes != 0: + break + + # would block + while True: + ready = yield WAIT_R + if ready: + break + pgconn.consume_input() + + if nbytes > 0: + # some data + return data + + # Retrieve the final result of copy + results = yield from _fetch_many(pgconn) + if len(results) > 1: + # TODO: too brutal? Copy worked. + raise e.ProgrammingError("you cannot mix COPY with other operations") + result = results[0] + if result.status != COMMAND_OK: + raise e.error_from_result(result, encoding=pgconn._encoding) + + return result + + +def copy_to(pgconn: PGconn, buffer: Buffer, flush: bool = True) -> PQGen[None]: + # Retry enqueuing data until successful. + # + # WARNING! This can cause an infinite loop if the buffer is too large. (see + # ticket #255). We avoid it in the Copy object by splitting a large buffer + # into smaller ones. We prefer to do it there instead of here in order to + # do it upstream the queue decoupling the writer task from the producer one. + while pgconn.put_copy_data(buffer) == 0: + while True: + ready = yield WAIT_W + if ready: + break + + # Flushing often has a good effect on macOS because memcpy operations + # seem expensive on this platform so accumulating a large buffer has a + # bad effect (see #745). + if flush: + # Repeat until it the message is flushed to the server + while True: + while True: + ready = yield WAIT_W + if ready: + break + f = pgconn.flush() + if f == 0: + break + + +def copy_end(pgconn: PGconn, error: bytes | None) -> PQGen[PGresult]: + # Retry enqueuing end copy message until successful + while pgconn.put_copy_end(error) == 0: + while True: + ready = yield WAIT_W + if ready: + break + + # Repeat until it the message is flushed to the server + while True: + while True: + ready = yield WAIT_W + if ready: + break + f = pgconn.flush() + if f == 0: + break + + # Retrieve the final result of copy + (result,) = yield from _fetch_many(pgconn) + if result.status != COMMAND_OK: + raise e.error_from_result(result, encoding=pgconn._encoding) + + return result + + +# Override functions with fast versions if available +if _psycopg: + connect = _psycopg.connect + cancel = _psycopg.cancel + execute = _psycopg.execute + send = _psycopg.send + fetch_many = _psycopg.fetch_many + fetch = _psycopg.fetch + pipeline_communicate = _psycopg.pipeline_communicate + +else: + connect = _connect + cancel = _cancel + execute = _execute + send = _send + fetch_many = _fetch_many + fetch = _fetch + pipeline_communicate = _pipeline_communicate diff --git a/backend/.venv/Lib/site-packages/psycopg/postgres.py b/backend/.venv/Lib/site-packages/psycopg/postgres.py new file mode 100644 index 0000000..3c2536f --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/postgres.py @@ -0,0 +1,158 @@ +""" +Types configuration specific to PostgreSQL. +""" + +# Copyright (C) 2020 The Psycopg Team + +from .abc import AdaptContext +from ._typemod import BitTypeModifier, CharTypeModifier, NumericTypeModifier +from ._typemod import TimeTypeModifier +from ._typeinfo import TypeInfo, TypesRegistry +from ._adapters_map import AdaptersMap + +# Global objects with PostgreSQL builtins and globally registered user types. +types = TypesRegistry() + +# Global adapter maps with PostgreSQL types configuration +adapters = AdaptersMap(types=types) + + +def register_default_types(types: TypesRegistry) -> None: + from .types.range import RangeInfo + from .types.multirange import MultirangeInfo + + # Use tools/update_oids.py to update this data. + for t in [ + TypeInfo('"char"', 18, 1002, typemod=CharTypeModifier), + # autogenerated: start + # Generated from PostgreSQL 17.0 + TypeInfo("aclitem", 1033, 1034), + TypeInfo("bit", 1560, 1561, typemod=BitTypeModifier), + TypeInfo("bool", 16, 1000, regtype="boolean"), + TypeInfo("box", 603, 1020, delimiter=";"), + TypeInfo("bpchar", 1042, 1014, regtype="character", typemod=CharTypeModifier), + TypeInfo("bytea", 17, 1001), + TypeInfo("cid", 29, 1012), + TypeInfo("cidr", 650, 651), + TypeInfo("circle", 718, 719), + TypeInfo("date", 1082, 1182), + TypeInfo("float4", 700, 1021, regtype="real"), + TypeInfo("float8", 701, 1022, regtype="double precision"), + TypeInfo("gtsvector", 3642, 3644), + TypeInfo("inet", 869, 1041), + TypeInfo("int2", 21, 1005, regtype="smallint"), + TypeInfo("int2vector", 22, 1006), + TypeInfo("int4", 23, 1007, regtype="integer"), + TypeInfo("int8", 20, 1016, regtype="bigint"), + TypeInfo("interval", 1186, 1187, typemod=TimeTypeModifier), + TypeInfo("json", 114, 199), + TypeInfo("jsonb", 3802, 3807), + TypeInfo("jsonpath", 4072, 4073), + TypeInfo("line", 628, 629), + TypeInfo("lseg", 601, 1018), + TypeInfo("macaddr", 829, 1040), + TypeInfo("macaddr8", 774, 775), + TypeInfo("money", 790, 791), + TypeInfo("name", 19, 1003), + TypeInfo("numeric", 1700, 1231, typemod=NumericTypeModifier), + TypeInfo("oid", 26, 1028), + TypeInfo("oidvector", 30, 1013), + TypeInfo("path", 602, 1019), + TypeInfo("pg_lsn", 3220, 3221), + TypeInfo("point", 600, 1017), + TypeInfo("polygon", 604, 1027), + TypeInfo("record", 2249, 2287), + TypeInfo("refcursor", 1790, 2201), + TypeInfo("regclass", 2205, 2210), + TypeInfo("regcollation", 4191, 4192), + TypeInfo("regconfig", 3734, 3735), + TypeInfo("regdictionary", 3769, 3770), + TypeInfo("regnamespace", 4089, 4090), + TypeInfo("regoper", 2203, 2208), + TypeInfo("regoperator", 2204, 2209), + TypeInfo("regproc", 24, 1008), + TypeInfo("regprocedure", 2202, 2207), + TypeInfo("regrole", 4096, 4097), + TypeInfo("regtype", 2206, 2211), + TypeInfo("text", 25, 1009), + TypeInfo("tid", 27, 1010), + TypeInfo( + "time", + 1083, + 1183, + regtype="time without time zone", + typemod=TimeTypeModifier, + ), + TypeInfo( + "timestamp", + 1114, + 1115, + regtype="timestamp without time zone", + typemod=TimeTypeModifier, + ), + TypeInfo( + "timestamptz", + 1184, + 1185, + regtype="timestamp with time zone", + typemod=TimeTypeModifier, + ), + TypeInfo( + "timetz", + 1266, + 1270, + regtype="time with time zone", + typemod=TimeTypeModifier, + ), + TypeInfo("tsquery", 3615, 3645), + TypeInfo("tsvector", 3614, 3643), + TypeInfo("txid_snapshot", 2970, 2949), + TypeInfo("uuid", 2950, 2951), + TypeInfo("varbit", 1562, 1563, regtype="bit varying", typemod=BitTypeModifier), + TypeInfo( + "varchar", 1043, 1015, regtype="character varying", typemod=CharTypeModifier + ), + TypeInfo("xid", 28, 1011), + TypeInfo("xid8", 5069, 271), + TypeInfo("xml", 142, 143), + RangeInfo("daterange", 3912, 3913, subtype_oid=1082), + RangeInfo("int4range", 3904, 3905, subtype_oid=23), + RangeInfo("int8range", 3926, 3927, subtype_oid=20), + RangeInfo("numrange", 3906, 3907, subtype_oid=1700), + RangeInfo("tsrange", 3908, 3909, subtype_oid=1114), + RangeInfo("tstzrange", 3910, 3911, subtype_oid=1184), + MultirangeInfo("datemultirange", 4535, 6155, range_oid=3912, subtype_oid=1082), + MultirangeInfo("int4multirange", 4451, 6150, range_oid=3904, subtype_oid=23), + MultirangeInfo("int8multirange", 4536, 6157, range_oid=3926, subtype_oid=20), + MultirangeInfo("nummultirange", 4532, 6151, range_oid=3906, subtype_oid=1700), + MultirangeInfo("tsmultirange", 4533, 6152, range_oid=3908, subtype_oid=1114), + MultirangeInfo("tstzmultirange", 4534, 6153, range_oid=3910, subtype_oid=1184), + # autogenerated: end + ]: + types.add(t) + + +def register_default_adapters(context: AdaptContext) -> None: + from .types import array, bool, composite, datetime, enum, json, multirange + from .types import net, none, numeric, numpy, range, string, uuid + + array.register_default_adapters(context) + composite.register_default_adapters(context) + datetime.register_default_adapters(context) + enum.register_default_adapters(context) + json.register_default_adapters(context) + multirange.register_default_adapters(context) + net.register_default_adapters(context) + none.register_default_adapters(context) + range.register_default_adapters(context) + string.register_default_adapters(context) + uuid.register_default_adapters(context) + + # Both numpy Decimal and uint64 dumpers use the numeric oid, but the former + # covers the entire numeric domain, whereas the latter only deals with + # integers. For this reason, if we specify dumpers by oid, we want to make + # sure to get the Decimal dumper. We enforce that by registering the + # numeric dumpers last. + numpy.register_default_adapters(context) + bool.register_default_adapters(context) + numeric.register_default_adapters(context) diff --git a/backend/.venv/Lib/site-packages/psycopg/pq/__init__.py b/backend/.venv/Lib/site-packages/psycopg/pq/__init__.py new file mode 100644 index 0000000..b9aee92 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/pq/__init__.py @@ -0,0 +1,137 @@ +""" +psycopg libpq wrapper + +This package exposes the libpq functionalities as Python objects and functions. + +The real implementation (the binding to the C library) is +implementation-dependant but all the implementations share the same interface. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import os +import logging +from typing import Callable + +from . import abc +from .misc import ConninfoOption, PGnotify, PGresAttDesc +from .misc import error_message, version_pretty +from ._enums import ConnStatus, DiagnosticField, ExecStatus, Format, Trace +from ._enums import Ping, PipelineStatus, PollingStatus, TransactionStatus + +logger = logging.getLogger(__name__) + +__impl__: str +"""The currently loaded implementation of the `!psycopg.pq` package. + +Possible values include ``python``, ``c``, ``binary``. +""" + +__build_version__: int +"""The libpq version the C package was built with. + +A number in the same format of `~psycopg.ConnectionInfo.server_version` +representing the libpq used to build the speedup module (``c``, ``binary``) if +available. + +Certain features might not be available if the built version is too old. +""" + +version: Callable[[], int] +PGconn: type[abc.PGconn] +PGresult: type[abc.PGresult] +Conninfo: type[abc.Conninfo] +Escaping: type[abc.Escaping] +PGcancel: type[abc.PGcancel] +PGcancelConn: type[abc.PGcancelConn] + + +def import_from_libpq() -> None: + """ + Import pq objects implementation from the best libpq wrapper available. + + If an implementation is requested try to import only it, otherwise + try to import the best implementation available. + """ + # import these names into the module on success as side effect + global __impl__, version, __build_version__ + global PGconn, PGresult, Conninfo, Escaping, PGcancel, PGcancelConn + + impl = os.environ.get("PSYCOPG_IMPL", "").lower() + module = None + attempts: list[str] = [] + + def handle_error(name: str, e: Exception) -> None: + if not impl: + msg = f"couldn't import psycopg '{name}' implementation: {e}" + attempts.append(msg) + else: + msg = f"couldn't import requested psycopg '{name}' implementation: {e}" + raise ImportError(msg) from e + + # The best implementation: fast but requires the system libpq installed + if not impl or impl == "c": + try: + from psycopg_c import pq as module # type: ignore + except Exception as e: + handle_error("c", e) + + # Second best implementation: fast and stand-alone + if not module and (not impl or impl == "binary"): + try: + from psycopg_binary import pq as module # type: ignore + except Exception as e: + handle_error("binary", e) + + # Pure Python implementation, slow and requires the system libpq installed. + if not module and (not impl or impl == "python"): + try: + from . import pq_ctypes as module # type: ignore[assignment] + except Exception as e: + handle_error("python", e) + + if module: + __impl__ = module.__impl__ + version = module.version + PGconn = module.PGconn + PGresult = module.PGresult + Conninfo = module.Conninfo + Escaping = module.Escaping + PGcancel = module.PGcancel + PGcancelConn = module.PGcancelConn + __build_version__ = module.__build_version__ + elif impl: + raise ImportError(f"requested psycopg implementation '{impl}' unknown") + else: + sattempts = "\n".join(f"- {attempt}" for attempt in attempts) + raise ImportError( + f"""\ +no pq wrapper available. +Attempts made: +{sattempts}""" + ) + + +import_from_libpq() + +__all__ = ( + "ConnStatus", + "PipelineStatus", + "PollingStatus", + "TransactionStatus", + "ExecStatus", + "Ping", + "DiagnosticField", + "Format", + "Trace", + "PGconn", + "PGnotify", + "Conninfo", + "PGresAttDesc", + "error_message", + "ConninfoOption", + "version", + "version_pretty", +) diff --git a/backend/.venv/Lib/site-packages/psycopg/pq/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/pq/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4496f6b3884a31f15e2b4bbc1eadb30042dee20c GIT binary patch literal 4114 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 uUB&J9JiAssyGk#wd7hi+|HZd6y9i;S literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/pq/__pycache__/_enums.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/pq/__pycache__/_enums.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..68bc5c413adebf2f6a08db12eed03f358071b07c GIT binary patch literal 5178 zcmcIoOK;oQ6(%L>{jl}$YvN4UCdkB7#F^=&Nsu<_$P#5MmMD!#JF#JaW<=UiBZ)F8 zx#KK43XlQ;i~i8-TsN$q&w-Z>~_=aJcx=Gv+B8*6fJ4g&9ozcm-jpO zLGqk)&-sqN4u$*_{C+3hD}OmdQGdsv|8rTLcYlM8Lt4omFO& zp(zKoOexM6l)|Wv*G_ZIri(~jAaxH&-9+jEsdqr?AyOYm{R2`jkp@5-9FY2mGz8M{ zfYeW<6Cj-&kOqh}0@CP!G)SZ|kj7P~{l1}tsfFohSNxUorq6F&>TWK-AGT7xx+kkxkB#uJq-!8Emmb-PGree1Wh zyI9}TvC{a3IPywTO|Ghvg#40J)s$uh_k)tO*OV*Ph)0qXtps96epSZ~i=0b|6!HjS zq9}4H#N-kw4n-0V6B#kXFH1#EDCBv8L!QK%xFY3Okz3$Ij$cOsLC8vE*;)a)d5%lL z@^Es6ORh=}iy1Mol!aAESiF|wP+(aQ?Abwc7Cds96H&-Suoa(L+CaWUHk(f-;AQ?q zy~9@ic0GA_>(`q8)TqlPb*uKPhH+gkm9%E9QLgP?FKN2E^;j-FRcp%D;=Wqj-^!LB zZyDu=dL0%#m3LKR%hJ}3`rZu*JFBr+KhQm}Icb8>F}{H21@(=?;qsn&sp$Ky2PZy% zYpKKB==#HlS6j&rbNMtJJ=|$6cLNiLw_2(0?EEYD8)m9&Nkfst^;WtYoo-)kt#&Om zHP>Em@%<^*SZtXWQvkt~(iTyIYwKb5Fn6f1~k-;t>pgze6!{NW3H1N1QQK z&?*&BspXGf5Kj}q`-Xkd&_LG>R%z-mmz9TnlPt;Xu-n^3E|CHU+TLa%6l`x}k1*kZ z)?};l0c)rg@M!k23b8_E>*k|bc~>r5KCXMQHcaRC>pl!{?9~If!6rlQbRv`GQl=k! ztS2Im^(;L^<|LA0W}VaL@hYO<_i>NyH`kzJ{2Ur=dj@PDG;JRWx6&Qvie(k2S#vk1cyd&cmz+3;K>mjF@qTQxmvQE z=Eq~42D?bLD%TV{pYq|es4;)ZEle=?uTL43dg$S1B9vYdds-ekV8 zA?4RZ9B81I;ZYF6*?H6o^Laj<5EEI6D;D!b6c_|PvSukSuAra*&Y9&TvNZ}7G6gQ1 z;Ws_!uOhH(I z=yK*T5zL1m(?_%O?fo}Q{LJAVn(B0UO((|hJ>H3b;NTMxb-8B9B*$64^s((rjq|aA zU^EDJzSRh zy37YBk&9NM?R!5YQ^=xy1bz?6w2#2!;lvPRst<2CUVV39{%?ql_+%}cw z544h|V%!uk6v#+@G!errP9r*t=pw%`Gv1dpT|r)fTjzjeZJ?=sPlDu!sdP583Dn#xe3k`{Eplig z#|c7WnUe~|OfFH}K;gb1#fiYEP_U0zAUdKbS(W2>Q7YsGpmE@^5g6c#Jmghd6t+bq zZxiY-a*rTF2te?235icY9pEQ*f!Plv^Vzi=Z-P(?(zLiy;7mAy3kQhIu&Fg!$gdTX zoRkK}2V0r|=V&z1A6esp>gB%^xH)iP9XDUYW&9bM;lPbEZtUoj!_QkQ-T6y@aK2i3 z!_0LjqLyfS?)Y;1Nh{x-nmvxS9|4z-O&=NUJHX%P=8uI}vu~K`?(Bu*EGshPuEK%& zY1;$Gj1&)Vv4;2s_t>Mu5D#@PWq3FTqtUkl3w7N511ND=#Kn)F-SPfmPu)u>#*i8L@1uA8*$_+!+_f?&c>}CxVcK$bk znTM+IMsLkJYP=R=!djsKmA)W}894f4B3BSlu*fYFSuUUYPWiM4Tk5#^H(bUgXokISdi7s6)s#^6F+$C*fHaO1)asmWQ~BQ%n+aE-j}y~6x@0@qcH0sUgGV2_#S=fXtzhf at#>y>&%XpY+RqT@J*6DOf!XIFKVy3*ZlT{(NZIoI9Q)rh1b2=QL%+tl6W>gtMK`8L^H z?(uieGAbxYVHSx6~LA}Ot;6vN`EO|p&JCHtsDau8lC(43NU)Frt_ z-I9B>Kq?q5lnO_Sq@vMcshIHC!X=}nQt4=!R0eIk>k6G9&$ORV#xe(bt zwrC7e1ITuuh8$NTvW#rISB_kCx>FF8W6<;Vd*6=ix|b#w=VZ2^mbh6iky`!{<8H~J zTT$!CzI)|MZODyWLuSdKwV9!4M1%) zP}h)^>&oeAEoraJwbzk$cdq>aX|Kw)*OPWnuDyY@SLfOrNqbGM{UGv;#F!pwP1=N9 z!zQ%JpwYF^%4rl(3gu;`^bkQk#GxMIPzlCOYtm-47W&$3K)Io1?CUJ$Wu>$QR(y*A z^8mDrnDdO6)}*cI0qAKfL&+9s8Br6ImzC1PWPA@Z6nX$X%%LV3H?2wAkc;TrMRh%F zM%y?U+c+7|Q6wv+M@Y|)FcggU5e}7P+_WZbC#dZlYCDH|k@B)q+Cfk|7z%dc4i0sZ zanqW#lc08TsGS_@70Sy>X&14RT^wo`hniyCv?lE)eeE`&Txd6kx}PT!POz+fa~<)0*@sK|RW$9_3Io zl$Vv#L4rESp$>AWZ!vCKlMWHoAp^>d4sob&Q(jg|eFW9Vq53$~cNjOVNr%x|uskz5 zY{0poW%K}P%FRltpY+ymK)F#rhx#t#rZs7RpawY90EhaB^0HDoLQqExC>J`yp?<)) zX-zsxP)7|YH#*9pW+^W#rN;>BF%I<@hx!rYrZwqtf_j`oJg)WZ0k;l4$>IJ5$uYf zoEx3ya2d+YN-3=4!W=Hl;j)aM)}&FgdZQd_ltX<^d08n%aBpCl78GGf;%l7Li^3b@ zp7_rUO>0s#Cnd_HfZQmDT%`Q0lwvt#j6=pac2B?T9d{IYRrK0p)n5iKPWFN zrL)*qq5@dSvkaNHl4m(7|C6CD9Pam&o0ZaYWR3rMvC?x~pU-i9 z{$JJ?tx3<5K9`G?p64VzZB@b7$4DMBedzHhz znujY{1~&zIz%kbphn&homMw#vCOuAbxamAx#WJ`{1b2zUUCP5%Era_8!F_|neZzpG z*3w9HTeFOW%lcd|b22V78G7cS!?41aA)BGa?f-|!ty@O!Yh+}v8KiDNuQ90v=UE2# zO|$`G>u(xxZfF^NG1zY7GPo-QcZI`U$-{YtI6Ur(B(RS;xb=*m)}(J?zfEHCZyB&|^sPMXMv7pi^q%hX-{X+)*WV>^ZGF7otsEMyP14ilfJ9< z12O-1Sub$I`R+ZEHyC!*cZs}SDutEO_jLV#kCXO2CXFEXF$AqiACY_9gD{eh3|Kd` za$XQ-ZwHGgM(c84JHJol9i&oNDg6LO@_kqb3;KaU-uI!ElLz|I?CCWkrH`R$P5L3R zfFBwpxX}*{5^x07Pq|qs%@W)!hnvmA9bx>mCS4=AYaH%c9_}&9%}VJ<1otBj_oF=A zF~(18(#Hh%F^Bt@;Ue%=6Qa6}hTZZ*LV3_YnI)7>2Ff);dB{Nd5ut20P(CI)f0B-b zmC`39pI}Cxuu;LPf5Jv3ZXUXw6x8MpWznW%S#LxZt1 z-as&j;&Ja-JQNxB1{32k6nFg^_vbTZ-GN9Xng}F9(MY_{XURH`CX}&YVoX6<=dRwz z`*uC{RR5l=z5nq3zQ^_)@!7Mspg(vjpky6d>5pZtL4PQcz=U{c0{IhJd(b~NIG#Y5 zcT9hEHX4%sF`qeW*%2AfI{KnV5OfmxHU0$vP%DN)5!p|M>mM2mhyAfY;#9WiEK=ey zGJi}#iNyG?@f8EcT-p~+936|rqDlhEdlV(AOjK(#g{Klw#=S5l?@)9sA_ws_>7V{< z1Jhj`T3;2AAerD-66SFe3_$GNe{c_0fWz;P1V)kHpLO~DqfvP*jOzt{|CzBsSbK9# zxQj*pPTIBk#JQ+)IvxuI(TT`NBEAY#4c#U{(W`<{1)UfS1W%)ge4^(pikv-hFf@1~ z9!j8905}~OM)4D|_;@fH8(tkdv)Ug!h@xjIe8LPGZaE$IqvVfW>u>3KyVzb)Zzz@470_4zrmdRegzL+ z8!{e+;-wGV^W8#tyewooe93)kQQLy((>O8HKY1p_{d*M@9}6e+xhTybjSQ|&X~osN z5p`f1er(4T{Id&f5SYXbLcb-N?&5=+sS^}w88XXe^0bhrNS;>mw2`MBi9_aLyJQ`A z_?+45{sFA)P-G~2IEMF~KGdxJG#UqUlCw6jm9u1vMMq|rkBh>hvn;hwbu?t0rKwG-!;^8A zr=C&|WHbl-OR_r|AvL(rl&1~k zYuZ1yW(7Y^@Poi4ZV-RW{Zrknjtv}d2x>O1Q$?&eY4dyVQ@#WiOa7)UG*Jt5GovT;jVB0(_m=l9{Be59Ppssc z{y_wGfqJ%vqrpHpzO9FQ`&WREnCY&?QtVn1EKV2kXFi*PLv;n`)Rg_SmbF1R0>O(? zj45^SfQcW#^+)jo2jg+PK+inm)#g&c4No7ug2U~<#Jo83_76$n@6DpswNxM!)T&|) z=|1%7f=S4_`Ug(IiUed?36;#4;h2RJBpi*Seg(w>3LFoGlmHPC92DjK191pCc5ytV zMxw@7fk}y7r^X_uk$fb2E`BH~qihif(|nnN0uaPu;iP>u5l|A@658Aex<3tpPPTwj z`lI16g9CeFEN*B6J4$4sQ%xKR+zvrt3V{&o-8~P_S4&{aL!cQJE|ow@ zevo@XfFH<~%9e}b1yjNX+~iLdC!oAwPT>7d{wB?IzitpNSSBqaZu*9mH0&S2@l@U) zeRn~W;RnI8K(EFoVX9=vBwH^!64-{x-}55vYqvmgC%~0muwJlD0)En32jRjMd(eCe zT-?cScw?WmkCak8E9IP*iJLB0PTJw8!9txdQqDMNO?JpmIwskK1IahcmwQCvg5!dH zSh(O!R8melq7fW-=KaxkyM>eQz)6P3?7HBdbWJ+W3X18nJAnn0ze)FGP6sfy8t9{d zX<*Vlf;V&CAJfW7hzg1H!V5){1tSf4jL?)_lZCPquOfJ3w^^7p!6*tRi|BRzJ>mVF zmQBKCp9nvV#yp^1_j1Wxin~xe>0Guy+oTJ6a>xZEIMm7eo6LRS1D?XkVt5w4Z>RHt z{%1sC(m5$kTD37x+UfSIDBP&3LZXO7@huIyF!%_yj~S1%}LX^Y0{j?F^qxvjKc|?(A6LaW8kf!ojY8i?SOV}3loF| zD0;j^5XF<`k!8LD$s)PCi<71oOykyZ+kLp~V8q?PQ+A*C4!pTwX`SywB$3EDfj`7e zReluayzIza&}X^qzRz3QW5N5D`${Mz5{kZ#gad*M8iE;=Ou{^1gXsE)5T&#)EA~Yr zh#bIK3(h4t5BB@@6oeHg8R8QKr0`C9F(5TW z2L_y#m~i_0qriuh;}az?u#SXRMuD*RTqtqMJ0U{w<%Jj+FT57-;?qaL_NI_aAaM`n7|THkE7TD?{+ zS^KN%x|y{fY<_ohI*=Zm**0I@rIvK*Qq=m*Hw!msDjR3cd@%9u#BB3y%gl3XW6x|r zEnlM+tjTp|$DP@svl5}I=|0R$Hlc8<>gk>xnB6s-xW4E5gKFKD`GPH}4J1CxnnJ-` zWDW|!4h8O!rn@)z zK@`SKKen8M1l2_AiFgo}{PsCStLTIQYCLtd2^?|Rm!fh#d3bui{XN~e4 z$j*v5MHMf~2L>Ucve~r7(nmQF6?`ADv zgcIh?-U)NJcf#uPuG$90W^YeVPu6rUYjXJ77zmfMcF-}VWW^EKuvzOl z1yH_HG8E+k9*=n_k~IyH+#U37gFG9KsYSS2$;ykE!FoCpJr{wYgoYy!KZ8K!VNAC~ z2S>6t2=@b{ak8vL1*AuOk0Mi#<5&zfH21e%zfN&0tb7EVzrp($9|f?WzYq)mTJ+u( z+pSx_>Ng24xB*W$CU<`BESws=T$38el$2hzy>5Hcal54TW=ZRO$%-lKZ!Exf*9MmG zt7>n$a-q88t`!d2JiO3`#tDn7Gg-T^yy-qAc8S+WRl4-x>h3Q?1tNz#hKd)?` zb^kTn)7=5eCI=I$L1R=KDFN%|IDh^_1$tD zUaA$UI+i?ww=214sy(%Kx+|4XMbEFWCR44K8)lj_4(Ap7v^^zWb-wPLSutPYU2rhs z<-*@s1y}V{!*3n|^-kCP{_n~_6Tj&uwBN;BVc|Y%>TR_A)K}HJQv3^{4xWG2x~_MP zwNVvSY&^4TK_oKU`tS)s*a`M**#j;0M_@cmw&&T0Mm8f10)X{c<#@ zWxt2UumM6E7oUG{gp9|POStCN)6`>$P*}m6TEUJ_!9kE>#}9Ju;7g2l47qWQoJ#nR zA~_tmH)`7#Uq78 z%G-D#SMk8$Y71|UXw*f7QO7e{)l}A!(B(DUwb}grlhf$ErO5+y3 z0rLr9od>c6IPHmBB{Yvm5{mkJJt)!NgKMBkG)!@8Qc*A=50d*cbODW{#KGV@yw=X$ z(V+=WIRL40?T)UGs8>MkLLh zTBIu*zB)rNBlZu#xS%x_M+z=ua9hVEPHm7>h;kV8N#4LBXRZAMkl@QY`v;;VNgl`j zg15ve1-Q3E{x=d21abNtI>kiDZxHW@AWkxnlxQLf$wYk#@ob=f$T(2~TUU z2|teG#|iv62@ic>yU3jjZ-gOmHhK$&rMWk38N?BWz)C<%Fy>v+*!b>1B7h-!a}PvY z@Diq(dkJF&uMkAa)3__J9QY24+r&Phqfs=f`0-Gl!SBI`j0R4lJ)^P2IQ7oDMl{8N zZ&l)$f(H{sM^F%jz;9?PmFVM$N&w3p#E&3;$oPTafyW5GGI1D=m7_-wlCVqrT2Y5t z$j4j{=5uU?-2$JQw<(Pfkl`Cb{Qtpu2uW#^=}WWOB>t}g!PNRUg6kJT;V*=;UkYn( z3Tu8T9KJ0az9}63rQrQV`9g7y*t6N{#ntE`~QkN;Nyz=by zv$u;oZWedUTIP$pll$(t%i&T~(JEJ_x_wa;Fd zwBV6-rS{{Ib$#W)^^jh7nrt&rhvKUmtI3AxP<&MaJTt!g@BXg%$KiLg_7l|OJzcF>6OTIB)HuU6~U=x-aew}r)5PEMapx-!+xsc_N-;&Uo5B9G*Qj-~OOlzbRR~Ak<{)dT?322v;~*%%mez*_1k%bSwy^neu8} zmMppou5?XzCGDAt#?;oN9Y~q7s-*p5@ggWeThH3onF4M_7mG@$ep*tKx_;`3eiohX zE4956ptdhdMc zmgIr^_v3I~aZEds)=ZfvT~^sO znzE~EZdY~Rtm;-_0li%_lTa=Qo=jsasnjo4RNb!Vyjjty!U8pR&UUH|4?uN6sDrg7 zmD)U(nG^JVv;N*_5A8EsbvtO%?7(PcSRtC}Hfu(2l> zYtk^D+6AE{)8-?U=EeGk+w~i7)^Ak799OJPAB1v2XwJ049HHV}T+X!Xh-t%C1LM?< zsbS{4TGpxAMgy@8I;KUjC?ghRMCTpRJ+Veowa6S$6z2e zZNxVj*D>8WyYD*sS5JI;^v_PHl?U`i^=gaCG{^O~d`HEOdNa{2xRSbdO}mxVw=27D zR(7diDNVlFO={zMs4fWgnFdf5RO%MXD{q&#-z;wj&y;ECn5|Jg>!7*-immS;m6}CM ziDuW>kUDQxbtVsk9nJ1jn>Hj5FNk1CUAWW?sqJP(Tk;UKqvW9l5zMGFdFYl{3-{pa zmFmi^H-_e`_9PGAspy<-y3sygu_JlN=%ng9W_olRX(Y3ND|=1d?dqPJ)ji-;GtH~g zMNlpX4VfkwAyhoT0b^q`T{-)>+6YFh&2)u6Q|5HMsclB516~3QLf=^}si*ZtsMQvM zZMu7286>7xsO6oy&^qkNU`&A29bj{MgIeL!ePETgEtxxOOCzIe8q{jv9kN$0Nu2W8r-CH@~yd3JcVrJmD!Z6q%Z=f*v+m>+0OMaXGt9CFI_^dH*KG<=_FAC^v$NL<8qx@EgmzOI0SX|E$NQ=x-K$zmd(smtw*ixy7wcrV>GOep-&#NtP)Ko19O_^p`H>kijhFWk*bGl1f zIs2sQh0{j!N+1P$rJUca^W3gmGgk*;b9JVz=ek2}eF&-xqBqmhK`Kp);NWVy=W4oD zu`<)rJ$p)Reh{h)Vq?a;0xGw}2JoH`qpjZk>Ck-LAwb;$=2hE2ZJ)2%4-CY}FOlGp z1xGEK{SynD(?Umf{%XFJ#0{77f;9d7B`3pN?qsM`Jve+NCxcf%8OXUmr^SKyocq{G zUCImch@+wIdX64UGhuDRWbks6T|ti=e2}l3t6v8{Ux9=CdZpS1dZ}3u$yqMe+!DQC zfL7M@erB7mKMZd`G>yXWerunrY)|&V(Ki!L_Q4UAX;_8JI{(GA;tIZW_QrOyE28l2uaX+}11EZ9ff$24&`bqU|zYFEq@ z>Ct|@79-)n5E~{4sHi0;Cb%0o1x{YdyOK0he+_nC;+@lPLEs{+YVAheHL&hl(@&~3 zJ$jGYjZt%)6t7=uZd9tZk8na@6fiVu*lCAa?lZ;`xlK=kr8ycb?NOW7>A_M<^6)LO z{tH-(Tqr~W!b^F9eGLgez@Tw#qP=WPNqQWhz07rn6+1~HLCaJw8HhsJeJ-xdt$zPGrY`` ztafj`aY}94ONB#3h=m)ryNZO5{*`xaeI`@Y(x6!o3#KOKEVXyU(w7gz$0)ImB#8b$)A9{^ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/pq/__pycache__/abc.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/pq/__pycache__/abc.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fbe18aaa2a8f690db9c9ce2741910ff3f4369901 GIT binary patch literal 18861 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%0A&PaJ=h|n;WA9M1t*Yxs$mU>*FDGrIfCjt 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 Y@LgVeIdog7_-V str: + cls = f"{self.__class__.__module__}.{self.__class__.__qualname__}" + info = connection_summary(self._pgconn) + return f"<{cls} {info} at 0x{id(self):x}>" + + def __getattr__(self, attr: str) -> Any: + value = getattr(self._pgconn, attr) + if callable(value): + return debugging(value) + else: + logger.info("PGconn.%s -> %s", attr, value) + return value + + def __setattr__(self, attr: str, value: Any) -> None: + setattr(self._pgconn, attr, value) + logger.info("PGconn.%s <- %s", attr, value) + + @classmethod + def connect(cls, conninfo: bytes) -> Self: + return cls(debugging(PGconn.connect)(conninfo)) + + @classmethod + def connect_start(cls, conninfo: bytes) -> Self: + return cls(debugging(PGconn.connect_start)(conninfo)) + + @classmethod + def ping(self, conninfo: bytes) -> int: + return debugging(PGconn.ping)(conninfo) + + +def debugging(f: Func) -> Func: + """Wrap a function in order to log its arguments and return value on call.""" + + @wraps(f) + def debugging_(*args: Any, **kwargs: Any) -> Any: + reprs = [] + for arg in args: + reprs.append(f"{arg!r}") + for k, v in kwargs.items(): + reprs.append(f"{k}={v!r}") + + logger.info("PGconn.%s(%s)", f.__name__, ", ".join(reprs)) + rv = f(*args, **kwargs) + # Display the return value only if the function is declared to return + # something else than None. + ra = inspect.signature(f).return_annotation + if ra is not None or rv is not None: + logger.info(" <- %r", rv) + return rv + + return debugging_ # type: ignore diff --git a/backend/.venv/Lib/site-packages/psycopg/pq/_enums.py b/backend/.venv/Lib/site-packages/psycopg/pq/_enums.py new file mode 100644 index 0000000..5d0cdf9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/pq/_enums.py @@ -0,0 +1,259 @@ +""" +libpq enum definitions for psycopg +""" + +# Copyright (C) 2020 The Psycopg Team + +from enum import IntEnum, IntFlag, auto + +# Check in src/interfaces/libpq/libpq-fe.h for updates. + + +class ConnStatus(IntEnum): + """ + Current status of the connection. + """ + + __module__ = "psycopg.pq" + + OK = 0 + """The connection is in a working state.""" + BAD = auto() + """The connection is closed.""" + + STARTED = auto() + MADE = auto() + AWAITING_RESPONSE = auto() + AUTH_OK = auto() + SETENV = auto() + SSL_STARTUP = auto() + NEEDED = auto() + CHECK_WRITABLE = auto() + CONSUME = auto() + GSS_STARTUP = auto() + CHECK_TARGET = auto() + CHECK_STANDBY = auto() + ALLOCATED = auto() # Only for cancel connections. + """Connection to the server hasn't been initiated yet.""" + + +class PollingStatus(IntEnum): + """ + The status of the socket during a connection. + + If ``READING`` or ``WRITING`` you may select before polling again. + """ + + __module__ = "psycopg.pq" + + FAILED = 0 + """Connection attempt failed.""" + READING = auto() + """Will have to wait before reading new data.""" + WRITING = auto() + """Will have to wait before writing new data.""" + OK = auto() + """Connection completed.""" + + ACTIVE = auto() + + +class ExecStatus(IntEnum): + """ + The status of a command. + """ + + __module__ = "psycopg.pq" + + EMPTY_QUERY = 0 + """The string sent to the server was empty.""" + + COMMAND_OK = auto() + """Successful completion of a command returning no data.""" + + TUPLES_OK = auto() + """ + Successful completion of a command returning data (such as a SELECT or SHOW). + """ + + COPY_OUT = auto() + """Copy Out (from server) data transfer started.""" + + COPY_IN = auto() + """Copy In (to server) data transfer started.""" + + BAD_RESPONSE = auto() + """The server's response was not understood.""" + + NONFATAL_ERROR = auto() + """A nonfatal error (a notice or warning) occurred.""" + + FATAL_ERROR = auto() + """A fatal error occurred.""" + + COPY_BOTH = auto() + """ + Copy In/Out (to and from server) data transfer started. + + This feature is currently used only for streaming replication, so this + status should not occur in ordinary applications. + """ + + SINGLE_TUPLE = auto() + """ + The PGresult contains a single result tuple from the current command. + + This status occurs only when single-row mode has been selected for the + query. + """ + + PIPELINE_SYNC = auto() + """ + The PGresult represents a synchronization point in pipeline mode, + requested by PQpipelineSync. + + This status occurs only when pipeline mode has been selected. + """ + + PIPELINE_ABORTED = auto() + """ + The PGresult represents a pipeline that has received an error from the server. + + PQgetResult must be called repeatedly, and each time it will return this + status code until the end of the current pipeline, at which point it will + return PGRES_PIPELINE_SYNC and normal processing can resume. + """ + TUPLES_CHUNK = auto() + """The PGresult contains several result tuples from the current command. + + This status occurs only when chunked mode has been selected for the query. + """ + + +class TransactionStatus(IntEnum): + """ + The transaction status of a connection. + """ + + __module__ = "psycopg.pq" + + IDLE = 0 + """Connection ready, no transaction active.""" + + ACTIVE = auto() + """A command is in progress.""" + + INTRANS = auto() + """Connection idle in an open transaction.""" + + INERROR = auto() + """An error happened in the current transaction.""" + + UNKNOWN = auto() + """Unknown connection state, broken connection.""" + + +class Ping(IntEnum): + """Response from a ping attempt.""" + + __module__ = "psycopg.pq" + + OK = 0 + """ + The server is running and appears to be accepting connections. + """ + + REJECT = auto() + """ + The server is running but is in a state that disallows connections. + """ + + NO_RESPONSE = auto() + """ + The server could not be contacted. + """ + + NO_ATTEMPT = auto() + """ + No attempt was made to contact the server. + """ + + +class PipelineStatus(IntEnum): + """Pipeline mode status of the libpq connection.""" + + __module__ = "psycopg.pq" + + OFF = 0 + """ + The libpq connection is *not* in pipeline mode. + """ + ON = auto() + """ + The libpq connection is in pipeline mode. + """ + ABORTED = auto() + """ + The libpq connection is in pipeline mode and an error occurred while + processing the current pipeline. The aborted flag is cleared when + PQgetResult returns a result of type PGRES_PIPELINE_SYNC. + """ + + +class DiagnosticField(IntEnum): + """ + Fields in an error report. + """ + + __module__ = "psycopg.pq" + + # from src/include/postgres_ext.h + + SEVERITY = ord("S") + SEVERITY_NONLOCALIZED = ord("V") + SQLSTATE = ord("C") + MESSAGE_PRIMARY = ord("M") + MESSAGE_DETAIL = ord("D") + MESSAGE_HINT = ord("H") + STATEMENT_POSITION = ord("P") + INTERNAL_POSITION = ord("p") + INTERNAL_QUERY = ord("q") + CONTEXT = ord("W") + SCHEMA_NAME = ord("s") + TABLE_NAME = ord("t") + COLUMN_NAME = ord("c") + DATATYPE_NAME = ord("d") + CONSTRAINT_NAME = ord("n") + SOURCE_FILE = ord("F") + SOURCE_LINE = ord("L") + SOURCE_FUNCTION = ord("R") + + +class Format(IntEnum): + """ + Enum representing the format of a query argument or return value. + + These values are only the ones managed by the libpq. `~psycopg` may also + support automatically-chosen values: see `psycopg.adapt.PyFormat`. + """ + + __module__ = "psycopg.pq" + + TEXT = 0 + """Text parameter.""" + BINARY = 1 + """Binary parameter.""" + + +class Trace(IntFlag): + """ + Enum to control tracing of the client/server communication. + """ + + __module__ = "psycopg.pq" + + SUPPRESS_TIMESTAMPS = 1 + """Do not include timestamps in messages.""" + + REGRESS_MODE = 2 + """Redact some fields, e.g. OIDs, from messages.""" diff --git a/backend/.venv/Lib/site-packages/psycopg/pq/_pq_ctypes.py b/backend/.venv/Lib/site-packages/psycopg/pq/_pq_ctypes.py new file mode 100644 index 0000000..f3a7b14 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/pq/_pq_ctypes.py @@ -0,0 +1,841 @@ +""" +libpq access using ctypes +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import sys +import ctypes +import ctypes.util +from ctypes import Structure, CFUNCTYPE, POINTER +from ctypes import c_char, c_char_p, c_int, c_size_t, c_ubyte, c_uint, c_void_p +from typing import Any, NoReturn + +from .misc import find_libpq_full_path, version_pretty +from ..errors import NotSupportedError + +libname = find_libpq_full_path() +if not libname: + raise ImportError("libpq library not found") + +pq = ctypes.cdll.LoadLibrary(libname) + + +class FILE(Structure): + pass + + +FILE_ptr = POINTER(FILE) + +if sys.platform == "linux": + libcname = ctypes.util.find_library("c") + if not libcname: + # Likely this is a system using musl libc, see the following bug: + # https://github.com/python/cpython/issues/65821 + libcname = "libc.so" + libc = ctypes.cdll.LoadLibrary(libcname) + + fdopen = libc.fdopen + fdopen.argtypes = (c_int, c_char_p) + fdopen.restype = FILE_ptr + + +# Get the libpq version to define what functions are available. + +PQlibVersion = pq.PQlibVersion +PQlibVersion.argtypes = [] +PQlibVersion.restype = c_int + +libpq_version = PQlibVersion() + + +# libpq data types + + +Oid = c_uint + + +class PGconn_struct(Structure): + _fields_: list[tuple[str, type]] = [] + + +class PGresult_struct(Structure): + _fields_: list[tuple[str, type]] = [] + + +class PQconninfoOption_struct(Structure): + _fields_ = [ + ("keyword", c_char_p), + ("envvar", c_char_p), + ("compiled", c_char_p), + ("val", c_char_p), + ("label", c_char_p), + ("dispchar", c_char_p), + ("dispsize", c_int), + ] + + +class PGnotify_struct(Structure): + _fields_ = [ + ("relname", c_char_p), + ("be_pid", c_int), + ("extra", c_char_p), + ] + + +class PGcancelConn_struct(Structure): + _fields_: list[tuple[str, type]] = [] + + +class PGcancel_struct(Structure): + _fields_: list[tuple[str, type]] = [] + + +class PGresAttDesc_struct(Structure): + _fields_ = [ + ("name", c_char_p), + ("tableid", Oid), + ("columnid", c_int), + ("format", c_int), + ("typid", Oid), + ("typlen", c_int), + ("atttypmod", c_int), + ] + + +PGconn_ptr = POINTER(PGconn_struct) +PGresult_ptr = POINTER(PGresult_struct) +PQconninfoOption_ptr = POINTER(PQconninfoOption_struct) +PGnotify_ptr = POINTER(PGnotify_struct) +PGcancelConn_ptr = POINTER(PGcancelConn_struct) +PGcancel_ptr = POINTER(PGcancel_struct) +PGresAttDesc_ptr = POINTER(PGresAttDesc_struct) + + +# Function definitions as explained in PostgreSQL 12 documentation + +# 33.1. Database Connection Control Functions + +# PQconnectdbParams: doesn't seem useful, won't wrap for now + +PQconnectdb = pq.PQconnectdb +PQconnectdb.argtypes = [c_char_p] +PQconnectdb.restype = PGconn_ptr + +# PQsetdbLogin: not useful +# PQsetdb: not useful + +# PQconnectStartParams: not useful + +PQconnectStart = pq.PQconnectStart +PQconnectStart.argtypes = [c_char_p] +PQconnectStart.restype = PGconn_ptr + +PQconnectPoll = pq.PQconnectPoll +PQconnectPoll.argtypes = [PGconn_ptr] +PQconnectPoll.restype = c_int + +PQconndefaults = pq.PQconndefaults +PQconndefaults.argtypes = [] +PQconndefaults.restype = PQconninfoOption_ptr + +PQconninfoFree = pq.PQconninfoFree +PQconninfoFree.argtypes = [PQconninfoOption_ptr] +PQconninfoFree.restype = None + +PQconninfo = pq.PQconninfo +PQconninfo.argtypes = [PGconn_ptr] +PQconninfo.restype = PQconninfoOption_ptr + +PQconninfoParse = pq.PQconninfoParse +PQconninfoParse.argtypes = [c_char_p, POINTER(c_char_p)] +PQconninfoParse.restype = PQconninfoOption_ptr + +PQfinish = pq.PQfinish +PQfinish.argtypes = [PGconn_ptr] +PQfinish.restype = None + +PQreset = pq.PQreset +PQreset.argtypes = [PGconn_ptr] +PQreset.restype = None + +PQresetStart = pq.PQresetStart +PQresetStart.argtypes = [PGconn_ptr] +PQresetStart.restype = c_int + +PQresetPoll = pq.PQresetPoll +PQresetPoll.argtypes = [PGconn_ptr] +PQresetPoll.restype = c_int + +PQping = pq.PQping +PQping.argtypes = [c_char_p] +PQping.restype = c_int + + +# 33.2. Connection Status Functions + +PQdb = pq.PQdb +PQdb.argtypes = [PGconn_ptr] +PQdb.restype = c_char_p + +PQuser = pq.PQuser +PQuser.argtypes = [PGconn_ptr] +PQuser.restype = c_char_p + +PQpass = pq.PQpass +PQpass.argtypes = [PGconn_ptr] +PQpass.restype = c_char_p + +PQhost = pq.PQhost +PQhost.argtypes = [PGconn_ptr] +PQhost.restype = c_char_p + + +def not_supported_before(fname: str, pgversion: int) -> Any: + def not_supported(*args: Any, **kwargs: Any) -> NoReturn: + raise NotSupportedError( + f"{fname} requires libpq from PostgreSQL {version_pretty(pgversion)} on" + f" the client; version {version_pretty(libpq_version)} available instead" + ) + + return not_supported + + +if libpq_version >= 120000: + PQhostaddr = pq.PQhostaddr + PQhostaddr.argtypes = [PGconn_ptr] + PQhostaddr.restype = c_char_p +else: + PQhostaddr = not_supported_before("PQhostaddr", 120000) + +PQport = pq.PQport +PQport.argtypes = [PGconn_ptr] +PQport.restype = c_char_p + +PQtty = pq.PQtty +PQtty.argtypes = [PGconn_ptr] +PQtty.restype = c_char_p + +PQoptions = pq.PQoptions +PQoptions.argtypes = [PGconn_ptr] +PQoptions.restype = c_char_p + +PQstatus = pq.PQstatus +PQstatus.argtypes = [PGconn_ptr] +PQstatus.restype = c_int + +PQtransactionStatus = pq.PQtransactionStatus +PQtransactionStatus.argtypes = [PGconn_ptr] +PQtransactionStatus.restype = c_int + +PQparameterStatus = pq.PQparameterStatus +PQparameterStatus.argtypes = [PGconn_ptr, c_char_p] +PQparameterStatus.restype = c_char_p + +PQprotocolVersion = pq.PQprotocolVersion +PQprotocolVersion.argtypes = [PGconn_ptr] +PQprotocolVersion.restype = c_int + +PQserverVersion = pq.PQserverVersion +PQserverVersion.argtypes = [PGconn_ptr] +PQserverVersion.restype = c_int + +PQerrorMessage = pq.PQerrorMessage +PQerrorMessage.argtypes = [PGconn_ptr] +PQerrorMessage.restype = c_char_p + +PQsocket = pq.PQsocket +PQsocket.argtypes = [PGconn_ptr] +PQsocket.restype = c_int + +PQbackendPID = pq.PQbackendPID +PQbackendPID.argtypes = [PGconn_ptr] +PQbackendPID.restype = c_int + +PQconnectionNeedsPassword = pq.PQconnectionNeedsPassword +PQconnectionNeedsPassword.argtypes = [PGconn_ptr] +PQconnectionNeedsPassword.restype = c_int + +PQconnectionUsedPassword = pq.PQconnectionUsedPassword +PQconnectionUsedPassword.argtypes = [PGconn_ptr] +PQconnectionUsedPassword.restype = c_int + +PQsslInUse = pq.PQsslInUse +PQsslInUse.argtypes = [PGconn_ptr] +PQsslInUse.restype = c_int + +# TODO: PQsslAttribute, PQsslAttributeNames, PQsslStruct, PQgetssl + + +# 33.3. Command Execution Functions + +PQexec = pq.PQexec +PQexec.argtypes = [PGconn_ptr, c_char_p] +PQexec.restype = PGresult_ptr + +PQexecParams = pq.PQexecParams +PQexecParams.argtypes = [ + PGconn_ptr, + c_char_p, + c_int, + POINTER(Oid), + POINTER(c_char_p), + POINTER(c_int), + POINTER(c_int), + c_int, +] +PQexecParams.restype = PGresult_ptr + +PQprepare = pq.PQprepare +PQprepare.argtypes = [PGconn_ptr, c_char_p, c_char_p, c_int, POINTER(Oid)] +PQprepare.restype = PGresult_ptr + +PQexecPrepared = pq.PQexecPrepared +PQexecPrepared.argtypes = [ + PGconn_ptr, + c_char_p, + c_int, + POINTER(c_char_p), + POINTER(c_int), + POINTER(c_int), + c_int, +] +PQexecPrepared.restype = PGresult_ptr + +PQdescribePrepared = pq.PQdescribePrepared +PQdescribePrepared.argtypes = [PGconn_ptr, c_char_p] +PQdescribePrepared.restype = PGresult_ptr + +PQdescribePortal = pq.PQdescribePortal +PQdescribePortal.argtypes = [PGconn_ptr, c_char_p] +PQdescribePortal.restype = PGresult_ptr + +if libpq_version >= 170000: + PQclosePrepared = pq.PQclosePrepared + PQclosePrepared.argtypes = [PGconn_ptr, c_char_p] + PQclosePrepared.restype = PGresult_ptr + + PQclosePortal = pq.PQclosePortal + PQclosePortal.argtypes = [PGconn_ptr, c_char_p] + PQclosePortal.restype = PGresult_ptr + +else: + PQclosePrepared = not_supported_before("PQclosePrepared", 170000) + PQclosePortal = not_supported_before("PQclosePortal", 170000) + +PQresultStatus = pq.PQresultStatus +PQresultStatus.argtypes = [PGresult_ptr] +PQresultStatus.restype = c_int + +# PQresStatus: not needed, we have pretty enums + +PQresultErrorMessage = pq.PQresultErrorMessage +PQresultErrorMessage.argtypes = [PGresult_ptr] +PQresultErrorMessage.restype = c_char_p + +# TODO: PQresultVerboseErrorMessage + +PQresultErrorField = pq.PQresultErrorField +PQresultErrorField.argtypes = [PGresult_ptr, c_int] +PQresultErrorField.restype = c_char_p + +PQclear = pq.PQclear +PQclear.argtypes = [PGresult_ptr] +PQclear.restype = None + + +# 33.3.2. Retrieving Query Result Information + +PQntuples = pq.PQntuples +PQntuples.argtypes = [PGresult_ptr] +PQntuples.restype = c_int + +PQnfields = pq.PQnfields +PQnfields.argtypes = [PGresult_ptr] +PQnfields.restype = c_int + +PQfname = pq.PQfname +PQfname.argtypes = [PGresult_ptr, c_int] +PQfname.restype = c_char_p + +# PQfnumber: useless and hard to use + +PQftable = pq.PQftable +PQftable.argtypes = [PGresult_ptr, c_int] +PQftable.restype = Oid + +PQftablecol = pq.PQftablecol +PQftablecol.argtypes = [PGresult_ptr, c_int] +PQftablecol.restype = c_int + +PQfformat = pq.PQfformat +PQfformat.argtypes = [PGresult_ptr, c_int] +PQfformat.restype = c_int + +PQftype = pq.PQftype +PQftype.argtypes = [PGresult_ptr, c_int] +PQftype.restype = Oid + +PQfmod = pq.PQfmod +PQfmod.argtypes = [PGresult_ptr, c_int] +PQfmod.restype = c_int + +PQfsize = pq.PQfsize +PQfsize.argtypes = [PGresult_ptr, c_int] +PQfsize.restype = c_int + +PQbinaryTuples = pq.PQbinaryTuples +PQbinaryTuples.argtypes = [PGresult_ptr] +PQbinaryTuples.restype = c_int + +PQgetvalue = pq.PQgetvalue +PQgetvalue.argtypes = [PGresult_ptr, c_int, c_int] +PQgetvalue.restype = POINTER(c_char) # not a null-terminated string + +PQgetisnull = pq.PQgetisnull +PQgetisnull.argtypes = [PGresult_ptr, c_int, c_int] +PQgetisnull.restype = c_int + +PQgetlength = pq.PQgetlength +PQgetlength.argtypes = [PGresult_ptr, c_int, c_int] +PQgetlength.restype = c_int + +PQnparams = pq.PQnparams +PQnparams.argtypes = [PGresult_ptr] +PQnparams.restype = c_int + +PQparamtype = pq.PQparamtype +PQparamtype.argtypes = [PGresult_ptr, c_int] +PQparamtype.restype = Oid + +# PQprint: pretty useless + +# 33.3.3. Retrieving Other Result Information + +PQcmdStatus = pq.PQcmdStatus +PQcmdStatus.argtypes = [PGresult_ptr] +PQcmdStatus.restype = c_char_p + +PQcmdTuples = pq.PQcmdTuples +PQcmdTuples.argtypes = [PGresult_ptr] +PQcmdTuples.restype = c_char_p + +PQoidValue = pq.PQoidValue +PQoidValue.argtypes = [PGresult_ptr] +PQoidValue.restype = Oid + + +# 33.3.4. Escaping Strings for Inclusion in SQL Commands + +PQescapeLiteral = pq.PQescapeLiteral +PQescapeLiteral.argtypes = [PGconn_ptr, c_char_p, c_size_t] +PQescapeLiteral.restype = POINTER(c_char) + +PQescapeIdentifier = pq.PQescapeIdentifier +PQescapeIdentifier.argtypes = [PGconn_ptr, c_char_p, c_size_t] +PQescapeIdentifier.restype = POINTER(c_char) + +PQescapeStringConn = pq.PQescapeStringConn +# TODO: raises "wrong type" error +# PQescapeStringConn.argtypes = [ +# PGconn_ptr, c_char_p, c_char_p, c_size_t, POINTER(c_int) +# ] +PQescapeStringConn.restype = c_size_t + +PQescapeString = pq.PQescapeString +# TODO: raises "wrong type" error +# PQescapeString.argtypes = [c_char_p, c_char_p, c_size_t] +PQescapeString.restype = c_size_t + +PQescapeByteaConn = pq.PQescapeByteaConn +PQescapeByteaConn.argtypes = [ + PGconn_ptr, + POINTER(c_char), # actually POINTER(c_ubyte) but this is easier + c_size_t, + POINTER(c_size_t), +] +PQescapeByteaConn.restype = POINTER(c_ubyte) + +PQescapeBytea = pq.PQescapeBytea +PQescapeBytea.argtypes = [ + POINTER(c_char), # actually POINTER(c_ubyte) but this is easier + c_size_t, + POINTER(c_size_t), +] +PQescapeBytea.restype = POINTER(c_ubyte) + + +PQunescapeBytea = pq.PQunescapeBytea +PQunescapeBytea.argtypes = [ + POINTER(c_char), # actually POINTER(c_ubyte) but this is easier + POINTER(c_size_t), +] +PQunescapeBytea.restype = POINTER(c_ubyte) + + +# 33.4. Asynchronous Command Processing + +PQsendQuery = pq.PQsendQuery +PQsendQuery.argtypes = [PGconn_ptr, c_char_p] +PQsendQuery.restype = c_int + +PQsendQueryParams = pq.PQsendQueryParams +PQsendQueryParams.argtypes = [ + PGconn_ptr, + c_char_p, + c_int, + POINTER(Oid), + POINTER(c_char_p), + POINTER(c_int), + POINTER(c_int), + c_int, +] +PQsendQueryParams.restype = c_int + +PQsendPrepare = pq.PQsendPrepare +PQsendPrepare.argtypes = [PGconn_ptr, c_char_p, c_char_p, c_int, POINTER(Oid)] +PQsendPrepare.restype = c_int + +PQsendQueryPrepared = pq.PQsendQueryPrepared +PQsendQueryPrepared.argtypes = [ + PGconn_ptr, + c_char_p, + c_int, + POINTER(c_char_p), + POINTER(c_int), + POINTER(c_int), + c_int, +] +PQsendQueryPrepared.restype = c_int + +PQsendDescribePrepared = pq.PQsendDescribePrepared +PQsendDescribePrepared.argtypes = [PGconn_ptr, c_char_p] +PQsendDescribePrepared.restype = c_int + +PQsendDescribePortal = pq.PQsendDescribePortal +PQsendDescribePortal.argtypes = [PGconn_ptr, c_char_p] +PQsendDescribePortal.restype = c_int + +if libpq_version >= 170000: + PQsendClosePrepared = pq.PQsendClosePrepared + PQsendClosePrepared.argtypes = [PGconn_ptr, c_char_p] + PQsendClosePrepared.restype = c_int + + PQsendClosePortal = pq.PQsendClosePortal + PQsendClosePortal.argtypes = [PGconn_ptr, c_char_p] + PQsendClosePortal.restype = c_int + +else: + PQsendClosePrepared = not_supported_before("PQsendClosePrepared", 170000) + PQsendClosePortal = not_supported_before("PQsendClosePortal", 170000) + +PQgetResult = pq.PQgetResult +PQgetResult.argtypes = [PGconn_ptr] +PQgetResult.restype = PGresult_ptr + +PQconsumeInput = pq.PQconsumeInput +PQconsumeInput.argtypes = [PGconn_ptr] +PQconsumeInput.restype = c_int + +PQisBusy = pq.PQisBusy +PQisBusy.argtypes = [PGconn_ptr] +PQisBusy.restype = c_int + +PQsetnonblocking = pq.PQsetnonblocking +PQsetnonblocking.argtypes = [PGconn_ptr, c_int] +PQsetnonblocking.restype = c_int + +PQisnonblocking = pq.PQisnonblocking +PQisnonblocking.argtypes = [PGconn_ptr] +PQisnonblocking.restype = c_int + +PQflush = pq.PQflush +PQflush.argtypes = [PGconn_ptr] +PQflush.restype = c_int + + +# 32.6. Retrieving Query Results in Chunks +PQsetSingleRowMode = pq.PQsetSingleRowMode +PQsetSingleRowMode.argtypes = [PGconn_ptr] +PQsetSingleRowMode.restype = c_int + +if libpq_version >= 170000: + PQsetChunkedRowsMode = pq.PQsetChunkedRowsMode + PQsetChunkedRowsMode.argtypes = [PGconn_ptr, c_int] + PQsetChunkedRowsMode.restype = c_int +else: + PQsetChunkedRowsMode = not_supported_before("PQsetChunkedRowsMode", 170000) + +# 33.6. Canceling Queries in Progress + +if libpq_version >= 170000: + PQcancelCreate = pq.PQcancelCreate + PQcancelCreate.argtypes = [PGconn_ptr] + PQcancelCreate.restype = PGcancelConn_ptr + + PQcancelStart = pq.PQcancelStart + PQcancelStart.argtypes = [PGcancelConn_ptr] + PQcancelStart.restype = c_int + + PQcancelBlocking = pq.PQcancelBlocking + PQcancelBlocking.argtypes = [PGcancelConn_ptr] + PQcancelBlocking.restype = c_int + + PQcancelPoll = pq.PQcancelPoll + PQcancelPoll.argtypes = [PGcancelConn_ptr] + PQcancelPoll.restype = c_int + + PQcancelStatus = pq.PQcancelStatus + PQcancelStatus.argtypes = [PGcancelConn_ptr] + PQcancelStatus.restype = c_int + + PQcancelSocket = pq.PQcancelSocket + PQcancelSocket.argtypes = [PGcancelConn_ptr] + PQcancelSocket.restype = c_int + + PQcancelErrorMessage = pq.PQcancelErrorMessage + PQcancelErrorMessage.argtypes = [PGcancelConn_ptr] + PQcancelErrorMessage.restype = c_char_p + + PQcancelReset = pq.PQcancelReset + PQcancelReset.argtypes = [PGcancelConn_ptr] + PQcancelReset.restype = None + + PQcancelFinish = pq.PQcancelFinish + PQcancelFinish.argtypes = [PGcancelConn_ptr] + PQcancelFinish.restype = None + +else: + PQcancelCreate = not_supported_before("PQcancelCreate", 170000) + PQcancelStart = not_supported_before("PQcancelStart", 170000) + PQcancelBlocking = not_supported_before("PQcancelBlocking", 170000) + PQcancelPoll = not_supported_before("PQcancelPoll", 170000) + PQcancelStatus = not_supported_before("PQcancelStatus", 170000) + PQcancelSocket = not_supported_before("PQcancelSocket", 170000) + PQcancelErrorMessage = not_supported_before("PQcancelErrorMessage", 170000) + PQcancelReset = not_supported_before("PQcancelReset", 170000) + PQcancelFinish = not_supported_before("PQcancelFinish", 170000) + + +PQgetCancel = pq.PQgetCancel +PQgetCancel.argtypes = [PGconn_ptr] +PQgetCancel.restype = PGcancel_ptr + +PQfreeCancel = pq.PQfreeCancel +PQfreeCancel.argtypes = [PGcancel_ptr] +PQfreeCancel.restype = None + +PQcancel = pq.PQcancel +# TODO: raises "wrong type" error +# PQcancel.argtypes = [PGcancel_ptr, POINTER(c_char), c_int] +PQcancel.restype = c_int + + +# 33.8. Asynchronous Notification + +PQnotifies = pq.PQnotifies +PQnotifies.argtypes = [PGconn_ptr] +PQnotifies.restype = PGnotify_ptr + + +# 33.9. Functions Associated with the COPY Command + +PQputCopyData = pq.PQputCopyData +PQputCopyData.argtypes = [PGconn_ptr, c_char_p, c_int] +PQputCopyData.restype = c_int + +PQputCopyEnd = pq.PQputCopyEnd +PQputCopyEnd.argtypes = [PGconn_ptr, c_char_p] +PQputCopyEnd.restype = c_int + +PQgetCopyData = pq.PQgetCopyData +PQgetCopyData.argtypes = [PGconn_ptr, POINTER(c_char_p), c_int] +PQgetCopyData.restype = c_int + + +# 33.10. Control Functions + +PQtrace = pq.PQtrace +PQtrace.argtypes = [PGconn_ptr, FILE_ptr] +PQtrace.restype = None + +if libpq_version >= 140000: + PQsetTraceFlags = pq.PQsetTraceFlags + PQsetTraceFlags.argtypes = [PGconn_ptr, c_int] + PQsetTraceFlags.restype = None +else: + PQsetTraceFlags = not_supported_before("PQsetTraceFlags", 140000) + +PQuntrace = pq.PQuntrace +PQuntrace.argtypes = [PGconn_ptr] +PQuntrace.restype = None + +# 33.11. Miscellaneous Functions + +PQfreemem = pq.PQfreemem +PQfreemem.argtypes = [c_void_p] +PQfreemem.restype = None + +if libpq_version >= 100000: + PQencryptPasswordConn = pq.PQencryptPasswordConn + PQencryptPasswordConn.argtypes = [ + PGconn_ptr, + c_char_p, + c_char_p, + c_char_p, + ] + PQencryptPasswordConn.restype = POINTER(c_char) +else: + PQencryptPasswordConn = not_supported_before("PQencryptPasswordConn", 100000) + +if libpq_version >= 170000: + PQchangePassword = pq.PQchangePassword + PQchangePassword.argtypes = [ + PGconn_ptr, + c_char_p, + c_char_p, + ] + PQchangePassword.restype = PGresult_ptr +else: + PQchangePassword = not_supported_before("PQchangePassword", 170000) + +PQmakeEmptyPGresult = pq.PQmakeEmptyPGresult +PQmakeEmptyPGresult.argtypes = [PGconn_ptr, c_int] +PQmakeEmptyPGresult.restype = PGresult_ptr + +PQsetResultAttrs = pq.PQsetResultAttrs +PQsetResultAttrs.argtypes = [PGresult_ptr, c_int, PGresAttDesc_ptr] +PQsetResultAttrs.restype = c_int + + +# 33.12. Notice Processing + +PQnoticeReceiver = CFUNCTYPE(None, c_void_p, PGresult_ptr) + +PQsetNoticeReceiver = pq.PQsetNoticeReceiver +PQsetNoticeReceiver.argtypes = [PGconn_ptr, PQnoticeReceiver, c_void_p] +PQsetNoticeReceiver.restype = PQnoticeReceiver + +# 34.5 Pipeline Mode + +if libpq_version >= 140000: + PQpipelineStatus = pq.PQpipelineStatus + PQpipelineStatus.argtypes = [PGconn_ptr] + PQpipelineStatus.restype = c_int + + PQenterPipelineMode = pq.PQenterPipelineMode + PQenterPipelineMode.argtypes = [PGconn_ptr] + PQenterPipelineMode.restype = c_int + + PQexitPipelineMode = pq.PQexitPipelineMode + PQexitPipelineMode.argtypes = [PGconn_ptr] + PQexitPipelineMode.restype = c_int + + PQpipelineSync = pq.PQpipelineSync + PQpipelineSync.argtypes = [PGconn_ptr] + PQpipelineSync.restype = c_int + + PQsendFlushRequest = pq.PQsendFlushRequest + PQsendFlushRequest.argtypes = [PGconn_ptr] + PQsendFlushRequest.restype = c_int + +else: + PQpipelineStatus = not_supported_before("PQpipelineStatus", 140000) + PQenterPipelineMode = not_supported_before("PQenterPipelineMode", 140000) + PQexitPipelineMode = not_supported_before("PQexitPipelineMode", 140000) + PQpipelineSync = not_supported_before("PQpipelineSync", 140000) + PQsendFlushRequest = not_supported_before("PQsendFlushRequest", 140000) + + +# 33.18. SSL Support + +PQinitOpenSSL = pq.PQinitOpenSSL +PQinitOpenSSL.argtypes = [c_int, c_int] +PQinitOpenSSL.restype = None + + +def generate_stub() -> None: + import re + from ctypes import _CFuncPtr # type: ignore[attr-defined] + + def type2str(fname: str, narg: int | None, t: Any) -> str: + if t is None: + return "None" + elif t is c_void_p: + return "Any" + elif t is c_int or t is c_uint or t is c_size_t: + return "int" + elif t is c_char_p or t.__name__ == "LP_c_char": + if narg is not None: + return "bytes" + else: + return "bytes | None" + + elif t.__name__ in ( + "LP_PGconn_struct", + "LP_PGresult_struct", + "LP_PGcancelConn_struct", + "LP_PGcancel_struct", + ): + if narg is not None: + return f"{t.__name__[3:]} | None" + else: + return str(t.__name__[3:]) + + elif t.__name__ in ("LP_PQconninfoOption_struct",): + return f"Sequence[{t.__name__[3:]}]" + + elif t.__name__ in ( + "LP_c_ubyte", + "LP_c_char_p", + "LP_c_int", + "LP_c_uint", + "LP_c_ulong", + "LP_FILE", + ): + return f"_Pointer[{t.__name__[3:]}]" + + else: + assert False, f"can't deal with {t} in {fname}" + + fn = __file__ + "i" + with open(fn) as f: + lines = f.read().splitlines() + + istart, iend = ( + i + for i, line in enumerate(lines) + if re.match(r"\s*#\s*autogenerated:\s+(start|end)", line) + ) + + known = { + line[4:].split("(", 1)[0] for line in lines[:istart] if line.startswith("def ") + } + + signatures = [] + + for name, obj in globals().items(): + if name in known: + continue + if not isinstance(obj, _CFuncPtr): + continue + + params = [] + for i, t in enumerate(obj.argtypes): + params.append(f"arg{i + 1}: {type2str(name, i, t)}") + + resname = type2str(name, None, obj.restype) + + signatures.append(f"def {name}({', '.join(params)}) -> {resname}: ...") + + lines[istart + 1 : iend] = signatures + + with open(fn, "w") as f: + f.write("\n".join(lines)) + f.write("\n") + + +if __name__ == "__main__": + generate_stub() diff --git a/backend/.venv/Lib/site-packages/psycopg/pq/_pq_ctypes.pyi b/backend/.venv/Lib/site-packages/psycopg/pq/_pq_ctypes.pyi new file mode 100644 index 0000000..94e0af9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/pq/_pq_ctypes.pyi @@ -0,0 +1,227 @@ +""" +types stub for ctypes functions +""" + +# Copyright (C) 2020 The Psycopg Team + +from typing import Any, Callable, Sequence +from ctypes import Array, pointer, _Pointer +from ctypes import c_char, c_char_p, c_int, c_ubyte, c_uint, c_ulong + +class FILE: ... + +def fdopen(fd: int, mode: bytes) -> _Pointer[FILE]: ... # type: ignore[type-var] + +Oid = c_uint + +class PGconn_struct: ... +class PGresult_struct: ... +class PGcancelConn_struct: ... +class PGcancel_struct: ... + +class PQconninfoOption_struct: + keyword: bytes + envvar: bytes + compiled: bytes + val: bytes + label: bytes + dispchar: bytes + dispsize: int + +class PGnotify_struct: + be_pid: int + relname: bytes + extra: bytes + +class PGresAttDesc_struct: + name: bytes + tableid: int + columnid: int + format: int + typid: int + typlen: int + atttypmod: int + +def PQhostaddr(arg1: PGconn_struct | None) -> bytes: ... +def PQerrorMessage(arg1: PGconn_struct | None) -> bytes: ... +def PQresultErrorMessage(arg1: PGresult_struct | None) -> bytes: ... +def PQexecPrepared( + arg1: PGconn_struct | None, + arg2: bytes, + arg3: int, + arg4: Array[c_char_p] | None, + arg5: Array[c_int] | None, + arg6: Array[c_int] | None, + arg7: int, +) -> PGresult_struct: ... +def PQprepare( + arg1: PGconn_struct | None, + arg2: bytes, + arg3: bytes, + arg4: int, + arg5: Array[c_uint] | None, +) -> PGresult_struct: ... +def PQgetvalue( + arg1: PGresult_struct | None, arg2: int, arg3: int +) -> _Pointer[c_char]: ... +def PQcmdTuples(arg1: PGresult_struct | None) -> bytes: ... +def PQescapeStringConn( + arg1: PGconn_struct | None, + arg2: c_char_p, + arg3: bytes, + arg4: int, + arg5: _Pointer[c_int], +) -> int: ... +def PQescapeString(arg1: c_char_p, arg2: bytes, arg3: int) -> int: ... +def PQsendPrepare( + arg1: PGconn_struct | None, + arg2: bytes, + arg3: bytes, + arg4: int, + arg5: Array[c_uint] | None, +) -> int: ... +def PQsendQueryPrepared( + arg1: PGconn_struct | None, + arg2: bytes, + arg3: int, + arg4: Array[c_char_p] | None, + arg5: Array[c_int] | None, + arg6: Array[c_int] | None, + arg7: int, +) -> int: ... +def PQcancelCreate(arg1: PGconn_struct | None) -> PGcancelConn_struct: ... +def PQcancelBlocking(arg1: PGcancelConn_struct | None) -> int: ... +def PQcancelStart(arg1: PGcancelConn_struct | None) -> int: ... +def PQcancelPoll(arg1: PGcancelConn_struct | None) -> int: ... +def PQcancelStatus(arg1: PGcancelConn_struct | None) -> int: ... +def PQcancelSocket(arg1: PGcancelConn_struct | None) -> int: ... +def PQcancelErrorMessage(arg1: PGcancelConn_struct | None) -> bytes: ... +def PQcancelReset(arg1: PGcancelConn_struct | None) -> None: ... +def PQcancelFinish(arg1: PGcancelConn_struct | None) -> None: ... +def PQcancel(arg1: PGcancel_struct | None, arg2: c_char_p, arg3: int) -> int: ... +def PQsetNoticeReceiver( + arg1: PGconn_struct, arg2: Callable[[Any], PGresult_struct], arg3: Any +) -> Callable[[Any], PGresult_struct]: ... + +# TODO: Ignoring type as getting an error on mypy/ctypes: +# Type argument "psycopg.pq._pq_ctypes.PGnotify_struct" of "pointer" must be +# a subtype of "ctypes._CData" +def PQnotifies( + arg1: PGconn_struct | None, +) -> _Pointer[PGnotify_struct] | None: ... # type: ignore +def PQputCopyEnd(arg1: PGconn_struct | None, arg2: bytes | None) -> int: ... + +# Arg 2 is a _Pointer, reported as _CArgObject by mypy +def PQgetCopyData(arg1: PGconn_struct | None, arg2: Any, arg3: int) -> int: ... +def PQsetResultAttrs( + arg1: PGresult_struct | None, + arg2: int, + arg3: Array[PGresAttDesc_struct], # type: ignore +) -> int: ... +def PQtrace( + arg1: PGconn_struct | None, + arg2: _Pointer[FILE], # type: ignore[type-var] +) -> None: ... +def PQsetTraceFlags(arg1: PGconn_struct | None, arg2: int) -> None: ... +def PQencryptPasswordConn( + arg1: PGconn_struct | None, + arg2: bytes, + arg3: bytes, + arg4: bytes | None, +) -> bytes: ... +def PQpipelineStatus(pgconn: PGconn_struct | None) -> int: ... +def PQenterPipelineMode(pgconn: PGconn_struct | None) -> int: ... +def PQexitPipelineMode(pgconn: PGconn_struct | None) -> int: ... +def PQpipelineSync(pgconn: PGconn_struct | None) -> int: ... +def PQsendFlushRequest(pgconn: PGconn_struct | None) -> int: ... + +# Autogenerated section. +# In order to refresh, run: +# python -m psycopg.pq._pq_ctypes + +# fmt: off +# autogenerated: start +def PQlibVersion() -> int: ... +def PQconnectdb(arg1: bytes) -> PGconn_struct: ... +def PQconnectStart(arg1: bytes) -> PGconn_struct: ... +def PQconnectPoll(arg1: PGconn_struct | None) -> int: ... +def PQconndefaults() -> Sequence[PQconninfoOption_struct]: ... +def PQconninfoFree(arg1: Sequence[PQconninfoOption_struct]) -> None: ... +def PQconninfo(arg1: PGconn_struct | None) -> Sequence[PQconninfoOption_struct]: ... +def PQconninfoParse(arg1: bytes, arg2: _Pointer[c_char_p]) -> Sequence[PQconninfoOption_struct]: ... +def PQfinish(arg1: PGconn_struct | None) -> None: ... +def PQreset(arg1: PGconn_struct | None) -> None: ... +def PQresetStart(arg1: PGconn_struct | None) -> int: ... +def PQresetPoll(arg1: PGconn_struct | None) -> int: ... +def PQping(arg1: bytes) -> int: ... +def PQdb(arg1: PGconn_struct | None) -> bytes | None: ... +def PQuser(arg1: PGconn_struct | None) -> bytes | None: ... +def PQpass(arg1: PGconn_struct | None) -> bytes | None: ... +def PQhost(arg1: PGconn_struct | None) -> bytes | None: ... +def PQport(arg1: PGconn_struct | None) -> bytes | None: ... +def PQtty(arg1: PGconn_struct | None) -> bytes | None: ... +def PQoptions(arg1: PGconn_struct | None) -> bytes | None: ... +def PQstatus(arg1: PGconn_struct | None) -> int: ... +def PQtransactionStatus(arg1: PGconn_struct | None) -> int: ... +def PQparameterStatus(arg1: PGconn_struct | None, arg2: bytes) -> bytes | None: ... +def PQprotocolVersion(arg1: PGconn_struct | None) -> int: ... +def PQserverVersion(arg1: PGconn_struct | None) -> int: ... +def PQsocket(arg1: PGconn_struct | None) -> int: ... +def PQbackendPID(arg1: PGconn_struct | None) -> int: ... +def PQconnectionNeedsPassword(arg1: PGconn_struct | None) -> int: ... +def PQconnectionUsedPassword(arg1: PGconn_struct | None) -> int: ... +def PQsslInUse(arg1: PGconn_struct | None) -> int: ... +def PQexec(arg1: PGconn_struct | None, arg2: bytes) -> PGresult_struct: ... +def PQexecParams(arg1: PGconn_struct | None, arg2: bytes, arg3: int, arg4: _Pointer[c_uint], arg5: _Pointer[c_char_p], arg6: _Pointer[c_int], arg7: _Pointer[c_int], arg8: int) -> PGresult_struct: ... +def PQdescribePrepared(arg1: PGconn_struct | None, arg2: bytes) -> PGresult_struct: ... +def PQdescribePortal(arg1: PGconn_struct | None, arg2: bytes) -> PGresult_struct: ... +def PQclosePrepared(arg1: PGconn_struct | None, arg2: bytes) -> PGresult_struct: ... +def PQclosePortal(arg1: PGconn_struct | None, arg2: bytes) -> PGresult_struct: ... +def PQresultStatus(arg1: PGresult_struct | None) -> int: ... +def PQresultErrorField(arg1: PGresult_struct | None, arg2: int) -> bytes | None: ... +def PQclear(arg1: PGresult_struct | None) -> None: ... +def PQntuples(arg1: PGresult_struct | None) -> int: ... +def PQnfields(arg1: PGresult_struct | None) -> int: ... +def PQfname(arg1: PGresult_struct | None, arg2: int) -> bytes | None: ... +def PQftable(arg1: PGresult_struct | None, arg2: int) -> int: ... +def PQftablecol(arg1: PGresult_struct | None, arg2: int) -> int: ... +def PQfformat(arg1: PGresult_struct | None, arg2: int) -> int: ... +def PQftype(arg1: PGresult_struct | None, arg2: int) -> int: ... +def PQfmod(arg1: PGresult_struct | None, arg2: int) -> int: ... +def PQfsize(arg1: PGresult_struct | None, arg2: int) -> int: ... +def PQbinaryTuples(arg1: PGresult_struct | None) -> int: ... +def PQgetisnull(arg1: PGresult_struct | None, arg2: int, arg3: int) -> int: ... +def PQgetlength(arg1: PGresult_struct | None, arg2: int, arg3: int) -> int: ... +def PQnparams(arg1: PGresult_struct | None) -> int: ... +def PQparamtype(arg1: PGresult_struct | None, arg2: int) -> int: ... +def PQcmdStatus(arg1: PGresult_struct | None) -> bytes | None: ... +def PQoidValue(arg1: PGresult_struct | None) -> int: ... +def PQescapeLiteral(arg1: PGconn_struct | None, arg2: bytes, arg3: int) -> bytes | None: ... +def PQescapeIdentifier(arg1: PGconn_struct | None, arg2: bytes, arg3: int) -> bytes | None: ... +def PQescapeByteaConn(arg1: PGconn_struct | None, arg2: bytes, arg3: int, arg4: _Pointer[c_ulong]) -> _Pointer[c_ubyte]: ... +def PQescapeBytea(arg1: bytes, arg2: int, arg3: _Pointer[c_ulong]) -> _Pointer[c_ubyte]: ... +def PQunescapeBytea(arg1: bytes, arg2: _Pointer[c_ulong]) -> _Pointer[c_ubyte]: ... +def PQsendQuery(arg1: PGconn_struct | None, arg2: bytes) -> int: ... +def PQsendQueryParams(arg1: PGconn_struct | None, arg2: bytes, arg3: int, arg4: _Pointer[c_uint], arg5: _Pointer[c_char_p], arg6: _Pointer[c_int], arg7: _Pointer[c_int], arg8: int) -> int: ... +def PQsendDescribePrepared(arg1: PGconn_struct | None, arg2: bytes) -> int: ... +def PQsendDescribePortal(arg1: PGconn_struct | None, arg2: bytes) -> int: ... +def PQsendClosePrepared(arg1: PGconn_struct | None, arg2: bytes) -> int: ... +def PQsendClosePortal(arg1: PGconn_struct | None, arg2: bytes) -> int: ... +def PQgetResult(arg1: PGconn_struct | None) -> PGresult_struct: ... +def PQconsumeInput(arg1: PGconn_struct | None) -> int: ... +def PQisBusy(arg1: PGconn_struct | None) -> int: ... +def PQsetnonblocking(arg1: PGconn_struct | None, arg2: int) -> int: ... +def PQisnonblocking(arg1: PGconn_struct | None) -> int: ... +def PQflush(arg1: PGconn_struct | None) -> int: ... +def PQsetSingleRowMode(arg1: PGconn_struct | None) -> int: ... +def PQsetChunkedRowsMode(arg1: PGconn_struct | None, arg2: int) -> int: ... +def PQgetCancel(arg1: PGconn_struct | None) -> PGcancel_struct: ... +def PQfreeCancel(arg1: PGcancel_struct | None) -> None: ... +def PQputCopyData(arg1: PGconn_struct | None, arg2: bytes, arg3: int) -> int: ... +def PQuntrace(arg1: PGconn_struct | None) -> None: ... +def PQfreemem(arg1: Any) -> None: ... +def PQchangePassword(arg1: PGconn_struct | None, arg2: bytes, arg3: bytes) -> PGresult_struct: ... +def PQmakeEmptyPGresult(arg1: PGconn_struct | None, arg2: int) -> PGresult_struct: ... +def PQinitOpenSSL(arg1: int, arg2: int) -> None: ... +# autogenerated: end +# fmt: on diff --git a/backend/.venv/Lib/site-packages/psycopg/pq/abc.py b/backend/.venv/Lib/site-packages/psycopg/pq/abc.py new file mode 100644 index 0000000..8e91fd2 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/pq/abc.py @@ -0,0 +1,336 @@ +""" +Protocol objects to represent objects exposed by different pq implementations. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +from typing import Any, Callable, Protocol, Sequence, TYPE_CHECKING +from typing import Union # drop with Python 3.8 + +from ._enums import Format, Trace +from .._compat import Self, TypeAlias + +if TYPE_CHECKING: + from .misc import PGnotify, ConninfoOption, PGresAttDesc + +# An object implementing the buffer protocol (ish) +Buffer: TypeAlias = Union[bytes, bytearray, memoryview] + + +class PGconn(Protocol): + notice_handler: Callable[[PGresult], None] | None + notify_handler: Callable[[PGnotify], None] | None + + @classmethod + def connect(cls, conninfo: bytes) -> Self: ... + + @classmethod + def connect_start(cls, conninfo: bytes) -> Self: ... + + def connect_poll(self) -> int: ... + + def finish(self) -> None: ... + + @property + def info(self) -> list[ConninfoOption]: ... + + def reset(self) -> None: ... + + def reset_start(self) -> None: ... + + def reset_poll(self) -> int: ... + + @classmethod + def ping(self, conninfo: bytes) -> int: ... + + @property + def db(self) -> bytes: ... + + @property + def user(self) -> bytes: ... + + @property + def password(self) -> bytes: ... + + @property + def host(self) -> bytes: ... + + @property + def hostaddr(self) -> bytes: ... + + @property + def port(self) -> bytes: ... + + @property + def tty(self) -> bytes: ... + + @property + def options(self) -> bytes: ... + + @property + def status(self) -> int: ... + + @property + def transaction_status(self) -> int: ... + + def parameter_status(self, name: bytes) -> bytes | None: ... + + @property + def error_message(self) -> bytes: ... + + def get_error_message(self, encoding: str = ...) -> str: ... + + @property + def _encoding(self) -> str: ... + + @property + def server_version(self) -> int: ... + + @property + def socket(self) -> int: ... + + @property + def backend_pid(self) -> int: ... + + @property + def needs_password(self) -> bool: ... + + @property + def used_password(self) -> bool: ... + + @property + def ssl_in_use(self) -> bool: ... + + def exec_(self, command: bytes) -> PGresult: ... + + def send_query(self, command: bytes) -> None: ... + + def exec_params( + self, + command: bytes, + param_values: Sequence[Buffer | None] | None, + param_types: Sequence[int] | None = None, + param_formats: Sequence[int] | None = None, + result_format: int = Format.TEXT, + ) -> PGresult: ... + + def send_query_params( + self, + command: bytes, + param_values: Sequence[Buffer | None] | None, + param_types: Sequence[int] | None = None, + param_formats: Sequence[int] | None = None, + result_format: int = Format.TEXT, + ) -> None: ... + + def send_prepare( + self, + name: bytes, + command: bytes, + param_types: Sequence[int] | None = None, + ) -> None: ... + + def send_query_prepared( + self, + name: bytes, + param_values: Sequence[Buffer | None] | None, + param_formats: Sequence[int] | None = None, + result_format: int = Format.TEXT, + ) -> None: ... + + def prepare( + self, + name: bytes, + command: bytes, + param_types: Sequence[int] | None = None, + ) -> PGresult: ... + + def exec_prepared( + self, + name: bytes, + param_values: Sequence[Buffer] | None, + param_formats: Sequence[int] | None = None, + result_format: int = 0, + ) -> PGresult: ... + + def describe_prepared(self, name: bytes) -> PGresult: ... + + def send_describe_prepared(self, name: bytes) -> None: ... + + def describe_portal(self, name: bytes) -> PGresult: ... + + def send_describe_portal(self, name: bytes) -> None: ... + + def close_prepared(self, name: bytes) -> PGresult: ... + + def send_close_prepared(self, name: bytes) -> None: ... + + def close_portal(self, name: bytes) -> PGresult: ... + + def send_close_portal(self, name: bytes) -> None: ... + + def get_result(self) -> PGresult | None: ... + + def consume_input(self) -> None: ... + + def is_busy(self) -> int: ... + + @property + def nonblocking(self) -> int: ... + + @nonblocking.setter + def nonblocking(self, arg: int) -> None: ... + + def flush(self) -> int: ... + + def set_single_row_mode(self) -> None: ... + + def set_chunked_rows_mode(self, size: int) -> None: ... + + def cancel_conn(self) -> PGcancelConn: ... + + def get_cancel(self) -> PGcancel: ... + + def notifies(self) -> PGnotify | None: ... + + def put_copy_data(self, buffer: Buffer) -> int: ... + + def put_copy_end(self, error: bytes | None = None) -> int: ... + + def get_copy_data(self, async_: int) -> tuple[int, memoryview]: ... + + def trace(self, fileno: int) -> None: ... + + def set_trace_flags(self, flags: Trace) -> None: ... + + def untrace(self) -> None: ... + + def encrypt_password( + self, passwd: bytes, user: bytes, algorithm: bytes | None = None + ) -> bytes: ... + + def change_password(self, user: bytes, passwd: bytes) -> None: ... + + def make_empty_result(self, exec_status: int) -> PGresult: ... + + @property + def pipeline_status(self) -> int: ... + + def enter_pipeline_mode(self) -> None: ... + + def exit_pipeline_mode(self) -> None: ... + + def pipeline_sync(self) -> None: ... + + def send_flush_request(self) -> None: ... + + +class PGresult(Protocol): + def clear(self) -> None: ... + + @property + def status(self) -> int: ... + + @property + def error_message(self) -> bytes: ... + + def get_error_message(self, encoding: str = ...) -> str: ... + + def error_field(self, fieldcode: int) -> bytes | None: ... + + @property + def ntuples(self) -> int: ... + + @property + def nfields(self) -> int: ... + + def fname(self, column_number: int) -> bytes | None: ... + + def ftable(self, column_number: int) -> int: ... + + def ftablecol(self, column_number: int) -> int: ... + + def fformat(self, column_number: int) -> int: ... + + def ftype(self, column_number: int) -> int: ... + + def fmod(self, column_number: int) -> int: ... + + def fsize(self, column_number: int) -> int: ... + + @property + def binary_tuples(self) -> int: ... + + def get_value(self, row_number: int, column_number: int) -> bytes | None: ... + + @property + def nparams(self) -> int: ... + + def param_type(self, param_number: int) -> int: ... + + @property + def command_status(self) -> bytes | None: ... + + @property + def command_tuples(self) -> int | None: ... + + @property + def oid_value(self) -> int: ... + + def set_attributes(self, descriptions: list[PGresAttDesc]) -> None: ... + + +class PGcancelConn(Protocol): + def start(self) -> None: ... + + def blocking(self) -> None: ... + + def poll(self) -> int: ... + + @property + def status(self) -> int: ... + + @property + def socket(self) -> int: ... + + @property + def error_message(self) -> bytes: ... + + def get_error_message(self, encoding: str = ...) -> str: ... + + def reset(self) -> None: ... + + def finish(self) -> None: ... + + +class PGcancel(Protocol): + def free(self) -> None: ... + + def cancel(self) -> None: ... + + +class Conninfo(Protocol): + @classmethod + def get_defaults(cls) -> list[ConninfoOption]: ... + + @classmethod + def parse(cls, conninfo: bytes) -> list[ConninfoOption]: ... + + @classmethod + def _options_from_array(cls, opts: Sequence[Any]) -> list[ConninfoOption]: ... + + +class Escaping(Protocol): + def __init__(self, conn: PGconn | None = None): ... + + def escape_literal(self, data: Buffer) -> bytes: ... + + def escape_identifier(self, data: Buffer) -> bytes: ... + + def escape_string(self, data: Buffer) -> bytes: ... + + def escape_bytea(self, data: Buffer) -> bytes: ... + + def unescape_bytea(self, data: Buffer) -> bytes: ... diff --git a/backend/.venv/Lib/site-packages/psycopg/pq/misc.py b/backend/.venv/Lib/site-packages/psycopg/pq/misc.py new file mode 100644 index 0000000..cb95e5e --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/pq/misc.py @@ -0,0 +1,187 @@ +""" +Various functionalities to make easier to work with the libpq. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import re +import os +import sys +import logging +import ctypes.util +from typing import NamedTuple +from pathlib import Path + +from . import abc +from ._enums import ConnStatus, TransactionStatus, PipelineStatus +from .._compat import cache + +logger = logging.getLogger("psycopg.pq") + +OK = ConnStatus.OK + + +class PGnotify(NamedTuple): + relname: bytes + be_pid: int + extra: bytes + + +class ConninfoOption(NamedTuple): + keyword: bytes + envvar: bytes | None + compiled: bytes | None + val: bytes | None + label: bytes + dispchar: bytes + dispsize: int + + +class PGresAttDesc(NamedTuple): + name: bytes + tableid: int + columnid: int + format: int + typid: int + typlen: int + atttypmod: int + + +@cache +def find_libpq_full_path() -> str | None: + if sys.platform == "win32": + libname = ctypes.util.find_library("libpq.dll") + libname = str(Path(libname).resolve()) + + elif sys.platform == "darwin": + libname = ctypes.util.find_library("libpq.dylib") + # (hopefully) temporary hack: libpq not in a standard place + # https://github.com/orgs/Homebrew/discussions/3595 + # If pg_config is available and agrees, let's use its indications. + if not libname: + try: + import subprocess as sp + + libdir = sp.check_output(["pg_config", "--libdir"]).strip().decode() + libname = os.path.join(libdir, "libpq.dylib") + if not os.path.exists(libname): + libname = None + except Exception as ex: + logger.debug("couldn't use pg_config to find libpq: %s", ex) + + else: + libname = ctypes.util.find_library("pq") + + return libname + + +def error_message( + obj: abc.PGconn | abc.PGresult | abc.PGcancelConn, encoding: str = "" +) -> str: + """ + Return an error message from a `PGconn`, `PGresult`, `PGcancelConn`. + + The return value is a `!str` (unlike pq data which is usually `!bytes`): + use the connection encoding if available, otherwise the `!encoding` + parameter as a fallback for decoding. Don't raise exceptions on decoding + errors. + """ + # Note: this function is exposed by the pq module and was documented, therefore + # we are not going to remove it, but we don't use it internally. + + # Don't pass the encoding if not specified, because different classes have + # different defaults (conn has its own encoding. others default to utf8). + return obj.get_error_message(encoding) if encoding else obj.get_error_message() + + +# Possible prefixes to strip for error messages, in the known localizations. +# This regular expression is generated from PostgreSQL sources using the +# `tools/update_error_prefixes.py` script +PREFIXES = re.compile( + # autogenerated: start + r""" + ^ (?: + DEBUG | INFO | HINWEIS | WARNUNG | FEHLER | LOG | FATAL | PANIK # de + | DEBUG | INFO | NOTICE | WARNING | ERROR | LOG | FATAL | PANIC # en + | DEBUG | INFO | NOTICE | WARNING | ERROR | LOG | FATAL | PANIC # es + | DEBUG | INFO | NOTICE | ATTENTION | ERREUR | LOG | FATAL | PANIC # fr + | DEBUG | INFO | NOTICE | PERINGATAN | ERROR | LOG | FATAL | PANIK # id + | DEBUG | INFO | NOTIFICA | ATTENZIONE | ERRORE | LOG | FATALE | PANICO # it + | DEBUG | INFO | NOTICE | WARNING | ERROR | LOG | FATAL | PANIC # ja + | 디버그 | 정보 | 알림 | 경고 | 오류 | 로그 | 치명적오류 | 손상 # ko + | DEBUG | INFORMACJA | UWAGA | OSTRZEŻENIE | BŁĄD | DZIENNIK | KATASTROFALNY | PANIKA # pl + | DEPURAÇÃO | INFO | NOTA | AVISO | ERRO | LOG | FATAL | PÂNICO # pt_BR + | ОТЛАДКА | ИНФОРМАЦИЯ | ЗАМЕЧАНИЕ | ПРЕДУПРЕЖДЕНИЕ | ОШИБКА | СООБЩЕНИЕ | ВАЖНО | ПАНИКА # ru + | DEBUG | INFO | NOTIS | VARNING | FEL | LOGG | FATALT | PANIK # sv + | DEBUG | BİLGİ | NOT | UYARI | HATA | LOG | ÖLÜMCÜL\ \(FATAL\) | KRİTİK # tr + | НАЛАГОДЖЕННЯ | ІНФОРМАЦІЯ | ПОВІДОМЛЕННЯ | ПОПЕРЕДЖЕННЯ | ПОМИЛКА | ЗАПИСУВАННЯ | ФАТАЛЬНО | ПАНІКА # uk + | 调试 | 信息 | 注意 | 警告 | 错误 | 日志 | 致命错误 | 比致命错误还过分的错误 # zh_CN + ) : \s+ + """, # noqa: E501 + # autogenerated: end + re.VERBOSE | re.MULTILINE, +) + + +def strip_severity(msg: str) -> str: + """Strip severity and whitespaces from error message.""" + m = PREFIXES.match(msg) + if m: + msg = msg[m.span()[1] :] + + return msg.strip() + + +def _clean_error_message(msg: bytes, encoding: str) -> str: + smsg = msg.decode(encoding, "replace") + if smsg: + return strip_severity(smsg) + else: + return "no error details available" + + +def connection_summary(pgconn: abc.PGconn) -> str: + """ + Return summary information on a connection. + + Useful for __repr__ + """ + parts = [] + if pgconn.status == OK: + # Put together the [STATUS] + status = TransactionStatus(pgconn.transaction_status).name + if pgconn.pipeline_status: + status += f", pipeline={PipelineStatus(pgconn.pipeline_status).name}" + + # Put together the (CONNECTION) + if not pgconn.host.startswith(b"/"): + parts.append(("host", pgconn.host.decode())) + if pgconn.port != b"5432": + parts.append(("port", pgconn.port.decode())) + if pgconn.user != pgconn.db: + parts.append(("user", pgconn.user.decode())) + parts.append(("database", pgconn.db.decode())) + + else: + status = ConnStatus(pgconn.status).name + + sparts = " ".join("%s=%s" % part for part in parts) + if sparts: + sparts = f" ({sparts})" + return f"[{status}]{sparts}" + + +def version_pretty(version: int) -> str: + """ + Return a pretty representation of a PostgreSQL version + + For instance: 140002 -> 14.2, 90610 -> 9.6.10 + """ + version, patch = divmod(version, 100) + major, minor = divmod(version, 100) + if major >= 10 and minor == 0: + return f"{major}.{patch}" + else: + return f"{major}.{minor}.{patch}" diff --git a/backend/.venv/Lib/site-packages/psycopg/pq/pq_ctypes.py b/backend/.venv/Lib/site-packages/psycopg/pq/pq_ctypes.py new file mode 100644 index 0000000..8335f87 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/pq/pq_ctypes.py @@ -0,0 +1,1276 @@ +""" +libpq Python wrapper using ctypes bindings. + +Clients shouldn't use this module directly, unless for testing: they should use +the `pq` module instead, which is in charge of choosing the best +implementation. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import sys +import logging +from os import getpid +from weakref import ref + +from ctypes import Array, POINTER, cast, string_at, create_string_buffer, byref +from ctypes import addressof, c_char_p, c_int, c_size_t, c_ulong, c_void_p, py_object +from typing import Any, Callable, Sequence +from typing import cast as t_cast, TYPE_CHECKING + +from .. import errors as e +from .._encodings import pg2pyenc +from . import _pq_ctypes as impl +from .misc import PGnotify, ConninfoOption, PGresAttDesc +from .misc import connection_summary, _clean_error_message +from ._enums import ConnStatus, ExecStatus, Format, Trace + +# Imported locally to call them from __del__ methods +from ._pq_ctypes import PQclear, PQfinish, PQfreeCancel, PQcancelFinish, PQstatus + +if TYPE_CHECKING: + from . import abc + +__impl__ = "python" + +logger = logging.getLogger("psycopg") + +OK = ConnStatus.OK + + +def version() -> int: + """Return the version number of the libpq currently loaded. + + The number is in the same format of `~psycopg.ConnectionInfo.server_version`. + + Certain features might not be available if the libpq library used is too old. + """ + return impl.PQlibVersion() + + +@impl.PQnoticeReceiver # type: ignore +def notice_receiver(arg: c_void_p, result_ptr: impl.PGresult_struct) -> None: + pgconn = cast(arg, POINTER(py_object)).contents.value + if callable(pgconn): # Not a weak reference on PyPy. + pgconn = pgconn() + + if not (pgconn and pgconn.notice_handler): + return + + res = PGresult(result_ptr) + try: + pgconn.notice_handler(res) + except Exception as exc: + logger.exception("error in notice receiver: %s", exc) + finally: + res._pgresult_ptr = None # avoid destroying the pgresult_ptr + + +class PGconn: + """ + Python representation of a libpq connection. + """ + + __slots__ = ( + "_pgconn_ptr", + "notice_handler", + "notify_handler", + "_self_ptr", + "_procpid", + "__weakref__", + ) + + def __init__(self, pgconn_ptr: impl.PGconn_struct): + self._pgconn_ptr: impl.PGconn_struct | None = pgconn_ptr + self.notice_handler: Callable[[abc.PGresult], None] | None = None + self.notify_handler: Callable[[PGnotify], None] | None = None + + # Keep alive for the lifetime of PGconn + self._self_ptr = py_object(ref(self)) + impl.PQsetNoticeReceiver(pgconn_ptr, notice_receiver, byref(self._self_ptr)) + + self._procpid = getpid() + + def __del__(self) -> None: + # Close the connection only if it was created in this process, + # not if this object is being GC'd after fork. + if getpid() == self._procpid: + self.finish() + + def __repr__(self) -> str: + cls = f"{self.__class__.__module__}.{self.__class__.__qualname__}" + info = connection_summary(self) + return f"<{cls} {info} at 0x{id(self):x}>" + + @classmethod + def connect(cls, conninfo: bytes) -> PGconn: + if not isinstance(conninfo, bytes): + raise TypeError(f"bytes expected, got {type(conninfo)} instead") + + pgconn_ptr = impl.PQconnectdb(conninfo) + if not pgconn_ptr: + raise MemoryError("couldn't allocate PGconn") + return cls(pgconn_ptr) + + @classmethod + def connect_start(cls, conninfo: bytes) -> PGconn: + if not isinstance(conninfo, bytes): + raise TypeError(f"bytes expected, got {type(conninfo)} instead") + + pgconn_ptr = impl.PQconnectStart(conninfo) + if not pgconn_ptr: + raise MemoryError("couldn't allocate PGconn") + return cls(pgconn_ptr) + + def connect_poll(self) -> int: + return self._call_int(impl.PQconnectPoll) + + def finish(self) -> None: + self._pgconn_ptr, p = None, self._pgconn_ptr + if p: + PQfinish(p) + + @property + def pgconn_ptr(self) -> int | None: + """The pointer to the underlying `!PGconn` structure, as integer. + + `!None` if the connection is closed. + + The value can be used to pass the structure to libpq functions which + psycopg doesn't (currently) wrap, either in C or in Python using FFI + libraries such as `ctypes`. + """ + if self._pgconn_ptr is None: + return None + + return addressof(self._pgconn_ptr.contents) # type: ignore[attr-defined] + + @property + def info(self) -> list[ConninfoOption]: + self._ensure_pgconn() + opts = impl.PQconninfo(self._pgconn_ptr) + if not opts: + raise MemoryError("couldn't allocate connection info") + try: + return Conninfo._options_from_array(opts) + finally: + impl.PQconninfoFree(opts) + + def reset(self) -> None: + self._ensure_pgconn() + impl.PQreset(self._pgconn_ptr) + + def reset_start(self) -> None: + if not impl.PQresetStart(self._pgconn_ptr): + raise e.OperationalError("couldn't reset connection") + + def reset_poll(self) -> int: + return self._call_int(impl.PQresetPoll) + + @classmethod + def ping(self, conninfo: bytes) -> int: + if not isinstance(conninfo, bytes): + raise TypeError(f"bytes expected, got {type(conninfo)} instead") + + return impl.PQping(conninfo) + + @property + def db(self) -> bytes: + return self._call_bytes(impl.PQdb) + + @property + def user(self) -> bytes: + return self._call_bytes(impl.PQuser) + + @property + def password(self) -> bytes: + return self._call_bytes(impl.PQpass) + + @property + def host(self) -> bytes: + return self._call_bytes(impl.PQhost) + + @property + def hostaddr(self) -> bytes: + return self._call_bytes(impl.PQhostaddr) + + @property + def port(self) -> bytes: + return self._call_bytes(impl.PQport) + + @property + def tty(self) -> bytes: + return self._call_bytes(impl.PQtty) + + @property + def options(self) -> bytes: + return self._call_bytes(impl.PQoptions) + + @property + def status(self) -> int: + return PQstatus(self._pgconn_ptr) + + @property + def transaction_status(self) -> int: + return impl.PQtransactionStatus(self._pgconn_ptr) + + def parameter_status(self, name: bytes) -> bytes | None: + self._ensure_pgconn() + return impl.PQparameterStatus(self._pgconn_ptr, name) + + @property + def error_message(self) -> bytes: + return impl.PQerrorMessage(self._pgconn_ptr) + + def get_error_message(self, encoding: str = "") -> str: + return _clean_error_message(self.error_message, encoding or self._encoding) + + @property + def _encoding(self) -> str: + if self.status == OK: + pgenc = self.parameter_status(b"client_encoding") or b"UTF8" + return pg2pyenc(pgenc) + else: + return "utf-8" + + @property + def protocol_version(self) -> int: + return self._call_int(impl.PQprotocolVersion) + + @property + def server_version(self) -> int: + return self._call_int(impl.PQserverVersion) + + @property + def socket(self) -> int: + rv = self._call_int(impl.PQsocket) + if rv == -1: + raise e.OperationalError("the connection is lost") + return rv + + @property + def backend_pid(self) -> int: + return self._call_int(impl.PQbackendPID) + + @property + def needs_password(self) -> bool: + """True if the connection authentication method required a password, + but none was available. + + See :pq:`PQconnectionNeedsPassword` for details. + """ + return bool(impl.PQconnectionNeedsPassword(self._pgconn_ptr)) + + @property + def used_password(self) -> bool: + """True if the connection authentication method used a password. + + See :pq:`PQconnectionUsedPassword` for details. + """ + return bool(impl.PQconnectionUsedPassword(self._pgconn_ptr)) + + @property + def ssl_in_use(self) -> bool: + return self._call_bool(impl.PQsslInUse) + + def exec_(self, command: bytes) -> PGresult: + if not isinstance(command, bytes): + raise TypeError(f"bytes expected, got {type(command)} instead") + self._ensure_pgconn() + rv = impl.PQexec(self._pgconn_ptr, command) + if not rv: + raise e.OperationalError( + f"executing query failed: {self.get_error_message()}" + ) + return PGresult(rv) + + def send_query(self, command: bytes) -> None: + if not isinstance(command, bytes): + raise TypeError(f"bytes expected, got {type(command)} instead") + self._ensure_pgconn() + if not impl.PQsendQuery(self._pgconn_ptr, command): + raise e.OperationalError( + f"sending query failed: {self.get_error_message()}" + ) + + def exec_params( + self, + command: bytes, + param_values: Sequence[abc.Buffer | None] | None, + param_types: Sequence[int] | None = None, + param_formats: Sequence[int] | None = None, + result_format: int = Format.TEXT, + ) -> PGresult: + args = self._query_params_args( + command, param_values, param_types, param_formats, result_format + ) + self._ensure_pgconn() + rv = impl.PQexecParams(*args) + if not rv: + raise e.OperationalError( + f"executing query failed: {self.get_error_message()}" + ) + return PGresult(rv) + + def send_query_params( + self, + command: bytes, + param_values: Sequence[abc.Buffer | None] | None, + param_types: Sequence[int] | None = None, + param_formats: Sequence[int] | None = None, + result_format: int = Format.TEXT, + ) -> None: + args = self._query_params_args( + command, param_values, param_types, param_formats, result_format + ) + self._ensure_pgconn() + if not impl.PQsendQueryParams(*args): + raise e.OperationalError( + f"sending query and params failed: {self.get_error_message()}" + ) + + def send_prepare( + self, + name: bytes, + command: bytes, + param_types: Sequence[int] | None = None, + ) -> None: + atypes: Array[impl.Oid] | None + if not param_types: + nparams = 0 + atypes = None + else: + nparams = len(param_types) + atypes = (impl.Oid * nparams)(*param_types) + + self._ensure_pgconn() + if not impl.PQsendPrepare(self._pgconn_ptr, name, command, nparams, atypes): + raise e.OperationalError( + f"sending query and params failed: {self.get_error_message()}" + ) + + def send_query_prepared( + self, + name: bytes, + param_values: Sequence[abc.Buffer | None] | None, + param_formats: Sequence[int] | None = None, + result_format: int = Format.TEXT, + ) -> None: + # repurpose this function with a cheeky replacement of query with name, + # drop the param_types from the result + args = self._query_params_args( + name, param_values, None, param_formats, result_format + ) + args = args[:3] + args[4:] + + self._ensure_pgconn() + if not impl.PQsendQueryPrepared(*args): + raise e.OperationalError( + f"sending prepared query failed: {self.get_error_message()}" + ) + + def _query_params_args( + self, + command: bytes, + param_values: Sequence[abc.Buffer | None] | None, + param_types: Sequence[int] | None = None, + param_formats: Sequence[int] | None = None, + result_format: int = Format.TEXT, + ) -> Any: + if not isinstance(command, bytes): + raise TypeError(f"bytes expected, got {type(command)} instead") + + aparams: Array[c_char_p] | None + alenghts: Array[c_int] | None + if param_values: + nparams = len(param_values) + aparams = (c_char_p * nparams)( + *( + # convert bytearray/memoryview to bytes + b if b is None or isinstance(b, bytes) else bytes(b) + for b in param_values + ) + ) + alenghts = (c_int * nparams)(*(len(p) if p else 0 for p in param_values)) + else: + nparams = 0 + aparams = alenghts = None + + atypes: Array[impl.Oid] | None + if not param_types: + atypes = None + else: + if len(param_types) != nparams: + raise ValueError( + "got %d param_values but %d param_types" + % (nparams, len(param_types)) + ) + atypes = (impl.Oid * nparams)(*param_types) + + if not param_formats: + aformats = None + else: + if len(param_formats) != nparams: + raise ValueError( + "got %d param_values but %d param_formats" + % (nparams, len(param_formats)) + ) + aformats = (c_int * nparams)(*param_formats) + + return ( + self._pgconn_ptr, + command, + nparams, + atypes, + aparams, + alenghts, + aformats, + result_format, + ) + + def prepare( + self, + name: bytes, + command: bytes, + param_types: Sequence[int] | None = None, + ) -> PGresult: + if not isinstance(name, bytes): + raise TypeError(f"'name' must be bytes, got {type(name)} instead") + + if not isinstance(command, bytes): + raise TypeError(f"'command' must be bytes, got {type(command)} instead") + + if not param_types: + nparams = 0 + atypes = None + else: + nparams = len(param_types) + atypes = (impl.Oid * nparams)(*param_types) + + self._ensure_pgconn() + rv = impl.PQprepare(self._pgconn_ptr, name, command, nparams, atypes) + if not rv: + raise e.OperationalError( + f"preparing query failed: {self.get_error_message()}" + ) + return PGresult(rv) + + def exec_prepared( + self, + name: bytes, + param_values: Sequence[abc.Buffer] | None, + param_formats: Sequence[int] | None = None, + result_format: int = 0, + ) -> PGresult: + if not isinstance(name, bytes): + raise TypeError(f"'name' must be bytes, got {type(name)} instead") + + aparams: Array[c_char_p] | None + alenghts: Array[c_int] | None + if param_values: + nparams = len(param_values) + aparams = (c_char_p * nparams)( + *( + # convert bytearray/memoryview to bytes + b if b is None or isinstance(b, bytes) else bytes(b) + for b in param_values + ) + ) + alenghts = (c_int * nparams)(*(len(p) if p else 0 for p in param_values)) + else: + nparams = 0 + aparams = alenghts = None + + if not param_formats: + aformats = None + else: + if len(param_formats) != nparams: + raise ValueError( + "got %d param_values but %d param_types" + % (nparams, len(param_formats)) + ) + aformats = (c_int * nparams)(*param_formats) + + self._ensure_pgconn() + rv = impl.PQexecPrepared( + self._pgconn_ptr, + name, + nparams, + aparams, + alenghts, + aformats, + result_format, + ) + if not rv: + raise e.OperationalError( + f"executing prepared query failed: {self.get_error_message()}" + ) + return PGresult(rv) + + def describe_prepared(self, name: bytes) -> PGresult: + if not isinstance(name, bytes): + raise TypeError(f"'name' must be bytes, got {type(name)} instead") + self._ensure_pgconn() + rv = impl.PQdescribePrepared(self._pgconn_ptr, name) + if not rv: + raise e.OperationalError( + f"describe prepared failed: {self.get_error_message()}" + ) + return PGresult(rv) + + def send_describe_prepared(self, name: bytes) -> None: + if not isinstance(name, bytes): + raise TypeError(f"bytes expected, got {type(name)} instead") + self._ensure_pgconn() + if not impl.PQsendDescribePrepared(self._pgconn_ptr, name): + raise e.OperationalError( + f"sending describe prepared failed: {self.get_error_message()}" + ) + + def describe_portal(self, name: bytes) -> PGresult: + if not isinstance(name, bytes): + raise TypeError(f"'name' must be bytes, got {type(name)} instead") + self._ensure_pgconn() + rv = impl.PQdescribePortal(self._pgconn_ptr, name) + if not rv: + raise e.OperationalError( + f"describe portal failed: {self.get_error_message()}" + ) + return PGresult(rv) + + def send_describe_portal(self, name: bytes) -> None: + if not isinstance(name, bytes): + raise TypeError(f"bytes expected, got {type(name)} instead") + self._ensure_pgconn() + if not impl.PQsendDescribePortal(self._pgconn_ptr, name): + raise e.OperationalError( + f"sending describe portal failed: {self.get_error_message()}" + ) + + def close_prepared(self, name: bytes) -> PGresult: + if not isinstance(name, bytes): + raise TypeError(f"'name' must be bytes, got {type(name)} instead") + self._ensure_pgconn() + rv = impl.PQclosePrepared(self._pgconn_ptr, name) + if not rv: + raise e.OperationalError( + f"close prepared failed: {self.get_error_message()}" + ) + return PGresult(rv) + + def send_close_prepared(self, name: bytes) -> None: + if not isinstance(name, bytes): + raise TypeError(f"bytes expected, got {type(name)} instead") + self._ensure_pgconn() + if not impl.PQsendClosePrepared(self._pgconn_ptr, name): + raise e.OperationalError( + f"sending close prepared failed: {self.get_error_message()}" + ) + + def close_portal(self, name: bytes) -> PGresult: + if not isinstance(name, bytes): + raise TypeError(f"'name' must be bytes, got {type(name)} instead") + self._ensure_pgconn() + rv = impl.PQclosePortal(self._pgconn_ptr, name) + if not rv: + raise e.OperationalError(f"close portal failed: {self.get_error_message()}") + return PGresult(rv) + + def send_close_portal(self, name: bytes) -> None: + if not isinstance(name, bytes): + raise TypeError(f"bytes expected, got {type(name)} instead") + self._ensure_pgconn() + if not impl.PQsendClosePortal(self._pgconn_ptr, name): + raise e.OperationalError( + f"sending close portal failed: {self.get_error_message()}" + ) + + def get_result(self) -> PGresult | None: + rv = impl.PQgetResult(self._pgconn_ptr) + return PGresult(rv) if rv else None + + def consume_input(self) -> None: + if 1 != impl.PQconsumeInput(self._pgconn_ptr): + raise e.OperationalError( + f"consuming input failed: {self.get_error_message()}" + ) + + def is_busy(self) -> int: + return impl.PQisBusy(self._pgconn_ptr) + + @property + def nonblocking(self) -> int: + return impl.PQisnonblocking(self._pgconn_ptr) + + @nonblocking.setter + def nonblocking(self, arg: int) -> None: + if 0 > impl.PQsetnonblocking(self._pgconn_ptr, arg): + raise e.OperationalError( + f"setting nonblocking failed: {self.get_error_message()}" + ) + + def flush(self) -> int: + # PQflush segfaults if it receives a NULL connection + if not self._pgconn_ptr: + raise e.OperationalError("flushing failed: the connection is closed") + rv: int = impl.PQflush(self._pgconn_ptr) + if rv < 0: + raise e.OperationalError(f"flushing failed: {self.get_error_message()}") + return rv + + def set_single_row_mode(self) -> None: + if not impl.PQsetSingleRowMode(self._pgconn_ptr): + raise e.OperationalError("setting single row mode failed") + + def set_chunked_rows_mode(self, size: int) -> None: + if not impl.PQsetChunkedRowsMode(self._pgconn_ptr, size): + raise e.OperationalError("setting chunked rows mode failed") + + def cancel_conn(self) -> PGcancelConn: + """ + Create a connection over which a cancel request can be sent. + + See :pq:`PQcancelCreate` for details. + """ + rv = impl.PQcancelCreate(self._pgconn_ptr) + if not rv: + raise e.OperationalError("couldn't create cancelConn object") + return PGcancelConn(rv) + + def get_cancel(self) -> PGcancel: + """ + Create an object with the information needed to cancel a command. + + See :pq:`PQgetCancel` for details. + """ + rv = impl.PQgetCancel(self._pgconn_ptr) + if not rv: + raise e.OperationalError("couldn't create cancel object") + return PGcancel(rv) + + def notifies(self) -> PGnotify | None: + ptr = impl.PQnotifies(self._pgconn_ptr) + if ptr: + c = ptr.contents + rv = PGnotify(c.relname, c.be_pid, c.extra) + impl.PQfreemem(ptr) + return rv + else: + return None + + def put_copy_data(self, buffer: abc.Buffer) -> int: + if not isinstance(buffer, bytes): + buffer = bytes(buffer) + rv = impl.PQputCopyData(self._pgconn_ptr, buffer, len(buffer)) + if rv < 0: + raise e.OperationalError( + f"sending copy data failed: {self.get_error_message()}" + ) + return rv + + def put_copy_end(self, error: bytes | None = None) -> int: + rv = impl.PQputCopyEnd(self._pgconn_ptr, error) + if rv < 0: + raise e.OperationalError( + f"sending copy end failed: {self.get_error_message()}" + ) + return rv + + def get_copy_data(self, async_: int) -> tuple[int, memoryview]: + buffer_ptr = c_char_p() + nbytes = impl.PQgetCopyData(self._pgconn_ptr, byref(buffer_ptr), async_) + if nbytes == -2: + raise e.OperationalError( + f"receiving copy data failed: {self.get_error_message()}" + ) + if buffer_ptr: + # TODO: do it without copy + data = string_at(buffer_ptr, nbytes) + impl.PQfreemem(buffer_ptr) + return nbytes, memoryview(data) + else: + return nbytes, memoryview(b"") + + def trace(self, fileno: int) -> None: + """ + Enable tracing of the client/server communication to a file stream. + + See :pq:`PQtrace` for details. + """ + if sys.platform != "linux": + raise e.NotSupportedError("currently only supported on Linux") + stream = impl.fdopen(fileno, b"w") + impl.PQtrace(self._pgconn_ptr, stream) + + def set_trace_flags(self, flags: Trace) -> None: + """ + Configure tracing behavior of client/server communication. + + :param flags: operating mode of tracing. + + See :pq:`PQsetTraceFlags` for details. + """ + impl.PQsetTraceFlags(self._pgconn_ptr, flags) + + def untrace(self) -> None: + """ + Disable tracing, previously enabled through `trace()`. + + See :pq:`PQuntrace` for details. + """ + impl.PQuntrace(self._pgconn_ptr) + + def encrypt_password( + self, passwd: bytes, user: bytes, algorithm: bytes | None = None + ) -> bytes: + """ + Return the encrypted form of a PostgreSQL password. + + See :pq:`PQencryptPasswordConn` for details. + """ + out = impl.PQencryptPasswordConn(self._pgconn_ptr, passwd, user, algorithm) + if not out: + raise e.OperationalError( + f"password encryption failed: {self.get_error_message()}" + ) + + rv = string_at(out) + impl.PQfreemem(out) + return rv + + def change_password(self, user: bytes, passwd: bytes) -> None: + """ + Change a PostgreSQL password. + + :raises OperationalError: if the command to change password failed. + + See :pq:`PQchangePassword` for details. + """ + res = impl.PQchangePassword(self._pgconn_ptr, user, passwd) + if impl.PQresultStatus(res) != ExecStatus.COMMAND_OK: + raise e.OperationalError( + f"failed to change password change command: {self.get_error_message()}" + ) + + def make_empty_result(self, exec_status: int) -> PGresult: + rv = impl.PQmakeEmptyPGresult(self._pgconn_ptr, exec_status) + if not rv: + raise MemoryError("couldn't allocate empty PGresult") + return PGresult(rv) + + @property + def pipeline_status(self) -> int: + if version() < 140000: + return 0 + return impl.PQpipelineStatus(self._pgconn_ptr) + + def enter_pipeline_mode(self) -> None: + """Enter pipeline mode. + + :raises ~e.OperationalError: in case of failure to enter the pipeline + mode. + """ + if impl.PQenterPipelineMode(self._pgconn_ptr) != 1: + raise e.OperationalError("failed to enter pipeline mode") + + def exit_pipeline_mode(self) -> None: + """Exit pipeline mode. + + :raises ~e.OperationalError: in case of failure to exit the pipeline + mode. + """ + if impl.PQexitPipelineMode(self._pgconn_ptr) != 1: + raise e.OperationalError(self.get_error_message()) + + def pipeline_sync(self) -> None: + """Mark a synchronization point in a pipeline. + + :raises ~e.OperationalError: if the connection is not in pipeline mode + or if sync failed. + """ + rv = impl.PQpipelineSync(self._pgconn_ptr) + if rv == 0: + raise e.OperationalError("connection not in pipeline mode") + if rv != 1: + raise e.OperationalError("failed to sync pipeline") + + def send_flush_request(self) -> None: + """Sends a request for the server to flush its output buffer. + + :raises ~e.OperationalError: if the flush request failed. + """ + if impl.PQsendFlushRequest(self._pgconn_ptr) == 0: + raise e.OperationalError( + f"flush request failed: {self.get_error_message()}" + ) + + def _call_bytes(self, func: Callable[[impl.PGconn_struct], bytes | None]) -> bytes: + """ + Call one of the pgconn libpq functions returning a bytes pointer. + """ + if not self._pgconn_ptr: + raise e.OperationalError("the connection is closed") + rv = func(self._pgconn_ptr) + assert rv is not None + return rv + + def _call_int(self, func: Callable[[impl.PGconn_struct], int]) -> int: + """ + Call one of the pgconn libpq functions returning an int. + """ + if not self._pgconn_ptr: + raise e.OperationalError("the connection is closed") + return func(self._pgconn_ptr) + + def _call_bool(self, func: Callable[[impl.PGconn_struct], int]) -> bool: + """ + Call one of the pgconn libpq functions returning a logical value. + """ + if not self._pgconn_ptr: + raise e.OperationalError("the connection is closed") + return bool(func(self._pgconn_ptr)) + + def _ensure_pgconn(self) -> None: + if not self._pgconn_ptr: + raise e.OperationalError("the connection is closed") + + +class PGresult: + """ + Python representation of a libpq result. + """ + + __slots__ = ("_pgresult_ptr",) + + def __init__(self, pgresult_ptr: impl.PGresult_struct): + self._pgresult_ptr: impl.PGresult_struct | None = pgresult_ptr + + def __del__(self) -> None: + self.clear() + + def __repr__(self) -> str: + cls = f"{self.__class__.__module__}.{self.__class__.__qualname__}" + status = ExecStatus(self.status) + return f"<{cls} [{status.name}] at 0x{id(self):x}>" + + def clear(self) -> None: + self._pgresult_ptr, p = None, self._pgresult_ptr + if p: + PQclear(p) + + @property + def pgresult_ptr(self) -> int | None: + """The pointer to the underlying `!PGresult` structure, as integer. + + `!None` if the result was cleared. + + The value can be used to pass the structure to libpq functions which + psycopg doesn't (currently) wrap, either in C or in Python using FFI + libraries such as `ctypes`. + """ + if self._pgresult_ptr is None: + return None + + return addressof(self._pgresult_ptr.contents) # type: ignore[attr-defined] + + @property + def status(self) -> int: + return impl.PQresultStatus(self._pgresult_ptr) + + @property + def error_message(self) -> bytes: + return impl.PQresultErrorMessage(self._pgresult_ptr) + + def get_error_message(self, encoding: str = "utf-8") -> str: + return _clean_error_message(self.error_message, encoding) + + def error_field(self, fieldcode: int) -> bytes | None: + return impl.PQresultErrorField(self._pgresult_ptr, fieldcode) + + @property + def ntuples(self) -> int: + return impl.PQntuples(self._pgresult_ptr) + + @property + def nfields(self) -> int: + return impl.PQnfields(self._pgresult_ptr) + + def fname(self, column_number: int) -> bytes | None: + return impl.PQfname(self._pgresult_ptr, column_number) + + def ftable(self, column_number: int) -> int: + return impl.PQftable(self._pgresult_ptr, column_number) + + def ftablecol(self, column_number: int) -> int: + return impl.PQftablecol(self._pgresult_ptr, column_number) + + def fformat(self, column_number: int) -> int: + return impl.PQfformat(self._pgresult_ptr, column_number) + + def ftype(self, column_number: int) -> int: + return impl.PQftype(self._pgresult_ptr, column_number) + + def fmod(self, column_number: int) -> int: + return impl.PQfmod(self._pgresult_ptr, column_number) + + def fsize(self, column_number: int) -> int: + return impl.PQfsize(self._pgresult_ptr, column_number) + + @property + def binary_tuples(self) -> int: + return impl.PQbinaryTuples(self._pgresult_ptr) + + def get_value(self, row_number: int, column_number: int) -> bytes | None: + length: int = impl.PQgetlength(self._pgresult_ptr, row_number, column_number) + if length: + v = impl.PQgetvalue(self._pgresult_ptr, row_number, column_number) + return string_at(v, length) + else: + if impl.PQgetisnull(self._pgresult_ptr, row_number, column_number): + return None + else: + return b"" + + @property + def nparams(self) -> int: + return impl.PQnparams(self._pgresult_ptr) + + def param_type(self, param_number: int) -> int: + return impl.PQparamtype(self._pgresult_ptr, param_number) + + @property + def command_status(self) -> bytes | None: + return impl.PQcmdStatus(self._pgresult_ptr) + + @property + def command_tuples(self) -> int | None: + rv = impl.PQcmdTuples(self._pgresult_ptr) + return int(rv) if rv else None + + @property + def oid_value(self) -> int: + return impl.PQoidValue(self._pgresult_ptr) + + def set_attributes(self, descriptions: list[PGresAttDesc]) -> None: + structs = [ + impl.PGresAttDesc_struct(*desc) for desc in descriptions # type: ignore + ] + array = (impl.PGresAttDesc_struct * len(structs))(*structs) # type: ignore + rv = impl.PQsetResultAttrs(self._pgresult_ptr, len(structs), array) + if rv == 0: + raise e.OperationalError("PQsetResultAttrs failed") + + +class PGcancelConn: + """ + Token to handle non-blocking cancellation requests. + + Created by `PGconn.cancel_conn()`. + """ + + __slots__ = ("pgcancelconn_ptr",) + + def __init__(self, pgcancelconn_ptr: impl.PGcancelConn_struct): + self.pgcancelconn_ptr: impl.PGcancelConn_struct | None = pgcancelconn_ptr + + def __del__(self) -> None: + self.finish() + + def start(self) -> None: + """Requests that the server abandons processing of the current command + in a non-blocking manner. + + See :pq:`PQcancelStart` for details. + """ + if not impl.PQcancelStart(self.pgcancelconn_ptr): + raise e.OperationalError( + f"couldn't start cancellation: {self.get_error_message()}" + ) + + def blocking(self) -> None: + """Requests that the server abandons processing of the current command + in a blocking manner. + + See :pq:`PQcancelBlocking` for details. + """ + if not impl.PQcancelBlocking(self.pgcancelconn_ptr): + raise e.OperationalError( + f"couldn't start cancellation: {self.get_error_message()}" + ) + + def poll(self) -> int: + self._ensure_pgcancelconn() + return impl.PQcancelPoll(self.pgcancelconn_ptr) + + @property + def status(self) -> int: + return impl.PQcancelStatus(self.pgcancelconn_ptr) + + @property + def socket(self) -> int: + rv = impl.PQcancelSocket(self.pgcancelconn_ptr) + if rv == -1: + raise e.OperationalError("cancel connection not opened") + return rv + + @property + def error_message(self) -> bytes: + return impl.PQcancelErrorMessage(self.pgcancelconn_ptr) + + def get_error_message(self, encoding: str = "utf-8") -> str: + return _clean_error_message(self.error_message, encoding) + + def reset(self) -> None: + self._ensure_pgcancelconn() + impl.PQcancelReset(self.pgcancelconn_ptr) + + def finish(self) -> None: + """ + Free the data structure created by `PQcancelCreate()`. + + Automatically invoked by `!__del__()`. + + See :pq:`PQcancelFinish()` for details. + """ + self.pgcancelconn_ptr, p = None, self.pgcancelconn_ptr + if p: + PQcancelFinish(p) + + def _ensure_pgcancelconn(self) -> None: + if not self.pgcancelconn_ptr: + raise e.OperationalError("the cancel connection is closed") + + +class PGcancel: + """ + Token to cancel the current operation on a connection. + + Created by `PGconn.get_cancel()`. + """ + + __slots__ = ("pgcancel_ptr",) + + def __init__(self, pgcancel_ptr: impl.PGcancel_struct): + self.pgcancel_ptr: impl.PGcancel_struct | None = pgcancel_ptr + + def __del__(self) -> None: + self.free() + + def free(self) -> None: + """ + Free the data structure created by :pq:`PQgetCancel()`. + + Automatically invoked by `!__del__()`. + + See :pq:`PQfreeCancel()` for details. + """ + self.pgcancel_ptr, p = None, self.pgcancel_ptr + if p: + PQfreeCancel(p) + + def cancel(self) -> None: + """Requests that the server abandon processing of the current command. + + See :pq:`PQcancel()` for details. + """ + buf = create_string_buffer(256) + res = impl.PQcancel( + self.pgcancel_ptr, + byref(buf), # type: ignore[arg-type] + len(buf), + ) + if not res: + raise e.OperationalError( + f"cancel failed: {buf.value.decode('utf8', 'ignore')}" + ) + + +class Conninfo: + """ + Utility object to manipulate connection strings. + """ + + @classmethod + def get_defaults(cls) -> list[ConninfoOption]: + opts = impl.PQconndefaults() + if not opts: + raise MemoryError("couldn't allocate connection defaults") + try: + return cls._options_from_array(opts) + finally: + impl.PQconninfoFree(opts) + + @classmethod + def parse(cls, conninfo: bytes) -> list[ConninfoOption]: + if not isinstance(conninfo, bytes): + raise TypeError(f"bytes expected, got {type(conninfo)} instead") + + errmsg = c_char_p() + rv = impl.PQconninfoParse(conninfo, byref(errmsg)) # type: ignore[arg-type] + if not rv: + if not errmsg: + raise MemoryError("couldn't allocate on conninfo parse") + else: + exc = e.OperationalError( + (errmsg.value or b"").decode("utf8", "replace") + ) + impl.PQfreemem(errmsg) + raise exc + + try: + return cls._options_from_array(rv) + finally: + impl.PQconninfoFree(rv) + + @classmethod + def _options_from_array( + cls, opts: Sequence[impl.PQconninfoOption_struct] + ) -> list[ConninfoOption]: + rv = [] + skws = "keyword envvar compiled val label dispchar".split() + for opt in opts: + if not opt.keyword: + break + d = {kw: getattr(opt, kw) for kw in skws} + d["dispsize"] = opt.dispsize + rv.append(ConninfoOption(**d)) + + return rv + + +class Escaping: + """ + Utility object to escape strings for SQL interpolation. + """ + + def __init__(self, conn: PGconn | None = None): + self.conn = conn + + def escape_literal(self, data: abc.Buffer) -> bytes: + if not self.conn: + raise e.OperationalError("escape_literal failed: no connection provided") + + self.conn._ensure_pgconn() + # TODO: might be done without copy (however C does that) + if not isinstance(data, bytes): + data = bytes(data) + out = impl.PQescapeLiteral(self.conn._pgconn_ptr, data, len(data)) + if not out: + raise e.OperationalError( + f"escape_literal failed: {self.conn.get_error_message()} bytes" + ) + rv = string_at(out) + impl.PQfreemem(out) + return rv + + def escape_identifier(self, data: abc.Buffer) -> bytes: + if not self.conn: + raise e.OperationalError("escape_identifier failed: no connection provided") + + self.conn._ensure_pgconn() + + if not isinstance(data, bytes): + data = bytes(data) + out = impl.PQescapeIdentifier(self.conn._pgconn_ptr, data, len(data)) + if not out: + raise e.OperationalError( + f"escape_identifier failed: {self.conn.get_error_message()} bytes" + ) + rv = string_at(out) + impl.PQfreemem(out) + return rv + + def escape_string(self, data: abc.Buffer) -> bytes: + if not isinstance(data, bytes): + data = bytes(data) + + if self.conn: + self.conn._ensure_pgconn() + error = c_int() + out = create_string_buffer(len(data) * 2 + 1) + impl.PQescapeStringConn( + self.conn._pgconn_ptr, + byref(out), # type: ignore[arg-type] + data, + len(data), + byref(error), # type: ignore[arg-type] + ) + + if error: + raise e.OperationalError( + f"escape_string failed: {self.conn.get_error_message()} bytes" + ) + + else: + out = create_string_buffer(len(data) * 2 + 1) + impl.PQescapeString( + byref(out), # type: ignore[arg-type] + data, + len(data), + ) + + return out.value + + def escape_bytea(self, data: abc.Buffer) -> bytes: + len_out = c_size_t() + # TODO: might be able to do without a copy but it's a mess. + # the C library does it better anyway, so maybe not worth optimising + # https://mail.python.org/pipermail/python-dev/2012-September/121780.html + if not isinstance(data, bytes): + data = bytes(data) + if self.conn: + self.conn._ensure_pgconn() + out = impl.PQescapeByteaConn( + self.conn._pgconn_ptr, + data, + len(data), + byref(t_cast(c_ulong, len_out)), # type: ignore[arg-type] + ) + else: + out = impl.PQescapeBytea( + data, + len(data), + byref(t_cast(c_ulong, len_out)), # type: ignore[arg-type] + ) + if not out: + raise MemoryError( + f"couldn't allocate for escape_bytea of {len(data)} bytes" + ) + + rv = string_at(out, len_out.value - 1) # out includes final 0 + impl.PQfreemem(out) + return rv + + def unescape_bytea(self, data: abc.Buffer) -> bytes: + # not needed, but let's keep it symmetric with the escaping: + # if a connection is passed in, it must be valid. + if self.conn: + self.conn._ensure_pgconn() + + len_out = c_size_t() + if not isinstance(data, bytes): + data = bytes(data) + out = impl.PQunescapeBytea( + data, + byref(t_cast(c_ulong, len_out)), # type: ignore[arg-type] + ) + if not out: + raise MemoryError( + f"couldn't allocate for unescape_bytea of {len(data)} bytes" + ) + + rv = string_at(out, len_out.value) + impl.PQfreemem(out) + return rv + + +# importing the ssl module sets up Python's libcrypto callbacks +import ssl # noqa + +# disable libcrypto setup in libpq, so it won't stomp on the callbacks +# that have already been set up +impl.PQinitOpenSSL(1, 0) + +__build_version__ = version() diff --git a/backend/.venv/Lib/site-packages/psycopg/py.typed b/backend/.venv/Lib/site-packages/psycopg/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/psycopg/raw_cursor.py b/backend/.venv/Lib/site-packages/psycopg/raw_cursor.py new file mode 100644 index 0000000..41486a2 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/raw_cursor.py @@ -0,0 +1,73 @@ +""" +psycopg raw queries cursors +""" + +# Copyright (C) 2023 The Psycopg Team + +from __future__ import annotations + +from typing import TYPE_CHECKING +from .abc import ConnectionType, Query, Params +from .sql import Composable +from .rows import Row +from ._enums import PyFormat +from .cursor import Cursor +from .cursor_async import AsyncCursor +from .server_cursor import ServerCursor, AsyncServerCursor +from ._queries import PostgresQuery +from ._cursor_base import BaseCursor + +if TYPE_CHECKING: + from typing import Any # noqa: F401 + from .connection import Connection # noqa: F401 + from .connection_async import AsyncConnection # noqa: F401 + + +class PostgresRawQuery(PostgresQuery): + def convert(self, query: Query, vars: Params | None) -> None: + if isinstance(query, str): + bquery = query.encode(self._encoding) + elif isinstance(query, Composable): + bquery = query.as_bytes(self._tx) + else: + bquery = query + + self.query = bquery + self._want_formats = self._order = None + self.dump(vars) + + def dump(self, vars: Params | None) -> None: + if vars is not None: + if not PostgresQuery.is_params_sequence(vars): + raise TypeError("raw queries require a sequence of parameters") + self._want_formats = [PyFormat.AUTO] * len(vars) + + self.params = self._tx.dump_sequence(vars, self._want_formats) + self.types = self._tx.types or () + self.formats = self._tx.formats + else: + self.params = None + self.types = () + self.formats = None + + +class RawCursorMixin(BaseCursor[ConnectionType, Row]): + _query_cls = PostgresRawQuery + + +class RawCursor(RawCursorMixin["Connection[Any]", Row], Cursor[Row]): + __module__ = "psycopg" + + +class AsyncRawCursor(RawCursorMixin["AsyncConnection[Any]", Row], AsyncCursor[Row]): + __module__ = "psycopg" + + +class RawServerCursor(RawCursorMixin["Connection[Any]", Row], ServerCursor[Row]): + __module__ = "psycopg" + + +class AsyncRawServerCursor( + RawCursorMixin["AsyncConnection[Any]", Row], AsyncServerCursor[Row] +): + __module__ = "psycopg" diff --git a/backend/.venv/Lib/site-packages/psycopg/rows.py b/backend/.venv/Lib/site-packages/psycopg/rows.py new file mode 100644 index 0000000..fe97b7d --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/rows.py @@ -0,0 +1,276 @@ +""" +psycopg row factories +""" + +# Copyright (C) 2021 The Psycopg Team + +from __future__ import annotations + +import functools +from typing import Any, Callable, NamedTuple, NoReturn +from typing import TYPE_CHECKING, Protocol, Sequence +from typing import Dict, Tuple # drop with Python 3.8 +from collections import namedtuple + +from . import pq +from . import errors as e +from ._compat import TypeAlias, TypeVar +from ._encodings import _as_python_identifier + +if TYPE_CHECKING: + from .cursor import Cursor + from ._cursor_base import BaseCursor + from .cursor_async import AsyncCursor + from psycopg.pq.abc import PGresult + +COMMAND_OK = pq.ExecStatus.COMMAND_OK +TUPLES_OK = pq.ExecStatus.TUPLES_OK +SINGLE_TUPLE = pq.ExecStatus.SINGLE_TUPLE +TUPLES_CHUNK = pq.ExecStatus.TUPLES_CHUNK + +T = TypeVar("T", covariant=True) + +# Row factories + +Row = TypeVar("Row", covariant=True, default="TupleRow") + + +class RowMaker(Protocol[Row]): + """ + Callable protocol taking a sequence of value and returning an object. + + The sequence of value is what is returned from a database query, already + adapted to the right Python types. The return value is the object that your + program would like to receive: by default (`tuple_row()`) it is a simple + tuple, but it may be any type of object. + + Typically, `!RowMaker` functions are returned by `RowFactory`. + """ + + def __call__(self, __values: Sequence[Any]) -> Row: ... + + +class RowFactory(Protocol[Row]): + """ + Callable protocol taking a `~psycopg.Cursor` and returning a `RowMaker`. + + A `!RowFactory` is typically called when a `!Cursor` receives a result. + This way it can inspect the cursor state (for instance the + `~psycopg.Cursor.description` attribute) and help a `!RowMaker` to create + a complete object. + + For instance the `dict_row()` `!RowFactory` uses the names of the column to + define the dictionary key and returns a `!RowMaker` function which would + use the values to create a dictionary for each record. + """ + + def __call__(self, __cursor: Cursor[Any]) -> RowMaker[Row]: ... + + +class AsyncRowFactory(Protocol[Row]): + """ + Like `RowFactory`, taking an async cursor as argument. + """ + + def __call__(self, __cursor: AsyncCursor[Any]) -> RowMaker[Row]: ... + + +class BaseRowFactory(Protocol[Row]): + """ + Like `RowFactory`, taking either type of cursor as argument. + """ + + def __call__(self, __cursor: BaseCursor[Any, Any]) -> RowMaker[Row]: ... + + +TupleRow: TypeAlias = Tuple[Any, ...] +""" +An alias for the type returned by `tuple_row()` (i.e. a tuple of any content). +""" + + +DictRow: TypeAlias = Dict[str, Any] +""" +An alias for the type returned by `dict_row()` + +A `!DictRow` is a dictionary with keys as string and any value returned by the +database. +""" + + +def tuple_row(cursor: BaseCursor[Any, Any]) -> RowMaker[TupleRow]: + r"""Row factory to represent rows as simple tuples. + + This is the default factory, used when `~psycopg.Connection.connect()` or + `~psycopg.Connection.cursor()` are called without a `!row_factory` + parameter. + + """ + # Implementation detail: make sure this is the tuple type itself, not an + # equivalent function, because the C code fast-paths on it. + return tuple + + +def dict_row(cursor: BaseCursor[Any, Any]) -> RowMaker[DictRow]: + """Row factory to represent rows as dictionaries. + + The dictionary keys are taken from the column names of the returned columns. + """ + names = _get_names(cursor) + if names is None: + return no_result + + def dict_row_(values: Sequence[Any]) -> dict[str, Any]: + return dict(zip(names, values)) + + return dict_row_ + + +def namedtuple_row(cursor: BaseCursor[Any, Any]) -> RowMaker[NamedTuple]: + """Row factory to represent rows as `~collections.namedtuple`. + + The field names are taken from the column names of the returned columns, + with some mangling to deal with invalid names. + """ + res = cursor.pgresult + if not res: + return no_result + + nfields = _get_nfields(res) + if nfields is None: + return no_result + + nt = _make_nt(cursor._encoding, *(res.fname(i) for i in range(nfields))) + return nt._make + + +@functools.lru_cache(512) +def _make_nt(enc: str, *names: bytes) -> type[NamedTuple]: + snames = tuple(_as_python_identifier(n.decode(enc)) for n in names) + return namedtuple("Row", snames) # type: ignore[return-value] + + +def class_row(cls: type[T]) -> BaseRowFactory[T]: + r"""Generate a row factory to represent rows as instances of the class `!cls`. + + The class must support every output column name as a keyword parameter. + + :param cls: The class to return for each row. It must support the fields + returned by the query as keyword arguments. + :rtype: `!Callable[[Cursor],` `RowMaker`\[~T]] + """ + + def class_row_(cursor: BaseCursor[Any, Any]) -> RowMaker[T]: + names = _get_names(cursor) + if names is None: + return no_result + + def class_row__(values: Sequence[Any]) -> T: + return cls(**dict(zip(names, values))) + + return class_row__ + + return class_row_ + + +def args_row(func: Callable[..., T]) -> BaseRowFactory[T]: + """Generate a row factory calling `!func` with positional parameters for every row. + + :param func: The function to call for each row. It must support the fields + returned by the query as positional arguments. + """ + + def args_row_(cur: BaseCursor[Any, T]) -> RowMaker[T]: + def args_row__(values: Sequence[Any]) -> T: + return func(*values) + + return args_row__ + + return args_row_ + + +def kwargs_row(func: Callable[..., T]) -> BaseRowFactory[T]: + """Generate a row factory calling `!func` with keyword parameters for every row. + + :param func: The function to call for each row. It must support the fields + returned by the query as keyword arguments. + """ + + def kwargs_row_(cursor: BaseCursor[Any, T]) -> RowMaker[T]: + names = _get_names(cursor) + if names is None: + return no_result + + def kwargs_row__(values: Sequence[Any]) -> T: + return func(**dict(zip(names, values))) + + return kwargs_row__ + + return kwargs_row_ + + +def scalar_row(cursor: BaseCursor[Any, Any]) -> RowMaker[Any]: + """ + Generate a row factory returning the first column + as a scalar value. + """ + res = cursor.pgresult + if not res: + return no_result + + nfields = _get_nfields(res) + if nfields is None: + return no_result + + if nfields < 1: + raise e.ProgrammingError("at least one column expected") + + def scalar_row_(values: Sequence[Any]) -> Any: + return values[0] + + return scalar_row_ + + +def no_result(values: Sequence[Any]) -> NoReturn: + """A `RowMaker` that always fail. + + It can be used as return value for a `RowFactory` called with no result. + Note that the `!RowFactory` *will* be called with no result, but the + resulting `!RowMaker` never should. + """ + raise e.InterfaceError("the cursor doesn't have a result") + + +def _get_names(cursor: BaseCursor[Any, Any]) -> list[str] | None: + res = cursor.pgresult + if not res: + return None + + nfields = _get_nfields(res) + if nfields is None: + return None + + enc = cursor._encoding + return [ + res.fname(i).decode(enc) for i in range(nfields) # type: ignore[union-attr] + ] + + +def _get_nfields(res: PGresult) -> int | None: + """ + Return the number of columns in a result, if it returns tuples else None + + Take into account the special case of results with zero columns. + """ + nfields = res.nfields + + if ( + res.status == TUPLES_OK + or res.status == SINGLE_TUPLE + or res.status == TUPLES_CHUNK + # "describe" in named cursors + or (res.status == COMMAND_OK and nfields) + ): + return nfields + else: + return None diff --git a/backend/.venv/Lib/site-packages/psycopg/server_cursor.py b/backend/.venv/Lib/site-packages/psycopg/server_cursor.py new file mode 100644 index 0000000..c1492b3 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/server_cursor.py @@ -0,0 +1,475 @@ +""" +psycopg server-side cursor objects. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +from typing import Any, AsyncIterator, Iterable, Iterator, TYPE_CHECKING, overload +from warnings import warn + +from . import pq +from . import sql +from . import errors as e +from .abc import ConnectionType, Query, Params, PQGen +from .rows import Row, RowFactory, AsyncRowFactory +from .cursor import Cursor +from ._compat import Self +from .generators import execute +from ._cursor_base import BaseCursor +from .cursor_async import AsyncCursor + +if TYPE_CHECKING: + from .connection import Connection + from .connection_async import AsyncConnection + +DEFAULT_ITERSIZE = 100 + +TEXT = pq.Format.TEXT +BINARY = pq.Format.BINARY + +COMMAND_OK = pq.ExecStatus.COMMAND_OK +TUPLES_OK = pq.ExecStatus.TUPLES_OK + +IDLE = pq.TransactionStatus.IDLE +INTRANS = pq.TransactionStatus.INTRANS + + +class ServerCursorMixin(BaseCursor[ConnectionType, Row]): + """Mixin to add ServerCursor behaviour and implementation a BaseCursor.""" + + __slots__ = "_name _scrollable _withhold _described itersize _format".split() + + def __init__( + self, + name: str, + scrollable: bool | None, + withhold: bool, + ): + self._name = name + self._scrollable = scrollable + self._withhold = withhold + self._described = False + self.itersize: int = DEFAULT_ITERSIZE + self._format = TEXT + + def __repr__(self) -> str: + # Insert the name as the second word + parts = super().__repr__().split(None, 1) + parts.insert(1, f"{self._name!r}") + return " ".join(parts) + + @property + def name(self) -> str: + """The name of the cursor.""" + return self._name + + @property + def scrollable(self) -> bool | None: + """ + Whether the cursor is scrollable or not. + + If `!None` leave the choice to the server. Use `!True` if you want to + use `scroll()` on the cursor. + """ + return self._scrollable + + @property + def withhold(self) -> bool: + """ + If the cursor can be used after the creating transaction has committed. + """ + return self._withhold + + @property + def rownumber(self) -> int | None: + """Index of the next row to fetch in the current result. + + `!None` if there is no result to fetch. + """ + res = self.pgresult + # command_status is empty if the result comes from + # describe_portal, which means that we have just executed the DECLARE, + # so we can assume we are at the first row. + tuples = res and (res.status == TUPLES_OK or res.command_status == b"") + return self._pos if tuples else None + + def _declare_gen( + self, + query: Query, + params: Params | None = None, + binary: bool | None = None, + ) -> PQGen[None]: + """Generator implementing `ServerCursor.execute()`.""" + + query = self._make_declare_statement(query) + + # If the cursor is being reused, the previous one must be closed. + if self._described: + yield from self._close_gen() + self._described = False + + yield from self._start_query(query) + pgq = self._convert_query(query, params) + self._execute_send(pgq, force_extended=True) + results = yield from execute(self._conn.pgconn) + if results[-1].status != COMMAND_OK: + self._raise_for_result(results[-1]) + + # Set the format, which will be used by describe and fetch operations + if binary is None: + self._format = self.format + else: + self._format = BINARY if binary else TEXT + + # The above result only returned COMMAND_OK. Get the cursor shape + yield from self._describe_gen() + + def _describe_gen(self) -> PQGen[None]: + self._pgconn.send_describe_portal(self._name.encode(self._encoding)) + results = yield from execute(self._pgconn) + self._check_results(results) + self._results = results + self._select_current_result(0, format=self._format) + self._described = True + + def _close_gen(self) -> PQGen[None]: + ts = self._conn.pgconn.transaction_status + + # if the connection is not in a sane state, don't even try + if ts != IDLE and ts != INTRANS: + return + + # If we are IDLE, a WITHOUT HOLD cursor will surely have gone already. + if not self._withhold and ts == IDLE: + return + + # if we didn't declare the cursor ourselves we still have to close it + # but we must make sure it exists. + if not self._described: + query = sql.SQL( + "SELECT 1 FROM pg_catalog.pg_cursors WHERE name = {}" + ).format(sql.Literal(self._name)) + res = yield from self._conn._exec_command(query) + # pipeline mode otherwise, unsupported here. + assert res is not None + if res.ntuples == 0: + return + + query = sql.SQL("CLOSE {}").format(sql.Identifier(self._name)) + yield from self._conn._exec_command(query) + + def _fetch_gen(self, num: int | None) -> PQGen[list[Row]]: + if self.closed: + raise e.InterfaceError("the cursor is closed") + # If we are stealing the cursor, make sure we know its shape + if not self._described: + yield from self._start_query() + yield from self._describe_gen() + + query = sql.SQL("FETCH FORWARD {} FROM {}").format( + sql.SQL("ALL") if num is None else sql.Literal(num), + sql.Identifier(self._name), + ) + res = yield from self._conn._exec_command(query, result_format=self._format) + # pipeline mode otherwise, unsupported here. + assert res is not None + + self.pgresult = res + self._tx.set_pgresult(res, set_loaders=False) + return self._tx.load_rows(0, res.ntuples, self._make_row) + + def _scroll_gen(self, value: int, mode: str) -> PQGen[None]: + if mode not in ("relative", "absolute"): + raise ValueError(f"bad mode: {mode}. It should be 'relative' or 'absolute'") + query = sql.SQL("MOVE{} {} FROM {}").format( + sql.SQL(" ABSOLUTE" if mode == "absolute" else ""), + sql.Literal(value), + sql.Identifier(self._name), + ) + yield from self._conn._exec_command(query) + + def _make_declare_statement(self, query: Query) -> sql.Composed: + if isinstance(query, bytes): + query = query.decode(self._encoding) + if not isinstance(query, sql.Composable): + query = sql.SQL(query) + + parts = [ + sql.SQL("DECLARE"), + sql.Identifier(self._name), + ] + if self._scrollable is not None: + parts.append(sql.SQL("SCROLL" if self._scrollable else "NO SCROLL")) + parts.append(sql.SQL("CURSOR")) + if self._withhold: + parts.append(sql.SQL("WITH HOLD")) + parts.append(sql.SQL("FOR")) + parts.append(query) + + return sql.SQL(" ").join(parts) + + +class ServerCursor(ServerCursorMixin["Connection[Any]", Row], Cursor[Row]): + __module__ = "psycopg" + __slots__ = () + + @overload + def __init__( + self, + connection: Connection[Row], + name: str, + *, + scrollable: bool | None = None, + withhold: bool = False, + ): ... + + @overload + def __init__( + self, + connection: Connection[Any], + name: str, + *, + row_factory: RowFactory[Row], + scrollable: bool | None = None, + withhold: bool = False, + ): ... + + def __init__( + self, + connection: Connection[Any], + name: str, + *, + row_factory: RowFactory[Row] | None = None, + scrollable: bool | None = None, + withhold: bool = False, + ): + Cursor.__init__( + self, connection, row_factory=row_factory or connection.row_factory + ) + ServerCursorMixin.__init__(self, name, scrollable, withhold) + + def __del__(self) -> None: + if not self.closed: + warn( + f"the server-side cursor {self} was deleted while still open." + " Please use 'with' or '.close()' to close the cursor properly", + ResourceWarning, + ) + + def close(self) -> None: + """ + Close the current cursor and free associated resources. + """ + with self._conn.lock: + if self.closed: + return + if not self._conn.closed: + self._conn.wait(self._close_gen()) + super().close() + + def execute( + self, + query: Query, + params: Params | None = None, + *, + binary: bool | None = None, + **kwargs: Any, + ) -> Self: + """ + Open a cursor to execute a query to the database. + """ + if kwargs: + raise TypeError(f"keyword not supported: {list(kwargs)[0]}") + if self._pgconn.pipeline_status: + raise e.NotSupportedError( + "server-side cursors not supported in pipeline mode" + ) + + try: + with self._conn.lock: + self._conn.wait(self._declare_gen(query, params, binary)) + except e._NO_TRACEBACK as ex: + raise ex.with_traceback(None) + + return self + + def executemany( + self, + query: Query, + params_seq: Iterable[Params], + *, + returning: bool = True, + ) -> None: + """Method not implemented for server-side cursors.""" + raise e.NotSupportedError("executemany not supported on server-side cursors") + + def fetchone(self) -> Row | None: + with self._conn.lock: + recs = self._conn.wait(self._fetch_gen(1)) + if recs: + self._pos += 1 + return recs[0] + else: + return None + + def fetchmany(self, size: int = 0) -> list[Row]: + if not size: + size = self.arraysize + with self._conn.lock: + recs = self._conn.wait(self._fetch_gen(size)) + self._pos += len(recs) + return recs + + def fetchall(self) -> list[Row]: + with self._conn.lock: + recs = self._conn.wait(self._fetch_gen(None)) + self._pos += len(recs) + return recs + + def __iter__(self) -> Iterator[Row]: + while True: + with self._conn.lock: + recs = self._conn.wait(self._fetch_gen(self.itersize)) + for rec in recs: + self._pos += 1 + yield rec + if len(recs) < self.itersize: + break + + def scroll(self, value: int, mode: str = "relative") -> None: + with self._conn.lock: + self._conn.wait(self._scroll_gen(value, mode)) + # Postgres doesn't have a reliable way to report a cursor out of bound + if mode == "relative": + self._pos += value + else: + self._pos = value + + +class AsyncServerCursor( + ServerCursorMixin["AsyncConnection[Any]", Row], AsyncCursor[Row] +): + __module__ = "psycopg" + __slots__ = () + + @overload + def __init__( + self, + connection: AsyncConnection[Row], + name: str, + *, + scrollable: bool | None = None, + withhold: bool = False, + ): ... + + @overload + def __init__( + self, + connection: AsyncConnection[Any], + name: str, + *, + row_factory: AsyncRowFactory[Row], + scrollable: bool | None = None, + withhold: bool = False, + ): ... + + def __init__( + self, + connection: AsyncConnection[Any], + name: str, + *, + row_factory: AsyncRowFactory[Row] | None = None, + scrollable: bool | None = None, + withhold: bool = False, + ): + AsyncCursor.__init__( + self, connection, row_factory=row_factory or connection.row_factory + ) + ServerCursorMixin.__init__(self, name, scrollable, withhold) + + def __del__(self) -> None: + if not self.closed: + warn( + f"the server-side cursor {self} was deleted while still open." + " Please use 'with' or '.close()' to close the cursor properly", + ResourceWarning, + ) + + async def close(self) -> None: + async with self._conn.lock: + if self.closed: + return + if not self._conn.closed: + await self._conn.wait(self._close_gen()) + await super().close() + + async def execute( + self, + query: Query, + params: Params | None = None, + *, + binary: bool | None = None, + **kwargs: Any, + ) -> Self: + if kwargs: + raise TypeError(f"keyword not supported: {list(kwargs)[0]}") + if self._pgconn.pipeline_status: + raise e.NotSupportedError( + "server-side cursors not supported in pipeline mode" + ) + + try: + async with self._conn.lock: + await self._conn.wait(self._declare_gen(query, params, binary)) + except e._NO_TRACEBACK as ex: + raise ex.with_traceback(None) + + return self + + async def executemany( + self, + query: Query, + params_seq: Iterable[Params], + *, + returning: bool = True, + ) -> None: + raise e.NotSupportedError("executemany not supported on server-side cursors") + + async def fetchone(self) -> Row | None: + async with self._conn.lock: + recs = await self._conn.wait(self._fetch_gen(1)) + if recs: + self._pos += 1 + return recs[0] + else: + return None + + async def fetchmany(self, size: int = 0) -> list[Row]: + if not size: + size = self.arraysize + async with self._conn.lock: + recs = await self._conn.wait(self._fetch_gen(size)) + self._pos += len(recs) + return recs + + async def fetchall(self) -> list[Row]: + async with self._conn.lock: + recs = await self._conn.wait(self._fetch_gen(None)) + self._pos += len(recs) + return recs + + async def __aiter__(self) -> AsyncIterator[Row]: + while True: + async with self._conn.lock: + recs = await self._conn.wait(self._fetch_gen(self.itersize)) + for rec in recs: + self._pos += 1 + yield rec + if len(recs) < self.itersize: + break + + async def scroll(self, value: int, mode: str = "relative") -> None: + async with self._conn.lock: + await self._conn.wait(self._scroll_gen(value, mode)) diff --git a/backend/.venv/Lib/site-packages/psycopg/sql.py b/backend/.venv/Lib/site-packages/psycopg/sql.py new file mode 100644 index 0000000..c0b5b8e --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/sql.py @@ -0,0 +1,484 @@ +""" +SQL composition utility module +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import codecs +import string +from abc import ABC, abstractmethod +from typing import Any, Iterator, Iterable, Sequence + +from .pq import Escaping +from .abc import AdaptContext +from ._enums import PyFormat +from ._compat import LiteralString +from ._encodings import conn_encoding +from ._transformer import Transformer + + +def quote(obj: Any, context: AdaptContext | None = None) -> str: + """ + Adapt a Python object to a quoted SQL string. + + Use this function only if you absolutely want to convert a Python string to + an SQL quoted literal to use e.g. to generate batch SQL and you won't have + a connection available when you will need to use it. + + This function is relatively inefficient, because it doesn't cache the + adaptation rules. If you pass a `!context` you can adapt the adaptation + rules used, otherwise only global rules are used. + + """ + return Literal(obj).as_string(context) + + +class Composable(ABC): + """ + Abstract base class for objects that can be used to compose an SQL string. + + `!Composable` objects can be joined using the ``+`` operator: the result + will be a `Composed` instance containing the objects joined. The operator + ``*`` is also supported with an integer argument: the result is a + `!Composed` instance containing the left argument repeated as many times as + requested. + + `!SQL` and `!Composed` objects can be passed directly to + `~psycopg.Cursor.execute()`, `~psycopg.Cursor.executemany()`, + `~psycopg.Cursor.copy()` in place of the query string. + """ + + def __init__(self, obj: Any): + self._obj = obj + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self._obj!r})" + + @abstractmethod + def as_bytes(self, context: AdaptContext | None = None) -> bytes: + """ + Return the value of the object as bytes. + + :param context: the context to evaluate the object into. + :type context: `connection` or `cursor` + + The method is automatically invoked by `~psycopg.Cursor.execute()`, + `~psycopg.Cursor.executemany()`, `~psycopg.Cursor.copy()` if a + `!Composable` is passed instead of the query string. + + """ + raise NotImplementedError + + def as_string(self, context: AdaptContext | None = None) -> str: + """ + Return the value of the object as string. + + :param context: the context to evaluate the string into. + :type context: `connection` or `cursor` + + """ + conn = context.connection if context else None + enc = conn_encoding(conn) + b = self.as_bytes(context) + if isinstance(b, bytes): + return b.decode(enc) + else: + # buffer object + return codecs.lookup(enc).decode(b)[0] + + def __add__(self, other: Composable) -> Composed: + if isinstance(other, Composed): + return Composed([self]) + other + if isinstance(other, Composable): + return Composed([self]) + Composed([other]) + else: + return NotImplemented + + def __mul__(self, n: int) -> Composed: + return Composed([self] * n) + + def __eq__(self, other: Any) -> bool: + return type(self) is type(other) and self._obj == other._obj + + def __ne__(self, other: Any) -> bool: + return not self.__eq__(other) + + +class Composed(Composable): + """ + A `Composable` object made of a sequence of `!Composable`. + + The object is usually created using `!Composable` operators and methods + (such as the `SQL.format()` method). `!Composed` objects can be passed + directly to `~psycopg.Cursor.execute()`, `~psycopg.Cursor.executemany()`, + `~psycopg.Cursor.copy()` in place of the query string. + + It is also possible to create a `!Composed` directly specifying a sequence + of objects as arguments: if they are not `!Composable` they will be wrapped + in a `Literal`. + + Example:: + + >>> comp = sql.Composed( + ... [sql.SQL("INSERT INTO "), sql.Identifier("table")]) + >>> print(comp.as_string(conn)) + INSERT INTO "table" + + `!Composed` objects are iterable (so they can be used in `SQL.join` for + instance). + """ + + _obj: list[Composable] + + def __init__(self, seq: Sequence[Any]): + seq = [obj if isinstance(obj, Composable) else Literal(obj) for obj in seq] + super().__init__(seq) + + def as_bytes(self, context: AdaptContext | None = None) -> bytes: + return b"".join(obj.as_bytes(context) for obj in self._obj) + + def __iter__(self) -> Iterator[Composable]: + return iter(self._obj) + + def __add__(self, other: Composable) -> Composed: + if isinstance(other, Composed): + return Composed(self._obj + other._obj) + if isinstance(other, Composable): + return Composed(self._obj + [other]) + else: + return NotImplemented + + def join(self, joiner: SQL | LiteralString) -> Composed: + """ + Return a new `!Composed` interposing the `!joiner` with the `!Composed` items. + + The `!joiner` must be a `SQL` or a string which will be interpreted as + an `SQL`. + + Example:: + + >>> fields = sql.Identifier('foo') + sql.Identifier('bar') # a Composed + >>> print(fields.join(', ').as_string(conn)) + "foo", "bar" + + """ + if isinstance(joiner, str): + joiner = SQL(joiner) + elif not isinstance(joiner, SQL): + raise TypeError( + "Composed.join() argument must be strings or SQL," + f" got {joiner!r} instead" + ) + + return joiner.join(self._obj) + + +class SQL(Composable): + """ + A `Composable` representing a snippet of SQL statement. + + `!SQL` exposes `join()` and `format()` methods useful to create a template + where to merge variable parts of a query (for instance field or table + names). + + The `!obj` string doesn't undergo any form of escaping, so it is not + suitable to represent variable identifiers or values: you should only use + it to pass constant strings representing templates or snippets of SQL + statements; use other objects such as `Identifier` or `Literal` to + represent variable parts. + + `!SQL` objects can be passed directly to `~psycopg.Cursor.execute()`, + `~psycopg.Cursor.executemany()`, `~psycopg.Cursor.copy()` in place of the + query string. + + Example:: + + >>> query = sql.SQL("SELECT {0} FROM {1}").format( + ... sql.SQL(', ').join([sql.Identifier('foo'), sql.Identifier('bar')]), + ... sql.Identifier('table')) + >>> print(query.as_string(conn)) + SELECT "foo", "bar" FROM "table" + """ + + _obj: LiteralString + _formatter = string.Formatter() + + def __init__(self, obj: LiteralString): + super().__init__(obj) + if not isinstance(obj, str): + raise TypeError(f"SQL values must be strings, got {obj!r} instead") + + def as_string(self, context: AdaptContext | None = None) -> str: + return self._obj + + def as_bytes(self, context: AdaptContext | None = None) -> bytes: + conn = context.connection if context else None + enc = conn_encoding(conn) + return self._obj.encode(enc) + + def format(self, *args: Any, **kwargs: Any) -> Composed: + """ + Merge `Composable` objects into a template. + + :param args: parameters to replace to numbered (``{0}``, ``{1}``) or + auto-numbered (``{}``) placeholders + :param kwargs: parameters to replace to named (``{name}``) placeholders + :return: the union of the `!SQL` string with placeholders replaced + :rtype: `Composed` + + The method is similar to the Python `str.format()` method: the string + template supports auto-numbered (``{}``), numbered (``{0}``, + ``{1}``...), and named placeholders (``{name}``), with positional + arguments replacing the numbered placeholders and keywords replacing + the named ones. However placeholder modifiers (``{0!r}``, ``{0:<10}``) + are not supported. + + If a `!Composable` objects is passed to the template it will be merged + according to its `as_string()` method. If any other Python object is + passed, it will be wrapped in a `Literal` object and so escaped + according to SQL rules. + + Example:: + + >>> print(sql.SQL("SELECT * FROM {} WHERE {} = %s") + ... .format(sql.Identifier('people'), sql.Identifier('id')) + ... .as_string(conn)) + SELECT * FROM "people" WHERE "id" = %s + + >>> print(sql.SQL("SELECT * FROM {tbl} WHERE name = {name}") + ... .format(tbl=sql.Identifier('people'), name="O'Rourke")) + ... .as_string(conn)) + SELECT * FROM "people" WHERE name = 'O''Rourke' + + """ + rv: list[Composable] = [] + autonum: int | None = 0 + # TODO: this is probably not the right way to whitelist pre + # pyre complains. Will wait for mypy to complain too to fix. + pre: LiteralString + for pre, name, spec, conv in self._formatter.parse(self._obj): + if spec: + raise ValueError("no format specification supported by SQL") + if conv: + raise ValueError("no format conversion supported by SQL") + if pre: + rv.append(SQL(pre)) + + if name is None: + continue + + if name.isdigit(): + if autonum: + raise ValueError( + "cannot switch from automatic field numbering to manual" + ) + rv.append(args[int(name)]) + autonum = None + + elif not name: + if autonum is None: + raise ValueError( + "cannot switch from manual field numbering to automatic" + ) + rv.append(args[autonum]) + autonum += 1 + + else: + rv.append(kwargs[name]) + + return Composed(rv) + + def join(self, seq: Iterable[Composable]) -> Composed: + """ + Join a sequence of `Composable`. + + :param seq: the elements to join. + :type seq: iterable of `!Composable` + + Use the `!SQL` object's string to separate the elements in `!seq`. + Note that `Composed` objects are iterable too, so they can be used as + argument for this method. + + Example:: + + >>> snip = sql.SQL(', ').join( + ... sql.Identifier(n) for n in ['foo', 'bar', 'baz']) + >>> print(snip.as_string(conn)) + "foo", "bar", "baz" + """ + rv = [] + it = iter(seq) + try: + rv.append(next(it)) + except StopIteration: + pass + else: + for i in it: + rv.append(self) + rv.append(i) + + return Composed(rv) + + +class Identifier(Composable): + """ + A `Composable` representing an SQL identifier or a dot-separated sequence. + + Identifiers usually represent names of database objects, such as tables or + fields. PostgreSQL identifiers follow `different rules`__ than SQL string + literals for escaping (e.g. they use double quotes instead of single). + + .. __: https://www.postgresql.org/docs/current/sql-syntax-lexical.html# \ + SQL-SYNTAX-IDENTIFIERS + + Example:: + + >>> t1 = sql.Identifier("foo") + >>> t2 = sql.Identifier("ba'r") + >>> t3 = sql.Identifier('ba"z') + >>> print(sql.SQL(', ').join([t1, t2, t3]).as_string(conn)) + "foo", "ba'r", "ba""z" + + Multiple strings can be passed to the object to represent a qualified name, + i.e. a dot-separated sequence of identifiers. + + Example:: + + >>> query = sql.SQL("SELECT {} FROM {}").format( + ... sql.Identifier("table", "field"), + ... sql.Identifier("schema", "table")) + >>> print(query.as_string(conn)) + SELECT "table"."field" FROM "schema"."table" + + """ + + _obj: Sequence[str] + + def __init__(self, *strings: str): + # init super() now to make the __repr__ not explode in case of error + super().__init__(strings) + + if not strings: + raise TypeError("Identifier cannot be empty") + + for s in strings: + if not isinstance(s, str): + raise TypeError( + f"SQL identifier parts must be strings, got {s!r} instead" + ) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({', '.join(map(repr, self._obj))})" + + def as_bytes(self, context: AdaptContext | None = None) -> bytes: + conn = context.connection if context else None + if conn: + esc = Escaping(conn.pgconn) + enc = conn_encoding(conn) + escs = [esc.escape_identifier(s.encode(enc)) for s in self._obj] + else: + escs = [self._escape_identifier(s.encode()) for s in self._obj] + return b".".join(escs) + + def _escape_identifier(self, s: bytes) -> bytes: + """ + Approximation of PQescapeIdentifier taking no connection. + """ + return b'"' + s.replace(b'"', b'""') + b'"' + + +class Literal(Composable): + """ + A `Composable` representing an SQL value to include in a query. + + Usually you will want to include placeholders in the query and pass values + as `~cursor.execute()` arguments. If however you really really need to + include a literal value in the query you can use this object. + + The string returned by `!as_string()` follows the normal :ref:`adaptation + rules ` for Python objects. + + Example:: + + >>> s1 = sql.Literal("fo'o") + >>> s2 = sql.Literal(42) + >>> s3 = sql.Literal(date(2000, 1, 1)) + >>> print(sql.SQL(', ').join([s1, s2, s3]).as_string(conn)) + 'fo''o', 42, '2000-01-01'::date + + """ + + def as_bytes(self, context: AdaptContext | None = None) -> bytes: + tx = Transformer.from_context(context) + return tx.as_literal(self._obj) + + +class Placeholder(Composable): + """A `Composable` representing a placeholder for query parameters. + + If the name is specified, generate a named placeholder (e.g. ``%(name)s``, + ``%(name)b``), otherwise generate a positional placeholder (e.g. ``%s``, + ``%b``). + + The object is useful to generate SQL queries with a variable number of + arguments. + + Examples:: + + >>> names = ['foo', 'bar', 'baz'] + + >>> q1 = sql.SQL("INSERT INTO my_table ({}) VALUES ({})").format( + ... sql.SQL(', ').join(map(sql.Identifier, names)), + ... sql.SQL(', ').join(sql.Placeholder() * len(names))) + >>> print(q1.as_string(conn)) + INSERT INTO my_table ("foo", "bar", "baz") VALUES (%s, %s, %s) + + >>> q2 = sql.SQL("INSERT INTO my_table ({}) VALUES ({})").format( + ... sql.SQL(', ').join(map(sql.Identifier, names)), + ... sql.SQL(', ').join(map(sql.Placeholder, names))) + >>> print(q2.as_string(conn)) + INSERT INTO my_table ("foo", "bar", "baz") VALUES (%(foo)s, %(bar)s, %(baz)s) + + """ + + def __init__(self, name: str = "", format: str | PyFormat = PyFormat.AUTO): + super().__init__(name) + if not isinstance(name, str): + raise TypeError(f"expected string as name, got {name!r}") + + if ")" in name: + raise ValueError(f"invalid name: {name!r}") + + if type(format) is str: + format = PyFormat(format) + if not isinstance(format, PyFormat): + raise TypeError( + f"expected PyFormat as format, got {type(format).__name__!r}" + ) + + self._format: PyFormat = format + + def __repr__(self) -> str: + parts = [] + if self._obj: + parts.append(repr(self._obj)) + if self._format is not PyFormat.AUTO: + parts.append(f"format={self._format.name}") + + return f"{self.__class__.__name__}({', '.join(parts)})" + + def as_string(self, context: AdaptContext | None = None) -> str: + code = self._format.value + return f"%({self._obj}){code}" if self._obj else f"%{code}" + + def as_bytes(self, context: AdaptContext | None = None) -> bytes: + conn = context.connection if context else None + enc = conn_encoding(conn) + return self.as_string(context).encode(enc) + + +# Literals +NULL = SQL("NULL") +DEFAULT = SQL("DEFAULT") diff --git a/backend/.venv/Lib/site-packages/psycopg/transaction.py b/backend/.venv/Lib/site-packages/psycopg/transaction.py new file mode 100644 index 0000000..d0a3aa3 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/transaction.py @@ -0,0 +1,286 @@ +""" +Transaction context managers returned by Connection.transaction() +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import logging + +from types import TracebackType +from typing import Any, Generic, Iterator, TYPE_CHECKING + +from . import pq +from . import sql +from . import errors as e +from .abc import ConnectionType, PQGen +from ._compat import Self +from .pq.misc import connection_summary + +if TYPE_CHECKING: + from .connection import Connection + from .connection_async import AsyncConnection + +IDLE = pq.TransactionStatus.IDLE + +OK = pq.ConnStatus.OK + +logger = logging.getLogger(__name__) + + +class Rollback(Exception): + """ + Exit the current `Transaction` context immediately and rollback any changes + made within this context. + + If a transaction context is specified in the constructor, rollback + enclosing transactions contexts up to and including the one specified. + """ + + __module__ = "psycopg" + + def __init__(self, transaction: Transaction | AsyncTransaction | None = None): + self.transaction = transaction + + def __repr__(self) -> str: + return f"{self.__class__.__qualname__}({self.transaction!r})" + + +class OutOfOrderTransactionNesting(e.ProgrammingError): + """Out-of-order transaction nesting detected""" + + +class BaseTransaction(Generic[ConnectionType]): + def __init__( + self, + connection: ConnectionType, + savepoint_name: str | None = None, + force_rollback: bool = False, + ): + self._conn = connection + self.pgconn = self._conn.pgconn + self._savepoint_name = savepoint_name or "" + self.force_rollback = force_rollback + self._entered = self._exited = False + self._outer_transaction = False + self._stack_index = -1 + + @property + def savepoint_name(self) -> str | None: + """ + The name of the savepoint; `!None` if handling the main transaction. + """ + # Yes, it may change on __enter__. No, I don't care, because the + # un-entered state is outside the public interface. + return self._savepoint_name + + def __repr__(self) -> str: + cls = f"{self.__class__.__module__}.{self.__class__.__qualname__}" + info = connection_summary(self.pgconn) + if not self._entered: + status = "inactive" + elif not self._exited: + status = "active" + else: + status = "terminated" + + sp = f"{self.savepoint_name!r} " if self.savepoint_name else "" + return f"<{cls} {sp}({status}) {info} at 0x{id(self):x}>" + + def _enter_gen(self) -> PQGen[None]: + if self._entered: + raise TypeError("transaction blocks can be used only once") + self._entered = True + + self._push_savepoint() + for command in self._get_enter_commands(): + yield from self._conn._exec_command(command) + + def _exit_gen( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> PQGen[bool]: + if not exc_val and not self.force_rollback: + yield from self._commit_gen() + return False + else: + # try to rollback, but if there are problems (connection in a bad + # state) just warn without clobbering the exception bubbling up. + try: + return (yield from self._rollback_gen(exc_val)) + except OutOfOrderTransactionNesting: + # Clobber an exception happened in the block with the exception + # caused by out-of-order transaction detected, so make the + # behaviour consistent with _commit_gen and to make sure the + # user fixes this condition, which is unrelated from + # operational error that might arise in the block. + raise + except Exception as exc2: + logger.warning("error ignored in rollback of %s: %s", self, exc2) + return False + + def _commit_gen(self) -> PQGen[None]: + ex = self._pop_savepoint("commit") + self._exited = True + if ex: + raise ex + + for command in self._get_commit_commands(): + yield from self._conn._exec_command(command) + + def _rollback_gen(self, exc_val: BaseException | None) -> PQGen[bool]: + if isinstance(exc_val, Rollback): + logger.debug(f"{self._conn}: Explicit rollback from: ", exc_info=True) + + ex = self._pop_savepoint("rollback") + self._exited = True + if ex: + raise ex + + for command in self._get_rollback_commands(): + yield from self._conn._exec_command(command) + + # Also clear the prepared statements cache. + self._conn._prepared.clear() + yield from self._conn._prepared.maintain_gen(self._conn) + + if isinstance(exc_val, Rollback): + if not exc_val.transaction or exc_val.transaction is self: + return True # Swallow the exception + + return False + + def _get_enter_commands(self) -> Iterator[bytes]: + if self._outer_transaction: + yield self._conn._get_tx_start_command() + + if self._savepoint_name: + yield ( + sql.SQL("SAVEPOINT {}") + .format(sql.Identifier(self._savepoint_name)) + .as_bytes(self._conn) + ) + + def _get_commit_commands(self) -> Iterator[bytes]: + if self._savepoint_name and not self._outer_transaction: + yield ( + sql.SQL("RELEASE {}") + .format(sql.Identifier(self._savepoint_name)) + .as_bytes(self._conn) + ) + + if self._outer_transaction: + assert not self._conn._num_transactions + yield b"COMMIT" + + def _get_rollback_commands(self) -> Iterator[bytes]: + if self._savepoint_name and not self._outer_transaction: + yield ( + sql.SQL("ROLLBACK TO {n}") + .format(n=sql.Identifier(self._savepoint_name)) + .as_bytes(self._conn) + ) + yield ( + sql.SQL("RELEASE {n}") + .format(n=sql.Identifier(self._savepoint_name)) + .as_bytes(self._conn) + ) + + if self._outer_transaction: + assert not self._conn._num_transactions + yield b"ROLLBACK" + + def _push_savepoint(self) -> None: + """ + Push the transaction on the connection transactions stack. + + Also set the internal state of the object and verify consistency. + """ + self._outer_transaction = self.pgconn.transaction_status == IDLE + if self._outer_transaction: + # outer transaction: if no name it's only a begin, else + # there will be an additional savepoint + assert not self._conn._num_transactions + else: + # inner transaction: it always has a name + if not self._savepoint_name: + self._savepoint_name = f"_pg3_{self._conn._num_transactions + 1}" + + self._stack_index = self._conn._num_transactions + self._conn._num_transactions += 1 + + def _pop_savepoint(self, action: str) -> Exception | None: + """ + Pop the transaction from the connection transactions stack. + + Also verify the state consistency. + """ + self._conn._num_transactions -= 1 + if self._conn._num_transactions == self._stack_index: + return None + + return OutOfOrderTransactionNesting( + f"transaction {action} at the wrong nesting level: {self}" + ) + + +class Transaction(BaseTransaction["Connection[Any]"]): + """ + Returned by `Connection.transaction()` to handle a transaction block. + """ + + __module__ = "psycopg" + + @property + def connection(self) -> Connection[Any]: + """The connection the object is managing.""" + return self._conn + + def __enter__(self) -> Self: + with self._conn.lock: + self._conn.wait(self._enter_gen()) + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> bool: + if self.pgconn.status == OK: + with self._conn.lock: + return self._conn.wait(self._exit_gen(exc_type, exc_val, exc_tb)) + else: + return False + + +class AsyncTransaction(BaseTransaction["AsyncConnection[Any]"]): + """ + Returned by `AsyncConnection.transaction()` to handle a transaction block. + """ + + __module__ = "psycopg" + + @property + def connection(self) -> AsyncConnection[Any]: + return self._conn + + async def __aenter__(self) -> Self: + async with self._conn.lock: + await self._conn.wait(self._enter_gen()) + return self + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> bool: + if self.pgconn.status == OK: + async with self._conn.lock: + return await self._conn.wait(self._exit_gen(exc_type, exc_val, exc_tb)) + else: + return False diff --git a/backend/.venv/Lib/site-packages/psycopg/types/__init__.py b/backend/.venv/Lib/site-packages/psycopg/types/__init__.py new file mode 100644 index 0000000..bdddf05 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/types/__init__.py @@ -0,0 +1,11 @@ +""" +psycopg types package +""" + +# Copyright (C) 2020 The Psycopg Team + +from .. import _typeinfo + +# Exposed here +TypeInfo = _typeinfo.TypeInfo +TypesRegistry = _typeinfo.TypesRegistry diff --git a/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..77af945f1feb301e415e325d976d86cfce0dd5e9 GIT binary patch literal 367 zcmX@j%ge<81ikULnOlMMV-N=hn4pZ$EQRXW=X0p z)E&h!Q0M7`ou?lkpP83g5+AQuP1BnmJjEsyQnV1+^ mzVa|IN`7Et;1RvfEqjq$wt?e@faG-n^@{@Pjl4yiK(zqLGhk@| literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/array.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/array.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a928f3605c4770ebcf14312e83789b3d92351f6f GIT binary patch literal 21715 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 Mx?fesI~j!iUrmv`umAu6 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/bool.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/bool.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..556238da3ee586e2f9b6bca5adec888daa79f771 GIT binary patch literal 2675 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/datetime.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/datetime.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..680754a20c7eca1acccf3feb4e2d4302e0990776 GIT binary patch literal 37932 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 Le^Tw(Z87~Hgq5fL literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/enum.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/enum.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d65dcfdbb996e2bfb6fad34e51e4d45140bdf553 GIT binary patch literal 11576 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 bfs9{7#xEk{7m?vhk>R^kZ{xSqyX=1eeDlJa literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/hstore.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/hstore.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..695f068154bbd65fb3ae941c028439082953619e GIT binary patch literal 6022 zcmb_gZ%kX)6~E7Z{)1z%4H!ru;RWcx`Qs#Q+N~@hC55JG3F%U@rj9e`;r9$S_Oo-} zGX%$Iq(Y17ItA8rP_G|2 znjXtj1M;8LC2h=aTl89Jo8SpG3tq8B@Ern@g&ZS7?F

    M9*!j!LwbX)&tcqdP~$D zLX)snXqd5uTE$vno6tDJ-Zq8^ag)|SbFSGX#G?wQq`6U9NmG&I1wNzjN<1yO?jvh} zQMd4tl-6nT;C<8zh<1_EG?k&`%%o*ygo<*&qS}vUV=ug&%d@hi)g~MIJ0RJ59h>L^NZq8>+oa{CzJSQtOE{$;M7$>0yNiIz} zQI7H%QQ)GZJe4)hwyv%t-Q3xqp=2)4g~LHEuq)7}wT0zfhkGC^4=~Orv!d1py|h1$ zKX`gz0C<#9k<%EsC@*otA}3{&Np3F;uK*=GGOCn%w4*XScOjcrKpR8TWPD82gupaP zoO$lQX&5kd0WJ5ym+uIGA{jnTWlk0|JmpdT@FW*ar&7GO0+N7Bq7NB#<@|Ug&O&t$ z(qIJ!(~@|O*1*QA_7}Bd62+roCgYqk59)!kKtvK^;J#V}tH8{#A?u_iz^dM(ye#T{ z^}UW7y)+?s-{B-P51c@~;#eSgMrJ0N5%Q)(s46&OaPw!}QqaU#c@?){)p!<}^zJ zYxZDBo}I3J4419UCGFjyBl~~Qaf1er8QoqU{jCKSW+FHa6Tz9NHfK@(&pJ%rDO;W- zaPuot!dF3nYTl;Qn$!dyhl*sb|CBv%Pc&9ELN#AnpI1r1HTVEIq8s9Dc7Lz z4zoaJH$4*qV`>lkwJC>EI)4en+Td7b5-fRQ>iT_>HjXt(0@gv5Y0I(UaQFa#ot@8Q zL`hIx5h_M>s8OwQb{LS2kyX2r9up;5MqRk+?_PhtJ3Nu5V{(R%ieV|C$b0!{G@X?c zK&`z|famZqAB7%5I5;j!T%< z1tFr1mg}m#ia`O;H+U$Sj`B&lCs^V<09wgtn7*AREAHB>CuUD9wlBMP80GhOeGq&% zc(d`&&f>O%%kHO3ET6b{P~7`mt6@_Bykrdk(^7I0QBa2(IcGWCqp}Ek5mAZY9KmFv&!MttjZ_v%0jJ8!Vlt*$)58h6T@yB@GULz+@>ILgtr;3* z#0kW9NYBw0sL;KT<@}qj=Wgs#gbWt%Q%~(mUBg<-j)MIg)>_rN?jruCh2!(bfAjKe zU!k{fVYP1iB7dW9x$cS8hQ@`l`LU(8=Zg(}OWwXu-TpcLt${UT`8$@~t!o}{VRFUW zuuwf;y%_t%`^2ih^*VFosbzm>W$!P%TNig;bDO=}VQ1F26F;}kk?Oj+CkrpFczjnU zW+྾wQyW;aNG|e~N^L5zCRWw31UxKJ9Yn)860yAY(G?y58H-qG|5du^9YcO*FqL=FcNWp!s zOr}xH+s1wf%h{xqz&e2oSdjqkZ10iZT1=>WgHcN0y%|gkRv2|_g%GHgjbLf^j>mA8 zfPTuEcV2Gz-tn9ziNK#{^NvF>9>~Ul8J1NYHpKIp4;vg z)!TB<%iZ;I*Znt{4;{B0cbMC*qW38f;q@&z<{gX7+b&(+)M`CwlQtw~rpYMPB*lhoL9jWbFZy;{pwWsDTy#36ZJ*%~K3%locFL5WA zUOD~eiKQK{6>HBdxzDV5e1)nKQsRnI#2O7LHOvJ3Jcxv+F?$9xTssQabt4)+i&e}9 z;47hFy{%S9Lu`2j&k%_;Jgb3ohj=D$QA!R}*;RRi0o2+A)yk*@ZY)FH;BuFoXOL_p z$)l7IZ?pEtVO|;El#fi!t4Ag;q(xckQ~-NoI4gZ}GRG&W$O{lD!ViMR zJ)8($XKCzs424W`JZK#qjVA>vN*G6?WOE7_SL<^PauD>x0_twtf6kynr_yY=3f)Yd z#EYxTH7&zXc^!YRuHxslMM+)bYIhuOC2W=kryDxzQt1%13h>FJkWG`XIO6uM)-*0PyYty3^l)=ytX;209nmsX8JNAsyA7|5z3RIdJ|d zo^I7bMYn$-2v9({7*^zfpXCp>E`GMBo)G!z&cc ziT*-W6+wkGJjO}kx|Ly=uPqja{l-n0_Ag1*-^jMlNaN?^2cMCa&q>c+ z(xa8Rwd%&gsjH#c(4wnY-9GJF@oX*7tGU_SVpq}AKJ6~GuUod**!3o2b6k1p@=Fhz zYicahuJtzJ-!pA5R29kYhxS%x=iJX968JsrWBg3*+>wU_eh>GzFi)?)0I%4NuPrX7 O>46nWUtvi*0sjUu`gFqp literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/json.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/json.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..16c462dfa49cc5b1960fdb775b6aaace78f130d0 GIT binary patch literal 10964 zcmd5?T~HiXcD_B+J+Yzjlf~vJEY^|ymmGj_-JoqJ5$y=(Dhhc?_*)ANbYLf@QVMAh3M^FjPr>ZPrO{1IQQ$ICOq+LDWqS@J4T zNQ@|g;z|n{SIi|~-ko;G+>nZCF(bvKj3?#+zNC246&Y{L%kmYF_r-iH?}fZS7GQZ_ zI+&@9RkFN4y(trlg)&vKs!VmPI#Uy?$%JEJRu)M6Gm%(?<%8+kOkJ!lQy;4ri0VSiT$6!NM^sT>eg$t-DPB~@7BBgz3EQ2wVJRI2Yvu`L_8hm;!N zHmP;Wb4vKG_z7PK659%#=aqxZBk2Hn){=n}I7kxNVHv0^IEm?heLn1#X*z+s?Qs0oGZajk;puC_w3!~US;*K5}ZS)^k z5<|L5HMu`W<@1*>b<6t5kg9d~zrv2Af)Pk$vpGGXr*c`XJL)pr$Fn1b_hcfSPV}YK zuW;8v%AM#-LL$X;DMf>fN2N4JS?+X>W)gZ-GCU`S`}rvEc`cX4 z*0s~a*(45`v#=wZl{6I<=SMv70~Hn4x&<`yF<~M&Ms!w$Bo18uj0j`GplH1n({Y!M zZLmi-A%l=X1}heyr~Tz6gQZgV29ldB?o-<=Ct0@50dd?t=I$al_7lQ-1X0(t*gk&FmYSK=~sHr!=Nha=*D#vYwMQJx5KUT;HIY)HOMkWfc|BguaBPcKBI)M}`tKk&zYL z>LcP;0!1H*!* z*dTgaSckoKKOOS9ei^Jo)`rw%sz0SFdzo-bXANTS1L<5J*vg1=EOrmQZw+Z9$=uLD z$H`na3-bky?Ulh09Rj|^Dm%be6b7iV5%vwI(mE_z?;sdL z2On*Rd@VODClgsY_Xb#HN>SP1Qm`X@Y6)3Mp<$|7oi~?G_0a?!!GV|}$zj-l2sEAoa59yIuVQyJU zu%OQf#|KnBo*bq)YgQYY3C1&tTdMUIqUu0O18g)IQLiEKZYsxn0nL6z`An~cYA2W*aT}9#}~dHbQkoB zW7KAVOpw(!;tfr_z3L&`THgnb0oVl0}ZeR6DRsKnFElA|HsY{b*re9kLx6j}CwEna9 zN8#g>T`RRM^KA>#quP$i(}iGUIoP%sY@5Hj(EoYx(AO1EX$=NNO3+vW21Db2g3SMp z#)?a~(YW6QZ#D|Uo4bgb?9E2weixviYs>{GxX(mE_qeE6LU-%|94lg-1c+~=t0e*0 zZewPVH|7THH2n(TUnj#qG4Tbs4`w7K_y^dfq3K#mjYih5>dBkj`Yhz@r@0I>t@7BH zMxVy953?n$ZNNTL)QNq}X#)Bo2L535W9>W@{cPw1g!!@14@dGe^y8!b@z4)Vx!VxY z+zbh6U({#9(gheEgC#Zw!+#!1OZo?ao<4VTkhF{YYRM&2& z^qYo=$QyOD^`$aM8X`(*I1+1p={9&_M1jm2uI>bR90=VzHg#;Gs{omor(T{rycB3F zRM*dm({D_^Jt?jPLet{3K0Pq+UD%Ot-v21@OkRBE|I6agBRHiFBrgK77T^#vnC6ts z{{XU)q%rdoBy5u*V?XBB32UgevqU8^0RnB8B0yjbfwba=P*hYZ6cK_JX~YFyILKW8 zResWV2oVV&CfkDUq*D(Nj^SNclUc)K!WfA|jz75jj>A29D0I^GAkzt#cF|7W+0-)2e_>kV3d_QheWAsBN4SKk)O3+u;OA*v@VNUS^4I zmw}#}t^^9~$I|9;!J)&pjw`|~7(R`R!Qv^dM)GR{POzx!wjA)qkHv9Vi$U9A+Fg)A zJAf(jpawWXpq`IKu#bxFukcjyRV$EDkKEDGA@3TkkdrsTsYMN8mmx$U)Dx*XMA;e| z?zEaUeDQcPozS#+oMH?bb^DJHy8>i_tc1eTU9)Fr z&c62+TFs_O{k<2a=`UX@)HTi>m^(3@n!Y~od7v#E{O!p6txxOo;TI;m3N>}J9Wx!v zHPOYIXuf*)Ld!ze!gHTi=R*hb-UDop=ox4|Dslx7A%b*f9?7Zw0VgNcl769wQ%s#R1N^ibp}PGjp((9H!-L5AevA93fl_ zB}3ANA$;J9@)uB(4T)(as3@}`cQS3deJt0o4e&n`T$ND4Mk9_;$p)%>P_otv>~&ay7D}*7&}}(u73j|LS0{G_ zEhwN@x91IwnGbk%q1-Bs3t70JDPO}y0M%`z8+SVp)e#WbqpBKn4+gCMim7$md6|s4 zFPr<|G5jewvV;4FIF;L{3^h1Lyb3wE@5&}~ifV33(R&yop5CopF^^p$28E+l&TT=? zhtQCPZGqb9JM2nf4-p{e-J7vqB`lgr9~dsqcP4Aarfn@jL%-{1d11!L5(P-Tw`cxaV81Pm1sf zVucc@upzMxN{W#9B$&W!D}G)_tXFBbiRTWWL?3B*@v1a_>0B3_K2i$9GzXAnL4+dt zJNRj+WPqFg(7leSj(1LSIV>$dP{gRG4^;J(i%nx*HUUSFVNJugajP&Urj1B&Whl;y z=8)jof8&HG@{s%%ep&CvX$W zjv1kuB3Xc+V-q^3I;~B>(vqRNfdP-O_6ks^V|kLkJZT#g7jrSf-C)eeT#FxL3w|5j z$HO~5xsrefyN92!_AF$c{~XJ#(UhaW|DO!^9eNFD*Faqik;xE(^m z$KiUe<0HBp5Sj4nV-8HAV9GSkMgQyA4VRJ3DdmTTzl4z9vBU zAh1Ts9wVB;^CKM|;93ce;Yd1wBu#~aEFsu2+ua_>JZX3T4-XGq2iO@CH=9Ro7^zt* z!7RN6i^?d2idVD|nXsj44 z@YZ%>4y73R7s#yPE`bS(UM_)!Ke)eVK)9RU1-jAKU7+s)v*j3z?hj4tG!nQpaDy;=#)RU{xpf!@ zQ?yO4XlU%3pu(zGOp6lW)WmLzbNvdHYqWhhdn=o}os|diPE+n<_ni1?8NP@dk>A9# z@b&#S#$k?CAkOTUzJ)nv4{t-xX|{9%7$pwLVY|yHd=|(A`2$>;by{wH?tmQb zX=Jih)+SaHx&YO#&%?6~Ws4 z-$9bDYj9e)P42j_k=ufK-C_9gdziw`yoR6}Rj<(80DNN2z%4ub0&i5s%}edEXIN`dx=^o%xMAc{|S3o=p@~bL}IgG5>l@U8EvIu}4L>_Zq%)203 zGgAe}*MfQM%!xe4=Hka+{=q$NeOjh7Ap14SW4sR6yrH_~Q1fD_dE)GFL^Zr?rA{+K- z)y4}7#}J<}D&lb^m&ETg@p%6*+{D72D@8+Ps$zIxJb+^CG)B?O8HA!!;~}pPa~~kr zHS{_~b1@{g)%+ZXmPRX)p#4xbWOQB7X)>1?O6U}=g8laqzcL)eSGJzJFn1UUUS6=z zApGhG-8NTHvIBx4G>!5JCeqx|;yCHfJF0ICt~ z-+=;@3c@!ommvOEkO-}RB!Mr9{GX)e3ljN)G=4$qza+;$C&#}a+rA|2kDGTcgcqcR z@%*l%i_ORKq=N90%m*jpDupM^`=p!_F<)55B|O?a*lXyWP4mst8(@~uh0UwuU| zg|-PtnGmKZ1Su1OboIPITovEAMB&*rH{@0^x4P+1dEagd2nW9=K-QZCAv}3>oj|hg z#ry>`Un4}O+t&#s>$?SE^Yj+vZ(jGhAphn%fn?n;2#wQwkl(oO^$87gfpr4OdPAik zV_itrWkK-qx;|{*$K_dm3$`N&a4+u@WL{TZZSV;D3Y#{sx-pg8c-rwCOCL+MYZCBR zBgEsMJdED}^Wv8L)_n!Z2e0sLFfVSNJ5rGRlV|T;n!1!1oATQ_`Rm20i+Qne?mT>C Zy(qZyq$*!?ZjDHSYrQHcyud8~e*jGu|(K4VDWwu!~!5efCRyZNQwlXAi)PH5_|yCQ7h?I%bfuUa(6+^ z4oCtA+SFOj0hTT#b+QTGNku3p=fILG;>A}!rJTgNoGa%_oMcyk4$y`w@nT&Zm8%l! z07r^kW#{{Qp8EiSGq3ES(9`q({rLOu?*IS$@9x!q&d+yqc)lIj+5gKY7ro=CnwKjQIw@a+_H!UYkp-^=1I#0&j}ES`&ak-wP5-H4a?OISQFTpB6!m$A4f zTpp?LS41lPm60lcRixTq9jWoxFkF6kS)|rq8(HpO9;x%!F<3#kFyiz3BK7`y_U#Qf zL>m2#EM6F15n1V98ENu2vG1brsz|fHInv^9!FRD(5?&oy<6jeL^|waW`qxI<{A~NkA*|>w8SpE_xR!Gfn+f`orH!)}>pjA?? zv_@*J0)qaG6q{L!YNV)@6a9bH}IdFBr2`TxuF`N&$df@U?aP17& z09+$*o)p}6hFbyL$_(5NhHCBX|K5cZC*>ek9}`2zB}3XM&o-wE9)_owJD>l1G$`d zE|=5)iRZ;FFFE`NrA9FW>7&EzYF9BRZ7KIVeRXxj&S2bt#e@JRO#j-lKyGMS7$c2Bm07O1cIvN^*E0C?@lJ zpFX}nu`~0fkC`MEcC8R%(yE5JqK=z(Bu9wK^qP9*`;Kx-bw^ z&d3sj9vF}#L8Zl!^mGvA`v#(lbXiF{_YU^;NpjNJIT*Qscdq(=LK;dsP7F%&P>Vh3 zJt>6-AS^|b?!l-YCwMP7+ZF8_K--DOC#5s}F-0EwjKocgkaV0R{wMj~q?b4pVBHa5 z%_y<}PWMNHD%~R5l#pUWRI^Rw{dUnN+F$2&QI`4^b4Iy7UKCy`@C%Ydbcqg&D07Orq7y?7X)g1AR}a_X zP8J+B#u_nWc+JsZG>CE6j}PiYQ05Ds9vD=7!SrF-mgMeW+{w}z8l)kOW{$+S6MuN~ zbB7T5ef}n=;H^GmIV0S+VQP%N+6KTRl5hHGMN_}JWT}A5N&ZKg_soXOA66oL`vETpBt3r;1FTu zbtp}KjDk%FlDUCEC>)H%0)dzd-#+!Z`qgv$+Mm5NAfJz6_(;!2&ndCB!BA*mFsk%N z&#Vm%$kMZ?G03E-_-xxnDSGkQBmJkJjrA+iS{iTQX6)Guv7ykwg){4ju-H0tez#p1 zk~gBR;fmCLXwzHP2xM$Ef-kRf^QByF!B|ehRXJWd9-HX8dnxX!oObP=t!fw*UMZNZ zX&MzibXCqFH5W42h!3z^?T-J5$W5^R9Ny{AIcp9LDe~t5mCF<=fj#G_YttUlrt9Eu z@=C6bJjZNK{Y!m|c0J{}{8S8mjd16@S)jb0=N&>aAKAaJ*Qd0hPiS=bI(mHcZUqQ~gFf-1 zFC<`NhCs&PX?4@^U`gBCwK>q(KA+r9S-gQWl7h+EHxPiXk%xwtr;qPc{03x-J&oWhcR$a2ZQIzknY_kCUgJdH z2YIdcic4mSS0;*A&K4e;v)f7v9&on&f_W!bSaR*s*rf-yoP1%V&KM^<9&j-raR)SG;Ch!qq;zd!H3Cvu1l@&GvZB_77Y;7~@(zGL?|D zLq*Duvsiyrk+&iyAEkha(jydO@|3|ys4{GeAn!+fxFl8OJp()CxujE;ltDQvS0Duv z9;Qt76m%m<3f%)ysU??0JxxxCdUqfY84w4<6!!!$ynljRXf zIXfWA2dKa&sK9(p$cLnGI1sqQ%i92rk<#D8hOWwZ;=Yd%B7!ep;yw~KKPcoXt3S{8 zI9A;+D0<+)`+<`~EQew)uC(GoF2y`taoGb(^`L-YUWyfR}C} zJ7Nzg_Jz;x=;RrfS=}MjXgr$w#Q7gJFDe?eWF6LPwR+B@l6Ftb6C;G&E zygkTWfOo!FFM9DVz`GD{FWyCX7vf!vcM;wtcoz?qwlpN&=C~amIX;9Qi$a24fH5gW zRSTDy#X+kGX97=^h9n}}+)N&~LsADLKIq;^tlg&@y1s!vA4?kZDFZNV`j!4*xIYHD zdKRkU^f_2yZ7h3=e4yFN*yt;q~sU!@u{GFe5K?E+{} zlJ-dO0;DReRoJQ2lw^)7;;-Mu^I$dxqGYDytD7FFtdJ7 zV*Q@?S5CDanp)L0Dtz0MDGH6Io<&Y;Q%87H{OOH~)tlyk$Saxyi7Yz3x#!4yN_)P? zy&2_=THx188v~)GEEIbYSKIk1cp<`iV8eMsaGPn%FPy+ z-)y_lHdEY^C~k=tt)8r(?0omgog?uz+uz#|_wJ0lc4oGcdY-kCSPR!7+=l0@TmY0F zbGj(R7xtiyS(KqZ!t`+jZrIa28a1(ztPRd1$1-c82C6NEv`OiVEZRz5 zkHJZWr9C5tHiF+_krdgb)d)|9|B%Hn7_lja=F??aEKkYPs}>CniG{MU0A677*z^*v z*x)J2Dlc^kNR!rtf>CYR8;kXyf!8KVW)SoIwd7dl5(#T{B$E7=NfM}{^w;a881lu= zBYpKVxW$)yejtDK@Z8w$%2 zSxC{2@H=%0-NLI)PZyRXokb~}RXQ8+-=-$hiWt(_Q>eBj;i=0UpoTd`?z@GkI!E&% z?SWHlk)fy$3f^duowX?GgmEOv3Nv%E%(oX&({PbR6ROF-32>|)0h;9UT=R^1W?VH1 z7dmHR(@f)IiN?q7?w@LG|IoEPllR6nd(E1geF%@~!G=Z|iJH<*c{l+Q`_* z_~7j;x2`0-t#McDLt09NEZS11Y3B5hXvt#epv_sJ=P{Z!?RQ7he$?n>0sJyukqcod zg5{7Tsw4P!fJtwA7_QK?wiDmy#UT-&K9hHC; z5t)@=6?bXc;2E~AdZzce=U`)nC^@M|=585wt2lDZARnz>n1zjmWIL$F7(u^s>4j)0 zxa7nASeY?ozA0x=jh5o8Ja~+JBR(_TaHU=dz^PfZy2*{y;|nodro@3;CT2W`!;H9r;ONr}njTP7oZA z&3Sl7y_RmDhS|r`VadyK9eW_S9nG_4z6W-Cw;W*a`?>jZ4t&p5@(v$Wwqwp|cdVT& zusd4kK+9VCY$dAJvI)T?IgLBx;nf&F=Rw5uat-ltFc)-1l}+a0=!PwO9I0fJ&up5Q zd||VIf(iW1Q7^s3%?d8HYJ&e-Rd2OaEq@oe)4Smff>H1mMZQM?qlG|AuBoVdFhZNP zi&b`;il<$3ht&> zN1!EFS7ubF3@=vUA5uLO{3x|T0;NclrcH-bpo_Nm?6J~eGY5o*}nI5pSX z*&K1ONZgjXw5YyfMLC9LqIos2df0$es#o2OJu0??jg9|mK$AJNw-&hYf=v8@cby$o z2&kJyko@G4k~>*KY!cD-nCft+CSv({Rh4BVC5LOX@x^d#{u?BTtw-=BtQc3mx(!+~ zerDR$G~2Qk`=8!>wJT?8*CuM$PKxiIzjJ=7ww<;^t5qdzWiQDD#$G1`&qC(8>GvGu zWe=E!Oz96Z@2Ir2$Ml3=v5(ka?96Ti;yhBugB|hg-9v^0o-0CjN=AgN8>)7!aptt-M zpFYP10kbKRwwTDg1?XhW%OL*{*@l;8?Paa3e~%O~(vj*m;MTFNueT@iR+7tR>y53W z$L_;g|E;m#8V^l*vE@CR=Z)vp%odg1th`YVX)T4(QuWe zG^gl@u_bQ$4hA{->)FRa_Fh&Bz%urnE7W7=TOR>e1f@iWE-;E7KK2|V!iXba2oI&) zD9sTd&CQ+>2jhd0N{4e?cG}GmdPT6MxC%{?lx^;1=a13WG+Hq~DoslCnArka&&aJx zjgA?yE6en_UZ%VZb=K)n^R4*wxIu9yKeFV@PSZkVs57+4oT2i+LbdW~3dl^B-=%=5 zPbQZIIt-O8OxH8=9ZE*+WZSs%^AtORAX&mDe8e~o#7@W%6JUTdDgLi1>0Sy#6#Nl_ zq*Ij$G13`qrfUwxoWTocWSrJoV7hDA|AbsI4njC%x{p4QG1W(RKn#pNLC&Va>%zBPmU{I*fsY*Ec?rPsypRF8MwK6LAl zTGCX}x>4usvgM=BX;;;3UjDT$V_RN(=7T)nTmHMkk3!Qc+wWJ^&QxtkRBiZC^HkM# zs^fu+D=Z()f8gM%m#e6|4L@%BVbfF<=y~PveQ()lzAAwV0`Z;P zb6X();S0<*8(u8P4iDi7H|C=)o0Iw~|H|s@7&Vu`kpVuu*R6J}&v%k-)cbG{Op2VA z)V@M@=IY!zUwW!7bjqBm%S=EH0 zll~Xd#I_;0%FVg3<38Fk>n)_iAaQTQY(?eGOE)gPTA+av7SMxS+Mah~+b)ykhR}Z% z;3I>ZnvXuu5y{9d~Qds zqx6e%hhu}v6-rLB+IUE+;Nj;;8JY`icB)iR7cfJ17<7LO^l+4oHg$QD^;oiY=Asve zC{#7zqdf>sw$n)q9NqE7a5S{PuRo-n;1K)i1Tg%V>VXV)WG~CviyRODp}@~=QcZMT z^B?0Y{jnI^m`g8ifRfglX-%1Z3kYeA)sC53SNPdhPgm?wr(zg4S8y2j3=gB6#B&?O zGt7=`W{%?3OUDscyI%g=T5I4$&6>+REy;7QtQR;@7!gFr4iqIi&lTw%uFO#_-(X=Y3$J|k_juR{!Js5*Yq1@eX)jQB$}PYook7U!s3@V ztef_%*Fe{m4?WAEilGFY9Lx#(=-#oMS#L2(lyUpZSK_W^j4|DJ(x>)tzIu3F7bA}J z>CD`H#EWzf5ltpGqyCoI<3T`F6Vjhc50bBq?YMp?4atC$C!S5Y5FO~ zw6IRJD^5%>W9?%!kIPzvQ!hFF&8BIVQbvp%n5LbWru?}wvkpC$GC6UQeLD~>dD*5P zn=x$m$+W8}U!(x*6Hfjw6oe5#c^meVYK^mj_g@K5laO8C2*yZ?lCH<2npTu*xW?3c z*5ScsWChL0-$yF!2WDGqFKsSst zP%2`!%7FyMC@7_t(rOvr;rxrJzjpIgeJ$o6KW-*+!RWv$(KuHA%ErbGpFH z=GYW5GxYJ4dKA<=9%HU{sz3-?BJ^N|#EVYmpn-kYgPPz}T79zihRfo*a_G5I`P|5vF0B=uT+Uk#W@arjS1;$A{3Y(P z{b}wJ-{S6;X%G%K;-(?__$ASLD-2sbGTn*tUFuiP`s4_j7pcW#=yY{-$Dsv5*-Uy z=w@X<4o5}Lw0Loipr^OvWN)CWyI0;#gyv#fET|qQcAOqkuo8BPQfL5Ti#A#16%?$b zAV~qKVq8k-*?*i$Kx}_^CoAhBA?%^Ea?;&JXFyqry3ssESxHML?YJ(fs%kr^%P^Wh zLK>^ltVueOmg`7ztVcjbbIEmOyyM2Dw^n~pLDyt%uDP-1fsHRJy;q7;%;WL|Ki>SE zV>6|z6Q!#sx7^(}Rk|}?vg?7JFWSS;+3j?b#*UjbZq8fvdeKLY__oEru&9_ ze8X$`_sgrtAG^_i-HuXTZ+><6Y)##SeIoc~&P49`?(3birORf^DqlbJYT#Z)_4uam z3{C8ttbg<12Ni2(>l()0pDwSveg4+@*=0v?(z>o1mwl?L=UrUQvfFEJt(mRv__N0M zLqBbPzdBw?32Mrbpsf5$q$sTZ6~}`>jS=zX2d9b;#XX16UO>N!k?r=A#*W&3k8?le zw@~L+F*j*;ODl2xYTn?IEqLU8ILOcui$w36}u^A%ri_R z$P8I5SfsvjfD&up1I+kFE$TxOGOc_kq@Qg#AL(%EGnxmsKn1shDOfGZzWx$Y@M^%vJX{`4KvBFQ_u_GqOj9n=Il+k#WC} zq!bfe{ZWf3Y;nuv@i#?B(!rc_stMmjC?-ZoS}^e={}04;vz|s{(itVET}=Lrk}#RU z_a~h=7JNoIn`zlIfstX^Tf|0y#^-lY7HlINzU-W+pTc(8iA2#Vc(iGr-z%upWx&0n z^6MA>pmwz5URm9QFcF$6TRpiUQMMNTbC37>hOtAV`!rj9x`G5j=ywg_bf=g_)U|A)gxN$H;c#l#7|hmF zyBLgyB1RtVF;zSn4rEegQ>am|VmOac#`Zl0tEtudC1Zd_B3D zpI5K`vZc4)xPHZVCOmLD7!D6;rKQ7Dm1QuM2)#^z5}q(^gCXe{7a+B;H58(Hk~HvGOpJllR*yZ(SB?}+Xorm z5~b^aeFI=t49r6RY22b)XfZM=&CLq)I{EHyi1#4oi+&v!E89QCr%cW#+)0fD&r57! z3-}g-Zz8x?A7wg<)|S|HWvSI4h|n;wJZKdwvn3}L46(0{50X>FShgfimKY_PRLbOJ z93c7k&k?!GeZCsorS}Rd;+4mz3QojbC*b#V&#u+K+J`+g7Jh1@^f5m9WGNHeA(WokQJVJxDEo0RRiW zOKc>^_f_swSjC%ew%=&~&W`JC6V7tw^N-vgr|31BO|Bp}<+@{8@MT9jDR{yp3vG$jDjJA#A-1W-o=3Vhsd*0s}Klx;Q z?^7_dJx-X}4yW2gC?~J=4;cj?Qy|BdaA)t)sA4o`?5&oU$#MccGR0NKVN}!I{&2DjdwZ5ZG=3WoKgfdM zPw;2uxi8`N={zU=Be$T&Xo2-O?Zewp+}qRZUqUOYsTCCbDMd`y6X=l%uTB*&)=iFX z8NXwgv4~$zFbe*hA|^Ei`i)Rykrt`cAWjkdn4>0|2=vGVRj1DERBG@8kr~viAQ%PH6fxODphu>r&KUFNtW6~ee$xz+ zng~Y0EJZ3QU^`9(dSsI74U(+WFqJ6$C}svx%><+19z{$(5$KVLO4Hz~4YH61caa8X zdYcU4^wG7N$fMvd@i&);6wuqn74&liFFv92k+8oJk}dOaagw(#NHV!#WeWa^B5NsN z{Y{`prZZDlKb+J&=<59^yY?+e?PEkA1%Hh{U1Jni%oH~!iW_wn6aJA&Pt(#5r`ttZ zdO@PeV<}Vce<)(Im_UzAXExpZaANa&yN>S1hQZO}3sSs;2&G_-{xtiO*i64%rL&pv zk4(O)n4xQpQ)~}!fY)e1uYbWNbWjs0_#&+ds}jYl^d=Dgk(-cJMQbgP*AN+LI_Lnw zDEK>ynB##!zY%IIqCu6dIyJP_l1|Mbf>B_D^U6XEfgYKfg;cao5FLq2C+IN2C~y)% zTj+~PBmzA$L0MI_PR%x|E3LDR5R3wMDtid@$kZ&XqIHsXW+ADYU=$P(NxSKbF^E8q zOp>XhtrIeJ811Dh)A)3pU=$P+QJwU~h$2u3f5syqW~W8AfCHur9ZkN%!|#k#>5u6r zG5yc__6hl`7s+EB7+Exrafrm+$X_&1fljSr_^21nV{F=(8}p0iDL3jd?tv_tr`pIv z$8FiOXdXJT#U90{MYu)tn0#wkavqa!1UCFe2u zMth;`NomhI9csSu+hgnXuSL_^l#NSHYgfolWzVAJ3JN(9mzLI{Y+Z6%r_#RUw7f!R z&)Bmly*6dnlGECiJxfk2D0`Qj)}eGRIjvJUkeL<-&T_hw1^7LIO{V9YeQ&jV=SK%4 zmd^t0(n^+Zj}o(d6(})f*!*r;!94mFr@g3NePm}r*df9{23_(k3Yh2d4T`x)gx{u^ zhhlG1jCq;9Pci1Y`9q2^_XqPju*E)GV6$~?6J=|r;7dwJ3m>-7VD>w+hnb1Vj5KBr zF)M^=ex`7lieoATKi^>NA6VVn$tq*lK$QA|Fdx+`yV!k_pGI}%P(`s15up>H<=7fX zc9rlx!rp}e)3t5W>km!~mQvI6OxLcT-uT3{ zaKtEOx_0CAreo8>aRc%?GG&yK0$>##off(m&ciA?F)f@llCX-NoEDxkAo1F@)9dz4 z3!M*vj0dLM_D>7u9!X}VanO5US~!?m%He6@iBw3}v~c(#5UMGKGpweROjOg6Y2j#U zDaSt)PN?<;JKX40Hsw3s66zito7y=wwBFU!yz#i?9nD<$RYiK9(nWJe-4|a{_ zxrgPePs?YukhI)_N(*gBTWATfAJd?pe(f8?kHzA*PGmB4k~uh`ML&8klYx|UqIm50 zslUuYTT3z>QI*MnQGauT6s_!`fZPl+?S8OdIA$9SG8rK1Sq!$1XTzO#(wIqm@N`IK z1eH<>Im|PC+9Dq~6tYXQZ^%dl;mO)$19BC|%#w44lUA3dp2#)jL~ER2`*H zCZ(8wVzTK?f-#B2gwYS^lSwls*M3f)A0xn>4q23cNuR%<;D1uUc9s5?Vr-j?c9K;2 z$3!2KdQ9LkS+@i+_XrY>iK{e|I_cV>{y6Y1S%M71fB1z<3>6#!zUztKH(5A{+KKMn5+JntH6JsaC<)F_I$$aN^rYA;aWbXl&e4C*8LT?dy3l) zY=YbK3wz90BHW%Z1Oq?w_#V z2+VVc&bzXFkGm%xPgJf+NgyQ3R+@nE)f1-@)om8Q;fc$MW$QJ-9-iMYzI&dd_xu4{ zIbR#EKyi4_Z}j4$cEdb}_xuV6-^-8ho;-NBp6p0epnQCMev-#w zozd9KTd%r4$}hZL^75&x?vL^cRLH!u5b0|-+^tX4Zkp%t@t~P&$Em^<{JL3prTT8% z!ru2CxpNM{A3TNsRZh;Yz=~cRJVX?y6cNP%e}dY1rv^l9zMSV9<28&Ijl`^!kB0bi z#)F0oOnuzPm{G4{8a5JV8t03tfcnSP4_2DxqanVcoiJKy7EFD-X$N7n(wcXv1rz`R z+9vlUYRt+qAuB-TL;_w0#!lazY2B^9y)ZFukT#EN}XvQ`(;2#NZgmb#jDymuG%+(tDth9n)TF8172Ala-N5hF2s!NpHlq*o`Y9()^PV&k1lK&(uMXHK4uv&oCsw2Btt%lV+ zVxv?GoOODwNvelhgI;Tvc0sLCueC@`P;1s}yQLPW?bd61q&-k;)oZO%8`SpdwKgdT zwS9VRuhb5;{j4TLf>K9hpL8J7E**^QcaT?z)Om|Yhwj79VTp7wS_o)ea@BoarygL` zZlLy9s0SIf7pQ#}YA2)i1NE@nX^wD+QJ(|q5eqfMs7HZ1Aa}|g_XT~vE=GSI=!2G# zyBYNuP+yP(7VaKKKMwR0a*sJS+tLpHaUB)R!#O!_v#r&@CbI z+^i=woNe_CN#b-yrb=)!O@k>p^In=>3ub1gWu?#a1Xmv7RIivyr88nCo=zzthw2^{ z6A5u5A*=oi@0=Tr4!=4&{MvZXr^xChPF%PMjg>*ZE4V7?ezud$zH-fXah)2KZ`wSE#rkOL5df3xUz zfZMDG(rqG>2nW{GA@LFin!wLGLV{WqJu7Bs#|?ptab|Bqus;kBwwU$Lm`%C;x&$_r=8|p^EVKv~dKUgdt}tcl!_yiV zp4K9$0}yghTs3Xb@Lh;EYIqak&4_zgC$-X)fMWk*Z)*0X#h#ohC~{&_!PgCbeR252 zB{TraG$_iY)Ko_46=SjVOezykUFnUbseEZdj9rsc(xtxZa_ah}v+;>bN<1U?LWgVO z6q5jCGoXw0uu>?Npev+Gec9V5KgCLI8Apnni7+8G^%={ z`lNvSqS5cnhzYHQ?uWk1gm%D#wj*dWKnM_}0>CX&a8x>9)OfJDyjb->OHr(3e##95 zTZuSzadRe33i)?rTAM`Es<%SCa=iH|;Bg_BWq4;&n^2az5+6OD8{RoZ# zu$}?ifNX8a=mLhk1gppcrojl02in;ru!^ndK}@c77ExW^QavFsjW^h6PyLgWMj zrVL0b*;8HSxJ_)?SdFX4kCZc`-v9`?$!97J z`Wz1OdmYvMXXhvZirhwxU zlkvo?DqNLCNpS)xh($BFsQB5YGCRwp{|vM$c%C`3QB!}r<%ccvu8sBsKkxpy`$5fT z?MHsn`f1g?>tUdNadIiP-qyd;*8ia9li^>xe)U?u;ic8U(7dn_s9T&|xS4nF(KINe z+ba~$q6UE#vstNf7HJgwAi($9G`xf0Y}KR+Tb@~}8ceghvt0cWCiv6K)szpWwH1&x zH2AFSBy02)U<nUrYO-ju=N~(vI5gmcGH;1yoG&U z1@JT?bLZNJ*VfyPuCyI}@aCudugCt`n{OCd4UBFT8;VYdo=4DypaVfWf{O-t6OjuD zSR>L)q(J}z6mApUz~5MmsKiBhyt>bmNx0nK@<#;8CGilJ0_6r5ah(SPuU3!4E?Gq+ zdu}wIxhm73mSlJPdErc%%%l?j(i{Vc#eakH!LTaBU3=L7b76S5SRJCWnOhE zGkD>H04<)1XQELShJjx0gU%`+ODJkZOuHtkmCK&w(m)w zF(fu`Vzl-L2wdF$g^Cq-(^B2il{NRl4YzOIy?e#I`!{Y)Z_C^8|AEebL|x-DrUlQK z`ZZ~8Cv5~9U&ez@q2sren?lM5+<0BEm778a?+mPf*APH!@!p`-%XtXroYU|Sn%4Tt zX)WAim3T_Yh^d%txlw!@#-;Bd2qQq%W@;RA**pSen!-4lwxXAVlZ9gO31AmX<(+9a zDwJ{s!1mhhZCH$b^!hJO<#!)n^Pbpf+I`3Sp?AHhccrO!Vf<0k?)9e7N>gZl{4w(! z@q0DD7=GZo4?g3C)xhyB%FpB${%w)z%5Hn#E#tOttUIS+_lc{G06>^%-;KxFIn4)8Of=3W?s{s&DbX!JB zr<|&2TEIkodym#sX7iZDD=?XYUXw}udQHblO~-mo_exFoHlfg+cFr-gsd%<0RxQ zkw*P!xy^QHDe;VupkZE-1Fr}ectZiap`g~6W)HN~;h)5R(aW$#-C1dSg0?`@O?(fq zVpbPrOLJ%oHQm&oV^`b?Eo8vJ0EWh$R(bH^%*;?UcOj?!oS2bFI22Sd z2tdFcNgthA^L9S0Yg(%R(TnpVkGz4!frXO~>-OFie(wF)`;Y$By1u-x?{Qu0l7vy| zPm`;4J$YXbJ1xBS&%sa>V+PHOTm=lMok%!@AcWv1f-VFd2-*=`H$V;$1veK{S{2S- zjR%{{3qlXH6b0d_Qd*WEbvrTnPd2hOr}gw=G6#Z!HU@oyHU_kygAfv%B=Z zIY-eOFpAeAD!fI2P)S$;KjDBV3}pk#c>*JtQJ6jg=4M%$vyOl{GM!pF!m<#iXc(F6 z(5~AaCUbNasjnk=4S-rTe(vHx^xRvcW8>dGI~vxKw!4g$K}!q9bSwc30)00q(I7LNTm z`I&eBMxf!Nw$B2c4;$O>4z4zK<*U0MH+I~eyf>LY@ce4yV7_|r(atQIjMKk>RV;7G zWZC>tISEHqqX@nS|B9X{G%`O0A>cfwi8`{B7xnFI-Y}#mw-aWx!Qa&8J-e;bVo|4E zf>8V@+Ixy;X*EyGCS(J}w_wNqF>)OQQ1;j#2bz~U?sR|H{nOsnz@fbRkaj{_tq@B? zzK_$|jLzR84Z&UbH;s$>O4 z@9kf$JDm3&er&62vO)h2mp+fcCJJa_D1v+Nzg0WEhD;z!$tO2_KOUnBH$b?GlPMtB z%T0(H%6$ltxMCvJh&(t<$--Fn0+#@sitz+kym&IUS}~Kvg5d}XW%78M_w|n>CO!afJA73Y{LL35LRfvHR z4*6BLsQ;Km4N&=BODsQjliz;z}}U>-rTDjf^S{evm)%t zw+?)gUK7T)BMg2TSQD&Wwh#tBNv;VaC1cnLYlGu!!Wk>e7Run-3$L#UVGGYz%D|Rh zcFNL)wf#regaLDyrHem{tO*D?Jait(JvixV-5qp41IP};@Di~N|R zfoxbTot%bGei)e3Ac88S2cl8S?~q`=05-8G1oil7fAV1Y0C5Yu{S^Yt7F%R=2&OUuqpOdyPNY@JK`kd_jH@^B`h5APgBe{zC=2bGX(Re0TIe&bWoY^pGU%JSlo}4G| z>sTe-8{PdmU%u+lD(Tg*m!-85Eis+;2nw)>5rZ!i# zQB#MYK3DaX%fr3+I|884B5?Z_Ckq4~g(}3yblkx;BOM+EkCSU%>Msy@6si$_L&xj5 z*2VYlRTT&zg&sGw94ruc6n61k+tT3O(**)Z!RO|B^EC&sskgAJmOGYj>@E;^7P_2V Vh_%48P+bKTY=LK?9h#Z+{x2byZTGXajX5H2GV5tkHA-l;ret9P z4ng)RcpLESC9MC6mnh=4mdhhq%`(x4kR5z#|@>cu6$55U)%(qYrpCHbQAOkcxF>CHA97=o-^zC95iFGE>M(KZ4vy z>^7^`|E8>r_|`Nb27ECYizfK69t?znsNkcz91E4V@3kC*f#{q8pAkV43dJ~_CNB56 z1L=4?;4Ym0#EUykg!i`hOiv;P)Rl&1ESKeYB#dC(zQHoh3d6V*x_aBN0*$4pKm+D0 z@m1EZLHmqB+q;fyX#|?JL~EW^tS?xt1!qOY^zq2PBXxn5@7s`kQ2|y#5K8#y{1p&p z#86ZsaeBItzoW6!onGmFd2qlA&BmF=+l^$ONo|HoK;9LT<{P2doou23w#!iAr^^Ba z|5z!h?mLaA#c0sDvVW*C1;+mS>gJ8!9jT7=ILk$^Iy8DO%X3**rl^K{xm2Rp&+;Qt z@!tMzQQhtx6#X95BK9EQC>sjh8|z6f$HQv|I;XEy*!1zF@esA?##89`QE?ew)$73S zkw4boc<|=Iuj{uSgtz9PAc*bhz!(pmn?MOut7^K|4jsE|2Y2D4FkWpV>i~;`CQQ>RD@B?% zQJR*L*CUiy)AYE`MhiVm;BX`LmoG;QLj@1ifFw&9f!7Xv8mAmu;jKLMHqX4xhu-d) zxBJuAKTm)2ZanGE>)@oYX)W^DgLp-~1_y#ZsG(l~y22V8H|yuEuT2lT)cE#Y6@uI% z%}{#21x@&F+r9VIE?BV)9RvHvrIbE)9P0hMO6XgElj~>X`k!RyJc#J_4_oI1j`JN# I-?7>L4Ivz_b=0QmZL*s!WWr%ty$b+_G|cDK6=m`p@Zm|9MpJ<-|Svr@@T zyyviW8lq%brHQ!A2Ik0BwZIaMoc~v3G2h=h{b1# zSbf%r&1Z|)efEgM=OAf@urpHTD~pu-$|EkH3vfo(6t0L=`YK7-4B;wYH3?h7HIZ6h zEeTtpzB*qW3ERT;kp^EwWP@)*WTS6mWRq_b!P~>`NTaVYve~ye(&TF*I0xXGea(?A zzAcd!UrVIb*GlkCz_kd_9p~UvFfGZwF0r4j%cT4e#{r)KG^g*7XX-R&X2M)`~p!?IPGpz*cd) z6l@>CRs*(1Mf)hh)&jPUdsLy_O|bQVZQyn**gXWh0k9iYCF~{GO@MWCdllM!1ltJM z&8l)ABiJUuHgkOn?c)Ty1+XnD>=Ojr3fMLkwx3`wg6#wBquhXkeTrar19lHLs9=u}>|Vg`<2EYTqXhdHU>{duj}hz>fbCad zy#%`-umdXWae^HL>;V<_1i>Bz>>(BQB*8uj*uyI9(**kzV2`M@o_ znx%bb*yFxu*b}~I*^|Dr?9)CU_bhO&j2)7>#+@bcQ%c-N;-}?!Nb7r!)NlrBc!sla z=Q!6zO)U(7!khDu)>r-JblXA~Nx#v~0CQPuO1FWCh!0DBe zBLx3jfDdpHWh|ludjYUP6?T-p#Imn2zA-k$a`1kh9bqrRn`bYx!|;wxXg%S?26I0f z7>jd!%zbf`cSpw~93Kk0;}c_CtkZl4d*q=7OCTB@jR)eP(P+%;(Fof9{R4tMa3L1w z1HpKNi(eXLflM179roxTH98>}2Lj=6;6j)aEQ8#|z<4-57z)M(CK!mt1>32!Cl2@r zo;)yco{S{n(y1Y}(?MBSvlH$j9z zc3=>r!BLijC==tt7X|I;g^?Im=63(eH?aHMi=+JI81RQX7afVmIs(Dq=y)_9iVk-K zM|tkt1sFOm%AV_dfs4Ly?r7-3xmYO9bs$3n!(8m#SZpFVIyStGNb@#HwmZir1cn8H zNI3F6>_o&PQ1Oxrz!bIUC{Opidgb-cPk(;S;m#V}OW2LleAo{u*Qg{lqHqFf#V5~` zNlj8SMNiO4u)8jwqbMHYLlmn`Y7#&STw%O1R3P5dN00Kzf+Z}@?VLkwpC1o|#T3#n{&AqcNs$UkM|f;70Uij% ztN>o2mNc}kaaqskdPG8`3BsT9Nb*T9Vf8Ax28$NudO`z}t^!$eoF5v$5DW)mvDGAd zjFeJJvT+pSQf(A9PV<(yBI~NLrsF!fZF%enGP3B&&kBAUBtbJ76jnhSipKfvfZ@9l ztsZ?kUNG{6jfvV)og+ex5+ez~qScvpy?QuB-?mua9GKp_SYDY9zR{K%_@r3cMFHTS zfV?oogYe=HAUKEs<&i&x0L4TcwZj-ffKnR6j=n-IYxKHCkp@!=225fay@aBfAF$I@ zh{A0M$FLeS5m-H|g#pyD29|-henRIl!axp?N~a`={Wk95<8{#ta@ zX13g@oOiS?RzT>Dqp1U++R}s9j$J*LvotQas;}+4x^Jd3=W5MbTW_zd?TE1R15lI4 zP%QD-cEREItE?cuKd--vC&LLK=Mg*xf3a!+U!)eAwoE;lwY%q-ElUj1W@cHNA!QK$ zlt&sxdZ`Og`N_d)N2GncLJ0ww955oRmSwJM$pq007GeR2^CDIbG_8lD7emode4=&t zZem&V#c-Kx?YJLrL%cWORVY1LGGL+TMY23~U;t-FG!XUP&nYLQ2}C#JOX5HY!iT2s0Fj*mborxuA3UTtEb9Z7Rp)|obG!D#;O0plcFZU z90kmh7F~L&8B*3})&vcfnN>8AL=Jg9`r`3c^`aMh!J_~ck20*`6p!FJ_=_RmR2}%j zfY@A2FKDi^QlVh4-CRyTVh6&a$7h7`#+A)PR<<(Io&BL`fS*`xS*w9!O6$8JN?d+u zelyUlpw+7GtA?mF?A{V~AFZakOwXKSQ`WeNbYC_h1Raq&(L&e{q#koI%TY|hUO(*Z zfBLMThph-$^gNCOe-;55fKm&OA5#(FU#uPgjDpSe`uXYeQwLS@v<#EZEshCNmL8MB z#c0L(Ch}fScwa7x(!*hXBeZM<=2zce58?g@W(go5HXDBdf~BV=e;%n;WaKcWBEUbQ zHB{m}HK5`j5)|-H(N}$tvbIdaVve$_7qu3v1HEOK(8I!RlQw~$QHF&I7L0j6EAA-$ z@likSBv;^Tc|o0orOzV+WPxs)8JKglWsPlwzoObyX-#QQ5ktGPK%L47IC~|1DxpB3 zq8gVAiJ2gxDB>k8#6bPZGlxe5ST%2q#q)-!DvS5@u>(&Z9?0t|GF8Zudk7228)`&e z5JcfGhB{Lk=K7querf>MCeK|XRn@*w)v@4gEYQ7}tzh7P6WxpZ)$Y|buko<=RCm5F zMLodb;Ssz9e@hksqzA8ePIt;$7gHZfLwnb5=*kPkIJAOC@Occx5Rh>|)I(`q-`cGs zi*U*1>k769!S7%o-#SEn=GHl3kiDW)V%0YCqgZ*V)fESqNAM;1Q?ITlr}8*s`e$yd z37jUYHc~Kv39zC#PGUn5yowFYi(|)hhulm|Eoi0|5b)4TEWo_N1ow;Rh5^+G3X%bb zp$?pX(k$~CAa3MLO56-_3ujg0Hi+9fhZ1*!qQ%`)*#ra1)dWK#cC%pDf%{Zw4!tx; znv&lPsrD6=T;zzP>48*v-h$Jk-&1xLFN1mIO&oNGV(x&O4T0|_9=ycy?)a#CG>!q5 zc;aHaNubSxgy30p$HvFTMq?a{gcmq>5PXLm3w}YsV}Vy|9wxYC2KCT=-4=Ny}}_NKcO-P{Af*0ZG5I?Q(|t;tMgXHXg&(m(7j zVa{#{th^;lYUJ$}_;~MoWZOz37{tFv`?uC&GD{dOV8PWY>C9YtP*kP zqh+S@14qk3b^WdCwp?{v*4cJfOF3I%S5(uWpwe+AczZqBw&kj~Wu4nFn-nC1;^m)! zcEBzOT}Av+1SpR@Zd^sv1E=0<>6MsXUTm5W8wAxiS*`gk7@9_a3n1Tu;L8ZeO4N!W zRG~!a^KBS<4FU46c$s<5K^$n=T}#He9}C_O;O2e)4&03KECM13rS@H4#Z&}u!`~8Gp{jis zZWcC*Y(EkU}DTto05Fnft9woMc) zBzb6@bbvMdP*}(}VDn4MRYg%Hgh~GudnxO!+Dy}{pU)aaCF12*oNO~#34*_ezfwFB z9Z`g&fJa)Oho{&CUrD=zX|3lBvK{O*LfpiemAD1sR?eox?GSfxP9Q(7Q4u@;5OD|=;ZHg6(&%bM4q-}Z4z)u{o5V=Dh|pjp7t4e(lpqXl&l z$^0Lf;avo1A9xA>_&>pTk*s|eaR}~UfS47;qCnI`<%hJ^KOBCzv9T*lSV3KcA4`~F zJ^c7nBt&o*19^TR>Y?!?zYsngcHrz>fgSnfP&MCv1@y!XkMpfQGdSmHoN3HCnzKf6 zHmo8qe}+{d_$8K6!f@Ck&L<=(&97C|xOlj@8c)`v$g$cLxZxxx9V$-XeqGVv73ov2 zzLYiAiF4+D4NeNiJxTE-`U}J%_-8E6003_&Xms@=FEFJvFMb1sU2rJ08mrb;*|K(N zg7&Szu!5r@72n|Ec3xvQWKPXFHqUI&Ikset;`n>{zr;dIX`H{p1OyD0Q9^=RM6Myp zL*`n6UMOuTteq2SJtQ$tttT zChcBI2nz!xYtcYL2VCLtZT=?G+mZza_mOl!MxML@HA%-&;3e#cNe<`VIAidUEmqm& z(($JNE0`l(WR#zHA;i7Np9TaumJ;-E#0IzbR$y>>L6-<`;d1~ghW0DyG)rZgz5dj^ zrFGF&lc{)PPik<{QI(Egd+F*+Z%odqr1btdZp9Xqn&W?m2?)xuB6*H$b&|AV${l29 zhIP4_dyI$k%NSg^b@SZw;~}1l zxkK?zGbzRkSN(RoLl+4lE8eb^OG1x26vVpQu!McxeIED3=s0-Pqi*mYyWtgz!u`Pz zOG+ArYq8{7uNyA^2HZScuVmqRCAOw(w^&(+TRI|b+uqgH<>`!F3SEr1b@zJQ`;?Sc zOj_w_^^mGoC}&4OIbEv~_jGyOd>|A9UK|!Xaa?XcsiL&Hz%5bXym?2tsVd%tO456Q z2Jd6S=>^;)W{`DY(%Atk-MtgE;EWfvz_|kVE{wB35{kiXr(wT8QLP&EPE|q=ienuV z26At&1plsmQ%bu~QJrE^L(`@OM|ny-eDHc0{s%xNI$`@UM4F&0a;*vmzn>iq!X2br zNOK4Qu?X=hDF1;B;7b_!2IW1CNoQQH(&}6yA<`sjc0_PLD#wRa5 z`DAIy{|y#ISAlb;gp$)kdx(utc`a}H+iq-Ih($xP~!OkVX}hVhM=0E07| zJc!}nWa&wLUhT1(xT5y*ijmdIm+0a1gjy)ykkqqG0#s;{P8t9~u{w+;AcPoJk0He4 zds6>eJwqjRaG6eK(XQWOJ<=?C!$*{(^nEXK?OTDalk-DNiOT9>YOyailjuCS3*ggJt0o;MZBkB&0 zZertw0P7~VnhU-{h=qouyWL$^1o~Nz9qxTfm*ZuB+$Ao+3d-Gw6UT@05$}ORf{qVF zhvBd-%tZzB;DG`E;Ne4uPYnqszpQknWh@5Ajobx6M>Lz@RBnz)mq!KT5pIHGR=3VFx$2Irv*Xi6SN%W2p)4S)s;^zXdO6#? z|NY*-rQdJMZay+sbu|0*nXL27T`f}lifjq~eV=iFrv9349@wJw^8Xq5SJIvpFag0K z7nlW?|5)e>$4awvklbTP#P$ckXu~h3 z#1msQoG>J=r_!Lb<7ZW46P>Wea>L?fh!dl+_%PaZ(qM_E*70a~LNwlp85kZNy^O}# z_!wMhcf&>6PGaQ{W+tlfI|29%LtMi#((dl;>^v`6pc+5<#DR+iVNF#YWEfdv|04vx zPQxmzBuz6(>MP=^r`%-#oiDMNDtXc#+t1Q*)ac|X#ca4t?uJW#R9HW$jiVt$o}_jJ zC8X%NsJguFS6V$m<@4oRqfVay1I;Vw2!lo6rU?}JIDYK~-=N^7XRwk!h06H<0|34{ znurMo@q?5Y|4)cNig<%GHXfa*)4xcN(mFxtVA&A4>i5ThQxxj$DN$|zKZqt8N{9#8 zfMN??L@~#TK80Cjv`rgwMmU+x49^=|mW`CN>6WAO14rkAqw0Fo?{EFaR@kKf$l35o z&(8OBe`))kE!%x?-r4j6=eAF}cZh+zHp(fU{uJm9s6ZTH9Jp)Lgm|l0oP4EEVrojY z8U^?jY%%r|?k9Lpipp^tM8QHu-iWtxXdp_s)F0gyeixM3ENK})1A_q;OoZp)JHhj+ z%Z;`oGnZe$nu^p34kLdC0kWOPCW_x2*rf3Za^bMw57s-}W}#y6M?E196OjT0VN5`^ z^ywF=dm63Ic-Kr>oVU!P&Vi+`y>seFwybTA>G%a>(e1ojN9ijB<|JIs)K@Gr5;w4< z0)@1mLlAkNFRG7%!NaLUrYHJb3QgeBS7~GukFPDY=U@G6BlRgkeiADsTH+RH4SDj$ z@(>lrb%8uE_48(G-W)A4vEhE0Mn$XayhO3S|Npb*D`EPm4{8J8goOjB@B1T($2>bK_V zx6WJI7hP59*c*M<9>4ndoU1u&ZCxxRvfrgNHanSHULHrC_hM^{ z)=G5a@d#4bIN7OT)QK5MN@+1{hr-sjSPD*>3ioNN328Sprcg-bfy?jA#;MZoC=ev< z26>XIHDpckQ{{pwVU^3szm*ay@>4=}kx>yoxvkI=MT|kDp-cD39PxY%!{i0;Ak4OE{7Q;ZJ$cJRq79mw}b8Wxg$u^YG2BN(Ax)iz`RbBj+K0 zAU*=Aa0OK#iov(6(Y&64rDX>sk)=ia`j!tvoPZnH6}(Xc%cjBnrNkE!uOx3fDocN0 zSQp`w#@afmd#wk&T2|h^8g0@-ZrTcT zRG_^AebB>%ehxx;hlQf=;Kqyp2L!+|G32od#z4$Zb}NEI{$9n~@AbnsUxHIX9QGb8 z#GH^Y{3lq{&j1MJe)5wE($>k3ZXo_+Ofcc6rU9N0Oz=NJ>YpM&?s)9t<<|d&RC>u% zqvfuQ2?o(!6B9HqhWP)9$;N0xB;fC2R12F0K^u>Z!KaMl@OuVMz*4eML>98)7E`Q`S^ z&Y8B^lizC3)o*)u`v>*C3r1(Uf7+HZf;*=K#aw+aWHnk+ftRl=z-QnU)B4+GMGs$tmQxPr)S*RNdAjeb{uGV1 z?8pw#3U=w&ZsNNlH-Q4EUsy?k^899L)Dr4LIaULoRTJHzrh~%?(9D-%4)Nx^kq$ba0g3jg#$mwQ zOFZHA;G>2R>U}JOeyxcdq8Pno_LHkc(D?rX4HGrNB8Jf7A`W1WQQUl+FTgGxytKpd zOM+wn;Zyz-2cGtyI7HmFJp3dWCC=uLF(3R|m^7uO`|3Dn`OS#M$xWuEpyjzp42Mjd zm*SixmKK7a199v-5C8+oUY2gU)_Jvau6*+if3CcD&c5S4I%j_rWX&cg2gs)sv3?ACB)7nok{E6K?Q$5@IZvV}#;7dI@XMcQZAf-u_!HhMU zQqQEHpMEX_vb`Z^+%VPuq1m^VGf#62O{?7X=!*4-^$;za6~8O?cwj>z{dAq+ z;JM*Y41UE<{tgej!%rdj0|Y??&m!<6*n;4B1gQSR@6lQ@bOiybIq@qr4~8ZYEF%~} zfZhn=bmLLQkskozw_@n42)>RWgJ1^1FaTBKpeJx$id-8f_npb5UUHL_T-PMm6UntZ za*2%GWFn`Q9t}@pwcF5g0do-S8e-E3wfTOFw}AXIOL%n9{a>Vi8ZyA{!%=n1u_@=+ zH1*^HW4*;RFPLQk0Jy6nf$X#n?O6J^T29FBm<&q2vFWS)|oXy*f#$T{9wA?HE@gTFH8 ziIbBc{3*GM~xMi^PuLPKw;S5~RZ?bPMtS9SJpK&+}+m^4LN_M<$#2 z`3O2|cr+l%XR~lYOKcTigD7-Ch+kZg&koTN6h9Y0OOQu*A@4@ehyX1;z6k-^ad7PT zA|Duo^URp2wur_e%8KYIqN0c`xOu=i}$ z?IX)@)7!mlH$#q!wq*+5%XKten=RXdS!$P!t3?{J)mxFQ0m*8z&Ss3%EE{X-t~68w zujM|5-k45cEgP5ZrNj5iDL7&aywUQFp3Dnx?a7t5OgZ2;AL(t`4IP+q8)n>;4qM@UqG5>q+cn#C4CWTwk+GVz?T-xTaS5LGQd=LVcvpp z`XIsIwNrM-lzG8kF=bH!N9B}t0Rb*j&a2g#$~QJHFwU#3nMdZzw}_#wbLA~??WsbO zrJT!l2klC4%>-w5Wx}~~;2y;9HB+{lSC37ZJ~Y`=zb*b$#ScwQQ~e9B#;L>LsXGe3 zJaaRA-d@uH8a;I}^=!7fJ8SFCp@uJ;I{2kyUpSU-onz{5F)cZ!Wl5*4fyyfG!O!{B zVTNG3C!@^_Wo?Z!JF>R69OEg@wkgMKf^1cgt$f*9Nk2npfH(NQ*G0Lu%$%I1XZO5E z&z0|*v0A9<^TKZ`yZKeqY;%R!h&qUj^6|Kt@ lyq9Zi5UGPj4xAEg~jSLia@vD~(m-ba?3{}0iJ`O^RZ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/numpy.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/numpy.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8d0b21ff34183ecb8f93bfb80e95067626ebac30 GIT binary patch literal 5516 zcmcIo&2JM&6rZ)nAMr;vBq84+0V-M-VjwYr@|h1v2`UCbk=m8R%JFU@2d^Dw*R+m6 zq7oMl6}=IuJ>*zKjy?2mXfGhP0U*>PSce41Dvac}^M3Q@?VC4m zp6Bh);c$RJ`&vGg{wYMrAIOxOr_?E)7YKPs6e1BtP+S>7b4f0NC~k#j+!~cA?|U*H z%`16%-<$Die#x&jNll#hWdd4I3Th!Kq=lt0V1A`3)2xY-sI^EfoDXDnXsuGK)+V)a zJ_vlf)UNH6c4{3`ht?@|3dBV|CQ9fYQNn8LW4CRe)Wy+eKt%`I&CwP>cR0`{Ber4AjRR-=+ zX|S*>GPu+m7*~>uhRXE8xf~nJ=C#Gbpix*<^=RM~t|=l|?(uBlmCNpXqxM_l5wGQ!9dv_T>OX>QUAZ6O&(8tkz+S>aHg8b zE*SbyGL_2Zvqm~QKa|QbH8BfrR)@P3UPu9YXIX=T$wis25VX#rcDL zR}bLloebqpO{R}*!%by2&p9Xr%n~vi(CQ|^g6=Oi^p94iuy^2fqL7H(x zn(-HC#ACIU&V}=^L7dMnSYDTDSL8-p4b$B^uU zUl9$1-3Yfmn7Kc5cWR9ap1sTNH3E+n&pJNr^MDiH(e{iCJGY0sjUB+(y@kDDQBVZC z6MzRhh~y9u=dN%cl{Tf;622)Y&PI@6T8J|Y#*H35ju?_5>>NYFa|lB3$Y-OmckeUI z&Gmg&YYF$+QJh%EXQxmG33q7KX9&G@pY5z;F&n`#6MyOUu4q+z>eS>N0H#sXLw84^x%)-0Fo2%(>FQzG5g@hR=jxdV|EbZ z1k0DQuUY(D##5EV2xFM0@x8^fkUk%h+hhTljqQ$bTUbD;4NVb@a+)WPOUGRxTgbW^ zkaZiF8+og%ml~CeRb5$61F~KNv(ENx@HHUoZ@>>t4fr9@z}kWaR7%@iTc`oqu+hA2 zz0D2CiUyub-sZGyw%-{<_2U%19R{Oy#*3!i7y50atUse$CiSX{^3yvGcxR8 zMq^9Owpb>YoyT8U#Vi!IWkKxAWhT#+hwNF%fOZE5>Kz>D7fX_r7ldtK4r^bS>ttcF zlO2skS}cFERPb9OQ|Hq<)c!KwdR1nZgjiGYQifrHz{>@O=aAtaBEPTlD;B>qFiaBs zuZ-c5VpvMTC2s=zXMs5HcUE`xb?RI)pE2aJC2R_0agq)nRp8eBLhN`h4m=eH?wDr?hW5v3km+AHAsXGpiR(dVJgblm4OAJ0?9b^LW+cIto9AN@fz=~#7wyqc*|@H&43R^(W*x&O3D&r}u6ms~?V{^kPQ0fp{$|JMD!Zx&FdZ@rlcdzXjS2|V7^k1bz9nb=zMZed(lxxGg4`6FHD IPwxKz04@*wSO5S3 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/range.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/range.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f00695b33597573c547bac89cb7f2870c8ef0e55 GIT binary patch literal 31821 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/shapely.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/shapely.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6bf4ff6c0cf12dc5be8916a96e9ed5790ac47996 GIT binary patch literal 4404 zcmc&%O>7&-6`t8$QY(@oW&K!x{@Fxs6xtT;xPbd($Eg&@wgQ_eA|Xv^8SIKXl4)~y z>DiTKvT~sY0+Jvosv;(`wY+?A+_hy$g zDX|99O9$Ya+4tW3ee?eKmyV7If%fz4%lVadLjH~)wHERRbaOu?|73IhFIJfGWwR4TfzM^yMVLH=x^ZcF7*x*wsRlh z?RX-#(}>*yY_Ppc7sxgF9kM`^yUWi-#tgmaGVW-zHrIY=JMQU;No|hVCUbe7Igzh$ zPLg_2-Lh;~ck{O8d?oojwFvrioH=Ta_Ac2dqoy~qkBjk7EBc{r2if@V?AUDoHAHZti;M>N;gW|)?@99J(C zn32Ql)f!$48r?hy^af!hL&26LCSOv8powHcU{`cm$%IQ%Qt^6fM;y;vIxqRR%>^rp zi3(7#2fCSt!42XD??K2Sb?bV!f{_z-1KUA)?d`5pH?Z|a?j%{G>7?vM@{YKdm1ACL zrsOh*cfeL_lBYPVFzYFX?&=P1plMGsuYP}e!RD78fQU_7mt1F5&*kiS%gtMJqdA+i z=@|fzS;lngDzmOmpUuxqJ9(Fl2ADe20se;s{)YnmQ^k^};1iYyS|O4`(JnZGvlqw` zxt|zV-S=^*l6c{McmHb7N5|ejc|Xy!GWFq4*44pHP$B6xh4(|x+kkjs&fIx!@dSJ% z+dMU!wRDqZvtA^d_00mtv26Cryk77n9ODKUy_w8^Aq1V|I70qUHF|+NsO+m zqXOMDN7G0ud=GRSEre@Ga2t+GHayt3@Ds`N@N@9~%cLqPp_H$KlGg9^KR9=PV+`^g z+z)F_4lcu%@S~e(uFVc!bKptByFr+wJPzHO#QUK0WP9dPBdp-55d6x!|J$x96pzA8 zCk6zasApyJ!}7X1;G+m0a|i^&N%(FUl{@@+tSxG3+hWPKtpKBs@aK>qn*1=5EqEhr z9Law8ZFdkF8uWojmDa#N!$G*NDBid%17>c?9T3P#d2&0DaY{B!=%M_TNtIzmqt)t{(IsfWL%0Z8PImuznjf zITD;wH)9&|9YRRbO;#2LJz-_P6~)dXfmBgXB}P3}yh|5JD>$Ae6AFoi#~@xHxLcZ) zaB&~eTFI|Vi&CpN1AB@xtv1*1T{KhCYOx3Q{wDL$S+>u|P`stNT{VV_(Mz<}XR3K* z(}|wFBKqn#S`lKuT;BI4o69>;VrfAQqM`S~r*0V}D6#U+hz4a9vm7YD{7J?u>151n$HM6~&Ta0gJlMxm^`NHXSS)ynnjq`%2H_@e z`1uZlWP{v4mf_&oz z2ju}D1MyMRTLH2}9z{s3^M1Ts+mrCrevg@|8Yjx^3Z~yx3%E+;ba{P;C=Epy+C`apxH>W>2{;Bf0 z`k8v?z*t2YuPfi2t{gb=sr&i0&#v7$aOQ8ygz(;6-J9Tqh@kK`jC$`u=)vOreKJd- z^ivJV1+L#}<@R z@b-SE4xYBI?Df|aWkQ(0g3~a3@*e;xcQ^ja3bMJ#@SY+PyCR;>lk=AAC;omc&d+bp zW)~nkiC2CD*A_Lxo^7g)7+py2@!GOk!_N7|_Ut^=;ZS&U^mmW=p+?qcavT$fU#y2j zAmV6k9E(y zUqe4!MJLRn&0P@+pT;)vB*Lgg-0>|~yu>h`sb2ki>T&Co!YDuJ%r6{4w?x2goX zYNtX6SFctHbk(>-M^|@N33Sy+g1$~S4ic&DYYAkVGK@BGv=I+@n&3SGp7wa-v_#bI puVIz&y-4qdMB9fpWjPw&AaW?YAp`q~gJAwKKCX~IEAjCz`9IH`wVD6` literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/string.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/string.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c43cfd3ab378b90bdefbb5918bde33f1079f45c1 GIT binary patch literal 11375 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 B(CYvI literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/uuid.cpython-312.pyc b/backend/.venv/Lib/site-packages/psycopg/types/__pycache__/uuid.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..290fe53ede6dccff7ca4b35dc149ff4a47886b17 GIT binary patch literal 3260 zcmb_eTW=gi7Ov{sjOXHZGPYwwhzI8aW5|TP1W*!I0h>z*42Wz%G|sl#-DT5GPq(S= zNivo}eu%X314H25aKPuW@^ZX)M!qfI(51( z-?`OC#bS;?d)I!#|Cd3?*Enc5T{3k2HZaTNEb)j%JnAU{tt*y7kyit?u31`Lw{#e5 zo*o$WjFl0*5oGHg?iB{)_bkqx@nn|Fr90#R!`7p^?5zcE-%M+ zd-)Tvt3sY7Ug0wFimdm#D$iq;gtQl=CM$KM{X*IY(p}8#NC$*;H%Lotpd%gh2E6{u znzg6dQyHAUFZZP9%q5J+<>`o*lQ&uU?AcQj<)k^ss=4oR*9uMZP8ddsllV~>SClk6 z?gW7|6|l7U&(~jm+8%%I>G9L2YR`VJNOj$gd@qLYjAtTVcM{+VVw>?OOxUHQqNc`E zjp=E|Q)8l0pTquz$nhAj%@4KLexq8gK3r}ze6NZpI+tqLxe^CSaXV;q{b8WXgb|B^ znG~kZX2rx7V(FghQMkC#R4Q7U!`0;GZfhN(jy!-(*B=FDnJm!REvv}EY|9+oQ`cLA zGh~(403`KIb}2Pj=tdq}RZ=Zx!E~xdQ?oH{Q7-@T+W4`_ixEE`&p9re3}=)0u;aQ> zBTW2o=CB)aHaX?E=UM1YRxhyd!sHA7)MV@@>@a+A-kD+X> z@Nm8;%~f6~*P@VBGHKSfL#NJcJI&d4J@Og>@&(&|tKkH4hG$^0G>gZuUph4bclSL$ z1hQ4ahoR$pkeF?Pqqq;qWpX=bUac-w7sod=s+XlQ>iucP@54hq<%bS$?%)Cxwh}IY zko}emoFRM{Os~>ZpK2y7=KU~gnO5EmuR1@leJ5dy`%$+5MB1Xc)Vz@$68Efe+_aM6 z_d&<^AsIn}4h=zbs`lh7ucrotDuk5)laJ!`CY}dyhy=fF<5?_SJ-2jj@fpN(SSq8+ z7Cbc&K%?tpK>ytpP7pTQ6*5gBc#4+l>7D{X1d>bC($A2JAwx;VuiG6MxT3)EBryM> z%Ortbwk36eybC#Yfi5W5Tj57Z(mDg+k`cL9tt$@X+9v!eYK@~}h4LbHTB^ql%pBl} ze&{E*E##?&&Rfy=04Q<9InB5->!dxl?FLR9+jfi_mCNNtX{joV=1XWPd5da$$wM#^ zBmO@xk~`VrQs!oMXr;6=vz9&dP2Rk6;)}xlcU4l5rrVN6I(NtP0XIjV5^aGdt@{$v zzB$h)t$KrqTyN>VO%sfu)>pGVZGN+Fr=0c|EuXCDY0i)RFixD%WofR?>Je{V@YzNF z0DLTQGCU?TlRye`hLbqm?we`>WMr8|TBx7^Gi{8p03i8+YujLU>Xd_aRh8au6rbcYeN1{-P{6U!F6(ne~?HTI{lp*;m{Qo~=sqG4YDsCr^ zV9<%Nk6{3Ln(S1n-=CMdW>3iH&Oi8zpp5<)`#|ohl+qs*g=#+*2;Ki38T*#>e@^y%PWF9C#%_|auhhQJ zH1n=OMh`7&H;jF^$iWRmqvdOZ8w9$IUX2c4n@4_lqc=zQqa3=8dkoM4IdmJlb^4e< F?^iIMnri?6 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg/types/array.py b/backend/.venv/Lib/site-packages/psycopg/types/array.py new file mode 100644 index 0000000..1da8f43 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/types/array.py @@ -0,0 +1,476 @@ +""" +Adapters for arrays +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import re +import struct +from math import prod +from typing import Any, cast, Callable, Pattern + +from .. import pq +from .. import errors as e +from .. import postgres +from ..abc import AdaptContext, Buffer, Dumper, DumperKey, NoneType, Loader, Transformer +from ..adapt import RecursiveDumper, RecursiveLoader, PyFormat +from .._oids import TEXT_OID, INVALID_OID, TEXT_ARRAY_OID +from .._compat import cache +from .._struct import pack_len, unpack_len +from .._cmodule import _psycopg +from .._typeinfo import TypeInfo + +_struct_head = struct.Struct("!III") # ndims, hasnull, elem oid +_pack_head = cast(Callable[[int, int, int], bytes], _struct_head.pack) +_unpack_head = cast( + Callable[[Buffer], "tuple[int, int, int]"], _struct_head.unpack_from +) +_struct_dim = struct.Struct("!II") # dim, lower bound +_pack_dim = cast(Callable[[int, int], bytes], _struct_dim.pack) +_unpack_dim = cast(Callable[[Buffer, int], "tuple[int, int]"], _struct_dim.unpack_from) + +PY_TEXT = PyFormat.TEXT +PQ_BINARY = pq.Format.BINARY + + +class BaseListDumper(RecursiveDumper): + element_oid = INVALID_OID + + def __init__(self, cls: type, context: AdaptContext | None = None): + if cls is NoneType: + cls = list + + super().__init__(cls, context) + self.sub_dumper: Dumper | None = None + if self.element_oid and context: + sdclass = context.adapters.get_dumper_by_oid(self.element_oid, self.format) + self.sub_dumper = sdclass(NoneType, context) + + def _find_list_element(self, L: list[Any], format: PyFormat) -> Any: + """ + Find the first non-null element of an eventually nested list + """ + items = list(self._flatiter(L, set())) + types = {type(item): item for item in items} + if not types: + return None + + if len(types) == 1: + t, v = types.popitem() + else: + # More than one type in the list. It might be still good, as long + # as they dump with the same oid (e.g. IPv4Network, IPv6Network). + dumpers = [self._tx.get_dumper(item, format) for item in types.values()] + oids = {d.oid for d in dumpers} + if len(oids) == 1: + t, v = types.popitem() + else: + raise e.DataError( + "cannot dump lists of mixed types;" + f" got: {', '.join(sorted(t.__name__ for t in types))}" + ) + + # Checking for precise type. If the type is a subclass (e.g. Int4) + # we assume the user knows what type they are passing. + if t is not int: + return v + + # If we got an int, let's see what is the biggest one in order to + # choose the smallest OID and allow Postgres to do the right cast. + imax: int = max(items) + imin: int = min(items) + if imin >= 0: + return imax + else: + return max(imax, -imin - 1) + + def _flatiter(self, L: list[Any], seen: set[int]) -> Any: + if id(L) in seen: + raise e.DataError("cannot dump a recursive list") + + seen.add(id(L)) + + for item in L: + if type(item) is list: + yield from self._flatiter(item, seen) + elif item is not None: + yield item + + return None + + def _get_base_type_info(self, base_oid: int) -> TypeInfo: + """ + Return info about the base type. + + Return text info as fallback. + """ + if base_oid: + info = self._tx.adapters.types.get(base_oid) + if info: + return info + + return self._tx.adapters.types["text"] + + +class ListDumper(BaseListDumper): + delimiter = b"," + + def get_key(self, obj: list[Any], format: PyFormat) -> DumperKey: + if self.oid: + return self.cls + + item = self._find_list_element(obj, format) + if item is None: + return self.cls + + sd = self._tx.get_dumper(item, format) + return (self.cls, sd.get_key(item, format)) + + def upgrade(self, obj: list[Any], format: PyFormat) -> BaseListDumper: + # If we have an oid we don't need to upgrade + if self.oid: + return self + + item = self._find_list_element(obj, format) + if item is None: + # Empty lists can only be dumped as text if the type is unknown. + return self + + sd = self._tx.get_dumper(item, PyFormat.from_pq(self.format)) + dumper = type(self)(self.cls, self._tx) + dumper.sub_dumper = sd + + # We consider an array of unknowns as unknown, so we can dump empty + # lists or lists containing only None elements. + if sd.oid != INVALID_OID: + info = self._get_base_type_info(sd.oid) + dumper.oid = info.array_oid or TEXT_ARRAY_OID + dumper.delimiter = info.delimiter.encode() + else: + dumper.oid = INVALID_OID + + return dumper + + # Double quotes and backslashes embedded in element values will be + # backslash-escaped. + _re_esc = re.compile(rb'(["\\])') + + def dump(self, obj: list[Any]) -> Buffer | None: + tokens: list[Buffer] = [] + needs_quotes = _get_needs_quotes_regexp(self.delimiter).search + + def dump_list(obj: list[Any]) -> None: + if not obj: + tokens.append(b"{}") + return + + tokens.append(b"{") + for item in obj: + if isinstance(item, list): + dump_list(item) + elif item is not None: + ad = self._dump_item(item) + if ad is None: + tokens.append(b"NULL") + else: + if needs_quotes(ad): + if not isinstance(ad, bytes): + ad = bytes(ad) + ad = b'"' + self._re_esc.sub(rb"\\\1", ad) + b'"' + tokens.append(ad) + else: + tokens.append(b"NULL") + + tokens.append(self.delimiter) + + tokens[-1] = b"}" + + dump_list(obj) + + return b"".join(tokens) + + def _dump_item(self, item: Any) -> Buffer | None: + if self.sub_dumper: + return self.sub_dumper.dump(item) + else: + return self._tx.get_dumper(item, PY_TEXT).dump(item) + + +@cache +def _get_needs_quotes_regexp(delimiter: bytes) -> Pattern[bytes]: + """Return a regexp to recognise when a value needs quotes + + from https://www.postgresql.org/docs/current/arrays.html#ARRAYS-IO + + The array output routine will put double quotes around element values if + they are empty strings, contain curly braces, delimiter characters, + double quotes, backslashes, or white space, or match the word NULL. + """ + return re.compile( + rb"""(?xi) + ^$ # the empty string + | ["{}%s\\\s] # or a char to escape + | ^null$ # or the word NULL + """ + % delimiter + ) + + +class ListBinaryDumper(BaseListDumper): + format = pq.Format.BINARY + + def get_key(self, obj: list[Any], format: PyFormat) -> DumperKey: + if self.oid: + return self.cls + + item = self._find_list_element(obj, format) + if item is None: + return (self.cls,) + + sd = self._tx.get_dumper(item, format) + return (self.cls, sd.get_key(item, format)) + + def upgrade(self, obj: list[Any], format: PyFormat) -> BaseListDumper: + # If we have an oid we don't need to upgrade + if self.oid: + return self + + item = self._find_list_element(obj, format) + if item is None: + return ListDumper(self.cls, self._tx) + + sd = self._tx.get_dumper(item, format.from_pq(self.format)) + dumper = type(self)(self.cls, self._tx) + dumper.sub_dumper = sd + info = self._get_base_type_info(sd.oid) + dumper.oid = info.array_oid or TEXT_ARRAY_OID + + return dumper + + def dump(self, obj: list[Any]) -> Buffer | None: + # Postgres won't take unknown for element oid: fall back on text + sub_oid = self.sub_dumper and self.sub_dumper.oid or TEXT_OID + + if not obj: + return _pack_head(0, 0, sub_oid) + + data: list[Buffer] = [b"", b""] # placeholders to avoid a resize + dims: list[int] = [] + hasnull = 0 + + def calc_dims(L: list[Any]) -> None: + if isinstance(L, self.cls): + if not L: + raise e.DataError("lists cannot contain empty lists") + dims.append(len(L)) + calc_dims(L[0]) + + calc_dims(obj) + + def dump_list(L: list[Any], dim: int) -> None: + nonlocal hasnull + if len(L) != dims[dim]: + raise e.DataError("nested lists have inconsistent lengths") + + if dim == len(dims) - 1: + for item in L: + if item is not None: + # If we get here, the sub_dumper must have been set + item = self.sub_dumper.dump(item) # type: ignore[union-attr] + if item is not None: + data.append(pack_len(len(item))) + data.append(item) + else: + hasnull = 1 + data.append(b"\xff\xff\xff\xff") + else: + for item in L: + if not isinstance(item, self.cls): + raise e.DataError("nested lists have inconsistent depths") + dump_list(item, dim + 1) # type: ignore + + dump_list(obj, 0) + + data[0] = _pack_head(len(dims), hasnull, sub_oid) + data[1] = b"".join(_pack_dim(dim, 1) for dim in dims) + return b"".join(data) + + +class ArrayLoader(RecursiveLoader): + delimiter = b"," + base_oid: int + + def load(self, data: Buffer) -> list[Any]: + loader = self._tx.get_loader(self.base_oid, self.format) + return _load_text(data, loader, self.delimiter) + + +class ArrayBinaryLoader(RecursiveLoader): + format = pq.Format.BINARY + + def load(self, data: Buffer) -> list[Any]: + return _load_binary(data, self._tx) + + +def register_array(info: TypeInfo, context: AdaptContext | None = None) -> None: + if not info.array_oid: + raise ValueError(f"the type info {info} doesn't describe an array") + + adapters = context.adapters if context else postgres.adapters + + loader = _make_loader(info.name, info.oid, info.delimiter) + adapters.register_loader(info.array_oid, loader) + + # No need to make a new loader because the binary datum has all the info. + loader = getattr(_psycopg, "ArrayBinaryLoader", ArrayBinaryLoader) + adapters.register_loader(info.array_oid, loader) + + dumper = _make_dumper(info.name, info.oid, info.array_oid, info.delimiter) + adapters.register_dumper(None, dumper) + + dumper = _make_binary_dumper(info.name, info.oid, info.array_oid) + adapters.register_dumper(None, dumper) + + +# Cache all dynamically-generated types to avoid leaks in case the types +# cannot be GC'd. + + +@cache +def _make_loader(name: str, oid: int, delimiter: str) -> type[Loader]: + # Note: caching this function is really needed because, if the C extension + # is available, the resulting type cannot be GC'd, so calling + # register_array() in a loop results in a leak. See #647. + base = getattr(_psycopg, "ArrayLoader", ArrayLoader) + attribs = {"base_oid": oid, "delimiter": delimiter.encode()} + return type(f"{name.title()}{base.__name__}", (base,), attribs) + + +@cache +def _make_dumper( + name: str, oid: int, array_oid: int, delimiter: str +) -> type[BaseListDumper]: + attribs = {"oid": array_oid, "element_oid": oid, "delimiter": delimiter.encode()} + return type(f"{name.title()}ListDumper", (ListDumper,), attribs) + + +@cache +def _make_binary_dumper(name: str, oid: int, array_oid: int) -> type[BaseListDumper]: + attribs = {"oid": array_oid, "element_oid": oid} + return type(f"{name.title()}ListBinaryDumper", (ListBinaryDumper,), attribs) + + +def register_default_adapters(context: AdaptContext) -> None: + # The text dumper is more flexible as it can handle lists of mixed type, + # so register it later. + context.adapters.register_dumper(list, ListBinaryDumper) + context.adapters.register_dumper(list, ListDumper) + + +def register_all_arrays(context: AdaptContext) -> None: + """ + Associate the array oid of all the types in Loader.globals. + + This function is designed to be called once at import time, after having + registered all the base loaders. + """ + for t in context.adapters.types: + if t.array_oid: + t.register(context) + + +def _load_text( + data: Buffer, + loader: Loader, + delimiter: bytes = b",", + __re_unescape: Pattern[bytes] = re.compile(rb"\\(.)"), +) -> list[Any]: + rv = None + stack: list[Any] = [] + a: list[Any] = [] + rv = a + load = loader.load + + # Remove the dimensions information prefix (``[...]=``) + if data and data[0] == b"["[0]: + if isinstance(data, memoryview): + data = bytes(data) + idx = data.find(b"=") + if idx == -1: + raise e.DataError("malformed array: no '=' after dimension information") + data = data[idx + 1 :] + + re_parse = _get_array_parse_regexp(delimiter) + for m in re_parse.finditer(data): + t = m.group(1) + if t == b"{": + if stack: + stack[-1].append(a) + stack.append(a) + a = [] + + elif t == b"}": + if not stack: + raise e.DataError("malformed array: unexpected '}'") + rv = stack.pop() + + else: + if not stack: + wat = t[:10].decode("utf8", "replace") + "..." if len(t) > 10 else "" + raise e.DataError(f"malformed array: unexpected '{wat}'") + if t == b"NULL": + v = None + else: + if t.startswith(b'"'): + t = __re_unescape.sub(rb"\1", t[1:-1]) + v = load(t) + + stack[-1].append(v) + + assert rv is not None + return rv + + +@cache +def _get_array_parse_regexp(delimiter: bytes) -> Pattern[bytes]: + """ + Return a regexp to tokenize an array representation into item and brackets + """ + return re.compile( + rb"""(?xi) + ( [{}] # open or closed bracket + | " (?: [^"\\] | \\. )* " # or a quoted string + | [^"{}%s\\]+ # or an unquoted non-empty string + ) ,? + """ + % delimiter + ) + + +def _load_binary(data: Buffer, tx: Transformer) -> list[Any]: + ndims, hasnull, oid = _unpack_head(data) + load = tx.get_loader(oid, PQ_BINARY).load + + if not ndims: + return [] + + p = 12 + 8 * ndims + dims = [_unpack_dim(data, i)[0] for i in range(12, p, 8)] + nelems = prod(dims) + + out: list[Any] = [None] * nelems + for i in range(nelems): + size = unpack_len(data, p)[0] + p += 4 + if size == -1: + continue + out[i] = load(data[p : p + size]) + p += size + + # fon ndims > 1 we have to aggregate the array into sub-arrays + for dim in dims[-1:0:-1]: + out = [out[i : i + dim] for i in range(0, len(out), dim)] + + return out diff --git a/backend/.venv/Lib/site-packages/psycopg/types/bool.py b/backend/.venv/Lib/site-packages/psycopg/types/bool.py new file mode 100644 index 0000000..8f367b8 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/types/bool.py @@ -0,0 +1,50 @@ +""" +Adapters for booleans. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +from .. import _oids +from ..pq import Format +from ..abc import AdaptContext +from ..adapt import Buffer, Dumper, Loader + + +class BoolDumper(Dumper): + oid = _oids.BOOL_OID + + def dump(self, obj: bool) -> Buffer | None: + return b"t" if obj else b"f" + + def quote(self, obj: bool) -> Buffer: + return b"true" if obj else b"false" + + +class BoolBinaryDumper(Dumper): + format = Format.BINARY + oid = _oids.BOOL_OID + + def dump(self, obj: bool) -> Buffer | None: + return b"\x01" if obj else b"\x00" + + +class BoolLoader(Loader): + def load(self, data: Buffer) -> bool: + return data == b"t" + + +class BoolBinaryLoader(Loader): + format = Format.BINARY + + def load(self, data: Buffer) -> bool: + return data != b"\x00" + + +def register_default_adapters(context: AdaptContext) -> None: + adapters = context.adapters + adapters.register_dumper(bool, BoolDumper) + adapters.register_dumper(bool, BoolBinaryDumper) + adapters.register_loader("bool", BoolLoader) + adapters.register_loader("bool", BoolBinaryLoader) diff --git a/backend/.venv/Lib/site-packages/psycopg/types/composite.py b/backend/.venv/Lib/site-packages/psycopg/types/composite.py new file mode 100644 index 0000000..576529a --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/types/composite.py @@ -0,0 +1,386 @@ +""" +Support for composite types adaptation. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import re +import struct +from collections import namedtuple +from typing import Any, Callable, cast, Iterator +from typing import NamedTuple, Sequence, TYPE_CHECKING + +from .. import pq +from .. import abc +from .. import sql +from .. import postgres +from ..adapt import Transformer, PyFormat, RecursiveDumper, Loader, Dumper, Buffer +from .._oids import TEXT_OID +from .._compat import cache +from .._struct import pack_len, unpack_len +from .._typeinfo import TypeInfo +from .._encodings import _as_python_identifier + +if TYPE_CHECKING: + from .._connection_base import BaseConnection + +_struct_oidlen = struct.Struct("!Ii") +_pack_oidlen = cast(Callable[[int, int], bytes], _struct_oidlen.pack) +_unpack_oidlen = cast( + Callable[[abc.Buffer, int], "tuple[int, int]"], _struct_oidlen.unpack_from +) + + +class CompositeInfo(TypeInfo): + """Manage information about a composite type.""" + + def __init__( + self, + name: str, + oid: int, + array_oid: int, + *, + regtype: str = "", + field_names: Sequence[str], + field_types: Sequence[int], + ): + super().__init__(name, oid, array_oid, regtype=regtype) + self.field_names = field_names + self.field_types = field_types + # Will be set by register() if the `factory` is a type + self.python_type: type | None = None + + @classmethod + def _get_info_query(cls, conn: BaseConnection[Any]) -> abc.Query: + return sql.SQL( + """\ +SELECT + t.typname AS name, t.oid AS oid, t.typarray AS array_oid, + t.oid::regtype::text AS regtype, + coalesce(a.fnames, '{{}}') AS field_names, + coalesce(a.ftypes, '{{}}') AS field_types +FROM pg_type t +LEFT JOIN ( + SELECT + attrelid, + array_agg(attname) AS fnames, + array_agg(atttypid) AS ftypes + FROM ( + SELECT a.attrelid, a.attname, a.atttypid + FROM pg_attribute a + JOIN pg_type t ON t.typrelid = a.attrelid + WHERE t.oid = {regtype} + AND a.attnum > 0 + AND NOT a.attisdropped + ORDER BY a.attnum + ) x + GROUP BY attrelid +) a ON a.attrelid = t.typrelid +WHERE t.oid = {regtype} +""" + ).format(regtype=cls._to_regtype(conn)) + + +class SequenceDumper(RecursiveDumper): + def _dump_sequence( + self, obj: Sequence[Any], start: bytes, end: bytes, sep: bytes + ) -> bytes: + if not obj: + return start + end + + parts: list[abc.Buffer] = [start] + + for item in obj: + if item is None: + parts.append(sep) + continue + + dumper = self._tx.get_dumper(item, PyFormat.from_pq(self.format)) + ad = dumper.dump(item) + if ad is None: + ad = b"" + elif not ad: + ad = b'""' + elif self._re_needs_quotes.search(ad): + ad = b'"' + self._re_esc.sub(rb"\1\1", ad) + b'"' + + parts.append(ad) + parts.append(sep) + + parts[-1] = end + + return b"".join(parts) + + _re_needs_quotes = re.compile(rb'[",\\\s()]') + _re_esc = re.compile(rb"([\\\"])") + + +class TupleDumper(SequenceDumper): + # Should be this, but it doesn't work + # oid = _oids.RECORD_OID + + def dump(self, obj: tuple[Any, ...]) -> Buffer | None: + return self._dump_sequence(obj, b"(", b")", b",") + + +class TupleBinaryDumper(Dumper): + format = pq.Format.BINARY + + # Subclasses must set this info + _field_types: tuple[int, ...] + + def __init__(self, cls: type, context: abc.AdaptContext | None = None): + super().__init__(cls, context) + + # Note: this class is not a RecursiveDumper because it would use the + # same Transformer of the context, which would confuse dump_sequence() + # in case the composite contains another composite. Make sure to use + # a separate Transformer instance instead. + self._tx = Transformer(context) + self._tx.set_dumper_types(self._field_types, self.format) + + nfields = len(self._field_types) + self._formats = (PyFormat.from_pq(self.format),) * nfields + + def dump(self, obj: tuple[Any, ...]) -> Buffer | None: + out = bytearray(pack_len(len(obj))) + adapted = self._tx.dump_sequence(obj, self._formats) + for i in range(len(obj)): + b = adapted[i] + oid = self._field_types[i] + if b is not None: + out += _pack_oidlen(oid, len(b)) + out += b + else: + out += _pack_oidlen(oid, -1) + + return out + + +class BaseCompositeLoader(Loader): + def __init__(self, oid: int, context: abc.AdaptContext | None = None): + super().__init__(oid, context) + self._tx = Transformer(context) + + def _parse_record(self, data: abc.Buffer) -> Iterator[bytes | None]: + """ + Split a non-empty representation of a composite type into components. + + Terminators shouldn't be used in `!data` (so that both record and range + representations can be parsed). + """ + for m in self._re_tokenize.finditer(data): + if m.group(1): + yield None + elif m.group(2) is not None: + yield self._re_undouble.sub(rb"\1", m.group(2)) + else: + yield m.group(3) + + # If the final group ended in `,` there is a final NULL in the record + # that the regexp couldn't parse. + if m and m.group().endswith(b","): + yield None + + _re_tokenize = re.compile( + rb"""(?x) + (,) # an empty token, representing NULL + | " ((?: [^"] | "")*) " ,? # or a quoted string + | ([^",)]+) ,? # or an unquoted string + """ + ) + + _re_undouble = re.compile(rb'(["\\])\1') + + +class RecordLoader(BaseCompositeLoader): + def load(self, data: abc.Buffer) -> tuple[Any, ...]: + if data == b"()": + return () + + cast = self._tx.get_loader(TEXT_OID, self.format).load + return tuple( + cast(token) if token is not None else None + for token in self._parse_record(data[1:-1]) + ) + + +class RecordBinaryLoader(Loader): + format = pq.Format.BINARY + + def __init__(self, oid: int, context: abc.AdaptContext | None = None): + super().__init__(oid, context) + self._ctx = context + # Cache a transformer for each sequence of oid found. + # Usually there will be only one, but if there is more than one + # row in the same query (in different columns, or even in different + # records), oids might differ and we'd need separate transformers. + self._txs: dict[tuple[int, ...], abc.Transformer] = {} + + def load(self, data: abc.Buffer) -> tuple[Any, ...]: + nfields = unpack_len(data, 0)[0] + offset = 4 + oids = [] + record = [] + for _ in range(nfields): + oid, length = _unpack_oidlen(data, offset) + offset += 8 + record.append(data[offset : offset + length] if length != -1 else None) + oids.append(oid) + if length >= 0: + offset += length + + key = tuple(oids) + try: + tx = self._txs[key] + except KeyError: + tx = self._txs[key] = Transformer(self._ctx) + tx.set_loader_types(oids, self.format) + + return tx.load_sequence(tuple(record)) + + +class CompositeLoader(RecordLoader): + factory: Callable[..., Any] + fields_types: list[int] + _types_set = False + + def load(self, data: abc.Buffer) -> Any: + if not self._types_set: + self._config_types(data) + self._types_set = True + + if data == b"()": + return type(self).factory() + + return type(self).factory( + *self._tx.load_sequence(tuple(self._parse_record(data[1:-1]))) + ) + + def _config_types(self, data: abc.Buffer) -> None: + self._tx.set_loader_types(self.fields_types, self.format) + + +class CompositeBinaryLoader(RecordBinaryLoader): + format = pq.Format.BINARY + factory: Callable[..., Any] + + def load(self, data: abc.Buffer) -> Any: + r = super().load(data) + return type(self).factory(*r) + + +def register_composite( + info: CompositeInfo, + context: abc.AdaptContext | None = None, + factory: Callable[..., Any] | None = None, +) -> None: + """Register the adapters to load and dump a composite type. + + :param info: The object with the information about the composite to register. + :param context: The context where to register the adapters. If `!None`, + register it globally. + :param factory: Callable to convert the sequence of attributes read from + the composite into a Python object. + + .. note:: + + Registering the adapters doesn't affect objects already created, even + if they are children of the registered context. For instance, + registering the adapter globally doesn't affect already existing + connections. + """ + + # A friendly error warning instead of an AttributeError in case fetch() + # failed and it wasn't noticed. + if not info: + raise TypeError("no info passed. Is the requested composite available?") + + # Register arrays and type info + info.register(context) + + if not factory: + factory = _nt_from_info(info) + + adapters = context.adapters if context else postgres.adapters + + # generate and register a customized text loader + loader: type[BaseCompositeLoader] + loader = _make_loader(info.name, tuple(info.field_types), factory) + adapters.register_loader(info.oid, loader) + + # generate and register a customized binary loader + loader = _make_binary_loader(info.name, factory) + adapters.register_loader(info.oid, loader) + + # If the factory is a type, create and register dumpers for it + if isinstance(factory, type): + dumper: type[Dumper] + dumper = _make_binary_dumper(info.name, info.oid, tuple(info.field_types)) + adapters.register_dumper(factory, dumper) + + # Default to the text dumper because it is more flexible + dumper = _make_dumper(info.name, info.oid) + adapters.register_dumper(factory, dumper) + + info.python_type = factory + + +def register_default_adapters(context: abc.AdaptContext) -> None: + adapters = context.adapters + adapters.register_dumper(tuple, TupleDumper) + adapters.register_loader("record", RecordLoader) + adapters.register_loader("record", RecordBinaryLoader) + + +def _nt_from_info(info: CompositeInfo) -> type[NamedTuple]: + name = _as_python_identifier(info.name) + fields = tuple(_as_python_identifier(n) for n in info.field_names) + return _make_nt(name, fields) + + +# Cache all dynamically-generated types to avoid leaks in case the types +# cannot be GC'd. + + +@cache +def _make_nt(name: str, fields: tuple[str, ...]) -> type[NamedTuple]: + return namedtuple(name, fields) # type: ignore[return-value] + + +@cache +def _make_loader( + name: str, types: tuple[int, ...], factory: Callable[..., Any] +) -> type[BaseCompositeLoader]: + return type( + f"{name.title()}Loader", + (CompositeLoader,), + {"factory": factory, "fields_types": list(types)}, + ) + + +@cache +def _make_binary_loader( + name: str, factory: Callable[..., Any] +) -> type[BaseCompositeLoader]: + return type( + f"{name.title()}BinaryLoader", (CompositeBinaryLoader,), {"factory": factory} + ) + + +@cache +def _make_dumper(name: str, oid: int) -> type[TupleDumper]: + return type(f"{name.title()}Dumper", (TupleDumper,), {"oid": oid}) + + +@cache +def _make_binary_dumper( + name: str, oid: int, field_types: tuple[int, ...] +) -> type[TupleBinaryDumper]: + return type( + f"{name.title()}BinaryDumper", + (TupleBinaryDumper,), + {"oid": oid, "_field_types": field_types}, + ) diff --git a/backend/.venv/Lib/site-packages/psycopg/types/datetime.py b/backend/.venv/Lib/site-packages/psycopg/types/datetime.py new file mode 100644 index 0000000..3d8db27 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/types/datetime.py @@ -0,0 +1,763 @@ +""" +Adapters for date/time types. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import re +import struct +from datetime import date, datetime, time, timedelta, timezone +from typing import Any, Callable, cast, TYPE_CHECKING + +from .. import _oids +from ..pq import Format +from .._tz import get_tzinfo +from ..abc import AdaptContext, DumperKey +from ..adapt import Buffer, Dumper, Loader, PyFormat +from ..errors import InterfaceError, DataError +from .._struct import pack_int4, pack_int8, unpack_int4, unpack_int8 + +if TYPE_CHECKING: + from .._connection_base import BaseConnection + +_struct_timetz = struct.Struct("!qi") # microseconds, sec tz offset +_pack_timetz = cast(Callable[[int, int], bytes], _struct_timetz.pack) +_unpack_timetz = cast(Callable[[Buffer], "tuple[int, int]"], _struct_timetz.unpack) + +_struct_interval = struct.Struct("!qii") # microseconds, days, months +_pack_interval = cast(Callable[[int, int, int], bytes], _struct_interval.pack) +_unpack_interval = cast( + Callable[[Buffer], "tuple[int, int, int]"], _struct_interval.unpack +) + +utc = timezone.utc +_pg_date_epoch_days = date(2000, 1, 1).toordinal() +_pg_datetime_epoch = datetime(2000, 1, 1) +_pg_datetimetz_epoch = datetime(2000, 1, 1, tzinfo=utc) +_py_date_min_days = date.min.toordinal() + + +class DateDumper(Dumper): + oid = _oids.DATE_OID + + def dump(self, obj: date) -> Buffer | None: + # NOTE: whatever the PostgreSQL DateStyle input format (DMY, MDY, YMD) + # the YYYY-MM-DD is always understood correctly. + return str(obj).encode() + + +class DateBinaryDumper(Dumper): + format = Format.BINARY + oid = _oids.DATE_OID + + def dump(self, obj: date) -> Buffer | None: + days = obj.toordinal() - _pg_date_epoch_days + return pack_int4(days) + + +class _BaseTimeDumper(Dumper): + def get_key(self, obj: time, format: PyFormat) -> DumperKey: + # Use (cls,) to report the need to upgrade to a dumper for timetz (the + # Frankenstein of the data types). + if not obj.tzinfo: + return self.cls + else: + return (self.cls,) + + def upgrade(self, obj: time, format: PyFormat) -> Dumper: + raise NotImplementedError + + def _get_offset(self, obj: time) -> timedelta: + offset = obj.utcoffset() + if offset is None: + raise DataError( + f"cannot calculate the offset of tzinfo '{obj.tzinfo}' without a date" + ) + return offset + + +class _BaseTimeTextDumper(_BaseTimeDumper): + def dump(self, obj: time) -> Buffer | None: + return str(obj).encode() + + +class TimeDumper(_BaseTimeTextDumper): + oid = _oids.TIME_OID + + def upgrade(self, obj: time, format: PyFormat) -> Dumper: + if not obj.tzinfo: + return self + else: + return TimeTzDumper(self.cls) + + +class TimeTzDumper(_BaseTimeTextDumper): + oid = _oids.TIMETZ_OID + + def dump(self, obj: time) -> Buffer | None: + self._get_offset(obj) + return super().dump(obj) + + +class TimeBinaryDumper(_BaseTimeDumper): + format = Format.BINARY + oid = _oids.TIME_OID + + def dump(self, obj: time) -> Buffer | None: + us = obj.microsecond + 1_000_000 * ( + obj.second + 60 * (obj.minute + 60 * obj.hour) + ) + return pack_int8(us) + + def upgrade(self, obj: time, format: PyFormat) -> Dumper: + if not obj.tzinfo: + return self + else: + return TimeTzBinaryDumper(self.cls) + + +class TimeTzBinaryDumper(_BaseTimeDumper): + format = Format.BINARY + oid = _oids.TIMETZ_OID + + def dump(self, obj: time) -> Buffer | None: + us = obj.microsecond + 1_000_000 * ( + obj.second + 60 * (obj.minute + 60 * obj.hour) + ) + off = self._get_offset(obj) + return _pack_timetz(us, -int(off.total_seconds())) + + +class _BaseDatetimeDumper(Dumper): + def get_key(self, obj: datetime, format: PyFormat) -> DumperKey: + # Use (cls,) to report the need to upgrade (downgrade, actually) to a + # dumper for naive timestamp. + if obj.tzinfo: + return self.cls + else: + return (self.cls,) + + def upgrade(self, obj: datetime, format: PyFormat) -> Dumper: + raise NotImplementedError + + +class _BaseDatetimeTextDumper(_BaseDatetimeDumper): + def dump(self, obj: datetime) -> Buffer | None: + # NOTE: whatever the PostgreSQL DateStyle input format (DMY, MDY, YMD) + # the YYYY-MM-DD is always understood correctly. + return str(obj).encode() + + +class DatetimeDumper(_BaseDatetimeTextDumper): + oid = _oids.TIMESTAMPTZ_OID + + def upgrade(self, obj: datetime, format: PyFormat) -> Dumper: + if obj.tzinfo: + return self + else: + return DatetimeNoTzDumper(self.cls) + + +class DatetimeNoTzDumper(_BaseDatetimeTextDumper): + oid = _oids.TIMESTAMP_OID + + +class DatetimeBinaryDumper(_BaseDatetimeDumper): + format = Format.BINARY + oid = _oids.TIMESTAMPTZ_OID + + def dump(self, obj: datetime) -> Buffer | None: + delta = obj - _pg_datetimetz_epoch + micros = delta.microseconds + 1_000_000 * (86_400 * delta.days + delta.seconds) + return pack_int8(micros) + + def upgrade(self, obj: datetime, format: PyFormat) -> Dumper: + if obj.tzinfo: + return self + else: + return DatetimeNoTzBinaryDumper(self.cls) + + +class DatetimeNoTzBinaryDumper(_BaseDatetimeDumper): + format = Format.BINARY + oid = _oids.TIMESTAMP_OID + + def dump(self, obj: datetime) -> Buffer | None: + delta = obj - _pg_datetime_epoch + micros = delta.microseconds + 1_000_000 * (86_400 * delta.days + delta.seconds) + return pack_int8(micros) + + +class TimedeltaDumper(Dumper): + oid = _oids.INTERVAL_OID + + def __init__(self, cls: type, context: AdaptContext | None = None): + super().__init__(cls, context) + if _get_intervalstyle(self.connection) == b"sql_standard": + self._dump_method = self._dump_sql + else: + self._dump_method = self._dump_any + + def dump(self, obj: timedelta) -> Buffer | None: + return self._dump_method(self, obj) + + @staticmethod + def _dump_any(self: TimedeltaDumper, obj: timedelta) -> bytes: + # The comma is parsed ok by PostgreSQL but it's not documented + # and it seems brittle to rely on it. CRDB doesn't consume it well. + return str(obj).encode().replace(b",", b"") + + @staticmethod + def _dump_sql(self: TimedeltaDumper, obj: timedelta) -> bytes: + # sql_standard format needs explicit signs + # otherwise -1 day 1 sec will mean -1 sec + return b"%+d day %+d second %+d microsecond" % ( + obj.days, + obj.seconds, + obj.microseconds, + ) + + +class TimedeltaBinaryDumper(Dumper): + format = Format.BINARY + oid = _oids.INTERVAL_OID + + def dump(self, obj: timedelta) -> Buffer | None: + micros = 1_000_000 * obj.seconds + obj.microseconds + return _pack_interval(micros, obj.days, 0) + + +class DateLoader(Loader): + _ORDER_YMD = 0 + _ORDER_DMY = 1 + _ORDER_MDY = 2 + + def __init__(self, oid: int, context: AdaptContext | None = None): + super().__init__(oid, context) + ds = _get_datestyle(self.connection) + if ds.startswith(b"I"): # ISO + self._order = self._ORDER_YMD + elif ds.startswith(b"G"): # German + self._order = self._ORDER_DMY + elif ds.startswith(b"S") or ds.startswith(b"P"): # SQL or Postgres + self._order = self._ORDER_DMY if ds.endswith(b"DMY") else self._ORDER_MDY + else: + raise InterfaceError(f"unexpected DateStyle: {ds.decode('ascii')}") + + def load(self, data: Buffer) -> date: + if self._order == self._ORDER_YMD: + ye = data[:4] + mo = data[5:7] + da = data[8:] + elif self._order == self._ORDER_DMY: + da = data[:2] + mo = data[3:5] + ye = data[6:] + else: + mo = data[:2] + da = data[3:5] + ye = data[6:] + + try: + return date(int(ye), int(mo), int(da)) + except ValueError as ex: + s = bytes(data).decode("utf8", "replace") + if s == "infinity" or (s and len(s.split()[0]) > 10): + raise DataError(f"date too large (after year 10K): {s!r}") from None + elif s == "-infinity" or "BC" in s: + raise DataError(f"date too small (before year 1): {s!r}") from None + else: + raise DataError(f"can't parse date {s!r}: {ex}") from None + + +class DateBinaryLoader(Loader): + format = Format.BINARY + + def load(self, data: Buffer) -> date: + days = unpack_int4(data)[0] + _pg_date_epoch_days + try: + return date.fromordinal(days) + except (ValueError, OverflowError): + if days < _py_date_min_days: + raise DataError("date too small (before year 1)") from None + else: + raise DataError("date too large (after year 10K)") from None + + +class TimeLoader(Loader): + _re_format = re.compile(rb"^(\d+):(\d+):(\d+)(?:\.(\d+))?") + + def load(self, data: Buffer) -> time: + m = self._re_format.match(data) + if not m: + s = bytes(data).decode("utf8", "replace") + raise DataError(f"can't parse time {s!r}") + + ho, mi, se, fr = m.groups() + + # Pad the fraction of second to get micros + if fr: + us = int(fr) + if len(fr) < 6: + us *= _uspad[len(fr)] + else: + us = 0 + + try: + return time(int(ho), int(mi), int(se), us) + except ValueError as e: + s = bytes(data).decode("utf8", "replace") + raise DataError(f"can't parse time {s!r}: {e}") from None + + +class TimeBinaryLoader(Loader): + format = Format.BINARY + + def load(self, data: Buffer) -> time: + val = unpack_int8(data)[0] + val, us = divmod(val, 1_000_000) + val, s = divmod(val, 60) + h, m = divmod(val, 60) + try: + return time(h, m, s, us) + except ValueError: + raise DataError(f"time not supported by Python: hour={h}") from None + + +class TimetzLoader(Loader): + _re_format = re.compile( + rb"""(?ix) + ^ + (\d+) : (\d+) : (\d+) (?: \. (\d+) )? # Time and micros + ([-+]) (\d+) (?: : (\d+) )? (?: : (\d+) )? # Timezone + $ + """ + ) + + def load(self, data: Buffer) -> time: + m = self._re_format.match(data) + if not m: + s = bytes(data).decode("utf8", "replace") + raise DataError(f"can't parse timetz {s!r}") + + ho, mi, se, fr, sgn, oh, om, os = m.groups() + + # Pad the fraction of second to get the micros + if fr: + us = int(fr) + if len(fr) < 6: + us *= _uspad[len(fr)] + else: + us = 0 + + # Calculate timezone + off = 60 * 60 * int(oh) + if om: + off += 60 * int(om) + if os: + off += int(os) + tz = timezone(timedelta(0, off if sgn == b"+" else -off)) + + try: + return time(int(ho), int(mi), int(se), us, tz) + except ValueError as e: + s = bytes(data).decode("utf8", "replace") + raise DataError(f"can't parse timetz {s!r}: {e}") from None + + +class TimetzBinaryLoader(Loader): + format = Format.BINARY + + def load(self, data: Buffer) -> time: + val, off = _unpack_timetz(data) + + val, us = divmod(val, 1_000_000) + val, s = divmod(val, 60) + h, m = divmod(val, 60) + + try: + return time(h, m, s, us, timezone(timedelta(seconds=-off))) + except ValueError: + raise DataError(f"time not supported by Python: hour={h}") from None + + +class TimestampLoader(Loader): + _re_format = re.compile( + rb"""(?ix) + ^ + (\d+) [^a-z0-9] (\d+) [^a-z0-9] (\d+) # Date + (?: T | [^a-z0-9] ) # Separator, including T + (\d+) [^a-z0-9] (\d+) [^a-z0-9] (\d+) # Time + (?: \.(\d+) )? # Micros + $ + """ + ) + _re_format_pg = re.compile( + rb"""(?ix) + ^ + [a-z]+ [^a-z0-9] # DoW, separator + (\d+|[a-z]+) [^a-z0-9] # Month or day + (\d+|[a-z]+) [^a-z0-9] # Month or day + (\d+) [^a-z0-9] (\d+) [^a-z0-9] (\d+) # Time + (?: \.(\d+) )? # Micros + [^a-z0-9] (\d+) # Year + $ + """ + ) + + _ORDER_YMD = 0 + _ORDER_DMY = 1 + _ORDER_MDY = 2 + _ORDER_PGDM = 3 + _ORDER_PGMD = 4 + + def __init__(self, oid: int, context: AdaptContext | None = None): + super().__init__(oid, context) + + ds = _get_datestyle(self.connection) + if ds.startswith(b"I"): # ISO + self._order = self._ORDER_YMD + elif ds.startswith(b"G"): # German + self._order = self._ORDER_DMY + elif ds.startswith(b"S"): # SQL + self._order = self._ORDER_DMY if ds.endswith(b"DMY") else self._ORDER_MDY + elif ds.startswith(b"P"): # Postgres + self._order = self._ORDER_PGDM if ds.endswith(b"DMY") else self._ORDER_PGMD + self._re_format = self._re_format_pg + else: + raise InterfaceError(f"unexpected DateStyle: {ds.decode('ascii')}") + + def load(self, data: Buffer) -> datetime: + m = self._re_format.match(data) + if not m: + raise _get_timestamp_load_error(self.connection, data) from None + + if self._order == self._ORDER_YMD: + ye, mo, da, ho, mi, se, fr = m.groups() + imo = int(mo) + elif self._order == self._ORDER_DMY: + da, mo, ye, ho, mi, se, fr = m.groups() + imo = int(mo) + elif self._order == self._ORDER_MDY: + mo, da, ye, ho, mi, se, fr = m.groups() + imo = int(mo) + else: + if self._order == self._ORDER_PGDM: + da, mo, ho, mi, se, fr, ye = m.groups() + else: + mo, da, ho, mi, se, fr, ye = m.groups() + try: + imo = _month_abbr[mo] + except KeyError: + s = mo.decode("utf8", "replace") + raise DataError(f"can't parse month: {s!r}") from None + + # Pad the fraction of second to get the micros + if fr: + us = int(fr) + if len(fr) < 6: + us *= _uspad[len(fr)] + else: + us = 0 + + try: + return datetime(int(ye), imo, int(da), int(ho), int(mi), int(se), us) + except ValueError as ex: + raise _get_timestamp_load_error(self.connection, data, ex) from None + + +class TimestampBinaryLoader(Loader): + format = Format.BINARY + + def load(self, data: Buffer) -> datetime: + micros = unpack_int8(data)[0] + try: + return _pg_datetime_epoch + timedelta(microseconds=micros) + except OverflowError: + if micros <= 0: + raise DataError("timestamp too small (before year 1)") from None + else: + raise DataError("timestamp too large (after year 10K)") from None + + +class TimestamptzLoader(Loader): + _re_format = re.compile( + rb"""(?ix) + ^ + (\d+) [^a-z0-9] (\d+) [^a-z0-9] (\d+) # Date + (?: T | [^a-z0-9] ) # Separator, including T + (\d+) [^a-z0-9] (\d+) [^a-z0-9] (\d+) # Time + (?: \.(\d+) )? # Micros + ([-+]) (\d+) (?: : (\d+) )? (?: : (\d+) )? # Timezone + $ + """ + ) + + def __init__(self, oid: int, context: AdaptContext | None = None): + super().__init__(oid, context) + self._timezone = get_tzinfo(self.connection.pgconn if self.connection else None) + + ds = _get_datestyle(self.connection) + if ds.startswith(b"I"): # ISO + self._load_method = self._load_iso + else: + self._load_method = self._load_notimpl + + def load(self, data: Buffer) -> datetime: + return self._load_method(self, data) + + @staticmethod + def _load_iso(self: TimestamptzLoader, data: Buffer) -> datetime: + m = self._re_format.match(data) + if not m: + raise _get_timestamp_load_error(self.connection, data) from None + + ye, mo, da, ho, mi, se, fr, sgn, oh, om, os = m.groups() + + # Pad the fraction of second to get the micros + if fr: + us = int(fr) + if len(fr) < 6: + us *= _uspad[len(fr)] + else: + us = 0 + + # Calculate timezone offset + soff = 60 * 60 * int(oh) + if om: + soff += 60 * int(om) + if os: + soff += int(os) + tzoff = timedelta(0, soff if sgn == b"+" else -soff) + + # The return value is a datetime with the timezone of the connection + # (in order to be consistent with the binary loader, which is the only + # thing it can return). So create a temporary datetime object, in utc, + # shift it by the offset parsed from the timestamp, and then move it to + # the connection timezone. + dt = None + ex: Exception + try: + dt = datetime(int(ye), int(mo), int(da), int(ho), int(mi), int(se), us, utc) + return (dt - tzoff).astimezone(self._timezone) + except OverflowError as e: + # If we have created the temporary 'dt' it means that we have a + # datetime close to max, the shift pushed it past max, overflowing. + # In this case return the datetime in a fixed offset timezone. + if dt is not None: + return dt.replace(tzinfo=timezone(tzoff)) + else: + ex = e + except ValueError as e: + ex = e + + raise _get_timestamp_load_error(self.connection, data, ex) from None + + @staticmethod + def _load_notimpl(self: TimestamptzLoader, data: Buffer) -> datetime: + s = bytes(data).decode("utf8", "replace") + ds = _get_datestyle(self.connection).decode("ascii") + raise NotImplementedError( + f"can't parse timestamptz with DateStyle {ds!r}: {s!r}" + ) + + +class TimestamptzBinaryLoader(Loader): + format = Format.BINARY + + def __init__(self, oid: int, context: AdaptContext | None = None): + super().__init__(oid, context) + self._timezone = get_tzinfo(self.connection.pgconn if self.connection else None) + + def load(self, data: Buffer) -> datetime: + micros = unpack_int8(data)[0] + try: + ts = _pg_datetimetz_epoch + timedelta(microseconds=micros) + return ts.astimezone(self._timezone) + except OverflowError: + # If we were asked about a timestamp which would overflow in UTC, + # but not in the desired timezone (e.g. datetime.max at Chicago + # timezone) we can still save the day by shifting the value by the + # timezone offset and then replacing the timezone. + if self._timezone: + utcoff = self._timezone.utcoffset( + datetime.min if micros < 0 else datetime.max + ) + if utcoff: + usoff = 1_000_000 * int(utcoff.total_seconds()) + try: + ts = _pg_datetime_epoch + timedelta(microseconds=micros + usoff) + except OverflowError: + pass # will raise downstream + else: + return ts.replace(tzinfo=self._timezone) + + if micros <= 0: + raise DataError("timestamp too small (before year 1)") from None + else: + raise DataError("timestamp too large (after year 10K)") from None + + +class IntervalLoader(Loader): + _re_interval = re.compile( + rb""" + (?: ([-+]?\d+) \s+ years? \s* )? # Years + (?: ([-+]?\d+) \s+ mons? \s* )? # Months + (?: ([-+]?\d+) \s+ days? \s* )? # Days + (?: ([-+])? (\d+) : (\d+) : (\d+ (?:\.\d+)?) # Time + )? + """, + re.VERBOSE, + ) + + def __init__(self, oid: int, context: AdaptContext | None = None): + super().__init__(oid, context) + if _get_intervalstyle(self.connection) == b"postgres": + self._load_method = self._load_postgres + else: + self._load_method = self._load_notimpl + + def load(self, data: Buffer) -> timedelta: + return self._load_method(self, data) + + @staticmethod + def _load_postgres(self: IntervalLoader, data: Buffer) -> timedelta: + m = self._re_interval.match(data) + if not m: + s = bytes(data).decode("utf8", "replace") + raise DataError(f"can't parse interval {s!r}") + + ye, mo, da, sgn, ho, mi, se = m.groups() + days = 0 + seconds = 0.0 + + if ye: + days += 365 * int(ye) + if mo: + days += 30 * int(mo) + if da: + days += int(da) + + if ho: + seconds = 3600 * int(ho) + 60 * int(mi) + float(se) + if sgn == b"-": + seconds = -seconds + + try: + return timedelta(days=days, seconds=seconds) + except OverflowError as e: + s = bytes(data).decode("utf8", "replace") + raise DataError(f"can't parse interval {s!r}: {e}") from None + + @staticmethod + def _load_notimpl(self: IntervalLoader, data: Buffer) -> timedelta: + s = bytes(data).decode("utf8", "replace") + ints = _get_intervalstyle(self.connection).decode("utf8", "replace") + raise NotImplementedError( + f"can't parse interval with IntervalStyle {ints}: {s!r}" + ) + + +class IntervalBinaryLoader(Loader): + format = Format.BINARY + + def load(self, data: Buffer) -> timedelta: + micros, days, months = _unpack_interval(data) + if months > 0: + years, months = divmod(months, 12) + days = days + 30 * months + 365 * years + elif months < 0: + years, months = divmod(-months, 12) + days = days - 30 * months - 365 * years + + try: + return timedelta(days=days, microseconds=micros) + except OverflowError as e: + raise DataError(f"can't parse interval: {e}") from None + + +def _get_datestyle(conn: BaseConnection[Any] | None) -> bytes: + if conn: + ds = conn.pgconn.parameter_status(b"DateStyle") + if ds: + return ds + + return b"ISO, DMY" + + +def _get_intervalstyle(conn: BaseConnection[Any] | None) -> bytes: + if conn: + ints = conn.pgconn.parameter_status(b"IntervalStyle") + if ints: + return ints + + return b"unknown" + + +def _get_timestamp_load_error( + conn: BaseConnection[Any] | None, data: Buffer, ex: Exception | None = None +) -> Exception: + s = bytes(data).decode("utf8", "replace") + + def is_overflow(s: str) -> bool: + if not s: + return False + + ds = _get_datestyle(conn) + if not ds.startswith(b"P"): # Postgres + return len(s.split()[0]) > 10 # date is first token + else: + return len(s.split()[-1]) > 4 # year is last token + + if s == "-infinity" or s.endswith("BC"): + return DataError("timestamp too small (before year 1): {s!r}") + elif s == "infinity" or is_overflow(s): + return DataError(f"timestamp too large (after year 10K): {s!r}") + else: + return DataError(f"can't parse timestamp {s!r}: {ex or '(unknown)'}") + + +_month_abbr = { + n: i + for i, n in enumerate(b"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(), 1) +} + +# Pad to get microseconds from a fraction of seconds +_uspad = [0, 100_000, 10_000, 1_000, 100, 10, 1] + + +def register_default_adapters(context: AdaptContext) -> None: + adapters = context.adapters + adapters.register_dumper("datetime.date", DateDumper) + adapters.register_dumper("datetime.date", DateBinaryDumper) + + # first register dumpers for 'timetz' oid, then the proper ones on time type. + adapters.register_dumper("datetime.time", TimeTzDumper) + adapters.register_dumper("datetime.time", TimeTzBinaryDumper) + adapters.register_dumper("datetime.time", TimeDumper) + adapters.register_dumper("datetime.time", TimeBinaryDumper) + + # first register dumpers for 'timestamp' oid, then the proper ones + # on the datetime type. + adapters.register_dumper("datetime.datetime", DatetimeNoTzDumper) + adapters.register_dumper("datetime.datetime", DatetimeNoTzBinaryDumper) + adapters.register_dumper("datetime.datetime", DatetimeDumper) + adapters.register_dumper("datetime.datetime", DatetimeBinaryDumper) + + adapters.register_dumper("datetime.timedelta", TimedeltaDumper) + adapters.register_dumper("datetime.timedelta", TimedeltaBinaryDumper) + + adapters.register_loader("date", DateLoader) + adapters.register_loader("date", DateBinaryLoader) + adapters.register_loader("time", TimeLoader) + adapters.register_loader("time", TimeBinaryLoader) + adapters.register_loader("timetz", TimetzLoader) + adapters.register_loader("timetz", TimetzBinaryLoader) + adapters.register_loader("timestamp", TimestampLoader) + adapters.register_loader("timestamp", TimestampBinaryLoader) + adapters.register_loader("timestamptz", TimestamptzLoader) + adapters.register_loader("timestamptz", TimestamptzBinaryLoader) + adapters.register_loader("interval", IntervalLoader) + adapters.register_loader("interval", IntervalBinaryLoader) diff --git a/backend/.venv/Lib/site-packages/psycopg/types/enum.py b/backend/.venv/Lib/site-packages/psycopg/types/enum.py new file mode 100644 index 0000000..82e7f17 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/types/enum.py @@ -0,0 +1,254 @@ +""" +Adapters for the enum type. +""" + +from __future__ import annotations + +from enum import Enum +from typing import Any, Generic, Mapping, Sequence, cast, TYPE_CHECKING + +from .. import sql +from .. import postgres +from .. import errors as e +from ..pq import Format +from ..abc import AdaptContext, Query +from ..adapt import Buffer, Dumper, Loader +from .._compat import cache, TypeAlias, TypeVar +from .._encodings import conn_encoding +from .._typeinfo import TypeInfo + +if TYPE_CHECKING: + from .._connection_base import BaseConnection + +E = TypeVar("E", bound=Enum) + +EnumDumpMap: TypeAlias = "dict[E, bytes]" +EnumLoadMap: TypeAlias = "dict[bytes, E]" +EnumMapping: TypeAlias = "Mapping[E, str] | Sequence[tuple[E, str]] | None" + +# Hashable versions +_HEnumDumpMap: TypeAlias = "tuple[tuple[E, bytes], ...]" +_HEnumLoadMap: TypeAlias = "tuple[tuple[bytes, E], ...]" + +TEXT = Format.TEXT +BINARY = Format.BINARY + + +class EnumInfo(TypeInfo): + """Manage information about an enum type.""" + + def __init__( + self, + name: str, + oid: int, + array_oid: int, + labels: Sequence[str], + ): + super().__init__(name, oid, array_oid) + self.labels = labels + # Will be set by register_enum() + self.enum: type[Enum] | None = None + + @classmethod + def _get_info_query(cls, conn: BaseConnection[Any]) -> Query: + return sql.SQL( + """\ +SELECT name, oid, array_oid, array_agg(label) AS labels +FROM ( + SELECT + t.typname AS name, t.oid AS oid, t.typarray AS array_oid, + e.enumlabel AS label + FROM pg_type t + LEFT JOIN pg_enum e + ON e.enumtypid = t.oid + WHERE t.oid = {regtype} + ORDER BY e.enumsortorder +) x +GROUP BY name, oid, array_oid +""" + ).format(regtype=cls._to_regtype(conn)) + + +class _BaseEnumLoader(Loader, Generic[E]): + """ + Loader for a specific Enum class + """ + + enum: type[E] + _load_map: EnumLoadMap[E] + + def load(self, data: Buffer) -> E: + if not isinstance(data, bytes): + data = bytes(data) + + try: + return self._load_map[data] + except KeyError: + enc = conn_encoding(self.connection) + label = data.decode(enc, "replace") + raise e.DataError( + f"bad member for enum {self.enum.__qualname__}: {label!r}" + ) + + +class _BaseEnumDumper(Dumper, Generic[E]): + """ + Dumper for a specific Enum class + """ + + enum: type[E] + _dump_map: EnumDumpMap[E] + + def dump(self, value: E) -> Buffer | None: + return self._dump_map[value] + + +class EnumDumper(Dumper): + """ + Dumper for a generic Enum class + """ + + def __init__(self, cls: type, context: AdaptContext | None = None): + super().__init__(cls, context) + self._encoding = conn_encoding(self.connection) + + def dump(self, value: E) -> Buffer | None: + return value.name.encode(self._encoding) + + +class EnumBinaryDumper(EnumDumper): + format = BINARY + + +def register_enum( + info: EnumInfo, + context: AdaptContext | None = None, + enum: type[E] | None = None, + *, + mapping: EnumMapping[E] = None, +) -> None: + """Register the adapters to load and dump a enum type. + + :param info: The object with the information about the enum to register. + :param context: The context where to register the adapters. If `!None`, + register it globally. + :param enum: Python enum type matching to the PostgreSQL one. If `!None`, + a new enum will be generated and exposed as `EnumInfo.enum`. + :param mapping: Override the mapping between `!enum` members and `!info` + labels. + """ + + if not info: + raise TypeError("no info passed. Is the requested enum available?") + + if enum is None: + enum = cast("type[E]", _make_enum(info.name, tuple(info.labels))) + + info.enum = enum + adapters = context.adapters if context else postgres.adapters + info.register(context) + + load_map = _make_load_map(info, enum, mapping, context) + + loader = _make_loader(info.name, info.enum, load_map) + adapters.register_loader(info.oid, loader) + + loader = _make_binary_loader(info.name, info.enum, load_map) + adapters.register_loader(info.oid, loader) + + dump_map = _make_dump_map(info, enum, mapping, context) + + dumper = _make_dumper(info.enum, info.oid, dump_map) + adapters.register_dumper(info.enum, dumper) + + dumper = _make_binary_dumper(info.enum, info.oid, dump_map) + adapters.register_dumper(info.enum, dumper) + + +# Cache all dynamically-generated types to avoid leaks in case the types +# cannot be GC'd. + + +@cache +def _make_enum(name: str, labels: tuple[str, ...]) -> Enum: + return Enum(name.title(), labels, module=__name__) + + +@cache +def _make_loader( + name: str, enum: type[Enum], load_map: _HEnumLoadMap[E] +) -> type[_BaseEnumLoader[E]]: + attribs = {"enum": enum, "_load_map": dict(load_map)} + return type(f"{name.title()}Loader", (_BaseEnumLoader,), attribs) + + +@cache +def _make_binary_loader( + name: str, enum: type[Enum], load_map: _HEnumLoadMap[E] +) -> type[_BaseEnumLoader[E]]: + attribs = {"enum": enum, "_load_map": dict(load_map), "format": BINARY} + return type(f"{name.title()}BinaryLoader", (_BaseEnumLoader,), attribs) + + +@cache +def _make_dumper( + enum: type[Enum], oid: int, dump_map: _HEnumDumpMap[E] +) -> type[_BaseEnumDumper[E]]: + attribs = {"enum": enum, "oid": oid, "_dump_map": dict(dump_map)} + return type(f"{enum.__name__}Dumper", (_BaseEnumDumper,), attribs) + + +@cache +def _make_binary_dumper( + enum: type[Enum], oid: int, dump_map: _HEnumDumpMap[E] +) -> type[_BaseEnumDumper[E]]: + attribs = {"enum": enum, "oid": oid, "_dump_map": dict(dump_map), "format": BINARY} + return type(f"{enum.__name__}BinaryDumper", (_BaseEnumDumper,), attribs) + + +def _make_load_map( + info: EnumInfo, enum: type[E], mapping: EnumMapping[E], context: AdaptContext | None +) -> _HEnumLoadMap[E]: + enc = conn_encoding(context.connection if context else None) + rv = [] + for label in info.labels: + try: + member = enum[label] + except KeyError: + # tolerate a missing enum, assuming it won't be used. If it is we + # will get a DataError on fetch. + pass + else: + rv.append((label.encode(enc), member)) + + if mapping: + if isinstance(mapping, Mapping): + mapping = list(mapping.items()) + + for member, label in mapping: + rv.append((label.encode(enc), member)) + + return tuple(rv) + + +def _make_dump_map( + info: EnumInfo, enum: type[E], mapping: EnumMapping[E], context: AdaptContext | None +) -> _HEnumDumpMap[E]: + enc = conn_encoding(context.connection if context else None) + rv = [] + for member in enum: + rv.append((member, member.name.encode(enc))) + + if mapping: + if isinstance(mapping, Mapping): + mapping = list(mapping.items()) + + for member, label in mapping: + rv.append((member, label.encode(enc))) + + return tuple(rv) + + +def register_default_adapters(context: AdaptContext) -> None: + context.adapters.register_dumper(Enum, EnumBinaryDumper) + context.adapters.register_dumper(Enum, EnumDumper) diff --git a/backend/.venv/Lib/site-packages/psycopg/types/hstore.py b/backend/.venv/Lib/site-packages/psycopg/types/hstore.py new file mode 100644 index 0000000..55944c1 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/types/hstore.py @@ -0,0 +1,146 @@ +""" +dict to hstore adaptation +""" + +# Copyright (C) 2021 The Psycopg Team + +from __future__ import annotations + +import re + +from .. import errors as e +from .. import postgres +from ..abc import Buffer, AdaptContext +from .._oids import TEXT_OID +from ..adapt import PyFormat, RecursiveDumper, RecursiveLoader +from .._compat import cache, TypeAlias +from .._typeinfo import TypeInfo + +_re_escape = re.compile(r'(["\\])') +_re_unescape = re.compile(r"\\(.)") + +_re_hstore = re.compile( + r""" + # hstore key: + # a string of normal or escaped chars + "((?: [^"\\] | \\. )*)" + \s*=>\s* # hstore value + (?: + NULL # the value can be null - not caught + # or a quoted string like the key + | "((?: [^"\\] | \\. )*)" + ) + (?:\s*,\s*|$) # pairs separated by comma or end of string. +""", + re.VERBOSE, +) + + +Hstore: TypeAlias = "dict[str, str | None]" + + +class BaseHstoreDumper(RecursiveDumper): + def dump(self, obj: Hstore) -> Buffer | None: + if not obj: + return b"" + + tokens: list[str] = [] + + def add_token(s: str) -> None: + tokens.append('"') + tokens.append(_re_escape.sub(r"\\\1", s)) + tokens.append('"') + + for k, v in obj.items(): + if not isinstance(k, str): + raise e.DataError("hstore keys can only be strings") + add_token(k) + + tokens.append("=>") + + if v is None: + tokens.append("NULL") + elif not isinstance(v, str): + raise e.DataError("hstore keys can only be strings") + else: + add_token(v) + + tokens.append(",") + + del tokens[-1] + data = "".join(tokens) + dumper = self._tx.get_dumper(data, PyFormat.TEXT) + return dumper.dump(data) + + +class HstoreLoader(RecursiveLoader): + def load(self, data: Buffer) -> Hstore: + loader = self._tx.get_loader(TEXT_OID, self.format) + s: str = loader.load(data) + + rv: Hstore = {} + start = 0 + for m in _re_hstore.finditer(s): + if m is None or m.start() != start: + raise e.DataError(f"error parsing hstore pair at char {start}") + k = _re_unescape.sub(r"\1", m.group(1)) + v = m.group(2) + if v is not None: + v = _re_unescape.sub(r"\1", v) + + rv[k] = v + start = m.end() + + if start < len(s): + raise e.DataError(f"error parsing hstore: unparsed data after char {start}") + + return rv + + +def register_hstore(info: TypeInfo, context: AdaptContext | None = None) -> None: + """Register the adapters to load and dump hstore. + + :param info: The object with the information about the hstore type. + :param context: The context where to register the adapters. If `!None`, + register it globally. + + .. note:: + + Registering the adapters doesn't affect objects already created, even + if they are children of the registered context. For instance, + registering the adapter globally doesn't affect already existing + connections. + """ + # A friendly error warning instead of an AttributeError in case fetch() + # failed and it wasn't noticed. + if not info: + raise TypeError("no info passed. Is the 'hstore' extension loaded?") + + # Register arrays and type info + info.register(context) + + adapters = context.adapters if context else postgres.adapters + + # Generate and register a customized text dumper + adapters.register_dumper(dict, _make_hstore_dumper(info.oid)) + + # register the text loader on the oid + adapters.register_loader(info.oid, HstoreLoader) + + +# Cache all dynamically-generated types to avoid leaks in case the types +# cannot be GC'd. + + +@cache +def _make_hstore_dumper(oid_in: int) -> type[BaseHstoreDumper]: + """ + Return an hstore dumper class configured using `oid_in`. + + Avoid to create new classes if the oid configured is the same. + """ + + class HstoreDumper(BaseHstoreDumper): + oid = oid_in + + return HstoreDumper diff --git a/backend/.venv/Lib/site-packages/psycopg/types/json.py b/backend/.venv/Lib/site-packages/psycopg/types/json.py new file mode 100644 index 0000000..56ac234 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/types/json.py @@ -0,0 +1,253 @@ +""" +Adapters for JSON types. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import json +from typing import Any, Callable + +from .. import abc +from .. import _oids +from .. import errors as e +from ..pq import Format +from ..adapt import Buffer, Dumper, Loader, PyFormat, AdaptersMap +from ..errors import DataError +from .._compat import cache, TypeAlias + +JsonDumpsFunction: TypeAlias = Callable[[Any], "str | bytes"] +JsonLoadsFunction: TypeAlias = Callable[["str | bytes"], Any] + + +def set_json_dumps( + dumps: JsonDumpsFunction, context: abc.AdaptContext | None = None +) -> None: + """ + Set the JSON serialisation function to store JSON objects in the database. + + :param dumps: The dump function to use. + :type dumps: `!Callable[[Any], str]` + :param context: Where to use the `!dumps` function. If not specified, use it + globally. + :type context: `~psycopg.Connection` or `~psycopg.Cursor` + + By default dumping JSON uses the builtin `json.dumps`. You can override + it to use a different JSON library or to use customised arguments. + + If the `Json` wrapper specified a `!dumps` function, use it in precedence + of the one set by this function. + """ + if context is None: + # If changing load function globally, just change the default on the + # global class + _JsonDumper._dumps = dumps + else: + adapters = context.adapters + + # If the scope is smaller than global, create subclassess and register + # them in the appropriate scope. + grid = [ + (Json, PyFormat.BINARY), + (Json, PyFormat.TEXT), + (Jsonb, PyFormat.BINARY), + (Jsonb, PyFormat.TEXT), + ] + for wrapper, format in grid: + base = _get_current_dumper(adapters, wrapper, format) + dumper = _make_dumper(base, dumps) + adapters.register_dumper(wrapper, dumper) + + +def set_json_loads( + loads: JsonLoadsFunction, context: abc.AdaptContext | None = None +) -> None: + """ + Set the JSON parsing function to fetch JSON objects from the database. + + :param loads: The load function to use. + :type loads: `!Callable[[bytes], Any]` + :param context: Where to use the `!loads` function. If not specified, use + it globally. + :type context: `~psycopg.Connection` or `~psycopg.Cursor` + + By default loading JSON uses the builtin `json.loads`. You can override + it to use a different JSON library or to use customised arguments. + """ + if context is None: + # If changing load function globally, just change the default on the + # global class + _JsonLoader._loads = loads + else: + # If the scope is smaller than global, create subclassess and register + # them in the appropriate scope. + grid = [ + ("json", JsonLoader), + ("json", JsonBinaryLoader), + ("jsonb", JsonbLoader), + ("jsonb", JsonbBinaryLoader), + ] + for tname, base in grid: + loader = _make_loader(base, loads) + context.adapters.register_loader(tname, loader) + + +# Cache all dynamically-generated types to avoid leaks in case the types +# cannot be GC'd. + + +@cache +def _make_dumper(base: type[abc.Dumper], dumps: JsonDumpsFunction) -> type[abc.Dumper]: + name = base.__name__ + if not name.startswith("Custom"): + name = f"Custom{name}" + return type(name, (base,), {"_dumps": dumps}) + + +@cache +def _make_loader(base: type[Loader], loads: JsonLoadsFunction) -> type[Loader]: + name = base.__name__ + if not name.startswith("Custom"): + name = f"Custom{name}" + return type(name, (base,), {"_loads": loads}) + + +class _JsonWrapper: + __slots__ = ("obj", "dumps") + + def __init__(self, obj: Any, dumps: JsonDumpsFunction | None = None): + self.obj = obj + self.dumps = dumps + + def __repr__(self) -> str: + sobj = repr(self.obj) + if len(sobj) > 40: + sobj = f"{sobj[:35]} ... ({len(sobj)} chars)" + return f"{self.__class__.__name__}({sobj})" + + +class Json(_JsonWrapper): + __slots__ = () + + +class Jsonb(_JsonWrapper): + __slots__ = () + + +class _JsonDumper(Dumper): + # The globally used JSON dumps() function. It can be changed globally (by + # set_json_dumps) or by a subclass. + _dumps: JsonDumpsFunction = json.dumps + + def __init__(self, cls: type, context: abc.AdaptContext | None = None): + super().__init__(cls, context) + self.dumps = self.__class__._dumps + + def dump(self, obj: Any) -> Buffer | None: + if isinstance(obj, _JsonWrapper): + dumps = obj.dumps or self.dumps + obj = obj.obj + else: + dumps = self.dumps + data = dumps(obj) + if isinstance(data, str): + return data.encode() + return data + + +class JsonDumper(_JsonDumper): + oid = _oids.JSON_OID + + +class JsonBinaryDumper(_JsonDumper): + format = Format.BINARY + oid = _oids.JSON_OID + + +class JsonbDumper(_JsonDumper): + oid = _oids.JSONB_OID + + +class JsonbBinaryDumper(_JsonDumper): + format = Format.BINARY + oid = _oids.JSONB_OID + + def dump(self, obj: Any) -> Buffer | None: + obj_bytes = super().dump(obj) + if obj_bytes is not None: + return b"\x01" + obj_bytes + else: + return None + + +class _JsonLoader(Loader): + # The globally used JSON loads() function. It can be changed globally (by + # set_json_loads) or by a subclass. + _loads: JsonLoadsFunction = json.loads + + def __init__(self, oid: int, context: abc.AdaptContext | None = None): + super().__init__(oid, context) + self.loads = self.__class__._loads + + def load(self, data: Buffer) -> Any: + # json.loads() cannot work on memoryview. + if not isinstance(data, bytes): + data = bytes(data) + return self.loads(data) + + +class JsonLoader(_JsonLoader): + pass + + +class JsonbLoader(_JsonLoader): + pass + + +class JsonBinaryLoader(_JsonLoader): + format = Format.BINARY + + +class JsonbBinaryLoader(_JsonLoader): + format = Format.BINARY + + def load(self, data: Buffer) -> Any: + if data and data[0] != 1: + raise DataError("unknown jsonb binary format: {data[0]}") + data = data[1:] + if not isinstance(data, bytes): + data = bytes(data) + return self.loads(data) + + +def _get_current_dumper( + adapters: AdaptersMap, cls: type, format: PyFormat +) -> type[abc.Dumper]: + try: + return adapters.get_dumper(cls, format) + except e.ProgrammingError: + return _default_dumpers[cls, format] + + +_default_dumpers: dict[tuple[type[_JsonWrapper], PyFormat], type[Dumper]] = { + (Json, PyFormat.BINARY): JsonBinaryDumper, + (Json, PyFormat.TEXT): JsonDumper, + (Jsonb, PyFormat.BINARY): JsonbBinaryDumper, + (Jsonb, PyFormat.TEXT): JsonDumper, +} + + +def register_default_adapters(context: abc.AdaptContext) -> None: + adapters = context.adapters + + # Currently json binary format is nothing different than text, maybe with + # an extra memcopy we can avoid. + adapters.register_dumper(Json, JsonBinaryDumper) + adapters.register_dumper(Json, JsonDumper) + adapters.register_dumper(Jsonb, JsonbBinaryDumper) + adapters.register_dumper(Jsonb, JsonbDumper) + adapters.register_loader("json", JsonLoader) + adapters.register_loader("jsonb", JsonbLoader) + adapters.register_loader("json", JsonBinaryLoader) + adapters.register_loader("jsonb", JsonbBinaryLoader) diff --git a/backend/.venv/Lib/site-packages/psycopg/types/multirange.py b/backend/.venv/Lib/site-packages/psycopg/types/multirange.py new file mode 100644 index 0000000..1bf98ed --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/types/multirange.py @@ -0,0 +1,561 @@ +""" +Support for multirange types adaptation. +""" + +# Copyright (C) 2021 The Psycopg Team + +from __future__ import annotations + +from decimal import Decimal +from typing import Any, Generic, Iterable, MutableSequence, overload, TYPE_CHECKING +from datetime import date, datetime + +from .. import sql +from .. import _oids +from .. import errors as e +from .. import postgres +from ..pq import Format +from ..abc import AdaptContext, Buffer, Dumper, DumperKey, Query +from ..adapt import RecursiveDumper, RecursiveLoader, PyFormat +from .._oids import INVALID_OID, TEXT_OID +from .._compat import cache +from .._struct import pack_len, unpack_len +from .._typeinfo import TypeInfo, TypesRegistry + +from .range import Range, T, load_range_text, load_range_binary +from .range import dump_range_text, dump_range_binary, fail_dump + +if TYPE_CHECKING: + from .._connection_base import BaseConnection + + +class MultirangeInfo(TypeInfo): + """Manage information about a multirange type.""" + + def __init__( + self, + name: str, + oid: int, + array_oid: int, + *, + regtype: str = "", + range_oid: int, + subtype_oid: int, + ): + super().__init__(name, oid, array_oid, regtype=regtype) + self.range_oid = range_oid + self.subtype_oid = subtype_oid + + @classmethod + def _get_info_query(cls, conn: BaseConnection[Any]) -> Query: + if conn.info.server_version < 140000: + raise e.NotSupportedError( + "multirange types are only available from PostgreSQL 14" + ) + return sql.SQL( + """\ +SELECT t.typname AS name, t.oid AS oid, t.typarray AS array_oid, + t.oid::regtype::text AS regtype, + r.rngtypid AS range_oid, r.rngsubtype AS subtype_oid +FROM pg_type t +JOIN pg_range r ON t.oid = r.rngmultitypid +WHERE t.oid = {regtype} +""" + ).format(regtype=cls._to_regtype(conn)) + + def _added(self, registry: TypesRegistry) -> None: + # Map multiranges ranges and subtypes to info + registry._registry[MultirangeInfo, self.range_oid] = self + registry._registry[MultirangeInfo, self.subtype_oid] = self + + +class Multirange(MutableSequence[Range[T]]): + """Python representation for a PostgreSQL multirange type. + + :param items: Sequence of ranges to initialise the object. + """ + + def __init__(self, items: Iterable[Range[T]] = ()): + self._ranges: list[Range[T]] = list(map(self._check_type, items)) + + def _check_type(self, item: Any) -> Range[Any]: + if not isinstance(item, Range): + raise TypeError( + f"Multirange is a sequence of Range, got {type(item).__name__}" + ) + return item + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self._ranges!r})" + + def __str__(self) -> str: + return f"{{{', '.join(map(str, self._ranges))}}}" + + @overload + def __getitem__(self, index: int) -> Range[T]: ... + + @overload + def __getitem__(self, index: slice) -> Multirange[T]: ... + + def __getitem__(self, index: int | slice) -> Range[T] | Multirange[T]: + if isinstance(index, int): + return self._ranges[index] + else: + return Multirange(self._ranges[index]) + + def __len__(self) -> int: + return len(self._ranges) + + @overload + def __setitem__(self, index: int, value: Range[T]) -> None: ... + + @overload + def __setitem__(self, index: slice, value: Iterable[Range[T]]) -> None: ... + + def __setitem__( + self, index: int | slice, value: Range[T] | Iterable[Range[T]] + ) -> None: + if isinstance(index, int): + self._check_type(value) + self._ranges[index] = self._check_type(value) + elif not isinstance(value, Iterable): + raise TypeError("can only assign an iterable") + else: + value = map(self._check_type, value) + self._ranges[index] = value + + def __delitem__(self, index: int | slice) -> None: + del self._ranges[index] + + def insert(self, index: int, value: Range[T]) -> None: + self._ranges.insert(index, self._check_type(value)) + + def __eq__(self, other: Any) -> bool: + if not isinstance(other, Multirange): + return False + return self._ranges == other._ranges + + # Order is arbitrary but consistent + + def __lt__(self, other: Any) -> bool: + if not isinstance(other, Multirange): + return NotImplemented + return self._ranges < other._ranges + + def __le__(self, other: Any) -> bool: + return self == other or self < other # type: ignore + + def __gt__(self, other: Any) -> bool: + if not isinstance(other, Multirange): + return NotImplemented + return self._ranges > other._ranges + + def __ge__(self, other: Any) -> bool: + return self == other or self > other # type: ignore + + +# Subclasses to specify a specific subtype. Usually not needed + + +class Int4Multirange(Multirange[int]): + pass + + +class Int8Multirange(Multirange[int]): + pass + + +class NumericMultirange(Multirange[Decimal]): + pass + + +class DateMultirange(Multirange[date]): + pass + + +class TimestampMultirange(Multirange[datetime]): + pass + + +class TimestamptzMultirange(Multirange[datetime]): + pass + + +class BaseMultirangeDumper(RecursiveDumper): + def __init__(self, cls: type, context: AdaptContext | None = None): + super().__init__(cls, context) + self.sub_dumper: Dumper | None = None + self._adapt_format = PyFormat.from_pq(self.format) + + def get_key(self, obj: Multirange[Any], format: PyFormat) -> DumperKey: + # If we are a subclass whose oid is specified we don't need upgrade + if self.cls is not Multirange: + return self.cls + + item = self._get_item(obj) + if item is not None: + sd = self._tx.get_dumper(item, self._adapt_format) + return (self.cls, sd.get_key(item, format)) + else: + return (self.cls,) + + def upgrade(self, obj: Multirange[Any], format: PyFormat) -> BaseMultirangeDumper: + # If we are a subclass whose oid is specified we don't need upgrade + if self.cls is not Multirange: + return self + + item = self._get_item(obj) + if item is None: + return self + + dumper: BaseMultirangeDumper + if type(item) is int: + # postgres won't cast int4range -> int8range so we must use + # text format and unknown oid here + sd = self._tx.get_dumper(item, PyFormat.TEXT) + dumper = MultirangeDumper(self.cls, self._tx) + dumper.sub_dumper = sd + dumper.oid = INVALID_OID + return dumper + + sd = self._tx.get_dumper(item, format) + dumper = type(self)(self.cls, self._tx) + dumper.sub_dumper = sd + if sd.oid == INVALID_OID and isinstance(item, str): + # Work around the normal mapping where text is dumped as unknown + dumper.oid = self._get_multirange_oid(TEXT_OID) + else: + dumper.oid = self._get_multirange_oid(sd.oid) + + return dumper + + def _get_item(self, obj: Multirange[Any]) -> Any: + """ + Return a member representative of the multirange + """ + for r in obj: + if r.lower is not None: + return r.lower + if r.upper is not None: + return r.upper + return None + + def _get_multirange_oid(self, sub_oid: int) -> int: + """ + Return the oid of the range from the oid of its elements. + """ + info = self._tx.adapters.types.get_by_subtype(MultirangeInfo, sub_oid) + return info.oid if info else INVALID_OID + + +class MultirangeDumper(BaseMultirangeDumper): + """ + Dumper for multirange types. + + The dumper can upgrade to one specific for a different range type. + """ + + def dump(self, obj: Multirange[Any]) -> Buffer | None: + if not obj: + return b"{}" + + item = self._get_item(obj) + if item is not None: + dump = self._tx.get_dumper(item, self._adapt_format).dump + else: + dump = fail_dump + + out: list[Buffer] = [b"{"] + for r in obj: + out.append(dump_range_text(r, dump)) + out.append(b",") + out[-1] = b"}" + return b"".join(out) + + +class MultirangeBinaryDumper(BaseMultirangeDumper): + format = Format.BINARY + + def dump(self, obj: Multirange[Any]) -> Buffer | None: + item = self._get_item(obj) + if item is not None: + dump = self._tx.get_dumper(item, self._adapt_format).dump + else: + dump = fail_dump + + out: list[Buffer] = [pack_len(len(obj))] + for r in obj: + data = dump_range_binary(r, dump) + out.append(pack_len(len(data))) + out.append(data) + return b"".join(out) + + +class BaseMultirangeLoader(RecursiveLoader, Generic[T]): + subtype_oid: int + + def __init__(self, oid: int, context: AdaptContext | None = None): + super().__init__(oid, context) + self._load = self._tx.get_loader(self.subtype_oid, format=self.format).load + + +class MultirangeLoader(BaseMultirangeLoader[T]): + def load(self, data: Buffer) -> Multirange[T]: + if not data or data[0] != _START_INT: + raise e.DataError( + "malformed multirange starting with" + f" {bytes(data[:1]).decode('utf8', 'replace')}" + ) + + out = Multirange[T]() + if data == b"{}": + return out + + pos = 1 + data = data[pos:] + try: + while True: + r, pos = load_range_text(data, self._load) + out.append(r) + + sep = data[pos] # can raise IndexError + if sep == _SEP_INT: + data = data[pos + 1 :] + continue + elif sep == _END_INT: + if len(data) == pos + 1: + return out + else: + raise e.DataError( + "malformed multirange: data after closing brace" + ) + else: + raise e.DataError( + f"malformed multirange: found unexpected {chr(sep)}" + ) + + except IndexError: + raise e.DataError("malformed multirange: separator missing") + + return out + + +_SEP_INT = ord(",") +_START_INT = ord("{") +_END_INT = ord("}") + + +class MultirangeBinaryLoader(BaseMultirangeLoader[T]): + format = Format.BINARY + + def load(self, data: Buffer) -> Multirange[T]: + nelems = unpack_len(data, 0)[0] + pos = 4 + out = Multirange[T]() + for i in range(nelems): + length = unpack_len(data, pos)[0] + pos += 4 + out.append(load_range_binary(data[pos : pos + length], self._load)) + pos += length + + if pos != len(data): + raise e.DataError("unexpected trailing data in multirange") + + return out + + +def register_multirange( + info: MultirangeInfo, context: AdaptContext | None = None +) -> None: + """Register the adapters to load and dump a multirange type. + + :param info: The object with the information about the range to register. + :param context: The context where to register the adapters. If `!None`, + register it globally. + + Register loaders so that loading data of this type will result in a `Range` + with bounds parsed as the right subtype. + + .. note:: + + Registering the adapters doesn't affect objects already created, even + if they are children of the registered context. For instance, + registering the adapter globally doesn't affect already existing + connections. + """ + # A friendly error warning instead of an AttributeError in case fetch() + # failed and it wasn't noticed. + if not info: + raise TypeError("no info passed. Is the requested multirange available?") + + # Register arrays and type info + info.register(context) + + adapters = context.adapters if context else postgres.adapters + + # generate and register a customized text loader + loader: type[BaseMultirangeLoader[Any]] + loader = _make_loader(info.name, info.subtype_oid) + adapters.register_loader(info.oid, loader) + + # generate and register a customized binary loader + loader = _make_binary_loader(info.name, info.subtype_oid) + adapters.register_loader(info.oid, loader) + + +# Cache all dynamically-generated types to avoid leaks in case the types +# cannot be GC'd. + + +@cache +def _make_loader(name: str, oid: int) -> type[MultirangeLoader[Any]]: + return type(f"{name.title()}Loader", (MultirangeLoader,), {"subtype_oid": oid}) + + +@cache +def _make_binary_loader(name: str, oid: int) -> type[MultirangeBinaryLoader[Any]]: + return type( + f"{name.title()}BinaryLoader", (MultirangeBinaryLoader,), {"subtype_oid": oid} + ) + + +# Text dumpers for builtin multirange types wrappers +# These are registered on specific subtypes so that the upgrade mechanism +# doesn't kick in. + + +class Int4MultirangeDumper(MultirangeDumper): + oid = _oids.INT4MULTIRANGE_OID + + +class Int8MultirangeDumper(MultirangeDumper): + oid = _oids.INT8MULTIRANGE_OID + + +class NumericMultirangeDumper(MultirangeDumper): + oid = _oids.NUMMULTIRANGE_OID + + +class DateMultirangeDumper(MultirangeDumper): + oid = _oids.DATEMULTIRANGE_OID + + +class TimestampMultirangeDumper(MultirangeDumper): + oid = _oids.TSMULTIRANGE_OID + + +class TimestamptzMultirangeDumper(MultirangeDumper): + oid = _oids.TSTZMULTIRANGE_OID + + +# Binary dumpers for builtin multirange types wrappers +# These are registered on specific subtypes so that the upgrade mechanism +# doesn't kick in. + + +class Int4MultirangeBinaryDumper(MultirangeBinaryDumper): + oid = _oids.INT4MULTIRANGE_OID + + +class Int8MultirangeBinaryDumper(MultirangeBinaryDumper): + oid = _oids.INT8MULTIRANGE_OID + + +class NumericMultirangeBinaryDumper(MultirangeBinaryDumper): + oid = _oids.NUMMULTIRANGE_OID + + +class DateMultirangeBinaryDumper(MultirangeBinaryDumper): + oid = _oids.DATEMULTIRANGE_OID + + +class TimestampMultirangeBinaryDumper(MultirangeBinaryDumper): + oid = _oids.TSMULTIRANGE_OID + + +class TimestamptzMultirangeBinaryDumper(MultirangeBinaryDumper): + oid = _oids.TSTZMULTIRANGE_OID + + +# Text loaders for builtin multirange types + + +class Int4MultirangeLoader(MultirangeLoader[int]): + subtype_oid = _oids.INT4_OID + + +class Int8MultirangeLoader(MultirangeLoader[int]): + subtype_oid = _oids.INT8_OID + + +class NumericMultirangeLoader(MultirangeLoader[Decimal]): + subtype_oid = _oids.NUMERIC_OID + + +class DateMultirangeLoader(MultirangeLoader[date]): + subtype_oid = _oids.DATE_OID + + +class TimestampMultirangeLoader(MultirangeLoader[datetime]): + subtype_oid = _oids.TIMESTAMP_OID + + +class TimestampTZMultirangeLoader(MultirangeLoader[datetime]): + subtype_oid = _oids.TIMESTAMPTZ_OID + + +# Binary loaders for builtin multirange types + + +class Int4MultirangeBinaryLoader(MultirangeBinaryLoader[int]): + subtype_oid = _oids.INT4_OID + + +class Int8MultirangeBinaryLoader(MultirangeBinaryLoader[int]): + subtype_oid = _oids.INT8_OID + + +class NumericMultirangeBinaryLoader(MultirangeBinaryLoader[Decimal]): + subtype_oid = _oids.NUMERIC_OID + + +class DateMultirangeBinaryLoader(MultirangeBinaryLoader[date]): + subtype_oid = _oids.DATE_OID + + +class TimestampMultirangeBinaryLoader(MultirangeBinaryLoader[datetime]): + subtype_oid = _oids.TIMESTAMP_OID + + +class TimestampTZMultirangeBinaryLoader(MultirangeBinaryLoader[datetime]): + subtype_oid = _oids.TIMESTAMPTZ_OID + + +def register_default_adapters(context: AdaptContext) -> None: + adapters = context.adapters + adapters.register_dumper(Multirange, MultirangeBinaryDumper) + adapters.register_dumper(Multirange, MultirangeDumper) + adapters.register_dumper(Int4Multirange, Int4MultirangeDumper) + adapters.register_dumper(Int8Multirange, Int8MultirangeDumper) + adapters.register_dumper(NumericMultirange, NumericMultirangeDumper) + adapters.register_dumper(DateMultirange, DateMultirangeDumper) + adapters.register_dumper(TimestampMultirange, TimestampMultirangeDumper) + adapters.register_dumper(TimestamptzMultirange, TimestamptzMultirangeDumper) + adapters.register_dumper(Int4Multirange, Int4MultirangeBinaryDumper) + adapters.register_dumper(Int8Multirange, Int8MultirangeBinaryDumper) + adapters.register_dumper(NumericMultirange, NumericMultirangeBinaryDumper) + adapters.register_dumper(DateMultirange, DateMultirangeBinaryDumper) + adapters.register_dumper(TimestampMultirange, TimestampMultirangeBinaryDumper) + adapters.register_dumper(TimestamptzMultirange, TimestamptzMultirangeBinaryDumper) + adapters.register_loader("int4multirange", Int4MultirangeLoader) + adapters.register_loader("int8multirange", Int8MultirangeLoader) + adapters.register_loader("nummultirange", NumericMultirangeLoader) + adapters.register_loader("datemultirange", DateMultirangeLoader) + adapters.register_loader("tsmultirange", TimestampMultirangeLoader) + adapters.register_loader("tstzmultirange", TimestampTZMultirangeLoader) + adapters.register_loader("int4multirange", Int4MultirangeBinaryLoader) + adapters.register_loader("int8multirange", Int8MultirangeBinaryLoader) + adapters.register_loader("nummultirange", NumericMultirangeBinaryLoader) + adapters.register_loader("datemultirange", DateMultirangeBinaryLoader) + adapters.register_loader("tsmultirange", TimestampMultirangeBinaryLoader) + adapters.register_loader("tstzmultirange", TimestampTZMultirangeBinaryLoader) diff --git a/backend/.venv/Lib/site-packages/psycopg/types/net.py b/backend/.venv/Lib/site-packages/psycopg/types/net.py new file mode 100644 index 0000000..a04aed0 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/types/net.py @@ -0,0 +1,203 @@ +""" +Adapters for network types. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +from typing import Callable, TYPE_CHECKING + +from .. import _oids +from ..pq import Format +from ..abc import AdaptContext +from ..adapt import Buffer, Dumper, Loader +from .._compat import TypeAlias + +if TYPE_CHECKING: + import ipaddress + +Address: TypeAlias = "ipaddress.IPv4Address | ipaddress.IPv6Address" +Interface: TypeAlias = "ipaddress.IPv4Interface | ipaddress.IPv6Interface" +Network: TypeAlias = "ipaddress.IPv4Network | ipaddress.IPv6Network" + +# These objects will be imported lazily +ip_address: Callable[[str], Address] = None # type: ignore[assignment] +ip_interface: Callable[[str], Interface] = None # type: ignore[assignment] +ip_network: Callable[[str], Network] = None # type: ignore[assignment] +IPv4Address: type[ipaddress.IPv4Address] = None # type: ignore[assignment] +IPv6Address: type[ipaddress.IPv6Address] = None # type: ignore[assignment] +IPv4Interface: type[ipaddress.IPv4Interface] = None # type: ignore[assignment] +IPv6Interface: type[ipaddress.IPv6Interface] = None # type: ignore[assignment] +IPv4Network: type[ipaddress.IPv4Network] = None # type: ignore[assignment] +IPv6Network: type[ipaddress.IPv6Network] = None # type: ignore[assignment] + +PGSQL_AF_INET = 2 +PGSQL_AF_INET6 = 3 +IPV4_PREFIXLEN = 32 +IPV6_PREFIXLEN = 128 + + +class _LazyIpaddress: + def _ensure_module(self) -> None: + global ip_address, ip_interface, ip_network + global IPv4Address, IPv6Address, IPv4Interface, IPv6Interface + global IPv4Network, IPv6Network + + if ip_address is None: + from ipaddress import ip_address, ip_interface, ip_network + from ipaddress import IPv4Address, IPv6Address + from ipaddress import IPv4Interface, IPv6Interface + from ipaddress import IPv4Network, IPv6Network + + +class InterfaceDumper(Dumper): + oid = _oids.INET_OID + + def dump(self, obj: Interface) -> Buffer | None: + return str(obj).encode() + + +class NetworkDumper(Dumper): + oid = _oids.CIDR_OID + + def dump(self, obj: Network) -> Buffer | None: + return str(obj).encode() + + +class _AIBinaryDumper(Dumper): + format = Format.BINARY + oid = _oids.INET_OID + + +class AddressBinaryDumper(_AIBinaryDumper): + def dump(self, obj: Address) -> Buffer | None: + packed = obj.packed + family = PGSQL_AF_INET if obj.version == 4 else PGSQL_AF_INET6 + head = bytes((family, obj.max_prefixlen, 0, len(packed))) + return head + packed + + +class InterfaceBinaryDumper(_AIBinaryDumper): + def dump(self, obj: Interface) -> Buffer | None: + packed = obj.packed + family = PGSQL_AF_INET if obj.version == 4 else PGSQL_AF_INET6 + head = bytes((family, obj.network.prefixlen, 0, len(packed))) + return head + packed + + +class InetBinaryDumper(_AIBinaryDumper, _LazyIpaddress): + """Either an address or an interface to inet + + Used when looking up by oid. + """ + + def __init__(self, cls: type, context: AdaptContext | None = None): + super().__init__(cls, context) + self._ensure_module() + + def dump(self, obj: Address | Interface) -> Buffer | None: + packed = obj.packed + family = PGSQL_AF_INET if obj.version == 4 else PGSQL_AF_INET6 + if isinstance(obj, (IPv4Interface, IPv6Interface)): + prefixlen = obj.network.prefixlen + else: + prefixlen = obj.max_prefixlen + + head = bytes((family, prefixlen, 0, len(packed))) + return head + packed + + +class NetworkBinaryDumper(Dumper): + format = Format.BINARY + oid = _oids.CIDR_OID + + def dump(self, obj: Network) -> Buffer | None: + packed = obj.network_address.packed + family = PGSQL_AF_INET if obj.version == 4 else PGSQL_AF_INET6 + head = bytes((family, obj.prefixlen, 1, len(packed))) + return head + packed + + +class _LazyIpaddressLoader(Loader, _LazyIpaddress): + def __init__(self, oid: int, context: AdaptContext | None = None): + super().__init__(oid, context) + self._ensure_module() + + +class InetLoader(_LazyIpaddressLoader): + def load(self, data: Buffer) -> Address | Interface: + if isinstance(data, memoryview): + data = bytes(data) + + if b"/" in data: + return ip_interface(data.decode()) + else: + return ip_address(data.decode()) + + +class InetBinaryLoader(_LazyIpaddressLoader): + format = Format.BINARY + + def load(self, data: Buffer) -> Address | Interface: + if isinstance(data, memoryview): + data = bytes(data) + + prefix = data[1] + packed = data[4:] + if data[0] == PGSQL_AF_INET: + if prefix == IPV4_PREFIXLEN: + return IPv4Address(packed) + else: + return IPv4Interface((packed, prefix)) + else: + if prefix == IPV6_PREFIXLEN: + return IPv6Address(packed) + else: + return IPv6Interface((packed, prefix)) + + +class CidrLoader(_LazyIpaddressLoader): + def load(self, data: Buffer) -> Network: + if isinstance(data, memoryview): + data = bytes(data) + + return ip_network(data.decode()) + + +class CidrBinaryLoader(_LazyIpaddressLoader): + format = Format.BINARY + + def load(self, data: Buffer) -> Network: + if isinstance(data, memoryview): + data = bytes(data) + + prefix = data[1] + packed = data[4:] + if data[0] == PGSQL_AF_INET: + return IPv4Network((packed, prefix)) + else: + return IPv6Network((packed, prefix)) + + return ip_network(data.decode()) + + +def register_default_adapters(context: AdaptContext) -> None: + adapters = context.adapters + adapters.register_dumper("ipaddress.IPv4Address", InterfaceDumper) + adapters.register_dumper("ipaddress.IPv6Address", InterfaceDumper) + adapters.register_dumper("ipaddress.IPv4Interface", InterfaceDumper) + adapters.register_dumper("ipaddress.IPv6Interface", InterfaceDumper) + adapters.register_dumper("ipaddress.IPv4Network", NetworkDumper) + adapters.register_dumper("ipaddress.IPv6Network", NetworkDumper) + adapters.register_dumper("ipaddress.IPv4Address", AddressBinaryDumper) + adapters.register_dumper("ipaddress.IPv6Address", AddressBinaryDumper) + adapters.register_dumper("ipaddress.IPv4Interface", InterfaceBinaryDumper) + adapters.register_dumper("ipaddress.IPv6Interface", InterfaceBinaryDumper) + adapters.register_dumper("ipaddress.IPv4Network", NetworkBinaryDumper) + adapters.register_dumper("ipaddress.IPv6Network", NetworkBinaryDumper) + adapters.register_dumper(None, InetBinaryDumper) + adapters.register_loader("inet", InetLoader) + adapters.register_loader("inet", InetBinaryLoader) + adapters.register_loader("cidr", CidrLoader) + adapters.register_loader("cidr", CidrBinaryLoader) diff --git a/backend/.venv/Lib/site-packages/psycopg/types/none.py b/backend/.venv/Lib/site-packages/psycopg/types/none.py new file mode 100644 index 0000000..1669abb --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/types/none.py @@ -0,0 +1,27 @@ +""" +Adapters for None. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +from ..abc import AdaptContext, NoneType, Buffer +from ..adapt import Dumper + + +class NoneDumper(Dumper): + """ + Not a complete dumper as it doesn't implement dump(), but it implements + quote(), so it can be used in sql composition. + """ + + def dump(self, obj: None) -> Buffer | None: + raise NotImplementedError("NULL is passed to Postgres in other ways") + + def quote(self, obj: None) -> Buffer: + return b"NULL" + + +def register_default_adapters(context: AdaptContext) -> None: + context.adapters.register_dumper(NoneType, NoneDumper) diff --git a/backend/.venv/Lib/site-packages/psycopg/types/numeric.py b/backend/.venv/Lib/site-packages/psycopg/types/numeric.py new file mode 100644 index 0000000..d13f16e --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/types/numeric.py @@ -0,0 +1,551 @@ +""" +Adapters for numeric types. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import sys +import struct +from abc import ABC, abstractmethod +from math import log +from typing import Any, Callable, DefaultDict, cast, TYPE_CHECKING +from decimal import Decimal, DefaultContext, Context + +from .. import _oids +from .. import errors as e +from ..pq import Format +from ..abc import AdaptContext +from ..adapt import Buffer, Dumper, Loader, PyFormat +from .._struct import pack_int2, pack_uint2, unpack_int2 +from .._struct import pack_int4, pack_uint4, unpack_int4, unpack_uint4 +from .._struct import pack_int8, unpack_int8 +from .._struct import pack_float4, pack_float8, unpack_float4, unpack_float8 + +# Exposed here +from .._wrappers import ( + Int2 as Int2, + Int4 as Int4, + Int8 as Int8, + IntNumeric as IntNumeric, + Oid as Oid, + Float4 as Float4, + Float8 as Float8, +) + +if TYPE_CHECKING: + import numpy + + +class _IntDumper(Dumper): + def dump(self, obj: Any) -> Buffer | None: + return str(obj).encode() + + def quote(self, obj: Any) -> Buffer: + value = self.dump(obj) + if value is None: + return b"NULL" + return value if obj >= 0 else b" " + value + + +class _IntOrSubclassDumper(_IntDumper): + def dump(self, obj: Any) -> Buffer | None: + t = type(obj) + # Convert to int in order to dump IntEnum or numpy.integer correctly + if t is not int: + obj = int(obj) + + return str(obj).encode() + + +class _SpecialValuesDumper(Dumper): + _special: dict[bytes, bytes] = {} + + def dump(self, obj: Any) -> Buffer | None: + return str(obj).encode() + + def quote(self, obj: Any) -> Buffer: + value = self.dump(obj) + + if value is None: + return b"NULL" + if not isinstance(value, bytes): + value = bytes(value) + if value in self._special: + return self._special[value] + + return value if obj >= 0 else b" " + value + + +class FloatDumper(_SpecialValuesDumper): + oid = _oids.FLOAT8_OID + + _special = { + b"inf": b"'Infinity'::float8", + b"-inf": b"'-Infinity'::float8", + b"nan": b"'NaN'::float8", + } + + +class Float4Dumper(FloatDumper): + oid = _oids.FLOAT4_OID + + +class FloatBinaryDumper(Dumper): + format = Format.BINARY + oid = _oids.FLOAT8_OID + + def dump(self, obj: float) -> Buffer | None: + return pack_float8(obj) + + +class Float4BinaryDumper(FloatBinaryDumper): + oid = _oids.FLOAT4_OID + + def dump(self, obj: float) -> Buffer | None: + return pack_float4(obj) + + +class DecimalDumper(_SpecialValuesDumper): + oid = _oids.NUMERIC_OID + + def dump(self, obj: Decimal) -> Buffer | None: + return dump_decimal_to_text(obj) + + _special = { + b"Infinity": b"'Infinity'::numeric", + b"-Infinity": b"'-Infinity'::numeric", + b"NaN": b"'NaN'::numeric", + } + + +class Int2Dumper(_IntOrSubclassDumper): + oid = _oids.INT2_OID + + +class Int4Dumper(_IntOrSubclassDumper): + oid = _oids.INT4_OID + + +class Int8Dumper(_IntOrSubclassDumper): + oid = _oids.INT8_OID + + +class IntNumericDumper(_IntOrSubclassDumper): + oid = _oids.NUMERIC_OID + + +class OidDumper(_IntOrSubclassDumper): + oid = _oids.OID_OID + + +class IntDumper(Dumper): + def dump(self, obj: Any) -> Buffer | None: + raise TypeError( + f"{type(self).__name__} is a dispatcher to other dumpers:" + " dump() is not supposed to be called" + ) + + def get_key(self, obj: int, format: PyFormat) -> type: + return self.upgrade(obj, format).cls + + _int2_dumper = Int2Dumper(Int2) + _int4_dumper = Int4Dumper(Int4) + _int8_dumper = Int8Dumper(Int8) + _int_numeric_dumper = IntNumericDumper(IntNumeric) + + def upgrade(self, obj: int, format: PyFormat) -> Dumper: + if -(2**31) <= obj < 2**31: + if -(2**15) <= obj < 2**15: + return self._int2_dumper + else: + return self._int4_dumper + else: + if -(2**63) <= obj < 2**63: + return self._int8_dumper + else: + return self._int_numeric_dumper + + +class Int2BinaryDumper(Int2Dumper): + format = Format.BINARY + + def dump(self, obj: int) -> Buffer | None: + return pack_int2(obj) + + +class Int4BinaryDumper(Int4Dumper): + format = Format.BINARY + + def dump(self, obj: int) -> Buffer | None: + return pack_int4(obj) + + +class Int8BinaryDumper(Int8Dumper): + format = Format.BINARY + + def dump(self, obj: int) -> Buffer | None: + return pack_int8(obj) + + +# Ratio between number of bits required to store a number and number of pg +# decimal digits required. +BIT_PER_PGDIGIT = log(2) / log(10_000) + + +class IntNumericBinaryDumper(IntNumericDumper): + format = Format.BINARY + + def dump(self, obj: int) -> Buffer | None: + return dump_int_to_numeric_binary(obj) + + +class OidBinaryDumper(OidDumper): + format = Format.BINARY + + def dump(self, obj: int) -> Buffer | None: + return pack_uint4(obj) + + +class IntBinaryDumper(IntDumper): + format = Format.BINARY + + _int2_dumper = Int2BinaryDumper(Int2) + _int4_dumper = Int4BinaryDumper(Int4) + _int8_dumper = Int8BinaryDumper(Int8) + _int_numeric_dumper = IntNumericBinaryDumper(IntNumeric) + + +class IntLoader(Loader): + def load(self, data: Buffer) -> int: + # it supports bytes directly + return int(data) + + +class Int2BinaryLoader(Loader): + format = Format.BINARY + + def load(self, data: Buffer) -> int: + return unpack_int2(data)[0] + + +class Int4BinaryLoader(Loader): + format = Format.BINARY + + def load(self, data: Buffer) -> int: + return unpack_int4(data)[0] + + +class Int8BinaryLoader(Loader): + format = Format.BINARY + + def load(self, data: Buffer) -> int: + return unpack_int8(data)[0] + + +class OidBinaryLoader(Loader): + format = Format.BINARY + + def load(self, data: Buffer) -> int: + return unpack_uint4(data)[0] + + +class FloatLoader(Loader): + def load(self, data: Buffer) -> float: + # it supports bytes directly + return float(data) + + +class Float4BinaryLoader(Loader): + format = Format.BINARY + + def load(self, data: Buffer) -> float: + return unpack_float4(data)[0] + + +class Float8BinaryLoader(Loader): + format = Format.BINARY + + def load(self, data: Buffer) -> float: + return unpack_float8(data)[0] + + +class NumericLoader(Loader): + def load(self, data: Buffer) -> Decimal: + if isinstance(data, memoryview): + data = bytes(data) + return Decimal(data.decode()) + + +DEC_DIGITS = 4 # decimal digits per Postgres "digit" +NUMERIC_POS = 0x0000 +NUMERIC_NEG = 0x4000 +NUMERIC_NAN = 0xC000 +NUMERIC_PINF = 0xD000 +NUMERIC_NINF = 0xF000 + +_decimal_special = { + NUMERIC_NAN: Decimal("NaN"), + NUMERIC_PINF: Decimal("Infinity"), + NUMERIC_NINF: Decimal("-Infinity"), +} + + +class _ContextMap(DefaultDict[int, Context]): + """ + Cache for decimal contexts to use when the precision requires it. + + Note: if the default context is used (prec=28) you can get an invalid + operation or a rounding to 0: + + - Decimal(1000).shift(24) = Decimal('1000000000000000000000000000') + - Decimal(1000).shift(25) = Decimal('0') + - Decimal(1000).shift(30) raises InvalidOperation + """ + + def __missing__(self, key: int) -> Context: + val = Context(prec=key) + self[key] = val + return val + + +_contexts = _ContextMap() +for i in range(DefaultContext.prec): + _contexts[i] = DefaultContext + +_unpack_numeric_head = cast( + Callable[[Buffer], "tuple[int, int, int, int]"], + struct.Struct("!HhHH").unpack_from, +) +_pack_numeric_head = cast( + Callable[[int, int, int, int], bytes], + struct.Struct("!HhHH").pack, +) + + +class NumericBinaryLoader(Loader): + format = Format.BINARY + + def load(self, data: Buffer) -> Decimal: + ndigits, weight, sign, dscale = _unpack_numeric_head(data) + if sign == NUMERIC_POS or sign == NUMERIC_NEG: + val = 0 + for i in range(8, len(data), 2): + val = val * 10_000 + data[i] * 0x100 + data[i + 1] + + shift = dscale - (ndigits - weight - 1) * DEC_DIGITS + ctx = _contexts[(weight + 2) * DEC_DIGITS + dscale] + return ( + Decimal(val if sign == NUMERIC_POS else -val) + .scaleb(-dscale, ctx) + .shift(shift, ctx) + ) + else: + try: + return _decimal_special[sign] + except KeyError: + raise e.DataError(f"bad value for numeric sign: 0x{sign:X}") from None + + +NUMERIC_NAN_BIN = _pack_numeric_head(0, 0, NUMERIC_NAN, 0) +NUMERIC_PINF_BIN = _pack_numeric_head(0, 0, NUMERIC_PINF, 0) +NUMERIC_NINF_BIN = _pack_numeric_head(0, 0, NUMERIC_NINF, 0) + + +class DecimalBinaryDumper(Dumper): + format = Format.BINARY + oid = _oids.NUMERIC_OID + + def dump(self, obj: Decimal) -> Buffer | None: + return dump_decimal_to_numeric_binary(obj) + + +class _MixedNumericDumper(Dumper, ABC): + """Base for dumper to dump int, decimal, numpy.integer to Postgres numeric + + Only used when looking up by oid. + """ + + oid = _oids.NUMERIC_OID + + # If numpy is available, the dumped object might be a numpy integer too + int_classes: type | tuple[type, ...] = () + + def __init__(self, cls: type, context: AdaptContext | None = None): + super().__init__(cls, context) + + # Verify if numpy is available. If it is, we might have to dump + # its integers too. + if not _MixedNumericDumper.int_classes: + if "numpy" in sys.modules: + import numpy + + _MixedNumericDumper.int_classes = (int, numpy.integer) + else: + _MixedNumericDumper.int_classes = int + + @abstractmethod + def dump(self, obj: Decimal | int | numpy.integer[Any]) -> Buffer | None: ... + + +class NumericDumper(_MixedNumericDumper): + def dump(self, obj: Decimal | int | numpy.integer[Any]) -> Buffer | None: + if isinstance(obj, self.int_classes): + return str(obj).encode() + elif isinstance(obj, Decimal): + return dump_decimal_to_text(obj) + else: + raise TypeError( + f"class {type(self).__name__} cannot dump {type(obj).__name__}" + ) + + +class NumericBinaryDumper(_MixedNumericDumper): + format = Format.BINARY + + def dump(self, obj: Decimal | int | numpy.integer[Any]) -> Buffer | None: + if type(obj) is int: + return dump_int_to_numeric_binary(obj) + elif isinstance(obj, Decimal): + return dump_decimal_to_numeric_binary(obj) + elif isinstance(obj, self.int_classes): + return dump_int_to_numeric_binary(int(obj)) + else: + raise TypeError( + f"class {type(self).__name__} cannot dump {type(obj).__name__}" + ) + + +def dump_decimal_to_text(obj: Decimal) -> bytes: + if obj.is_nan(): + # cover NaN and sNaN + return b"NaN" + else: + return str(obj).encode() + + +def dump_decimal_to_numeric_binary(obj: Decimal) -> bytearray | bytes: + sign, digits, exp = obj.as_tuple() + if exp == "n" or exp == "N": + return NUMERIC_NAN_BIN + elif exp == "F": + return NUMERIC_NINF_BIN if sign else NUMERIC_PINF_BIN + + # Weights of py digits into a pg digit according to their positions. + # Starting with an index wi != 0 is equivalent to prepending 0's to + # the digits tuple, but without really changing it. + weights = (1000, 100, 10, 1) + wi = 0 + + ndigits = nzdigits = len(digits) + + # Find the last nonzero digit + while nzdigits > 0 and digits[nzdigits - 1] == 0: + nzdigits -= 1 + + if exp <= 0: + dscale = -exp + else: + dscale = 0 + # align the py digits to the pg digits if there's some py exponent + ndigits += exp % DEC_DIGITS + + if not nzdigits: + return _pack_numeric_head(0, 0, NUMERIC_POS, dscale) + + # Equivalent of 0-padding left to align the py digits to the pg digits + # but without changing the digits tuple. + mod = (ndigits - dscale) % DEC_DIGITS + if mod: + wi = DEC_DIGITS - mod + ndigits += wi + + tmp = nzdigits + wi + out = bytearray( + _pack_numeric_head( + tmp // DEC_DIGITS + (tmp % DEC_DIGITS and 1), # ndigits + (ndigits + exp) // DEC_DIGITS - 1, # weight + NUMERIC_NEG if sign else NUMERIC_POS, # sign + dscale, + ) + ) + + pgdigit = 0 + for i in range(nzdigits): + pgdigit += weights[wi] * digits[i] + wi += 1 + if wi >= DEC_DIGITS: + out += pack_uint2(pgdigit) + pgdigit = wi = 0 + + if pgdigit: + out += pack_uint2(pgdigit) + + return out + + +def dump_int_to_numeric_binary(obj: int) -> bytearray: + ndigits = int(obj.bit_length() * BIT_PER_PGDIGIT) + 1 + out = bytearray(b"\x00\x00" * (ndigits + 4)) + if obj < 0: + sign = NUMERIC_NEG + obj = -obj + else: + sign = NUMERIC_POS + + out[:8] = _pack_numeric_head(ndigits, ndigits - 1, sign, 0) + i = 8 + (ndigits - 1) * 2 + while obj: + rem = obj % 10_000 + obj //= 10_000 + out[i : i + 2] = pack_uint2(rem) + i -= 2 + + return out + + +def register_default_adapters(context: AdaptContext) -> None: + adapters = context.adapters + adapters.register_dumper(int, IntDumper) + adapters.register_dumper(int, IntBinaryDumper) + adapters.register_dumper(float, FloatDumper) + adapters.register_dumper(float, FloatBinaryDumper) + adapters.register_dumper(Int2, Int2Dumper) + adapters.register_dumper(Int4, Int4Dumper) + adapters.register_dumper(Int8, Int8Dumper) + adapters.register_dumper(IntNumeric, IntNumericDumper) + adapters.register_dumper(Oid, OidDumper) + + # The binary dumper is currently some 30% slower, so default to text + # (see tests/scripts/testdec.py for a rough benchmark) + # Also, must be after IntNumericDumper + adapters.register_dumper("decimal.Decimal", DecimalBinaryDumper) + adapters.register_dumper("decimal.Decimal", DecimalDumper) + + # Used only by oid, can take both int and Decimal as input + adapters.register_dumper(None, NumericBinaryDumper) + adapters.register_dumper(None, NumericDumper) + + adapters.register_dumper(Float4, Float4Dumper) + adapters.register_dumper(Float8, FloatDumper) + adapters.register_dumper(Int2, Int2BinaryDumper) + adapters.register_dumper(Int4, Int4BinaryDumper) + adapters.register_dumper(Int8, Int8BinaryDumper) + adapters.register_dumper(Oid, OidBinaryDumper) + adapters.register_dumper(Float4, Float4BinaryDumper) + adapters.register_dumper(Float8, FloatBinaryDumper) + adapters.register_loader("int2", IntLoader) + adapters.register_loader("int4", IntLoader) + adapters.register_loader("int8", IntLoader) + adapters.register_loader("oid", IntLoader) + adapters.register_loader("int2", Int2BinaryLoader) + adapters.register_loader("int4", Int4BinaryLoader) + adapters.register_loader("int8", Int8BinaryLoader) + adapters.register_loader("oid", OidBinaryLoader) + adapters.register_loader("float4", FloatLoader) + adapters.register_loader("float8", FloatLoader) + adapters.register_loader("float4", Float4BinaryLoader) + adapters.register_loader("float8", Float8BinaryLoader) + adapters.register_loader("numeric", NumericLoader) + adapters.register_loader("numeric", NumericBinaryLoader) diff --git a/backend/.venv/Lib/site-packages/psycopg/types/numpy.py b/backend/.venv/Lib/site-packages/psycopg/types/numpy.py new file mode 100644 index 0000000..9427a22 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/types/numpy.py @@ -0,0 +1,99 @@ +""" +Adapters for numpy types. +""" + +# Copyright (C) 2022 The Psycopg Team + +from typing import Any + +from .. import _oids +from ..pq import Format +from ..abc import AdaptContext, Buffer +from .._struct import pack_int2, pack_int4, pack_int8 + +from .bool import BoolDumper, BoolBinaryDumper +from .numeric import _IntDumper, dump_int_to_numeric_binary +from .numeric import FloatDumper, Float4Dumper, FloatBinaryDumper, Float4BinaryDumper + + +class NPInt16Dumper(_IntDumper): + oid = _oids.INT2_OID + + +class NPInt32Dumper(_IntDumper): + oid = _oids.INT4_OID + + +class NPInt64Dumper(_IntDumper): + oid = _oids.INT8_OID + + +class NPNumericDumper(_IntDumper): + oid = _oids.NUMERIC_OID + + +# Binary Dumpers + + +class NPInt16BinaryDumper(NPInt16Dumper): + format = Format.BINARY + + def dump(self, obj: Any) -> bytes: + return pack_int2(int(obj)) + + +class NPInt32BinaryDumper(NPInt32Dumper): + format = Format.BINARY + + def dump(self, obj: Any) -> bytes: + return pack_int4(int(obj)) + + +class NPInt64BinaryDumper(NPInt64Dumper): + format = Format.BINARY + + def dump(self, obj: Any) -> bytes: + return pack_int8(int(obj)) + + +class NPNumericBinaryDumper(NPNumericDumper): + format = Format.BINARY + + def dump(self, obj: Any) -> Buffer: + return dump_int_to_numeric_binary(int(obj)) + + +def register_default_adapters(context: AdaptContext) -> None: + adapters = context.adapters + + adapters.register_dumper("numpy.int8", NPInt16Dumper) + adapters.register_dumper("numpy.int16", NPInt16Dumper) + adapters.register_dumper("numpy.int32", NPInt32Dumper) + adapters.register_dumper("numpy.int64", NPInt64Dumper) + adapters.register_dumper("numpy.longlong", NPInt64Dumper) + adapters.register_dumper("numpy.bool", BoolDumper) + adapters.register_dumper("numpy.bool_", BoolDumper) + adapters.register_dumper("numpy.uint8", NPInt16Dumper) + adapters.register_dumper("numpy.uint16", NPInt32Dumper) + adapters.register_dumper("numpy.uint32", NPInt64Dumper) + adapters.register_dumper("numpy.uint64", NPNumericDumper) + adapters.register_dumper("numpy.ulonglong", NPNumericDumper) + adapters.register_dumper("numpy.float16", Float4Dumper) + adapters.register_dumper("numpy.float32", Float4Dumper) + adapters.register_dumper("numpy.float64", FloatDumper) + + adapters.register_dumper("numpy.int8", NPInt16BinaryDumper) + adapters.register_dumper("numpy.int16", NPInt16BinaryDumper) + adapters.register_dumper("numpy.int32", NPInt32BinaryDumper) + adapters.register_dumper("numpy.int64", NPInt64BinaryDumper) + adapters.register_dumper("numpy.longlong", NPInt64BinaryDumper) + adapters.register_dumper("numpy.bool", BoolBinaryDumper) + adapters.register_dumper("numpy.bool_", BoolBinaryDumper) + adapters.register_dumper("numpy.uint8", NPInt16BinaryDumper) + adapters.register_dumper("numpy.uint16", NPInt32BinaryDumper) + adapters.register_dumper("numpy.uint32", NPInt64BinaryDumper) + adapters.register_dumper("numpy.uint64", NPNumericBinaryDumper) + adapters.register_dumper("numpy.ulonglong", NPNumericBinaryDumper) + adapters.register_dumper("numpy.float16", Float4BinaryDumper) + adapters.register_dumper("numpy.float32", Float4BinaryDumper) + adapters.register_dumper("numpy.float64", FloatBinaryDumper) diff --git a/backend/.venv/Lib/site-packages/psycopg/types/range.py b/backend/.venv/Lib/site-packages/psycopg/types/range.py new file mode 100644 index 0000000..3327a84 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/types/range.py @@ -0,0 +1,753 @@ +""" +Support for range types adaptation. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import re +from typing import Any, Generic, cast, TYPE_CHECKING +from decimal import Decimal +from datetime import date, datetime + +from .. import sql +from .. import _oids +from .. import errors as e +from .. import postgres +from ..pq import Format +from ..abc import AdaptContext, Buffer, Dumper, DumperKey, DumpFunc, LoadFunc, Query +from ..adapt import RecursiveDumper, RecursiveLoader, PyFormat +from .._oids import INVALID_OID, TEXT_OID +from .._compat import cache, TypeVar +from .._struct import pack_len, unpack_len +from .._typeinfo import TypeInfo, TypesRegistry + +if TYPE_CHECKING: + from .._connection_base import BaseConnection + +RANGE_EMPTY = 0x01 # range is empty +RANGE_LB_INC = 0x02 # lower bound is inclusive +RANGE_UB_INC = 0x04 # upper bound is inclusive +RANGE_LB_INF = 0x08 # lower bound is -infinity +RANGE_UB_INF = 0x10 # upper bound is +infinity + +_EMPTY_HEAD = bytes([RANGE_EMPTY]) + +T = TypeVar("T") + + +class RangeInfo(TypeInfo): + """Manage information about a range type.""" + + def __init__( + self, + name: str, + oid: int, + array_oid: int, + *, + regtype: str = "", + subtype_oid: int, + ): + super().__init__(name, oid, array_oid, regtype=regtype) + self.subtype_oid = subtype_oid + + @classmethod + def _get_info_query(cls, conn: BaseConnection[Any]) -> Query: + return sql.SQL( + """\ +SELECT t.typname AS name, t.oid AS oid, t.typarray AS array_oid, + t.oid::regtype::text AS regtype, + r.rngsubtype AS subtype_oid +FROM pg_type t +JOIN pg_range r ON t.oid = r.rngtypid +WHERE t.oid = {regtype} +""" + ).format(regtype=cls._to_regtype(conn)) + + def _added(self, registry: TypesRegistry) -> None: + # Map ranges subtypes to info + registry._registry[RangeInfo, self.subtype_oid] = self + + +class Range(Generic[T]): + """Python representation for a PostgreSQL range type. + + :param lower: lower bound for the range. `!None` means unbound + :param upper: upper bound for the range. `!None` means unbound + :param bounds: one of the literal strings ``()``, ``[)``, ``(]``, ``[]``, + representing whether the lower or upper bounds are included + :param empty: if `!True`, the range is empty + + """ + + __slots__ = ("_lower", "_upper", "_bounds") + + def __init__( + self, + lower: T | None = None, + upper: T | None = None, + bounds: str = "[)", + empty: bool = False, + ): + if not empty: + if bounds not in ("[)", "(]", "()", "[]"): + raise ValueError("bound flags not valid: %r" % bounds) + + self._lower = lower + self._upper = upper + + # Make bounds consistent with infs + if lower is None and bounds[0] == "[": + bounds = "(" + bounds[1] + if upper is None and bounds[1] == "]": + bounds = bounds[0] + ")" + + self._bounds = bounds + else: + self._lower = self._upper = None + self._bounds = "" + + def __repr__(self) -> str: + if self._bounds: + args = f"{self._lower!r}, {self._upper!r}, {self._bounds!r}" + else: + args = "empty=True" + + return f"{self.__class__.__name__}({args})" + + def __str__(self) -> str: + if not self._bounds: + return "empty" + + items = [ + self._bounds[0], + str(self._lower), + ", ", + str(self._upper), + self._bounds[1], + ] + return "".join(items) + + @property + def lower(self) -> T | None: + """The lower bound of the range. `!None` if empty or unbound.""" + return self._lower + + @property + def upper(self) -> T | None: + """The upper bound of the range. `!None` if empty or unbound.""" + return self._upper + + @property + def bounds(self) -> str: + """The bounds string (two characters from '[', '(', ']', ')').""" + return self._bounds + + @property + def isempty(self) -> bool: + """`!True` if the range is empty.""" + return not self._bounds + + @property + def lower_inf(self) -> bool: + """`!True` if the range doesn't have a lower bound.""" + if not self._bounds: + return False + return self._lower is None + + @property + def upper_inf(self) -> bool: + """`!True` if the range doesn't have an upper bound.""" + if not self._bounds: + return False + return self._upper is None + + @property + def lower_inc(self) -> bool: + """`!True` if the lower bound is included in the range.""" + if not self._bounds or self._lower is None: + return False + return self._bounds[0] == "[" + + @property + def upper_inc(self) -> bool: + """`!True` if the upper bound is included in the range.""" + if not self._bounds or self._upper is None: + return False + return self._bounds[1] == "]" + + def __contains__(self, x: T) -> bool: + if not self._bounds: + return False + + if self._lower is not None: + if self._bounds[0] == "[": + # It doesn't seem that Python has an ABC for ordered types. + if x < self._lower: # type: ignore[operator] + return False + else: + if x <= self._lower: # type: ignore[operator] + return False + + if self._upper is not None: + if self._bounds[1] == "]": + if x > self._upper: # type: ignore[operator] + return False + else: + if x >= self._upper: # type: ignore[operator] + return False + + return True + + def __bool__(self) -> bool: + return bool(self._bounds) + + def __eq__(self, other: Any) -> bool: + if not isinstance(other, Range): + return False + return ( + self._lower == other._lower + and self._upper == other._upper + and self._bounds == other._bounds + ) + + def __hash__(self) -> int: + return hash((self._lower, self._upper, self._bounds)) + + # as the postgres docs describe for the server-side stuff, + # ordering is rather arbitrary, but will remain stable + # and consistent. + + def __lt__(self, other: Any) -> bool: + if not isinstance(other, Range): + return NotImplemented + for attr in ("_lower", "_upper", "_bounds"): + self_value = getattr(self, attr) + other_value = getattr(other, attr) + if self_value == other_value: + pass + elif self_value is None: + return True + elif other_value is None: + return False + else: + return cast(bool, self_value < other_value) + return False + + def __le__(self, other: Any) -> bool: + return self == other or self < other # type: ignore + + def __gt__(self, other: Any) -> bool: + if isinstance(other, Range): + return other < self + else: + return NotImplemented + + def __ge__(self, other: Any) -> bool: + return self == other or self > other # type: ignore + + def __getstate__(self) -> dict[str, Any]: + return { + slot: getattr(self, slot) for slot in self.__slots__ if hasattr(self, slot) + } + + def __setstate__(self, state: dict[str, Any]) -> None: + for slot, value in state.items(): + setattr(self, slot, value) + + +# Subclasses to specify a specific subtype. Usually not needed: only needed +# in binary copy, where switching to text is not an option. + + +class Int4Range(Range[int]): + pass + + +class Int8Range(Range[int]): + pass + + +class NumericRange(Range[Decimal]): + pass + + +class DateRange(Range[date]): + pass + + +class TimestampRange(Range[datetime]): + pass + + +class TimestamptzRange(Range[datetime]): + pass + + +class BaseRangeDumper(RecursiveDumper): + def __init__(self, cls: type, context: AdaptContext | None = None): + super().__init__(cls, context) + self.sub_dumper: Dumper | None = None + self._adapt_format = PyFormat.from_pq(self.format) + + def get_key(self, obj: Range[Any], format: PyFormat) -> DumperKey: + # If we are a subclass whose oid is specified we don't need upgrade + if self.cls is not Range: + return self.cls + + item = self._get_item(obj) + if item is not None: + sd = self._tx.get_dumper(item, self._adapt_format) + return (self.cls, sd.get_key(item, format)) + else: + return (self.cls,) + + def upgrade(self, obj: Range[Any], format: PyFormat) -> BaseRangeDumper: + # If we are a subclass whose oid is specified we don't need upgrade + if self.cls is not Range: + return self + + item = self._get_item(obj) + if item is None: + return self + + dumper: BaseRangeDumper + if type(item) is int: + # postgres won't cast int4range -> int8range so we must use + # text format and unknown oid here + sd = self._tx.get_dumper(item, PyFormat.TEXT) + dumper = RangeDumper(self.cls, self._tx) + dumper.sub_dumper = sd + dumper.oid = INVALID_OID + return dumper + + sd = self._tx.get_dumper(item, format) + dumper = type(self)(self.cls, self._tx) + dumper.sub_dumper = sd + if sd.oid == INVALID_OID and isinstance(item, str): + # Work around the normal mapping where text is dumped as unknown + dumper.oid = self._get_range_oid(TEXT_OID) + else: + dumper.oid = self._get_range_oid(sd.oid) + + return dumper + + def _get_item(self, obj: Range[Any]) -> Any: + """ + Return a member representative of the range + """ + rv = obj.lower + return rv if rv is not None else obj.upper + + def _get_range_oid(self, sub_oid: int) -> int: + """ + Return the oid of the range from the oid of its elements. + """ + info = self._tx.adapters.types.get_by_subtype(RangeInfo, sub_oid) + return info.oid if info else INVALID_OID + + +class RangeDumper(BaseRangeDumper): + """ + Dumper for range types. + + The dumper can upgrade to one specific for a different range type. + """ + + def dump(self, obj: Range[Any]) -> Buffer | None: + item = self._get_item(obj) + if item is not None: + dump = self._tx.get_dumper(item, self._adapt_format).dump + else: + dump = fail_dump + + return dump_range_text(obj, dump) + + +def dump_range_text(obj: Range[Any], dump: DumpFunc) -> Buffer: + if obj.isempty: + return b"empty" + + parts: list[Buffer] = [b"[" if obj.lower_inc else b"("] + + def dump_item(item: Any) -> Buffer: + ad = dump(item) + if ad is None: + return b"" + elif not ad: + return b'""' + elif _re_needs_quotes.search(ad): + return b'"' + _re_esc.sub(rb"\1\1", ad) + b'"' + else: + return ad + + if obj.lower is not None: + parts.append(dump_item(obj.lower)) + + parts.append(b",") + + if obj.upper is not None: + parts.append(dump_item(obj.upper)) + + parts.append(b"]" if obj.upper_inc else b")") + + return b"".join(parts) + + +_re_needs_quotes = re.compile(rb'[",\\\s()\[\]]') +_re_esc = re.compile(rb"([\\\"])") + + +class RangeBinaryDumper(BaseRangeDumper): + format = Format.BINARY + + def dump(self, obj: Range[Any]) -> Buffer | None: + item = self._get_item(obj) + if item is not None: + dump = self._tx.get_dumper(item, self._adapt_format).dump + else: + dump = fail_dump + + return dump_range_binary(obj, dump) + + +def dump_range_binary(obj: Range[Any], dump: DumpFunc) -> Buffer: + if not obj: + return _EMPTY_HEAD + + out = bytearray([0]) # will replace the head later + + head = 0 + if obj.lower_inc: + head |= RANGE_LB_INC + if obj.upper_inc: + head |= RANGE_UB_INC + + if obj.lower is not None: + data = dump(obj.lower) + if data is not None: + out += pack_len(len(data)) + out += data + else: + head |= RANGE_LB_INF + else: + head |= RANGE_LB_INF + + if obj.upper is not None: + data = dump(obj.upper) + if data is not None: + out += pack_len(len(data)) + out += data + else: + head |= RANGE_UB_INF + else: + head |= RANGE_UB_INF + + out[0] = head + return out + + +def fail_dump(obj: Any) -> Buffer: + raise e.InternalError("trying to dump a range element without information") + + +class BaseRangeLoader(RecursiveLoader, Generic[T]): + """Generic loader for a range. + + Subclasses must specify the oid of the subtype and the class to load. + """ + + subtype_oid: int + + def __init__(self, oid: int, context: AdaptContext | None = None): + super().__init__(oid, context) + self._load = self._tx.get_loader(self.subtype_oid, format=self.format).load + + +class RangeLoader(BaseRangeLoader[T]): + def load(self, data: Buffer) -> Range[T]: + return load_range_text(data, self._load)[0] + + +def load_range_text(data: Buffer, load: LoadFunc) -> tuple[Range[Any], int]: + if data == b"empty": + return Range(empty=True), 5 + + m = _re_range.match(data) + if m is None: + raise e.DataError( + f"failed to parse range: '{bytes(data).decode('utf8', 'replace')}'" + ) + + lower = None + item = m.group(3) + if item is None: + item = m.group(2) + if item is not None: + lower = load(_re_undouble.sub(rb"\1", item)) + else: + lower = load(item) + + upper = None + item = m.group(5) + if item is None: + item = m.group(4) + if item is not None: + upper = load(_re_undouble.sub(rb"\1", item)) + else: + upper = load(item) + + bounds = (m.group(1) + m.group(6)).decode() + + return Range(lower, upper, bounds), m.end() + + +_re_range = re.compile( + rb""" + ( \(|\[ ) # lower bound flag + (?: # lower bound: + " ( (?: [^"] | "")* ) " # - a quoted string + | ( [^",]+ ) # - or an unquoted string + )? # - or empty (not caught) + , + (?: # upper bound: + " ( (?: [^"] | "")* ) " # - a quoted string + | ( [^"\)\]]+ ) # - or an unquoted string + )? # - or empty (not caught) + ( \)|\] ) # upper bound flag + """, + re.VERBOSE, +) + +_re_undouble = re.compile(rb'(["\\])\1') + + +class RangeBinaryLoader(BaseRangeLoader[T]): + format = Format.BINARY + + def load(self, data: Buffer) -> Range[T]: + return load_range_binary(data, self._load) + + +def load_range_binary(data: Buffer, load: LoadFunc) -> Range[Any]: + head = data[0] + if head & RANGE_EMPTY: + return Range(empty=True) + + lb = "[" if head & RANGE_LB_INC else "(" + ub = "]" if head & RANGE_UB_INC else ")" + + pos = 1 # after the head + if head & RANGE_LB_INF: + min = None + else: + length = unpack_len(data, pos)[0] + pos += 4 + min = load(data[pos : pos + length]) + pos += length + + if head & RANGE_UB_INF: + max = None + else: + length = unpack_len(data, pos)[0] + pos += 4 + max = load(data[pos : pos + length]) + pos += length + + return Range(min, max, lb + ub) + + +def register_range(info: RangeInfo, context: AdaptContext | None = None) -> None: + """Register the adapters to load and dump a range type. + + :param info: The object with the information about the range to register. + :param context: The context where to register the adapters. If `!None`, + register it globally. + + Register loaders so that loading data of this type will result in a `Range` + with bounds parsed as the right subtype. + + .. note:: + + Registering the adapters doesn't affect objects already created, even + if they are children of the registered context. For instance, + registering the adapter globally doesn't affect already existing + connections. + """ + # A friendly error warning instead of an AttributeError in case fetch() + # failed and it wasn't noticed. + if not info: + raise TypeError("no info passed. Is the requested range available?") + + # Register arrays and type info + info.register(context) + + adapters = context.adapters if context else postgres.adapters + + # generate and register a customized text loader + loader: type[BaseRangeLoader[Any]] + loader = _make_loader(info.name, info.subtype_oid) + adapters.register_loader(info.oid, loader) + + # generate and register a customized binary loader + loader = _make_binary_loader(info.name, info.subtype_oid) + adapters.register_loader(info.oid, loader) + + +# Cache all dynamically-generated types to avoid leaks in case the types +# cannot be GC'd. + + +@cache +def _make_loader(name: str, oid: int) -> type[RangeLoader[Any]]: + return type(f"{name.title()}Loader", (RangeLoader,), {"subtype_oid": oid}) + + +@cache +def _make_binary_loader(name: str, oid: int) -> type[RangeBinaryLoader[Any]]: + return type( + f"{name.title()}BinaryLoader", (RangeBinaryLoader,), {"subtype_oid": oid} + ) + + +# Text dumpers for builtin range types wrappers +# These are registered on specific subtypes so that the upgrade mechanism +# doesn't kick in. + + +class Int4RangeDumper(RangeDumper): + oid = _oids.INT4RANGE_OID + + +class Int8RangeDumper(RangeDumper): + oid = _oids.INT8RANGE_OID + + +class NumericRangeDumper(RangeDumper): + oid = _oids.NUMRANGE_OID + + +class DateRangeDumper(RangeDumper): + oid = _oids.DATERANGE_OID + + +class TimestampRangeDumper(RangeDumper): + oid = _oids.TSRANGE_OID + + +class TimestamptzRangeDumper(RangeDumper): + oid = _oids.TSTZRANGE_OID + + +# Binary dumpers for builtin range types wrappers +# These are registered on specific subtypes so that the upgrade mechanism +# doesn't kick in. + + +class Int4RangeBinaryDumper(RangeBinaryDumper): + oid = _oids.INT4RANGE_OID + + +class Int8RangeBinaryDumper(RangeBinaryDumper): + oid = _oids.INT8RANGE_OID + + +class NumericRangeBinaryDumper(RangeBinaryDumper): + oid = _oids.NUMRANGE_OID + + +class DateRangeBinaryDumper(RangeBinaryDumper): + oid = _oids.DATERANGE_OID + + +class TimestampRangeBinaryDumper(RangeBinaryDumper): + oid = _oids.TSRANGE_OID + + +class TimestamptzRangeBinaryDumper(RangeBinaryDumper): + oid = _oids.TSTZRANGE_OID + + +# Text loaders for builtin range types + + +class Int4RangeLoader(RangeLoader[int]): + subtype_oid = _oids.INT4_OID + + +class Int8RangeLoader(RangeLoader[int]): + subtype_oid = _oids.INT8_OID + + +class NumericRangeLoader(RangeLoader[Decimal]): + subtype_oid = _oids.NUMERIC_OID + + +class DateRangeLoader(RangeLoader[date]): + subtype_oid = _oids.DATE_OID + + +class TimestampRangeLoader(RangeLoader[datetime]): + subtype_oid = _oids.TIMESTAMP_OID + + +class TimestampTZRangeLoader(RangeLoader[datetime]): + subtype_oid = _oids.TIMESTAMPTZ_OID + + +# Binary loaders for builtin range types + + +class Int4RangeBinaryLoader(RangeBinaryLoader[int]): + subtype_oid = _oids.INT4_OID + + +class Int8RangeBinaryLoader(RangeBinaryLoader[int]): + subtype_oid = _oids.INT8_OID + + +class NumericRangeBinaryLoader(RangeBinaryLoader[Decimal]): + subtype_oid = _oids.NUMERIC_OID + + +class DateRangeBinaryLoader(RangeBinaryLoader[date]): + subtype_oid = _oids.DATE_OID + + +class TimestampRangeBinaryLoader(RangeBinaryLoader[datetime]): + subtype_oid = _oids.TIMESTAMP_OID + + +class TimestampTZRangeBinaryLoader(RangeBinaryLoader[datetime]): + subtype_oid = _oids.TIMESTAMPTZ_OID + + +def register_default_adapters(context: AdaptContext) -> None: + adapters = context.adapters + adapters.register_dumper(Range, RangeBinaryDumper) + adapters.register_dumper(Range, RangeDumper) + adapters.register_dumper(Int4Range, Int4RangeDumper) + adapters.register_dumper(Int8Range, Int8RangeDumper) + adapters.register_dumper(NumericRange, NumericRangeDumper) + adapters.register_dumper(DateRange, DateRangeDumper) + adapters.register_dumper(TimestampRange, TimestampRangeDumper) + adapters.register_dumper(TimestamptzRange, TimestamptzRangeDumper) + adapters.register_dumper(Int4Range, Int4RangeBinaryDumper) + adapters.register_dumper(Int8Range, Int8RangeBinaryDumper) + adapters.register_dumper(NumericRange, NumericRangeBinaryDumper) + adapters.register_dumper(DateRange, DateRangeBinaryDumper) + adapters.register_dumper(TimestampRange, TimestampRangeBinaryDumper) + adapters.register_dumper(TimestamptzRange, TimestamptzRangeBinaryDumper) + adapters.register_loader("int4range", Int4RangeLoader) + adapters.register_loader("int8range", Int8RangeLoader) + adapters.register_loader("numrange", NumericRangeLoader) + adapters.register_loader("daterange", DateRangeLoader) + adapters.register_loader("tsrange", TimestampRangeLoader) + adapters.register_loader("tstzrange", TimestampTZRangeLoader) + adapters.register_loader("int4range", Int4RangeBinaryLoader) + adapters.register_loader("int8range", Int8RangeBinaryLoader) + adapters.register_loader("numrange", NumericRangeBinaryLoader) + adapters.register_loader("daterange", DateRangeBinaryLoader) + adapters.register_loader("tsrange", TimestampRangeBinaryLoader) + adapters.register_loader("tstzrange", TimestampTZRangeBinaryLoader) diff --git a/backend/.venv/Lib/site-packages/psycopg/types/shapely.py b/backend/.venv/Lib/site-packages/psycopg/types/shapely.py new file mode 100644 index 0000000..6a7e157 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/types/shapely.py @@ -0,0 +1,89 @@ +""" +Adapters for PostGIS geometries +""" + +from __future__ import annotations + +from .. import postgres +from ..abc import AdaptContext, Buffer +from ..adapt import Dumper, Loader +from ..pq import Format +from .._compat import cache +from .._typeinfo import TypeInfo + +try: + from shapely.wkb import loads, dumps + from shapely.geometry.base import BaseGeometry + +except ImportError: + raise ImportError( + "The module psycopg.types.shapely requires the package 'Shapely'" + " to be installed" + ) + + +class GeometryBinaryLoader(Loader): + format = Format.BINARY + + def load(self, data: Buffer) -> BaseGeometry: + if not isinstance(data, bytes): + data = bytes(data) + return loads(data) + + +class GeometryLoader(Loader): + def load(self, data: Buffer) -> BaseGeometry: + # it's a hex string in binary + if isinstance(data, memoryview): + data = bytes(data) + return loads(data.decode(), hex=True) + + +class BaseGeometryBinaryDumper(Dumper): + format = Format.BINARY + + def dump(self, obj: BaseGeometry) -> Buffer | None: + return dumps(obj) # type: ignore + + +class BaseGeometryDumper(Dumper): + def dump(self, obj: BaseGeometry) -> Buffer | None: + return dumps(obj, hex=True).encode() # type: ignore + + +def register_shapely(info: TypeInfo, context: AdaptContext | None = None) -> None: + """Register Shapely dumper and loaders.""" + + # A friendly error warning instead of an AttributeError in case fetch() + # failed and it wasn't noticed. + if not info: + raise TypeError("no info passed. Is the 'postgis' extension loaded?") + + info.register(context) + adapters = context.adapters if context else postgres.adapters + + adapters.register_loader(info.oid, GeometryBinaryLoader) + adapters.register_loader(info.oid, GeometryLoader) + # Default binary dump + adapters.register_dumper(BaseGeometry, _make_dumper(info.oid)) + adapters.register_dumper(BaseGeometry, _make_binary_dumper(info.oid)) + + +# Cache all dynamically-generated types to avoid leaks in case the types +# cannot be GC'd. + + +@cache +def _make_dumper(oid_in: int) -> type[BaseGeometryDumper]: + class GeometryDumper(BaseGeometryDumper): + oid = oid_in + + return GeometryDumper + + +@cache +def _make_binary_dumper(oid_in: int) -> type[BaseGeometryBinaryDumper]: + class GeometryBinaryDumper(BaseGeometryBinaryDumper): + oid = oid_in + + return GeometryBinaryDumper diff --git a/backend/.venv/Lib/site-packages/psycopg/types/string.py b/backend/.venv/Lib/site-packages/psycopg/types/string.py new file mode 100644 index 0000000..b802a6c --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/types/string.py @@ -0,0 +1,233 @@ +""" +Adapters for textual types. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +from typing import TYPE_CHECKING + +from .. import _oids +from ..pq import Format, Escaping +from ..abc import AdaptContext +from ..adapt import Buffer, Dumper, Loader +from ..errors import DataError +from .._encodings import conn_encoding + +if TYPE_CHECKING: + from ..pq.abc import Escaping as EscapingProto + + +class _BaseStrDumper(Dumper): + def __init__(self, cls: type, context: AdaptContext | None = None): + super().__init__(cls, context) + enc = conn_encoding(self.connection) + self._encoding = enc if enc != "ascii" else "utf-8" + + +class _StrBinaryDumper(_BaseStrDumper): + """ + Base class to dump a Python strings to a Postgres text type, in binary format. + + Subclasses shall specify the oids of real types (text, varchar, name...). + """ + + format = Format.BINARY + + def dump(self, obj: str) -> Buffer | None: + # the server will raise DataError subclass if the string contains 0x00 + return obj.encode(self._encoding) + + +class _StrDumper(_BaseStrDumper): + """ + Base class to dump a Python strings to a Postgres text type, in text format. + + Subclasses shall specify the oids of real types (text, varchar, name...). + """ + + def dump(self, obj: str) -> Buffer | None: + if "\x00" in obj: + raise DataError("PostgreSQL text fields cannot contain NUL (0x00) bytes") + else: + return obj.encode(self._encoding) + + +# The next are concrete dumpers, each one specifying the oid they dump to. + + +class StrBinaryDumper(_StrBinaryDumper): + oid = _oids.TEXT_OID + + +class StrBinaryDumperVarchar(_StrBinaryDumper): + oid = _oids.VARCHAR_OID + + +class StrBinaryDumperName(_StrBinaryDumper): + oid = _oids.NAME_OID + + +class StrDumper(_StrDumper): + """ + Dumper for strings in text format to the text oid. + + Note that this dumper is not used by default because the type is too strict + and PostgreSQL would require an explicit casts to everything that is not a + text field. However it is useful where the unknown oid is ambiguous and the + text oid is required, for instance with variadic functions. + """ + + oid = _oids.TEXT_OID + + +class StrDumperVarchar(_StrDumper): + oid = _oids.VARCHAR_OID + + +class StrDumperName(_StrDumper): + oid = _oids.NAME_OID + + +class StrDumperUnknown(_StrDumper): + """ + Dumper for strings in text format to the unknown oid. + + This dumper is the default dumper for strings and allows to use Python + strings to represent almost every data type. In a few places, however, the + unknown oid is not accepted (for instance in variadic functions such as + 'concat()'). In that case either a cast on the placeholder ('%s::text') or + the StrTextDumper should be used. + """ + + pass + + +class TextLoader(Loader): + def __init__(self, oid: int, context: AdaptContext | None = None): + super().__init__(oid, context) + enc = conn_encoding(self.connection) + self._encoding = enc if enc != "ascii" else "" + + def load(self, data: Buffer) -> bytes | str: + if self._encoding: + if isinstance(data, memoryview): + data = bytes(data) + return data.decode(self._encoding) + else: + # return bytes for SQL_ASCII db + if not isinstance(data, bytes): + data = bytes(data) + return data + + +class TextBinaryLoader(TextLoader): + format = Format.BINARY + + +class BytesDumper(Dumper): + oid = _oids.BYTEA_OID + _qprefix = b"" + + def __init__(self, cls: type, context: AdaptContext | None = None): + super().__init__(cls, context) + self._esc = Escaping(self.connection.pgconn if self.connection else None) + + def dump(self, obj: Buffer) -> Buffer | None: + return self._esc.escape_bytea(obj) + + def quote(self, obj: Buffer) -> Buffer: + escaped = self.dump(obj) + if escaped is None: + return b"NULL" + + # We cannot use the base quoting because escape_bytea already returns + # the quotes content. if scs is off it will escape the backslashes in + # the format, otherwise it won't, but it doesn't tell us what quotes to + # use. + if self.connection: + if not self._qprefix: + scs = self.connection.pgconn.parameter_status( + b"standard_conforming_strings" + ) + self._qprefix = b"'" if scs == b"on" else b" E'" + + return self._qprefix + escaped + b"'" + + # We don't have a connection, so someone is using us to generate a file + # to use off-line or something like that. PQescapeBytea, like its + # string counterpart, is not predictable whether it will escape + # backslashes. + rv: bytes = b" E'" + escaped + b"'" + if self._esc.escape_bytea(b"\x00") == b"\\000": + rv = rv.replace(b"\\", b"\\\\") + return rv + + +class BytesBinaryDumper(Dumper): + format = Format.BINARY + oid = _oids.BYTEA_OID + + def dump(self, obj: Buffer) -> Buffer | None: + return obj + + +class ByteaLoader(Loader): + _escaping: EscapingProto + + def __init__(self, oid: int, context: AdaptContext | None = None): + super().__init__(oid, context) + if not hasattr(self.__class__, "_escaping"): + self.__class__._escaping = Escaping() + + def load(self, data: Buffer) -> bytes: + return self._escaping.unescape_bytea(data) + + +class ByteaBinaryLoader(Loader): + format = Format.BINARY + + def load(self, data: Buffer) -> Buffer: + return data + + +def register_default_adapters(context: AdaptContext) -> None: + adapters = context.adapters + + # NOTE: the order the dumpers are registered is relevant. The last one + # registered becomes the default for each type. Usually, binary is the + # default dumper. For text we use the text dumper as default because it + # plays the role of unknown, and it can be cast automatically to other + # types. However, before that, we register dumper with 'text', 'varchar', + # 'name' oids, which will be used when a text dumper is looked up by oid. + adapters.register_dumper(str, StrBinaryDumperName) + adapters.register_dumper(str, StrBinaryDumperVarchar) + adapters.register_dumper(str, StrBinaryDumper) + adapters.register_dumper(str, StrDumperName) + adapters.register_dumper(str, StrDumperVarchar) + adapters.register_dumper(str, StrDumper) + adapters.register_dumper(str, StrDumperUnknown) + + adapters.register_loader(_oids.INVALID_OID, TextLoader) + adapters.register_loader("bpchar", TextLoader) + adapters.register_loader("name", TextLoader) + adapters.register_loader("text", TextLoader) + adapters.register_loader("varchar", TextLoader) + adapters.register_loader('"char"', TextLoader) + adapters.register_loader("bpchar", TextBinaryLoader) + adapters.register_loader("name", TextBinaryLoader) + adapters.register_loader("text", TextBinaryLoader) + adapters.register_loader("varchar", TextBinaryLoader) + adapters.register_loader('"char"', TextBinaryLoader) + + adapters.register_dumper(bytes, BytesDumper) + adapters.register_dumper(bytearray, BytesDumper) + adapters.register_dumper(memoryview, BytesDumper) + adapters.register_dumper(bytes, BytesBinaryDumper) + adapters.register_dumper(bytearray, BytesBinaryDumper) + adapters.register_dumper(memoryview, BytesBinaryDumper) + + adapters.register_loader("bytea", ByteaLoader) + adapters.register_loader(_oids.INVALID_OID, ByteaBinaryLoader) + adapters.register_loader("bytea", ByteaBinaryLoader) diff --git a/backend/.venv/Lib/site-packages/psycopg/types/uuid.py b/backend/.venv/Lib/site-packages/psycopg/types/uuid.py new file mode 100644 index 0000000..33d8acd --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/types/uuid.py @@ -0,0 +1,64 @@ +""" +Adapters for the UUID type. +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +from typing import Callable, TYPE_CHECKING + +from .. import _oids +from ..pq import Format +from ..abc import AdaptContext +from ..adapt import Buffer, Dumper, Loader + +if TYPE_CHECKING: + import uuid + +# Importing the uuid module is slow, so import it only on request. +UUID: Callable[..., uuid.UUID] = None # type: ignore[assignment] + + +class UUIDDumper(Dumper): + oid = _oids.UUID_OID + + def dump(self, obj: uuid.UUID) -> Buffer | None: + return obj.hex.encode() + + +class UUIDBinaryDumper(UUIDDumper): + format = Format.BINARY + + def dump(self, obj: uuid.UUID) -> Buffer | None: + return obj.bytes + + +class UUIDLoader(Loader): + def __init__(self, oid: int, context: AdaptContext | None = None): + super().__init__(oid, context) + global UUID + if UUID is None: + from uuid import UUID + + def load(self, data: Buffer) -> uuid.UUID: + if isinstance(data, memoryview): + data = bytes(data) + return UUID(data.decode()) + + +class UUIDBinaryLoader(UUIDLoader): + format = Format.BINARY + + def load(self, data: Buffer) -> uuid.UUID: + if isinstance(data, memoryview): + data = bytes(data) + return UUID(bytes=data) + + +def register_default_adapters(context: AdaptContext) -> None: + adapters = context.adapters + adapters.register_dumper("uuid.UUID", UUIDDumper) + adapters.register_dumper("uuid.UUID", UUIDBinaryDumper) + adapters.register_loader("uuid", UUIDLoader) + adapters.register_loader("uuid", UUIDBinaryLoader) diff --git a/backend/.venv/Lib/site-packages/psycopg/version.py b/backend/.venv/Lib/site-packages/psycopg/version.py new file mode 100644 index 0000000..b6c68c2 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/version.py @@ -0,0 +1,12 @@ +""" +psycopg distribution version file. +""" + +# Copyright (C) 2020 The Psycopg Team + +from importlib import metadata + +try: + __version__ = metadata.version("psycopg") +except metadata.PackageNotFoundError: + __version__ = "0.0.0.0" diff --git a/backend/.venv/Lib/site-packages/psycopg/waiting.py b/backend/.venv/Lib/site-packages/psycopg/waiting.py new file mode 100644 index 0000000..0a80834 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg/waiting.py @@ -0,0 +1,424 @@ +""" +Code concerned with waiting in different contexts (blocking, async, etc). + +These functions are designed to consume the generators returned by the +`generators` module function and to return their final value. + +""" + +# Copyright (C) 2020 The Psycopg Team + +from __future__ import annotations + +import os +import sys +import select +import logging +import selectors +from asyncio import get_event_loop, wait_for, Event, TimeoutError +from selectors import DefaultSelector + +from . import errors as e +from .abc import RV, PQGen, PQGenConn, WaitFunc +from ._enums import Wait as Wait, Ready as Ready # re-exported +from ._cmodule import _psycopg + +WAIT_R = Wait.R +WAIT_W = Wait.W +WAIT_RW = Wait.RW +READY_NONE = Ready.NONE +READY_R = Ready.R +READY_W = Ready.W +READY_RW = Ready.RW + +logger = logging.getLogger(__name__) + + +def wait_selector(gen: PQGen[RV], fileno: int, interval: float | None = None) -> RV: + """ + Wait for a generator using the best strategy available. + + :param gen: a generator performing database operations and yielding + `Ready` values when it would block. + :param fileno: the file descriptor to wait on. + :param interval: interval (in seconds) to check for other interrupt, e.g. + to allow Ctrl-C. If zero or None, wait indefinitely. + :return: whatever `!gen` returns on completion. + + Consume `!gen`, scheduling `fileno` for completion when it is reported to + block. Once ready again send the ready state back to `!gen`. + """ + try: + s = next(gen) + with DefaultSelector() as sel: + sel.register(fileno, s) + while True: + rlist = sel.select(timeout=interval) + if not rlist: + gen.send(READY_NONE) + continue + + sel.unregister(fileno) + ready = rlist[0][1] + s = gen.send(ready) + sel.register(fileno, s) + + except StopIteration as ex: + rv: RV = ex.args[0] if ex.args else None + return rv + + +def wait_conn(gen: PQGenConn[RV], interval: float | None = None) -> RV: + """ + Wait for a connection generator using the best strategy available. + + :param gen: a generator performing database operations and yielding + (fd, `Ready`) pairs when it would block. + :param interval: interval (in seconds) to check for other interrupt, e.g. + to allow Ctrl-C. If zero or None, wait indefinitely. + :return: whatever `!gen` returns on completion. + + Behave like in `wait()`, but take the fileno to wait from the generator + itself, which might change during processing. + """ + try: + fileno, s = next(gen) + if not interval: + interval = None + with DefaultSelector() as sel: + sel.register(fileno, s) + while True: + rlist = sel.select(timeout=interval) + if not rlist: + gen.send(READY_NONE) + continue + + sel.unregister(fileno) + ready = rlist[0][1] + fileno, s = gen.send(ready) + sel.register(fileno, s) + + except StopIteration as ex: + rv: RV = ex.args[0] if ex.args else None + return rv + + +async def wait_async(gen: PQGen[RV], fileno: int, interval: float | None = None) -> RV: + """ + Coroutine waiting for a generator to complete. + + :param gen: a generator performing database operations and yielding + `Ready` values when it would block. + :param fileno: the file descriptor to wait on. + :param interval: interval (in seconds) to check for other interrupt, e.g. + to allow Ctrl-C. If None, wait indefinitely. + :return: whatever `!gen` returns on completion. + + Behave like in `wait()`, but exposing an `asyncio` interface. + """ + # Use an event to block and restart after the fd state changes. + # Not sure this is the best implementation but it's a start. + ev = Event() + loop = get_event_loop() + ready: int + s: Wait + + def wakeup(state: Ready) -> None: + nonlocal ready + ready |= state + ev.set() + + try: + s = next(gen) + while True: + reader = s & WAIT_R + writer = s & WAIT_W + if not reader and not writer: + raise e.InternalError(f"bad poll status: {s}") + ev.clear() + ready = 0 + if reader: + loop.add_reader(fileno, wakeup, READY_R) + if writer: + loop.add_writer(fileno, wakeup, READY_W) + try: + if interval is not None: + try: + await wait_for(ev.wait(), interval) + except TimeoutError: + pass + else: + await ev.wait() + finally: + if reader: + loop.remove_reader(fileno) + if writer: + loop.remove_writer(fileno) + s = gen.send(ready) + + except OSError as ex: + # Assume the connection was closed + raise e.OperationalError(str(ex)) + except StopIteration as ex: + rv: RV = ex.args[0] if ex.args else None + return rv + + +async def wait_conn_async(gen: PQGenConn[RV], interval: float | None = None) -> RV: + """ + Coroutine waiting for a connection generator to complete. + + :param gen: a generator performing database operations and yielding + (fd, `Ready`) pairs when it would block. + :param interval: interval (in seconds) to check for other interrupt, e.g. + to allow Ctrl-C. If zero or None, wait indefinitely. + :return: whatever `!gen` returns on completion. + + Behave like in `wait()`, but take the fileno to wait from the generator + itself, which might change during processing. + """ + # Use an event to block and restart after the fd state changes. + # Not sure this is the best implementation but it's a start. + ev = Event() + loop = get_event_loop() + ready: Ready + s: Wait + + def wakeup(state: Ready) -> None: + nonlocal ready + ready = state + ev.set() + + try: + fileno, s = next(gen) + while True: + reader = s & WAIT_R + writer = s & WAIT_W + if not reader and not writer: + raise e.InternalError(f"bad poll status: {s}") + ev.clear() + ready = 0 # type: ignore[assignment] + if reader: + loop.add_reader(fileno, wakeup, READY_R) + if writer: + loop.add_writer(fileno, wakeup, READY_W) + try: + if interval: + try: + await wait_for(ev.wait(), interval) + except TimeoutError: + pass + else: + await ev.wait() + finally: + if reader: + loop.remove_reader(fileno) + if writer: + loop.remove_writer(fileno) + fileno, s = gen.send(ready) + + except StopIteration as ex: + rv: RV = ex.args[0] if ex.args else None + return rv + + +# Specialised implementation of wait functions. + + +def wait_select(gen: PQGen[RV], fileno: int, interval: float | None = None) -> RV: + """ + Wait for a generator using select where supported. + + BUG: on Linux, can't select on FD >= 1024. On Windows it's fine. + """ + try: + s = next(gen) + + empty = () + fnlist = (fileno,) + while True: + rl, wl, xl = select.select( + fnlist if s & WAIT_R else empty, + fnlist if s & WAIT_W else empty, + fnlist, + interval, + ) + ready = 0 + if rl: + ready = READY_R + if wl: + ready |= READY_W + if not ready: + gen.send(READY_NONE) + continue + + s = gen.send(ready) + + except StopIteration as ex: + rv: RV = ex.args[0] if ex.args else None + return rv + + +if hasattr(selectors, "EpollSelector"): + _epoll_evmasks = { + WAIT_R: select.EPOLLONESHOT | select.EPOLLIN | select.EPOLLERR, + WAIT_W: select.EPOLLONESHOT | select.EPOLLOUT | select.EPOLLERR, + WAIT_RW: select.EPOLLONESHOT + | (select.EPOLLIN | select.EPOLLOUT | select.EPOLLERR), + } +else: + _epoll_evmasks = {} + + +def wait_epoll(gen: PQGen[RV], fileno: int, interval: float | None = None) -> RV: + """ + Wait for a generator using epoll where supported. + + Parameters are like for `wait()`. If it is detected that the best selector + strategy is `epoll` then this function will be used instead of `wait`. + + See also: https://linux.die.net/man/2/epoll_ctl + + BUG: if the connection FD is closed, `epoll.poll()` hangs. Same for + EpollSelector. For this reason, wait_poll() is currently preferable. + To reproduce the bug: + + export PSYCOPG_WAIT_FUNC=wait_epoll + pytest tests/test_concurrency.py::test_concurrent_close + """ + try: + s = next(gen) + + if interval is None or interval < 0: + interval = 0.0 + + with select.epoll() as epoll: + evmask = _epoll_evmasks[s] + epoll.register(fileno, evmask) + while True: + fileevs = epoll.poll(interval) + if not fileevs: + gen.send(READY_NONE) + continue + ev = fileevs[0][1] + ready = 0 + if ev & ~select.EPOLLOUT: + ready = READY_R + if ev & ~select.EPOLLIN: + ready |= READY_W + s = gen.send(ready) + evmask = _epoll_evmasks[s] + epoll.modify(fileno, evmask) + + except StopIteration as ex: + rv: RV = ex.args[0] if ex.args else None + return rv + + +if hasattr(selectors, "PollSelector"): + _poll_evmasks = { + WAIT_R: select.POLLIN, + WAIT_W: select.POLLOUT, + WAIT_RW: select.POLLIN | select.POLLOUT, + } +else: + _poll_evmasks = {} + + +def wait_poll(gen: PQGen[RV], fileno: int, interval: float | None = None) -> RV: + """ + Wait for a generator using poll where supported. + + Parameters are like for `wait()`. + """ + try: + s = next(gen) + + if interval is None or interval < 0: + interval = 0 + else: + interval = int(interval * 1000.0) + + poll = select.poll() + evmask = _poll_evmasks[s] + poll.register(fileno, evmask) + while True: + fileevs = poll.poll(interval) + if not fileevs: + gen.send(READY_NONE) + continue + + ev = fileevs[0][1] + ready = 0 + if ev & ~select.POLLOUT: + ready = READY_R + if ev & ~select.POLLIN: + ready |= READY_W + s = gen.send(ready) + evmask = _poll_evmasks[s] + poll.modify(fileno, evmask) + + except StopIteration as ex: + rv: RV = ex.args[0] if ex.args else None + return rv + + +def _is_select_patched() -> bool: + """ + Detect if some greenlet library has patched the select library. + + If this is the case, avoid to use the wait_c function as it doesn't behave + in a collaborative way. + + Currently supported: gevent. + """ + # If not imported, don't import it. + m = sys.modules.get("gevent.monkey") + if m: + try: + if m.is_module_patched("select"): + return True + except Exception as ex: + logger.warning("failed to detect gevent monkey-patching: %s", ex) + + return False + + +if _psycopg: + wait_c = _psycopg.wait_c + + +# Choose the best wait strategy for the platform. +# +# the selectors objects have a generic interface but come with some overhead, +# so we also offer more finely tuned implementations. + +wait: WaitFunc + +# Allow the user to choose a specific function for testing +if "PSYCOPG_WAIT_FUNC" in os.environ: + fname = os.environ["PSYCOPG_WAIT_FUNC"] + if not fname.startswith("wait_") or fname not in globals(): + raise ImportError( + "PSYCOPG_WAIT_FUNC should be the name of an available wait function;" + f" got {fname!r}" + ) + wait = globals()[fname] + +# On Windows, for the moment, avoid using wait_c, because it was reported to +# use excessive CPU (see #645). +# TODO: investigate why. +elif _psycopg and sys.platform != "win32" and not _is_select_patched(): + wait = wait_c + +elif selectors.DefaultSelector is getattr(selectors, "SelectSelector", None): + # On Windows, SelectSelector should be the default. + wait = wait_select + +elif hasattr(selectors, "PollSelector"): + # On linux, EpollSelector is the default. However, it hangs if the fd is + # closed while polling. + wait = wait_poll + +else: + wait = wait_selector diff --git a/backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/DELVEWHEEL b/backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/DELVEWHEEL new file mode 100644 index 0000000..bdffe67 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/DELVEWHEEL @@ -0,0 +1,2 @@ +Version: 1.8.2 +Arguments: ['C:\\Users\\runneradmin\\AppData\\Local\\Temp\\cibw-run-9hvmegor\\cp312-win_amd64\\build\\venv\\Scripts\\delvewheel', 'repair', '-w', 'C:\\Users\\runneradmin\\AppData\\Local\\Temp\\cibw-run-9hvmegor\\cp312-win_amd64\\repaired_wheel', '--no-mangle', 'libiconv-2.dll;libwinpthread-1.dll', 'C:\\Users\\runneradmin\\AppData\\Local\\Temp\\cibw-run-9hvmegor\\cp312-win_amd64\\built_wheel\\psycopg_binary-3.2.3-cp312-cp312-win_amd64.whl'] diff --git a/backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/INSTALLER b/backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/LICENSE.txt b/backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/LICENSE.txt new file mode 100644 index 0000000..0a04128 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/METADATA b/backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/METADATA new file mode 100644 index 0000000..f52fc6f --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/METADATA @@ -0,0 +1,70 @@ +Metadata-Version: 2.1 +Name: psycopg-binary +Version: 3.2.3 +Summary: PostgreSQL database adapter for Python -- C optimisation distribution +Home-page: https://psycopg.org/psycopg3/ +Author: Daniele Varrazzo +Author-email: daniele.varrazzo@gmail.com +License: GNU Lesser General Public License v3 (LGPLv3) +Project-URL: Homepage, https://psycopg.org/ +Project-URL: Documentation, https://psycopg.org/psycopg3/docs/ +Project-URL: Changes, https://psycopg.org/psycopg3/docs/news.html +Project-URL: Code, https://github.com/psycopg/psycopg +Project-URL: Issue Tracker, https://github.com/psycopg/psycopg/issues +Project-URL: Download, https://pypi.org/project/psycopg-binary/ +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3) +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Operating System :: Microsoft :: Windows +Classifier: Operating System :: POSIX +Classifier: Programming Language :: Cython +Classifier: Programming Language :: Python :: 3 +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: Topic :: Database +Classifier: Topic :: Database :: Front-Ends +Classifier: Topic :: Software Development +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Requires-Python: >=3.8 +Description-Content-Type: text/x-rst +License-File: LICENSE.txt + +Psycopg 3: PostgreSQL database adapter for Python - binary package +================================================================== + +This distribution package is an optional component of `Psycopg 3`__: it +contains the optional optimization package `psycopg_binary`__. + +.. __: https://pypi.org/project/psycopg/ +.. __: https://www.psycopg.org/psycopg3/docs/basic/install.html + #binary-installation + +You shouldn't install this package directly: use instead :: + + pip install "psycopg[binary]" + +to install a version of the optimization package matching the ``psycopg`` +version installed. + +Installing this package requires pip >= 20.3 or newer installed. + +This package is not available for every platform: check out `Binary +installation`__ in the documentation. + +.. __: https://www.psycopg.org/psycopg3/docs/basic/install.html + #binary-installation + +Please read `the project readme`__ and `the installation documentation`__ for +more details. + +.. __: https://github.com/psycopg/psycopg#readme +.. __: https://www.psycopg.org/psycopg3/docs/basic/install.html + + +Copyright (C) 2020 The Psycopg Team diff --git a/backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/RECORD b/backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/RECORD new file mode 100644 index 0000000..8840822 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/RECORD @@ -0,0 +1,21 @@ +psycopg_binary-3.2.3.dist-info/DELVEWHEEL,sha256=YmNu4gY6MYk1zT7h81r7yN2kAJI7ZWe_A5b7WG1M6Ng,459 +psycopg_binary-3.2.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +psycopg_binary-3.2.3.dist-info/LICENSE.txt,sha256=fTqV5eBpeAZO0_jit8j4Ref9ikBSlHJ8xwj5TLg7gFk,7817 +psycopg_binary-3.2.3.dist-info/METADATA,sha256=ffwpoxVjgjYMtzBiO7hR3H0_rzKMcaBexr2-u8uZ1Zo,2903 +psycopg_binary-3.2.3.dist-info/RECORD,, +psycopg_binary-3.2.3.dist-info/WHEEL,sha256=3vidnDuZ-QSnHIxLhNbI1gIM-KgyEcMHuZuv1mWPd_Q,101 +psycopg_binary-3.2.3.dist-info/top_level.txt,sha256=8OM_PsAa5oKkzVvRu8kDESihBQo_LXqwG_nrlecubIk,15 +psycopg_binary.libs/libcrypto-1_1-x64-15ec4b7b2d8017a72acf488cff1a1c38.dll,sha256=8p4Xaq76dQpU2oSizZF1dYRfu37lWI1TogQqNAlWaAY,2878976 +psycopg_binary.libs/libiconv-2.dll,sha256=zxMXOPS1_j9C6RCOJFlfw-ZXM0fXjk5p7EIQbB7r5Cw,1851113 +psycopg_binary.libs/libintl-9-6b2fa35014185f5e79c4c76df54d19ae.dll,sha256=ESWsjcDE9cPtRxLg2K0pR0CZ_LVbsOVjo1LOnQPvHXg,475769 +psycopg_binary.libs/libpq-de0d6d7eef3cda3760db155fac0f1d34.dll,sha256=uir45E2pz2qSk5-t-NajqQvWI9TGkBUtizbKuYlqKDw,308224 +psycopg_binary.libs/libssl-1_1-x64-56850767f4919548e5b00c9d311d045e.dll,sha256=R0BHmyye631jqqJGcgoP7-EsBrdZd0N66rEJmKp_M2Y,686592 +psycopg_binary.libs/libwinpthread-1.dll,sha256=_-LVY3W7Tove6QN99r78UBbd2IcdDYUCcxTdV5L4_ck,52736 +psycopg_binary/__init__.py,sha256=4T4K9dajJtHgy5P4TZZLpybxZH6UM2lyd_bSogyDoe8,755 +psycopg_binary/__pycache__/__init__.cpython-312.pyc,, +psycopg_binary/__pycache__/version.cpython-312.pyc,, +psycopg_binary/_psycopg.cp312-win_amd64.pyd,sha256=t5mf20Ld-sY53vesacxtQoXPS9iD7QRyZHjkIQfh_j0,669184 +psycopg_binary/_psycopg.pyi,sha256=0v5aDSJFWe5k-CdutT799zrJjCrGyI7YN4PvrlyVsRY,3322 +psycopg_binary/pq.cp312-win_amd64.pyd,sha256=4EdDrS-kmTXIlMrNkBPUNM3F2-0dQjU6VkDfXI1YIsU,284672 +psycopg_binary/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +psycopg_binary/version.py,sha256=K_wT8GlZNR5_XxaeCzavlI4pZhs90InDwJ3tnoT25jE,248 diff --git a/backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/WHEEL b/backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/WHEEL new file mode 100644 index 0000000..e4b52df --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: setuptools (75.1.0) +Root-Is-Purelib: false +Tag: cp312-cp312-win_amd64 + diff --git a/backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/top_level.txt b/backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/top_level.txt new file mode 100644 index 0000000..1a1eb79 --- /dev/null +++ b/backend/.venv/Lib/site-packages/psycopg_binary-3.2.3.dist-info/top_level.txt @@ -0,0 +1 @@ +psycopg_binary diff --git a/backend/.venv/Lib/site-packages/psycopg_binary.libs/libcrypto-1_1-x64-15ec4b7b2d8017a72acf488cff1a1c38.dll b/backend/.venv/Lib/site-packages/psycopg_binary.libs/libcrypto-1_1-x64-15ec4b7b2d8017a72acf488cff1a1c38.dll new file mode 100644 index 0000000000000000000000000000000000000000..074f7739d5ed08d118ee47591ccdb6030c0946e1 GIT binary patch literal 2878976 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 Ot`N3u}?c~IkITiDK4}cekxY+}pt(~fs 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

    K*p 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%0AD*ypq;cQ_W6+A&n%Hrcp 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

    PF;ylMNf;cv-|U@>%mpj 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 VS~bwBfmRK)YM@mE|KV!j{{csQ7H0qe literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg_binary.libs/libiconv-2.dll b/backend/.venv/Lib/site-packages/psycopg_binary.libs/libiconv-2.dll new file mode 100644 index 0000000000000000000000000000000000000000..7723625bc01be9ef73221ac655a17cfecb61d3ed GIT binary patch literal 1851113 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�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ⅇ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%0AK&+1dW6vJs=fSf6P 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

    ={YAY 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

    Fw!_ne`b$_Id7A?n%y)|CxUby$HPmeF}XK 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బNADVLr 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

    L#wiZ{7US&0k$xr7*U$ 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

    %ni;B&8?r?FxPp*b>sWO zzpu~_U&z07|J?U85I~x(!h$K zijF>S#Yly!Qdc=7TQA!n8eQ{aeYXo>cuu`CsM#l)oxpd18SkK*MM@Ydf?v+D@%Y z+ogS0`8z($X}h&O+Fos+)~%h;7a3kLUNs&u9yJ~_9ygvazGnQ?c+z;vIBE0? zr;O9a*Ntx&-!#5woF8z-c-lB){KR<1_?Gc)<5}Z7MwhwWTwGsLUs_*QFRT~Um)DEy z2O9opc-b;$*=-4KTmxCOwrO2cf73wIuBJ^DAS6o+o*OIP;uBCW2v5VJr!?mm{ zscU&xa#u=MQCDhLS{EPRx$xZVbK>p=JxtFZJ+#-~^Cu+GUp@1BZ|j}kyP!9*H=vj4 z#ro-6-S=GIs=kC1-@AW+tohOXlly1<`-}UZ?ti(XBLD4vDDpq<|GEoB|8xK9{>}Zn z`=6Oq(*Hugum8W%Tj6Ed)<4>>8TfecncJ5PB@8VcTD3TFh&Qxs=n^E= z<-w$(^r4KQD}$LsSwn%huNcZ6axU)hc6wdjF7LD6=e(;Rle)b< z-d=B?_a(2}>+!DkKJQ)QUF%)v?Z@}vNx}1=cgVZmyTLo`_2PdK@grWzM(M`6jSDw% zo1B~4H?7(9ug(A7yuml@^ZG`7FZlNRHv0DZ+I^dRn|)h+y*{6BtM8LL;DhuzeA|4x zeEzN9Z~JcB!06y;->7@kGrDj4{_Q`&#B15<7w*}$ch|mMvoBwI`S{q0vDd~Wc-EkQ+wXpGYQ5s1#H--sPEhF-tXDJdVl6b*2Id5 z?1`L-+=+sTyovmYl@q1|TF5TlfxRjE1N&0&$qxQ`@UMgO4$VKb;84IJ<`6l=9!fa; z#^DQxTW)!ej2uZk$~&q%raxvlW;|v+W;$j*R)4JFnB`c|iNCK(@QKV5AtyplEIJW( zBK$u#*Q@vkrb{RQ@N%fnwEd~o!e?ce%^_1|}P5B}@)Zvs(Exvjjle5Is7 zQYaBfiX_F75=p6~Od^zsB;^vZL?YQG9hXK{L{%J;y)N4*za{@eezIz$`VNI(xC7Gg zIn^pvx2i|gtLjs^RUXx9)$^(~soEhMU&< z=K7ZUtymPtEhj8*G`-n$vFUWvbkj`JnWpD$AR0Dx>)MITkh|M8yR z*E-KRk2;Szk2_B|bG9$uBn^Pcdda` zTHCd*tG{cYYq0CZuA#1vpBr6O(cRm9XU|ZH?=pdm*1Pwo7tNM z8MUJK`Mx!MgPux{+*9SL_9#5hN7i_h9+juoQ|D28Hh451tw-n4dkh|<$K>&P%$|Br zgU8}o8`o61o)(YI)9PvS*gX!hK7f{LnA{k41F@VacI-f=AplL#+D)9(AJ@CL!(36ho**J9NICo zb7s>Uj5Mfk@uqaWA7#J zW$zX5P46e(PrXmvx{B|>AL{+gd(Hc~cg}m=d&B#M_e<}mw}0jR+S|WzC0R-)Y~B?~Ly)-;F!o_MP?J@V(He&&anA7_4=`StD1XWu>h_N|>~-#Z(BZppcXb6S=Vq_Z-kAMj_RHC?X8(O({D)~5`4`hK{^#O_DO~%Udf1Lk94neTgCVzw^iO=sjoCt8Y?$fUXgtw`&71DKEEows;%l& z)nt{jc6;>>Wa{@S{#5;?npZo&_MzGZwE?wEEvaQ|Y3*&bLAAHn-cfsJ?OnAG)JD`c zsP3*^Sj*MkQ+sdieYN-3KCXE}^Q7i}-Cx>yy7{^Vx&R%cy8{Wvtd8n#(|=Ai(qy<9WePDxn_^6hO|hmpQ@m-3DZ#YVlxWH^@l5N@8?ez=*FRssraryF zFMP-HzouWCerx)@DGD)yT`lk7d7Ew2w%zukZHH~AZI|sO+sn2`+LU&cz1Ci5SKCiH zC!Ke;PdTR{weD(P=e)apVY{N8Yrm)cb?3e9e&HL=?>fHkxY6}R*Oy&ib$#8nzN_F_ zzwn!`Z@a$hn*Z$gT|adF-1TGEPhG!s{j=*|UH|U-PuG9D{@3+u*Kb|Fcm3IQv+GvZ zA6<35>RwH+wpZ7y@4a*N-K$U1g{!&MyXXU}Kk{7keC)a8x$L>(`NZ?7=c?x)p3gkj zJfC~!Jl8!pJYRUe^nB&{+VhR)ThDi%?>#?wepvmZ=O@q4o_VW(@i1%sLbCSXHxIA- z{pQF0m-;XFU+Etonzw%b`UUF))-&tLdUk#Kdb<9$^|!CTWBrk#JJ;W}{%=WhH=Y-+ z=hok|{@(TXtxsHk|M~~k?}2Q4ef@*$A6ozL`lm*o9(iUYaKtYR8VMfp#)piAjw~7p z8wnqY7>OK-8lfZ6BQYb3N4|me7&{U-l0OnZvSegqd;)%A=}6)TZ=`bL(8jMf9@}($ z(}_*5ZF+lC(U#R)O1Fe>x#j!A=lA{T`^#rfn74KQ)&*O?@O|kE*vf1rTiLC2>-}4A z+j{%fuY7lGy>shbTkqWVpKW)H9vFS{#gtoXcC6houw&hh{vGVjzMVlY1-}&XQs_&I zUJ83D{H1@se0*8(?)!E_x9@&n_k+71+WqkEM|MBDyKwhoyC2{E1YUn~_fxx{-u=w( zcgFYG&W)cRe|P*n*o^Ow-?R7Lz4z_CfA0f(xxEkWeQ58)dlQyFviHos(f!-^@7n+3 z{=*YTCXP-Vn>apkV&cNYnTgjXPEMSfn4FlJn4Wlj;*AOAt+4~U4~!q!b71d*eFsh+ z*neQ+z;w$09eCxyfdj9nyn5i^0qr5(A^jo4A>$#_A@ia7Lk)*4hu|YRoPIdt@HdBr zM@2`=kBW~D9b12F!?EFG-eV)jUO2W9eyUB!HXqw^?C6POCyqnTojCE@iBtIZAG8&rJU@{nqr`(`TpOnLamte!A!Ncce=}pEchVc1Lgzr0s8^{ zK=z^h!{Uo27fUZb`tf5QKmM^__yq9irN=Jy-T(a6hRc@A>fFZ5O_!~gn=iLqwq0($ zocw9Zr>URHK27^H>(ez?w_ja*b=}qet9!2wTy4u6ygGDs{nb5J|1WRD)#0n#uI>hN zL;UXg{Ob#@2V7^alk2Ci&s_HlCvF^s&)hHk^^5zz-1b%P|0D0b!;<{}f8Vy9nxnmU zYFo`&nJYDC;>>|YhB$L1E;KO#6G6d+gx~}P1QitrqbyBRGs_e-ZCH*RWz#zEzUQBF zo$H+Icb)Uc`RDxcE-*fRiu=A_-tX7z`FQXlvE=cGixa4cq>1E-yA#r>hf|NHvOkkP zlRvx6xXvs(l+RVnG3V}oUB19uNV@LmnCx`dDaGljbEk8c^E2meXE3vN?sb0c%!BYj z7k#tqMpwA&at|L5k%!o$#`A(xj&H7So^QTyfiK0k(3k2v?fbx&=8N_{=zkV=4rUM2 zg!z)3U=A?EGHsX+Oc!<@rU%o9-Gmvyf|f_Iido=M6eKbh)P5iV$s1g=y`Bo@QdL7;FrON z!VZTW2?INxuwx)E?6<%Bc3s4xgCL?lVqet$sPO39(HTf(`XFy0 zVaTn>o5*d*0OX3em0*g#DsC~>F3~>GA<;3>De+n&G*SA~IT4cRlIWV~mgo-ZqDP`< z;`KzY#Ft5+2b}DatbX_W-HepSDfpDklpJ&}`f{3Snpv7_+H~6SI325`q*&3MM6x?vg@Cp`;X27%7}|n-oEc1l25x6ivEAiXkCMv7}wU zvT|PJ9?d^a(V%Ejv?wPiCn-jhQ|YG#pP&!FP@-L?Q>Ia-TXr5)CcUz;^3n3I<>t&q2MeYp^9s|7Y0WIF zEU&Bpy{mQXRqSx~diDnPM)oGQB74z6iS7GKnXSTBWvhW_o7w8@0q$$=AlMNOaZ7lm zyfR)nuY$(}H3spE#jE61fk%rDY#xWlZj}{%8e_3=KUTdNkBF^k(Ss(37F|p^l+B^QS|dL+3`cN6bfbMz)Xc z7~MI#YjpSMo>Amz%;=xdM`LYckH?;jwS&s>-~;W$)A7#n*^e(jUYanQpidM}luUF? zJ)JrhZkVc3Q(gZo{a?Yj5Ma5OgHOMvCb+x;|eT`?6XEWI3{PB(1`PX*|bSZQhbUAbd zbS3ySkwpgu=xXR1=vwGH=z8b|=td9>{&$2I9W?ymFfdbrrNR)f=$qI82D}(v0xyL( z!^`01@CtZ3oC#;aTfpv5V|gXK3eE^D4s1g_Mm#|XyW0^Rh^L57L>FRf@cUrvFq^Qe zVXMLy9XcbrBA!KbM|d1SMJGj{ak+(rBdd{tNCfgJvI@yVW`aAUAS53djC_(-B{Ok^ciCRQb~6FG_AiQL3DsIjDlq=7^16ix~^r6Hv{g_mND2Ja`DhUTPkK|q0* z#!s90S(8?qR+lD7t50i43p?JJCQNHeYffuP8%}FY6QzmMBx%yL=;NRdn)WEIE$wmI zleG3U158KS)3naCuC!-qU~rn|rm+*Z3+I>apZ+lYQF>eY-}Jxtmt-u>SeEgX;6Yp< zd?RoO-w8hmorTMq(0IMl5UPZG%i2bg_iF~aiaWMdyQg1aRxK# z8ue z-(b&j=eTpcdEOV^SKb2e8}B>s2k$4(y2h$zdu>-OuQs9X&ac>C+XPay#_bo{FSdtvgmr{>-0Mv1#B^diah>U%_d7E>@tv8S1W++%pEY;4bhmbky2ag+ z?w}r>UP!NQ@A+Q6Uj1H!Uc+9a-ow4dz5k9t>vPfb=F2cpLvFrs>G$tILeQ|ot?@QCt&-pWi8R87dI%_5y)R{$x`MEE1U*{I)yuTKHeejj`b;kmA z!P!w6vKyibQG=*M*8kiB5kn*pDTL;--F1g+sOx5T_3Ihey`bJu)_>}U57ZY5h5AAL z!LwXg9xNYL0HeSPVN}=y*lYM8dM`RsRHST@lhs5#3kBOfWClcF#u1j8@?3dh^ z@*<@_H8>BvMe6B+8G%*Hjwq-+Nw3ucCu_TJe+O_Tr?nJreaye+KP1*>nlo`Im}#U9y6a=z_dG0VQ#CeuH>+}Y!&@#Hjm9` z*RX5Zt?W9sfL+gSVDIFtuij9-vHD!~rfS7%rE2Bsef<6W1ALIj;veE4<{#l7CqwWi5;kp)=p8UxKq+8?R?nzs1y8A=bvYb4g=jo z-LJbNdR%&4d)<27dp&w5pKsed|2*tP_=}|eDQkJKM#Et%+${`%y6w6XVT_` zGbiUy&7Yn>GY@vU^XKNZ=gqI`%vXQKFC1DZTG0Ilx-eibZ~}4?atv}D@&uyevd1;d zb+@~}N4rO>r^r+6SqBwB>!A(M#{XP(LTD4T89E28fq@o1Y#3S(djV^JHNvjkoP*E9 zzrcUOzrvRVjv~eo_rtJZZzCom-bI{?B1V5gPJkWyNJBWvUhG6)ntGridwKN|;jSL*|CS{gus?%Q-7JD>#rNj>@O}AEz8~M852<-p+g+Pmmsj^m zFd>)}#5X21CN}=NYEg|zjq{BMg;e1K;k3kMNLFt_mpzp+WW}-)S%<6?oatq&UDZ;ID01*@X zmak_QT5OfSUw~YMEc09Lx595F5Hh}mJ%!~2tO`^JWCwBrKOyE2MPc+XMp)$SuMrCo z-@x8dKlWg(UaUc^VXRTC4oVkw9;JuUM;V|DQAQ|Zlobl3IZ*qOVad;ve}eN;2x>pb z*I*P@*MdhSm_|$~rVLY#slYHXEKCcg5>tg?W3+Hf?o)_`#17(9VkfbS_zawxRAM)= zhuBMePV58EK(dH@o$N*SCa+xAKoL?_t*fClQEDl56al4-a{AYw!rz5&Xj1w^x=Kk^ z8M};A#x1Ka`@l2<=aM?T)C?YIFMj^>`R`}-S4Gh!6Vm3n!*8eGF24`3kFZa$37Bf&Z17xgZP-+3}Z$xZ!n`6<<(>0`KgSRS*x-Xvckw1GM0Rg z45mlqbn<<21{qJjlw*vySDdjA3znTX{WVkcj$K+bQyLTb*Vht)3di{ zU(f!Y17L$d?#=1V>dWpU^^yB>`Z8YNUkLm4UmAjAHaxg%Xute`+){o}en@^;enfuI z@~HfnTuXjJepP-_KJn|6{IvXx{H*+(Tw4xOLvlO0F8KYtTu-hqH;^03jpTxn`Vrqz z=;*~U1i0oM-s`*{d~ZB{_M`iR*`(W~`{bLc(W$Yiw^OClWz*%;n`VyBIL|_6U1qP( zy3V@Iy3cxm<98D*jW46~^Ygu5ofoN5OM<=y|Dl59T$EF66zUEt28BcgBrn4*$F9Jx#IC|BU{_<;VAo>T zVb5W~-#TMg*6yr5S$nfUKRIiE)`2XIEFQUrTuZJa3&`D+pHzjSrlObhUix5Jf0-x5 zr1DuMox|W1b4oa+oH9;1$Fur+^%H(Ozk~mjzp7pVOsF3=er@Cn1;QHPq9jW3kL0gp ziFB!SnRK~yjdX={rF4~4L8|mv`SIq*DvwnkM_tP4$n7xb(d^Lz*HUAjurGSE;Y;%Y zivi1lD+6y{e|SAHxMxUr$X5=N-;@W)Z^_|uggi(dEDw=~%EROt@^JZWd4xPt9wmP= z(mwM3O2^34kG}k6k~k%tR+~9F1Fo9c`?Du(GG_6! znX`mh;%wGz_AF_3{}+`ngJ0Kv>-v5JauWiBJcmI2R@^KMI23p+Ffi6HHUou6olV|| zK8QVpJq+HzBiQvCpmT>khCPnez#3&-$}-71lO-aH$r5ruBLC zX_7qIH{CydXvW;;p4#KthqI4n+h*;*IDB#Z;`HU(7x`DvgMz$(g!xt7-V_OsMZ^Zh zM#tu$a#4Ax%UBPrDR$|7mn_#TH*j7Iko(E6DZ`XO%JK)F%d~aRRPW#L$2wqDHEv=Zu};|0{2_`eOO0h)`IWQ4`NsLee_FSx z{)Q9=-sziCMhCVF*Y&gSy?jbOE&nW^k^hl@7#Sboy?y&Od3C{nkw79AAp=b9p= zQPS)#QrD8iw>dKOSUxA-mBsw-V7F3Vnlfy@by}%g}pS6{{_J#KF z?-9gY(A=XRHQSKbRW;Pdr@wA^fsNG%-^cK)!LZ@*{{RF2uO9y2^1+wDH~X&`VJq;O zf1L0?9{C>={Er9r0m~1pf86gsuJ<3y`;XiG$LylO`p4_0gY}Qm{m171<8t%B`XBk* z<;(tS_I49^jUre|U@3#80+uRRYG7>vYb#jWz}gPh4zPBDwHvHGVC@BKA6WarIsn!| zu>NPh_P=6l&w>9&8?65wSNlIRwI<-Tm%%ax>;HtO{eQvI{(sESUOS$ok*1LffUPFY zcFjIbp{7(*q$$>XsTrc#pgE@5sL9o;)#7Lcp4f0w;pFV8ucxL?eLgjDYVy?dDTUM0 zGpoK)fRqvs+yrgucoP~SkmMgNXLqCu=dj6t+PlA(v8o1v9qtYL!TZo@P~tRciO-Z0M4 z(U58^G%hwq8xI*XjBAaHjQPeE7tAh{UQoHHd{OD*n~U8S4_!KP>FA{sCL2r+ny8o< zn5;8VGC66o#bm3Awu!olqKT@>^2HMiq(;m}a(@L`jGm%-N z8Q)B37HCc|-)nKeVyjoBMU@59f@Kk68EF}68D*KUWAe%lt6x{9uZ&tPUfE@(Z*|40 zNes`|5z*7c-r(`l}H|6eR#E1^5m+G?H*fg+jF+} zY!BM*wLN5Oy2{vA-}Zp5iS1QeTieUF7i=%up0_;?8X0oCPWuk~LHk$s1NOc4?e;zP zefB@>y8%|?>40%i`Olm&-zmu{&MDR@7i2i{oU)yePG~2KYXorfdI=H+dU_`zCJ=YX zPDnUJ6Y@l1FJuSgljJC57vu~?(QTvKtYm|mlAE%dy4xDJO>Q|LdrNZ5b<1`myV#CQBm$O%p7u4&PmovzLc=)>bUh|FjEd!|#S6??@n6HzsyYGzeQ9lj8 zV}6JIV176Kh<@3Ad4AJ=vwl;4AN@M~hy4fr4PaMcfiNU27M2Wy!*0N!pgWlYW~N23 z$(!SAKipIV)Sh0zwgBCLivimK%eNz7XMpmp4Yw2kpOA2?{%j&37Upl&!yDlZ@FsX2 zn1<{P)I%5|v=NpF6ry&WF~SC6glJlK5~P21f^vd#gOq|d04f0!yd&gVh;xW<2qffE zh+>FMh#TOP%|ha>Y(st|riR`P{Sx{$bPi-sOvCM@mf`2Z7sF15n}A$!|N1lGk8V3l z`)?}LBHbe0BMl;lqWYt{qpnL?(Vo)c=r4B; z#Ebw+VGghg%VK8l{JqnA=hdC(fMkG5rvTY7bLZuqH8EfBh+`kdK8wxSD2ja)+ZWpv zn;)MWp8<%4qW_V_}XT)SQNfR>eWWX{CGqN)LGOlN!GTbsC8L=5T88vK zKZu@L?pfAZE?M4Lj#+kD3V^KolC_YvB6~4wW%d!0GwBk^gJeiL0rE30Bp;BVu_xJ) z3_w<9LD`$+4$?FiNM0aiqe;3>(gz`gdGa)QitLu-o8zA2m2*AEFJ}bgl;7nP=jP{9 za|?1~Hdo{_a_OK|e<*)jzF_l?eAWEz`CIaLN2!OX`>7|Xd#FdKr>V!Nr>F<07pa%1CV(>5rS5pJ^TDnM3lEBE zX*3EALrbMGX=qv@jYy->?$PKpD(wO7ZxL`l(7zXbD_TlVrKiy&=|S`;dJ;W_4nR0M z1aM!@3{QqPV85<0oEVM_I|h{D%TO;?E7mL?C~he}p;}$cD&`bFD;5-=Qhi>`EoK*Y z74wVhieD5LsOpv<0Yun^@{8qX%8!?8l`Ao~fNaiIkkEOrx`BC!d58ImInR8_e9C;r z>|pjVyO@2<7tH6(er6~0HM5r~XFg>KSamEhOTzkD`J-}o)y}FU-;yePRbf?56|ss? zRa})_Rn9JBSFo9E7JD~mAE$yt;$(7|oFcIIq;SZbI1ZIlz{v%>Py*P8KH)y*wsAYS zx2vC2>#Fxw4^~f9f2{soJzf2yT3)TjH{~brbNEy~nvdt_@hSXtegXdhzm%WBzgT;& zR;Tu4tzNBm?dpf^waRs>b^Gcz*KMiWTc;@4BRC-_7SO@;ohi6k533KZkE-{pkFM9- z5?LQq&)w49$ZPCq>~G{Y@*7_^K5A@e>}l+6tZ9@sK5cAltZsA%JgIAQZgW;MshQZE z*__dw)4U!KCmR7}q6D~;ycYAV{1*GIJ6iX&?rnVzvOT(@#beLlJ2eOz85%f^Pnz{w zK_?!ZkX0(5R6mJ0x$^X{Q;VloonCVK@2NkhYEQ2`qi{xew(%_XT(thHHVv)*Q%%|@FIHmhxPZS`z*Yz=KSZIf)XZBuP2wl%gW+cw*L+Z@|0 zTeL0S_N?uF+Z5XpTaxW3`(gVgr*HNX_9OP=_HXPz+E3fRv!AqwIy`a^JBS=w9V8B0 z9IKq@z(?}HiSJbGv`c~EROVFTR0c_hBtZ%xX^><{CZq(=fOtp>Bn~nu$%hmJrk4bq z5dC0Bi-s^DWXKM;t!{;GR5yxSft#oMb@y<0sC%=!$X)2(;@;@qDB3_;QhvHwRf}cXWs$e*S;@zKkyv}iKiA{wr{C#h3^;ND&HDkf$yMit8blek*^G- zpo)F@z9qg)UlzzkaeaULYWbb?%k}&2x8V21f5QKb|6BhESO6?-iTX>NRVd_MchD$*TE5Y z5J-eUP+?F((2n3;!Fz*A!L;Do;0M83!Q^062pZ7&m=G&z3b0OCh9rgD4T-kGhj2sw zg#HS(3wI883%3p*S`P_-b9><#IB?7y7p)A+9V?)b6zk@%kYp?F#RO#EQ{yZG7oC-LL)AL1X!%i}xa z9|AJ*Enp9SCH_wQleiqU1htsB5=?wbQG8TL((R` zlPdR30h#%jdv`%|2a7_8kU>t-w6MyvK+zA21uRXbcB~ z#f)Q~V76jgG3&7(F`qC~>0{|{)5p_$(?`>99C!vi8j_4B8J{xv8ABOO8SgV5XG~^P z13Sy}jMj{g880#hlpbctlsbTMqc`Ji#yIeB)BZIsqQ6VO^{uV}5b1{$9xr1jCJXkyv`?J4a9eLtN9GHQkNTzWD?LG>0R zfDyq6WF#_z7$`;*Ba#u$2w~i1Y%QKEHat98JW;$*{JHo`@pSQg@lyi65RZeQ+O?f}?r$MVn8lnPCz5%VN7j`^Osz%n9ZU^Aqy} zbCLOuInDga{K1?BUHUIlC6=7^iX~$WvYxZvu;i7$E06pqdD~W1T~!Y9x56r3RZrEw zd3h~+1xJG;;uLZkIPGdZoadZA&I`^%PA#XJQ^S#P>N$@%{oE0diF?VFaaDQid7F3} zd4H-`@YVrB>TmUGo+3}3w;51UYj_91Ed3zg0?Yw=`7iiVKAT_37x7y`pShDS;Xmd- zuJL>0L}UAw_l;AH9~)N-mk8fA z{%-VXzTWKBd~j=ivl?JS_q3?AY->>mB-NFzvn`HWXIhT59%wz*dc5^T>k83IQKpC> zDiN>I*r&BkYope7t<_q*;2jdmN#)bKPB)%zIW0WB`plX$&@+$E9C5jSF8!Q|j*SjN z=aPOgd~&YwE3c^<1*t(UGx*JJ46_0sh2>k;&j z`gns3gO7%th7S$94WAhH7`7Sq8hRPNF??$H$ndRUxzTgu*T%iZgT^)&u3p%2ar|PS ziI>R@6F-w^6MqwgiH}K)i2}gMZ<_j=J~!(#>oFSwuwKHB}Y|6{+=0q4-}(BZJn@ukxQ(##_@{+uO+dg!f_Zv)aBbVLrK9+8irAaX&zHxrSH$U~F_?FJMoH@G^uF1R~{7g7Vf zG7{jMsSarfX#}2`PT-uW3&{vw9=0MZG(0N&b~rXXCfr_%3l9(fd;8bz#oIHt=WqYM zJ$IWBSr}OrNs3g7R*v2rtrop0x;DBg8W&R)!-`?X$dq?)(>_gdyvyWzLWbe#A4sb~Z zse)8RqJk75msCm0CsmWmNjwst)IcgG)sa{rZTO7zh`coCFL{w1l@py4ne#2@X>Q8q zzTB6&FLL{HpXYk!U&|jUu%JvA3>JJS=m-47n*v$EXhBHfjl$r4;O>#sTeMhO91TVLNn2SoLHkAfNc&9tP5VH5Bb}x#(oWM$={0mNy`El1 z=h5FwF^o(`IwO~{PBo8_&mb@|0L?lGKd%~5a;ikPL`U^pNkEByiD5}#$(<5|5~C6_ zNO2UEQOam#H_L;|5#?d!5#>?kcgkxjK2&%;&&T?;_8DXUTKn>G3Y{jCubORaf{!`~m(Tf0VEA@Za3*CEvEztk$viTJ6=^E49|O z&{})IXt>nb)VbAJ)_H=|w1J>UFf8Z?39AvofPh=is;{V@u5YTh*&?YgtFNkO*6$P^ z7U~L>g%-l&LN(!5p`mcU@R-mK*g{y%Di689AEME6pygo8k(M7V-&z)1{Mk-q4%=#nT)L=?RM3CUAh`?Zc}9oBlJML)6kv8nn>Y3_W>Bs9Q=*Q_x^nV+EGn_G; zGMqL1Zurr7;^NK~c$0J!v`MB3#$@$nyUU-<-kXh@eK4Ccdt-LiBGMwlBHW?|$YuzZ zZ>)x`URcdp{ju6?t!2H{X0_edoh$9ufKTOKZntRr+jg1VCA)17N)D~q}ZxYzNW(_satYoDDQf$OXC8qDRU3j;VC(_AjQU|sIGxVxCRKwPf4#JZTdAYGhY z%0MG5%)Q_Jm3xo-KF>X#`#pDg26@uGqr6MJ5#B}KvEFyRZ+hSMMtc`~BfVq11H8k$ zBfYOcb)d(fnou+75$GZ4C8!2e7kV6e25JgD@At$1r@sJXs~TbTFg`3eAT=N(peTSI za7vngivsBXXX}~}EeHalbKPfrl3^@@q z5;GMu5aTCRK~BdwY}}0e5%WFfU|fK7YuuhVlQ`oz(*)}T%LLnmi-6a+NpMKGl5jO4 zJmFG;eZsW_yM(}m#bdV;920H=iIa2U4%ALm;=Wy|{ixljH>gfj2kI&6G3p5_KPfAT zkVHx%CS@mOB<)Pzm%KOmWAf+Zk>vNuZ|3l5`y2}z$k<-2CYCLgV!N^Luq$y2xcAuYxDSBm zZ^o+Q_}BsLIJOeY#y-Y=#D2p5N&l6;4mF!X+Y<=uC7cUIQ6zO_1ia z0BO!7qQ9~)F(oTKOFR2S_Ni>0>{8MIX@)dMS|p8=CP>qy5s=58BK4ELgG}}?=>zE% zX^ixlw29nKHq&33vp#1-PC`y%4k~A9?(*EZ+|k^zTzT%t-0|Fz+@*P6bKmAJJs6dD zJ3lzzH{T~8ksqFaD?cD#8E_sdlueYQ6gA3niWx|7D*;MvsNgu|7+^pSQ(_7WsJYZ^ zDwdiH*;0E z3f%SFZPm)^>eZ{N)v6Uh0(DLG)@s%2Af7(Y2ykrvJU^Z*FP0a=yTjAqJMiuK*8C+k ziZz>S{__9ur}%EQF0~%DuWO_0uGhip{OUFf_6sfwj0G12Q-U$UC&7&1z2GBAsZI;} z>U-*k>L=?1gb3hDyCM7`ydv}#ItyKe*1}stUm;W&BJ>h&c<3ke6y5}>y@qB%v#`0o zncuA6qS>O`a-!vQ%SAx2$y;TuuUm&&6#=JWDasL%L}XE$s6gX2NTipE*J@BSI<$08 zoIg==V*lxVr}v)jIzu>@d2Ui?L}yB8weCBeX`Qz^6FOr$pLEvhx=MQV#`OC1y7dP1 z;+MVI{#x(3p0&P>eyo0?{!{(GhO3QMi#^q zCV3`>CRCFWlTwp4mrq;{HAR?)nSM5#G1Ip=Z((4eYq5As&m!95jzyG3j%9&mu4SI3 zlJ#2aMXOELTdkK{t6HzOUSq9neb)Mz^=fNP>m$}&iH7wd>oeA+E4SI~vQecQM;3N$LucKY1#ES9B};R^u=l3>AO=6@UG;zWCNpHwM(Iks|(#F&n4ew&!*&r z*Y3maY96~iH9fUFk9!Kd8@*e+8@yk5k9mu{o4uR7`QBo0ns=)AOYe5?8t>QM1KvFE zSKcsaDAX6~0lf)zfI36h=w8x#;J4()AOFAp9k3(Pc33&=F^nI;3aAJu2fl%i@G1Bl zd;&fVA4d#=r1%)(9by{s0)UU2!J=SE@cPh=p$ehup=(0bLi0ikLiyo!;k@vx`kNzE zBHl+1MUF?li`0tN0KSyYXhY;_q$bi7X@s;x9z;4K_ak-UbmPo{0nsSVGVV&;&bW_z zixd9&1kw^nz%-DN5CzNvNeLL>8$c$I6XFu?B)BFXKxv}1P{&b`($}b0sD3b-c#w1? z`C#(y-933m*48Fvkri#v}q#u?#kaW=SfxC^*bxEI*txHGtmIA@$S&J1UO zGsT(U3~?bi2u>I0g7a6>!71Edb$`u$CLWI`;)VEfd?CICUxClWGw^x%QalY`fG@)5 zcp{P*N<tVgxagct0y6%P9N5+nQEv z-au9ddG?LuPo$mX<>YKHH<^9fGk+(K)N#0_vLf)!8rMx?N(Rugs6Z5h8t`r|i1ZBU9Wz-TXo0^@#rJj3m z{(*#cvglaR@gmJ4ts;%0{Y86=_7w%vQGk|9q<7Oh=`ZMg^d3etql3}KXkv6TR+PRd z=`ML*@~h-kNl(dQ$v{be$@`KYCA4x%d13j$k-rsQObFAP>B`h#9b_G5on#$g9b##+ zv{*-3r&y+y=9LbWS1Ro)%_?mxuU0x%?q#oGZ)0y~tA;AFe@ImTU8l@m$9~4{Wp}gt z*w5KL>@DYhN!M_8a1V12a<_Aja(8o2au0BiaJO<#a1T`Ptv*=&FMAwWeS;SP=-zl< z2Jbdc@qQ)mI7sEY@b}g1tT|qzQKMONre=H1;hJMLM{4weN-VVYPHi+WOd)FHY9neR zYvr{!>XPeH>yUM6b?CaJy4X5Yoe8kheFF*8pMsSQf9f|i{H_04zoubN!}(@4{ZunMzUl=9C3i(2eFi&_#m@G^X(u5g8x)3GI62=RYgm_`Guu@17!kPn`JDMLi z_cUK5huF=;UdHkQ(stH6MeZ~3nEP3vf@nn*>o{h=%1`@BR~0M+LrY6ldL zTr?tjBN`TsipE3)af`TFyiUVG>#A1$lFgFR6NgS8KKjfF-))1XOEG87GsgA$!ejvUgz97CMYJ>Per-M6#9|v~@ zw+9~!-5a_yv?;tfTpT{T{z>@mh}p=g$hpXo$ZwG+qjjQBMQcYtjz$1ZHV$yJA;?f< zI5H9$fs97pLHZ$skoIx5ar@%f2^9(S1WH0d0xh97ft65{P@2F=C{K_ioI;&Ook5*N z>41Fn07{0EqlQr$A?kRK0X( zsZuGwthTJKyt!NqEG4G^*`LhRXK4eEs~zhC>nux`WymsOonz^-%vd_C^DI+VRHY~I zOGZ}y^Go_y`c;NjdR2y1{sE>*qpIUb<5c5ZwRn1)vv8zUB9Z{q`|zwxWTN!t^u*dsv%^HL&Hm9i}00jMEC*ZV_yhA3*QUh z3j2ip!cW4fEsesDLdA!O=8)#_=CJ0z=C0-!&2B9&Ee@1(EF|TRc}_Wz+j8fHlyFhe~g!3 zaJ+E*(jya*3DR_xxuu1`f^O+xZDZ|aecjr}dcO_MF4!)@?zUa1U5H(v-66--*A#Zm z0ORE^7e&|gt_v=ITw>kdxa)cbdv5Vj_1WR0=yT3TU8)Y8aff`4_#E{)=CjR5O{!qd z1e_ZUS_P#;OQ9BiEBqJz-PW$Y(F=PN&>XPiR>`f>TTI|d`UU?D{{debxGHExkb(3p z@KBxx#!1c4bD^)o_eboBSQ@n?YI&4UY!H1h`dsvr==;b*WG>)eE09zq2}wapkhhUc zBzq$?&OOd8?qPy7;aS4t1V%zr!t(_0M19m4>I14QiIr5IbS!!G-8FaX(V~0edxCp! za1*$9xSzPUxOM3-ai4J`xJleE97p;b_a65fH->wLdyN~y^#bw@uB3in?fxA8H-1az z0{#zv9{&x$H1h|3RpwW`V&*V@dFJZOSD7mbWFn7P1qhx}K);m{SwtprMOI$cmF!Do z7qS)Elx#`1CcBcI$=f%ZkuQ_o$pPg1IT<;-a)sy6ud}@9{KA%!WVN!S$Hpti$ z3$qJJh2+9#)GlfV)#`y+kx7v$@G4i)*>nzFKp&-#(cjajfJI2J*tPU-saI(%Ful5z zUMux1jW10sO)iC$LRGJqHk7?6cVXUS!kAZB)+`5>CF?57oMpqZV%f6df%PmISkKx6 z(7=9X4%}y!z<8FZc2_My?K0b*ZN@fdzh!UY7;~(+5a4i}RkP>1aIbS6xt?4bu0geN zwOO@M_2p{Q>WkI7)t9PGs$;6@yarw?Ps)45>)`qDV`{={!fI~UB-Ws6%#UW*X4K+q z3AI_Z*xL6%87lzZ$L6}Ox`sM6!6CsxfwjO6*kbJk4g!^W)%xxANe#ITdB8lB(tvI# zXt)DBM2QW_4XB1)P1}JH@|SRB)1D@!rWH+#!sShhOJ}n+C*IT@S1FgU1Rm+;z)vfSW|JLx<+pSZr2Sf)&w?w6)GSNEmPr%9k6|E32 zh*pYo#Y}ONSRgK2;-}@N6?P)#O!hf1T_4@+x^B82x}Lg0x)5C#-DUdg^jGWK>mM{a zVzl3Auh9Xcqu}$i)?R2gd1}&O^2{W`G}g4=bdC8s^GNeJi(*T6YY%HrYkzBmU6Nh0 zU8-HS9mcNT;fUjgYg(?;5>3~=u3KI8-3;9H+~VE!JeC99 z0*dV)y+-$2e`5gF8BlfWFZ@7YV~{XN8(1fv1Mh?Zu(ry>$HEUs9F4$kSQ(`dwI0Zm znvp_eH&TqOK|Vp=h&#UNMZ##pP{LTk>jZHE@amx0NtH=eN$c*4(6y=csjc^laYxek zr5{b-lD<2A2QZ!%{-U6Mp-NK zWabIr5`3LGkl9ES66=U!ViU2Nh)}*9+Jkf;!^tr6?#({rK(amgHaUtMOh%Azl6$0g z$@m;X4l!qU?x{T8yz_ZF0N9jJ9#c9f&nP*CebndFSJVNjjM_u(ry4zQDS{MTE0WUR z(x(}p8S{)e#teg5npes$C70e(4ODF@%_=1VWpHDeuxy|_km<;BV!5+iSk5d6aLi;? zk}AoSSE{V4t^q>(ADit8IBgd|ZjZAk*puwdoEuy?*Owc>g>t>PSGg9|SE|Q&gS=O~ zejd68Uz1sLuO_P|xu#mZpeDU0r6#8~uePA}L+!)5?z*13t%AdXom-p)n)UnYHMi`p zZ)&Il7MaQhAu!7D8#)^58h8y24YduO4b2Tt8rD7ZYSM4=Y4T{oG`Tg|G?_JBZZd4T z&}7hrYr5EE-DK2sr75;KrrEzGs3oA~R!eY8U`t5L%@%lz=~h;YyhYYB)bbFDYfWxV zYQ5K*(u!*R+WNWmOY2L>tB1#cJZ+;(g*h;=N)O@n$ha zTp%t4G%8%{@#$#YNZkf9xX`$N?k8yC1nLv23Ec=jMdT^^G5Q(w3A!Eq4Bd@x0Cvpf_oVkM z(;d^b)32moOuw4GHQgrNG~GJgJl!JQHeDzEQu>ulv&^;1mYKGh_L

    y=j#?6YIY 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�@?n^E%KxlwRyvkC$Q|?!)%}c)f$p51 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%0DSu;g5RWnV4 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

    B!&u*DtS>g!Z#CBQC0XBWtjjwRQ=@x!!C03o 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 blWo>6&ISjPliE1im0fA_=AGC6S@Qn?XFil% literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/psycopg_binary.libs/libpq-de0d6d7eef3cda3760db155fac0f1d34.dll b/backend/.venv/Lib/site-packages/psycopg_binary.libs/libpq-de0d6d7eef3cda3760db155fac0f1d34.dll new file mode 100644 index 0000000000000000000000000000000000000000..1b51f80894feb4ab9304ee5571b179e6897e1062 GIT binary patch literal 308224 zcmd?Sd3;nw);Hdrjj)6plvZ#fYLqC5k$@&7KsR*YHgqtuC=QEg5OG9B>{b+nj@{9; zmsVWI868I*$5C-+5FCcZB`hXEc5ne#9ChZl4T_=&GJ1dC@2T5Mg7ZB7-uKU!&nNV~ zwVXP2>eM->PMxY-^Q*;S~4}KrXI=FBL zem^<&;KKLt`{C^e7wn$*&4Oh|4=wx(@5_#Uv+x7?Em*+c4{yI(ewQ6RAn9YTt((cV z|65OMs~wK%cjY;L^ZB3|$ub8VXB2hL>Uy?A&vH0s;}8F)4aaYxJcd9P^^BxENlO1Z z9Jz|vNY8eVf^Jnp)y1>@ka|}sg;(V`{?pCj=n}|rJi`X|V#El1X^ulbU4fAQ59BzW zLwZx69LM;Kh@z0G;_fy3jjRnYf((cQGwg6GCso!i>Q2L0zI?h1($T8*I z{pQ>}rw&;{lO%1P{kd{i&$Nh1en8*jrF=Qxwup}W)+v~MxfZOhc^^mv3_&%AMh>F8#V@dg)6dyC+UW-haPiX zGcn6y&Ifi4P1-|Es8O=Mzxqj5OZ~dXsUGh^)j|Twvs~sS?AK^?MPB!)SGWE8rg{bb zlDkH|*4nQxs@IA3>+jX;H2d{l^*Y;rU8r8?+OMqSGQECZNX995*#nRSWgGOUw|KVSxHexmzR-!4(br#YwC(d+=#eNksL&*-Md=2{Iqwa8{@g=!4Zd3vni{L4Vk2f8^ymF>P* zY&WvZ<$vI-UqNs-I~{Q*V~BNYZF$Z)!Nb0~CcScPfc1N^{@AwlZ$75}qo~i8$Kp5q zg;R@k;lmG30WqE+w6-8hj{z|OHGIY`==&D(bdlxSK$_M!6E|OU1Ss7UJO>zUA-JYO z=@D4i{QQabz3GG+p*tK`>oI?Ek>6+z4qbM&`PWYD;%-3EB5NSj0IBYBK)OXi@{?P) zn&rQ55A0QxU3QCkV@CD)tPc7Wg(@6@69H%}0iBmdX{?|`a)zopJA&VvFFogU`0Eb) zIE!j7CX1Sa$a$7!>BhS=v|e6-wAO{Hjz{roW1HW2LpL^=9sf*pwuBEC1&*^^omn$h z&=;-6fB4C=w8CnKN9%T12ppjm))eCT-o<#fT%U}|a;yRs9Og*0oa}ZDl!h-hrifF# z)cngbCns6s`AGGwEJ9&PXR~*r60^Fqf^n(tH(In_4xiODEL4@{2p(dYe$T5iWKz#c z6hw8`8<@S!>}F@~LNWkM1b`Wf+t&ZmZewX?{RX@K4mjA`l3>708gX~J=+( ze|Gg!kMSta>{MjL!U;f*XLro88PGA0p}n zLx}nj=UoAc3E0<92K(7jmAc2H`i*VwjN${&SN z1Fc+w`x6R$2ZBFQVfS;CAd-#{TYh{JvtJW6MFm&%6N^f(tzJ+Qf(Bd-gZG7qtHhDEdr{;z>jpxpi}vphaX_W z7juHepp(p}D>%V|$K(AxR3gM8^Gu+VC`xifXPYCI-4@JRc7rN$lZ^EI;!;Q83O^b^ z^*mOu3lx{A5(~+QVJR_KiJkD;EIoUx<+{TsJ)zMWI76~5*R@O&iU%}R|0_YXCDB{G z?&WK&;7Vv*b9_GgkRo0XlZP`DBqOw1&eLwig!g!Hh%^Xqm?l=Po3`Giu=1W`s*$_7 z(H^o$@nT7VseV|rwBPu~eBw#ALTRBzKE}X!jhb0rqk5)pOqd4FhG2WV_(@iaO(`NL z6q&PN9H4X~#sR5N=~PR-Ur>qnAkiO#Jt?foPL-P1*;@GqIZ5#>!IoZyHHY5;e{dTo~uv^)WdMTUXe!KRE zb|%%6tq<3GLRF{1-XI|39X7GjF0@1-6ybmN95Z06xy8;B+M>S~V~}E(_0lVk+}eed zC^cGrmD_KIz2+~zk*RK`qAHW;l*iBHXaou>+a&;NO?ugy4N2@1-ql2dd z1s6~-^A*CR$9WGr9kR45nmT3DdObQHV}YT8vDxg0Jes&{j!7doDHwmHn96N)CU{-U z>rSwjU>0!P*qN#he6L)q-FZC9w`0I<=Eea^zaNqjfL5AT4P2wuSk*NJDamF-d&ECR zF0c@6mfdUyGO!RKXKb?h6XtzB+B0{;;PclVfWE{!m@DgOHI|J{fxqh3`cPFbL2*~L zu@$nD<5c#T(-Ezn301+N8OWizG1cC+W)9m!?dv=%vFH#6cY{lzCx!tuM2y>4YXQs8_f{1HCCk+)sL&1yoabw4qO7p(`)rx7+jL_W2ib%;66=~K zz-UxT@+TU?T%kX}b`rp(PbDb^bAz`aKw-v(_d(R=E()hq-ZU(WYm5Va;|E%D4I8z{ z=VXuA^J*cx#hexc30hi+m)`Kc*6^wj()C-K4nS*117{#iO9~W@T3Lnl2 zbTSJu8RMXf!)*RNR_D^ZlhXJkkc~e`F)tG~2{8+9?zG2NqsX4j0Bvg5$ z9vgT$AOyRF<~eT&=7r{EIRdAlb!EfMSgftcIUZ}sLEdgwu%jOSAt$(BH$H-V?jyb4 zWS-Sul<&E)PR(B5a%u?$8ty?y5;w8Ao(jJnY))#ogc13fW}#Z2 z;f5W3Sg(7}_&QWRCpg|{#?qok*z6SWg-vI`i(w87MawtCQc0ZbGa4IVnVJ*!TUMk= zYj|2%sNhgdmSc^W>Qy%0u`ZS7w0kj>$K`-ke(Iv#o#0|E=9=_@Wf_Z>HTA|@_M6rx z06mjNPERH1#_AIDV+IYaH#wo=C45hDzFOXUe5d+SO@FLciYU1I>YnQ z6s#`WXt@&eazLIq?PyQixs|k;p-$2e_?A8#-v&f6<3Y(LN z&4jkt+=4NPmmuF)7g_`Wp61XVnAJ`_)+OXKLSSitoZMQ3X%{T;851E0-`66&kQ}OX zXps}}5dJAwYj^`~$1a7ftMs7x(?Q~(HGIhQF~cp_S+Yo%$T_YNerx$&nql=%V( z#9x$7TsF}bLuq@(AJb*_O@EfG7x2Td?d>5{xwIa+2&In*_S#Lbkir*loG)!V)o2h8N22N7Y`hY9Ei<#%_{f zDn)xth86trDTVdf?89zQ#TRQ7=@oPR5$gf7E7O~huEy^x(3s@;D^lY8&lg@v_H+b$ zq$|EjfNvY9csEMa)UDhr<2V}j{JU`6D6doSO!6U{nD=8QHNg;O1=l!_$qanT5diSncsau z$pc_j0H&=_b<5S0SjP&!fw^vO`A;Uc=9fSapQ z%8>~Pb*B3KU)^dGNE<_)UE*ZPcOOFcKIi{Eh zJJ{yx_$$Dqt;L3E~V<925(atW{q$cxWjxVLLBHmm=iqJT`vBEV0W|`rigg<2f;VK zidiGjsTE=(_-`V_)D`p;z#!2>L-6(zb7HPdLy72C z^TTt6Zl{%pDQdMyy+Bj`4EW3k{}JU9#i-DUmM|*3s48>=ar9X3x4=Z#s$uXPPT{ch zOPOUMRB|!f_6Bt%xdq9KrPE+`+Z|?MkQ8Texj7XEbgW>s^#2Gk-=25{jlshcD|ncx zi|y2BlZ3-M*L74R>^8GN&=V@HWZ^nhIDQKmw=PU6-yBW}dEE#rAwQl%erK>iH^xE8 z!~1_43Wf%OATB)EPTI>p2aIT#!ywjH9{J&VV0XpyLb5Ck`{3EYqsRk1#)SKCO#g|mTM{i34_M5!Gtb(i|2ZyFWbW!DSi@|v_y(I5s{5y zf2BBtUpk^7wdP~`0gVTV9O;T(v2d$AM~WMfB@0CG92un6vx*?7TxPQDG$!g)KvYm< zB`&P}Xj?joOt(+-LIN2p0nv*V%azu`Qwd*-fY%~aAr3^D4Fad>#FP2c%;`|Ebk$f` zTeGio20|bl3iPf2>A38U4oHny!HF<&&6BXs#9Rc$Xk3FjHbq{>lfPm)dl&SsD#V-R zx)3lhQKZKpK38m?Lav(cfW^cZRQ}=b!!{En=4gcx=^8x0P=3>)q^Hn=J;~-5Oz;;V zh|D)qHQZ#(nTC^Qy5I2RdkuK&HbGs^Igf214>^U{P0cqOq1a^f5>Ul>pNn@|-iwOK zLNvZl>qgh~fu$SJe=jGURO_vXK;%6VbtnIJ>}gfV}5IXpcKOr zA?%^wl4L2T;51C*V-!7IIrivIER)eC$8l;AOfJk4^DwO53@|HXd5 z-ouQU4E2p551j@RX3~bzj3AE;9Yy-9{W&`OiYBDuAYv~T7k&=~TEFi=N1~Pc^i8&` zXxN(%h1Gw5b$^%ud&JRG<3f?TdLj@$T%g_EgYU6|uQp??9jTwM<1KrwwU>P=W z2dn2Wo-h&tmu|QbxY88p0=8zN=kLx$UbEBbH$G_&OL=%eiqX(rK*A9F$uKba99C21 z+WBXM*O;h;CGcF}0pHcVv+>&!W+Ee-JVtX=>OlV;kS2EqdK!iUu*?cN8l%gZj2}Tr z*=JmR+lHAxHlS6HRfnF-rkJS-c~*AeV8^PLzJ_0iUfJr^MmE;~|1*4R_hzw3*-mp! zFR({9?Xsq_Lt3}$5dIe9@5z>G;_ZkABhlr=z-KJz0a2hu{)*JlQ1tOnc(7bW=VPNW z<*wwKIf{kBx&5$&IG|U~FP^PM)^%mU?~xQP$C_(7Ug^4=ExzYKKl-n*KG48+*imLi zpc{k>rI{)c{5a7OZceS?Hq?xbum=AG$HXoDF!r0ckNVdyvEnsGV5dnGC1#3w-8^NB z)y7YSXnU<3gO6P-4Dbq6SnbFmRbtzLzqtc8ipS_mN8)%gRvaNLpCcoD1dhM!kP@wl zpxzg#7nPBa+BLF6ED%J%8h~O$OiRa5l~efwXU*vkT>n8_vw&+_gn3q7ho=0o20>-T z?Mb9(V&~5vGdS2~8?lQS(qj)xkv~4l&6;3WJ-mjQAW19!hwxne6A>tQ5N*JQGarNX znr;RHHrdA5R2w;Hqoq0oQUC#I%4duz%xvsJ)mW!wW5FxX&?Ty&7sjfF`lBJxzA#OD zG-mF*E!mSNu)YS|e7lKE@b6-04}Cc&2|myZY|LI^0zNnu;MEkv{FIo8L?v3^^`mt2 zTQ~^W&6it>2Jpy$G#WNA?E>LUYk1gmNL(z|PI#9PqR=R54w9xT!IGKVCu= zS0e5VBBwF@0A3Th)e$Q&av22jCUer6q~|8H?t1yvTf&n$Iq=ULT|Nts=JQWeTv{AmJ(O2LKrG1gFQ#YX-VKHOQmdu$D5%ja ztCawh__a`j*a9b&;Wh;(mll~nolF`S7$XOApk8DC(zxJrePV3zieFl)?!vDT%(H#kLLmK8biU`{>=vO{e23cbnVH}263vDVv z2@x5l$k7)44r%0g;sBz*HVUF~B~>nhGPZ-gYUT?UdH0VTX3#~Bz)`yaq)G)`Vkxr=_vaI(Mb9@d>lEmv=#iH({wE!U4F6mbdxnTO!S zjg&C4f`5XR38)BxXl~dmu5O>@dNZR6aBek!tIGe%#`y=RrOXN1Vy?Ue06FAJkvQWs zj#w5E)*{$6Le}WH9NvqQvUUQ(2R5J;TJqIPxeL@6_?!#)=I`48H(vua+Cc6C$P{?P z1+Ecdmm$Vx@xRGzq!?Vg7ybaQhT%1uWmdvuq4SJ1z;4m325VvN>qVy!Eu#_Dla+R* zD@``@>`L4%LB}RHY+RTtZfF{%Zis@F*S46LX`WS7Q%o#h4e~$QQqAGPKG`eRu4TSW z-Dq_a*OK$oOExiXE!U+8l>u{(uw3Ku1R}WLs0Uv>VzTabS{ycSpj$gIV3?X5H?um} zjxYylix{Je*qw7wczR}cE}BjnFmxtkkk(2K8T}b8;rGC}pe1K2rl{q5=4@f1@s?{f zo(2zqdryme1b@8cdY%bolCVV*9%VvzNq9vP?nVNQzD;JVm>tPzb+ojK1SM|RYW$)! zCM45jviDqBM6Ko#0rEI`+q1F*gpcLA63{Upwa8L5W{k($0&bkk@XQA3e@wFBe#{U% zE+aUBncF^A7S+qxf6yYYV*|nVWlb}^@2jjAkf^=pEuL02E_kyM)-i|>2+N$&uvf-& zllkU2i8^Sw5kLr(@8QGQur7cC-8NTAMwn7NR6bj47=icD8p>%jS|Kl#($Ii?@zN|3 z+~N6$Gd>vjR*lgjMF3P)tu-9PyCM_2A3qJRhC%}bnh4aRf}h#=o@)3@7^1{|V%69{ zJ^@?^Kr#`qN+y3g%pX-Z8`h(!7qJ4x6EQe5J)y&6gQYRg;lZt_amyeuVuZUW+P_Hk zv8b3Kq28PW2{i{~LapjxSJo;CqT##W0)BekgCtpa?SG809}j)j!BCxvt?flU0GTzk zhM|}uN;lotNs)3Ouu-&zY8i!=6}7Q74f`t6nNAGZ!|P;W*%LmJ7mUZdPe3 z+y1@`dlGK5)*?q>946pgput%&a`kXhU|tBXU`|ZCfoK5xkDZeHgJ%is{pkHWm!kLG zU`+Xq;qcF-jI*sbaoWky!U7B(xiWa6&0t!?73f52n8(VC8sUk9A(xzp>KN4K@NRV8DZ|Re^mOxdn+^UAN@H5gL?I0B z^zaush>E)wGNQH(H)ZdNca1w!(E1Ao=(5n(`%@Z6FPTEj^)k~xYB zC3w-p^AHe_HhB zRFkz2K;A3sNycF-=x01=;(s`6;e@(nPHfnZur{>2JEG0{HE$tj@fA+T9auOQ13kPt z41-V9K+6FdtDf)=*}+^`+==Y)kt`TtT=c$)ETn^vh5$34hM2}T{;3eRUF845wn6+f z05rlygojG+qEZ_AMuLD}tRp}Na{4zVvX(lv6|LHewF8_8QP);90cr$jOqI5m2jNj18JQx+q2i+XQZ1ZeU;3%`_QHzPrfI2B!7 zsq++=g*KS!Hkk8mFz47{&LLsrv9*Yi-mZ!QxM_5P+O|Hwzb>#+|GyKM|fBH3}@aT=G+hzB60( zcMaJK{k==QH*^6kdB2Xopx6N0Gj!Yr??=TSsA&KZRv?qx6Y=U5%7BzL(L)3)VuocT5Hh4*mT`x^ESH4TY zo6OSP>UZvkK&Khu-u8^m{Wo^~Fd66KC;rt}n2fQ4$?)KtL(x)(=@u)v2kt!BpXMPf z1maJm#+pMQ;}CyDM$$Gq!*CA+#Rr>!lc&WILMg=efQ`W^(Z%u>!&}nc6ytF+C1$MP zPa}Xzr|+;gYjPQsRJTX$tp!=Y&y=~0n8Y21~2%9O#G9+?*&Y`tO z11H-`RdFs#+r4S!h{Ou=0X_b>0P*Ah3elng#-vPT&Yh~%oqWC(7$=lSqf3~pzrE?r`+l`da{CumE7OBMJvQG9Wo3$8XiAvDxHX_ynfX(0U zP>gyeK*kGD8c2D7h#C2aZER0g{S)Y5H%Z+FuUfhpyeT$X*2&y2<+hpMg#qtX89rA% z;Mp8SF1r0m)#M+Ls|Z#=f|0x9zmc9DP{ZL;f}gTsKb!iUpF;nP9#!h4axxq2Pf4l`zi*XT%ha)DNJDmkB~ zHjMx2-e{@4ys7?#mPTNZ~%+(#q8H}56mhBeC<-Cbs@{MJs zTIrCq*p@m~6xAx9STT)^zfTze_W{Mw8r#mhQ(i>T2XDhL!=jy@v-5=W%Ql+(golD| zC~NHPDMen6U16Ll%I{XJr_9~>pTv}Jp2tt+I?<^AhBzRo7 zo}P=+i4mCE%gcnP%wcv0EGA4&D{wA6tpNmjj!vFjboOLH>^wdR7QkUk2DfXGI7U;) zK4b}k76NDLMrX=19E#l4gQc;#J4Z_M$dML#1%+!+xQ~aW3B1rQ{tSvsDC=+q9O)>( zNPzDT^v20L2fH)6)Gi+o@CfKRUX@3BQ(zi z4dth?d=1NEFJUy^q>`8@h~j+l&+?BSGi7sD-KA7mm=awF5;!yq~*CC{9iQ@J|{Add{f@6WOv z*aO?pJmB!nm6*JUJ}AZc76}H>;ZZ>bS;TEVbPgdM7Ah}6M<^^>%`vrvOAq^RNO|m? z)atP-WPg969y`xMBs1A?8vLXSFQCzm(g?6?ILOk*=mW&|R?GGJ2`C5p&Jw%oCX!Ol zoM{bjO2LoyiVlI(R6KKf|L7^!%Gf``VBL!(gyDcfSS}M8Z1$jWc5gYm2ipRqbb}P= zoH5QU+n8Dpo@3F!dn6z6sIh_(P+yj-#73)IsQdyEnZGHA%$g*TQlmi%ET_iE3jj6Q z`&HVCE?L+S8062hf{d}x4ep23KlC2N0lFmE&ND%QZ{h5Zk3;Q@y(d1}^LKu651G2| zGI&!lbFroK*uucve!QW2*iE8y*;b#CxA8 zey8(2E8&4)&cn%^@hZm!TUSM0fmC_&Z1$yPqZ~OBOIOxq6*MkQmi`x2zP4{s4>HVqGO?rd=Gk+Zka#r7}E`e;JF5Zu{a@z=5j!SJt3zqK(y763y~ZHKyzA3mlF;r(L zV^5BU$bLCUdM`zII{*b1N0YJ7%zp}T~NzV#hK;pm^utEf^XOx zjJ$5X_X(B=COm+_;bm6Enp*J1f(qmN)P8kX7xv;&Cw4`-kqvKYq1C+`KL zl#27W8*h+wZjuu;WlJKa^*U@46#PSC7S|A9T7~Gb0U`5hn2d-f{XSzq$vhn_j>`@H z*1k(^s3Oy1D>y2pBL-omPnJBRD-Ay_@**V!-ghFM?~n7HIw09w?cRta!3l2QSj&Iu zZyx%ahyI?{w!iFcc~S_2?y93(u`bn(pX=y+ERfoFv>Y7P9!|28ZO88~L^QmL_9y(u zf56)+wQjw>kPWuV{Axt9Rw$cKh*HuDjft52S~tBAi8JNVU4+!RDzy};jVjfR)JIin zEmEITsnd|UQl-wuVOQDh!eQ4?2+bJbd@Pot^=#4zcadkYSqz-qqD6Sj*l~VfVxRT0 zmgV@F>9ZL#r`&J6iDJQ?HFc2TuKu8<&)8_*`IbaOg*TM1H|}SHUWO@oje0g{zQtg1 z<|PSd{|fy$|JZPKl6HP0%2jQ!%5T)0ctA4;2dQRGMl)EMGW(eQdmXVZ#*aj0b=Gb2B2?;ygKcF24}1T-T}SuA)$c$MsS2J)oZdZQk8k7K=@jj${Fjh(DAl7t?H5iA75 zaRe{4dVeG25SX(fRj+8FpU*~cT@N{1NquN>UV;9 zF-?;tm|vL8?_ku^iJXxw{KqqU{vj|O|F)UqR4;P{I3hM;6{mzFkfR$8P`%(0DBO4y zrAR9I2l&B!dt!mf>q&@Y6kFw54mCzPSs1?=_`r@g>N&mI_&V1dk}vKT5MlZbsF-je&15^l#yHLPepG&i4;F1g&mLeC%oEBr8PXt z(%eI&&jz80G1u$oacvU9E3PV8k&~a?eCmk>L2hv0GAB&<2e%>SuhpD|&2gTPY*`0O z$eOVjXW0-(RfxkhdU)L_di@WCa%(w&J`MXySw#8IKt#%s2B_7eT!Di|E<-P|HhzzL zfm%;~->jYu;kQ1KYlmkpDt;1R=n$j}V?+zC5EmpHbd@Y)utM6H=|aEE{>q#(cKD1V z*q_2RUgk-!ibgMDtZHmUxI)-QaM1zx(8-_RYz=&H1zrGjU-1 zxHT*lq1{(c&2ciDUPt;HOQMjB(4TFPZD%^n12$1VXC|DGcYVeYU& zalXsQ103zhJ)wfc-DKYI2cAUMjYX+&><|9Qk$wD_b3aLjwe8LD>JVlqO1?)g(wpYM zD`os>c5!)SgqbZSo^I`xUz_<={Z$Z#tZcbn!~l|#G1rCV#Hm#Z$0t1HOzVVX+x&(7 zSAt0uD|l>Vjw5h^S#_B>zAqPuh-(&pXhj!?6I{&o%sE)~bpSN12a&hgoTn<3*cJMw zDx9k-+{_B^Jjn_s7OiLyx1FUiNYAgNt%&gmoSD?%*umO?9jrrehT|qG8{+3MNQ$P? ztHbyuaOo!fD@p%o^5{0g_Yb|!L118!n`)!w4Nh8*amX86_#aNr0ZAVTE5E;^lkt5b4^6>8 z7Pb&sLJJ*P7kDey&@c;j#5oN1C(w(h({^AOyoTh!QQ)`Z@amfNY%~0oGtdS91--G$ zptKUXWjkY|5c0bPD4I?XUE*k_pkvr<4i+{_Ah5zV-yVshJF&by91pOJg}~BMJWzx= z;{EZ|c0FAYTJ>vY1x_(P1Mzt@(jFsl+OJ@Hn)@$t+OZ$&e@Mm>u!gJ&WWCcOVZ;D! zsgUD51XJo1RTB9U4O2EEUTGf($C*Zz(d{PEu))h=HoZWbTg?v$uIU+;k{?uMuo3nR zPsxuWq=<=tNk;9gHdD;sA-I+rKIWQxHm8g%ZOjc9I}w_wHlAPs|6Q^Qrt$|inE5tn zo8AjC4+)1ZLQEo(p~WBhNJ$YSQ=1bPTgqn4A7!q@?x%U^p%j9Dbuhs~@ihfqX{Ji^ zw34`(PiG3_4a+R^F&(p99;6&{vz@@UtpjBWl6b8`%7wy8y7BSP#ou3WZ1vNa#L7Td zNp1Hy3hTMD@1DDGSc=%Sl5$CYnH60niw)({?2DkJtZE!wI8*#2GZrIcs4vVJBo9N7 z!&oO4Lq;nK1pk$|P&b^koX&v_AK4i=L+!|ie(39o>4=c1MR~W=gVFFBYa=^RL51+? z(HDy!MeD0e$SOE0^(0>W(PxUEliwGMXUp%)#WUsimEvjmjY=py_h}JJQ*ODc5e)*y zT+H#KQ{;R2QFY^HEaeU%Gz5U%e#k;zj~=^6SvhzDA2jduT(SX1&ft*gN7<*IHyqalIbzr@sj2 z*jml!56GQw{eXrcXvJ=I)>CfeXJ%yp>A?t3}siw$V*q zCg`7n(sF|Icsv*q*owmfUgO{B=)KP;I{-H(JCo{wORcBc;jgXeP}R2)idTB^Mn*4= z{`7Ob`1Gq|dod;&sK~c_F)BR2JRiNd8+*bwYSsqTm%ZAe8R$o7esO8vK(4oPZ{Skw zCcTb6Kxa(EkG7&4*yKboNNgnd;}YXf24Gnb%N7@(c!H0_t zj=vzP+*^L$`8~35yi^nx`f)nm5}iE8k9d9t`p9zi14!I2mLDA=-0JI?q#hXo&PP*Q zG#s=82LokrFm|*7wx1Sp;{hDZZr;ysmi-LtYVF26gJ*fajGW>wVD!7(9~n5lh9?V! zXTRHj>}ZdQ&Z@w!f$%Ixy9Y*_L21d+wmBCV&jH4mNWtlz@Q=>m&xTs>u=cc1t#bU4Se$G60QW%~k^cB>L{?Y^~wjhmd4&*40f?2 zCgQJQuOF54RHaib*K$?@Aj@?LX`9?my+Mi&pGMA8Cr{2r>o`C?Go3=er!tYOa=I6`&|UQgTDEk{UTJ${E3vL0JhTnpf){*a)87G&$QCoo&(z{bAiI)O+= zrEM*;D-Vd^-cdwasBBoW4Wc}L*7u#5%5?Y>)Zh0pjg z^S&$CeIo4){~%1NjhG{#X)gR|gCO{ZBL;FbZuG)dvoU@Uwjp8pn?GRJ-ev=<8A%mI z*cd6PTuxCqf2nTFo9&Mce)SZ_k(~7aw@6~He{+wR2Z$a9<$T7Lw)e|uN%sI_Q?Xwd zr@4kwvOfv;0rL@$*u{e5CVZqra9`pE$qk_xgi&Ob?Wyn=Y{{DCBS3}Uf#HM-!+s#oNsO)#g0bU}$_`G0o$%+iGe{1-BcJ^sSxrpT9}cBqUt`G0ReMm4t0`*E@Ep zcU00q^k5zaAlZZ0S5o^Mf{L2&=nvTbZ`gD-=TxH?Z^70BviU@og7|;Ja)RC1wW={< zImS-9G>xSJ*u-*p8p~35C zj-Zux^L2sB2VS`u^xLz7=%r_Ci}@QISBXQ6Qv6*9u1WI4-`bVLS-0FtRrq<))We(SbY{`)5|;|OJ^&h& zqu4CYImc(cF>H|cTr1e$7ydCfn6O+EzT-L#Zq651i<`4y24ymglg|zjkKup=B%Ely zIm{)WbEz{fJK{0dFqszH%vt~9@CG}gvur$3k5(_V^J-O|rq*o8b;PfLHdmdX`GUb} zLvN8!E;X8}5?Ig?KQ~qBTlO6N$sGMQs4LoeePzAKhy!&Y~5i35NH$CrWT!nyOhQkH;kr|{E zO-Ce;1XU9c012#cHwLl!B!M(P8$t8(KWHaqM$lXcUf?R3OIO)Amwj}#3T@|~@;1Wq zkeeWR(^~Rod&C@+?XNNRVtBs|t5}{dye>Zh-}ENaH&7zGPJ*F@dyScL>v<%gDRXL!Ozg?U zGoj4Pe&AaBHs+xcIZ`UQAL#zGKIM%>GDl-)l^2*dOSN3ziAz!#4hmC)-re z8RHT|5(uyjoudcX3EwOW8MEwkHB%bm(6$G+VW9GPASQ;G11p|-5$L9%Rqgxnz{02s15F^#-NRgdYJjy%sS08qr)YL#5u>f(MHL`Dc2;cCpGwxqfPDI~?RQ0zI|A;)+8KlV76#EA zg%iP%Cas~IN%q)hdZpg`GP4^p>@7&bD0U<%Vg>b3L1y4@c*c$QV4~j+PBT#^p!<&n zv_O*n3;tKODKG3ZMm5YB5j337hL8R=)o@Wp!$qlhpA@CLwSgxc`3VbN;WHkSPZCm# zTtWh?{l*M>?qK1z_uEhkT0=;<4j|aNl z9H6>EnSFT`fhxf%;t~OG-Qh4mmval~I50MG``p&Yg-CXnac11kH&O>XngXeRp=_$t*4xW_=DZ;VCk?XiA+=mxAn1?@P1Mpj> zJdV81p^5Ojc?th1iYb{SnZv+b}?&2=>iQ8RaiNwmb^xMxv@W?$|SqqUdEde+n))1DBH(F8!t8 zM^%%9-QWsDL9G$tNiAq1ktJ0xlZV_fk%Z~zjTJMf}H3@>n^KGIfn z=CQVW$$q$p_{ij7S4j%|s}baBO1v97(mT*WJ@10&4Kn>}tduEOj=nF}Tr!682Z(xq zY@m@314paId_fFl2OlETKv-PHS;v;ssz|hCmzgIg~+aeff** zBLvcA*hZT%jI|DYOe$8;kBh(GJ|`3gBpqwuNdwc;xt&>ydJ}=c)&RQywmFsqsMu&* z1{IBela1!V+qpim%5oKRP?TJJ4-F24f;LN3gKVt^qmfwrztZc7?1;+Uv;6E6KN+NP zg>S93TxYOB*`C1XwqgalAXLrfKTDU`LIV8}{}E0YiT@}Y^StV;faYoBhT(MFvl(X~ zj`mvTm}h%c$6IsplQ<#fdA%x^&l?k+VxB+X8A|1O?X_{v*r@HHBP=#*d!k2d)a#)m zEH`RnqH}E2ANbNMHtKoseAe2%Ii1%A^3e{i+fCdB+!kUM%kAQ0IGs-il0x+D#PicK zb^~_OD6CbJ>apDbfKGn+6yaF(7w1nHcPT!R1xc|F8(tyw072(9&?Yf_T*UaM|NG`s zrGSXfZSs&WTYd9z?5HJz@K9P@o`G=@#V{svHzNsI91k2Edh@ff7VyHRJv~Y{a-`!_dHU5iZ5q z!mGE(^CTGU-y6}sJ7f(C4h0l{Y&fFss2D2U!NUOKp?~)vT7a%=UImK?)5j-fVl(~B4 zds<{09+Xbi!Lp$vLvPLVX@6{;Q$qqGd_7h`mG0^Dk-7F6l4Lt=58Mwr8arxO18p&H zzW@^=CLXn2(4Vd<1)+IPhWbu`Xk;WbWWIpG5rUMaki<1_+H2W%#SL>5fgHgvRITl- z6;QSM21mKI74HgDTIP&d98puaD*@C335IHs z1`dOT&oO}`903jcF_lBpBLz+^OESp>p8D;#+5f=b}Dw(dXR{Fsvm*3 zss;xykd;(#_Mov+2JUF$bKSTMRs~OG?9>{#ods^`gGlsvJw~DG>_A8G18%QhpIBpa z7`>fPq3FTen9AlApiJ_l3U&fi@-|bKWEvD&bSNeEL+pq4nkTM4@in=tD^9$O9T8P;45O0zv$batCxe{8pD;sNZd z8wUeEzj3`g{wi08u>uENbn#o%k=R902Ij&i*@Y=?N)e#)B>E6P5o`l|;vU65U07!r z>PRPWT?pM`faPcXp;8}<<}K!Q)MekyCFjb+cJpaGP;<1^814y--- zzz+CAR{{Jp!WGV7t?`>yuqQ+9+&JW1isdJKO&jr8;zWhy)}ncrpN$sWmxXb80o#%6 zP)u$x=UFnhIioLnwu56@clRQ2Fz@+Z%oY)@F^#`+bKu>Jk!5sm#f2C+>|_L53lrG+ z3$*5AHQCyO(V@8@E3#szz67rpiUlr~gP@=?<_`@2cd-7F`0v8D@!ust?hGPVU?Yd9 z!=faHjGk&X*Mkodr=whdmizn(AeHWfv57^V6qd0uhkI8rr(2gjDBEl@&Lb@fk;LAJtGNVMcE7fZf@v-Vv5Jvp+aP4x>WvE|t=lP6?IoTAWzJ`*l1=Hl2e81zFt(;sK2j;$(Pz9!J&`U~ zOvSml$5AI^`HJ||^v85&LWTXOr>(;96*YX1soFTe&lZ1;`v%^H`uj&$s3@;-SX}_Q z8%b2aP#5`mMe@WxfCz(0jf?w)x-o1 zA2ZuZha;nk`$8)gp=u$1i*Xx>`ktx;sw4Om(5hpeLd#VLIN`&E>U)Nkt8WVI+W>nu zEvmYgi<<-mQ96%34y4sJ*W#b&_rUx!{_F(RJs`9ZcQnF z*vf0rxtf^I@_cWu{UOVEb8Wm=_6}{ux~9EZu`Y#K8@=bQ^@N&AamB9JSl6&~;Z`HJ z2^!EByW|H?)Ps%3P1-+lmm$Sp*E|C$Kf$lc(YMt1$CRBs$r(I^V$}aLxQS;aFQtDN zh~e9xmdlR^ICuuPr3d_ulaK)l7g(;-@uVpHp3wgCWZgnMtOOfjRQzBLXxg)v1B38} znf6yqGWJmIczyd^5YM*SG0bWYD;eXRYwp^?h~$X?>kQ5gt=Uag6THTzbb3DsKFZK5 z+0)s2@F36o2Rg50QL-qHb7FJxT3F3SYs#PcQ1X5|&!F-7$qVjGc~Kt|&o~Ck10FUg zo5>aa+6ruZ?!h|ze1r-1;f8HQ7!g5)^HdPwa0U@}L#|qkt8ds%TCd`CGw5OaGx(7_ zDBuaO{T@Y=KI|TVO((J^m?7}bU)JQ0Mv6rU;bUfSg6N)C8_;WfPtaRD({jCnF|ZvM zy`lBDKnt2p2%oY|*UvG9V;zrQYv@PDT;a|V%u=j^ z0m0X?7iF38usgeH4nYjV>>!YE+Eb$ z97B46q~ZfXaI0HDK88v-%n>*N7m~+ZQ&=}va5jH%&@NHMC|FhSc0vbX7 zlKp!92x_i_SKn_Wbq2_MS$hXZbJUQ9B=`8p=G$Sj@CF3PSr zI{+Nd1dhGf;Ei^J*RVktSNiK%R6F7m`3kATe)`lAU7xjXM0wxigWvnJcY(Bi#Cq$A zg^E1d-MvvkNEAL5Pv|v@B*rUT@~hQrH8wjty$*5Zh#w|mG%_0L{FaY0_>HgQpCB1^ z1aD7cp3jnx!`8+(BAo#hYo(e(%Z~{u-blvO`hhE#1L6diZKV-pq6~Wzv;G(CS6-Bk zH^Fia@g^9AokuYUgW>Z`Qr?y!Kb$1=kB@@Wh(Rg7?Dyd~>k))w4D;e!vZ9I-36%Mv zOG!$KHXSP+<6RySXlRr@NleyWTd38KLj2rvA+{8=mFsE;RExO*c5_C<=4U6{qn_BD z9QC*8ZpC-GiRZ)ZivJzO6>t1im7076GaO6*f(P+n&XD4?e<{&R&?6BZ_oZOZRkhA$ z;R-1X`6*_^(VlkUt5Su>slsay+f9V5{xf5}eG2>)d zG+cu6s~m1NnmbQ2OEB4yh}z+D{I-PqCKJ*Jm~lF@2g~4JOV~~6;3iII5IsJk2|JNc z@CbP(dFWkBcs3G>PzQNj7Fw<^-XwC%cjE(-4*ktNgh~z1U98Jb#H^}z#@B*w98FzXXtKWr zA|Er{O4`XbA+|(VEOzR_PoX-j4Z2ziVp-xY@7n=xiNO{KqlGJ3s(oHvYeUllsJ~Mx zQtLr&#b`{*;ZSb7@m&E7AJiLe8(r^i?4$Q-0oDsYL}PcMF%^Q+LjqcU0zN2+9jxR@ zHdC_I2LYUA2dodX zGa!N&390miBqWBB-HC;ix&LmqM+P_0-UgO>p*u=}yHLwtTw=MhT1jcewmhx4sF+hk z{NH~>4nA#$S1!yM#CFUFk?GgP{yMfyxeu|pBf;ig1i_}4ZP2j-4N1y3yeQ1*<~Pb?Dfo6TI1;K8OH~y=j14cR74%?9E)o3`d%*Qk3Iq6k`Fe7}cTR|)kfqP+h=CH+64ElqVxEyFvA_xVg#QRRh`B6Pt_qxht}{n z;6j}K%+ZV$6rxqgceR4WopP~)pAIsm5GmBfxfWjia**psJlO)u27Bf)$Xue3>GwY& z6T`L|`1_o4;0rv|=JZMcH*ao`fq{&KrECs7&bAN8U&0fR;iXRjof!6Cz$3U9w#aAP zjOEv-$J}RO?>8WTum~c_WY|LT#>DGC;*i2UScS0#XOyRIOsta}*yv}doYSz`4DN;v zzm>s^<#bHC>Ghc!pC}iNAm|WBQ_V?oi^*ZInL2JH9gx$IFMY_^tsr!nI&wXQ{0q-M zEI4sTuU!vZQn6c!A#Qvg$SW=4e&=mccVM#a=}GyMQNO-TeGz^)Ac>pQf-l02fM6PL z*^&C0{g^|DkBaseJqE|y5ybHWiZ?a_$`vbLEHC*LtZ$n7NdN^j#HW{2AJXT0Z91nj729f*~^*|u20*SnIwj2h$X8YotA z5+iC=i`;~E7_Xp3uEA3cZJT=xScEkE0Ukg1CC_LJmCfGmIc& zsPniB$&~YYl8Znyu*)XXeTxzST?r-TI&y%#hws}r@K zU4g9Xvd<)Kg`M^^(&Q!*J;pjWB9?`HFbD;-MgUF=mLH{kcIes2$9KX}PdM{hDZx$8 z7E#G`8(>qk%kkdw=}ueq;uSLoP}t)Rq4_!rqU><=*zQt&g6>Df}FyVb9kjo%|$f_@6#1zwZ>ZIcD{Fsyw>XRN* zLOp~Ysms2vb3>?$0Wle$am9>*pRP$JhZwDQwgo&X1^A_oWcK$1Pb0usr0}lLkwJkz zkW9T9ciasEeU!5ruLx*fhfZzePh&o;Q*A{j6b-&z-B<)uI6e(FtL=^#`O;$oRSCsC zru81(ST$F8%L;U7d@Gzm3vtTh;Hzxi3Vw-Gd`}{u3k7`sRF5tZlOwt$S?L1t0HozP zb`}>FBC;gkRtql>5S>L&*$_Vf#HDO8y5u?aL-oz3>!*Z+00{*@W^3n_x&W+FZU z3$tVlD8-flqUNg>riA* zCtCP!0yCmZ2xUfe$!@$M?}K#dja;=xm)OPf2@^6!bnBG$YX2jpuU~zK#MooG7QIIP z3iMCu>*bOI-k76udf3)GB6|M9k!T9$sXdyuTO#e?Pf5b>D^P-+m7yS;JEGqqw|yw{ zI&RqjBAXE7XSp0GTecD0?gj0jVqv991@a8_k-FbZSEu%tRLkkGV!83u z21gb_xlZ^R%C&Gln@ApHH7~$KjE7N((P{Aa{|e5$NAU`?^KWlE9k3(a_)?{gRBkfz z?k^-!u`vm&2n-^uIKG7Jml7gcWIj4lI*5CeHko~gW1&LzeiYizyqC8;r7-Z|PB7TO zzI-JRc>V=O)=cv0Y!Ib3NrU8EOwqS3J@7r-Be--Hw$qf)r}Nc!Uog$3ua z_ls}O?7jIC`klDlCjKQhnL%+9UgDM&m9gZ=pnHprdhI=Dhgm!#P4kr=o91^z zC7UO;Y1O9r+j+l`=3v`+k5TChD}Rn2;6$+GGN&-*9y3~_`v2RE{=fYt`+r;8{zH)_ zZngVA2K~30um7(98|FJ1^FbKy9yWPun&oww&RtRfY^WS_?U!dG`>nN!Tj zJ?3MW&EU5p*c#&S8O~;(o!h3TyetL_$g3b9Yrqin3vJksVhh_Adr}pn*RLKb2)4uB zH;PEzWIlW`0dnIjumVd2x!C-rT64jT9CfYnWGRNV$`-Tp^(qO>g&MoKf9OGyqLWjYH~Fugad`@Zcv5PhTm7v4@1h}|MVDLUSlaNpAm0pm!WH$hk`19 zod0p+#3T@$E1C?!vHK^2Rd}_~6kvvqg%{#Z2F1R;nVCfvCC($8y!K zq=FccuWC7iUFz5HmN0rS=XYV9%L2r8E-Vi$v^JUM82ig9>Q3^u>x3)BhEUqIEBvo3 z0J~*GKEWaAOX<}Sgu%d6>G@E$Qt>`v4&+Xag^`@Ci z;8-`-Ohz?aM;E-E<2iQ@hj&45+9zZ#f&_EDB*|LCE*ZK_<|XpJ@I$r#QnnLC;Q=%6 zv5N_l0@@4qgb;CzckUO5*3cet1S?Z52kzn|uf-R*ff~MC549e)I%s!aipF6BxGsTN z%N@8oKU;=`Y-njliYZ3gxexI+IyPFNfw%^b9^Uv3Z zVeg%pJ9FmDnKNh3IddlIzZ`4p?7JDT_i}RVRfT}yMNE^uXDU(DAh=%g6C+C0bW`F} ze&XS(I9dD_sHjaouC2az`Q<92$XsGsM=;k{Y~ZVO>D`YAh1xC?Z-B}3ZQ%&oO^AMukFpss#g=)?_AAyN7>W;oGRzx(Ur~C`oY-91JTSpO}f?RExBYVn{NJ+59Q^(&EJ>&mGHhle?Q?l zyBP3b_ZODmMfdgAF3t>Eer%NQZiWXL_(t_N(1if~zCWmW#YHL_9qOH9xL6}J*5hrM zBYw!be_Kap>tPrxj%B%^nCE`=9UNbAvFeK*nF+kE72;tj-afk&h_b7lR|;}7b#^V# zNBS-Y?o30~zD%V1SfUqZ>MwT}h<}0q!uZx9F#@-&5WR5=Xts*8h-j@c>293ruABvr zeRvu?R(FuU@kd}0iv>7y&f(MyaOOyX*Z6e?xU*JMZOES6pwtn&9=yl$D88~s3y%mN~8#C9YtPvZ%v01r^>7(t;R&73gNZctgL=vgr z%HdI;Jyh5k5cdl1M{AZQ6bJhPVdZ@2F$XJcUodVIFp7Q1S4>JegVo+8*U_uAv-o$A zgKNz56(*o=+$*f=ntO~eQ*nXm_|vY*0CVy7!f<_eIDq}{Ol3v)ah91t&07fF{rQG; zx19ogtq9xac)QiBu+w%qa3E>lh@x5(nE0$knt4!Ej<#&d8rYg<2D88p!Wt&XD~KF_QBk-^55 zN@9`y>sbh8Lmsa8jy)KG-_!ZLKGH!)*59Dmu?TkF)FY;1z`c zDz$c=Q?oANYMQImednuDx9h4*`2Q@6@jIRKG_Yg(sML9#39kbV*c%&i;Hbe?a(9A=^iym*CRVQ#mX&5O+$s^)&kaYLt{HE zAp`7hupxA5Y>mR@Ev#vrXl$Omo6blm@Q}oT48T5NmjQBW6Cf{!7!AnAyyHE@soUNJ z<-Ol51VtO?UF}{w6M3QHTJ85l#H;7R-JbW(JI@T;*{;c8+vgK;{pxU_+naN`a-$=i zW!GxCgpRp)A$e6gbtokv-I=q^*ZYO*UouWYYrWqZ%5NN@x>wrVLNjg|E`|&+v6UW1 zF>c-2&YUoW)DM&P1?1^|1_FHy0)smj@bUNG&;PeH|5@O3Mz(EBKbr2FncgMW(zEou z3wNITmjByDftz`R&wg|N@Y95o*nM_#AIUsmCHY0)#BMpmq_l~CZ#B72Tca6t%jWxl z=-+4IL-$AYK6=YQ=;$}U4RMDuF8NihFIGD@cU2!{WS;0goI^AlgE5~9^d9d=hQ-H5 zRkuB^QD&LQS&#H+S>z4_rTLR{zss@(`Zi~OYS>T?&8vK|50caR5$vr0tk8HO31{NV z+e`d{T~sRb#U~LL&jO#n>zc*h8%XziB7O37Z`vnNwpE8jwW6ioWJUV{9!-KI9i3`f zNnY$Ik{TJcyjZ2LVa2|WA`mk_X6aCQV-V#B@8iG?uMIqwc@Kj0l=O{HQma?StjQsx z;Aa+VKq1tzvAkFs*C-lS1l=7kn)HX&`tXC4fE&!c7a%k0@omE|(_ZJ7e?^)65cC$V z@8I>_SCJ0ff__)mm`{Y?J*7qvUbu)+#vDAGiR$fNX>>R#x#J;ydUpM+4!T=2=#9<< zqPRC0o_J-QH7z+GE1qYy3c@_X<;R+uakHu@xf zBU64T{B45bOpwH?FXSUY{h^ix_o+WHp%Uk*a8cEBx(rtDvCX=BCEh+X(a}I(sDXXoTmnF?VKQWQmyOK*l=ynU zn6bZdh+-ym?JOJ9f=#xL$8h{A1^k|(NB4^*6FzMIa^L7x&axg)3q0Ot&Qq(aI%4NL z%g(~E+tso$_C}<>rl2l47hvCH;X1L-J-G-=V93Q0oE_mHbMm({d;Vsi`w~aMpygr} zUsYCH)zkD`YIqPk-)hE8^%`s2#(U)JA`Pq4@*52%jz8{JqC8a}wgvrejbA^}&j^sQ zZ*2dG$L7a|wJF#MP^R{xRBCt93#*sqr;6!@_sHq_c_zQlX>Ju>c9HrabmC}rqSoDj zhXXwz{8wECJqQU?1HoTKTyG109pDpC1M}cDc*9th2W3|0m@nAT&eVEkeXwvjq_FN6 zai2~7r9ZLp#;6&3IU0J|NAxl#LoXFRy-aaKc||)D%s*fE3Fdcu{X2sB@9H1EbNx4F z>Ob!PLj5H>*FPas|NCS9zr#Oj=lWlI&BxDm{}<}lmSTqqdwHh*@BCk=f9%fn@0O|m zxjp|Ke&i4r9M6moJ3C(%2Yu!4r=l!09phm(4t3kpVZ^;c#)ePA!AtYhq%^PLfP06vCDEr4KEiLZ@B`LU z`_hl*Gx9YHDOK{B5kiQYVF0^gLmyycEMP?QpNfCovC)faX|Qp;v+NieJ#zw_XCy2}M-o`xoyhU~r0 zSvYRVX76pXqfOZ?ojat4JH)GVT8cXg*)cEaCRj^<#YLZ|{xc74Upd@a%8k*@t_Oz{jdc zJ<+0G47}%Z2M_*Pk{u8^D8~g2k zFq22v@?$UBUppUj5uKe(nnJzj>`O0LXm?a`?Ns06`}Ng_P}$?1Heh|DzM(!sXgzXL z?*V*c$4Kwfdw0*igD*_7tZ zs})xr7j(DFUubY>Vsv5|(Vmg4tBrprius8pMt6}O1>4vamNuz~^VqlH4D5%iP&G}4 z!?NF?fSQGc5l7<7TR}E=)KNewhZ*mtob%J%>63^nm-rX`ipKuV=@0=N<|+=qvIk9x zp4!CaMf{cUS5}L8f4BZ=QFFo^#_DXHqq#Nwti{@L4Nk!RBTUqE)2z|~9kYf)V? zX9U!3;rdT~%Tn01wn1WgiN-dUWpc8ck1E@yjt6`}>EA$r;e?mA_;UVLyz0bMb|+J5 zVJc>(sbz`F$0ep-%qM0)kccle#Z3Q6?ABXXd_6xK^eEHYG9H|gh1S+I6@GB>D03GBd#A+I z2L2kUQLysU#!tck8|GLWgHyR9T9+*EfhFwlcMb2Ezf4|c06ETAqLALFFnZHN?mHaE zGgDwK3NqumfMIyFVfogf_D`e--Jc6#i6#0sqIHs+0GR>Rk&0KGWkqen2kERy%bM7y zq7FRwi9G)M@@5L_u$4Mt4#d?ZFDVFad4~Jiu+Fl%zoaNqe@0$t()%=;z(Bgd5u!o#x+4ir->r;$)6I@}Oe}C^Fw2rpnuCNFi6&hbvyn z?uT}18_vn<(`|pr}Z-L z2ZVNwxYz32=B7Yd9yd9=S?gt`ng1&a$Q1YF67Em{>tz58!*NZq&QPE%KdAf9R}+ZH z)Yney7)*n#jny!$>A^FDvrsfJauuA2U~cu8b;?iA5I?`7P&iEg z{kA4US-Af72;nF>D5E6-C0Snls)9V{dXXgY=N7-lukmmfyU8WZSG>oH)G41XMF#!o z@{kstYT4q`rCCOJni(6 z@IU%w!-1@dgDVB{fPyJS-ex=$q+3ZX=?ldASR%Yc~rwPX zSzS^!t)MBTAZydb@gE$gny_E9OBk9u3yDD05S$kGgmk#$y@KNclQ-Aa<6jw!Z)fqj zo!q)s?yi%XvZi&*{1FOykrCPwR~8|~b6{J5A_UUFTx5Qqa$?nTd2>*um36YVJbI!U z^4KXs<32oohwygOB(*y^W*#=r{Oqe(#)|_Z|3! z;DIV(KG6C-F;@zNm;2V*2n-Eugecn82meYDCsBFF}ztL&MZpGH|*zGHX z-S7*ZG{ouBpDz}XcxI+lkb_JAF)Ze%paa~XVwKG|#-DljqMZJce_fgjrq17wPCO?Qa(Zhjq6pR3|Oy z{>s=N!WD1!-eG_`fm4>nIe^?v>V%ExA0*EGlo#3}mTNnQ4x)u^!z)r}Q%ON3RnOuI zxVC}{qcdzz)p4&Sp^gJrl3iPw-`rc-ylu#p-_y$=|K&SW6KvlU;Ajrtw+{;qLMQ5{ zj8Yq+L4z_iR&`x=ExHm8*b*q^3|zOs5?8e7?Nr`03)#L5%qk;^Z>2W%5n0aD4)kQl z)1I?p4Fd9`k6af(3%fbw?mvzvGfR45ig;w3)u+`UWQex#!cF5o#GvQ$!`QHzmUOJp zC`k2>BFu-=&+8JTt!g5KN@1^YY=HfihTSdNoDZ}}IAT;>> z&)DyrWk($Iyn4B<+F6Ey;q@&W429MrVY<)N?X@w&NgIjcNBi;@#5XcIWz*y{uiUHo zivx8gp<_^rJ1b|!1|OFk{=?L8j>mDN5#d;J?72vS{n!1j=A&dfyFFp- zvet5mgH2i)oMn3?kK5F|?aV93tNx*FB~V3MN$MmuQH!=ZHuSu%yjiobK@955n?)x7 zrjAg?VEgVYdya?p-oecsm2J9c^*JIvG`};X`RySlWe}eRnpahtnl(^(l*Zb8VgjH} z$;RzM;6NM;eiNOfy=s|RC|``CD%BnZAGeX-L*fJe2IcA-SS~J^MuOd-sKNn!G|YJ9 z?BA*1UT>-MyCcKN1$My`r5lLE6~5~xx*6M#(ZXoS?M7M=S{^r|_1ApJ|&IlrYeloWzaos;95O ziaaE(bZL`XqDR5ZUVMSs&MA}XlP46}zOC2_3M$rtV^x!IO-JMHxhxhf@*Z-GUVv0(r%MlN)8HBP z0Ll_u6uhG)xY#m`vxu572PLfCe<$wKMj~-(CDvx7}yRF)=Qjn1d8Q2gv52 zCzz9UN1cPN;J*9p7fbC=yZsTx=D4FuY^==c3FMRN>j~PLDVVD#5cky7s2{%TF>^5{8GOSZdpw8p#$1Yp5AgLy@!}fVvPd>G9G2BX=(aR#DKl}s z84JUb`XisWTKA1e;-r!~^i_36^JJ zAd) z+(zqF6upV2^;hI)tpIt7CE=8uz)eAhuoX+747sd%a*6zl;;V*fF9K>l+a@=(cCnhO z&gvq}M{+n;>4@7MuIR=pHPo(;!`g1552KiiB+&3!6sY|G5&tw~`el{C zG2nG?)EsnI4X|pg*Q&89vufCKhDQ_G^RkfyAd9ze4hIaAkFP389py9WSL2pRU+6RG zm7_Jg`f=)TG7O_I+X`q9n)hU^?Ch}YGPHc(nb(+Tw-K&5yKXr7`*pC&r-r+EIJ$wC^G7=7J4sPe3!P`G2q82 zz`)N!VZ{)Dd9o{MpJ27)gy~yP{P@+?wQfR(Vkc~jxSsKM_$1_RByK=-hSh%svFmr% z5xk_L-Po%Jvga4qxv$kBFCw!%pBht#FjrWY*ex}rF7b2K9dQW@b+*(^VZpu`@X5qk|HE`u6Ws}r~I~pVT!2-If46Y4Lk|1o?omdXkdmhdOq*Xy382+ za5P)%ZP|=&C~@s*N)XF+XfW|BJ-VwCg`-vn@_H|noR=(}t+Q8n-0f?>+Hk5}!#H_FAMyk7sXg}9#6Wvz$(kd$1-&RuPSMny|Sl}!szKV#Ob!V+Y z;LbLiYSApQ{!90!wAY4(98bsC*o#O!ClD&1ebI(<0*F|^sg1Ak%8qXx6gz@_ePev< zu%_KF*idp{ULIv;XUhB*vbm@|^K~Xw>>3B8SkVQu${Y2GpON}0jW7L^?eAd*)L6y8 z@9)j4)2sQqj2@#)NS5Bg{ zXnOMs?Zp`!vkdEKI~8!zP1wEPMC_`+vLJfk%3>9PMPBM@5=zmot1!`Ga=7k{(^p55 zX7yJvfH1Td?s!M4EgLTreFBmT3)COWo2kW{{25h9?O~RMv?|7Fbn!zxpmQX4DU;W$ zasMHWyjcrz<4V?T4JQ_vwlj1DeE0ILg!v06D$q=q zq2Mj4t=imljd2&tbeGTC%xCL`n+c`H?#DL$X@k<}KAbQaYVre-#6pRb;Y3xiYoWY? zdGU2zyG5#=7S6fkgi5~kcPWFVKZebKO?x1v57T|)n0d_1n`XKIm2au+UD#m3Ba zr+I|J{QXr1j?6D>Nv{XJWZtpIz1FmYJ#Juqwr-@H9(H@tDWEOX_Ik?(*reFM`$gSe zFPeQe9$ctnwnT?Tl3`+h3_mUvV&AO}PqzAH_S+-AdB1&Pzy0=e#;3|N`|VxQrIUbD zB8B0ku>;X=VoOODzr&*Ky*yc%T^~-`3l6qC#{$r9E>;&brP@vp(RLcB&g;sb)u?U0 zC2mIDUD1?k$9btbPcs^3~{FU?YPGY@j zz~@&y>rxZ<4l|57|A5;%3Y^YJMHi}~%Wi?}tidK(69`s(9_VD4VncDRE<|$@=;9ON z;QW+|4D+(v!UG|X)hxc=vZD-nr~@0j4QZ^^TuK(-@keB(O{%Jxs-%i3t5GnPP}_c} zrF3MRg9${qQH;a-?Gb5_IEvQeJ;0I~4!qSXm07s{BeeIeTjs^Y7#dK7fsJTHl@<^H zyt<{mafs2QrGh~>X;Jd3cVkMzk7JaWaW6l*f5!eo2)=YzCOP(TYIs{f<)-BeE|G-0 zP8h6O+jO&GcYxYC6=wzM|jUw9e$XjI_xy6!?mfS@Wg5qHQf3> zLy!)+n^7L_Z>F)SB|1u2@=K??f>qm_-boeeXNW8rH>cn}0P90%mPPtJUD`+SffqT4 z>aCq<20CoxQ+Xdjt?a>|A)|48=JH}`9Hq-tweJdDvo(iiijmJ@gB7WGOM5of6z0Ls z(edOjCu6t4-8iB@u@nd0H@s!YzZvJ$py9Rx8-=XlG_Qi9p!-2+(mh(l=1q&Z zUm<_8Acqw8_>s4uHc+#}JP9|Lg0bR%7QJ0*ke@dSGN zYclxt{a8y;8|#ASZw2E|&jc6w(NQ`vd?U9P`Y3Asz&Hd5JK7(cb%pwIvaA5H^wirum8z){`*MY{c}&&(T|%VYMxERCEs{|I?TfGAtR9*8BYgdMTrNL zlPZj-i=vg29?;M^Eo;q4^>{BoZSm3i6$zMVA5(g=co|Omy*JzEYxJDpxo@y|8fd(n zW$(jo6b$Dz?<+(YF_3q`tq@;3T));=@vv!Db@pgqOXsl7QC)*;Ex`s&f`^Hm>^A0ti;JsrG zY&rmIte+`j>15AoCOCXQz&Xuu!kp6F+0J7KFoQH-{+B^pQLQTL>S4{EwQYKbU`+Kd zOqNG>rMZUMU#Vw{9iyUYg2&3x^`wuy>E1SoOZ0X!TPZ_tYrSj7*(ABi_#}9_pL7UG zHLZW2_d_WonyExfeJ#tj@#c}~=QSVkg?`Cnh(nU)Fa6??Jmi<$2raR4MXJ8qAs)$M zzracrU>KhFLH(V1f9c^V-ef=JR-3{oKe~vi_AEk-`o!X%>C+>A(j_EGt0FF|j!ah& zfN8lM811(jqNGaTV3Z60)0wi~$39L>_?Cg-f8HFI{U63|E$cu~+gZn7>QfrHhyXM$)!CbX zYi)1>t+NdhRc6c81~I&khz)%i=+fR5W-J?j3%>56CiM+s%k$1O>9NJ4mAh>Z*z<`) z*#0Bb!4onQH3P=kDN$P=`)u)QDlk`6_IOQ0e3sPvGZJ^=zd81Pj)%$%mFSMfYv?sk zkv7GOzb~O3fvb$3KS|^fuknz6Lw*~qrFV>x?0dXl4pyG!*Mmv(1DK2wc+Dnnvsp)P zXZ#qckj;3%|FqxrJaW)%twvqbO}xX!%^auAG5UL8260}^qYpYH&*%!^d$vyn6xoC@lz|Fn}s;r%}KKZt%0F*Z63p9cbkY|D@7s+P<2{ki?Wzjnv( z&G@~I)*=oM^Xu*(=+W;#$70s}G0^ANS8XJp%y~ub^RC5@Pd)^@QIFgvcj33T{)=hJ z$xq`j7eIRE9t?KlneA6f&7riIDf_XUwzLb=LVB4|UzXHXY%+Qae?Js)Lt{6iI@=s^ z3-Fi@WRz;1sM{iL?bxl{Q^YV+LOd>dqDc$eAib&wy?^uMeA&LzU96>nt=hrHSC5NS zecp6WB!4cIpvCZyrq0&3W2T1K>~n~}e%9(_4S}mR!1x%}$*AsuKJaBEIeEL)2XL!q zy7YVS0=acy7}#(XwM*Jq{pf#i2LI6528aZ-L${n4z5-=AN?ZoV)%89C$WW*SKi zeVXL?gt<81o>O@hy)##=tU)!ci%u?@gXV?Z>Ph^Hhyj5s0m9fmD{$54h)>7cfpEUN zo~ja8lfYL}j*jnMnxAIWrQqCg50@-H4+MH^Sb@Wd!CY{*5kSJb4@e zVc$PL({PNC=*73AY4#TDQ>hWHaPtte&LUVl(kV2*K-G|x(2E>FbnqwF55}L*emor- zjNv}=Gbw)Y>E;-+ph!&T^F_rJTAiW0`N1j-<=U9$KKc)#}{JknAd`9R0`18s4S8K?em-h;Gv+JSV;oexOS(yx#D}ZRN#zm$xUGc2TNO-Zq zIDuk1*dkfI&f|BcvROQ4yCZq4G>DK#D=%d#;=S>dMyMOV4X=X<%GWZFeaj2=Ko6M^ zpQvC7^;|;yekMBc`@I9mtxb|_4m9`6>)$=Q-#4Z!8~%1Y9;q<5D+s=q>65ylt(WOj zBQNqe;04_tkcR=uolzj@RYvOEKIp&I2YsLq`cdAs&jG!3gYbpfAfC{)-eshjcY6ri zB<=t#uLJNm`YwN5g`j`UyLf~hm){5$Mg2_Azd`{VzT$|ZcUC!xee9x{DazGWeLek# z(c_Sb(RmF#a5KiM@BK!Ow)4DwpUjTj5Q7FYa=UoftucMCP7U+s^Jsc&#>x)UMGWEP zWo8(6?)`t!{}S8(dw1ync+-Cbzuf*mO#kP7Q~yJB%cow3JO=~n9Rokptkmv|%ALAz z2zS3HvfVE-nDD#rc4xca%;W#d?wj$48)xE$$!JRQmD1Za(K>cNpXHigSu;HVitt*Ryxjb5W zH_CS0Ic`51*(mwT@@A@oBA|wgpoX0<=J1I_^8tKtc+W6Fa|w(9aSIQ-JL`YcMhYk~ zkv_cRIK?Ja%&zpqAN%-EN9SRnOBP>pJF{fcw{xkaHd$EqOH%*&2X>LKo2nO;FXh*8 zxUk!i?R&@8GIMak>2}t@1!TFX<>&?TJgl2&^i3E>Xnx6W5Wj?o;1}ZD1Mx+1aACTL zPx)=~G2dt~|3rB+$?lBN-f}`?`8@KDl`L8?$nk_IsV<5k{c}GAH<{~HIjpw>BVn1d z#_4v~V4LfByDYp*N6Jy5&$!mh7ZasZ5ylivzj(48jU~L>(b!=m3_r@@pC6!N{6FBI zMZ%)G*Pnm>725E7w%T;kP|zsv7@*yee;%eDh@Tn>Xux3K8UC3A?_>k7)AoScwwy5j z)8TosL!gG)w=wP&`zRwLVnGf2{({tZDNj3n>|29bO()Dk!LPqYU_sIvVHOK_hJpRrZGxAo% zk5A;?G}Pkd!(6PDM}`sMEJ624aWl$AIQ@hH&1$doPgzucVIB>Af6JSTmF=6wxU85D+W;%b0oMUs5wN|Mm_n}{r$RszzW_=rf zra`AFtrk3o;s3y}D#P%t4C-`?@?r84;DxzW)$1dK$%pW=mD3Zm)ZqojJgZKJq zvP63(_$-?;)Ck_o$g5_gdRzEX_m4NzkiD+SyA>s%$a$zLb#KY+OCcPMT5kq5qGcGKD)f#8B(@Z`g+a7HI;Tw=gWS_BAadF(@~*S(y>x?Z@AQG%+a2`V z3Oj3Ei+jxGJ=Ma#XtL*?fKces~0(hhu@+%7ECjxSSDx~7fCfNA4{Z5HM%zd z=@^9q3&R$0H18unC@Q*FXM8c3PzIJGm2A_<~8HZ*^23^J(tATl$53>>LbTMV(dU*X0N)0lQ z=VmMsmTV;GUGHW`*!qo2U`PsDi4E08mRmYxDCBx@A*bcb?IyDfIFl!%cmW-UoD9=J_v$SE7&JLHKKeSZ zG2ikB$*>F1_ORtIqo0%1&x<+B+c)T5k`9_Xda?sq(;$(1w)jZs8#+#Zbu~Tv2laRs zt>l4-ncuke9rp(x0h_&IgNx@SI_=^uL4-$Y*UrC{N5k)6AFU&H?r9Axtm*0Xd(j^m zVCS@Myy{f$Z8}LzhIkj^wciI_1~J=}nltNryqnnGfrCFSwzPjP>Z(38z;s3XvpF8z zd&k#)9V@dnd+%{BskNPf(TU)itwFb|w~=DZlb`XEv)cUm&&KPa+6F0%4I^+XGDCIn z3@jqjoLfJ{Fs8eE?_k}CKWTQ!x*%5y|8~FZioVi3MdN zP4b90G+@c24~BL{=kGz<{rtgL|CuXl>ly@#;BxXcc~qUd)w{$98F*GEr$ay3NdAJo zCP9^1e+kY~@4=amqiRdi+=~$ZqA2!ZVuHD8f_|TGsAZk^LeRL#7bPw)=*3kLfJ$fi zSzHkaV0a&0Uer6zW{p^+AzSC&p3NHGTWqtA^uKD(W|j1Qs=-c{R`^-xX0t~1zG}0U zy0*gOvRR{hpCBvZ{+SO4@nN6;3O>FLuD3^phNWX%L%2=-xqNJI($;jXUsIl~sgU?b zsTg%!frEfR_Nq;9NH0&FL3*d3zCN2iE>&Zjy%Cx)=TG|D!)G7AIocbaDzk;IP@x=% zhGrnDWPpfl;?+F>gR9!=EIOPy&p6lc0i*s8P^dAzguQ_rEy_ZZ_KPXl{hJBVKN>9N zYwweEDm1CSAU2wu)yi3{9IhAR^Ij&ia*IsvZO4LiWwI_-*7s~yo3f^nHP&REsI0LzYp${?$r^96j#O5@&AL!orDRpczC&AkDeE8T zoQx-~nZ)e$Nwf{OdFImAC)9 z`snBF7qC=sOqcFg$B4pe_Lw+2x|>`Nzr(OGmBTiIxUNLVwLtaX?-GRO7c<2otVmSV zbH%}djfB}o_B>MOrxBDEPbWWJ`sZ5P%s%17wMt3+O5a(POr_8_QO$5Egh}t4FAG-Z zm8rw3at~GcQMSsfY?Xv&u->@Lhh3RJ-Ve=iVZbviET`^1toA+m{ps)TS^tY_(<%Iw zKM7a$IM=p7jp6!hLZrGk)GDuHbJeQ3hhUOCigTP3NvT+0OMKnrs3LC&8c}zl${w^( zWe-{y=3k7dL+Nh9yd+F^xayyM_^Jw5eJXsJ%F?C3oM!QbT5_SPPuwYxviR!nUFw=l zBVX)*uTO<9zsiWMQus2`lkg?Sql12t5#I0a!%OCgUJH6|;;yF=l=kO6M(0iD*8P>diZGGG%anTJq!M4eH zX_JuYtf31{sevMVbI_~}U2Y6h(taC7JZbaGTla9?QPKA<1mqXhQ} zs3dp7bbXtpmX|onQsAufE<}Qcj9w*FLk<}wCg;Zu6%p*ljDtT;xnB=DuVY=2_Z|EF zE&abgFI&N&frhbvec2}^3 znTnm~5~Dcd@%U(HBQJVnrq%kmzN&RyHD1*{cSIyPYN&t6dfioQuZELgj$8*@p^h6> zZQ@1&yxwaDp3ELBFWjBz;+P+9YU*5l3Oz8 ziL~IwS4dt=#}4&gM$H8^FK(6iQGBOdxoUr@&Sn(-UOo0Q`MPj8#ds|H$4N{Ww{f+} zheJRdsoz}=%$R*vi0o_JA;GHka|wMt?;yfYi26entLp08@mTPJ-_yoru={fGpdkmv zH5XJo@!i_w1F8zQ300BWBXPf(OzyL2nSzN!DB-?b=YABfe_RY(9w(?_ndp-EXCEz$ zImyo%fk^%4@PbaghpRq!uKhbn3b0q42X|Uph)nSKW(FY_w$tQWe=Rvg#dZ*G(eA}+h!gENp_ZaN` z_I7l(3&LgKEzptPM5xDBd_wZ7CqA$Qu$@+II*G}ZJUO40M;%C6U3QDaTWLsI-{67C zCRBW5udnz?rq?H?OZQ|8WBTk|zkqL@mJU^g9k4}>9jtE0s{T`r<*+&#ZjY zyxDxEc8PBVW2#x28i-O7(sX;W3t842Rbt7s2WB*v4mNn%y6ctGS**~D5@8vXv}91? zO)3ERWa&r(-;o^<4d_n3oVnTcGa7qQ*tz2<`OwS+zx?m-F|P#qOAeyC+`prF|4)Cp z<#V6^(|5|xl+WMOMHWJ25scOZ^&;D+Se98d18L=C#bzM zU}S%}A8x@1&Eno};q+_zl=>z`p(~?@=CJvXgy>}Hr538?{CMYPpt2gjrt33gQ>wBk z{clxOs6y}JS3a44EWeMZ?D>WIJB2Om`V^h1PNTO`@!5=8S4;VHlE|02zFNQO(itdP z!i-GO=NnM8Ri+A9+)=Xd$iv}D&PkHY5`u+I)-_cSPTpkdOPAJtUwRC_o}Df|k>{gF z9jF<61taf`5WvaO-_18D-^h>G#-fFdf%Dds%_zjs*E3}7#5OZ+6xYGGJR}Rx*Qf4F z-X5q6q~}(b<^E~AEDg9phBV*gNb~(QM@!IrYXAlaw!tX*{(E>L!FW|UQ@C2q7}EA` z+HpvYyrDI%#0d399j3j1TZ>End#AcR7^+9uSq$w{eOStwu8MnQe;z$oT8P0!`fEvaq{Sis#vFzHzRUJ*6t6ppJg}o|atlBUT5bJ`O{T&Hnv&HMAJ!$j(Y+H7n|ze$(OU1Te+km7rb=n~Q%x9I z_$GHQP|Q(0B&xDM|8PyXXy@(#zReL2*^tcBGUz@fPzmY zOGjB0#rW~|g^%Pg_DR?I#Q^V+WKd`+VNby{(z8Yy~?Xab9hY34-|%A zjAyH#5&)@HmI|sl>aF9-3qELrX~E<#YU*S1q!2r`M!_NB5xN(sAGgo5pe|sXnWfM1 z<6X%tHK5u!3ko`HXtwt!G>Q!-I<|R*1h2g4Zr)FhHxW06nboit1u_Hh%W~aH5yl+W z&abh{@{6LqZ#}p}<*6#R8zxAn1(6#2>%E4L6V=FHC302<8C)^{Y>5_&*29^FLM7!= zM@cOu)B>$;#~K}RpGh4sfdD>3#b2s6&l~1GU(t=DL1n5?byeyg++$c!`WBN#rV?YS z(qf`TC0&{~2~yk&S)PHNfoFd)nWSNUhK(e{e8yDP)svsh>m~4RTGmFU&uzhuV zzjghU#Gn-o?B4p0m1OO;%D{pOmYDw>YZTtJk{CQ{CDA)8$)l{dtRxy`k-?c~tPZ+g zrLdd)pu9w(AVdP)LIUGVu$H^bBg_YL=@;GsGECHO4YBz;M`nVT*&2r3X}S-b^;*c& zP_^@ojG7X2v8u_Ex|GL=4Hg#0C$E`TEx!#sLn(RZEg?wDl!*n0az4Uc*Va;Aq|tOY zc{ksbPMce&Wh-N6CIe|39}q|(T{;u|m{~+dm~)YoX-t<+Q7R)z8R8>aH<5Jdcv4kh zjv|AIUJeBG+DZ4CrF<`VO5YFXGV7}CsvOO6vQD&I;D))Makx>JiOZjSX|N)$LW zisrz|lql1hCl{g9N)4K@CYTt$G#Ge3ShY6foX{HzysZG`oEfRI(Jh)58^M8kLtt7s z)HsB#kCWmBWX_w&>UmDkd8iBhMKJK04(tt2))D&leKy8K)oH%E5W%J#e6QdSYJE}Z zRi4vY!n^3d!xV%wck>_)y_{d+>SN0LAKj5DbFW|KCcjLNAWIf^T%m=2K9e+a2=Eb; zQM!~2!}h0XfGi%ge>J#pq~ELRa9Yq<yyJrq9D9_P+l@P2ti^w94hTR^n>!*6&(}SOx(q(>5g}d zu6m&fcf-;n3<&GIJ$Df(3NsWP)@eyFKeemh!6yvpp0jLP0kX?E6Q||J3MWnrpsREJ z1G@Ei)1x~Utx>aG0Vh4)_QF!`A14}B5IN) zyLlJNDL^wYlsu2EGFSPu@Itqs>c+79@^S9utxRF;5$aKf95tSte;UGg1_Pae%{5i; zYL-B-?#uY`fTv*knMk^;uIlTiKZWFWV5)q11zw5JO_vH(Y>DojGvC~oR~&3Ie@ABg zqx=|}rcC);NYa+L0otE!DCS$Dp6KXWmor0L)y5D{XXMY1G7xvK6RTm8=-gNF+~c8b z=J;3CZN5C+d|72q6(vh=<_mP_jAjTyk4R-sO}jUn8d4KX9aMT4MQViYF7H@n+()g8 z)zA--0vHZ|7%IriIZrP9&C#8Q?oEbUs1*B@nGz8Aoh~|J0k`Z-FVz;~JWUikMn85= z`8YWsm3hrzO$T)6vcM`nO1kOSrW3o{$pfAMX*WPhm(D$$DQyV1I9^9WCpxS}1xywd zby|B^zeH@@ofU`;Q=KbFNfjXYo&k9Z6FP0>u8mgJy3=z>e$b2z^L@JMl)Ln5-BEEC|gqY?_>iI<4%V0tsu2kZ< zEIP`(YSiqRRYqf}00edQABU5L&(pB`IdPm$R%0;EyQn^#yn0Zb`;}HM5%%%P!$0JQ z8vba=P|MeSyw@g659BL9zK205;RuUURGAvu{CyK=!zbtiCqVnj!rAI(vh)-4Q~VA; zb?BWIZ&PLL^={?Y$Y3JXIjXP@&7`wz*JvdK3Xq@3(332EO&`LsTGp`OkK%>?8$@}3 zw!o*(WPAvpe)S-jgVQ4Pw^A(P)Vz=?Hm~#S>x;JD+f*;JfI4g3f^zRJ>Y)R%VO7!c zbLNgvMcKJI3+|Kd1epC)MZBws4wdPVr6^fA?=mGmLtKCl(U3`?k*|=jC^m5yzuMGl zGONSFq9sI2f}^P?UHZkL>gCmgQe%b0J!%>BW(v}YJo16l%TqtIlY1rQ>jK*WX$h@| znfe)_AUk5o(z(h?7XB5E>$FbC=51!DsOmUD5IZijDti+aX;#`L8pHUle1W=;Z!bTN zDxA<(Zv-VmNDax-`D7AVUoc(F!e;xTnWDhnnp96Us7K>~(6Ao~+>Ki5A>Ch^UOCI2 zFtSa$)ICIi2qHOXsXbSvh>FG=cI#7lD$AAU_kRED-CxXFY;Dz1ZTl)B)V zZi*5ZP)c~t5yQ>BTZ!hZ`Oh~jS-&$McWcQy>p7*-%?a(*hou!$3!l1upoZR2{FA%Q z%sz*hv!hSSJ;XZ^?h!@`7xn1B+T;-d@U5V6PR%C-P?C>LnRm~1iea#hv#?$xk5to$ zjEP)^SffREHv`tzTK8|_pAA0V&7NIx-0r7l0=EA~Eu>3#Wp^x2p*AH!Vt>*R!pB%Y zyx-yElsw)p&rhiw8XWq1`5G2Q-A=>>BE$sY{+!Pwujrzjb>1;Rw4*RLVPj&~8n$R- zLhiHfODfg=vvj&@@Vr5Z!HO^SX45}1!8KUL9+TrinGbdR2{U){oEAhA+n}@f9bnBY z!V|V+)?eFxXF|jboUamh6quol>YzL8Pd<46tLz;nafbM+ z4>PDUUOwp4NC(h#XQb-0rX|dV3uX!_>%6m}lo0#NMix+CI5=+!EgztUTQ@fDVdOdY zRe!x6`3?1ddN9@5+E;NlCRsYvuRovqdHv#4+uWyJ+6Zm|rOsmL&esP__;A7&-GH(f zYZB#rAI(geQlOk2l;)B%J)&;-=jXUn={mwLaZ_yAZcQ#Z2yOrY4u z*A(F1313X3eM!&Y%UN^@6Tu(}C@TG)j01{by0fP0U(TY*_9Z$qc37}@K3w*Q%~_3@HDE0k&?dowY@ zndomiUB0uzTlxS(3;8+$frU=s)Qht^fo4)_+_yRHhBgg1JZ~2u!gno%Ai3#U0oPK# zSzjUIRx(K$j?G-FGmn6urPBe~yZsrK{^7jM&|8u>xn?fD6++jRe3QOqv!}I#xHz$f z;6>?Ok@`*izEi)Wp1@|>jjK-)Yn1op`?>OTvFWRsu&a>Bd*R54b>aH-ykdmgM-G-& zrgSf1Zne2}G+8>~c-6VqyOH7((y4+8=?NQI1%8a_3Z21hV8CDMK{Et3o6lRKNwL;D zg`OJC?hoWKga&u5cM{)Qq3aD^`3$eaWa-f-1L8!oQVva$Fo&AF14*Ebp|l}_-ZF1~ zmcAx%0ON@7Q-~UBofoiqP4$-pk<8wl3*3)B4jt zps|%gxZnEw7m;wk%4!u)P!UUiS<`iWOU(!DHMD4%abQi?IB1z{)-P&=iwnue6`R*g zPytj4S@v%9iKE4V%Zz4$(*dF;>6)u++)Z`$#)rh+hG-Ymy+J+R1FW*yH#oXC#w^T# zENAv>u!Hfh^PNRSFkX7^w4@nO?tsHM-|`uc%|@gCd$Wo^#NQ<@c<*tgw08xv>T#N}|Yh&Bb$G@O3a= z-(4H{M8X-nzb6#+sFEv9O_ZYXHTS(09ai1^VP$pm*F&!ebaJ-~Y*6cY^Lz=>%gqz9 zAHLl@AJKz*-B75rn&%&ce;lZ%cT~q`so!hTs`xQg_8Y?UaBVqb|9rGU9HN~j_)ztRDl(^aW|faKXX=?)ULn<_BI>T+ zMwFu7#~q|jP|dM}h2z+PQV4+8suqKuxg7XAp(tH?C*4l%;%_3a;e}|%Nsd%-qLROh z!kl)7c*Ov7Ln|91HtiW9MdwM2PWB1dzaJe%WTf5;Cx6Pup_dDhjC6t!ADZ~1fUeAV z0c5>+zGT6%wAu^5XNg&4CK2Rb>wYa(cqkD-5ze-3sM)JMh`zhu`Vw?QNtVNoV4yu1 z=peRt)w-rsXySp=<;4ik`N7;VY6zWJbi{c} z`s$aG>=S>X{JiM_mhJ|%rj=@rJgc=mCE}(w2j$|i&{>#W2kV`O3#F2aBku9oVUT$q zq@R)t%*q4z(%LQox0zpq-YkF3Odp2BThh$Z(L65zZFh5}6l#}b;l1aI)OTgab+?|_ z$`u%HM3tU-W~fO4XOxe#M3clcDnbs%Pi+b#N_;I#eZGxmXm5KU<*Tse0F0 z^j+XEJ&5k1m~osvp*rZF(lYzZN$p{N=t46YtUzk!{-=Z-JOBxKjx=Db0(LUM$VLA- z@tw`#E|_;&ts9wXg94)%=>U1~xZ8SzwF{i2MU9}7@0F(h3& ztFMVsTKrLoum;?*a&r_C-b^30jFNHPQ8ab&{>{f^XYz-XgEp;h&K6R1Gfg?l{;t!`bm8xN6HU*wyv|q4U(-(aB@i z#kWp%7Tzzs-RdlB8C(l%au;1&zz?yj({F2hlI~{my)iyQo2eONA_`qe`W%>0XZA*V z#_Xs>jre{{;Tt5h?T;T`j>+$sOUS4AUw^LTY(SmeIYF;BFjI^VF0ZCyZ~WgeX=Q`l z^j4FrK&n07qckrJY$GM7z&`q%?7x@U?APu4q&OmIUi9ST^kLpr2)j8jYNPzoNx-<^ zt$r}x{bO6xQNY;S%`($v>Y$q3_H>0T4kwS~dxL(R3CBZ;yxyN{Ve-*qRZ4b5ziiEI z-D%wimInkE3xf1t`$16VL$LhjOwH7p*E?A?+aN;V*l8Khdwk*`?keinWGC7pV^vDE z<(A$~2jUY8oz{Qx0OS^`n!D)a-$-GUi$EFEz)pejf3Z{G2GyN(hugg5^a5|BpVLTA z?|u5z&5V2W5YF}tiIuo@Wr61st|me+E|UGA-pxQAa9W4);GSHjL3?N)J81i>N_HCk zKB(axCqbtbGiDBE-@*iMy4m|HI_y{UkFmC*Hz?XW+*ah%Wb|M+JTAU%5YX91U*}k3 z@2wbCbQq-{$S;9yhGxxK49z)j_8Xd3W1@%NZvt<3Q_f&ZeRzCN+w|GAYUvU}&FfvL zGT?zO^?0}VWw4+4WtiUFRE=6TFE!iP3017YFSdKO7{<;_u}MHSUywcbMlNJh*SB3@ zn`yo=mu}!+`NnUQQGq*&S;jjG1J6w|;}a{-y5f%XeIR`Y!qbiy*U=cJs>Lj5_f)kz zW2bgY{C10Im)7F#g?$q<5Lbf<^Dh@@V7+)LVJh{$L+~|`@ikbGQ{V0TBDHU%z8ilL zN_zizUS*;sV#3a{lli*Gd!$Ugglijj0HbbV^&iKf&G*=c?ssf{UMVDVDjSnMj>*sa z8^4YG{*u2W`PJm5@vOR<-_@iQkj54z?|G&3_daQP`GZFE|1VHbIAZXSq7g&=8C(G~8xw-gUy7>Xr|kn>*qigA?I#sB*NZ&DIxlyq65hVwZ-n zmo_(*&&hLI64a@PU8cs9)(NGt6J*9M1E0<^P7`~@w_smfh7>+|YHUyK=gRQ*ItO@y zvcKnfcVKW!4Vyf@+F3>@)ewp@Q{5cz96LfcYh=9n8L%G&Y~wGX;h8N7P5PQ@ZfRM~ z4H40Uv`;VR4y3zi0bUkmV5b-9!Z=6ulr5p2guS!gzud?b!fAH0ZGm%i$>PbX`Vgv46>1w^MnCQ{=;w}lI*J@; z@1|NWC?A_g6Q+lAZH)>;ZYf9dYsUWz)rQm$#?cKui?mjrar@d9k`VV|Y%C40-iL;l zZLoc!=Nr$1`}_mA!;>Dl4+vsoI45I30gS@xiIuTe_-gGe1o`fjCm9gg^IXpNBP$EK5%=IX`^38OSu!}R0IeqDJ1ev!{03R z-IWb~$&W9~mYlZoCw}7VB(lfk%e~b_>A@!8pQ|qE8eZ*Gz87{coqGNzoFu^2o=SWNM+8v1qNSrxyp zU-1i79Qo4}U)#Ul4eJ z6tl#5F7=7WGJEg|)4plCmc>l$RpPGt3z6X`(gOJ!pr;Ff9zJ4j!+tH4od31!uhF%t zBC|-h5^7G;wnUMB`W>@hGKRrdy}ajap-+U6dX|%_SDi)M_<|F4k{^}b z9V+p+oYIf^XsF+gk-+${tqCZ&hPP+n2Ng!azRq;$UmN?tCoI}3ElY2TO0;&W)odk<1# z;%7*p=q$RXQrX79TXu%`mpFISe@XXcv4*`1#Oc_VqU7dZd8s#h7ch!{XCpq5(Q_@O zxUM!Offp*aB@E?+>tBq2T#z9!cWu@7`Q^3sUEX!r-u*AS0ta1)}*__l&*WqeyXbD?ca;- zalVu_-QE*Xr8bpMwA3$PUAbyYnmHcuH0KQ&a|>Njy1IG$uvlSds3;Aev3Xgw&K1=l z;ty@A&emWHRJTR*NrJ+(u+(Lm%Rx^+g4s#lwChBr35^E zXnDJeGWQdmfQy8$tEjZ4Tc4+Nxc=C!^5EY;KL0Bw3*y!4=up@3hEqmsiQ^r{VO}k1 zcTpPiAv(&ce>E-5g?W=L(T3umD%g+sUB1MBpY5-AXYww$wdu)*A(1Dt8pY(nm)_6O zwCr+P266d&-Xl?-!sD+3DpV<2pvt{f1o$KET(Qn_t7*I$l5(D6E0a+-mL{h>EnVXR zGSD?XcKu;V}~q0{-LlmVj#I!gcTwvb{DcE*({E=+08!fe(su1vk@~^H zf4Kr4QnLmCWqovr_c{fL!L^?$=d>cTrmY8mgH`OkzS%;=bV-BI)DH#L%|l@#$69e< z1qD(#GWK}s;Z_{@E=7ek(oj0&Ta0H^lNY(Kc-PWO>U@2o`OCM3wfm0xWAeX9K+5 z5DEHNmee*cAcm`sH4AKSvhAjRL$HPi&s*{mYtR$?y~*ELa3AAWHo0H(oHuyz;C%kf ze}nXIVDR7qehT|dZ>xXsPZ6=(BCg72WA|I5UH33|!Fp(!V1$^hf-@hNY$$$pii}++ z>Y&M?Zs7stoXMC{z#>@2QyW3yO!;OzCuG?cDN2n;=#Y{r6 zfIS6EPxEA=<$fMtJ&Y`jDeciYs=i*;Px;g-DO_;^WL4ku=@e%~0k*}$hk2jU7CN*j zIc;dfJ(1wn4YBm)9u?)825}oBp5Lqflh}H?@bIr(b*F`qkkTmo`K%xb%|C z^Nvdl=gb8rzY{BS8tErr570l#M=A$wFW9`I07j4(y|T^?;)m8A8_Gj957Bdj>hoFZ z^U-v9E<;C`Ig6FS^3|jW%O%NaBWmkk;6CVz^>u+)Z2Keq(KPrS;kTV*FJvv;;v*Q- zQ+xD0HFmZdtERD~`>CaSg_t4Op|7@by`*`H(7dFoszn}UtliONB58{2noo)yHF8$UXakf`pO-s z_R8sx!|tv-^w-+YLL7&az97&ZsbA0S=MivazURJbTu&n+{!df;_I+;ct9|Cge}ynA zh61azwKoG0SD_C9Oqm=1m7K{zhYewD&2&o!G<%}TNDF2`7xYCSc1mYKWu5^Cp8z96 z_qhQOzd)NkiGBX%7ag26ZVequyl*LB=58`v!1L zLVsuSu2$YD*}Qi0!tUd9AiJtZ8~AtLAy)CBTbJ?sEX<5UY?!UgY~2!ZeULC8gx!zu z7&==nfbb8N3A10b)`tflw`&2ixETC&OoMhS84j3u0lFI}Tu%mW2)k+HgC_7h{x^s7 zjk%lz<0C8kZ>1BQqvKL@02!FMuc=kF+Z|d#lh`qt;5o+l74H|JpO>&2TBiiN`?7kj z_2bCek8Qsy*^3WdS3)k@bPl>$bBDi|(dMqdPnzT_KPtxn_DX!ryfG_mpJjb8yYqhh zz{d~b@~hqw_F7BXVKp&s10{z{|)z5 z>c@othrM@?kE*&FzmrUE5W)$UARw2hu|Hj=8}m0^?CZf zpZA}a4>@zrzOKFY+H0@9_gZV`q!!#4_81|F^9`m05OUW4WvV>wG^R>j<4fluX(H$d zN?dVgCbGT^xv6xCSu(kjKI?A11td5+B|<0H1#TKIdy7n_i5$8#&D}sFGjOe^iBoG( zH&Gz!|I9r(cwn7W9gN7dT`AKxz-@IJIr7y)%}P3L)sb2+rG`z9Gvhl#9s88oIMnPH zE$OJNG@Yx~n@)H}ajRj`*;$cu7S-8L`lIJ$J9|yzTXc`Ienxi1ZZG zKiMHh%k2f{k4-{t40i}w(6yW**=X+?*nYpK;V5on$Y4Tl;s6G7tM>P@aMa_sW`2sw zFsga&|IA{oU$N84`%u~1^2vVtQ$5cH3idx-d0Jsra!HkD$d!QJm2 z*1CbMbwwpQ0d7Wt$j(RQfh>WDzsRjw`TqE3dQ0S=e)EUWoi|dGALyzXDG5032+0Vg zBFu7YM#l2$BCD1X!jDEsYfl3j5gyqr=-=AD;#@!d7S0FUeLXB((fhOyM9#1$$S-k`JzUJPwYGtObf!BpH46&P417Vz6-<7dFdf7KHZUrwT_6;f!g4yp#y>7xX^()8{q5a%-X8m z6ba9V{K-E;?Cfl8o%cV@tv*id1dt>1ygCzZhq!$a@giy#7Tm0xaA_n_qoNsk< z!A4RjOvr>i*CGD6@BJ1)a!JUb{!k7?>Ku zP9~k%MzGbYTaNaYgyk9fd7n}a3Fjxoo^^mD1`R64n5kBdYnSQ*JC_L+2P5^n{OxbB zb-)a^?10H%?w-_+*U$xSXpNcf8_@FP@YOG&@-medRq;yLFk&DWaW@57-Ys_iut;>4 z-T|&kulM$`Ysk1*7%ggdWd~019 zx4g4ABdXc6vDdH1&&f8?jrOy3F*96ARW=ZU%>cU`l^}vR&&Z>%8Q5^qd z5Kx5iW3b@tdY|=KsJgrmCrq1Qf~CIbm6_h~LG<$A#P(`c_jgW2O$bBSZgMhH0Re<* zMAvh6IS>Aq*-e^&ase8_faBw>vQBo6VguA(+h)1!^Xy}l7^v@zKN*NW>7#uUuwTrk z?hLDC3M3W7DO}4t*Rpp_3+?B`XsE_tPs&qP)<%3STyd^Jb)3kROn$(0_!?E%s(5N%-1udNWzbM=E(c4kjvEnGNTe3{gLFW-3;VN&GPxX1C=lYL(Pl4oQn%~$k+9GOX?V-z{ER4n(`5BK;z&pS({PRtGkjz3l# zIIbYf9L;XwP1dL-sKU2=HmxkXjCy2_8t%1US^H3lK>ce;gYi|vzK7<@_if4Ct9ip* z20Qfq0xmrqFCM9{j2DX+(JNmpc61?HDW;J!tBJ*n3{*K1UYamnbe1P?=WY zmgx+}j@TLz3T}Qtmbbxr3Q4UGOj*hA4!*~+U)k$fRuh_fd_xuX8u)xVH?v_gzYLVvH=g`CklIB{tp1D>R6Ja<_3XCbt!%Ui)12*7PiGfM?qic zCIX$i&gprVIV~k=nYWtrMcAx#dq-r>RG0Yeh%k9DxkEgeV2{FaJ^VtA?k{qx0ENa5 zV9gnRq7qv(Uy5pfv)CYt!xyd;lU-|eOX!5H&h>IA=!o31iUcqyN|VDR zx4a_y4MwF%)N43epk2H8aq9mhJK<8CxC+oSuo6K?tOgMjeVb!Vlh)}`RviU%M1}{vfh>5jsnWf6>(;hJ+oFXVCzJaDH@ACw z{YNZEp~Xte*ri4*3|kZ-P`$C zFP2?+I%Tt806gPaa-HED73cQ1@Td4^ms-}iwe*Flr&)rrCvo9=@pXl(Tyh+cD0QLm z_al`m{vfM-s}_CE_Agdn{5LvFIiD$lqjI)H`XHbO8x#XLw4FjrvM0<74LpvblKn() zGKl;{uI`rKdeZ*kJ%q7T-o<~QE7>8p9VzP?tS*st>#~V)qvf)L69rGeT%%n zNZFOwgAP}Zt)s5~0~L?VeaUTss?Nrf=#5I&E#^#kFiQg061_KGT!P|^ZeqURJSTkx zM}z==EY+w28XW)kB=L6oPLuOrC`0^5bDlB|@rwZnzCgXZKQotaUePwlWomh%B(){n z2L<6Nm&uWAgVnOLwXkcVC&T)2PCGvd1iI_XXkit}taUFrXETD}BI(P^(3D~=V;pnw z=+Kl9+3`77u`_yBjng|_Jl}mh$#}lo&#!YWC8#i-evfbhD7U`wMj1Mw;Khbf&K{UjS-8iv3n}^ zi+iK%SiU*8PnY7O(gaix*}HL0Ri3FK2u=09PPGKc4cr(LF#$xrNr}$IlGKT5*wLp`j0z*GF%#&~h;ZSAZ@ z@#5EblN+&0f>Wo=_$uwMOgRB7u{n>PDuosvO=&C#oUA_>K5wdFwd=HFxE#C zsqg^R*1|&m%S6(I=VI^mS^2b8J5j zJXh@!5uPQ?gTT)@Gxr8c+4X%gIn7e`I3nMW$QgYiWyzK;C3c}Z!s)g&UY0kzVuXnt zvsy1F7W3nGkWG=xq@UIN7z<9;rSM^KW;B#OSi28_d5{}MgJd}vOd6JmEaY7$rf_}IpuwpZc#1;GF#iszH^EIyksx-sFG;){o zvGkP*F;ui)0@A4H+qA$LMn0t?F;iy>`d;fHygA)^$M9=~n06eNn6}FH+-cI&hask) zvw~yfLrk~w_OFO(&J^H@7Cu*Dy7-$8bD1D(~VzEC#EZaUx_I!Wsm5S$vIuh7GkJC=p#uB$88v zWj}kSbYjENv~Ps8Z&adv#)Iw|pbJCZ-4u-Ea*AkpAqUk2r#p+u$b9Go<(CpplX&MF z@)a#CaPhyD1)E|^OB4J@PSXN^K!HvLiN!T8^WqNU%@BZ2Baq_8Q_4Hya-p?P5zcSH zHisXx%wp?dM}Sb3UdeF9K1#i?Z-%8N!x&kbA{ft+b<9?0>5DW-0?_A_$$52Y2#93R z_dX#&aXlR0m~fZ;i|dK;hl?*mcS$Dps;C*wS5Fn7J|d{E*lk=MN6){&S;Zi5eY7=i zmdfnzI)wR!&Qdrfz6k73VGlR|RAT616gFxy#Q(!n&RpU#A#1oMUQ4FM`N*sdCA9Vs z1KIiZ{fgm$d&k)iKyP$zJOA|bLtnkxe659P%$2v_#R zk?aS$-;vONK@d&IpBrSx6>-(M`PWJL6HiF@$jX|f1pNMjmGY|cWFPtS1Ujvs{Mi+% zrdK}^R;2Q30$^AEjN4rzfodEW=`V(=ye8CGK>z~dVV9~od$IX}??*b7a_#?;?mq!jv|u;=Scp=>=T%k5g$ zKXHYd^h3)Zmb!CB%VLqfWU7eBmXy-#1M=dY*Cq*6M)8ld zC2IiABn+n#CjAo_{Tpf0LXMEzOw!<`hbb>OlLXyvf-hL>Qv%x%_L?1Tf`r+BYRN_w zIkhLh87qE7PB#%I77N#TardD(+XM_pywXZzaje(IuU>k|uk#ihQsyl`zh?WpVY2fH zlLTRdb_6{>+Svo$Id^B>~>V0}UjyLyM(=X7Dcoh}1y6H#Ze6FLE`%*~Vel9{@K zs$3P8-%1PZ+ht^cF!rU;{Tz{U6;?TBU;~rt<~rT2NsbRvw8?q~5~&=MDJgI^RQn=+ zGjP|#OkM#Zf^{IF{7aCq4;k1rv~ejTLz)b856Jx!+nk@8HZ~MQXJhrZ&1vD=>Er?8NZ^knDPD;FW#-6!-Lnxi+AvvSVI3;Zd9=Iowx6lvI~u$uwBkyf1Zv4 z{HYmAXe^_Z-_DVw+$k;O@a`l-QX`$Y5C$Z5%>i;o3qJypJ@+$CYu07P@;f1;49t`z z$4lhk@;9@I0;}G|FhF}l=4$*Kovf7G+(DpyyBu-JX5Lh46t4bzLMftim29$PI;TlV z_NrZi0g3*JcIG6j<%bedziPFPia{aL$Vmf}UpErz?qGxXy<7~B`wc)ciE%Fj7;)(~ zxnGaIPk{{9s`jAo5!RKG()r|Reqlu?!}_EJ(b=bi9LAV)R1y&v&<2|FonA%6`GSax z4}yqh4mc{Zq@2{eq^=f{!y!2%SEk9oTCtiA{QnmE%#gqz|-*HYh z#m_XwuXT&}AFg;^%7dYXn~BP`Os+?^>1EEQ=SPDYb5PaZMt#v=M>ybx92j zmpFgm4VXIiYZI$o7@qj4%nRE@`YjQOF*P?_H-Vhdu^%3h-p=Pt>$%FLy}=!bF(rG6pRYHC&1h~ev(c) zX4tPlDArpmto6Rq(>7-8!^`9`?He;f{4zYm?e7!hjcrP_T)2Z*MsJ4G#pEFvnC47j zatGn(eJmB|=us}>RUIM`V(xO2N_qE5d8cxdr0be>(Tj>`8FS7pZn}W87xYqO{39uH zAK88;O~{}L(uXp6rKU4y<5wu6>O-#C5)26HkDyTXx*?~oBVC}FW$*sL^#$U54qJzP z+#@+eFbZMkj=hya|A;70IKLtVtNbha1U8$%bDe+zaIOFtEwnh+l!nf`Qvk$um+mzP zos1ROqGN9>M%YcZc`2MtIOaK&rm9_f@%R9N$ViH^Nu!dZ9aZ6&J%Km>L^RhKkjgt3 zM{bEjT6cYtyw8OFzH$~v-24(PydR?}=TXL)$P7c2%Zz=QFnFca!qHiV^A|-!uk!zb2{PYnr0Vh!sW8yD_ZZm{gI2%8US z3A(JfUZaB7NbqH;;EPP~r4l?h6@0M?u9e{PQ^A5aI_*RW_NRiUn_!NHwmVZ&!Ic`^ zaE`F~T`)`#vt|^C846<1_AVL4MCskY1Bs(>3U2HkY2)1+^%p9HvY92?#k$aD|3Osn z%26ss-lY_OWb6;5uqTCyP{BN@!0ZMMl)}eTZtPxF3X|wlH2P+tc3rkU>s)=jigG^t zY2v-n*$bVcNuxt7b`z^8>0fjHuKLEwUD`h}=KU2<_|edjEq}UP_V{l@(r_M5RpNY& z;>BdsTJtuk;>F)30T zb1WcB^$C3n12N89N1MXVF@^oNv@lv&PI~9lAE(#sj43rKOHIlaQYzo+xnAD*%h0P> z!2Lt)x=_e4t+dy9xKB9ACti|3~tP-Zk8A3P@< z3kCz>*vUa(I5sLcH5{7~JR|&RR`679|36Iosd;70Lyq9Ma4au43hj;H@RhNZga-$$ z{PY)Di1{tkL|nFS$|o5zZ#E=+x+j7XamGWnW;mJ2{2~a&y-UP_A@8o zk`nu#H@sLs^wUo*%%tJYNL$8tL&1hjN|J3dHPHnh?_n+C9E7cCY*xS6qdtWAUrxk& z`o%sfc^}hQ3@DffvPoe1wy=k$HMlz#ENk>U*jl$zgwej6ainS4Y(IlXot`&e|Dx`N z6v1vAv7O1-{we|ezk41{CRGS}j(np}!98d9{g(5;)LG3RhV|hB?p;Fx*X_&u!GX?G zWbb)YIs_-f3+VvXb6hF&-DjkWZk7R}OX4Syp}4n1LhBt&+F4CZ;$lH=*{hVCU`j|;@N}g>A{enED@n}#It17|>|Vjhg)TEcB=S%{9f}IE9&w?F+ zQL*EKora}#4-mET3Bg0Z4ON*>`kwcFNBCX(Ow#AP&!?3|lY}CteevS2OK3gwiV(^u zKJ0z}148LOirmq{?=x`;I*wcGqC-z@g_r$vj7un2v(w=W=o9Z8KTZiHE`r{#w+RY> zDaC9a{hb84_&0=-<}TtX{C%gLbzUvZExqmUGaA^4l;%qJFOc%nyZ;0N{>R&dxO+WX0oDVVkU8w+XokUr_0lc5pm{)e8H#C--u*MAZ8#kR_TkiD~6 zDkQr5=NKUzq=h4ec;w6_UL26l>T06@!S4zn~~FkCRW1 z<2aLx7k>oskA_IavSB15gL*%ob-NIMkF+Z~>-N-kmuvB9&kAdJ*)B4DGM3)<=wZqI zSIWG1vox_TT6;SJ^mQW13|S~mn6;|beoP>H6sbGIo{@<+&J(@QyvI1L#LyaGyrF+) z29HBiq@mOs`n)!n%k!KD?)brusyGNyxn(WODq4Ju;Qh`HG9izoRl?r}Mkid~=;CN5MZjln#(+|<& zdcGI5cVjrd-CE!KD2eEyE@v?*L1W|CHA*spU&M+WC(X;lU~Twt}eIq9;m5g zK^=_lK|$+#NrUp0{iq(@r$`)=)Kh>}B9({OtPfCZ^CZCH-X9N*F*Ab9nCm!wpZxa4Z4NtI* zM=4s^#v4Ql+jtaWk^tcyC6xC&=*a0LlJ~oLm$d7pm?J61aFb?9@=KGSJ*eU!-x6bQ z?|I*o4#STGao0)aS5n~#T2>Mx_jQu!$^kBY{h5R=F%vh=VAVN|G8lp`9gmdyk0FQ@ zgLnt;(ThAT>nb2T+;)hlzaNpA;n~FiOY3=S{Q*+TV0`0pGZ=kTC~ZH+rI%>&Z^=g@ z#-sBXiTpwyPR|(9*&S=qJ&zWLlPP?5b~#OVeoR7kK_%(md*07VA0yucLK!3H>p@|n z8|G-}cIQ$uD)){SpFpXU^(d$itoQs%i_vM0I_p7&b0VpG#5HgquGZisewZL-F!2UY z!m9R-An4Qiil;Yuhj*m#^akOE#ZRL=QV*31o+h+sl2)J$h47uGvCcz8x%@3mVTQjw zmCoPRl0rt``rz{Og%;`3@!xcGdELz@Z~?k=yhJ)NAUqO?@-SBv`*mpJ~<5snfGLhgH%w9a*(5WA(?W! z86=gP$I2gt-DdczKDBPXmzM;-JS0scYGG$mL6LyY%}}o{dok9K;sjn==6p04Y2cC+ z=ME}RTb-8)H$ZK9A_dgXhr2*Ud4YHps0T@^@Wh6t3jc_5oZE>}a0B*jkYR>tvk%$UR9$e(3qoXB4je+z$( zP9A@w?#|4(lfOUkmq{4|5Y#@RoMEJ&N4j17MM$@wc>EHNOaF&gVw@5W7+5fF(717h z;|5zrLxzqUHoSP;h(xL*MvfchzK@pQBgc#zYb1P;zf<~tZL|}q`*b!}+-1`r3E980 zL@M=1?-XPrZ(A)b1RMFf#JTu(0>!{dD{`ACXaI>=zv0H>BnQk@+|*FCI0FZvNw?(ASxKovWl;V1$&P z5K78$yr|)9;;M*qZX%4Khbe6Fg;J(nAWU+x3C$P!wUK#h*ie zPNmi`%%!Ri+NHkL#xN4n8Ond5QW0t*gFLAUu&L+NSKD}@W zMbwKR^jAXaJS+ycIhzO+1k@g4)e$ZJB{5O&p@@fTx{0pyv^n=kieX$DJ57T(S?lX2 z99n>U!7M|P$S~7}3&`mNNz3x@IDdVCwSM?i9X zidQbfROdh zC$hUUl=#GY=XD9ll)CG!Y2bTO3g6ax%zum9Nr0wrB+uD>F%8-+4U*Awm<(=%){ukb z50G3f2cQ44q8B8K4w<6s)IWwDbLD-D>Zg%rnmq=vvMnxh2M+0r*`yDDsvWc)0~8zc zyKT-T!UDJ^vjL)9BpoFAv&cWgTA!`$@*)e9vesJPCgmuau~iWjK-Y6f&;E-N1{=C{ zApkKbl1NV)A>y4ZARa|HpzNWVW2nY?guJL_hLXv)!tD&#h}Cn2 zo&@wgXaXVWCXULG^~R|4le-~shgtPU1;jhp-dUbKl>IPUM}n`}LZ9=wu*v!Dg@`v5 z=xDs-wGYV+jdNAIH(Hv(*&$4x@z_c81D>b2BspGONgSvW zeseLU%aZN_%JkX$u`a^1xb*gVqnk@_E|iX(FP%S|8~<(?>$RVxL~mIq#i>T@_D3KQ zwo+gF3wVwe4|a>pk|Hz9WH&xBmEs!du>J44tCB${-QKGu>_Ugo`RmscoN>({>6`6P z+3<32v?gnT7yiZ92eo!51N~MKid%-}u>g~HACzIM3&<>8MN6+Dp)gHMj-zKCiWIN} zEkDFK5FW)6{T&_9Um?BYC1qkj50QX!0t|ynjpyy|@Z49R{HD+(L5!5K)u+szq;TH3 zAXVmHCE#TOzO2lK|Du3POaV(tB0Sb=5erkZ^GA2W4f_sL z*{1WykDdHTVzA0L^OxSIG&12I36G$9Ai=KVizt%0s&Jx}d@-n3d%4-Xi2pgOc?NIx zkL0^zbIZ=<*sO>BeE26Qom!meT`8o1Lv?zbX%^8;JHMd(n@Rt=}kCz^~Yaeh*r5EM7(zVZsFZpc(>n_+mQ@1TJx_}B9F{~-LP@C5v(@c$70R~Bv*#<)iu7m2D{@M*G6dQZXjU&m#{q%o^PF1@hIAvo7w1FNNK^&RDxguwygxA)9 zz?1XB2U*NPFvt!<+1=L@+^*?GlBJcoUu_@y`n^lk=-PMMFS_N=>0dtHUviq<@()+I zR+cEuoPSJBo=-$`t{WiJ!T|hFiEa41qE&ldc1-R!3HDX4D|G9E5>%g9vo{K9|c0}|?1T-PE<1VLJnv_f3zm9_h;b}Yd#3%M<) zPC-*tbv&%7`fQ&xFHi6^6Fxt)DD7a#FLyP1$lrk(vuC&b=9}LpBw{O2wJTuFWSZs- z<-1ZE6nX?@`6Kg+lpNEGV&+}R2A&2{8I9_1nPK`^Z(XfpO*zs?Mj{$8QN0*1-b594 zxwi5~Z6)$c;q{_ofnZcF2+yy;-Oly-u}Lnforgd*LD2H`O3O4Zr$8GlK}E3wze~h5 zt(6;)DV1o#xT_70!(NH{WcfKCN{TRs=agRL{G8QFb6fCr5sAuaMCIK6RNoJNz4*tE zBoi;ra^Yv|Mr0I!ctsHtBr8rDAaWu@zp~;TT}^o(lipMQ5HH?BD`cN%u>gUiC3_yz zj~5@8yBa5n!-a+ZvKRdxOOz&8oFzh^)w)WW!evTTTbF!q3RC`y6<3S5p6*!A#u9BM zMF_Rrq#qY@PSEKu+r${UW_DViHy^goU!l)m(LTTSL29AThq`^HqGc}_m(vVIS8!wb&#dx0QxE_I&6Uv6i%aF9#sPsAZS%J!wq)OfSj ziNvF_uG44=9$jZorwEU?wHimq@(RziJ*g7=6?QoIKVW%@TV9HGN|N9fh?_i*6!yGR zqToWn{R=-FxCTF|qu~JAu6OCBw{g0^?7%DxzC4uA>g5IJ9KR6E(sPtpwqG;EpLupZ z?m`qB3cFH|wdTJdl)e;1p)A8$A)cSkYlMcDoaVRL1IXEfvXtBB7yh^Q`P#QrtQ1}| zy{J!BNy_VLoaFb!{Z(C!1F?6}H{mx0fvR3;k2kiIKL3NEz2Rnb7vbY01vCTJ8Lp&F zud4Tx6thX^_h$-($+_bpDbmh~#rgqhxVPa>Dj!Es#z=fVwJGgg0{iO&buqq0cuUGp zB2R1ogeS{<5uBpxZL2cFy;%(-7OWMmzj7)tp&mkmZ~LRy=Zk8t(O^4XVx`noo){Zk z*V4nR=>`#cIOYoboIp*%fg45$M#NAYH<-+Z&!ShMj5uLAZkptduf+P?Tz_rsQEMU>*sjyLX~DT z`wO4vTVW2{GJKP-Dnb$7E~wZE6PEU1#hHcQBjAEIpejjTH@OVAnUk-|58?nGQiC72 zAxMdpYx%~Eq2f!fbOQI1bnEUKOF{3(0ZcRT;^7q2(k3-qKknj|-f+iAQ=*=EHNvT; zb^5--wH)SNQ@z%7Fl<9>z<2IB?c&`mnzKkI7|$!QD zq_SUePW-N12EGkAL?Hw+{O%0XEsOmU^rzAg?G#?Ol%A+bEQ{xL#E*R&wirKlhCX-c zbBjLzqR&6*^B#TPqR(c1HtKVsKEI*QI(?q0&vJbp{G*gST;Fr`*{dOY^?9E@7wB`L zKEI>SMf$v2pNsXmM4x}tXQMus>hn5%F4O07ecsP-k01MA`g}m2kLj~bpF4jqvG?iw zZTeiS&u{8;jy`ATvr?bO>vN1g2kSFKpC2$@ghKx<233=U@#t>4)ljvpz@YbAmpP z*QY7}M13#Ur>VDE-)HD^heG&>fm5G1-7hsR)#rEgxlEtS^||4<5_^_D@6+dP`fSzb zb^2VS&$;@Xth(dS5g?$k1$(B~`q+@a4+`n*q{x9PK0pV#Sg5zizuBRTJw?r+j|Bj zzx|mSkedp~l7uI>`aNtx;H6n%!Th-D)g?c`v0oNm!piVB*_IvPQtTmO_O#9U$(`_C zct;!;Q62tvXJ~lORQp-V$u1WU@?KL%s?z*gZt261=-ynw)9PYb4^H78@Xng7DU|J@ z1|xcW$#zUSYV}?4i^Q}jafp-f72vP`00eu`cf&uxPTip4qUcBC`LHO=8E}&U`WAk5S(n9OY*$!@E zM>*T%XSDOQ{0wsjqX`fj!AaSumqaio}lozet{cA%^9|-5s2vrrqCE z(|>ni9Mv7m-$ec@_&b9?FMsLnNW6y1QL=zeG6Ej?_1kBawb? zqM4KH*l(wqwX}22W0@JVJX^e|w}pF)Vq+LX@;8jXQT&bP?^ym4ZAkx>wv;9J5NOj%3V%chLwfwoZ@WEy!F{|S zQTJai!Y}9G3ISb6>Dk$}71$f?t&5x?d*7MJuq-y|5aheRFfIdlMDu^L>&UiGcE!6X zZ8ieLWtgteYseR`3Rm!p98}}AKdGraJ$RbvKLEvqQB;oKb9<}(oMVsFQj6F=^8DRq zC#kAoH+sJV)iZuiJ3CJHyW(}EQdgpE0*WywRQ}UnN>hy4&}vfo?0?91`)_#-*sQj; zJNF(TDYi$lA9mJJiL5E4k^_ONkCwgai&X!vE_%YxNba@YnAAjAtNroE3brvu`{DLolkDJ zs43@>p=m-|A+@Sq`G>S};>8)JjE4Nk=^`O^W#eF2oeSeXoqj+{tE>NbMx^>-alx@g z1Yi4E_1@+@KMB|ne`UvcArU0F`31lL6L$5({^$vRCXj83rCjY3FT%*gK;mxi6@N>? zs4HDcTgJqTmkM!ER7*CwqO0VFYsow1<fNv!z70NR#N~$q;>A^o%(Bt| z;eo3C*6Jpz4cJ`3lVN8+iio^4XBw8RQ_egf1}|v^Qk0w#Xi>m2I$r#?bhE%hu@u)8 zs5-RlQLmj{8n8bD-N(r0IY;;f!P4xNsb>EvdXr#{0kza%ZlR00=#=LrRkV2gKyXJ_m82o?cc!FZRkTHO zLq+}YuIY>4kj+NvLWB2U0)Vx8M8hO;^gV8aNAa=&nuy0>VMGkzdsfSvV!;bKK1Fjy znWp&5K}S;#(IH*G%qMUKIpIli3SXo$P~XK+3~NDcl2r>%&2K(C(^r*sO|BN%QPJkB znwD+do?O0)e8IB3kU&me zxR?XE?AI8xOQ;+nc{d2dGMnf`vGt}=lQl|eGlw@s-Qz}$Bg!iBmHHoL{PBjbQENz^ zHRRkPU)3Ad>JJHoSeyBgI-dj{sq>pIBzp+;ZYbfIEcghw;3xY;O^{p@-6+{nk?x=A zkIo$LuR74g{qCYoQ`NrYB$=g1+*McB^@x)`{m}Ye27iN)PHT#+3%ftGR`~a6&VNXgC&W9Xy_MDwnr{uE<=(27t(!+c zZ368$phfU2l=q>$D^-Z|Vd)p~^R!Tur$%1KNBD`wx}G&2?UGaEVdR$*ISi@)KnZ}& zFK2Rvl%?|1OtC_}lW%0n3Q_-+?%nE~eu{=1<)T^ezt#Ds3BbK)-jxK<&liZ>io8{&=vH zC*q_;YHrfl>YQN$Ir`k{Y~wv4_@%b*B<4@VD8Mf0huMl$m|c7x4&KYvVEZueZXlu$ zyj>{qNTuI14e1N-4@{uKJMK&2&HgvxP4Ek2?6LCg`;~BVo_yJ58s>t4I=iQ~r7a+H zG`_>Q%S0Tsmw5k@fglA*)LQ56;cD4hbg_|Ou0?#6!G08@Rf)*?mfDpY*`$Eb)Nq_F z1hs)^$>1mpaQp0G_M8Lajp- zS^C9-nh+Nx>as6J-Q`Bf{3vydIXTg&TRu#XpVfR?pN!h5H;9%pQH-O#Zlm5sVMa>1 z&2901u$@B2Vu|{l8?{?IVyja{Bjx(y4>9)MSVADy!(tC^-uF4XdB?CgI(v-gdCznH z`YrL|wX(F)i#yDLQ?303li`h8ceit$4Cne?Vgc=W)eG+ymoHB{Z(yGa5uPUs%wm?~ zA;mUjZ=D`a!np&b!+G4KInkt9Od2-RG)*1XoppN7aDHY|4D#R6=^H6+?ZN<2$v=|Z_KfyAaP{B{kK+t`|zTZN}Szp z#~%aOf6R<=C;e9E2;OB!Tkr(b8-h~VrDoGG-S`cT@Fo1!1@r^w_m30vu-hp&@_sT`EMca& z>NY0jbpYjd&=J>Ab7Dic?*u6O#qCaZot^X03t1VmQKX=e0tKNbLBe~&E3`B?6l~7`A$U-;4>#JdZ2u#q6_%UO^Y5R z->K+AKJ(I|2g`RV+Tt@mExJg)Q_(~C9FP`0RK8Qu!}uJS7Cl_PQ_;nI7NkXwkndD9 zihkZfY0)F)I~6^O&%(6m(ej;&K9Wy%?UFbjBj2g$v3znPTQYi_e5azvcTOuwnmpFH zYE!c-(Di>m5Sfg4;SDd%Mj30SjC@_Y8wr^$MfLAiQ(2wG`DM6w(GqO&k>Vf!^my2E zm&);CWAC+!isZ(W5LD{@3#F(lI>rKW_fobTP-Hd+42Wz-Cma?eGGGLVT`VMt3AF-eTbE=*2M<>UqrlR+Z1 zXW!+0_ohXF5-ptb-2IxD!Ur;OWhUwaNqL!V2|q3kIB7457vFu0RK)CZo4nxi?6t(f zzq&Bk;vA|cywA2ye}3%l&(_q{oBOBO`j$nKG=|f^S@lMT<7Pe=a7<^l$SQ;VgFBy4 zRXVO9!vEt58-xIQP_NXrP_%F+Y8=YdwmD$@@g$IR4PRQfAmOa|)gEgTofepbT&p{xJP-te?gH7(v>SJl?&IT_WpvNn`f z>dLxxKfqd71mhf(U-nEx9(mbOcn6)uTayb~^c^E>)5rw+WY2B*#FFZ{jh@cTsSNE* z4hNytxBCJn!11rn-t4Lg8~RSd#|{X3ai^XY9X=p^{e~v*1x@l z4TYVV8S(Bw8P_szUa>o^CIe65QsJ#GARmGw+G*++dP8-cZ8Fi6S&Yc?ooABs?R`mMNKH4g+g=xieHx>Tt0v&01m0=a7a6(@KUU^*8SNmifLPl?VIKuu8gjQvPjHZG$ zEWc$=k}zU~I}-d6EG_|K`mYq*7oJTR@CZEItO*&R!Pik;vSdK@3N5rDM{%42v(DZr zMT`V8FD}2Y>Xs(0k|N+3@zPAql}etbAA{dvTqj88qsVMO>*hUQZHurT7L6c)pC_dt zfy!CacIQ_&z{$GHwlgVOzO9;wMXMxp>ktg#_go4Ay>@nfTHVs_@PQSLi(mqqxdbcp z+SGQ3@xM8=@<1Hhy{5sX<9)4XWe#fNEX>~2Q99K}s&;44AW6WMZ_^0GMQ>=2+x~H1? zUARm5_3`bmBi>CdFcJHz_cVy)Lj=;zRN@L4m?C`YyGhhry|3XolL%QeAd#G~O4?2B zdvXifIltxZWj@4G^@PF)vx7OI15;xoLkFzbuu%Kr(1DX;1;oT)PV++t#y1V6 zfc&U8RPAld3my1K262*&CP@bde z{d|2(p_CV$wxW7alUqh~+JfrL#?jGfi>n7T4%;XLCA8^^GoH~+OKT=5@(`3lk(}q+ zJLFb2W|Q%HU(tYCELev7A_G;odQ-MHzJ>dXT6V5@!xtHy%4wR^pZ>LdI;wOag$|Z1 zDF_{0p@3MmUu-~6)yO^rm;9lFH-iG%D(wgzT$8{?MO*Vu>yEZ~k~5n6nP;jcxiqw+ zdQC99x$Rmv^Z#{hO9?%Xa;jvC(&zuG{$T$9qGnSm_(%4rwVwt5*3BVWp)+T239TC9 z<&v-^rwjELX29QK!>ZTd(?bG}Hi7U$w5_t*_vCvc+!pAtm>W{CBX$f(7)`pYCBx~% zWGpK`iOuoGyXo@C5HCmH=r)jq%2%wajg0a#l<8#oad84P?M_|_>k8ff0K?Idk>%J!NXScszv~mkEHv^uGOj_pw{(?=k&p>~6UmQrI3p4uQ;eU?< zYt1}1rVopU1c^|%p-&l+|1N$0XY|4NRN}ag8rRyH(1~6Ug%sHJPL$K1;`AY@jMp z=wPE~gfsZqLqp(QBlc*WSscN2bog2!pbnRSlKA?cjOYIhUrgCZ&5E+OKp9*ak=v*b zT9JndLBLRONUR$lH^~B-fp~j(&-lc2vJo+g8-o)$_Jt1YQF`@QH%1dV zSe7S}GnN>Mxzsm+pn~>|dh|6*YwHai*w=7|()tA?2(ST@$M4s&OlGor3fj@(k!fs` zTY^q$8`0T~$MQGwj9cs4ypb%Qr#(Qwq6P!B(#kcXiSu>|f))P>Qq|v@^9_ebL|2Tw zNg`Qj6?voAXUqAmN9d`Y&~WdH#_u3Gblcr3IrOOHFhvCiEA*O54x!C$*1GoCbR-Ky zDT5F$rl{ypEOG6UnGP-(9wuHI+)w);G&q(3A3zws?fey4&0Svwa&d63~HE)k~hyc)F7z)Yxn zX)Z2Y+G0xtN|jJ#X9^CqXMAjqhRHlEn>rFE(utSe@DeW}blZYp-B z(o^;MV#h2IM=$8agpJ{zaPQp4q26dn^%CZBoNTRno1Q?yioguW$GcHTbIM7dBAZRE zi;f*PJTqf@G<)EkWt*Pq73nvc{bLfa@3+2gWR|b0y)oApJufphn1Jk&zN)rse(Yl{ zSX;H_hHmf5-i#qYdt;ake9YscF-S$BXE?e)w^77D3_8Ml-kma#?VI2L(ulL-hS>tl z9Mb%fy@1AP@|DL|oTfLP!q<+>cs$%YwQ+*P==;3JF}#;#NO*2zk#}WVMg})Gt?X4w zai?c9W%m=epK|95nG6LLYvCWv`_0esZseS!bY44>NegAFJw@>UEanEfb%?KEN6)RA z4iTtH(s`E1P8(h5zzSt>7NwHL7O9NXRHo^U#bS+ACWTB!n*R0t0+}aG;X7kzM5kRr z$tUPA{;FGYb~2Bdtor3aU9H<^qcGPl1J=y8zDSXd+Y%kOpwWz5op=*`GckyDKz}AwuxYkML0o&}h9uNg@CWzebr2`u5V+)~udpDK}b!AlNi2#qx!jn>3!* ztXMq><|78@bY}e|R=`I|wbeADGwY`!;rC5iNo-Mdwj{kvlNM0$*v_nNAnwg%DUv_Z4#$A8GN;JNpPGoCw)pSiDjV@cc*e+yB@3Lz6R> zC09#`#x_!T-Zz?zYiR1HoQ|9w#OuU7X@J=MSebbnP&=SuwbFL8>bD|2V? z)y$eO?n1N6Xcq3e;aFZK`{v2z`BO5#Fy3pKL|678vu6a)^|B2dEMwBScAV-@_^Ng; zJKq~>o5#-FWlaGYI@$B8FN>X_wm*p8;-Md>I6Ie}kcewKhPNzDH9T1c=O2O0Q2V^l zfis&tWb4mL6(JmJ*V)g&F>YQ#p$iN@T{<8b)XHM>efE|Fpi>plk;-2$2yL1dI(S(V z(u)h-Ny;auB)*#}5)d^Vr|`y#HKQ)*0rbqKp$e$I$%o~ar&~r&*jtAC+{DTvy}vjd z6!FDdwPRV4w6aO3V|i;FWSZsGj$(f5n;lnIv`84={8W#E~*t)!BY?<^c91z(*07Z;KdyCtjUy<%SpK)01_QaNDwFm??rV~$1cA`+I z56g4RM@(dH(^y{pS=wcnH5JJRdk6I2WnbQZG*0_(d826`nP4z9aDfq>=7=1&(osr7 z>lrJaS!g#e@srMN>=YwWm9c}dWKtqHx9KbLswCBPq`Z0*M@72RV7He&Q|IYs$-lO? zY)c;&&278Lx1j?!H()^{eHI%PI}8?ujkig69@o72+N1DO9;b^& zA#c)VQ57=?2n8oeN?841#1ywjXWE?(tZ}%6?6Fq`V9#>BKZa*qXQ7Fs`5;ZJihQj}t zfq$|KVS8^Lo-M+AGI7`fds=c76(qYnnAYW6>O4TWdBtCA%kbuqfbjo^??1<%u0PE{ zfhjLLQCRiFa-?be^|q}*D!8F(nlk4V*uGQ>Z`Rlom78?H-j^MdOo*mIAk$D-J_Hsz zuspF7{AK(!NgvkDY?}!~En-Ky&}v@Emzh)+A_-(K!SN##msVXC+O#5c@P?+T5|ouK zaGfHr2C(CF(qLH}K9I$5FiB4%o}r+$Kg>YZSfJY&RhxsOuoRccgVPLO*=9p%)|&6L zGU!8WkTvu+z>GIbBt^TcT~`>Yxg9plK@$`=OrW(0+j68JCNyE_70x$RW0sztKHG(ga0@+gr<5vXdonjF*2NlLxE8Z=!bubE!^8TTmV zXgNw5B}XZPCx)tC2xeDLjSa1~VuQ06SDzHipBRc|WzVl3-&6vxl;e|;(ss^M?6z8b zV|&>CWZiglVvEOD_ADFJ?$%D<{pHny1Q8H|%aI92sqlBPF6ZOz^idXj%ScMG|9AJ0 zuNN{t++MnH>4g58(N_&)d+j}h{}$#i4h!w98tb+vKWUeZLqwP^Oq{*;$1v!Ur2JB2 zt$PmLv)Y`D49~u#O+-&!{afcmPx+M)f!@0{Yq8KpbLl+-kRN|6smOU(lR%=l+A`|ZwtDJu_c*Oz>C6cOtST{So zc}#Bu z0LC7khn8QSoqb0Hv>N~;!|w=G{e3ykRAOx8yqAxbftu`~uD<$o`Xhl}eCg7Dnyz^M z2Ma^@N=|gC43hABLnv2JZzffuc<HINh+8ckPv2_mVV>Q!RR^r-(^L=*XQ12~ z?j726e00^_@5<}&CX`!E^;dNid%CXLHD+b(t{D?DrbWh_+_OtE*|PJu@_=mpHBH%Y zY~YsCPhMkru<04cgDqqBRc&Lc(5r~9x>yT5vI)ggQ{c)D3G%$EMagzKQX41N-^4;R zU0;R4$-efc((&k|jo!cMo`zy;Jpy|1tvfO^s>a;dkXyCv#_V7tD|i3 z2kM{nc4glr`BPn({axvjPEquA2{`eHAJD3EZEd zejmBS=6%#tebI;@)mpdLe$i`CYpp`%8QYJMwQ%ndrKXoka?AKK9+CK^!Tu0Z12hTu57=Y#4{sx zVGN)~;C&~OtDA{0Q@J<#gWnM8jnw@pJDw|=2Mdw#%e`}PPYb0Dhk9kAxhO%A5S^h& z8aSH{3uE#t%B{2G#rcrGavZeUV8=^yYW8=HH}_BC0IwmJ&yt2~t@ZxgI!c_+XH9T; zr1085WWkQ6EaB&I=sF`dg2iU|pK<}rP1{gNi&n1`-LDB1yVLj!HeYvh#~b=!!oeKr zPZ_!R2>wT%@hd1!5&O2LesI9fjf`oH=f?JMzXwaK%8LEI=t{R&ATlNQ32ry+VIJz! z4OMM5){i@*GvE_==((%|TLLhU^FC}_F`y$dfu~DBnLBce=b>Z4eGrRW^xUZExhQ9U z$N1p2f*IaQ8op-`gPqm>4#msmzZblm`VD?`(P!}ThT!Gurv)#kfS29)92I2x?L(mC zF-3;#FEdHRyZlw3F6)uwk@;%BC3Y`>vlkJ_tDZTOw}h!Wo*HI*I%D0=Eqk; zW8ceF^W%(zkeZqw&%P8gIm$U#envaz$j>lm&0}hQJVU;6oLYX=Hm?FRgD!QOF=&)C zkI)vn@$N3UmOTZEzN$zDG5~b#&kkf}+{fSV_p6zxiNg5R{uHC(BD1L~m&v?evD?}I z4LNbl3=VQW;4R(}{xpBtUZaHn90A%7DimR;#Ac4^4Jj}D_C?~L1$&42`0`V_t>ZQg zzg4@b4qN9E8G+~p&ncb2b@zcdYMsvpJey=lmP3O4RPtBT>MQj*Z3t1^iRq&@@}MCZ z9OUX+Qr$%zetb~Z_{+pr4ku+2lGd)oYn}b_tjP3{vm$4gxS-97p4~mm-jRT8^Q`Ff z5`m5+JNVlbh@QP85Z@f&P>7S<$n-s8Y&zWmDnC%wImZK)AN}VEx>)MW$N++J53zt+ zmw^sVA5gSXF=oOufEYDR(Dq}6M<%QvYhW>QtEex-*@B>*%HE3e;j^^7H|Vm#t14iqZS!VV^Pq2%}c74Pe^uVFrRq1#S&4O zvm(h2yQ_4u6bJsnom(~^<)W54pP0T_T#aBXci<(^KQAaIv&LAg(}3k z7KY*r$&6J$vhDNn;!@xwuEvAcv@WX_4`(JpjEP%(8JoJAvHvjeXlw90g!W%rlLn_X z$snnpKR970V%}NfbjVEjMU~HV{)#E$OB)41?31q$ITogj8BBMIANJfpDQUeS#>pbsc#0T&2aSql@YY83&&=TU;;it%9_w&&B=M4a5Cj=;n(_+lwR_IRh08fKL468sn+G( z&HD#p`Z}MHy)bq)r$T%p5K0$a1S}UFd*bomdZdQbzSb*BFBP(!@BCIw-}P3#qT1Fg z@gUVEO9#D_FZ_A#vI(JO6EC^aZ$H;Cj@I z=lMsV{)s@@lbyN5;C|h7gphh04fZFke9fv!RH{!plkk;K2pw=~?PcCezu^9mYkqQG z`yB_c38Jhqq-H+4@`E22;O!u;Z5FxWLB(y((cH+f*E{B?S`s~+R=akO2#kJSs z$`Mv`Wv+BquAfWz94P_{x`*FD^t*^utgE!x&+8b`Yqh*js*eq_vYNp%Wv*;BU={c| zK^QY7bkpCppT&;53_HDT&XLeUXexJiJ}9$IRfg4kzcTm_D|TXJUuXH=0@LCUV`=Ej zYZ|5_nIhMnHjFl~LGfYtIfitRa$ zNA1aPGCr@UIXTYH9R4olkc^*&KKlcEFE5MOB<5$n{SwcM(4xoQ?FFjyMyJ0V?)|#8 z>SH*U*hm&0`s{PoDb1Oy^Ru|^Yh?{Tbbv!BM|$zspkT3x&xk$B+ZFouAXY3xVQH7P zytAR4D9hIk$G9{)=BLq19B*{YC9ySJJro=Qbh>{~(Pr=Jxt7-93c&u*-lc&(3khIm zn4J+U^8P8aqK*Be&q((*g1vT@prz%VAUoH%T;pHO`b_Ml9G?|vqZGPzA!&~#Eq0~2 z9w|tG>HXxDiZ&7xivo+O0H3%(yHvJ5LKFpAJKqMYqA>Oz>;doHg15TTMNFczIca$_ zSjUY!_Ub1jH9(Xo1TC96hO>78LAwAVAkYgv_rmw^U)Qp^4-CX;tHZ=rw6T1;2!I;- z2*Z=4#mY*3plwmlJc0p#zTmd!JU&2P!yxL-!K*%F%>K}zX`Bcv7m3OO>evRj*jRtP z`!-B4CXu-T``ljq)zqKcOT#V&t|dZYYJN z-%#2xQ5=~p748nx7d0vw>@COQi6zG6mVaUSV&qA0XKg9FgNX^iObQ~N$s|#S_$IS~ z2xlSrW%m01>HK2+&8Ij{V)nw`a={{{>lkoquh z15*J7g9Z#3kTq!N(89q(2Ux z(zXIA2*@_t6KPaKL*Rctb%$PY6(980d?`19zgvXA33;PGfb+SXOS~5m0d-Cep^((* z5zrpVtBLlUzJ1_6i7^@QcNzh2$Yj6) znFf*cSRGA|zEk1quS$i+t4^E>#80IH+dX5c@S#_wLUH0@l@Ou$gix2ZsJn5Zm$qmY zj`4Ga90Du*`B%OFpo&iNfFII|%8@@>^va;JsC`jdZltK)ZwoukAfE@KROWiPv}Num zUqm{p*hF=Vr6QuABaeJ}l*?nDJeu9EVFerIu}M02X=+3c4dceX{Gx=-nRp$xiGtiL zCDSF>VS*LbxrcK9mHQ$~ay{eUQ1fd~$|`ZD=QXSJ2&TMu(@m{T8a`Ckzpq=pKeeC5 z-6fH?JBHucF$<<=czO2@&+0c^YuYgk=lDkMi`|d1*rM&oS*}}ysG%7+o8?FouUT!o zZmmHj?^wIMm%WOwp<|f8l}S)YE4|8q(7z7^;a@`C2O1$tf;$d7!l&z1ID>LK=@Gui z8p)!X7emE&*_8Hy96Gy(eY&u{ciG)OW$P$$E^@qmpAYf0yGZH%Rp~t&DqLq%@&+M- zbFJBl+IAGEh*tLqW$Y1UY|G)o)i%ebaHr(Yl$q5wEF|l>jxjEK)g3yfqJNtxsp&b_ zn$_?!+!|Ayw{=A!=OP?&*5}Yk-D8Wq?>tG$29i`IWoQ}`Gh5i@lJsUbTf+5M5nl*< zIVb+69dgw3!y}L2gA6RfipB;Oa-JGZvlK6Lh|tyS&FX%xZv9m$w83Op8q^Ecfyv-> z)b4}s1M9&j;4bhw>Q+KZzm$~3ekuKuQj(*;l-RF-O8?l0ej5-|7&xGR|Ni|@7?hAQ zU~o#x;1u2mqzqXvZr^Hf7t}#~i{b2-d`-lCQgykMjK(gaS_P zoW@LS(6U}l!z!=sL(G@+67^D=QzSbyO|zqy2zC5= z?(SHccz~V7jLaFx=m3MoJkRI@ zdf>j!a@FVL@JCdO?hzPQM{VURqi9datSfTe^jhKChLMxP z&tpanN(OD4F*4!6T4LDtW⁡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

    -x*Sbo>nsqK=Oy{3rkS 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 z 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´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

    GKdY0Or4)nZX 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

    xvj|XVKmBdq5 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 + + + +## v2.12.5 (2025-11-26) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.12.5) + +This is the fifth 2.12 patch release, addressing an issue with the `MISSING` sentinel and providing several documentation improvements. + +The next 2.13 minor release will be published in a couple weeks, and will include a new *polymorphic serialization* feature addressing +the remaining unexpected changes to the *serialize as any* behavior. + +* Fix pickle error when using `model_construct()` on a model with `MISSING` as a default value by [@ornariece](https://github.com/ornariece) in [#12522](https://github.com/pydantic/pydantic/pull/12522). +* Several updates to the documentation by [@Viicos](https://github.com/Viicos). + +## v2.12.4 (2025-11-05) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.12.4) + +This is the fourth 2.12 patch release, fixing more regressions, and reverting a change in the `build()` method +of the [`AnyUrl` and Dsn types](https://docs.pydantic.dev/latest/api/networks/). + +This patch release also fixes an issue with the serialization of IP address types, when `serialize_as_any` is used. The next patch release +will try to address the remaining issues with *serialize as any* behavior by introducing a new *polymorphic serialization* feature, that +should be used in most cases in place of *serialize as any*. + +* Fix issue with forward references in parent `TypedDict` classes by [@Viicos](https://github.com/Viicos) in [#12427](https://github.com/pydantic/pydantic/pull/12427). + + This issue is only relevant on Python 3.14 and greater. +* Exclude fields with `exclude_if` from JSON Schema required fields by [@Viicos](https://github.com/Viicos) in [#12430](https://github.com/pydantic/pydantic/pull/12430) +* Revert URL percent-encoding of credentials in the `build()` method + of the [`AnyUrl` and Dsn types](https://docs.pydantic.dev/latest/api/networks/) by [@davidhewitt](https://github.com/davidhewitt) in + [pydantic-core#1833](https://github.com/pydantic/pydantic-core/pull/1833). + + This was initially considered as a bugfix, but caused regressions and as such was fully reverted. The next release will include + an opt-in option to percent-encode components of the URL. +* Add type inference for IP address types by [@davidhewitt](https://github.com/davidhewitt) in [pydantic-core#1868](https://github.com/pydantic/pydantic-core/pull/1868). + + The 2.12 changes to the `serialize_as_any` behavior made it so that IP address types could not properly serialize to JSON. +* Avoid getting default values from defaultdict by [@davidhewitt](https://github.com/davidhewitt) in [pydantic-core#1853](https://github.com/pydantic/pydantic-core/pull/1853). + + This fixes a subtle regression in the validation behavior of the [`collections.defaultdict`](https://docs.python.org/3/library/collections.html#collections.defaultdict) + type. +* Fix issue with field serializers on nested typed dictionaries by [@davidhewitt](https://github.com/davidhewitt) in [pydantic-core#1879](https://github.com/pydantic/pydantic-core/pull/1879). +* Add more `pydantic-core` builds for the three-threaded version of Python 3.14 by [@davidhewitt](https://github.com/davidhewitt) in [pydantic-core#1864](https://github.com/pydantic/pydantic-core/pull/1864). + +## v2.12.3 (2025-10-17) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.12.3) + +### What's Changed + +This is the third 2.12 patch release, fixing issues related to the `FieldInfo` class, and reverting a change to the supported +[*after* model validator](https://docs.pydantic.dev/latest/concepts/validators/#model-validators) function signatures. + +* Raise a warning when an invalid after model validator function signature is raised by [@Viicos](https://github.com/Viicos) in [#12414](https://github.com/pydantic/pydantic/pull/12414). + Starting in 2.12.0, using class methods for *after* model validators raised an error, but the error wasn't raised concistently. We decided + to emit a deprecation warning instead. +* Add [`FieldInfo.asdict()`](https://docs.pydantic.dev/latest/api/fields/#pydantic.fields.FieldInfo.asdict) method, improve documentation around `FieldInfo` by [@Viicos](https://github.com/Viicos) in [#12411](https://github.com/pydantic/pydantic/pull/12411). + This also add back support for mutations on `FieldInfo` classes, that are reused as `Annotated` metadata. **However**, note that this is still + *not* a supported pattern. Instead, please refer to the [added example](https://docs.pydantic.dev/latest/examples/dynamic_models/) in the documentation. + +The [blog post](https://pydantic.dev/articles/pydantic-v2-12-release#changes) section on changes was also updated to document the changes related to `serialize_as_any`. + +## v2.12.2 (2025-10-14) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.12.2) + +### What's Changed + +#### Fixes + +* Release a new `pydantic-core` version, as a corrupted CPython 3.10 `manylinux2014_aarch64` wheel got uploaded ([pydantic-core#1843](https://github.com/pydantic/pydantic-core/pull/1843)). +* Fix issue with recursive generic models with a parent model class by [@Viicos](https://github.com/Viicos) in [#12398](https://github.com/pydantic/pydantic/pull/12398) + +## v2.12.1 (2025-10-13) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.12.1) + +### What's Changed + +This is the first 2.12 patch release, addressing most (but not all yet) regressions from the initial 2.12.0 release. + +#### Fixes + +* Do not evaluate annotations when inspecting validators and serializers by [@Viicos](https://github.com/Viicos) in [#12355](https://github.com/pydantic/pydantic/pull/12355) +* Make sure `None` is converted as `NoneType` in Python 3.14 by [@Viicos](https://github.com/Viicos) in [#12370](https://github.com/pydantic/pydantic/pull/12370) +* Backport V1 runtime warning when using Python 3.14 by [@Viicos](https://github.com/Viicos) in [#12367](https://github.com/pydantic/pydantic/pull/12367) +* Fix error message for invalid validator signatures by [@Viicos](https://github.com/Viicos) in [#12366](https://github.com/pydantic/pydantic/pull/12366) +* Populate field name in `ValidationInfo` for validation of default value by [@Viicos](https://github.com/Viicos) in [pydantic-core#1826](https://github.com/pydantic/pydantic-core/pull/1826) +* Encode credentials in `MultiHostUrl` builder by [@willswire](https://github.com/willswire) in [pydantic-core#1829](https://github.com/pydantic/pydantic-core/pull/1829) +* Respect field serializers when using `serialize_as_any` serialization flag by [@davidhewitt](https://github.com/davidhewitt) in [pydantic-core#1829](https://github.com/pydantic/pydantic-core/pull/1829) +* Fix various `RootModel` serialization issues by [@davidhewitt](https://github.com/davidhewitt) in [pydantic-core#1836](https://github.com/pydantic/pydantic-core/pull/1836) + +### New Contributors + +* [@willswire](https://github.com/willswire) made their first contribution in [pydantic-core#1829](https://github.com/pydantic/pydantic-core/pull/1829) + +## v2.12.0 (2025-10-07) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.12.0) + +### What's Changed + +This is the final 2.12 release. It features the work of 20 external contributors and provides useful new features, along with initial Python 3.14 support. +Several minor changes (considered non-breaking changes according to our [versioning policy](https://docs.pydantic.dev/2.12/version-policy/#pydantic-v2)) +are also included in this release. Make sure to look into them before upgrading. + +**Note that Pydantic V1 is not compatible with Python 3.14 and greater**. + +Changes (see the alpha and beta releases for additional changes since 2.11): + +#### Packaging + +* Update V1 copy to v1.10.24 by [@Viicos](https://github.com/Viicos) in [#12338](https://github.com/pydantic/pydantic/pull/12338) + +#### New Features + +* Add `extra` parameter to the validate functions by [@anvilpete](https://github.com/anvilpete) in [#12233](https://github.com/pydantic/pydantic/pull/12233) +* Add `exclude_computed_fields` serialization option by [@Viicos](https://github.com/Viicos) in [#12334](https://github.com/pydantic/pydantic/pull/12334) +* Add `preverse_empty_path` URL options by [@Viicos](https://github.com/Viicos) in [#12336](https://github.com/pydantic/pydantic/pull/12336) +* Add `union_format` parameter to JSON Schema generation by [@Viicos](https://github.com/Viicos) in [#12147](https://github.com/pydantic/pydantic/pull/12147) +* Add `__qualname__` parameter for `create_model` by [@Atry](https://github.com/Atry) in [#12001](https://github.com/pydantic/pydantic/pull/12001) + +#### Fixes + +* Do not try to infer name from lambda definitions in pipelines API by [@Viicos](https://github.com/Viicos) in [#12289](https://github.com/pydantic/pydantic/pull/12289) +* Use proper namespace for functions in `TypeAdapter` by [@Viicos](https://github.com/Viicos) in [#12324](https://github.com/pydantic/pydantic/pull/12324) +* Use `Any` for context type annotation in `TypeAdapter` by [@inducer](https://github.com/inducer) in [#12279](https://github.com/pydantic/pydantic/pull/12279) +* Expose `FieldInfo` in `pydantic.fields.__all__` by [@Viicos](https://github.com/Viicos) in [#12339](https://github.com/pydantic/pydantic/pull/12339) +* Respect `validation_alias` in `@validate_call` by [@Viicos](https://github.com/Viicos) in [#12340](https://github.com/pydantic/pydantic/pull/12340) +* Use `Any` as context annotation in plugin API by [@Viicos](https://github.com/Viicos) in [#12341](https://github.com/pydantic/pydantic/pull/12341) +* Use proper `stacklevel` in warnings when possible by [@Viicos](https://github.com/Viicos) in [#12342](https://github.com/pydantic/pydantic/pull/12342) + +### New Contributors + +* [@anvilpete](https://github.com/anvilpete) made their first contribution in [#12233](https://github.com/pydantic/pydantic/pull/12233) +* [@JonathanWindell](https://github.com/JonathanWindell) made their first contribution in [#12327](https://github.com/pydantic/pydantic/pull/12327) +* [@inducer](https://github.com/inducer) made their first contribution in [#12279](https://github.com/pydantic/pydantic/pull/12279) +* [@Atry](https://github.com/Atry) made their first contribution in [#12001](https://github.com/pydantic/pydantic/pull/12001) + +## v2.12.0b1 (2025-10-03) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.12.0b1) + +This is the first beta release of the upcoming 2.12 release. + +### What's Changed + +#### Packaging + +* Bump `pydantic-core` to v2.40.1 by [@Viicos](https://github.com/Viicos) in [#12314](https://github.com/pydantic/pydantic/pull/12314) + +#### New Features + +* Add support for `exclude_if` at the field level by [@andresliszt](https://github.com/andresliszt) in [#12141](https://github.com/pydantic/pydantic/pull/12141) +* Add `ValidateAs` annotation helper by [@Viicos](https://github.com/Viicos) in [#11942](https://github.com/pydantic/pydantic/pull/11942) +* Add configuration options for validation and JSON serialization of temporal types by [@ollz272](https://github.com/ollz272) in [#12068](https://github.com/pydantic/pydantic/pull/12068) +* Add support for PEP 728 by [@Viicos](https://github.com/Viicos) in [#12179](https://github.com/pydantic/pydantic/pull/12179) +* Add field name in serialization error by [@NicolasPllr1](https://github.com/NicolasPllr1) in [pydantic-core#1799](https://github.com/pydantic/pydantic-core/pull/1799) +* Add option to preserve empty URL paths by [@davidhewitt](https://github.com/davidhewitt) in [pydantic-core#1789](https://github.com/pydantic/pydantic-core/pull/1789) + +#### Changes + +* Raise error if an incompatible `pydantic-core` version is installed by [@Viicos](https://github.com/Viicos) in [#12196](https://github.com/pydantic/pydantic/pull/12196) +* Remove runtime warning for experimental features by [@Viicos](https://github.com/Viicos) in [#12265](https://github.com/pydantic/pydantic/pull/12265) +* Warn if registering virtual subclasses on Pydantic models by [@Viicos](https://github.com/Viicos) in [#11669](https://github.com/pydantic/pydantic/pull/11669) + +#### Fixes + +* Fix `__getattr__()` behavior on Pydantic models when a property raised an `AttributeError` and extra values are present by [@raspuchin](https://github.com/raspuchin) in [#12106](https://github.com/pydantic/pydantic/pull/12106) +* Add test to prevent regression with Pydantic models used as annotated metadata by [@Viicos](https://github.com/Viicos) in [#12133](https://github.com/pydantic/pydantic/pull/12133) +* Allow to use property setters on Pydantic dataclasses with `validate_assignment` set by [@Viicos](https://github.com/Viicos) in [#12173](https://github.com/pydantic/pydantic/pull/12173) +* Fix mypy v2 plugin for upcoming mypy release by [@cdce8p](https://github.com/cdce8p) in [#12209](https://github.com/pydantic/pydantic/pull/12209) +* Respect custom title in functions JSON Schema by [@Viicos](https://github.com/Viicos) in [#11892](https://github.com/pydantic/pydantic/pull/11892) +* Fix `ImportString` JSON serialization for objects with a `name` attribute by [@chr1sj0nes](https://github.com/chr1sj0nes) in [#12219](https://github.com/pydantic/pydantic/pull/12219) +* Do not error on fields overridden by methods in the mypy plugin by [@Viicos](https://github.com/Viicos) in [#12290](https://github.com/pydantic/pydantic/pull/12290) + +### New Contributors + +* [@raspuchin](https://github.com/raspuchin) made their first contribution in [#12106](https://github.com/pydantic/pydantic/pull/12106) +* [@chr1sj0nes](https://github.com/chr1sj0nes) made their first contribution in [#12219](https://github.com/pydantic/pydantic/pull/12219) + +## v2.12.0a1 (2025-07-26) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.12.0a1) + +This is the first alpha release of the upcoming 2.12 release, which adds initial support for Python 3.14. + +### What's Changed + +#### New Features + +* Add `__pydantic_on_complete__()` hook that is called once model is fully ready to be used by [@DouweM](https://github.com/DouweM) in [#11762](https://github.com/pydantic/pydantic/pull/11762) +* Add initial support for Python 3.14 by [@Viicos](https://github.com/Viicos) in [#11991](https://github.com/pydantic/pydantic/pull/11991) +* Add regex patterns to JSON schema for `Decimal` type by [@Dima-Bulavenko](https://github.com/Dima-Bulavenko) in [#11987](https://github.com/pydantic/pydantic/pull/11987) +* Add support for `doc` attribute on dataclass fields by [@Viicos](https://github.com/Viicos) in [#12077](https://github.com/pydantic/pydantic/pull/12077) +* Add experimental `MISSING` sentinel by [@Viicos](https://github.com/Viicos) in [#11883](https://github.com/pydantic/pydantic/pull/11883) + +#### Changes + +* Allow config and bases to be specified together in `create_model()` by [@Viicos](https://github.com/Viicos) in [#11714](https://github.com/pydantic/pydantic/pull/11714) +* Move some field logic out of the `GenerateSchema` class by [@Viicos](https://github.com/Viicos) in [#11733](https://github.com/pydantic/pydantic/pull/11733) +* Always make use of `inspect.getsourcelines()` for docstring extraction on Python 3.13 and greater by [@Viicos](https://github.com/Viicos) in [#11829](https://github.com/pydantic/pydantic/pull/11829) +* Only support the latest Mypy version by [@Viicos](https://github.com/Viicos) in [#11832](https://github.com/pydantic/pydantic/pull/11832) +* Do not implicitly convert after model validators to class methods by [@Viicos](https://github.com/Viicos) in [#11957](https://github.com/pydantic/pydantic/pull/11957) +* Refactor `FieldInfo` creation implementation by [@Viicos](https://github.com/Viicos) in [#11898](https://github.com/pydantic/pydantic/pull/11898) +* Make `Secret` covariant by [@bluenote10](https://github.com/bluenote10) in [#12008](https://github.com/pydantic/pydantic/pull/12008) +* Emit warning when field-specific metadata is used in invalid contexts by [@Viicos](https://github.com/Viicos) in [#12028](https://github.com/pydantic/pydantic/pull/12028) + +#### Fixes + +* Properly fetch plain serializer function when serializing default value in JSON Schema by [@Viicos](https://github.com/Viicos) in [#11721](https://github.com/pydantic/pydantic/pull/11721) +* Remove generics cache workaround by [@Viicos](https://github.com/Viicos) in [#11755](https://github.com/pydantic/pydantic/pull/11755) +* Remove coercion of decimal constraints by [@Viicos](https://github.com/Viicos) in [#11772](https://github.com/pydantic/pydantic/pull/11772) +* Fix crash when expanding root type in the mypy plugin by [@Viicos](https://github.com/Viicos) in [#11735](https://github.com/pydantic/pydantic/pull/11735) +* Only mark model as complete once all fields are complete by [@DouweM](https://github.com/DouweM) in [#11759](https://github.com/pydantic/pydantic/pull/11759) +* Do not provide `field_name` in validator core schemas by [@DouweM](https://github.com/DouweM) in [#11761](https://github.com/pydantic/pydantic/pull/11761) +* Fix issue with recursive generic models by [@Viicos](https://github.com/Viicos) in [#11775](https://github.com/pydantic/pydantic/pull/11775) +* Fix qualified name comparison of private attributes during namespace inspection by [@karta9821](https://github.com/karta9821) in [#11803](https://github.com/pydantic/pydantic/pull/11803) +* Make sure Pydantic dataclasses with slots and `validate_assignment` can be unpickled by [@Viicos](https://github.com/Viicos) in [#11769](https://github.com/pydantic/pydantic/pull/11769) +* Traverse `function-before` schemas during schema gathering by [@Viicos](https://github.com/Viicos) in [#11801](https://github.com/pydantic/pydantic/pull/11801) +* Fix check for stdlib dataclasses by [@Viicos](https://github.com/Viicos) in [#11822](https://github.com/pydantic/pydantic/pull/11822) +* Check if `FieldInfo` is complete after applying type variable map by [@Viicos](https://github.com/Viicos) in [#11855](https://github.com/pydantic/pydantic/pull/11855) +* Do not delete mock validator/serializer in `model_rebuild()` by [@Viicos](https://github.com/Viicos) in [#11890](https://github.com/pydantic/pydantic/pull/11890) +* Rebuild dataclass fields before schema generation by [@Viicos](https://github.com/Viicos) in [#11949](https://github.com/pydantic/pydantic/pull/11949) +* Always store the original field assignment on `FieldInfo` by [@Viicos](https://github.com/Viicos) in [#11946](https://github.com/pydantic/pydantic/pull/11946) +* Do not use deprecated methods as default field values by [@Viicos](https://github.com/Viicos) in [#11914](https://github.com/pydantic/pydantic/pull/11914) +* Allow callable discriminator to be applied on PEP 695 type aliases by [@Viicos](https://github.com/Viicos) in [#11941](https://github.com/pydantic/pydantic/pull/11941) +* Suppress core schema generation warning when using `SkipValidation` by [@ygsh0816](https://github.com/ygsh0816) in [#12002](https://github.com/pydantic/pydantic/pull/12002) +* Do not emit typechecking error for invalid `Field()` default with `validate_default` set to `True` by [@Viicos](https://github.com/Viicos) in [#11988](https://github.com/pydantic/pydantic/pull/11988) +* Refactor logic to support Pydantic's `Field()` function in dataclasses by [@Viicos](https://github.com/Viicos) in [#12051](https://github.com/pydantic/pydantic/pull/12051) + +#### Packaging + +* Update project metadata to use PEP 639 by [@Viicos](https://github.com/Viicos) in [#11694](https://github.com/pydantic/pydantic/pull/11694) +* Bump `mkdocs-llmstxt` to v0.2.0 by [@Viicos](https://github.com/Viicos) in [#11725](https://github.com/pydantic/pydantic/pull/11725) +* Bump `pydantic-core` to v2.35.1 by [@Viicos](https://github.com/Viicos) in [#11963](https://github.com/pydantic/pydantic/pull/11963) +* Bump dawidd6/action-download-artifact from 10 to 11 by [@dependabot](https://github.com/dependabot)[bot] in [#12033](https://github.com/pydantic/pydantic/pull/12033) +* Bump astral-sh/setup-uv from 5 to 6 by [@dependabot](https://github.com/dependabot)[bot] in [#11826](https://github.com/pydantic/pydantic/pull/11826) +* Update mypy to 1.17.0 by [@Viicos](https://github.com/Viicos) in [#12076](https://github.com/pydantic/pydantic/pull/12076) + +### New Contributors + +* [@parth-paradkar](https://github.com/parth-paradkar) made their first contribution in [#11695](https://github.com/pydantic/pydantic/pull/11695) +* [@dqkqd](https://github.com/dqkqd) made their first contribution in [#11739](https://github.com/pydantic/pydantic/pull/11739) +* [@fhightower](https://github.com/fhightower) made their first contribution in [#11722](https://github.com/pydantic/pydantic/pull/11722) +* [@gbaian10](https://github.com/gbaian10) made their first contribution in [#11766](https://github.com/pydantic/pydantic/pull/11766) +* [@DouweM](https://github.com/DouweM) made their first contribution in [#11759](https://github.com/pydantic/pydantic/pull/11759) +* [@bowenliang123](https://github.com/bowenliang123) made their first contribution in [#11719](https://github.com/pydantic/pydantic/pull/11719) +* [@rawwar](https://github.com/rawwar) made their first contribution in [#11799](https://github.com/pydantic/pydantic/pull/11799) +* [@karta9821](https://github.com/karta9821) made their first contribution in [#11803](https://github.com/pydantic/pydantic/pull/11803) +* [@jinnovation](https://github.com/jinnovation) made their first contribution in [#11834](https://github.com/pydantic/pydantic/pull/11834) +* [@zmievsa](https://github.com/zmievsa) made their first contribution in [#11861](https://github.com/pydantic/pydantic/pull/11861) +* [@Otto-AA](https://github.com/Otto-AA) made their first contribution in [#11860](https://github.com/pydantic/pydantic/pull/11860) +* [@ygsh0816](https://github.com/ygsh0816) made their first contribution in [#12002](https://github.com/pydantic/pydantic/pull/12002) +* [@lukland](https://github.com/lukland) made their first contribution in [#12015](https://github.com/pydantic/pydantic/pull/12015) +* [@Dima-Bulavenko](https://github.com/Dima-Bulavenko) made their first contribution in [#11987](https://github.com/pydantic/pydantic/pull/11987) +* [@GSemikozov](https://github.com/GSemikozov) made their first contribution in [#12050](https://github.com/pydantic/pydantic/pull/12050) +* [@hannah-heywa](https://github.com/hannah-heywa) made their first contribution in [#12082](https://github.com/pydantic/pydantic/pull/12082) + +## v2.11.7 (2025-06-14) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.7) + +### What's Changed + +#### Fixes + +* Copy `FieldInfo` instance if necessary during `FieldInfo` build by [@Viicos](https://github.com/Viicos) in [#11898](https://github.com/pydantic/pydantic/pull/11898) + +## v2.11.6 (2025-06-13) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.6) + +### What's Changed + +#### Fixes + +* Rebuild dataclass fields before schema generation by [@Viicos](https://github.com/Viicos) in [#11949](https://github.com/pydantic/pydantic/pull/11949) +* Always store the original field assignment on `FieldInfo` by [@Viicos](https://github.com/Viicos) in [#11946](https://github.com/pydantic/pydantic/pull/11946) + +## v2.11.5 (2025-05-22) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.5) + +### What's Changed + +#### Fixes + +* Check if `FieldInfo` is complete after applying type variable map by [@Viicos](https://github.com/Viicos) in [#11855](https://github.com/pydantic/pydantic/pull/11855) +* Do not delete mock validator/serializer in `model_rebuild()` by [@Viicos](https://github.com/Viicos) in [#11890](https://github.com/pydantic/pydantic/pull/11890) +* Do not duplicate metadata on model rebuild by [@Viicos](https://github.com/Viicos) in [#11902](https://github.com/pydantic/pydantic/pull/11902) + +## v2.11.4 (2025-04-29) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.4) + +### What's Changed + +#### Packaging + +* Bump `mkdocs-llmstxt` to v0.2.0 by [@Viicos](https://github.com/Viicos) in [#11725](https://github.com/pydantic/pydantic/pull/11725) + +#### Changes + +* Allow config and bases to be specified together in `create_model()` by [@Viicos](https://github.com/Viicos) in [#11714](https://github.com/pydantic/pydantic/pull/11714). + This change was backported as it was previously possible (although not meant to be supported) + to provide `model_config` as a field, which would make it possible to provide both configuration + and bases. + +#### Fixes + +* Remove generics cache workaround by [@Viicos](https://github.com/Viicos) in [#11755](https://github.com/pydantic/pydantic/pull/11755) +* Remove coercion of decimal constraints by [@Viicos](https://github.com/Viicos) in [#11772](https://github.com/pydantic/pydantic/pull/11772) +* Fix crash when expanding root type in the mypy plugin by [@Viicos](https://github.com/Viicos) in [#11735](https://github.com/pydantic/pydantic/pull/11735) +* Fix issue with recursive generic models by [@Viicos](https://github.com/Viicos) in [#11775](https://github.com/pydantic/pydantic/pull/11775) +* Traverse `function-before` schemas during schema gathering by [@Viicos](https://github.com/Viicos) in [#11801](https://github.com/pydantic/pydantic/pull/11801) + +## v2.11.3 (2025-04-08) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.3) + +### What's Changed + +#### Packaging + +* Update V1 copy to v1.10.21 by [@Viicos](https://github.com/Viicos) in [#11706](https://github.com/pydantic/pydantic/pull/11706) + +#### Fixes + +* Preserve field description when rebuilding model fields by [@Viicos](https://github.com/Viicos) in [#11698](https://github.com/pydantic/pydantic/pull/11698) + +## v2.11.2 (2025-04-03) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.2) + +### What's Changed + +#### Fixes + +* Bump `pydantic-core` to v2.33.1 by [@Viicos](https://github.com/Viicos) in [#11678](https://github.com/pydantic/pydantic/pull/11678) +* Make sure `__pydantic_private__` exists before setting private attributes by [@Viicos](https://github.com/Viicos) in [#11666](https://github.com/pydantic/pydantic/pull/11666) +* Do not override `FieldInfo._complete` when using field from parent class by [@Viicos](https://github.com/Viicos) in [#11668](https://github.com/pydantic/pydantic/pull/11668) +* Provide the available definitions when applying discriminated unions by [@Viicos](https://github.com/Viicos) in [#11670](https://github.com/pydantic/pydantic/pull/11670) +* Do not expand root type in the mypy plugin for variables by [@Viicos](https://github.com/Viicos) in [#11676](https://github.com/pydantic/pydantic/pull/11676) +* Mention the attribute name in model fields deprecation message by [@Viicos](https://github.com/Viicos) in [#11674](https://github.com/pydantic/pydantic/pull/11674) +* Properly validate parameterized mappings by [@Viicos](https://github.com/Viicos) in [#11658](https://github.com/pydantic/pydantic/pull/11658) + +## v2.11.1 (2025-03-28) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.1) + +### What's Changed + +#### Fixes + +* Do not override `'definitions-ref'` schemas containing serialization schemas or metadata by [@Viicos](https://github.com/Viicos) in [#11644](https://github.com/pydantic/pydantic/pull/11644) + +## v2.11.0 (2025-03-27) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.0) + +### What's Changed + +Pydantic v2.11 is a version strongly focused on build time performance of Pydantic models (and core schema generation in general). +See the [blog post](https://pydantic.dev/articles/pydantic-v2-11-release) for more details. + +#### Packaging + +* Bump `pydantic-core` to v2.33.0 by [@Viicos](https://github.com/Viicos) in [#11631](https://github.com/pydantic/pydantic/pull/11631) + +#### New Features + +* Add `encoded_string()` method to the URL types by [@YassinNouh21](https://github.com/YassinNouh21) in [#11580](https://github.com/pydantic/pydantic/pull/11580) +* Add support for `defer_build` with `@validate_call` decorator by [@Viicos](https://github.com/Viicos) in [#11584](https://github.com/pydantic/pydantic/pull/11584) +* Allow `@with_config` decorator to be used with keyword arguments by [@Viicos](https://github.com/Viicos) in [#11608](https://github.com/pydantic/pydantic/pull/11608) +* Simplify customization of default value inclusion in JSON Schema generation by [@Viicos](https://github.com/Viicos) in [#11634](https://github.com/pydantic/pydantic/pull/11634) +* Add `generate_arguments_schema()` function by [@Viicos](https://github.com/Viicos) in [#11572](https://github.com/pydantic/pydantic/pull/11572) + +#### Fixes + +* Allow generic typed dictionaries to be used for unpacked variadic keyword parameters by [@Viicos](https://github.com/Viicos) in [#11571](https://github.com/pydantic/pydantic/pull/11571) +* Fix runtime error when computing model string representation involving cached properties and self-referenced models by [@Viicos](https://github.com/Viicos) in [#11579](https://github.com/pydantic/pydantic/pull/11579) +* Preserve other steps when using the ellipsis in the pipeline API by [@Viicos](https://github.com/Viicos) in [#11626](https://github.com/pydantic/pydantic/pull/11626) +* Fix deferred discriminator application logic by [@Viicos](https://github.com/Viicos) in [#11591](https://github.com/pydantic/pydantic/pull/11591) + +### New Contributors + +* [@cmenon12](https://github.com/cmenon12) made their first contribution in [#11562](https://github.com/pydantic/pydantic/pull/11562) +* [@Jeukoh](https://github.com/Jeukoh) made their first contribution in [#11611](https://github.com/pydantic/pydantic/pull/11611) + +## v2.11.0b2 (2025-03-17) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.0b2) + +### What's Changed + +#### Packaging + +* Bump `pydantic-core` to v2.32.0 by [@Viicos](https://github.com/Viicos) in [#11567](https://github.com/pydantic/pydantic/pull/11567) + +#### New Features + +* Add experimental support for free threading by [@Viicos](https://github.com/Viicos) in [#11516](https://github.com/pydantic/pydantic/pull/11516) + +#### Fixes + +* Fix `NotRequired` qualifier not taken into account in stringified annotation by [@Viicos](https://github.com/Viicos) in [#11559](https://github.com/pydantic/pydantic/pull/11559) + +### New Contributors + +* [@joren485](https://github.com/joren485) made their first contribution in [#11547](https://github.com/pydantic/pydantic/pull/11547) + +## v2.11.0b1 (2025-03-06) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.0b1) + +### What's Changed + +#### Packaging + +* Add a `check_pydantic_core_version()` function by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11324 +* Remove `greenlet` development dependency by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11351 +* Use the `typing-inspection` library by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11479 +* Bump `pydantic-core` to `v2.31.1` by [@sydney-runkle](https://github.com/sydney-runkle) in https://github.com/pydantic/pydantic/pull/11526 + +#### New Features + +* Support unsubstituted type variables with both a default and a bound or constraints by [@FyZzyss](https://github.com/FyZzyss) in https://github.com/pydantic/pydantic/pull/10789 +* Add a `default_factory_takes_validated_data` property to `FieldInfo` by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11034 +* Raise a better error when a generic alias is used inside `type[]` by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11088 +* Properly support PEP 695 generics syntax by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11189 +* Properly support type variable defaults by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11332 +* Add support for validating v6, v7, v8 UUIDs by [@astei](https://github.com/astei) in https://github.com/pydantic/pydantic/pull/11436 +* Improve alias configuration APIs by [@sydney-runkle](https://github.com/sydney-runkle) in https://github.com/pydantic/pydantic/pull/11468 + +#### Changes + +* Rework `create_model` field definitions format by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11032 +* Raise a deprecation warning when a field is annotated as final with a default value by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11168 +* Deprecate accessing `model_fields` and `model_computed_fields` on instances by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11169 +* **Breaking Change:** Move core schema generation logic for path types inside the `GenerateSchema` class by [@sydney-runkle](https://github.com/sydney-runkle) in https://github.com/pydantic/pydantic/pull/10846 +* Remove Python 3.8 Support by [@sydney-runkle](https://github.com/sydney-runkle) in https://github.com/pydantic/pydantic/pull/11258 +* Optimize calls to `get_type_ref` by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/10863 +* Disable `pydantic-core` core schema validation by [@sydney-runkle](https://github.com/sydney-runkle) in https://github.com/pydantic/pydantic/pull/11271 + +#### Performance + +* Only evaluate `FieldInfo` annotations if required during schema building by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/10769 +* Improve `__setattr__` performance of Pydantic models by caching setter functions by [@MarkusSintonen](https://github.com/MarkusSintonen) in https://github.com/pydantic/pydantic/pull/10868 +* Improve annotation application performance by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11186 +* Improve performance of `_typing_extra` module by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11255 +* Refactor and optimize schema cleaning logic by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11244 +* Create a single dictionary when creating a `CoreConfig` instance by [@sydney-runkle](https://github.com/sydney-runkle) in https://github.com/pydantic/pydantic/pull/11384 +* Bump `pydantic-core` and thus use `SchemaValidator` and `SchemaSerializer` caching by [@sydney-runkle](https://github.com/sydney-runkle) in https://github.com/pydantic/pydantic/pull/11402 +* Reuse cached core schemas for parametrized generic Pydantic models by [@MarkusSintonen](https://github.com/MarkusSintonen) in https://github.com/pydantic/pydantic/pull/11434 + +#### Fixes + +* Improve `TypeAdapter` instance repr by [@sydney-runkle](https://github.com/sydney-runkle) in https://github.com/pydantic/pydantic/pull/10872 +* Use the correct frame when instantiating a parametrized `TypeAdapter` by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/10893 +* Infer final fields with a default value as class variables in the mypy plugin by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11121 +* Recursively unpack `Literal` values if using PEP 695 type aliases by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11114 +* Override `__subclasscheck__` on `ModelMetaclass` to avoid memory leak and performance issues by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11116 +* Remove unused `_extract_get_pydantic_json_schema()` parameter by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11155 +* Improve discriminated union error message for invalid union variants by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11161 +* Unpack PEP 695 type aliases if using the `Annotated` form by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11109 +* Add missing stacklevel in `deprecated_instance_property` warning by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11200 +* Copy `WithJsonSchema` schema to avoid sharing mutated data by [@thejcannon](https://github.com/thejcannon) in https://github.com/pydantic/pydantic/pull/11014 +* Do not cache parametrized models when in the process of parametrizing another model by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/10704 +* Add discriminated union related metadata entries to the `CoreMetadata` definition by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11216 +* Consolidate schema definitions logic in the `_Definitions` class by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11208 +* Support initializing root model fields with values of the `root` type in the mypy plugin by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11212 +* Fix various issues with dataclasses and `use_attribute_docstrings` by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11246 +* Only compute normalized decimal places if necessary in `decimal_places_validator` by [@misrasaurabh1](https://github.com/misrasaurabh1) in https://github.com/pydantic/pydantic/pull/11281 +* Add support for `validation_alias` in the mypy plugin by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11295 +* Fix JSON Schema reference collection with `"examples"` keys by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11305 +* Do not transform model serializer functions as class methods in the mypy plugin by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11298 +* Simplify `GenerateJsonSchema.literal_schema()` implementation by [@misrasaurabh1](https://github.com/misrasaurabh1) in https://github.com/pydantic/pydantic/pull/11321 +* Add additional allowed schemes for `ClickHouseDsn` by [@Maze21127](https://github.com/Maze21127) in https://github.com/pydantic/pydantic/pull/11319 +* Coerce decimal constraints to `Decimal` instances by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11350 +* Use the correct JSON Schema mode when handling function schemas by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11367 +* Improve exception message when encountering recursion errors during type evaluation by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11356 +* Always include `additionalProperties: True` for arbitrary dictionary schemas by [@austinyu](https://github.com/austinyu) in https://github.com/pydantic/pydantic/pull/11392 +* Expose `fallback` parameter in serialization methods by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11398 +* Fix path serialization behavior by [@sydney-runkle](https://github.com/sydney-runkle) in https://github.com/pydantic/pydantic/pull/11416 +* Do not reuse validators and serializers during model rebuild by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11429 +* Collect model fields when rebuilding a model by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11388 +* Allow cached properties to be altered on frozen models by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11432 +* Fix tuple serialization for `Sequence` types by [@sydney-runkle](https://github.com/sydney-runkle) in https://github.com/pydantic/pydantic/pull/11435 +* Fix: do not check for `__get_validators__` on classes where `__get_pydantic_core_schema__` is also defined by [@tlambert03](https://github.com/tlambert03) in https://github.com/pydantic/pydantic/pull/11444 +* Allow callable instances to be used as serializers by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11451 +* Improve error thrown when overriding field with a property by [@sydney-runkle](https://github.com/sydney-runkle) in https://github.com/pydantic/pydantic/pull/11459 +* Fix JSON Schema generation with referenceable core schemas holding JSON metadata by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11475 +* Support strict specification on union member types by [@sydney-runkle](https://github.com/sydney-runkle) in https://github.com/pydantic/pydantic/pull/11481 +* Implicitly set `validate_by_name` to `True` when `validate_by_alias` is `False` by [@sydney-runkle](https://github.com/sydney-runkle) in https://github.com/pydantic/pydantic/pull/11503 +* Change type of `Any` when synthesizing `BaseSettings.__init__` signature in the mypy plugin by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11497 +* Support type variable defaults referencing other type variables by [@Viicos](https://github.com/Viicos) in https://github.com/pydantic/pydantic/pull/11520 +* Fix `ValueError` on year zero by [@davidhewitt](https://github.com/davidhewitt) in https://github.com/pydantic/pydantic-core/pull/1583 +* `dataclass` `InitVar` shouldn't be required on serialization by [@sydney-runkle](https://github.com/sydney-runkle) in https://github.com/pydantic/pydantic-core/pull/1602 + +## New Contributors + +* [@FyZzyss](https://github.com/FyZzyss) made their first contribution in https://github.com/pydantic/pydantic/pull/10789 +* [@tamird](https://github.com/tamird) made their first contribution in https://github.com/pydantic/pydantic/pull/10948 +* [@felixxm](https://github.com/felixxm) made their first contribution in https://github.com/pydantic/pydantic/pull/11077 +* [@alexprabhat99](https://github.com/alexprabhat99) made their first contribution in https://github.com/pydantic/pydantic/pull/11082 +* [@Kharianne](https://github.com/Kharianne) made their first contribution in https://github.com/pydantic/pydantic/pull/11111 +* [@mdaffad](https://github.com/mdaffad) made their first contribution in https://github.com/pydantic/pydantic/pull/11177 +* [@thejcannon](https://github.com/thejcannon) made their first contribution in https://github.com/pydantic/pydantic/pull/11014 +* [@thomasfrimannkoren](https://github.com/thomasfrimannkoren) made their first contribution in https://github.com/pydantic/pydantic/pull/11251 +* [@usernameMAI](https://github.com/usernameMAI) made their first contribution in https://github.com/pydantic/pydantic/pull/11275 +* [@ananiavito](https://github.com/ananiavito) made their first contribution in https://github.com/pydantic/pydantic/pull/11302 +* [@pawamoy](https://github.com/pawamoy) made their first contribution in https://github.com/pydantic/pydantic/pull/11311 +* [@Maze21127](https://github.com/Maze21127) made their first contribution in https://github.com/pydantic/pydantic/pull/11319 +* [@kauabh](https://github.com/kauabh) made their first contribution in https://github.com/pydantic/pydantic/pull/11369 +* [@jaceklaskowski](https://github.com/jaceklaskowski) made their first contribution in https://github.com/pydantic/pydantic/pull/11353 +* [@tmpbeing](https://github.com/tmpbeing) made their first contribution in https://github.com/pydantic/pydantic/pull/11375 +* [@petyosi](https://github.com/petyosi) made their first contribution in https://github.com/pydantic/pydantic/pull/11405 +* [@austinyu](https://github.com/austinyu) made their first contribution in https://github.com/pydantic/pydantic/pull/11392 +* [@mikeedjones](https://github.com/mikeedjones) made their first contribution in https://github.com/pydantic/pydantic/pull/11402 +* [@astei](https://github.com/astei) made their first contribution in https://github.com/pydantic/pydantic/pull/11436 +* [@dsayling](https://github.com/dsayling) made their first contribution in https://github.com/pydantic/pydantic/pull/11522 +* [@sobolevn](https://github.com/sobolevn) made their first contribution in https://github.com/pydantic/pydantic-core/pull/1645 + +## v2.11.0a2 (2025-02-10) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.0a2) + +### What's Changed + +Pydantic v2.11 is a version strongly focused on build time performance of Pydantic models (and core schema generation in general). +This is another early alpha release, meant to collect early feedback from users having issues with core schema builds. + +#### Packaging + +* Bump `ruff` from 0.9.2 to 0.9.5 by [@Viicos](https://github.com/Viicos) in [#11407](https://github.com/pydantic/pydantic/pull/11407) +* Bump `pydantic-core` to v2.29.0 by [@mikeedjones](https://github.com/mikeedjones) in [#11402](https://github.com/pydantic/pydantic/pull/11402) +* Use locally-built rust with symbols & pgo by [@davidhewitt](https://github.com/davidhewitt) in [#11403](https://github.com/pydantic/pydantic/pull/11403) + +#### Performance + +* Create a single dictionary when creating a `CoreConfig` instance by [@sydney-runkle](https://github.com/sydney-runkle) in [#11384](https://github.com/pydantic/pydantic/pull/11384) + +#### Fixes + +* Use the correct JSON Schema mode when handling function schemas by [@Viicos](https://github.com/Viicos) in [#11367](https://github.com/pydantic/pydantic/pull/11367) +* Fix JSON Schema reference logic with `examples` keys by [@Viicos](https://github.com/Viicos) in [#11366](https://github.com/pydantic/pydantic/pull/11366) +* Improve exception message when encountering recursion errors during type evaluation by [@Viicos](https://github.com/Viicos) in [#11356](https://github.com/pydantic/pydantic/pull/11356) +* Always include `additionalProperties: True` for arbitrary dictionary schemas by [@austinyu](https://github.com/austinyu) in [#11392](https://github.com/pydantic/pydantic/pull/11392) +* Expose `fallback` parameter in serialization methods by [@Viicos](https://github.com/Viicos) in [#11398](https://github.com/pydantic/pydantic/pull/11398) +* Fix path serialization behavior by [@sydney-runkle](https://github.com/sydney-runkle) in [#11416](https://github.com/pydantic/pydantic/pull/11416) + +### New Contributors + +* [@kauabh](https://github.com/kauabh) made their first contribution in [#11369](https://github.com/pydantic/pydantic/pull/11369) +* [@jaceklaskowski](https://github.com/jaceklaskowski) made their first contribution in [#11353](https://github.com/pydantic/pydantic/pull/11353) +* [@tmpbeing](https://github.com/tmpbeing) made their first contribution in [#11375](https://github.com/pydantic/pydantic/pull/11375) +* [@petyosi](https://github.com/petyosi) made their first contribution in [#11405](https://github.com/pydantic/pydantic/pull/11405) +* [@austinyu](https://github.com/austinyu) made their first contribution in [#11392](https://github.com/pydantic/pydantic/pull/11392) +* [@mikeedjones](https://github.com/mikeedjones) made their first contribution in [#11402](https://github.com/pydantic/pydantic/pull/11402) + +## v2.11.0a1 (2025-01-30) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.0a1) + +### What's Changed + +Pydantic v2.11 is a version strongly focused on build time performance of Pydantic models (and core schema generation in general). +This is an early alpha release, meant to collect early feedback from users having issues with core schema builds. + +#### Packaging + +* Bump dawidd6/action-download-artifact from 6 to 7 by [@dependabot](https://github.com/dependabot) in [#11018](https://github.com/pydantic/pydantic/pull/11018) +* Re-enable memray related tests on Python 3.12+ by [@Viicos](https://github.com/Viicos) in [#11191](https://github.com/pydantic/pydantic/pull/11191) +* Bump astral-sh/setup-uv to 5 by [@dependabot](https://github.com/dependabot) in [#11205](https://github.com/pydantic/pydantic/pull/11205) +* Bump `ruff` to v0.9.0 by [@sydney-runkle](https://github.com/sydney-runkle) in [#11254](https://github.com/pydantic/pydantic/pull/11254) +* Regular `uv.lock` deps update by [@sydney-runkle](https://github.com/sydney-runkle) in [#11333](https://github.com/pydantic/pydantic/pull/11333) +* Add a `check_pydantic_core_version()` function by [@Viicos](https://github.com/Viicos) in [#11324](https://github.com/pydantic/pydantic/pull/11324) +* Remove `greenlet` development dependency by [@Viicos](https://github.com/Viicos) in [#11351](https://github.com/pydantic/pydantic/pull/11351) +* Bump `pydantic-core` to v2.28.0 by [@Viicos](https://github.com/Viicos) in [#11364](https://github.com/pydantic/pydantic/pull/11364) + +#### New Features + +* Support unsubstituted type variables with both a default and a bound or constraints by [@FyZzyss](https://github.com/FyZzyss) in [#10789](https://github.com/pydantic/pydantic/pull/10789) +* Add a `default_factory_takes_validated_data` property to `FieldInfo` by [@Viicos](https://github.com/Viicos) in [#11034](https://github.com/pydantic/pydantic/pull/11034) +* Raise a better error when a generic alias is used inside `type[]` by [@Viicos](https://github.com/Viicos) in [#11088](https://github.com/pydantic/pydantic/pull/11088) +* Properly support PEP 695 generics syntax by [@Viicos](https://github.com/Viicos) in [#11189](https://github.com/pydantic/pydantic/pull/11189) +* Properly support type variable defaults by [@Viicos](https://github.com/Viicos) in [#11332](https://github.com/pydantic/pydantic/pull/11332) + +#### Changes + +* Rework `create_model` field definitions format by [@Viicos](https://github.com/Viicos) in [#11032](https://github.com/pydantic/pydantic/pull/11032) +* Raise a deprecation warning when a field is annotated as final with a default value by [@Viicos](https://github.com/Viicos) in [#11168](https://github.com/pydantic/pydantic/pull/11168) +* Deprecate accessing `model_fields` and `model_computed_fields` on instances by [@Viicos](https://github.com/Viicos) in [#11169](https://github.com/pydantic/pydantic/pull/11169) +* Move core schema generation logic for path types inside the `GenerateSchema` class by [@sydney-runkle](https://github.com/sydney-runkle) in [#10846](https://github.com/pydantic/pydantic/pull/10846) +* Move `deque` schema gen to `GenerateSchema` class by [@sydney-runkle](https://github.com/sydney-runkle) in [#11239](https://github.com/pydantic/pydantic/pull/11239) +* Move `Mapping` schema gen to `GenerateSchema` to complete removal of `prepare_annotations_for_known_type` workaround by [@sydney-runkle](https://github.com/sydney-runkle) in [#11247](https://github.com/pydantic/pydantic/pull/11247) +* Remove Python 3.8 Support by [@sydney-runkle](https://github.com/sydney-runkle) in [#11258](https://github.com/pydantic/pydantic/pull/11258) +* Disable `pydantic-core` core schema validation by [@sydney-runkle](https://github.com/sydney-runkle) in [#11271](https://github.com/pydantic/pydantic/pull/11271) + +#### Performance + +* Only evaluate `FieldInfo` annotations if required during schema building by [@Viicos](https://github.com/Viicos) in [#10769](https://github.com/pydantic/pydantic/pull/10769) +* Optimize calls to `get_type_ref` by [@Viicos](https://github.com/Viicos) in [#10863](https://github.com/pydantic/pydantic/pull/10863) +* Improve `__setattr__` performance of Pydantic models by caching setter functions by [@MarkusSintonen](https://github.com/MarkusSintonen) in [#10868](https://github.com/pydantic/pydantic/pull/10868) +* Improve annotation application performance by [@Viicos](https://github.com/Viicos) in [#11186](https://github.com/pydantic/pydantic/pull/11186) +* Improve performance of `_typing_extra` module by [@Viicos](https://github.com/Viicos) in [#11255](https://github.com/pydantic/pydantic/pull/11255) +* Refactor and optimize schema cleaning logic by [@Viicos](https://github.com/Viicos) and [@MarkusSintonen](https://github.com/MarkusSintonen) in [#11244](https://github.com/pydantic/pydantic/pull/11244) + +#### Fixes + +* Add validation tests for `_internal/_validators.py` by [@tkasuz](https://github.com/tkasuz) in [#10763](https://github.com/pydantic/pydantic/pull/10763) +* Improve `TypeAdapter` instance repr by [@sydney-runkle](https://github.com/sydney-runkle) in [#10872](https://github.com/pydantic/pydantic/pull/10872) +* Revert "ci: use locally built pydantic-core with debug symbols by [@sydney-runkle](https://github.com/sydney-runkle) in [#10942](https://github.com/pydantic/pydantic/pull/10942) +* Re-enable all FastAPI tests by [@tamird](https://github.com/tamird) in [#10948](https://github.com/pydantic/pydantic/pull/10948) +* Fix typo in HISTORY.md. by [@felixxm](https://github.com/felixxm) in [#11077](https://github.com/pydantic/pydantic/pull/11077) +* Infer final fields with a default value as class variables in the mypy plugin by [@Viicos](https://github.com/Viicos) in [#11121](https://github.com/pydantic/pydantic/pull/11121) +* Recursively unpack `Literal` values if using PEP 695 type aliases by [@Viicos](https://github.com/Viicos) in [#11114](https://github.com/pydantic/pydantic/pull/11114) +* Override `__subclasscheck__` on `ModelMetaclass` to avoid memory leak and performance issues by [@Viicos](https://github.com/Viicos) in [#11116](https://github.com/pydantic/pydantic/pull/11116) +* Remove unused `_extract_get_pydantic_json_schema()` parameter by [@Viicos](https://github.com/Viicos) in [#11155](https://github.com/pydantic/pydantic/pull/11155) +* Add FastAPI and SQLModel to third-party tests by [@sydney-runkle](https://github.com/sydney-runkle) in [#11044](https://github.com/pydantic/pydantic/pull/11044) +* Fix conditional expressions syntax for third-party tests by [@Viicos](https://github.com/Viicos) in [#11162](https://github.com/pydantic/pydantic/pull/11162) +* Move FastAPI tests to third-party workflow by [@Viicos](https://github.com/Viicos) in [#11164](https://github.com/pydantic/pydantic/pull/11164) +* Improve discriminated union error message for invalid union variants by [@Viicos](https://github.com/Viicos) in [#11161](https://github.com/pydantic/pydantic/pull/11161) +* Unpack PEP 695 type aliases if using the `Annotated` form by [@Viicos](https://github.com/Viicos) in [#11109](https://github.com/pydantic/pydantic/pull/11109) +* Include `openapi-python-client` check in issue creation for third-party failures, use `main` branch by [@sydney-runkle](https://github.com/sydney-runkle) in [#11182](https://github.com/pydantic/pydantic/pull/11182) +* Add pandera third-party tests by [@Viicos](https://github.com/Viicos) in [#11193](https://github.com/pydantic/pydantic/pull/11193) +* Add ODMantic third-party tests by [@sydney-runkle](https://github.com/sydney-runkle) in [#11197](https://github.com/pydantic/pydantic/pull/11197) +* Add missing stacklevel in `deprecated_instance_property` warning by [@Viicos](https://github.com/Viicos) in [#11200](https://github.com/pydantic/pydantic/pull/11200) +* Copy `WithJsonSchema` schema to avoid sharing mutated data by [@thejcannon](https://github.com/thejcannon) in [#11014](https://github.com/pydantic/pydantic/pull/11014) +* Do not cache parametrized models when in the process of parametrizing another model by [@Viicos](https://github.com/Viicos) in [#10704](https://github.com/pydantic/pydantic/pull/10704) +* Re-enable Beanie third-party tests by [@Viicos](https://github.com/Viicos) in [#11214](https://github.com/pydantic/pydantic/pull/11214) +* Add discriminated union related metadata entries to the `CoreMetadata` definition by [@Viicos](https://github.com/Viicos) in [#11216](https://github.com/pydantic/pydantic/pull/11216) +* Consolidate schema definitions logic in the `_Definitions` class by [@Viicos](https://github.com/Viicos) in [#11208](https://github.com/pydantic/pydantic/pull/11208) +* Support initializing root model fields with values of the `root` type in the mypy plugin by [@Viicos](https://github.com/Viicos) in [#11212](https://github.com/pydantic/pydantic/pull/11212) +* Fix various issues with dataclasses and `use_attribute_docstrings` by [@Viicos](https://github.com/Viicos) in [#11246](https://github.com/pydantic/pydantic/pull/11246) +* Only compute normalized decimal places if necessary in `decimal_places_validator` by [@misrasaurabh1](https://github.com/misrasaurabh1) in [#11281](https://github.com/pydantic/pydantic/pull/11281) +* Fix two misplaced sentences in validation errors documentation by [@ananiavito](https://github.com/ananiavito) in [#11302](https://github.com/pydantic/pydantic/pull/11302) +* Fix mkdocstrings inventory example in documentation by [@pawamoy](https://github.com/pawamoy) in [#11311](https://github.com/pydantic/pydantic/pull/11311) +* Add support for `validation_alias` in the mypy plugin by [@Viicos](https://github.com/Viicos) in [#11295](https://github.com/pydantic/pydantic/pull/11295) +* Do not transform model serializer functions as class methods in the mypy plugin by [@Viicos](https://github.com/Viicos) in [#11298](https://github.com/pydantic/pydantic/pull/11298) +* Simplify `GenerateJsonSchema.literal_schema()` implementation by [@misrasaurabh1](https://github.com/misrasaurabh1) in [#11321](https://github.com/pydantic/pydantic/pull/11321) +* Add additional allowed schemes for `ClickHouseDsn` by [@Maze21127](https://github.com/Maze21127) in [#11319](https://github.com/pydantic/pydantic/pull/11319) +* Coerce decimal constraints to `Decimal` instances by [@Viicos](https://github.com/Viicos) in [#11350](https://github.com/pydantic/pydantic/pull/11350) +* Fix `ValueError` on year zero by [@davidhewitt](https://github.com/davidhewitt) in [pydantic-core#1583](https://github.com/pydantic/pydantic-core/pull/1583) + +### New Contributors + +* [@FyZzyss](https://github.com/FyZzyss) made their first contribution in [#10789](https://github.com/pydantic/pydantic/pull/10789) +* [@tamird](https://github.com/tamird) made their first contribution in [#10948](https://github.com/pydantic/pydantic/pull/10948) +* [@felixxm](https://github.com/felixxm) made their first contribution in [#11077](https://github.com/pydantic/pydantic/pull/11077) +* [@alexprabhat99](https://github.com/alexprabhat99) made their first contribution in [#11082](https://github.com/pydantic/pydantic/pull/11082) +* [@Kharianne](https://github.com/Kharianne) made their first contribution in [#11111](https://github.com/pydantic/pydantic/pull/11111) +* [@mdaffad](https://github.com/mdaffad) made their first contribution in [#11177](https://github.com/pydantic/pydantic/pull/11177) +* [@thejcannon](https://github.com/thejcannon) made their first contribution in [#11014](https://github.com/pydantic/pydantic/pull/11014) +* [@thomasfrimannkoren](https://github.com/thomasfrimannkoren) made their first contribution in [#11251](https://github.com/pydantic/pydantic/pull/11251) +* [@usernameMAI](https://github.com/usernameMAI) made their first contribution in [#11275](https://github.com/pydantic/pydantic/pull/11275) +* [@ananiavito](https://github.com/ananiavito) made their first contribution in [#11302](https://github.com/pydantic/pydantic/pull/11302) +* [@pawamoy](https://github.com/pawamoy) made their first contribution in [#11311](https://github.com/pydantic/pydantic/pull/11311) +* [@Maze21127](https://github.com/Maze21127) made their first contribution in [#11319](https://github.com/pydantic/pydantic/pull/11319) + +## v2.10.6 (2025-01-23) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.10.6) + +### What's Changed + +#### Fixes + +* Fix JSON Schema reference collection with `'examples'` keys by [@Viicos](https://github.com/Viicos) in [#11325](https://github.com/pydantic/pydantic/pull/11325) +* Fix url python serialization by [@sydney-runkle](https://github.com/sydney-runkle) in [#11331](https://github.com/pydantic/pydantic/pull/11331) + +## v2.10.5 (2025-01-08) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.10.5) + +### What's Changed + +#### Fixes + +* Remove custom MRO implementation of Pydantic models by [@Viicos](https://github.com/Viicos) in [#11184](https://github.com/pydantic/pydantic/pull/11184) +* Fix URL serialization for unions by [@sydney-runkle](https://github.com/sydney-runkle) in [#11233](https://github.com/pydantic/pydantic/pull/11233) + +## v2.10.4 (2024-12-18) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.10.4) + +### What's Changed + +#### Packaging + +* Bump `pydantic-core` to v2.27.2 by [@davidhewitt](https://github.com/davidhewitt) in [#11138](https://github.com/pydantic/pydantic/pull/11138) + +#### Fixes + +* Fix for comparison of `AnyUrl` objects by [@alexprabhat99](https://github.com/alexprabhat99) in [#11082](https://github.com/pydantic/pydantic/pull/11082) +* Properly fetch PEP 695 type params for functions, do not fetch annotations from signature by [@Viicos](https://github.com/Viicos) in [#11093](https://github.com/pydantic/pydantic/pull/11093) +* Include JSON Schema input core schema in function schemas by [@Viicos](https://github.com/Viicos) in [#11085](https://github.com/pydantic/pydantic/pull/11085) +* Add `len` to `_BaseUrl` to avoid TypeError by [@Kharianne](https://github.com/Kharianne) in [#11111](https://github.com/pydantic/pydantic/pull/11111) +* Make sure the type reference is removed from the seen references by [@Viicos](https://github.com/Viicos) in [#11143](https://github.com/pydantic/pydantic/pull/11143) + +### New Contributors + +* [@FyZzyss](https://github.com/FyZzyss) made their first contribution in [#10789](https://github.com/pydantic/pydantic/pull/10789) +* [@tamird](https://github.com/tamird) made their first contribution in [#10948](https://github.com/pydantic/pydantic/pull/10948) +* [@felixxm](https://github.com/felixxm) made their first contribution in [#11077](https://github.com/pydantic/pydantic/pull/11077) +* [@alexprabhat99](https://github.com/alexprabhat99) made their first contribution in [#11082](https://github.com/pydantic/pydantic/pull/11082) +* [@Kharianne](https://github.com/Kharianne) made their first contribution in [#11111](https://github.com/pydantic/pydantic/pull/11111) + +## v2.10.3 (2024-12-03) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.10.3) + +### What's Changed + +#### Fixes + +* Set fields when `defer_build` is set on Pydantic dataclasses by [@Viicos](https://github.com/Viicos) in [#10984](https://github.com/pydantic/pydantic/pull/10984) +* Do not resolve the JSON Schema reference for `dict` core schema keys by [@Viicos](https://github.com/Viicos) in [#10989](https://github.com/pydantic/pydantic/pull/10989) +* Use the globals of the function when evaluating the return type for `PlainSerializer` and `WrapSerializer` functions by [@Viicos](https://github.com/Viicos) in [#11008](https://github.com/pydantic/pydantic/pull/11008) +* Fix host required enforcement for urls to be compatible with v2.9 behavior by [@sydney-runkle](https://github.com/sydney-runkle) in [#11027](https://github.com/pydantic/pydantic/pull/11027) +* Add a `default_factory_takes_validated_data` property to `FieldInfo` by [@Viicos](https://github.com/Viicos) in [#11034](https://github.com/pydantic/pydantic/pull/11034) +* Fix url json schema in `serialization` mode by [@sydney-runkle](https://github.com/sydney-runkle) in [#11035](https://github.com/pydantic/pydantic/pull/11035) + +## v2.10.2 (2024-11-25) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.10.2) + +### What's Changed + +#### Fixes + +* Only evaluate FieldInfo annotations if required during schema building by [@Viicos](https://github.com/Viicos) in [#10769](https://github.com/pydantic/pydantic/pull/10769) +* Do not evaluate annotations for private fields by [@Viicos](https://github.com/Viicos) in [#10962](https://github.com/pydantic/pydantic/pull/10962) +* Support serialization as any for `Secret` types and `Url` types by [@sydney-runkle](https://github.com/sydney-runkle) in [#10947](https://github.com/pydantic/pydantic/pull/10947) +* Fix type hint of `Field.default` to be compatible with Python 3.8 and 3.9 by [@Viicos](https://github.com/Viicos) in [#10972](https://github.com/pydantic/pydantic/pull/10972) +* Add hashing support for URL types by [@sydney-runkle](https://github.com/sydney-runkle) in [#10975](https://github.com/pydantic/pydantic/pull/10975) +* Hide `BaseModel.__replace__` definition from type checkers by [@Viicos](https://github.com/Viicos) in [#10979](https://github.com/pydantic/pydantic/pull/10979) + +## v2.10.1 (2024-11-21) + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.10.1) + +### What's Changed + +#### Packaging + +* Bump `pydantic-core` version to `v2.27.1` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10938](https://github.com/pydantic/pydantic/pull/10938) + +#### Fixes + +* Use the correct frame when instantiating a parametrized `TypeAdapter` by [@Viicos](https://github.com/Viicos) in [#10893](https://github.com/pydantic/pydantic/pull/10893) +* Relax check for validated data in `default_factory` utils by [@sydney-runkle](https://github.com/sydney-runkle) in [#10909](https://github.com/pydantic/pydantic/pull/10909) +* Fix type checking issue with `model_fields` and `model_computed_fields` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10911](https://github.com/pydantic/pydantic/pull/10911) +* Use the parent configuration during schema generation for stdlib `dataclass`es by [@sydney-runkle](https://github.com/sydney-runkle) in [#10928](https://github.com/pydantic/pydantic/pull/10928) +* Use the `globals` of the function when evaluating the return type of serializers and `computed_field`s by [@Viicos](https://github.com/Viicos) in [#10929](https://github.com/pydantic/pydantic/pull/10929) +* Fix URL constraint application by [@sydney-runkle](https://github.com/sydney-runkle) in [#10922](https://github.com/pydantic/pydantic/pull/10922) +* Fix URL equality with different validation methods by [@sydney-runkle](https://github.com/sydney-runkle) in [#10934](https://github.com/pydantic/pydantic/pull/10934) +* Fix JSON schema title when specified as `''` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10936](https://github.com/pydantic/pydantic/pull/10936) +* Fix `python` mode serialization for `complex` inference by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic-core#1549](https://github.com/pydantic/pydantic-core/pull/1549) + +### New Contributors + +## v2.10.0 (2024-11-20) + +The code released in v2.10.0 is practically identical to that of v2.10.0b2. + +[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.10.0) + +See the [v2.10 release blog post](https://pydantic.dev/articles/pydantic-v2-10-release) for the highlights! + +### What's Changed + +#### Packaging + +* Bump `pydantic-core` to `v2.27.0` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10825](https://github.com/pydantic/pydantic/pull/10825) +* Replaced pdm with uv by [@frfahim](https://github.com/frfahim) in [#10727](https://github.com/pydantic/pydantic/pull/10727) + +#### New Features + +* Support `fractions.Fraction` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10318](https://github.com/pydantic/pydantic/pull/10318) +* Support `Hashable` for json validation by [@sydney-runkle](https://github.com/sydney-runkle) in [#10324](https://github.com/pydantic/pydantic/pull/10324) +* Add a `SocketPath` type for `linux` systems by [@theunkn0wn1](https://github.com/theunkn0wn1) in [#10378](https://github.com/pydantic/pydantic/pull/10378) +* Allow arbitrary refs in JSON schema `examples` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10417](https://github.com/pydantic/pydantic/pull/10417) +* Support `defer_build` for Pydantic dataclasses by [@Viicos](https://github.com/Viicos) in [#10313](https://github.com/pydantic/pydantic/pull/10313) +* Adding v1 / v2 incompatibility warning for nested v1 model by [@sydney-runkle](https://github.com/sydney-runkle) in [#10431](https://github.com/pydantic/pydantic/pull/10431) +* Add support for unpacked `TypedDict` to type hint variadic keyword arguments with `@validate_call` by [@Viicos](https://github.com/Viicos) in [#10416](https://github.com/pydantic/pydantic/pull/10416) +* Support compiled patterns in `protected_namespaces` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10522](https://github.com/pydantic/pydantic/pull/10522) +* Add support for `propertyNames` in JSON schema by [@FlorianSW](https://github.com/FlorianSW) in [#10478](https://github.com/pydantic/pydantic/pull/10478) +* Adding `__replace__` protocol for Python 3.13+ support by [@sydney-runkle](https://github.com/sydney-runkle) in [#10596](https://github.com/pydantic/pydantic/pull/10596) +* Expose public `sort` method for JSON schema generation by [@sydney-runkle](https://github.com/sydney-runkle) in [#10595](https://github.com/pydantic/pydantic/pull/10595) +* Add runtime validation of `@validate_call` callable argument by [@kc0506](https://github.com/kc0506) in [#10627](https://github.com/pydantic/pydantic/pull/10627) +* Add `experimental_allow_partial` support by [@samuelcolvin](https://github.com/samuelcolvin) in [#10748](https://github.com/pydantic/pydantic/pull/10748) +* Support default factories taking validated data as an argument by [@Viicos](https://github.com/Viicos) in [#10678](https://github.com/pydantic/pydantic/pull/10678) +* Allow subclassing `ValidationError` and `PydanticCustomError` by [@Youssefares](https://github.com/Youssefares) in [pydantic/pydantic-core#1413](https://github.com/pydantic/pydantic-core/pull/1413) +* Add `trailing-strings` support to `experimental_allow_partial` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10825](https://github.com/pydantic/pydantic/pull/10825) +* Add `rebuild()` method for `TypeAdapter` and simplify `defer_build` patterns by [@sydney-runkle](https://github.com/sydney-runkle) in [#10537](https://github.com/pydantic/pydantic/pull/10537) +* Improve `TypeAdapter` instance repr by [@sydney-runkle](https://github.com/sydney-runkle) in [#10872](https://github.com/pydantic/pydantic/pull/10872) + +#### Changes + +* Don't allow customization of `SchemaGenerator` until interface is more stable by [@sydney-runkle](https://github.com/sydney-runkle) in [#10303](https://github.com/pydantic/pydantic/pull/10303) +* Cleanly `defer_build` on `TypeAdapters`, removing experimental flag by [@sydney-runkle](https://github.com/sydney-runkle) in [#10329](https://github.com/pydantic/pydantic/pull/10329) +* Fix `mro` of generic subclass by [@kc0506](https://github.com/kc0506) in [#10100](https://github.com/pydantic/pydantic/pull/10100) +* Strip whitespaces on JSON Schema title generation by [@sydney-runkle](https://github.com/sydney-runkle) in [#10404](https://github.com/pydantic/pydantic/pull/10404) +* Use `b64decode` and `b64encode` for `Base64Bytes` type by [@sydney-runkle](https://github.com/sydney-runkle) in [#10486](https://github.com/pydantic/pydantic/pull/10486) +* Relax protected namespace config default by [@sydney-runkle](https://github.com/sydney-runkle) in [#10441](https://github.com/pydantic/pydantic/pull/10441) +* Revalidate parametrized generics if instance's origin is subclass of OG class by [@sydney-runkle](https://github.com/sydney-runkle) in [#10666](https://github.com/pydantic/pydantic/pull/10666) +* Warn if configuration is specified on the `@dataclass` decorator and with the `__pydantic_config__` attribute by [@sydney-runkle](https://github.com/sydney-runkle) in [#10406](https://github.com/pydantic/pydantic/pull/10406) +* Recommend against using `Ellipsis` (...) with `Field` by [@Viicos](https://github.com/Viicos) in [#10661](https://github.com/pydantic/pydantic/pull/10661) +* Migrate to subclassing instead of annotated approach for pydantic url types by [@sydney-runkle](https://github.com/sydney-runkle) in [#10662](https://github.com/pydantic/pydantic/pull/10662) +* Change JSON schema generation of `Literal`s and `Enums` by [@Viicos](https://github.com/Viicos) in [#10692](https://github.com/pydantic/pydantic/pull/10692) +* Simplify unions involving `Any` or `Never` when replacing type variables by [@Viicos](https://github.com/Viicos) in [#10338](https://github.com/pydantic/pydantic/pull/10338) +* Do not require padding when decoding `base64` bytes by [@bschoenmaeckers](https://github.com/bschoenmaeckers) in [pydantic/pydantic-core#1448](https://github.com/pydantic/pydantic-core/pull/1448) +* Support dates all the way to 1BC by [@changhc](https://github.com/changhc) in [pydantic/speedate#77](https://github.com/pydantic/speedate/pull/77) + +#### Performance + +* Schema cleaning: skip unnecessary copies during schema walking by [@Viicos](https://github.com/Viicos) in [#10286](https://github.com/pydantic/pydantic/pull/10286) +* Refactor namespace logic for annotations evaluation by [@Viicos](https://github.com/Viicos) in [#10530](https://github.com/pydantic/pydantic/pull/10530) +* Improve email regexp on edge cases by [@AlekseyLobanov](https://github.com/AlekseyLobanov) in [#10601](https://github.com/pydantic/pydantic/pull/10601) +* `CoreMetadata` refactor with an emphasis on documentation, schema build time performance, and reducing complexity by [@sydney-runkle](https://github.com/sydney-runkle) in [#10675](https://github.com/pydantic/pydantic/pull/10675) + +#### Fixes + +* Remove guarding check on `computed_field` with `field_serializer` by [@nix010](https://github.com/nix010) in [#10390](https://github.com/pydantic/pydantic/pull/10390) +* Fix `Predicate` issue in `v2.9.0` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10321](https://github.com/pydantic/pydantic/pull/10321) +* Fixing `annotated-types` bound by [@sydney-runkle](https://github.com/sydney-runkle) in [#10327](https://github.com/pydantic/pydantic/pull/10327) +* Turn `tzdata` install requirement into optional `timezone` dependency by [@jakob-keller](https://github.com/jakob-keller) in [#10331](https://github.com/pydantic/pydantic/pull/10331) +* Use correct types namespace when building `namedtuple` core schemas by [@Viicos](https://github.com/Viicos) in [#10337](https://github.com/pydantic/pydantic/pull/10337) +* Fix evaluation of stringified annotations during namespace inspection by [@Viicos](https://github.com/Viicos) in [#10347](https://github.com/pydantic/pydantic/pull/10347) +* Fix `IncEx` type alias definition by [@Viicos](https://github.com/Viicos) in [#10339](https://github.com/pydantic/pydantic/pull/10339) +* Do not error when trying to evaluate annotations of private attributes by [@Viicos](https://github.com/Viicos) in [#10358](https://github.com/pydantic/pydantic/pull/10358) +* Fix nested type statement by [@kc0506](https://github.com/kc0506) in [#10369](https://github.com/pydantic/pydantic/pull/10369) +* Improve typing of `ModelMetaclass.mro` by [@Viicos](https://github.com/Viicos) in [#10372](https://github.com/pydantic/pydantic/pull/10372) +* Fix class access of deprecated `computed_field`s by [@Viicos](https://github.com/Viicos) in [#10391](https://github.com/pydantic/pydantic/pull/10391) +* Make sure `inspect.iscoroutinefunction` works on coroutines decorated with `@validate_call` by [@MovisLi](https://github.com/MovisLi) in [#10374](https://github.com/pydantic/pydantic/pull/10374) +* Fix `NameError` when using `validate_call` with PEP 695 on a class by [@kc0506](https://github.com/kc0506) in [#10380](https://github.com/pydantic/pydantic/pull/10380) +* Fix `ZoneInfo` with various invalid types by [@sydney-runkle](https://github.com/sydney-runkle) in [#10408](https://github.com/pydantic/pydantic/pull/10408) +* Fix `PydanticUserError` on empty `model_config` with annotations by [@cdwilson](https://github.com/cdwilson) in [#10412](https://github.com/pydantic/pydantic/pull/10412) +* Fix variance issue in `_IncEx` type alias, only allow `True` by [@Viicos](https://github.com/Viicos) in [#10414](https://github.com/pydantic/pydantic/pull/10414) +* Fix serialization schema generation when using `PlainValidator` by [@Viicos](https://github.com/Viicos) in [#10427](https://github.com/pydantic/pydantic/pull/10427) +* Fix schema generation error when serialization schema holds references by [@Viicos](https://github.com/Viicos) in [#10444](https://github.com/pydantic/pydantic/pull/10444) +* Inline references if possible when generating schema for `json_schema_input_type` by [@Viicos](https://github.com/Viicos) in [#10439](https://github.com/pydantic/pydantic/pull/10439) +* Fix recursive arguments in `Representation` by [@Viicos](https://github.com/Viicos) in [#10480](https://github.com/pydantic/pydantic/pull/10480) +* Fix representation for builtin function types by [@kschwab](https://github.com/kschwab) in [#10479](https://github.com/pydantic/pydantic/pull/10479) +* Add python validators for decimal constraints (`max_digits` and `decimal_places`) by [@sydney-runkle](https://github.com/sydney-runkle) in [#10506](https://github.com/pydantic/pydantic/pull/10506) +* Only fetch `__pydantic_core_schema__` from the current class during schema generation by [@Viicos](https://github.com/Viicos) in [#10518](https://github.com/pydantic/pydantic/pull/10518) +* Fix `stacklevel` on deprecation warnings for `BaseModel` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10520](https://github.com/pydantic/pydantic/pull/10520) +* Fix warning `stacklevel` in `BaseModel.__init__` by [@Viicos](https://github.com/Viicos) in [#10526](https://github.com/pydantic/pydantic/pull/10526) +* Improve error handling for in-evaluable refs for discriminator application by [@sydney-runkle](https://github.com/sydney-runkle) in [#10440](https://github.com/pydantic/pydantic/pull/10440) +* Change the signature of `ConfigWrapper.core_config` to take the title directly by [@Viicos](https://github.com/Viicos) in [#10562](https://github.com/pydantic/pydantic/pull/10562) +* Do not use the previous config from the stack for dataclasses without config by [@Viicos](https://github.com/Viicos) in [#10576](https://github.com/pydantic/pydantic/pull/10576) +* Fix serialization for IP types with `mode='python'` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10594](https://github.com/pydantic/pydantic/pull/10594) +* Support constraint application for `Base64Etc` types by [@sydney-runkle](https://github.com/sydney-runkle) in [#10584](https://github.com/pydantic/pydantic/pull/10584) +* Fix `validate_call` ignoring `Field` in `Annotated` by [@kc0506](https://github.com/kc0506) in [#10610](https://github.com/pydantic/pydantic/pull/10610) +* Raise an error when `Self` is invalid by [@kc0506](https://github.com/kc0506) in [#10609](https://github.com/pydantic/pydantic/pull/10609) +* Using `core_schema.InvalidSchema` instead of metadata injection + checks by [@sydney-runkle](https://github.com/sydney-runkle) in [#10523](https://github.com/pydantic/pydantic/pull/10523) +* Tweak type alias logic by [@kc0506](https://github.com/kc0506) in [#10643](https://github.com/pydantic/pydantic/pull/10643) +* Support usage of `type` with `typing.Self` and type aliases by [@kc0506](https://github.com/kc0506) in [#10621](https://github.com/pydantic/pydantic/pull/10621) +* Use overloads for `Field` and `PrivateAttr` functions by [@Viicos](https://github.com/Viicos) in [#10651](https://github.com/pydantic/pydantic/pull/10651) +* Clean up the `mypy` plugin implementation by [@Viicos](https://github.com/Viicos) in [#10669](https://github.com/pydantic/pydantic/pull/10669) +* Properly check for `typing_extensions` variant of `TypeAliasType` by [@Daraan](https://github.com/Daraan) in [#10713](https://github.com/pydantic/pydantic/pull/10713) +* Allow any mapping in `BaseModel.model_copy()` by [@Viicos](https://github.com/Viicos) in [#10751](https://github.com/pydantic/pydantic/pull/10751) +* Fix `isinstance` behavior for urls by [@sydney-runkle](https://github.com/sydney-runkle) in [#10766](https://github.com/pydantic/pydantic/pull/10766) +* Ensure `cached_property` can be set on Pydantic models by [@Viicos](https://github.com/Viicos) in [#10774](https://github.com/pydantic/pydantic/pull/10774) +* Fix equality checks for primitives in literals by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1459](https://github.com/pydantic/pydantic-core/pull/1459) +* Properly enforce `host_required` for URLs by [@Viicos](https://github.com/Viicos) in [pydantic/pydantic-core#1488](https://github.com/pydantic/pydantic-core/pull/1488) +* Fix when `coerce_numbers_to_str` enabled and string has invalid Unicode character by [@andrey-berenda](https://github.com/andrey-berenda) in [pydantic/pydantic-core#1515](https://github.com/pydantic/pydantic-core/pull/1515) +* Fix serializing `complex` values in `Enum`s by [@changhc](https://github.com/changhc) in [pydantic/pydantic-core#1524](https://github.com/pydantic/pydantic-core/pull/1524) +* Refactor `_typing_extra` module by [@Viicos](https://github.com/Viicos) in [#10725](https://github.com/pydantic/pydantic/pull/10725) +* Support intuitive equality for urls by [@sydney-runkle](https://github.com/sydney-runkle) in [#10798](https://github.com/pydantic/pydantic/pull/10798) +* Add `bytearray` to `TypeAdapter.validate_json` signature by [@samuelcolvin](https://github.com/samuelcolvin) in [#10802](https://github.com/pydantic/pydantic/pull/10802) +* Ensure class access of method descriptors is performed when used as a default with `Field` by [@Viicos](https://github.com/Viicos) in [#10816](https://github.com/pydantic/pydantic/pull/10816) +* Fix circular import with `validate_call` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10807](https://github.com/pydantic/pydantic/pull/10807) +* Fix error when using type aliases referencing other type aliases by [@Viicos](https://github.com/Viicos) in [#10809](https://github.com/pydantic/pydantic/pull/10809) +* Fix `IncEx` type alias to be compatible with mypy by [@Viicos](https://github.com/Viicos) in [#10813](https://github.com/pydantic/pydantic/pull/10813) +* Make `__signature__` a lazy property, do not deepcopy defaults by [@Viicos](https://github.com/Viicos) in [#10818](https://github.com/pydantic/pydantic/pull/10818) +* Make `__signature__` lazy for dataclasses, too by [@sydney-runkle](https://github.com/sydney-runkle) in [#10832](https://github.com/pydantic/pydantic/pull/10832) +* Subclass all single host url classes from `AnyUrl` to preserve behavior from v2.9 by [@sydney-runkle](https://github.com/sydney-runkle) in [#10856](https://github.com/pydantic/pydantic/pull/10856) + +### New Contributors + +* [@jakob-keller](https://github.com/jakob-keller) made their first contribution in [#10331](https://github.com/pydantic/pydantic/pull/10331) +* [@MovisLi](https://github.com/MovisLi) made their first contribution in [#10374](https://github.com/pydantic/pydantic/pull/10374) +* [@joaopalmeiro](https://github.com/joaopalmeiro) made their first contribution in [#10405](https://github.com/pydantic/pydantic/pull/10405) +* [@theunkn0wn1](https://github.com/theunkn0wn1) made their first contribution in [#10378](https://github.com/pydantic/pydantic/pull/10378) +* [@cdwilson](https://github.com/cdwilson) made their first contribution in [#10412](https://github.com/pydantic/pydantic/pull/10412) +* [@dlax](https://github.com/dlax) made their first contribution in [#10421](https://github.com/pydantic/pydantic/pull/10421) +* [@kschwab](https://github.com/kschwab) made their first contribution in [#10479](https://github.com/pydantic/pydantic/pull/10479) +* [@santibreo](https://github.com/santibreo) made their first contribution in [#10453](https://github.com/pydantic/pydantic/pull/10453) +* [@FlorianSW](https://github.com/FlorianSW) made their first contribution in [#10478](https://github.com/pydantic/pydantic/pull/10478) +* [@tkasuz](https://github.com/tkasuz) made their first contribution in [#10555](https://github.com/pydantic/pydantic/pull/10555) +* [@AlekseyLobanov](https://github.com/AlekseyLobanov) made their first contribution in [#10601](https://github.com/pydantic/pydantic/pull/10601) +* [@NiclasvanEyk](https://github.com/NiclasvanEyk) made their first contribution in [#10667](https://github.com/pydantic/pydantic/pull/10667) +* [@mschoettle](https://github.com/mschoettle) made their first contribution in [#10677](https://github.com/pydantic/pydantic/pull/10677) +* [@Daraan](https://github.com/Daraan) made their first contribution in [#10713](https://github.com/pydantic/pydantic/pull/10713) +* [@k4nar](https://github.com/k4nar) made their first contribution in [#10736](https://github.com/pydantic/pydantic/pull/10736) +* [@UriyaHarpeness](https://github.com/UriyaHarpeness) made their first contribution in [#10740](https://github.com/pydantic/pydantic/pull/10740) +* [@frfahim](https://github.com/frfahim) made their first contribution in [#10727](https://github.com/pydantic/pydantic/pull/10727) + +## v2.10.0b2 (2024-11-13) + +Pre-release, see [the GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.10.0b2) for details. + +## v2.10.0b1 (2024-11-06) + +Pre-release, see [the GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.10.0b1) for details. + + +... see [here](https://docs.pydantic.dev/changelog/#v0322-2019-08-17) for earlier changes. diff --git a/backend/.venv/Lib/site-packages/pydantic-2.12.5.dist-info/RECORD b/backend/.venv/Lib/site-packages/pydantic-2.12.5.dist-info/RECORD new file mode 100644 index 0000000..2baa547 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic-2.12.5.dist-info/RECORD @@ -0,0 +1,217 @@ +pydantic-2.12.5.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pydantic-2.12.5.dist-info/METADATA,sha256=o7oj6JUZH-1puDI8vLzcgphMoLajzcYsSKI0GIapwI0,90587 +pydantic-2.12.5.dist-info/RECORD,, +pydantic-2.12.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87 +pydantic-2.12.5.dist-info/licenses/LICENSE,sha256=qeGG88oWte74QxjnpwFyE1GgDLe4rjpDlLZ7SeNSnvM,1129 +pydantic/__init__.py,sha256=5iEnJ4wHv1OEzdKQPzaKaZKfO4pSQAC65ODrYI6_S8Y,15812 +pydantic/__pycache__/__init__.cpython-312.pyc,, +pydantic/__pycache__/_migration.cpython-312.pyc,, +pydantic/__pycache__/alias_generators.cpython-312.pyc,, +pydantic/__pycache__/aliases.cpython-312.pyc,, +pydantic/__pycache__/annotated_handlers.cpython-312.pyc,, +pydantic/__pycache__/class_validators.cpython-312.pyc,, +pydantic/__pycache__/color.cpython-312.pyc,, +pydantic/__pycache__/config.cpython-312.pyc,, +pydantic/__pycache__/dataclasses.cpython-312.pyc,, +pydantic/__pycache__/datetime_parse.cpython-312.pyc,, +pydantic/__pycache__/decorator.cpython-312.pyc,, +pydantic/__pycache__/env_settings.cpython-312.pyc,, +pydantic/__pycache__/error_wrappers.cpython-312.pyc,, +pydantic/__pycache__/errors.cpython-312.pyc,, +pydantic/__pycache__/fields.cpython-312.pyc,, +pydantic/__pycache__/functional_serializers.cpython-312.pyc,, +pydantic/__pycache__/functional_validators.cpython-312.pyc,, +pydantic/__pycache__/generics.cpython-312.pyc,, +pydantic/__pycache__/json.cpython-312.pyc,, +pydantic/__pycache__/json_schema.cpython-312.pyc,, +pydantic/__pycache__/main.cpython-312.pyc,, +pydantic/__pycache__/mypy.cpython-312.pyc,, +pydantic/__pycache__/networks.cpython-312.pyc,, +pydantic/__pycache__/parse.cpython-312.pyc,, +pydantic/__pycache__/root_model.cpython-312.pyc,, +pydantic/__pycache__/schema.cpython-312.pyc,, +pydantic/__pycache__/tools.cpython-312.pyc,, +pydantic/__pycache__/type_adapter.cpython-312.pyc,, +pydantic/__pycache__/types.cpython-312.pyc,, +pydantic/__pycache__/typing.cpython-312.pyc,, +pydantic/__pycache__/utils.cpython-312.pyc,, +pydantic/__pycache__/validate_call_decorator.cpython-312.pyc,, +pydantic/__pycache__/validators.cpython-312.pyc,, +pydantic/__pycache__/version.cpython-312.pyc,, +pydantic/__pycache__/warnings.cpython-312.pyc,, +pydantic/_internal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pydantic/_internal/__pycache__/__init__.cpython-312.pyc,, +pydantic/_internal/__pycache__/_config.cpython-312.pyc,, +pydantic/_internal/__pycache__/_core_metadata.cpython-312.pyc,, +pydantic/_internal/__pycache__/_core_utils.cpython-312.pyc,, +pydantic/_internal/__pycache__/_dataclasses.cpython-312.pyc,, +pydantic/_internal/__pycache__/_decorators.cpython-312.pyc,, +pydantic/_internal/__pycache__/_decorators_v1.cpython-312.pyc,, +pydantic/_internal/__pycache__/_discriminated_union.cpython-312.pyc,, +pydantic/_internal/__pycache__/_docs_extraction.cpython-312.pyc,, +pydantic/_internal/__pycache__/_fields.cpython-312.pyc,, +pydantic/_internal/__pycache__/_forward_ref.cpython-312.pyc,, +pydantic/_internal/__pycache__/_generate_schema.cpython-312.pyc,, +pydantic/_internal/__pycache__/_generics.cpython-312.pyc,, +pydantic/_internal/__pycache__/_git.cpython-312.pyc,, +pydantic/_internal/__pycache__/_import_utils.cpython-312.pyc,, +pydantic/_internal/__pycache__/_internal_dataclass.cpython-312.pyc,, +pydantic/_internal/__pycache__/_known_annotated_metadata.cpython-312.pyc,, +pydantic/_internal/__pycache__/_mock_val_ser.cpython-312.pyc,, +pydantic/_internal/__pycache__/_model_construction.cpython-312.pyc,, +pydantic/_internal/__pycache__/_namespace_utils.cpython-312.pyc,, +pydantic/_internal/__pycache__/_repr.cpython-312.pyc,, +pydantic/_internal/__pycache__/_schema_gather.cpython-312.pyc,, +pydantic/_internal/__pycache__/_schema_generation_shared.cpython-312.pyc,, +pydantic/_internal/__pycache__/_serializers.cpython-312.pyc,, +pydantic/_internal/__pycache__/_signature.cpython-312.pyc,, +pydantic/_internal/__pycache__/_typing_extra.cpython-312.pyc,, +pydantic/_internal/__pycache__/_utils.cpython-312.pyc,, +pydantic/_internal/__pycache__/_validate_call.cpython-312.pyc,, +pydantic/_internal/__pycache__/_validators.cpython-312.pyc,, +pydantic/_internal/_config.py,sha256=TWZwg3c0bZHiT3boR5-YYqkouHcwjRdenmyGHofV7E0,14674 +pydantic/_internal/_core_metadata.py,sha256=Y_g2t3i7uluK-wXCZvzJfRFMPUM23aBYLfae4FzBPy0,5162 +pydantic/_internal/_core_utils.py,sha256=1jru4VbJ0x63R6dtVcuOI-dKQTC_d_lSnJWEBQzGNEQ,6487 +pydantic/_internal/_dataclasses.py,sha256=Tk1mEafhad1kV7K5tPX5BwxWSXY7C-MKwf0OLFgIlEA,13158 +pydantic/_internal/_decorators.py,sha256=PnyAoKSg3BNbCVSZnwqw9naEg1UDtYvDT9LluigPiO8,33529 +pydantic/_internal/_decorators_v1.py,sha256=tfdfdpQKY4R2XCOwqHbZeoQMur6VNigRrfhudXBHx38,6185 +pydantic/_internal/_discriminated_union.py,sha256=aMl0SRSyQyHfW4-klnMTHNvwSRoqE3H3PRV_05vRsTg,25478 +pydantic/_internal/_docs_extraction.py,sha256=fyznSAHh5AzohnXZStV0HvH-nRbavNHPyg-knx-S_EE,4127 +pydantic/_internal/_fields.py,sha256=YSfEKq21FgjLJ6YqYXKh0eEEs5nxMPvQ6hp9pA8Nzfw,28093 +pydantic/_internal/_forward_ref.py,sha256=5n3Y7-3AKLn8_FS3Yc7KutLiPUhyXmAtkEZOaFnonwM,611 +pydantic/_internal/_generate_schema.py,sha256=TT49vzYzqH90rWrv5ptNoZgjzOsR0KPlSkqPVFrnrBw,132665 +pydantic/_internal/_generics.py,sha256=ELqjT6LMzQzWAK0EB5_9qke_iAazz0OQ4gunp_uKuYY,23822 +pydantic/_internal/_git.py,sha256=IwPh3DPfa2Xq3rBuB9Nx8luR2A1i69QdeTfWWXIuCVg,809 +pydantic/_internal/_import_utils.py,sha256=TRhxD5OuY6CUosioBdBcJUs0om7IIONiZdYAV7zQ8jM,402 +pydantic/_internal/_internal_dataclass.py,sha256=_bedc1XbuuygRGiLZqkUkwwFpQaoR1hKLlR501nyySY,144 +pydantic/_internal/_known_annotated_metadata.py,sha256=Jc7KTNFZoB3f-0ibP_NgJINOeVvYE3q3OTBQDjVMk3U,16765 +pydantic/_internal/_mock_val_ser.py,sha256=wmRRFSBvqfcLbI41PsFliB4u2AZ3mJpZeiERbD3xKTo,8885 +pydantic/_internal/_model_construction.py,sha256=wk-bNGDAJvduaGvn0U0_8zEl0GERu0shJvN8_ZfkYaw,37783 +pydantic/_internal/_namespace_utils.py,sha256=hl3-TRAr82U2jTyPP3t-QqsvKLirxtkLfNfrN-fp0x8,12878 +pydantic/_internal/_repr.py,sha256=jQfnJuyDxQpSRNhG29II9PX8e4Nv2qWZrEw2lqih3UE,5172 +pydantic/_internal/_schema_gather.py,sha256=VLEv51TYEeeND2czsyrmJq1MVnJqTOmnLan7VG44c8A,9114 +pydantic/_internal/_schema_generation_shared.py,sha256=F_rbQbrkoomgxsskdHpP0jUJ7TCfe0BADAEkq6CJ4nM,4842 +pydantic/_internal/_serializers.py,sha256=YIWvSmAR5fnbGSWCOQduWt1yB4ZQY42eAruc-enrb6c,1491 +pydantic/_internal/_signature.py,sha256=8EljPJe4pSnapuirG5DkBAgD1hggHxEAyzFPH-9H0zE,6779 +pydantic/_internal/_typing_extra.py,sha256=_GRYopNi4a9USi5UQ285ObrlsYmvqKEWTNbBoJFSK2c,30309 +pydantic/_internal/_utils.py,sha256=c6Naqf3bds4jBctepiW5jV0xISQQQk5EBUhMNmVQ3Nk,15912 +pydantic/_internal/_validate_call.py,sha256=PfdVnSzhXOrENtaDoDw3PFWPVYD5W_gNYPe8p3Ug6Lg,5321 +pydantic/_internal/_validators.py,sha256=dv0a2Nkc4zcYqv31Gh_QId2lcf-W0kQpV0oSNzgEdfg,20588 +pydantic/_migration.py,sha256=VF73LRCUz3Irb5xVt13jb3NAcXVnEF6T1-J0OLfeZ5A,12160 +pydantic/alias_generators.py,sha256=KM1n3u4JfLSBl1UuYg3hoYHzXJD-yvgrnq8u1ccwh_A,2124 +pydantic/aliases.py,sha256=vhCHyoSWnX-EJ-wWb5qj4xyRssgGWnTQfzQp4GSZ9ug,4937 +pydantic/annotated_handlers.py,sha256=WfyFSqwoEIFXBh7T73PycKloI1DiX45GWi0-JOsCR4Y,4407 +pydantic/class_validators.py,sha256=i_V3j-PYdGLSLmj_IJZekTRjunO8SIVz8LMlquPyP7E,148 +pydantic/color.py,sha256=AzqGfVQHF92_ZctDcue0DM4yTp2P6tekkwRINTWrLIo,21481 +pydantic/config.py,sha256=5MjjzlAR0_xq7C1yAEPf7qWp5qraQwStRvma9nzbqVI,44267 +pydantic/dataclasses.py,sha256=VlknbEulg08xdmPg_60hBsCVIw-W603OJWY2n5gyXA0,18936 +pydantic/datetime_parse.py,sha256=QC-WgMxMr_wQ_mNXUS7AVf-2hLEhvvsPY1PQyhSGOdk,150 +pydantic/decorator.py,sha256=YX-jUApu5AKaVWKPoaV-n-4l7UbS69GEt9Ra3hszmKI,145 +pydantic/deprecated/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pydantic/deprecated/__pycache__/__init__.cpython-312.pyc,, +pydantic/deprecated/__pycache__/class_validators.cpython-312.pyc,, +pydantic/deprecated/__pycache__/config.cpython-312.pyc,, +pydantic/deprecated/__pycache__/copy_internals.cpython-312.pyc,, +pydantic/deprecated/__pycache__/decorator.cpython-312.pyc,, +pydantic/deprecated/__pycache__/json.cpython-312.pyc,, +pydantic/deprecated/__pycache__/parse.cpython-312.pyc,, +pydantic/deprecated/__pycache__/tools.cpython-312.pyc,, +pydantic/deprecated/class_validators.py,sha256=EAcaVQM5zp2wBml0ybN62CfQfyJvDLx5Qd9Pk4_tb4U,10273 +pydantic/deprecated/config.py,sha256=k_lsVk57paxLJOcBueH07cu1OgEgWdVBxm6lfaC3CCU,2663 +pydantic/deprecated/copy_internals.py,sha256=Ghd-vkMd5EYCCgyCGtPKO58np9cEKBQC6qkBeIEFI2g,7618 +pydantic/deprecated/decorator.py,sha256=TBm6bJ7wJsNih_8Wq5IzDcwP32m9_vfxs96desLuk00,10845 +pydantic/deprecated/json.py,sha256=HlWCG35RRrxyzuTS6LTQiZBwRhmDZWmeqQH8rLW6wA8,4657 +pydantic/deprecated/parse.py,sha256=Gzd6b_g8zJXcuE7QRq5adhx_EMJahXfcpXCF0RgrqqI,2511 +pydantic/deprecated/tools.py,sha256=Nrm9oFRZWp8-jlfvPgJILEsywp4YzZD52XIGPDLxHcI,3330 +pydantic/env_settings.py,sha256=6IHeeWEqlUPRUv3V-AXiF_W91fg2Jw_M3O0l34J_eyA,148 +pydantic/error_wrappers.py,sha256=RK6mqATc9yMD-KBD9IJS9HpKCprWHd8wo84Bnm-3fR8,150 +pydantic/errors.py,sha256=7ctBNCtt57kZFx71Ls2H86IufQARv4wPKf8DhdsVn5w,6002 +pydantic/experimental/__init__.py,sha256=QT7rKYdDsCiTJ9GEjmsQdWHScwpKrrNkGq6vqONP6RQ,104 +pydantic/experimental/__pycache__/__init__.cpython-312.pyc,, +pydantic/experimental/__pycache__/arguments_schema.cpython-312.pyc,, +pydantic/experimental/__pycache__/missing_sentinel.cpython-312.pyc,, +pydantic/experimental/__pycache__/pipeline.cpython-312.pyc,, +pydantic/experimental/arguments_schema.py,sha256=EFnjX_ulp-tPyUjQX5pmQtug1OFL_Acc8bcMbLd-fVY,1866 +pydantic/experimental/missing_sentinel.py,sha256=hQejgtF00wUuQMni9429evg-eXyIwpKvjsD8ofqfj-w,127 +pydantic/experimental/pipeline.py,sha256=Kv_dvcexKumazfRL0y69AayeA6H37SrmsZ3SUl_n0qY,23582 +pydantic/fields.py,sha256=WuDGOvB22KWuuW3fXnS4Wvg4qX_tdp8X7BrAlza4sw8,79194 +pydantic/functional_serializers.py,sha256=rEzH391zqy3o_bWk2QEuvySmcQNZmwXmJQLC3ZGF7QA,17151 +pydantic/functional_validators.py,sha256=c_-7weWpGNcOYfRfVUFu11jrxMVMdfY_c-4istwk95Y,31839 +pydantic/generics.py,sha256=0ZqZ9O9annIj_3mGBRqps4htey3b5lV1-d2tUxPMMnA,144 +pydantic/json.py,sha256=ZH8RkI7h4Bz-zp8OdTAxbJUoVvcoU-jhMdRZ0B-k0xc,140 +pydantic/json_schema.py,sha256=-h8c7vsNGAJCIxR-n52-69Q54w38EM-j0AGC_4VGt30,123653 +pydantic/main.py,sha256=WZTxwW81igl75Y00zHJJmoU3qCNSy-1KCEmEsBPftiQ,84205 +pydantic/mypy.py,sha256=p6KU1GwPHazF7E5vJq1uLd4tHd6DE6bre4-m5Ln23ms,58986 +pydantic/networks.py,sha256=Smf_RyImQ-F5FZLCgFwHPfROYxW_e-Hz68R_8LW0sZ0,42099 +pydantic/parse.py,sha256=wkd82dgtvWtD895U_I6E1htqMlGhBSYEV39cuBSeo3A,141 +pydantic/plugin/__init__.py,sha256=a7Tw366U6K3kltCCNZY76nc9ss-7uGGQ40TXad9OypQ,7333 +pydantic/plugin/__pycache__/__init__.cpython-312.pyc,, +pydantic/plugin/__pycache__/_loader.cpython-312.pyc,, +pydantic/plugin/__pycache__/_schema_validator.cpython-312.pyc,, +pydantic/plugin/_loader.py,sha256=9QLXneLEmvyhXka_9j4Lrkbme4qPv6qYphlsjF2MGsA,2210 +pydantic/plugin/_schema_validator.py,sha256=QbmqsG33MBmftNQ2nNiuN22LhbrexUA7ipDVv3J02BU,5267 +pydantic/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pydantic/root_model.py,sha256=BvmLtW4i11dJk-dLOM3rl-jnJdQGeeQTFBcmEOq6pMg,6311 +pydantic/schema.py,sha256=Vqqjvq_LnapVknebUd3Bp_J1p2gXZZnZRgL48bVEG7o,142 +pydantic/tools.py,sha256=iHQpd8SJ5DCTtPV5atAV06T89bjSaMFeZZ2LX9lasZY,141 +pydantic/type_adapter.py,sha256=VT--yg4a27shSBzWHBPKz493f3iQ9obdkEkhjZKlE7Q,35653 +pydantic/types.py,sha256=nqdS-J2ZXqTh2qeyJOzBTBtHWyZ5YRFe8gaMV59d9HE,105431 +pydantic/typing.py,sha256=P7feA35MwTcLsR1uL7db0S-oydBxobmXa55YDoBgajQ,138 +pydantic/utils.py,sha256=15nR2QpqTBFlQV4TNtTItMyTJx_fbyV-gPmIEY1Gooc,141 +pydantic/v1/__init__.py,sha256=FLQ8ISp6MVZRfjnS7fQ4m1FxQxFCF2QVikE4DK-4PhE,3164 +pydantic/v1/__pycache__/__init__.cpython-312.pyc,, +pydantic/v1/__pycache__/_hypothesis_plugin.cpython-312.pyc,, +pydantic/v1/__pycache__/annotated_types.cpython-312.pyc,, +pydantic/v1/__pycache__/class_validators.cpython-312.pyc,, +pydantic/v1/__pycache__/color.cpython-312.pyc,, +pydantic/v1/__pycache__/config.cpython-312.pyc,, +pydantic/v1/__pycache__/dataclasses.cpython-312.pyc,, +pydantic/v1/__pycache__/datetime_parse.cpython-312.pyc,, +pydantic/v1/__pycache__/decorator.cpython-312.pyc,, +pydantic/v1/__pycache__/env_settings.cpython-312.pyc,, +pydantic/v1/__pycache__/error_wrappers.cpython-312.pyc,, +pydantic/v1/__pycache__/errors.cpython-312.pyc,, +pydantic/v1/__pycache__/fields.cpython-312.pyc,, +pydantic/v1/__pycache__/generics.cpython-312.pyc,, +pydantic/v1/__pycache__/json.cpython-312.pyc,, +pydantic/v1/__pycache__/main.cpython-312.pyc,, +pydantic/v1/__pycache__/mypy.cpython-312.pyc,, +pydantic/v1/__pycache__/networks.cpython-312.pyc,, +pydantic/v1/__pycache__/parse.cpython-312.pyc,, +pydantic/v1/__pycache__/schema.cpython-312.pyc,, +pydantic/v1/__pycache__/tools.cpython-312.pyc,, +pydantic/v1/__pycache__/types.cpython-312.pyc,, +pydantic/v1/__pycache__/typing.cpython-312.pyc,, +pydantic/v1/__pycache__/utils.cpython-312.pyc,, +pydantic/v1/__pycache__/validators.cpython-312.pyc,, +pydantic/v1/__pycache__/version.cpython-312.pyc,, +pydantic/v1/_hypothesis_plugin.py,sha256=5ES5xWuw1FQAsymLezy8QgnVz0ZpVfU3jkmT74H27VQ,14847 +pydantic/v1/annotated_types.py,sha256=uk2NAAxqiNELKjiHhyhxKaIOh8F1lYW_LzrW3X7oZBc,3157 +pydantic/v1/class_validators.py,sha256=ULOaIUgYUDBsHL7EEVEarcM-UubKUggoN8hSbDonsFE,14672 +pydantic/v1/color.py,sha256=iZABLYp6OVoo2AFkP9Ipri_wSc6-Kklu8YuhSartd5g,16844 +pydantic/v1/config.py,sha256=a6P0Wer9x4cbwKW7Xv8poSUqM4WP-RLWwX6YMpYq9AA,6532 +pydantic/v1/dataclasses.py,sha256=784cqvInbwIPWr9usfpX3ch7z4t3J2tTK6N067_wk1o,18172 +pydantic/v1/datetime_parse.py,sha256=4Qy1kQpq3rNVZJeIHeSPDpuS2Bvhp1KPtzJG1xu-H00,7724 +pydantic/v1/decorator.py,sha256=zaaxxxoWPCm818D1bs0yhapRjXm32V8G0ZHWCdM1uXA,10339 +pydantic/v1/env_settings.py,sha256=A9VXwtRl02AY-jH0C0ouy5VNw3fi6F_pkzuHDjgAAOM,14105 +pydantic/v1/error_wrappers.py,sha256=6625Mfw9qkC2NwitB_JFAWe8B-Xv6zBU7rL9k28tfyo,5196 +pydantic/v1/errors.py,sha256=mIwPED5vGM5Q5v4C4Z1JPldTRH-omvEylH6ksMhOmPw,17726 +pydantic/v1/fields.py,sha256=VqWJCriUNiEyptXroDVJ501JpVA0en2VANcksqXL2b8,50649 +pydantic/v1/generics.py,sha256=VzC9YUV-EbPpQ3aAfk1cNFej79_IzznkQ7WrmTTZS9E,17871 +pydantic/v1/json.py,sha256=WQ5Hy_hIpfdR3YS8k6N2E6KMJzsdbBi_ldWOPJaV81M,3390 +pydantic/v1/main.py,sha256=zuNpdN5Q0V0wG2UUTKt0HUy3XJ4OAvPSZDdiXY-FIzs,44824 +pydantic/v1/mypy.py,sha256=Cl8XRfCmIcVE3j5AEU52C8iDh8lcX__D3hz2jIWxMAs,38860 +pydantic/v1/networks.py,sha256=HYNtKAfOmOnKJpsDg1g6SIkj9WPhU_-i8l5e2JKBpG4,22124 +pydantic/v1/parse.py,sha256=BJtdqiZRtav9VRFCmOxoY-KImQmjPy-A_NoojiFUZxY,1821 +pydantic/v1/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pydantic/v1/schema.py,sha256=aqBuA--cq8gAVkim5BJPFASHzOZ8dFtmFX_fNGr6ip4,47801 +pydantic/v1/tools.py,sha256=1lDdXHk0jL5uP3u5RCYAvUAlGClgAO-45lkq9j7fyBA,2881 +pydantic/v1/types.py,sha256=Bzl-RcnitPBHnqwwj9iv7JjHuN1GpnWH24dKkF3l9e8,35455 +pydantic/v1/typing.py,sha256=7GdBg1YTHULU81thB_9cjRNDfZfn4khoX7nGtw_keCE,19677 +pydantic/v1/utils.py,sha256=M5FRyfNUb1A2mk9laGgCVdfHHb3AtQgrjO5qfyBf4xA,25989 +pydantic/v1/validators.py,sha256=lyUkn1MWhHxlCX5ZfEgFj_CAHojoiPcaQeMdEM9XviU,22187 +pydantic/v1/version.py,sha256=HXnXW-1bMW5qKhlr5RgOEPohrZDCDSuyy8-gi8GCgZo,1039 +pydantic/validate_call_decorator.py,sha256=8jqLlgXTjWEj4dXDg0wI3EGQKkb0JnCsL_JSUjbU5Sg,4389 +pydantic/validators.py,sha256=pwbIJXVb1CV2mAE4w_EGfNj7DwzsKaWw_tTL6cviTus,146 +pydantic/version.py,sha256=XNmGSyOP87Mqa_A9HFzfDcNippfnqfRK3ZUiGyBb4-A,3985 +pydantic/warnings.py,sha256=Wu1VGzrvFZw4T6yCIKHjH7LSY66HjbtyCFbn5uWoMJ4,4802 diff --git a/backend/.venv/Lib/site-packages/pydantic-2.12.5.dist-info/WHEEL b/backend/.venv/Lib/site-packages/pydantic-2.12.5.dist-info/WHEEL new file mode 100644 index 0000000..12228d4 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic-2.12.5.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: hatchling 1.27.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/backend/.venv/Lib/site-packages/pydantic-2.12.5.dist-info/licenses/LICENSE b/backend/.venv/Lib/site-packages/pydantic-2.12.5.dist-info/licenses/LICENSE new file mode 100644 index 0000000..488c626 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic-2.12.5.dist-info/licenses/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017 to present Pydantic Services Inc. and individual contributors. + +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/pydantic/__init__.py b/backend/.venv/Lib/site-packages/pydantic/__init__.py new file mode 100644 index 0000000..0121284 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/__init__.py @@ -0,0 +1,456 @@ +from importlib import import_module +from typing import TYPE_CHECKING +from warnings import warn + +from ._migration import getattr_migration +from .version import VERSION, _ensure_pydantic_core_version + +_ensure_pydantic_core_version() +del _ensure_pydantic_core_version + +if TYPE_CHECKING: + # import of virtually everything is supported via `__getattr__` below, + # but we need them here for type checking and IDE support + import pydantic_core + from pydantic_core.core_schema import ( + FieldSerializationInfo, + SerializationInfo, + SerializerFunctionWrapHandler, + ValidationInfo, + ValidatorFunctionWrapHandler, + ) + + from . import dataclasses + from .aliases import AliasChoices, AliasGenerator, AliasPath + from .annotated_handlers import GetCoreSchemaHandler, GetJsonSchemaHandler + from .config import ConfigDict, with_config + from .errors import * + from .fields import Field, PrivateAttr, computed_field + from .functional_serializers import ( + PlainSerializer, + SerializeAsAny, + WrapSerializer, + field_serializer, + model_serializer, + ) + from .functional_validators import ( + AfterValidator, + BeforeValidator, + InstanceOf, + ModelWrapValidatorHandler, + PlainValidator, + SkipValidation, + ValidateAs, + WrapValidator, + field_validator, + model_validator, + ) + from .json_schema import WithJsonSchema + from .main import * + from .networks import * + from .type_adapter import TypeAdapter + from .types import * + from .validate_call_decorator import validate_call + from .warnings import ( + PydanticDeprecatedSince20, + PydanticDeprecatedSince26, + PydanticDeprecatedSince29, + PydanticDeprecatedSince210, + PydanticDeprecatedSince211, + PydanticDeprecatedSince212, + PydanticDeprecationWarning, + PydanticExperimentalWarning, + ) + + # this encourages pycharm to import `ValidationError` from here, not pydantic_core + ValidationError = pydantic_core.ValidationError + from .deprecated.class_validators import root_validator, validator + from .deprecated.config import BaseConfig, Extra + from .deprecated.tools import * + from .root_model import RootModel + +__version__ = VERSION +__all__ = ( + # dataclasses + 'dataclasses', + # functional validators + 'field_validator', + 'model_validator', + 'AfterValidator', + 'BeforeValidator', + 'PlainValidator', + 'WrapValidator', + 'SkipValidation', + 'ValidateAs', + 'InstanceOf', + 'ModelWrapValidatorHandler', + # JSON Schema + 'WithJsonSchema', + # deprecated V1 functional validators, these are imported via `__getattr__` below + 'root_validator', + 'validator', + # functional serializers + 'field_serializer', + 'model_serializer', + 'PlainSerializer', + 'SerializeAsAny', + 'WrapSerializer', + # config + 'ConfigDict', + 'with_config', + # deprecated V1 config, these are imported via `__getattr__` below + 'BaseConfig', + 'Extra', + # validate_call + 'validate_call', + # errors + 'PydanticErrorCodes', + 'PydanticUserError', + 'PydanticSchemaGenerationError', + 'PydanticImportError', + 'PydanticUndefinedAnnotation', + 'PydanticInvalidForJsonSchema', + 'PydanticForbiddenQualifier', + # fields + 'Field', + 'computed_field', + 'PrivateAttr', + # alias + 'AliasChoices', + 'AliasGenerator', + 'AliasPath', + # main + 'BaseModel', + 'create_model', + # network + 'AnyUrl', + 'AnyHttpUrl', + 'FileUrl', + 'HttpUrl', + 'FtpUrl', + 'WebsocketUrl', + 'AnyWebsocketUrl', + 'UrlConstraints', + 'EmailStr', + 'NameEmail', + 'IPvAnyAddress', + 'IPvAnyInterface', + 'IPvAnyNetwork', + 'PostgresDsn', + 'CockroachDsn', + 'AmqpDsn', + 'RedisDsn', + 'MongoDsn', + 'KafkaDsn', + 'NatsDsn', + 'MySQLDsn', + 'MariaDBDsn', + 'ClickHouseDsn', + 'SnowflakeDsn', + 'validate_email', + # root_model + 'RootModel', + # deprecated tools, these are imported via `__getattr__` below + 'parse_obj_as', + 'schema_of', + 'schema_json_of', + # types + 'Strict', + 'StrictStr', + 'conbytes', + 'conlist', + 'conset', + 'confrozenset', + 'constr', + 'StringConstraints', + 'ImportString', + 'conint', + 'PositiveInt', + 'NegativeInt', + 'NonNegativeInt', + 'NonPositiveInt', + 'confloat', + 'PositiveFloat', + 'NegativeFloat', + 'NonNegativeFloat', + 'NonPositiveFloat', + 'FiniteFloat', + 'condecimal', + 'condate', + 'UUID1', + 'UUID3', + 'UUID4', + 'UUID5', + 'UUID6', + 'UUID7', + 'UUID8', + 'FilePath', + 'DirectoryPath', + 'NewPath', + 'Json', + 'Secret', + 'SecretStr', + 'SecretBytes', + 'SocketPath', + 'StrictBool', + 'StrictBytes', + 'StrictInt', + 'StrictFloat', + 'PaymentCardNumber', + 'ByteSize', + 'PastDate', + 'FutureDate', + 'PastDatetime', + 'FutureDatetime', + 'AwareDatetime', + 'NaiveDatetime', + 'AllowInfNan', + 'EncoderProtocol', + 'EncodedBytes', + 'EncodedStr', + 'Base64Encoder', + 'Base64Bytes', + 'Base64Str', + 'Base64UrlBytes', + 'Base64UrlStr', + 'GetPydanticSchema', + 'Tag', + 'Discriminator', + 'JsonValue', + 'FailFast', + # type_adapter + 'TypeAdapter', + # version + '__version__', + 'VERSION', + # warnings + 'PydanticDeprecatedSince20', + 'PydanticDeprecatedSince26', + 'PydanticDeprecatedSince29', + 'PydanticDeprecatedSince210', + 'PydanticDeprecatedSince211', + 'PydanticDeprecatedSince212', + 'PydanticDeprecationWarning', + 'PydanticExperimentalWarning', + # annotated handlers + 'GetCoreSchemaHandler', + 'GetJsonSchemaHandler', + # pydantic_core + 'ValidationError', + 'ValidationInfo', + 'SerializationInfo', + 'ValidatorFunctionWrapHandler', + 'FieldSerializationInfo', + 'SerializerFunctionWrapHandler', + 'OnErrorOmit', +) + +# A mapping of {: (package, )} defining dynamic imports +_dynamic_imports: 'dict[str, tuple[str, str]]' = { + 'dataclasses': (__spec__.parent, '__module__'), + # functional validators + 'field_validator': (__spec__.parent, '.functional_validators'), + 'model_validator': (__spec__.parent, '.functional_validators'), + 'AfterValidator': (__spec__.parent, '.functional_validators'), + 'BeforeValidator': (__spec__.parent, '.functional_validators'), + 'PlainValidator': (__spec__.parent, '.functional_validators'), + 'WrapValidator': (__spec__.parent, '.functional_validators'), + 'SkipValidation': (__spec__.parent, '.functional_validators'), + 'InstanceOf': (__spec__.parent, '.functional_validators'), + 'ValidateAs': (__spec__.parent, '.functional_validators'), + 'ModelWrapValidatorHandler': (__spec__.parent, '.functional_validators'), + # JSON Schema + 'WithJsonSchema': (__spec__.parent, '.json_schema'), + # functional serializers + 'field_serializer': (__spec__.parent, '.functional_serializers'), + 'model_serializer': (__spec__.parent, '.functional_serializers'), + 'PlainSerializer': (__spec__.parent, '.functional_serializers'), + 'SerializeAsAny': (__spec__.parent, '.functional_serializers'), + 'WrapSerializer': (__spec__.parent, '.functional_serializers'), + # config + 'ConfigDict': (__spec__.parent, '.config'), + 'with_config': (__spec__.parent, '.config'), + # validate call + 'validate_call': (__spec__.parent, '.validate_call_decorator'), + # errors + 'PydanticErrorCodes': (__spec__.parent, '.errors'), + 'PydanticUserError': (__spec__.parent, '.errors'), + 'PydanticSchemaGenerationError': (__spec__.parent, '.errors'), + 'PydanticImportError': (__spec__.parent, '.errors'), + 'PydanticUndefinedAnnotation': (__spec__.parent, '.errors'), + 'PydanticInvalidForJsonSchema': (__spec__.parent, '.errors'), + 'PydanticForbiddenQualifier': (__spec__.parent, '.errors'), + # fields + 'Field': (__spec__.parent, '.fields'), + 'computed_field': (__spec__.parent, '.fields'), + 'PrivateAttr': (__spec__.parent, '.fields'), + # alias + 'AliasChoices': (__spec__.parent, '.aliases'), + 'AliasGenerator': (__spec__.parent, '.aliases'), + 'AliasPath': (__spec__.parent, '.aliases'), + # main + 'BaseModel': (__spec__.parent, '.main'), + 'create_model': (__spec__.parent, '.main'), + # network + 'AnyUrl': (__spec__.parent, '.networks'), + 'AnyHttpUrl': (__spec__.parent, '.networks'), + 'FileUrl': (__spec__.parent, '.networks'), + 'HttpUrl': (__spec__.parent, '.networks'), + 'FtpUrl': (__spec__.parent, '.networks'), + 'WebsocketUrl': (__spec__.parent, '.networks'), + 'AnyWebsocketUrl': (__spec__.parent, '.networks'), + 'UrlConstraints': (__spec__.parent, '.networks'), + 'EmailStr': (__spec__.parent, '.networks'), + 'NameEmail': (__spec__.parent, '.networks'), + 'IPvAnyAddress': (__spec__.parent, '.networks'), + 'IPvAnyInterface': (__spec__.parent, '.networks'), + 'IPvAnyNetwork': (__spec__.parent, '.networks'), + 'PostgresDsn': (__spec__.parent, '.networks'), + 'CockroachDsn': (__spec__.parent, '.networks'), + 'AmqpDsn': (__spec__.parent, '.networks'), + 'RedisDsn': (__spec__.parent, '.networks'), + 'MongoDsn': (__spec__.parent, '.networks'), + 'KafkaDsn': (__spec__.parent, '.networks'), + 'NatsDsn': (__spec__.parent, '.networks'), + 'MySQLDsn': (__spec__.parent, '.networks'), + 'MariaDBDsn': (__spec__.parent, '.networks'), + 'ClickHouseDsn': (__spec__.parent, '.networks'), + 'SnowflakeDsn': (__spec__.parent, '.networks'), + 'validate_email': (__spec__.parent, '.networks'), + # root_model + 'RootModel': (__spec__.parent, '.root_model'), + # types + 'Strict': (__spec__.parent, '.types'), + 'StrictStr': (__spec__.parent, '.types'), + 'conbytes': (__spec__.parent, '.types'), + 'conlist': (__spec__.parent, '.types'), + 'conset': (__spec__.parent, '.types'), + 'confrozenset': (__spec__.parent, '.types'), + 'constr': (__spec__.parent, '.types'), + 'StringConstraints': (__spec__.parent, '.types'), + 'ImportString': (__spec__.parent, '.types'), + 'conint': (__spec__.parent, '.types'), + 'PositiveInt': (__spec__.parent, '.types'), + 'NegativeInt': (__spec__.parent, '.types'), + 'NonNegativeInt': (__spec__.parent, '.types'), + 'NonPositiveInt': (__spec__.parent, '.types'), + 'confloat': (__spec__.parent, '.types'), + 'PositiveFloat': (__spec__.parent, '.types'), + 'NegativeFloat': (__spec__.parent, '.types'), + 'NonNegativeFloat': (__spec__.parent, '.types'), + 'NonPositiveFloat': (__spec__.parent, '.types'), + 'FiniteFloat': (__spec__.parent, '.types'), + 'condecimal': (__spec__.parent, '.types'), + 'condate': (__spec__.parent, '.types'), + 'UUID1': (__spec__.parent, '.types'), + 'UUID3': (__spec__.parent, '.types'), + 'UUID4': (__spec__.parent, '.types'), + 'UUID5': (__spec__.parent, '.types'), + 'UUID6': (__spec__.parent, '.types'), + 'UUID7': (__spec__.parent, '.types'), + 'UUID8': (__spec__.parent, '.types'), + 'FilePath': (__spec__.parent, '.types'), + 'DirectoryPath': (__spec__.parent, '.types'), + 'NewPath': (__spec__.parent, '.types'), + 'Json': (__spec__.parent, '.types'), + 'Secret': (__spec__.parent, '.types'), + 'SecretStr': (__spec__.parent, '.types'), + 'SecretBytes': (__spec__.parent, '.types'), + 'StrictBool': (__spec__.parent, '.types'), + 'StrictBytes': (__spec__.parent, '.types'), + 'StrictInt': (__spec__.parent, '.types'), + 'StrictFloat': (__spec__.parent, '.types'), + 'PaymentCardNumber': (__spec__.parent, '.types'), + 'ByteSize': (__spec__.parent, '.types'), + 'PastDate': (__spec__.parent, '.types'), + 'SocketPath': (__spec__.parent, '.types'), + 'FutureDate': (__spec__.parent, '.types'), + 'PastDatetime': (__spec__.parent, '.types'), + 'FutureDatetime': (__spec__.parent, '.types'), + 'AwareDatetime': (__spec__.parent, '.types'), + 'NaiveDatetime': (__spec__.parent, '.types'), + 'AllowInfNan': (__spec__.parent, '.types'), + 'EncoderProtocol': (__spec__.parent, '.types'), + 'EncodedBytes': (__spec__.parent, '.types'), + 'EncodedStr': (__spec__.parent, '.types'), + 'Base64Encoder': (__spec__.parent, '.types'), + 'Base64Bytes': (__spec__.parent, '.types'), + 'Base64Str': (__spec__.parent, '.types'), + 'Base64UrlBytes': (__spec__.parent, '.types'), + 'Base64UrlStr': (__spec__.parent, '.types'), + 'GetPydanticSchema': (__spec__.parent, '.types'), + 'Tag': (__spec__.parent, '.types'), + 'Discriminator': (__spec__.parent, '.types'), + 'JsonValue': (__spec__.parent, '.types'), + 'OnErrorOmit': (__spec__.parent, '.types'), + 'FailFast': (__spec__.parent, '.types'), + # type_adapter + 'TypeAdapter': (__spec__.parent, '.type_adapter'), + # warnings + 'PydanticDeprecatedSince20': (__spec__.parent, '.warnings'), + 'PydanticDeprecatedSince26': (__spec__.parent, '.warnings'), + 'PydanticDeprecatedSince29': (__spec__.parent, '.warnings'), + 'PydanticDeprecatedSince210': (__spec__.parent, '.warnings'), + 'PydanticDeprecatedSince211': (__spec__.parent, '.warnings'), + 'PydanticDeprecatedSince212': (__spec__.parent, '.warnings'), + 'PydanticDeprecationWarning': (__spec__.parent, '.warnings'), + 'PydanticExperimentalWarning': (__spec__.parent, '.warnings'), + # annotated handlers + 'GetCoreSchemaHandler': (__spec__.parent, '.annotated_handlers'), + 'GetJsonSchemaHandler': (__spec__.parent, '.annotated_handlers'), + # pydantic_core stuff + 'ValidationError': ('pydantic_core', '.'), + 'ValidationInfo': ('pydantic_core', '.core_schema'), + 'SerializationInfo': ('pydantic_core', '.core_schema'), + 'ValidatorFunctionWrapHandler': ('pydantic_core', '.core_schema'), + 'FieldSerializationInfo': ('pydantic_core', '.core_schema'), + 'SerializerFunctionWrapHandler': ('pydantic_core', '.core_schema'), + # deprecated, mostly not included in __all__ + 'root_validator': (__spec__.parent, '.deprecated.class_validators'), + 'validator': (__spec__.parent, '.deprecated.class_validators'), + 'BaseConfig': (__spec__.parent, '.deprecated.config'), + 'Extra': (__spec__.parent, '.deprecated.config'), + 'parse_obj_as': (__spec__.parent, '.deprecated.tools'), + 'schema_of': (__spec__.parent, '.deprecated.tools'), + 'schema_json_of': (__spec__.parent, '.deprecated.tools'), + # deprecated dynamic imports + 'FieldValidationInfo': ('pydantic_core', '.core_schema'), + 'GenerateSchema': (__spec__.parent, '._internal._generate_schema'), +} +_deprecated_dynamic_imports = {'FieldValidationInfo', 'GenerateSchema'} + +_getattr_migration = getattr_migration(__name__) + + +def __getattr__(attr_name: str) -> object: + if attr_name in _deprecated_dynamic_imports: + from pydantic.warnings import PydanticDeprecatedSince20 + + warn( + f'Importing {attr_name} from `pydantic` is deprecated. This feature is either no longer supported, or is not public.', + PydanticDeprecatedSince20, + stacklevel=2, + ) + + dynamic_attr = _dynamic_imports.get(attr_name) + if dynamic_attr is None: + return _getattr_migration(attr_name) + + package, module_name = dynamic_attr + + if module_name == '__module__': + result = import_module(f'.{attr_name}', package=package) + globals()[attr_name] = result + return result + else: + module = import_module(module_name, package=package) + result = getattr(module, attr_name) + g = globals() + for k, (_, v_module_name) in _dynamic_imports.items(): + if v_module_name == module_name and k not in _deprecated_dynamic_imports: + g[k] = getattr(module, k) + return result + + +def __dir__() -> list[str]: + return list(__all__) diff --git a/backend/.venv/Lib/site-packages/pydantic/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..46a86f3ff5b909b0f218db7d597119bf4db8d6c1 GIT binary patch literal 14423 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/__pycache__/aliases.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/__pycache__/aliases.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d4d94a8e12140aeeb04480a448e4a99f414893eb GIT binary patch literal 6560 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/__pycache__/class_validators.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/__pycache__/class_validators.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..85918581f9f3ea0d7c1c10f44c65d64071f1cbc8 GIT binary patch literal 368 zcmZ8cze~h06i(U`&ntJ};A{t%4y`%~;<>nrqeBVia!D+)ZBmk4rEdNYf~%|er#L#< zO~k=XxXsCwvk1Q7{ruj0-}gKokASm1G!=I)zIR1${%^9}amhVkAO#FEuYjeOdJuSk zd)$A5D^xmY{Ah4 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/__pycache__/color.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/__pycache__/color.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..33f363ddfcf0eafe9852234b634a5fccd234ade3 GIT binary patch literal 30174 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/__pycache__/config.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/__pycache__/config.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..080b7b8e145d1b4d93c113e2e48a7deb4b7ed1da GIT binary patch literal 7500 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 kRCZ)K{#h-+Zg}?SrI>l zk%?>wF|Z+ZW5Q7h++g3=d-vRPzu!a7cF2LebN_o2wC4Xhi!JBeBY_emu<)ih_Yw~y z4}k~%6JB;Doyw0oH+!d-5RL_KZJ5<&9OhcgrVz?9WZ{JItkA}`$qS?N@N75!Y-U8b zUQfX?YYok1>f}uzEv@mpnjHOVLq7uxt^X;+G|4?vs75@}R zCvOvRa1**YnNW+q;eCJn-gCR%L|*ntU(UUK55Y>}UuUu7oqHrujszCb7?)8VVH6>V zAb!HjuDmgev&QYg`4yxCP*ZBbIjIUeNJ}jyV@RbqFI;BE$O6%rd-UPflp;WOFe5pn0YL-5tMWFi5PY%hAHX~ax z4n$o$+hv^Vi3((0t__d?1WJ(J)I*a~IV4s(==y;XE5MR!CYW#MyZ?XcRkJ!dTK;ux gTK-hPw_9F)#TesP)c-))TW9+rdFf<#EwkY(KgGRmZ~y=R literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/__pycache__/error_wrappers.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/__pycache__/error_wrappers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..51af470add1e8855a8586c9f8cc7afc3c0c60450 GIT binary patch literal 368 zcmY*UJx{|h5VeycN~>04U?u}gh87q>d)C#4H9gJ9qPLf->YJ2@ozHU3ducDq(>B0(TL_zFQOzO z5JCJz7pPus7N@nFz4I$b`haMWPf-*Fpz9~ORpSvP+9e_x2stb)`epMHZJu20c0a2_ zDJ|DC@WOlKxz12{ZOvJ_Qm%5YtmM3G{PnRSSk^f=B8M<)a=zTptQLH-wGhwHCz?}Bb2@6A!fn&u?i2#?||5bI1Sy?|= kC_BPtcvcB;8^L|Wl+ssn{6W&U_U1$VrJde3aV<=K0MU(aKmY&$ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/__pycache__/errors.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/__pycache__/errors.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f4b7dd24d549177c26a98ee63f7f537d301a53c4 GIT binary patch literal 7629 zcmd5>TWlQHc|Nl@?(!mDMN-slbn#_vEoC{j1<8sPijo`!3e`xKQf(NIhBJrcNV7BR zGqa*NWePP=TRE_s=%J7S$AF6js0I0wi(fWQxVqe2EY^wjS^ zbJ-*4v;W=G)5-8WGyPRdj4<{)`beHaR8dx6QW(3-Ojc#4 zVrFcmmZ@eHs%Pz7HHUZ3&esanLan3PQ7cx9vMq0yYMs?iSufaKweD)StasQwwJp^x zs29zW-COIc_Q`su-CrB14xrvu9W=W$j1Sz8IeD9zJ?~_zL%e8i*#=s5Ylgkd%-&nf z?7N?dI#q`ytsk@jKFmk%=VJP(qz{5V1p2m=J|^i~K_3QvdrIFS=_8$E_ z=0wU?IG8k^snsz=bJ9_XSkAzo`r8;i%>j#7E!N$SzGr@>KLaRWUmDz@E zFIM861OrCH^W9qIDj2AElHFj$aZcOdnlO z$DVYr;xE>Duzh`t!@22I>_~0F;QB^642!Q@Lkfsi3w9d1ZR;~OudMF@E_{717@+k` zv>ARSR%$R@gM{pe$%+fAkn#+6wbPR=wrnlvGF)fYnybvX{(P`S@EXRNm1_&SnDc^d zh9!)Kt&57_vs`e;;IZHyjaZRFE3*(?yF^FZJ}SB`xNa_18Xh-;ks00Nm53k9@qBU! z-RI_`p+;hDl@@1@Mj{o-1scvZ$6auwpdWQx(*7#a2!dS(mhh8#rSc+;Thf<;!Bng; ziAX+PFxn!f`yjPr%k3@1Beq=Q{=91jL+wrVh99YYM7XfDR#RO-M%S!*phi1|Z&^@x zz(pn6bZf%xtx*x*u`VoU)(wVRjn@xVJZlby*buyZKP}=|G`?-Ewzkjl(cadueX9;b z+c<$23@4I_bpo@Hc0NXBMK|?25UCQg+;F6d`=l_U1^EqM=)v}e!?BZwwB~4JiYS3< z>b@SitL0emSKWq%$bm2&+g%98sCAy)Qg+ZCGpbzIMX)B{v_CV}KyEO>^lP3;m%Bl*=UB+2eLEz1pN;PZd&CD$dxCJwdcYZMk1YeJl-?VO6 zPOv{RhgAedM) z4WD~Qs!zjp69pO2V)RMBqG?1caDTA*#05i6Th&XjG6L!R0hB;agAvQ;9 z5<4(P>_p*FxW~R8y)t=pdchUfJgA>fJ6C<^%rM*r;0kI-xZu+>FbwXP)8p5l zo26CIn2~M@AC%)r5%{RwWlQWT-W#8r-JmCeYiqnf{WqZ_+fw{Edt&VEFPQah_D=2s zD`%zxwX+kk8>S_oaG?@%iJFZ6>U9e;QOj8=Tq)*o;N+=G+NtyB&z;v!o}0X&T|9rb ztcYFU%cGsCVmHdLL(@FuE?SVL2kQhS+g_zHM^QjdUA;d%^7@fx*N)}Ek-Nw49BX#( z{_XJCUHgvxqgR{zPW|%qUpG%(ZdPCYsA@c@8qLdQbC5T?x!8l@Q{_U$S{BnvPFuNJ zn-wmpQ?A3qg5bblC(O}TIU^p&4B{~qCE4P_Ja^Q2V6IK5lqMQ#E79;E z20@KiCgIvqW_m@POB31gFNQ!;>rs^!C8=!!c_~Jol*lM?ZPKm7;Ew-Z|q$5Vdyw|8h{VLIN((A-C)QJ!< zENPk)BYcnCA2@h3(yfZGV1E)HE+(1UL>k3Y?0OA7JwnpY;FN?~Zlm zk>eJ_&%94%#hY&m+Cl;oK8em2?u z1-6g1M6{oYLkjcBBIR>6KGr7R^akKwYhDnZ0p#f!)YnW(!I= z7koVFI>-@xRbOX}a550SM2J_CV3|hC2_)dHU<-Yyq(n{n@6nBu&u~OhxiB|ld!-TQ zC0uQoCgu?C|0gj-^UxEN#-DoP$?>O;m!A-HZ29m?CrBp@GXj|Daa|bm z5+=j^oNya;I^G(#7k0LGB*!NaI0^&3loCXkDmNWG{U!1n-_W@McDzd{ZnBl3Z0VG; zJh=1j@jJ(FpL|$geS>f1ermk;)KA=B_P)?8zVO*vp7rhe15?oN*MnQ{9=UVmt?Bo_ z@?LQN_=kfpel$4oU~uAtJs%F9{K3hUEOmP1^+> zz&hIkYYEMHKyyxzaDso@7;GdG>y8?o-qcy$vI%-+1d8INY5=H_KB+U@U*N#)ONW5d zrh4hwFTvnH6=GA^1apLN*qE|Pv5g>>QmE*89l7J1z>6hiGf>4X8H2nD{R1^njv-AWmoI+Wt>h0sWGEt2pq_uWDNs5R{9vOg!~vH~07qJn za*#OQauqn)9*61t;<*U0bawnpF@s_3N=#63f{IBLF?O{F&BqhGigJn#S7WK}-@@os znsJ@(n@@aADt{tU#z|V|6crm4N)i@S+`<3q5Q=t%o=`}mC*rh`y8YQI?Z+g+o&TRo zzj5K*lp5XV$P=m5XuF>OQZ!5Q`@c2&Sfbf8o7`%qiv0=A^>r#_ru@Y!B#87ZPf{d9pbI6$sW`|k)aRIjlCFIbZ$I#pCmQdY=ytc;m)2xf|l%_!*p>aSa}H$8(>?wX98tE)g#hcH_Pm zci_>IVTrCCH5U_yr6{e%g;7|P2XLz8aks78!LDSr@6cW9chbw}11e5~-~DblC=YLP z*YbW{tLb$k3y~#Hnz~*GWkVpL>>Pmv=_ShO*)08BN|VXAGbV!1)nd}S^;ysKwJPdK3jyP)MCQU7H?6mLID^# zWjk8#OMD9V2^)S3NImLj80Jl(XoJe%4($2qV;}83{9y0lpLc$^ce1(X^aoD!;^mJn z)*f7}HJybA7jHCQ`I{A{EGgeo@ajLWtQ6S5@JbgeZTllDlsctx2Yf| z+tRnqQ#9If*sE!+9eT<6e$)6%4kx|tUs3U%L-E<)vyXF^z|z*omq!mQqr~4(dAWc0 z!=8>83(ed}bKBun){!rKI?$2te27}av7Dy7SDwh}(qXni7sObdEEG2nZ7hlBiByQZ zC)yYprJ&Rv6DD2X-cI9&5o5ZHu~JZfAeSOnqN8j!DMsm*PCo$dFzgq%)$JV z53`4cGx+{=Ug=Y25qGIvdt6bDHAkO%@5~xQZLK(_9B%G??%%96hT7WEB0k3symxJl wp|&<$R8A<({m;|a2_^pA_gwNhsB|{>JiEs5et3ZOs_zy*+*1C#E@{613zixo%K!iX literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/__pycache__/fields.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/__pycache__/fields.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..64e1aa0c045dfda2ebd4a1746991e2e412315c18 GIT binary patch literal 72925 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/__pycache__/generics.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/__pycache__/generics.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9ab51e7cfc8247d5ad1c5686507b849f8fcfa3b6 GIT binary patch literal 356 zcmYLEJx{|h5VeycN~2a{U?u}gh7=GJ2v}GV6Y3CIa$Wlfri~rhZc*9#57<~)5kG~I ziEIclupxD0!cmF1;qKk{doSH?2YK5gC-UCMk2+~A`~%A!4<3*}84_3o6I=vYfKh-T zfbbcwrn1&NOj>sbm)8&vb5LL;x5K#5Vmg6X+L*;7#>b^Lt|?v_UBrX^{#Sh>!PRCC zjyY#&A#=l=)aoKxtJWzMnp0YJ{_CcuR<$WrtN`DNC~bD>6I#}ceggr0d#pblbI;wi_7^kH=yOe+m-C zIYJOPk~tJ@#=;ZdulK!t?|bQV+Q4HMAIW>4KSHxY{8ub?eDMG{=mQRUG=Wvrk06ME zh(!Dhms|bTJkDCTy^Cvs1|zH009Be#Cjv=}C>l~WuC;Ni;g!)9y4)+if;@xGW+@zX z&X7u$hB~R$S+>@!6T&qkq-p=pO|aD@geY1GPo;#cwB!jaf}5Z7lLLIC&DhqI39LrW z=9Do#RZglhXW9rH3<=|t`YV_FJ}>p7=>o%O;mMLlnl!{tB6CiN$R dZM)^ecMKtX1N)yKd+%;PCa>M>E;SpT`2`%NW|9B^ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/__pycache__/json_schema.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/__pycache__/json_schema.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2b7ae54f2f1c8691a5a5927d03dce9922a06796e GIT binary patch literal 120011 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 MYQQ6VOuU-E0gyu3_W%F@ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/__pycache__/main.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/__pycache__/main.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c599aa7b4aa4265a6152caa25f533ca0f6c7672a GIT binary patch literal 77302 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

    GH|li9rcrB!p==7US6>yy=u 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 x0z|jqMooaSUj!&SMu4(s1X#o=I literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/__pycache__/mypy.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/__pycache__/mypy.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2a8e35e09e8923e5471f5e38a9ced51f4be85147 GIT binary patch literal 61637 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 `cG$) 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 kF(*Sag)DC@i=o*j*@Yr90TfvWlvN;! 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 Z7JNN&^ZQU3`IVdAnd-pjE0|gN{{brr)&Bqh literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/__pycache__/parse.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/__pycache__/parse.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c16c17c2d944f7d082bb92861c804234978ad5b2 GIT binary patch literal 350 zcmYLEJx{|h5VeycLZen;(AYfrdEFgx;lIz+>Fm3F}c8ki!4`60xMf?;- zCbA*Kz=qU~35QbghWmQ=bnl)!oi_65kpp?>^Lx`Q5&jkPEnnOtf%-^b5sYye^aG3n z1ObFkc(K)Q&BC;G(>uF_WKc0`e{LFIbwsIRC3q^Pbg89}Xx`ZQK0Vqa*V>G1#W)ak z&4=ivo8HD|%`-p#S7%rN literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/__pycache__/root_model.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/__pycache__/root_model.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..49f215ea95bcd3b969e9e15bea72f5f3c22e5c5e GIT binary patch literal 7811 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/__pycache__/type_adapter.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/__pycache__/type_adapter.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1d20d6a4bf8e33f92e6bdf6c4be1db433ad401d0 GIT binary patch literal 35547 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/__pycache__/types.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/__pycache__/types.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f67a32c99016b138819560b22c1eca6b71aa39bb GIT binary patch literal 96768 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 IL^Sz-0lg()SO5S3 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/__pycache__/typing.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/__pycache__/typing.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..73288d650013c793f12dcbcb936d2a7e9743f8a2 GIT binary patch literal 348 zcmYL^ze~h06vvbH#Cqip9Gvao(xFvx6LoPFCvhl&TrPVYgXwORUwn z7NsUuD0!Z)b?X>2MKSJ%|9$PDx(H)QYVJlc#w#s;0!z>Gb8&izZj`P}Lnue`+M0|| zs^-! a_Z>nA-@w5qNZ-fXkJ0Nmy^HmRoBRTS0A~*X literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/__pycache__/utils.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/__pycache__/utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5fbc66bd4ff2ae39da702d8ffc0092d8507671d0 GIT binary patch literal 350 zcmYLEJx{|h6tt5fLaSC{V8#PWhL*B0AYfrdEFgx+lIz+gm?m~)J4IpR2Qag;B7O=Z z6WI`AU_*L@!6$7lhVn|PEf9SnF%B>8M2Mof@KleGR!bhiqOtRRdbEeHwVBz1GJ(~V zvqQ?5E|rri9WreMZVU;<@n|m893RUmw$h2A7tClXEG{Ze{W{zJeP&ctb+o^H=+N~1 fjmEd#@Zl?j5Wa%l4-mf%HXovwL44aYYo7T58MJ4F literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/__pycache__/validate_call_decorator.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/__pycache__/validate_call_decorator.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dbb3ed9ac29e2cb4d99b0590a408c95f59e79c4b GIT binary patch literal 5446 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/__pycache__/validators.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/__pycache__/validators.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..61f0a87cb105a759d30e0b1938520f94ba9c6a2c GIT binary patch literal 360 zcmYLEJx{|h5VeycN~>04U?u}gh87rD_*z&I6GEu6RXpFmB!LonJ#VE?6oBbK2N(lxZ0sa&rYr$V@=`EA&bOC}hIv`F4;QMA iP1irF$=eO@enO1#J39D6@kf92sr}ZE@4IHrcm4pzS8J#M literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/__pycache__/version.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/__pycache__/version.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4f32b2bbe638842d7fa1d66854b437449e3ca951 GIT binary patch literal 4796 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/__pycache__/warnings.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/__pycache__/warnings.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..304b24de6f579298c1f1e8ec910fd211995231b2 GIT binary patch literal 7212 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 a^yB}|j=ZNg@9BBsrEFif)G!0o#QlHDmjMz0 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_core_metadata.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_core_metadata.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7e09285700c440c9c286a544b95308b0660e9105 GIT binary patch literal 4613 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_core_utils.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_core_utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5780f32492394d24effb529a26353a35613c9266 GIT binary patch literal 7710 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 J%(4s<{2zG-j?e%A literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_decorators.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_decorators.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f69985be86598140cdd095d76367c058c06aa3ce GIT binary patch literal 36756 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 Oi`Dn*@dWsYT1$_C#-_?n!B_qkxO=V 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_discriminated_union.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_discriminated_union.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a99adbffe385aca83df3101ddf5229e6765b2a85 GIT binary patch literal 20844 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 b-?wga<7L)N)zj-{3f#B$J+e}O$)^7kaURQt literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_forward_ref.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_forward_ref.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bd88638813ffef00510edf4d598f2834790755d9 GIT binary patch literal 1302 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 TFZn5kvE+U|92!uSAoza(>T2gi literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_generics.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_generics.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..47cf3fc28b410de9918b67174c7ead71df0adadb GIT binary patch literal 24329 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_git.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_git.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ad672897704f63c5a7fba96b9e421fb2538b7442 GIT binary patch literal 1508 zcmah}&2Jk;6rcUDy~(5vBsCuek!^}fR;q0UE+`7LRVXb8L8SE3)Y59bGqHEG-dWAe z+OgF`gt&0x7{m#2q6!jc{st~FsbsoJC8WZETSa<6J@IC3hmZ?T+L<@+{pQWQ-@La! zpF1~=K$h$81&)Ex6SbI#K2o&f>!9o*f;JJ+h#qNeeN)$zZbZhW0kavI?ZRdOY!)ee zVQv=56e+@7BGaSet0XyfDO92KdS$UOF(Bj=_t3 zHB7_=CFipb${xg!CwzwEf|@|ptO}~BPuSH^&$x`_2_RI_&d8gH8ydQcdZsK+T>sj- zXvesVx|&nyzp>`Uc9+^bjmIw{ZMsAKRCDNYo2_s3d1h?T@k%Fz>B|J{`g>h;~~B?#PG1-Rli zD{?AR9%p8QvB=T+Ys&LF45v}KH8bF9&Qw-%UBZ0V&8A&2| MvzK(Ot>q#90e0MI5&!@I literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_import_utils.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_import_utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9972711e49c96014b0e7752175f0135134277eb6 GIT binary patch literal 821 zcmbVKy^GX96rag=_CrrOMX@;+n-seucE@Sqa_XTjg4Y-VA)A>!<4!)9Nlq3OEc^>> zY_C21Q*5*iEGS}Ox4NB`Z)Ot^?Hrhw_vZKBZ{F`sKJ@z?1nYWmGkJ><`YMBV8I7|p zzg{aqZrY1bvtj%4BdSp^O}4 zv%I!AEi0aJ3kc%oKK0SS>af@6!GIzRDnQXIgwad%7VbMsM+p zkS`xd9D-Tt7~>_nvP3&y^sS{aSQ_5SLYlqObbR6D>dA{wgBw2)_-nmAUG-Y;AN+@` HQn&sFLHodM literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_internal_dataclass.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_internal_dataclass.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5eb216df31e4341d3a7b5c0ae33065498100bf5d GIT binary patch literal 342 zcmYLEF-ycS6i%9}O1T^KCKug=4m}YZMAXIY5GSW2P;yB;a;-^8(jFb}A9VBng1^N{ z7o{$OQ@4ZLoJ_^ygZIAg@xG6b_dFN`z|{%96qUoTcInFdBbzfv9svUkreFd%n0J>> z>5zE|20;4^v7UevuY>}$GxVEQbsKsOa@e$SwQo{o&0UCUWJ*)_3$Be&G8Xb))xqyE zwmRoeVAGnvlk0Q5P&zRgp&ZM(H4&jy<T5ZPYF%9WO!6?S>PKn#YR{jIYUBb z+~BNa#L4Ng3$a{FlK!)p5ld)Fj2UHRy>s!PSf27L-FMm0wK;NQjUa>{AXsmK-u4?B bzMx^Xctr>Ad;6=?>To&!+#N2*y8Z75NGV@c literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_known_annotated_metadata.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_known_annotated_metadata.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..30af5538bfdeb5b6e1c44a43b92d1f2e2475f11f GIT binary patch literal 14224 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_mock_val_ser.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_mock_val_ser.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a49a8143342ffec2a7b56359019aef5c5ce5f143 GIT binary patch literal 11091 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_model_construction.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_model_construction.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..077cdf4de6a07c6ad4b2e1f458bc6e3f7294db7d GIT binary patch literal 35103 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 z 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 YFI@C+hMZ3gF5W{;lk*AL*n0Q>1ILFMJ^%m! literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_namespace_utils.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_namespace_utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..da0d7e2b7d7b9a7894695f50ff67b1136859920c GIT binary patch literal 12311 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�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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_signature.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_signature.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e60219746683a583cee6c6ba4ca9521b8f79559e GIT binary patch literal 6759 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 wzGAWsn^~k|qGaB_j0R{Sj*Z=?k literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_utils.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4627a7dc82da9f596399678beb2ac8d0c4891993 GIT binary patch literal 19766 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 K9|UtIng0P`*c}%D literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_validators.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/_internal/__pycache__/_validators.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..63eafcb3db9580321d46d8b94e813ab9a9990715 GIT binary patch literal 22959 zcmeHvd2k%pnP2xDm;q*h!F>?`n*a!4NDw4=KqMqm1TTrC2wvbdAUGJH8{mL*Ks^H< zBS5BUR|%9<5iQFWyr$QT&9dc{QsH{HHr}!-MOiLej4IIE@C}LuzvQAYJ$dETO z{ZD@1>tlLAkd&+~um4Dsc>U(}yZZaS_g(LM{qy|%JPud;>8-)gA&&bs{m`#+HN!7# zvvJ(3+%Zn%e4NOOmJlDd_^dqTts$Gw&h9zB9Cmm39PIA&IdQjzY~fsAE~{$~<%L~7 z7t7~_+~Is*KFd2o1!0fR6E5@>hKqbf;bLELxWrcyF7=hN=gyEbT;?kam;1`Y6~2ma zrLQtv<*Q=PazoYOWxi$M8ea|jZ4K4>YB6qJs4l$Rw>&KPgzyUA3iiwustwos>cb7b z2KL(>Y7DRRtz`N9P*b?s*Ua(-p_Z`M=jFLv(?4;O==q|}w@T~~3vpj9J|Y(3-YRYu zi*a8gZV^jxZxcJkQry>CIH^J`lh#S?uUl0(`qqn&isg8=L3~WCz?@NQE`{J9QVh>-J*c|R&kHG0{3m= z6JkB?kBd)=4Y+R?_lk|UcZvJNmALN^_lr%q?-ZXBn{nSI9uQk_-z|2FUflPH2gOym zKVg1v%8Q4@)hK^bJS?{2zE?aVuEBkuv{l+BJuYpRx}+V_PHDHaM{K*E>)S7`m7WsU zJ%-noDkYCpEEP$mQlV5blv9N=-vN|uMCm4!ci_n*c(z$8k+uYLeBEL@+OB79og;s# zLe88@_K_Rr-)jC-l{!bhwPX*UwY2tA^y?hCx#S!^YpHYOJ4^K2BRNO@YRPi@$Q$>T z-=~kI>n_=E(B(TJZU81X5+*NMy+;!-9S?+pVjv!sg`u&?U_2O&#DpRIip2vFF(8XV zC^#SocI4X{XBmp^58j@sL5`|bWGKiA6Fc^)* z13`2cWNl*9C>)4fy0>$+7j*v{dT%eEb_F7lXgt8?(~aNGqter368c5nu}c~Zh65og z-XjOtq`f(5*WN?tH+G4lEX88!eEP9B5|`wmz@Vf)>z3jdqVhTRqr+UWBfDaUR?%xu zTe~8c($1ZMP$)1ElG2VI0O5E*PTP+~0I9TXFc6D-EorAO8j_U<7Yo0DJ@^!~W>Nh%^|Fp`=oUvVSmuwxWM1D1}6S5R<~QT796StluZ3 zh$J)MvM~oO06I^Q$CZOW@J4>28YQoCalM=y=U&(H6PCEfJvnaN5{Dd8uQ;`3*O29P z>Jyh-70*?39FtO_b=)$-q?=x<-h;f(k+1OR)2%-p<78LdqyI9^fwOSqyy-XkjTh+k z(8@AyJ<4UxvrvC(%#GE#XS961-ndnNj1TC_wyJ zM}tz!`Bp)H>=n)iVnQG!O9AncFd#`0VGsl+iEU|jOrvstEG{P=ZGMIpoj(!?OB2n4 z-WS@+l7Q8LK0?t8Sa8&x(YGzoR|Slj5Obg=<6qg-yq3~KNf`wJwOxsTjj zarw1#siOMJ`#y4V&f;sUuE%cfo(fGnR?iizm~~gry7$iJS5B>(sa}(;UZc3%792KD z-aKc^&6_VrgIA6v9o2K?)l-kA%9|%$|24n-+B2#AhRb{AbLeSL(or?*DVxln%PqOK z@1}h^x9JZ3oXstHWh|LnGv_J2cKn42#aZ)V4p&$`)s*tAP@F3kFgtG0SYh};JLF2MoqjKb2q6e9o#g1nmA=VvvSJ5aU@ zf3cHDE^~8^qH8O!mrOfq=PlOUQGTwZ`89j0qz#Cj&*KWqCfy%@l*<(^`z^=Q)8dsk zB1%V(a^lQ%|DYmDss175_;9NDtP+VT?&u%ptyJx9j8@9adCR$P=62;+U#sfkt#9#m zWV2A{KqZF4Cd~I$RW;|r`~=SfEh7fHP)oaB*X|?Ka?vFkEC)>2V5H*~9bKaB99~;4 zh`aQLqJ5nEy5$>24PvJvPb%Job=(>=*UVX5GgoD*nK5lkj_G7$7NcJ$>(>b~EYZgw zw~ae>0tF%37$F+$9E3P9VHX|a*7KZv;vw)b*uLI3M2JH)dOr>LPUK8DFnW<*V?5{U z97K%c>)bbtw-~gX;>6qu`?Gd77en}9E-;r)aS@wN-X(i16Po zzaogycpRm)v|>W+Y;-InLK+N)#zYB>e=r)tx*L$7wMo#)Bw;8BE(!fh3JXEf(gJbq zM@*F(n$FgiM?AWvhqO5Sk4S@1oS3E;6-2Octje)q>@0eYUmzhB5FkA?bq~6s5I|8J zi+5lwE(sUTq6P-X6wntWmh@3-!MEMfAC=%toCC zBrIbWm?@KirU|hzq2gdh1cB_?UkHXmcrBW~6done2F9S1K_MbRd`X+}(P%5vgr$pt zFa%<&I;AMdTpEyZC8pB$tN8H~e))Rw6NSu>!fZF&v8i+|7 zlxj33GlJP5pmzhtu|X*kkb}{f4&7|j81_h5T`C|8=mRU zW{+uF5IV3l`qBq8p_bkjV>hcWDwD8<<)F)1wOyL;{0%)wY*Ga^EIE?i23I;8I8Vz8 zZyAG$2-r4vHb06bF(?Jk19geV9@GqQiqLwzqyvc*UsLNe-}W2QmAVs!-BEKLbX+pX z3`UJ12-H$Ys>0FgjkS)6zJ*4e4?@`=FL&1338j>RN1}ZN(z|7e!<1L*d zvug5ss^NeYMr*#n zAolpHbzAyBv$xzSs+lROPZrguiW+B% zRwav8y|y7$wD$78IY-`P=NCRVRrD^@+JY*j=CE?4PdVJLR0mQ81B!FtPI1lD;V-SZ zy#JT3a#rD_a!OQA4lC7XQw2fA8JxGd?1jH9s+)QyRkV6C=c7u_=`y;UEv=h+`b!5U zb4mU3L;b3r>bS8bRRYa=&AgK~h_rJ4KIeaA5el+QZ>Q+1TIdqp_HdnD)S-V|n>$+WZ`*CH*QKhvfRdMVW zg~vXgE2)DrZQ)V!wljBUsr~ID3(DUv;VEBQO8FK$JzbZ(tI+!P zmf~G5>yKS_*wTFC@|1)2L90V7Zt7GJvF1>+Y6fZ24g_gY~FK-`f*#!SDv%lDFbs4FKVTQz>C)$%&zc8r_0$nc^ZQd=@Z zK(41^4=t2nNTSt2oig43d%WC?hcN<+ruA3qgGxaX?HNl@K8i|LsPKPXsnqfJ?VG*!@}ID6zZ=phRq z1Zjp3H>UDO;iJWjixI<3f_}9tgOx=%%;@!57%=y@L|az|b6NP*DGZiK##v&F=+00< zHoi^eR?(){2OZeE(}g-pz)~44B!qiuL6ep`b`RjKF4)9mK&I&3b z-C90O36Y6>1c{j(%FJUk`AVKl`2?!HNL8OkvX~a;TxHkJ&6InS<=!_oOuN?3meeWk zx(|w1DovY}&eN&lKE>Uql1j;R?#j6gnW%+j)49#?87TD|m5!6Cf>Vm~)c>a+z!~WI zqv)qt$02h@sT8yXH(^i71Y+#r{sbf+ro0D2A+mXZZX*-#&(}dGOT*H|#HxE2ysGTt@mMGz z3(`d>_^}vl9IuV7^|V7{`0_eTN%i#b40WdEtuB08{p2Bubt1XUK?AS{_&HC}ONpzA zspgcYUUAlcJm<=PY4g?15ajd_?0l`V!JjJVSDgJ&1W#8 zkGtzUPnE2II^=efYKg$m6@b_4Ba2wD{Yk%XyCm`djz zCx36oV|EXdtjOx#Br*rk{QLM@*nvc6lh42QlrUy&T3gfWwQSO|gE=+^|=VKjM@ znhjDSBFR!Hj79t}Lvo34bYUj|77`Jaw%G-TMKB(OiApB+1!z~$;IN|?AYVp5iSNO9 zKQyH<=2l3$*@!EI4_c&)a9xHdSdk#F1CcsSIM z`DvO3v$0`wvIP-Q_v;?CAhas_f*{lAVd&cE*BY77HG+0O!Qa9zBy76?TLi1G|M6?# z&l=_W{^q|d%Jo^8P~M@V=Kd(}fS;1>;_4_T&+@}iZuDzHc?9i#L2b`b^5?cfyVD+Z z4X{lw+QLpW++Qphm2{vGCw>4>suuNa0t;!(AK-6cClXyIOiVl0WMsl=$b_1y-jv6y zIK8?|Kp`nL8?NUan!o$!3fT^IJMqDg?Z66wx=EFE$dWnsFvyzvHbHg_ zE&n&QmMQu3Be=pLEtCQ_xQxxZ;Y96{6sK3yAwtIN10YhY*EfOUBAR@RznGcGE>1gI zGDLO)L{>57N_iR;XQNJJDAWwEW2u7Uit{)T*$Fd|p;LBQk>ZbE*n^B&r+cuD9CKy1 zQ$=G-6gz0}rg$yTd$F~GeHDLXEIc4lREG_l24~aGU`%}=mtip_ty4wQu4Qut!j0vrf_BB(KI?K{elp{c zKvi}T(AoQuMq++H*!6}Luw-C{HCvN4?e7`k9e7th@qQ2d+~hEqF2Z@O$$hpT(yzyo zWP(;`*W>9iY+cdTj|v=t#SpU$C;O=d3nA(y4DT$$nF4<74neCZ=sPGs59{GY<3ovA~ezr)TmPQO!x1Yd{9t zLLLPataxSc`lg!=N?Fsiqj}a-IOzmNukkNDa=BYYpMe%MBE_Ad?>sVO#Em1Cg*H`V z6&Z7m%rBFfVUQzs=(WC7!h~68LpSV#(cys!XKXTKE0n`lsA)6UFym+^e;6?+U~qog zAxm3^hV%P~XTBzGr1r&!CddC3{u% zhg;+cOi6wYN!G@Fxp`0%Q+OT~iwUaa7a}{)Za>1$78YIG@p8^wapR3Mx5PL1-IjmY zt!&z#Dt=0FKgFO7-cU+L$r12|3Z?p~cMij6TzM!}a9D93CjM|lvrMkk3fzs#%~lrd zgdy0qG$Ky_sS#0}1rsc#KnUoN9)b>ODRjt_crmXA{C|af7Vwv64HT9AY%CKNUP6my zgaz`*nXz!>We2dJtlaX0T|Zv+&XKpOVE0JsCh~L>_twk%t~mG3?wZUfOHlZ$sJ`Yw6yEWJ(l-yHj49(@p#H&uKnd->X8$d{Q~ zn@F9UsT~Az^5v;arI&|hGx^N(j}vR}yVdvOeeXPz+SRLU)Ew|xAn#Rq`!VJC3FX*H zrBd^o5_j)~_ID3kA@hfcSK0)~_K{}1br873=c_V+CxJW8X9RGju4uh(=uMwM=-Td! z3hbBU#-mX`f_P-89n5tHH8M{P)+PNXofi&9{Me8lhGLnI;AY4I?PsF%frvAjErmBo z>Fof9Dypv{r;CVhBA+E9N;Bh|Q1~rWdz?@hK!#B0u>1JA!jfxUU(T6Y^=@G!@Hktz z?6oIucN!sd$=cxstEHr1p0nf^AWpKdD8s(cn8bCDa_qR$b3&=qc2WqXJ_u}bKN{-XO}nK8ks(NTsd(v zb@WuS(6?Z>67sA-9=7a1G4kYZW0WbLfTNq(u|^VhZ6AVLzclEfEe=Q#2S?0-*KMSj8-sW9!R8tU|f%@mq$ z9XEDH(T{E1I%Hw-hK2gO#EbRZkVR9}$zEg^IM03AciE88D}qo2^au0AYyjbn2NLxjs9??gW^K<}s$Q&FpJc!w3i47y(%$F@ z3%@h%Lf~R6JNv5Djb>j-$nvYa2`Ps_lGnFmL%9d2+s>%EhJXKR`W~$dEtJnQ)!?dSEads%4jyom7Oo=yH;)R7@ zRykEWQ?({pwI)^8Hko(FRdVg==eI)C z*T$|#xVIju+fkM+9*v!)AEDO$R38>NZJDr|Rh=?qzCk6JshHq~1pmw?SN zzXbx&Gd>5VMlIo`Ag2|(H0DRfH@hC}r6|_XM`Bb%Jrk*F-b}vt`YbYSmXfC5voShI z=NcT$q#)T<2gcuFifP_2|25sqjEW*T0k!EYro7V3s3tM|Lv-+YqPWi^Lt;3O#Bk-t zTZdDXk6g{4+SqhLwC|CO!A6Ln01#=RlndUzYk0#wmnFz z)@e^|uoMl+{|=qNo5;Lf)M46_-N-NhJ(X6ONGH3(V)CiXerzJ4x6si`L_$}PArf-g z&+v1#TYj)2Rr^@dSv~2QDw=gwPn~(!wR&##6Yuc<$@MeW&+}8Ok0;$NihJdar)NDa zuWftRvt_QlWwx|swru5%XO+?p&`?D&G`*tYMVcOZCp8_hpFZVeuTptBRnVt6`-l~t zf#vlkrjg~)F|_j|cw+WTFXea7KERh@AmemqhSQG&zG1{2!Y>U|HV2Cf=8>0|-^Lg) zo^W8&h@el~MK~5Dc_%%xu<*gOLsehoEKM0WLOl~`e~K1=NuX^+hTQSxGp?GXtLAGb zZuF*V+uv-yz51Pt%Bj9o=b34jU$OaBudbPE8cz9tk1otFZ+6NrrOxU~tlWYFF$R}J zC)x#0ZH%*2`*CYFDE0mj0{Y-~mix8)9^b9+@BA2(KxnfX3Lqj3fasgW1^BTshH$$} zsM(B4@=vH{h5k^#Yn9}mkl> zjz?yzSI$&#N>*>0^dLNC#?zGaG~M{z-#c!*Qk$Pjc@8Mf10U$+O7ph29PhYN+j~-; zV~X?G1NKtL8}}Udob5Tg8F{)8eBPD;=2c^_jiCoB;pD_W`W*UCYROT0JL6@GX>eACagI1 zTJqgLTWiC#)W^Ws6tcvwtXY=prI~xYQqO1AgnM}Ll~wb>@AKJOKWvsY`pn`+4s)li zRCZ-@C>69qE|WuPy-{l9zRXW>R~;Am81`ka=1lM+|GYiEQm;4Cq~|jCabs6bc8U(L z0b0mzTADceh;8HZynIZwj(9UI^jv0vg6FT+OEY(U$>|JZ7xxlWv|)(bKF}d8#F5ra zZ9VrT%Zr6J)R{02Kf*<^R(~qmuF~;H`?w8h&Nu8=?Fl^6MVZ+#r zZ3xJGg*WqDk-y4iPYt{8i2(a-L2wY(DVqZcBOINl@yW&>(<9fSIEWA+Gky?f?j-fR z9ovVdJ!zczf`y8si8zI(^&@B^s#UPbYibMM; zf1XCXOvwuB);180hGY_gbT*v@6abfL+ekDRN#`JZc?@4hXrSuLka(TxGVN;%I-1lN zgtSYo%6`cy>W+`&>m}-!8T{ecu>39+7HidF(J^^YVzrGjhGzA{9xO_k`7pL$*61uh zi#QV7J{xiUHIYsd$?wU0C~nW2a~Hj`Y2J$52kwfO4qiPt<8Dm48*fVUc9cQ)%CA&Q zS0~-8-{_flP^pv4FM6eMK9}-&Tz(1FxZX4GqTg;Vzwnik`FzS3;Mt73HtDXt9-H@2 zNukkSQ_|h^hIPJ(N{fxs$~PF=y#>j zt|94exY;vbMWxk7>8hlA)f>C!mr-dAmtTxGt)+aOI>+Ud7u5U;%Gay!)quR>tetP- zD!lKOZ&O;gO}b_)0+a4JSJjNGG3jc&(TmXk-`Q;W#q(~iv{iAh#@8bhVN)`H)1B(N zZ+gGxeX~T_dSqtnspQsEsja=!TTZ7M`;uEu-|D(?_`AMu`;;xGlZ}0;>NAu3=Ze?P z7VlQ}oK$w7n&)^QUo~6RIF*lV6Hc*Nic0U4*MDfY6g4bZZRC%)!5@!r7_7X}oAgkK z(C>en&#gSe$H;K_$=Z@98l3ky-#3tU_86Xjh2PKduuaCfKCoV>tDpq+8t1PXhE|M! zv2dLKD*r0ab1#v0mWipP?qqu6DXv)0Vb%@)wXz=Q5VR7cRn>6~6^RBi!7_ zhVhvhME-9}bbe~0HQLS*!7fL?AO9nbV`Qd$-Mi)MKB#ZHdGVIzZ+G5uB%3$?VAV`# zPqMQoRS)ZEIb4_UGui4tv~msWzP%PDv#xsl&R9)4!I07qbn^=@B4d`_W@A^kBtH46 ziOkMU=2Y8|6%NBfgf+P^6uW4rmYjx}kCj}>{zORvQic%2zN1qW)IL!{a-E*w`y`AV zPskh59gs>SEt3i@V^wI;jO2~h52jExCi?{ypS5UCU!cKvnsDe11jK&(gV=KL#}o2D zq5A(IEUE^q`Z1EqX-EC6r*zV-pJ1t&vcK>-#aZ|992i{Z8N$AC|J1>Q`;Q$;)UfI#pnCU?_TYwPlxbJ8_t3pf z3Rn}YHFd$Iiw|@iI<&X@3ID+(d!N|b?Z;0*yakiF+hY3ERoihDq)~Z~_8qbla$xjH zw(}%2|H9pTT`}mTmCRPS{0H;{{{tb2tx&a;tyP=6n@U$uLfk-I!J4mvYOvCTN0!y3jmH3bPjBp4&%LE&iQZdE#BgsZ z*|hhTl6`z{DJ`mdOG%iZlsPpGNazqGwx5A^qKKjc#|0Kci90|91ZP@4msMNs!~C3) z?xHcw&ly!e;5j4s2RvtM;Q`OtGI_vrwt^Ntx5@vO-in+(8WkB+Ri@5hNBd^ar5?;je&H%=tKUnWH$?bhWgecObNcpGk7`icnC{^e(A zVh1UirG)H&3}{KaS3mC;lZhbl83+9g5nCiOQM61;K&I6p6Di9?`zkP**!Iv*@~tpY zo_6YzA;a#|Mc{9+Flf6FmIRw@zW&)UKd~tF@E7gX%jJ|X^?)=8qbZC;oYSQJOjW7C z*Ra&D{k0jNEklldtj0eU4~Ak)3rTy7Y7%`+E5>XM_VF_IK`ZsU4o7Lo6O{NUVf>6- z7AkK!Ot}F{hAA1LBtps4l#Eewk&F*RG7OK>iP`~j{5!%hUx|JGvVZNJOo_zl12 z%74YVe#PbfipzhGYkZGe_8wRFJ~uSO4ZY8G{DSLvpWFCruJV1ZJIQsw&#ixtYyI!s z?)SJY^EoT|dWuonJnukmwy192N+nJ%r(_`)xrIZ#lP_B+U&og(4Dk;B7{5^JqO^w6 z4{JD2`L*zkqpz(@6|B4LTF9~S0e+#t!JkAuHFZYIDi+)hzGR^^ zhd;tE6fc$bqTC4sVWB*i(#jUTpIx`(Imj>)h?F$`QZf@h5ZpFXsS;_ClqoW!C1oCoNJ+T4!yP&gVNe zp}!KPtbKuVpubYi?wYZcCvD|Zu9?cU$;!3pV8*sAX Self: + """Build a new `ConfigWrapper` instance for a `BaseModel`. + + The config wrapper built based on (in descending order of priority): + - options from `kwargs` + - options from the `namespace` + - options from the base classes (`bases`) + + Args: + bases: A tuple of base classes. + namespace: The namespace of the class being created. + raw_annotations: The (non-evaluated) annotations of the model. + kwargs: The kwargs passed to the class being created. + + Returns: + A `ConfigWrapper` instance for `BaseModel`. + """ + config_new = ConfigDict() + for base in bases: + config = getattr(base, 'model_config', None) + if config: + config_new.update(config.copy()) + + config_class_from_namespace = namespace.get('Config') + config_dict_from_namespace = namespace.get('model_config') + + if raw_annotations.get('model_config') and config_dict_from_namespace is None: + raise PydanticUserError( + '`model_config` cannot be used as a model field name. Use `model_config` for model configuration.', + code='model-config-invalid-field-name', + ) + + if config_class_from_namespace and config_dict_from_namespace: + raise PydanticUserError('"Config" and "model_config" cannot be used together', code='config-both') + + config_from_namespace = config_dict_from_namespace or prepare_config(config_class_from_namespace) + + config_new.update(config_from_namespace) + + for k in list(kwargs.keys()): + if k in config_keys: + config_new[k] = kwargs.pop(k) + + return cls(config_new) + + # we don't show `__getattr__` to type checkers so missing attributes cause errors + if not TYPE_CHECKING: # pragma: no branch + + def __getattr__(self, name: str) -> Any: + try: + return self.config_dict[name] + except KeyError: + try: + return config_defaults[name] + except KeyError: + raise AttributeError(f'Config has no attribute {name!r}') from None + + def core_config(self, title: str | None) -> core_schema.CoreConfig: + """Create a pydantic-core config. + + We don't use getattr here since we don't want to populate with defaults. + + Args: + title: The title to use if not set in config. + + Returns: + A `CoreConfig` object created from config. + """ + config = self.config_dict + + if config.get('schema_generator') is not None: + warnings.warn( + 'The `schema_generator` setting has been deprecated since v2.10. This setting no longer has any effect.', + PydanticDeprecatedSince210, + stacklevel=2, + ) + + if (populate_by_name := config.get('populate_by_name')) is not None: + # We include this patch for backwards compatibility purposes, but this config setting will be deprecated in v3.0, and likely removed in v4.0. + # Thus, the above warning and this patch can be removed then as well. + if config.get('validate_by_name') is None: + config['validate_by_alias'] = True + config['validate_by_name'] = populate_by_name + + # We dynamically patch validate_by_name to be True if validate_by_alias is set to False + # and validate_by_name is not explicitly set. + if config.get('validate_by_alias') is False and config.get('validate_by_name') is None: + config['validate_by_name'] = True + + if (not config.get('validate_by_alias', True)) and (not config.get('validate_by_name', False)): + raise PydanticUserError( + 'At least one of `validate_by_alias` or `validate_by_name` must be set to True.', + code='validate-by-alias-and-name-false', + ) + + return core_schema.CoreConfig( + **{ # pyright: ignore[reportArgumentType] + k: v + for k, v in ( + ('title', config.get('title') or title or None), + ('extra_fields_behavior', config.get('extra')), + ('allow_inf_nan', config.get('allow_inf_nan')), + ('str_strip_whitespace', config.get('str_strip_whitespace')), + ('str_to_lower', config.get('str_to_lower')), + ('str_to_upper', config.get('str_to_upper')), + ('strict', config.get('strict')), + ('ser_json_timedelta', config.get('ser_json_timedelta')), + ('ser_json_temporal', config.get('ser_json_temporal')), + ('val_temporal_unit', config.get('val_temporal_unit')), + ('ser_json_bytes', config.get('ser_json_bytes')), + ('val_json_bytes', config.get('val_json_bytes')), + ('ser_json_inf_nan', config.get('ser_json_inf_nan')), + ('from_attributes', config.get('from_attributes')), + ('loc_by_alias', config.get('loc_by_alias')), + ('revalidate_instances', config.get('revalidate_instances')), + ('validate_default', config.get('validate_default')), + ('str_max_length', config.get('str_max_length')), + ('str_min_length', config.get('str_min_length')), + ('hide_input_in_errors', config.get('hide_input_in_errors')), + ('coerce_numbers_to_str', config.get('coerce_numbers_to_str')), + ('regex_engine', config.get('regex_engine')), + ('validation_error_cause', config.get('validation_error_cause')), + ('cache_strings', config.get('cache_strings')), + ('validate_by_alias', config.get('validate_by_alias')), + ('validate_by_name', config.get('validate_by_name')), + ('serialize_by_alias', config.get('serialize_by_alias')), + ('url_preserve_empty_path', config.get('url_preserve_empty_path')), + ) + if v is not None + } + ) + + def __repr__(self): + c = ', '.join(f'{k}={v!r}' for k, v in self.config_dict.items()) + return f'ConfigWrapper({c})' + + +class ConfigWrapperStack: + """A stack of `ConfigWrapper` instances.""" + + def __init__(self, config_wrapper: ConfigWrapper): + self._config_wrapper_stack: list[ConfigWrapper] = [config_wrapper] + + @property + def tail(self) -> ConfigWrapper: + return self._config_wrapper_stack[-1] + + @contextmanager + def push(self, config_wrapper: ConfigWrapper | ConfigDict | None): + if config_wrapper is None: + yield + return + + if not isinstance(config_wrapper, ConfigWrapper): + config_wrapper = ConfigWrapper(config_wrapper, check=False) + + self._config_wrapper_stack.append(config_wrapper) + try: + yield + finally: + self._config_wrapper_stack.pop() + + +config_defaults = ConfigDict( + title=None, + str_to_lower=False, + str_to_upper=False, + str_strip_whitespace=False, + str_min_length=0, + str_max_length=None, + # let the model / dataclass decide how to handle it + extra=None, + frozen=False, + populate_by_name=False, + use_enum_values=False, + validate_assignment=False, + arbitrary_types_allowed=False, + from_attributes=False, + loc_by_alias=True, + alias_generator=None, + model_title_generator=None, + field_title_generator=None, + ignored_types=(), + allow_inf_nan=True, + json_schema_extra=None, + strict=False, + revalidate_instances='never', + ser_json_timedelta='iso8601', + ser_json_temporal='iso8601', + val_temporal_unit='infer', + ser_json_bytes='utf8', + val_json_bytes='utf8', + ser_json_inf_nan='null', + validate_default=False, + validate_return=False, + protected_namespaces=('model_validate', 'model_dump'), + hide_input_in_errors=False, + json_encoders=None, + defer_build=False, + schema_generator=None, + plugin_settings=None, + json_schema_serialization_defaults_required=False, + json_schema_mode_override=None, + coerce_numbers_to_str=False, + regex_engine='rust-regex', + validation_error_cause=False, + use_attribute_docstrings=False, + cache_strings=True, + validate_by_alias=True, + validate_by_name=False, + serialize_by_alias=False, + url_preserve_empty_path=False, +) + + +def prepare_config(config: ConfigDict | dict[str, Any] | type[Any] | None) -> ConfigDict: + """Create a `ConfigDict` instance from an existing dict, a class (e.g. old class-based config) or None. + + Args: + config: The input config. + + Returns: + A ConfigDict object created from config. + """ + if config is None: + return ConfigDict() + + if not isinstance(config, dict): + warnings.warn(DEPRECATION_MESSAGE, PydanticDeprecatedSince20, stacklevel=4) + config = {k: getattr(config, k) for k in dir(config) if not k.startswith('__')} + + config_dict = cast(ConfigDict, config) + check_deprecated(config_dict) + return config_dict + + +config_keys = set(ConfigDict.__annotations__.keys()) + + +V2_REMOVED_KEYS = { + 'allow_mutation', + 'error_msg_templates', + 'fields', + 'getter_dict', + 'smart_union', + 'underscore_attrs_are_private', + 'json_loads', + 'json_dumps', + 'copy_on_model_validation', + 'post_init_call', +} +V2_RENAMED_KEYS = { + 'allow_population_by_field_name': 'validate_by_name', + 'anystr_lower': 'str_to_lower', + 'anystr_strip_whitespace': 'str_strip_whitespace', + 'anystr_upper': 'str_to_upper', + 'keep_untouched': 'ignored_types', + 'max_anystr_length': 'str_max_length', + 'min_anystr_length': 'str_min_length', + 'orm_mode': 'from_attributes', + 'schema_extra': 'json_schema_extra', + 'validate_all': 'validate_default', +} + + +def check_deprecated(config_dict: ConfigDict) -> None: + """Check for deprecated config keys and warn the user. + + Args: + config_dict: The input config. + """ + deprecated_removed_keys = V2_REMOVED_KEYS & config_dict.keys() + deprecated_renamed_keys = V2_RENAMED_KEYS.keys() & config_dict.keys() + if deprecated_removed_keys or deprecated_renamed_keys: + renamings = {k: V2_RENAMED_KEYS[k] for k in sorted(deprecated_renamed_keys)} + renamed_bullets = [f'* {k!r} has been renamed to {v!r}' for k, v in renamings.items()] + removed_bullets = [f'* {k!r} has been removed' for k in sorted(deprecated_removed_keys)] + message = '\n'.join(['Valid config keys have changed in V2:'] + renamed_bullets + removed_bullets) + warnings.warn(message, UserWarning) diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_core_metadata.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_core_metadata.py new file mode 100644 index 0000000..9f2510c --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_core_metadata.py @@ -0,0 +1,97 @@ +from __future__ import annotations as _annotations + +from typing import TYPE_CHECKING, Any, TypedDict, cast +from warnings import warn + +if TYPE_CHECKING: + from ..config import JsonDict, JsonSchemaExtraCallable + from ._schema_generation_shared import ( + GetJsonSchemaFunction, + ) + + +class CoreMetadata(TypedDict, total=False): + """A `TypedDict` for holding the metadata dict of the schema. + + Attributes: + pydantic_js_functions: List of JSON schema functions that resolve refs during application. + pydantic_js_annotation_functions: List of JSON schema functions that don't resolve refs during application. + pydantic_js_prefer_positional_arguments: Whether JSON schema generator will + prefer positional over keyword arguments for an 'arguments' schema. + custom validation function. Only applies to before, plain, and wrap validators. + pydantic_js_updates: key / value pair updates to apply to the JSON schema for a type. + pydantic_js_extra: WIP, either key/value pair updates to apply to the JSON schema, or a custom callable. + pydantic_internal_union_tag_key: Used internally by the `Tag` metadata to specify the tag used for a discriminated union. + pydantic_internal_union_discriminator: Used internally to specify the discriminator value for a discriminated union + when the discriminator was applied to a `'definition-ref'` schema, and that reference was missing at the time + of the annotation application. + + TODO: Perhaps we should move this structure to pydantic-core. At the moment, though, + it's easier to iterate on if we leave it in pydantic until we feel there is a semi-stable API. + + TODO: It's unfortunate how functionally oriented JSON schema generation is, especially that which occurs during + the core schema generation process. It's inevitable that we need to store some json schema related information + on core schemas, given that we generate JSON schemas directly from core schemas. That being said, debugging related + issues is quite difficult when JSON schema information is disguised via dynamically defined functions. + """ + + pydantic_js_functions: list[GetJsonSchemaFunction] + pydantic_js_annotation_functions: list[GetJsonSchemaFunction] + pydantic_js_prefer_positional_arguments: bool + pydantic_js_updates: JsonDict + pydantic_js_extra: JsonDict | JsonSchemaExtraCallable + pydantic_internal_union_tag_key: str + pydantic_internal_union_discriminator: str + + +def update_core_metadata( + core_metadata: Any, + /, + *, + pydantic_js_functions: list[GetJsonSchemaFunction] | None = None, + pydantic_js_annotation_functions: list[GetJsonSchemaFunction] | None = None, + pydantic_js_updates: JsonDict | None = None, + pydantic_js_extra: JsonDict | JsonSchemaExtraCallable | None = None, +) -> None: + from ..json_schema import PydanticJsonSchemaWarning + + """Update CoreMetadata instance in place. When we make modifications in this function, they + take effect on the `core_metadata` reference passed in as the first (and only) positional argument. + + First, cast to `CoreMetadata`, then finish with a cast to `dict[str, Any]` for core schema compatibility. + We do this here, instead of before / after each call to this function so that this typing hack + can be easily removed if/when we move `CoreMetadata` to `pydantic-core`. + + For parameter descriptions, see `CoreMetadata` above. + """ + core_metadata = cast(CoreMetadata, core_metadata) + + if pydantic_js_functions: + core_metadata.setdefault('pydantic_js_functions', []).extend(pydantic_js_functions) + + if pydantic_js_annotation_functions: + core_metadata.setdefault('pydantic_js_annotation_functions', []).extend(pydantic_js_annotation_functions) + + if pydantic_js_updates: + if (existing_updates := core_metadata.get('pydantic_js_updates')) is not None: + core_metadata['pydantic_js_updates'] = {**existing_updates, **pydantic_js_updates} + else: + core_metadata['pydantic_js_updates'] = pydantic_js_updates + + if pydantic_js_extra is not None: + existing_pydantic_js_extra = core_metadata.get('pydantic_js_extra') + if existing_pydantic_js_extra is None: + core_metadata['pydantic_js_extra'] = pydantic_js_extra + if isinstance(existing_pydantic_js_extra, dict): + if isinstance(pydantic_js_extra, dict): + core_metadata['pydantic_js_extra'] = {**existing_pydantic_js_extra, **pydantic_js_extra} + if callable(pydantic_js_extra): + warn( + 'Composing `dict` and `callable` type `json_schema_extra` is not supported.' + 'The `callable` type is being ignored.' + "If you'd like support for this behavior, please open an issue on pydantic.", + PydanticJsonSchemaWarning, + ) + if callable(existing_pydantic_js_extra): + # if ever there's a case of a callable, we'll just keep the last json schema extra spec + core_metadata['pydantic_js_extra'] = pydantic_js_extra diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_core_utils.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_core_utils.py new file mode 100644 index 0000000..caa51e8 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_core_utils.py @@ -0,0 +1,174 @@ +from __future__ import annotations + +import inspect +from collections.abc import Mapping, Sequence +from typing import TYPE_CHECKING, Any, Union + +from pydantic_core import CoreSchema, core_schema +from typing_extensions import TypeGuard, get_args, get_origin +from typing_inspection import typing_objects + +from . import _repr +from ._typing_extra import is_generic_alias + +if TYPE_CHECKING: + from rich.console import Console + +AnyFunctionSchema = Union[ + core_schema.AfterValidatorFunctionSchema, + core_schema.BeforeValidatorFunctionSchema, + core_schema.WrapValidatorFunctionSchema, + core_schema.PlainValidatorFunctionSchema, +] + + +FunctionSchemaWithInnerSchema = Union[ + core_schema.AfterValidatorFunctionSchema, + core_schema.BeforeValidatorFunctionSchema, + core_schema.WrapValidatorFunctionSchema, +] + +CoreSchemaField = Union[ + core_schema.ModelField, core_schema.DataclassField, core_schema.TypedDictField, core_schema.ComputedField +] +CoreSchemaOrField = Union[core_schema.CoreSchema, CoreSchemaField] + +_CORE_SCHEMA_FIELD_TYPES = {'typed-dict-field', 'dataclass-field', 'model-field', 'computed-field'} +_FUNCTION_WITH_INNER_SCHEMA_TYPES = {'function-before', 'function-after', 'function-wrap'} +_LIST_LIKE_SCHEMA_WITH_ITEMS_TYPES = {'list', 'set', 'frozenset'} + + +def is_core_schema( + schema: CoreSchemaOrField, +) -> TypeGuard[CoreSchema]: + return schema['type'] not in _CORE_SCHEMA_FIELD_TYPES + + +def is_core_schema_field( + schema: CoreSchemaOrField, +) -> TypeGuard[CoreSchemaField]: + return schema['type'] in _CORE_SCHEMA_FIELD_TYPES + + +def is_function_with_inner_schema( + schema: CoreSchemaOrField, +) -> TypeGuard[FunctionSchemaWithInnerSchema]: + return schema['type'] in _FUNCTION_WITH_INNER_SCHEMA_TYPES + + +def is_list_like_schema_with_items_schema( + schema: CoreSchema, +) -> TypeGuard[core_schema.ListSchema | core_schema.SetSchema | core_schema.FrozenSetSchema]: + return schema['type'] in _LIST_LIKE_SCHEMA_WITH_ITEMS_TYPES + + +def get_type_ref(type_: Any, args_override: tuple[type[Any], ...] | None = None) -> str: + """Produces the ref to be used for this type by pydantic_core's core schemas. + + This `args_override` argument was added for the purpose of creating valid recursive references + when creating generic models without needing to create a concrete class. + """ + origin = get_origin(type_) or type_ + + args = get_args(type_) if is_generic_alias(type_) else (args_override or ()) + generic_metadata = getattr(type_, '__pydantic_generic_metadata__', None) + if generic_metadata: + origin = generic_metadata['origin'] or origin + args = generic_metadata['args'] or args + + module_name = getattr(origin, '__module__', '') + if typing_objects.is_typealiastype(origin): + type_ref = f'{module_name}.{origin.__name__}:{id(origin)}' + else: + try: + qualname = getattr(origin, '__qualname__', f'') + except Exception: + qualname = getattr(origin, '__qualname__', '') + type_ref = f'{module_name}.{qualname}:{id(origin)}' + + arg_refs: list[str] = [] + for arg in args: + if isinstance(arg, str): + # Handle string literals as a special case; we may be able to remove this special handling if we + # wrap them in a ForwardRef at some point. + arg_ref = f'{arg}:str-{id(arg)}' + else: + arg_ref = f'{_repr.display_as_type(arg)}:{id(arg)}' + arg_refs.append(arg_ref) + if arg_refs: + type_ref = f'{type_ref}[{",".join(arg_refs)}]' + return type_ref + + +def get_ref(s: core_schema.CoreSchema) -> None | str: + """Get the ref from the schema if it has one. + This exists just for type checking to work correctly. + """ + return s.get('ref', None) + + +def _clean_schema_for_pretty_print(obj: Any, strip_metadata: bool = True) -> Any: # pragma: no cover + """A utility function to remove irrelevant information from a core schema.""" + if isinstance(obj, Mapping): + new_dct = {} + for k, v in obj.items(): + if k == 'metadata' and strip_metadata: + new_metadata = {} + + for meta_k, meta_v in v.items(): + if meta_k in ('pydantic_js_functions', 'pydantic_js_annotation_functions'): + new_metadata['js_metadata'] = '' + else: + new_metadata[meta_k] = _clean_schema_for_pretty_print(meta_v, strip_metadata=strip_metadata) + + if list(new_metadata.keys()) == ['js_metadata']: + new_metadata = {''} + + new_dct[k] = new_metadata + # Remove some defaults: + elif k in ('custom_init', 'root_model') and not v: + continue + else: + new_dct[k] = _clean_schema_for_pretty_print(v, strip_metadata=strip_metadata) + + return new_dct + elif isinstance(obj, Sequence) and not isinstance(obj, str): + return [_clean_schema_for_pretty_print(v, strip_metadata=strip_metadata) for v in obj] + else: + return obj + + +def pretty_print_core_schema( + val: Any, + *, + console: Console | None = None, + max_depth: int | None = None, + strip_metadata: bool = True, +) -> None: # pragma: no cover + """Pretty-print a core schema using the `rich` library. + + Args: + val: The core schema to print, or a Pydantic model/dataclass/type adapter + (in which case the cached core schema is fetched and printed). + console: A rich console to use when printing. Defaults to the global rich console instance. + max_depth: The number of nesting levels which may be printed. + strip_metadata: Whether to strip metadata in the output. If `True` any known core metadata + attributes will be stripped (but custom attributes are kept). Defaults to `True`. + """ + # lazy import: + from rich.pretty import pprint + + # circ. imports: + from pydantic import BaseModel, TypeAdapter + from pydantic.dataclasses import is_pydantic_dataclass + + if (inspect.isclass(val) and issubclass(val, BaseModel)) or is_pydantic_dataclass(val): + val = val.__pydantic_core_schema__ + if isinstance(val, TypeAdapter): + val = val.core_schema + cleaned_schema = _clean_schema_for_pretty_print(val, strip_metadata=strip_metadata) + + pprint(cleaned_schema, console=console, max_depth=max_depth) + + +pps = pretty_print_core_schema diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_dataclasses.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_dataclasses.py new file mode 100644 index 0000000..869286b --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_dataclasses.py @@ -0,0 +1,315 @@ +"""Private logic for creating pydantic dataclasses.""" + +from __future__ import annotations as _annotations + +import copy +import dataclasses +import sys +import warnings +from collections.abc import Generator +from contextlib import contextmanager +from functools import partial +from typing import TYPE_CHECKING, Any, ClassVar, Protocol, cast + +from pydantic_core import ( + ArgsKwargs, + SchemaSerializer, + SchemaValidator, + core_schema, +) +from typing_extensions import TypeAlias, TypeIs + +from ..errors import PydanticUndefinedAnnotation +from ..fields import FieldInfo +from ..plugin._schema_validator import PluggableSchemaValidator, create_schema_validator +from ..warnings import PydanticDeprecatedSince20 +from . import _config, _decorators +from ._fields import collect_dataclass_fields +from ._generate_schema import GenerateSchema, InvalidSchemaError +from ._generics import get_standard_typevars_map +from ._mock_val_ser import set_dataclass_mocks +from ._namespace_utils import NsResolver +from ._signature import generate_pydantic_signature +from ._utils import LazyClassAttribute + +if TYPE_CHECKING: + from _typeshed import DataclassInstance as StandardDataclass + + from ..config import ConfigDict + + class PydanticDataclass(StandardDataclass, Protocol): + """A protocol containing attributes only available once a class has been decorated as a Pydantic dataclass. + + Attributes: + __pydantic_config__: Pydantic-specific configuration settings for the dataclass. + __pydantic_complete__: Whether dataclass building is completed, or if there are still undefined fields. + __pydantic_core_schema__: The pydantic-core schema used to build the SchemaValidator and SchemaSerializer. + __pydantic_decorators__: Metadata containing the decorators defined on the dataclass. + __pydantic_fields__: Metadata about the fields defined on the dataclass. + __pydantic_serializer__: The pydantic-core SchemaSerializer used to dump instances of the dataclass. + __pydantic_validator__: The pydantic-core SchemaValidator used to validate instances of the dataclass. + """ + + __pydantic_config__: ClassVar[ConfigDict] + __pydantic_complete__: ClassVar[bool] + __pydantic_core_schema__: ClassVar[core_schema.CoreSchema] + __pydantic_decorators__: ClassVar[_decorators.DecoratorInfos] + __pydantic_fields__: ClassVar[dict[str, FieldInfo]] + __pydantic_serializer__: ClassVar[SchemaSerializer] + __pydantic_validator__: ClassVar[SchemaValidator | PluggableSchemaValidator] + + @classmethod + def __pydantic_fields_complete__(cls) -> bool: ... + + +def set_dataclass_fields( + cls: type[StandardDataclass], + config_wrapper: _config.ConfigWrapper, + ns_resolver: NsResolver | None = None, +) -> None: + """Collect and set `cls.__pydantic_fields__`. + + Args: + cls: The class. + config_wrapper: The config wrapper instance. + ns_resolver: Namespace resolver to use when getting dataclass annotations. + """ + typevars_map = get_standard_typevars_map(cls) + fields = collect_dataclass_fields( + cls, ns_resolver=ns_resolver, typevars_map=typevars_map, config_wrapper=config_wrapper + ) + + cls.__pydantic_fields__ = fields # type: ignore + + +def complete_dataclass( + cls: type[Any], + config_wrapper: _config.ConfigWrapper, + *, + raise_errors: bool = True, + ns_resolver: NsResolver | None = None, + _force_build: bool = False, +) -> bool: + """Finish building a pydantic dataclass. + + This logic is called on a class which has already been wrapped in `dataclasses.dataclass()`. + + This is somewhat analogous to `pydantic._internal._model_construction.complete_model_class`. + + Args: + cls: The class. + config_wrapper: The config wrapper instance. + raise_errors: Whether to raise errors, defaults to `True`. + ns_resolver: The namespace resolver instance to use when collecting dataclass fields + and during schema building. + _force_build: Whether to force building the dataclass, no matter if + [`defer_build`][pydantic.config.ConfigDict.defer_build] is set. + + Returns: + `True` if building a pydantic dataclass is successfully completed, `False` otherwise. + + Raises: + PydanticUndefinedAnnotation: If `raise_error` is `True` and there is an undefined annotations. + """ + original_init = cls.__init__ + + # dataclass.__init__ must be defined here so its `__qualname__` can be changed since functions can't be copied, + # and so that the mock validator is used if building was deferred: + def __init__(__dataclass_self__: PydanticDataclass, *args: Any, **kwargs: Any) -> None: + __tracebackhide__ = True + s = __dataclass_self__ + s.__pydantic_validator__.validate_python(ArgsKwargs(args, kwargs), self_instance=s) + + __init__.__qualname__ = f'{cls.__qualname__}.__init__' + + cls.__init__ = __init__ # type: ignore + cls.__pydantic_config__ = config_wrapper.config_dict # type: ignore + + set_dataclass_fields(cls, config_wrapper=config_wrapper, ns_resolver=ns_resolver) + + if not _force_build and config_wrapper.defer_build: + set_dataclass_mocks(cls) + return False + + if hasattr(cls, '__post_init_post_parse__'): + warnings.warn( + 'Support for `__post_init_post_parse__` has been dropped, the method will not be called', + PydanticDeprecatedSince20, + ) + + typevars_map = get_standard_typevars_map(cls) + gen_schema = GenerateSchema( + config_wrapper, + ns_resolver=ns_resolver, + typevars_map=typevars_map, + ) + + # set __signature__ attr only for the class, but not for its instances + # (because instances can define `__call__`, and `inspect.signature` shouldn't + # use the `__signature__` attribute and instead generate from `__call__`). + cls.__signature__ = LazyClassAttribute( + '__signature__', + partial( + generate_pydantic_signature, + # It's important that we reference the `original_init` here, + # as it is the one synthesized by the stdlib `dataclass` module: + init=original_init, + fields=cls.__pydantic_fields__, # type: ignore + validate_by_name=config_wrapper.validate_by_name, + extra=config_wrapper.extra, + is_dataclass=True, + ), + ) + + try: + schema = gen_schema.generate_schema(cls) + except PydanticUndefinedAnnotation as e: + if raise_errors: + raise + set_dataclass_mocks(cls, f'`{e.name}`') + return False + + core_config = config_wrapper.core_config(title=cls.__name__) + + try: + schema = gen_schema.clean_schema(schema) + except InvalidSchemaError: + set_dataclass_mocks(cls) + return False + + # We are about to set all the remaining required properties expected for this cast; + # __pydantic_decorators__ and __pydantic_fields__ should already be set + cls = cast('type[PydanticDataclass]', cls) + + cls.__pydantic_core_schema__ = schema + cls.__pydantic_validator__ = create_schema_validator( + schema, cls, cls.__module__, cls.__qualname__, 'dataclass', core_config, config_wrapper.plugin_settings + ) + cls.__pydantic_serializer__ = SchemaSerializer(schema, core_config) + cls.__pydantic_complete__ = True + return True + + +def is_stdlib_dataclass(cls: type[Any], /) -> TypeIs[type[StandardDataclass]]: + """Returns `True` if the class is a stdlib dataclass and *not* a Pydantic dataclass. + + Unlike the stdlib `dataclasses.is_dataclass()` function, this does *not* include subclasses + of a dataclass that are themselves not dataclasses. + + Args: + cls: The class. + + Returns: + `True` if the class is a stdlib dataclass, `False` otherwise. + """ + return '__dataclass_fields__' in cls.__dict__ and not hasattr(cls, '__pydantic_validator__') + + +def as_dataclass_field(pydantic_field: FieldInfo) -> dataclasses.Field[Any]: + field_args: dict[str, Any] = {'default': pydantic_field} + + # Needed because if `doc` is set, the dataclass slots will be a dict (field name -> doc) instead of a tuple: + if sys.version_info >= (3, 14) and pydantic_field.description is not None: + field_args['doc'] = pydantic_field.description + + # Needed as the stdlib dataclass module processes kw_only in a specific way during class construction: + if sys.version_info >= (3, 10) and pydantic_field.kw_only: + field_args['kw_only'] = True + + # Needed as the stdlib dataclass modules generates `__repr__()` during class construction: + if pydantic_field.repr is not True: + field_args['repr'] = pydantic_field.repr + + return dataclasses.field(**field_args) + + +DcFields: TypeAlias = dict[str, dataclasses.Field[Any]] + + +@contextmanager +def patch_base_fields(cls: type[Any]) -> Generator[None]: + """Temporarily patch the stdlib dataclasses bases of `cls` if the Pydantic `Field()` function is used. + + When creating a Pydantic dataclass, it is possible to inherit from stdlib dataclasses, where + the Pydantic `Field()` function is used. To create this Pydantic dataclass, we first apply + the stdlib `@dataclass` decorator on it. During the construction of the stdlib dataclass, + the `kw_only` and `repr` field arguments need to be understood by the stdlib *during* the + dataclass construction. To do so, we temporarily patch the fields dictionary of the affected + bases. + + For instance, with the following example: + + ```python {test="skip" lint="skip"} + import dataclasses as stdlib_dc + + import pydantic + import pydantic.dataclasses as pydantic_dc + + @stdlib_dc.dataclass + class A: + a: int = pydantic.Field(repr=False) + + # Notice that the `repr` attribute of the dataclass field is `True`: + A.__dataclass_fields__['a'] + #> dataclass.Field(default=FieldInfo(repr=False), repr=True, ...) + + @pydantic_dc.dataclass + class B(A): + b: int = pydantic.Field(repr=False) + ``` + + When passing `B` to the stdlib `@dataclass` decorator, it will look for fields in the parent classes + and reuse them directly. When this context manager is active, `A` will be temporarily patched to be + equivalent to: + + ```python {test="skip" lint="skip"} + @stdlib_dc.dataclass + class A: + a: int = stdlib_dc.field(default=Field(repr=False), repr=False) + ``` + + !!! note + This is only applied to the bases of `cls`, and not `cls` itself. The reason is that the Pydantic + dataclass decorator "owns" `cls` (in the previous example, `B`). As such, we instead modify the fields + directly (in the previous example, we simply do `setattr(B, 'b', as_dataclass_field(pydantic_field))`). + + !!! note + This approach is far from ideal, and can probably be the source of unwanted side effects/race conditions. + The previous implemented approach was mutating the `__annotations__` dict of `cls`, which is no longer a + safe operation in Python 3.14+, and resulted in unexpected behavior with field ordering anyway. + """ + # A list of two-tuples, the first element being a reference to the + # dataclass fields dictionary, the second element being a mapping between + # the field names that were modified, and their original `Field`: + original_fields_list: list[tuple[DcFields, DcFields]] = [] + + for base in cls.__mro__[1:]: + dc_fields: dict[str, dataclasses.Field[Any]] = base.__dict__.get('__dataclass_fields__', {}) + dc_fields_with_pydantic_field_defaults = { + field_name: field + for field_name, field in dc_fields.items() + if isinstance(field.default, FieldInfo) + # Only do the patching if one of the affected attributes is set: + and (field.default.description is not None or field.default.kw_only or field.default.repr is not True) + } + if dc_fields_with_pydantic_field_defaults: + original_fields_list.append((dc_fields, dc_fields_with_pydantic_field_defaults)) + for field_name, field in dc_fields_with_pydantic_field_defaults.items(): + default = cast(FieldInfo, field.default) + # `dataclasses.Field` isn't documented as working with `copy.copy()`. + # It is a class with `__slots__`, so should work (and we hope for the best): + new_dc_field = copy.copy(field) + # For base fields, no need to set `doc` from `FieldInfo.description`, this is only relevant + # for the class under construction and handled in `as_dataclass_field()`. + if sys.version_info >= (3, 10) and default.kw_only: + new_dc_field.kw_only = True + if default.repr is not True: + new_dc_field.repr = default.repr + dc_fields[field_name] = new_dc_field + + try: + yield + finally: + for fields, original_fields in original_fields_list: + for field_name, original_field in original_fields.items(): + fields[field_name] = original_field diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_decorators.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_decorators.py new file mode 100644 index 0000000..2a43bbb --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_decorators.py @@ -0,0 +1,858 @@ +"""Logic related to validators applied to models etc. via the `@field_validator` and `@model_validator` decorators.""" + +from __future__ import annotations as _annotations + +import sys +import types +from collections import deque +from collections.abc import Iterable +from dataclasses import dataclass, field +from functools import cached_property, partial, partialmethod +from inspect import Parameter, Signature, isdatadescriptor, ismethoddescriptor, signature +from itertools import islice +from typing import TYPE_CHECKING, Any, Callable, ClassVar, Generic, Literal, TypeVar, Union + +from pydantic_core import PydanticUndefined, PydanticUndefinedType, core_schema +from typing_extensions import TypeAlias, is_typeddict + +from ..errors import PydanticUserError +from ._core_utils import get_type_ref +from ._internal_dataclass import slots_true +from ._namespace_utils import GlobalsNamespace, MappingNamespace +from ._typing_extra import get_function_type_hints +from ._utils import can_be_positional + +if TYPE_CHECKING: + from ..fields import ComputedFieldInfo + from ..functional_validators import FieldValidatorModes + from ._config import ConfigWrapper + + +@dataclass(**slots_true) +class ValidatorDecoratorInfo: + """A container for data from `@validator` so that we can access it + while building the pydantic-core schema. + + Attributes: + decorator_repr: A class variable representing the decorator string, '@validator'. + fields: A tuple of field names the validator should be called on. + mode: The proposed validator mode. + each_item: For complex objects (sets, lists etc.) whether to validate individual + elements rather than the whole object. + always: Whether this method and other validators should be called even if the value is missing. + check_fields: Whether to check that the fields actually exist on the model. + """ + + decorator_repr: ClassVar[str] = '@validator' + + fields: tuple[str, ...] + mode: Literal['before', 'after'] + each_item: bool + always: bool + check_fields: bool | None + + +@dataclass(**slots_true) +class FieldValidatorDecoratorInfo: + """A container for data from `@field_validator` so that we can access it + while building the pydantic-core schema. + + Attributes: + decorator_repr: A class variable representing the decorator string, '@field_validator'. + fields: A tuple of field names the validator should be called on. + mode: The proposed validator mode. + check_fields: Whether to check that the fields actually exist on the model. + json_schema_input_type: The input type of the function. This is only used to generate + the appropriate JSON Schema (in validation mode) and can only specified + when `mode` is either `'before'`, `'plain'` or `'wrap'`. + """ + + decorator_repr: ClassVar[str] = '@field_validator' + + fields: tuple[str, ...] + mode: FieldValidatorModes + check_fields: bool | None + json_schema_input_type: Any + + +@dataclass(**slots_true) +class RootValidatorDecoratorInfo: + """A container for data from `@root_validator` so that we can access it + while building the pydantic-core schema. + + Attributes: + decorator_repr: A class variable representing the decorator string, '@root_validator'. + mode: The proposed validator mode. + """ + + decorator_repr: ClassVar[str] = '@root_validator' + mode: Literal['before', 'after'] + + +@dataclass(**slots_true) +class FieldSerializerDecoratorInfo: + """A container for data from `@field_serializer` so that we can access it + while building the pydantic-core schema. + + Attributes: + decorator_repr: A class variable representing the decorator string, '@field_serializer'. + fields: A tuple of field names the serializer should be called on. + mode: The proposed serializer mode. + return_type: The type of the serializer's return value. + when_used: The serialization condition. Accepts a string with values `'always'`, `'unless-none'`, `'json'`, + and `'json-unless-none'`. + check_fields: Whether to check that the fields actually exist on the model. + """ + + decorator_repr: ClassVar[str] = '@field_serializer' + fields: tuple[str, ...] + mode: Literal['plain', 'wrap'] + return_type: Any + when_used: core_schema.WhenUsed + check_fields: bool | None + + +@dataclass(**slots_true) +class ModelSerializerDecoratorInfo: + """A container for data from `@model_serializer` so that we can access it + while building the pydantic-core schema. + + Attributes: + decorator_repr: A class variable representing the decorator string, '@model_serializer'. + mode: The proposed serializer mode. + return_type: The type of the serializer's return value. + when_used: The serialization condition. Accepts a string with values `'always'`, `'unless-none'`, `'json'`, + and `'json-unless-none'`. + """ + + decorator_repr: ClassVar[str] = '@model_serializer' + mode: Literal['plain', 'wrap'] + return_type: Any + when_used: core_schema.WhenUsed + + +@dataclass(**slots_true) +class ModelValidatorDecoratorInfo: + """A container for data from `@model_validator` so that we can access it + while building the pydantic-core schema. + + Attributes: + decorator_repr: A class variable representing the decorator string, '@model_validator'. + mode: The proposed serializer mode. + """ + + decorator_repr: ClassVar[str] = '@model_validator' + mode: Literal['wrap', 'before', 'after'] + + +DecoratorInfo: TypeAlias = """Union[ + ValidatorDecoratorInfo, + FieldValidatorDecoratorInfo, + RootValidatorDecoratorInfo, + FieldSerializerDecoratorInfo, + ModelSerializerDecoratorInfo, + ModelValidatorDecoratorInfo, + ComputedFieldInfo, +]""" + +ReturnType = TypeVar('ReturnType') +DecoratedType: TypeAlias = ( + 'Union[classmethod[Any, Any, ReturnType], staticmethod[Any, ReturnType], Callable[..., ReturnType], property]' +) + + +@dataclass # can't use slots here since we set attributes on `__post_init__` +class PydanticDescriptorProxy(Generic[ReturnType]): + """Wrap a classmethod, staticmethod, property or unbound function + and act as a descriptor that allows us to detect decorated items + from the class' attributes. + + This class' __get__ returns the wrapped item's __get__ result, + which makes it transparent for classmethods and staticmethods. + + Attributes: + wrapped: The decorator that has to be wrapped. + decorator_info: The decorator info. + shim: A wrapper function to wrap V1 style function. + """ + + wrapped: DecoratedType[ReturnType] + decorator_info: DecoratorInfo + shim: Callable[[Callable[..., Any]], Callable[..., Any]] | None = None + + def __post_init__(self): + for attr in 'setter', 'deleter': + if hasattr(self.wrapped, attr): + f = partial(self._call_wrapped_attr, name=attr) + setattr(self, attr, f) + + def _call_wrapped_attr(self, func: Callable[[Any], None], *, name: str) -> PydanticDescriptorProxy[ReturnType]: + self.wrapped = getattr(self.wrapped, name)(func) + if isinstance(self.wrapped, property): + # update ComputedFieldInfo.wrapped_property + from ..fields import ComputedFieldInfo + + if isinstance(self.decorator_info, ComputedFieldInfo): + self.decorator_info.wrapped_property = self.wrapped + return self + + def __get__(self, obj: object | None, obj_type: type[object] | None = None) -> PydanticDescriptorProxy[ReturnType]: + try: + return self.wrapped.__get__(obj, obj_type) # pyright: ignore[reportReturnType] + except AttributeError: + # not a descriptor, e.g. a partial object + return self.wrapped # type: ignore[return-value] + + def __set_name__(self, instance: Any, name: str) -> None: + if hasattr(self.wrapped, '__set_name__'): + self.wrapped.__set_name__(instance, name) # pyright: ignore[reportFunctionMemberAccess] + + def __getattr__(self, name: str, /) -> Any: + """Forward checks for __isabstractmethod__ and such.""" + return getattr(self.wrapped, name) + + +DecoratorInfoType = TypeVar('DecoratorInfoType', bound=DecoratorInfo) + + +@dataclass(**slots_true) +class Decorator(Generic[DecoratorInfoType]): + """A generic container class to join together the decorator metadata + (metadata from decorator itself, which we have when the + decorator is called but not when we are building the core-schema) + and the bound function (which we have after the class itself is created). + + Attributes: + cls_ref: The class ref. + cls_var_name: The decorated function name. + func: The decorated function. + shim: A wrapper function to wrap V1 style function. + info: The decorator info. + """ + + cls_ref: str + cls_var_name: str + func: Callable[..., Any] + shim: Callable[[Any], Any] | None + info: DecoratorInfoType + + @staticmethod + def build( + cls_: Any, + *, + cls_var_name: str, + shim: Callable[[Any], Any] | None, + info: DecoratorInfoType, + ) -> Decorator[DecoratorInfoType]: + """Build a new decorator. + + Args: + cls_: The class. + cls_var_name: The decorated function name. + shim: A wrapper function to wrap V1 style function. + info: The decorator info. + + Returns: + The new decorator instance. + """ + func = get_attribute_from_bases(cls_, cls_var_name) + if shim is not None: + func = shim(func) + func = unwrap_wrapped_function(func, unwrap_partial=False) + if not callable(func): + # This branch will get hit for classmethod properties + attribute = get_attribute_from_base_dicts(cls_, cls_var_name) # prevents the binding call to `__get__` + if isinstance(attribute, PydanticDescriptorProxy): + func = unwrap_wrapped_function(attribute.wrapped) + return Decorator( + cls_ref=get_type_ref(cls_), + cls_var_name=cls_var_name, + func=func, + shim=shim, + info=info, + ) + + def bind_to_cls(self, cls: Any) -> Decorator[DecoratorInfoType]: + """Bind the decorator to a class. + + Args: + cls: the class. + + Returns: + The new decorator instance. + """ + return self.build( + cls, + cls_var_name=self.cls_var_name, + shim=self.shim, + info=self.info, + ) + + +def get_bases(tp: type[Any]) -> tuple[type[Any], ...]: + """Get the base classes of a class or typeddict. + + Args: + tp: The type or class to get the bases. + + Returns: + The base classes. + """ + if is_typeddict(tp): + return tp.__orig_bases__ # type: ignore + try: + return tp.__bases__ + except AttributeError: + return () + + +def mro(tp: type[Any]) -> tuple[type[Any], ...]: + """Calculate the Method Resolution Order of bases using the C3 algorithm. + + See https://www.python.org/download/releases/2.3/mro/ + """ + # try to use the existing mro, for performance mainly + # but also because it helps verify the implementation below + if not is_typeddict(tp): + try: + return tp.__mro__ + except AttributeError: + # GenericAlias and some other cases + pass + + bases = get_bases(tp) + return (tp,) + mro_for_bases(bases) + + +def mro_for_bases(bases: tuple[type[Any], ...]) -> tuple[type[Any], ...]: + def merge_seqs(seqs: list[deque[type[Any]]]) -> Iterable[type[Any]]: + while True: + non_empty = [seq for seq in seqs if seq] + if not non_empty: + # Nothing left to process, we're done. + return + candidate: type[Any] | None = None + for seq in non_empty: # Find merge candidates among seq heads. + candidate = seq[0] + not_head = [s for s in non_empty if candidate in islice(s, 1, None)] + if not_head: + # Reject the candidate. + candidate = None + else: + break + if not candidate: + raise TypeError('Inconsistent hierarchy, no C3 MRO is possible') + yield candidate + for seq in non_empty: + # Remove candidate. + if seq[0] == candidate: + seq.popleft() + + seqs = [deque(mro(base)) for base in bases] + [deque(bases)] + return tuple(merge_seqs(seqs)) + + +_sentinel = object() + + +def get_attribute_from_bases(tp: type[Any] | tuple[type[Any], ...], name: str) -> Any: + """Get the attribute from the next class in the MRO that has it, + aiming to simulate calling the method on the actual class. + + The reason for iterating over the mro instead of just getting + the attribute (which would do that for us) is to support TypedDict, + which lacks a real __mro__, but can have a virtual one constructed + from its bases (as done here). + + Args: + tp: The type or class to search for the attribute. If a tuple, this is treated as a set of base classes. + name: The name of the attribute to retrieve. + + Returns: + Any: The attribute value, if found. + + Raises: + AttributeError: If the attribute is not found in any class in the MRO. + """ + if isinstance(tp, tuple): + for base in mro_for_bases(tp): + attribute = base.__dict__.get(name, _sentinel) + if attribute is not _sentinel: + attribute_get = getattr(attribute, '__get__', None) + if attribute_get is not None: + return attribute_get(None, tp) + return attribute + raise AttributeError(f'{name} not found in {tp}') + else: + try: + return getattr(tp, name) + except AttributeError: + return get_attribute_from_bases(mro(tp), name) + + +def get_attribute_from_base_dicts(tp: type[Any], name: str) -> Any: + """Get an attribute out of the `__dict__` following the MRO. + This prevents the call to `__get__` on the descriptor, and allows + us to get the original function for classmethod properties. + + Args: + tp: The type or class to search for the attribute. + name: The name of the attribute to retrieve. + + Returns: + Any: The attribute value, if found. + + Raises: + KeyError: If the attribute is not found in any class's `__dict__` in the MRO. + """ + for base in reversed(mro(tp)): + if name in base.__dict__: + return base.__dict__[name] + return tp.__dict__[name] # raise the error + + +@dataclass(**slots_true) +class DecoratorInfos: + """Mapping of name in the class namespace to decorator info. + + note that the name in the class namespace is the function or attribute name + not the field name! + """ + + validators: dict[str, Decorator[ValidatorDecoratorInfo]] = field(default_factory=dict) + field_validators: dict[str, Decorator[FieldValidatorDecoratorInfo]] = field(default_factory=dict) + root_validators: dict[str, Decorator[RootValidatorDecoratorInfo]] = field(default_factory=dict) + field_serializers: dict[str, Decorator[FieldSerializerDecoratorInfo]] = field(default_factory=dict) + model_serializers: dict[str, Decorator[ModelSerializerDecoratorInfo]] = field(default_factory=dict) + model_validators: dict[str, Decorator[ModelValidatorDecoratorInfo]] = field(default_factory=dict) + computed_fields: dict[str, Decorator[ComputedFieldInfo]] = field(default_factory=dict) + + @staticmethod + def build(model_dc: type[Any]) -> DecoratorInfos: # noqa: C901 (ignore complexity) + """We want to collect all DecFunc instances that exist as + attributes in the namespace of the class (a BaseModel or dataclass) + that called us + But we want to collect these in the order of the bases + So instead of getting them all from the leaf class (the class that called us), + we traverse the bases from root (the oldest ancestor class) to leaf + and collect all of the instances as we go, taking care to replace + any duplicate ones with the last one we see to mimic how function overriding + works with inheritance. + If we do replace any functions we put the replacement into the position + the replaced function was in; that is, we maintain the order. + """ + # reminder: dicts are ordered and replacement does not alter the order + res = DecoratorInfos() + for base in reversed(mro(model_dc)[1:]): + existing: DecoratorInfos | None = base.__dict__.get('__pydantic_decorators__') + if existing is None: + existing = DecoratorInfos.build(base) + res.validators.update({k: v.bind_to_cls(model_dc) for k, v in existing.validators.items()}) + res.field_validators.update({k: v.bind_to_cls(model_dc) for k, v in existing.field_validators.items()}) + res.root_validators.update({k: v.bind_to_cls(model_dc) for k, v in existing.root_validators.items()}) + res.field_serializers.update({k: v.bind_to_cls(model_dc) for k, v in existing.field_serializers.items()}) + res.model_serializers.update({k: v.bind_to_cls(model_dc) for k, v in existing.model_serializers.items()}) + res.model_validators.update({k: v.bind_to_cls(model_dc) for k, v in existing.model_validators.items()}) + res.computed_fields.update({k: v.bind_to_cls(model_dc) for k, v in existing.computed_fields.items()}) + + to_replace: list[tuple[str, Any]] = [] + + for var_name, var_value in vars(model_dc).items(): + if isinstance(var_value, PydanticDescriptorProxy): + info = var_value.decorator_info + if isinstance(info, ValidatorDecoratorInfo): + res.validators[var_name] = Decorator.build( + model_dc, cls_var_name=var_name, shim=var_value.shim, info=info + ) + elif isinstance(info, FieldValidatorDecoratorInfo): + res.field_validators[var_name] = Decorator.build( + model_dc, cls_var_name=var_name, shim=var_value.shim, info=info + ) + elif isinstance(info, RootValidatorDecoratorInfo): + res.root_validators[var_name] = Decorator.build( + model_dc, cls_var_name=var_name, shim=var_value.shim, info=info + ) + elif isinstance(info, FieldSerializerDecoratorInfo): + # check whether a serializer function is already registered for fields + for field_serializer_decorator in res.field_serializers.values(): + # check that each field has at most one serializer function. + # serializer functions for the same field in subclasses are allowed, + # and are treated as overrides + if field_serializer_decorator.cls_var_name == var_name: + continue + for f in info.fields: + if f in field_serializer_decorator.info.fields: + raise PydanticUserError( + 'Multiple field serializer functions were defined ' + f'for field {f!r}, this is not allowed.', + code='multiple-field-serializers', + ) + res.field_serializers[var_name] = Decorator.build( + model_dc, cls_var_name=var_name, shim=var_value.shim, info=info + ) + elif isinstance(info, ModelValidatorDecoratorInfo): + res.model_validators[var_name] = Decorator.build( + model_dc, cls_var_name=var_name, shim=var_value.shim, info=info + ) + elif isinstance(info, ModelSerializerDecoratorInfo): + res.model_serializers[var_name] = Decorator.build( + model_dc, cls_var_name=var_name, shim=var_value.shim, info=info + ) + else: + from ..fields import ComputedFieldInfo + + isinstance(var_value, ComputedFieldInfo) + res.computed_fields[var_name] = Decorator.build( + model_dc, cls_var_name=var_name, shim=None, info=info + ) + to_replace.append((var_name, var_value.wrapped)) + if to_replace: + # If we can save `__pydantic_decorators__` on the class we'll be able to check for it above + # so then we don't need to re-process the type, which means we can discard our descriptor wrappers + # and replace them with the thing they are wrapping (see the other setattr call below) + # which allows validator class methods to also function as regular class methods + model_dc.__pydantic_decorators__ = res + for name, value in to_replace: + setattr(model_dc, name, value) + return res + + def update_from_config(self, config_wrapper: ConfigWrapper) -> None: + """Update the decorator infos from the configuration of the class they are attached to.""" + for name, computed_field_dec in self.computed_fields.items(): + computed_field_dec.info._update_from_config(config_wrapper, name) + + +def inspect_validator( + validator: Callable[..., Any], *, mode: FieldValidatorModes, type: Literal['field', 'model'] +) -> bool: + """Look at a field or model validator function and determine whether it takes an info argument. + + An error is raised if the function has an invalid signature. + + Args: + validator: The validator function to inspect. + mode: The proposed validator mode. + type: The type of validator, either 'field' or 'model'. + + Returns: + Whether the validator takes an info argument. + """ + try: + sig = _signature_no_eval(validator) + except (ValueError, TypeError): + # `inspect.signature` might not be able to infer a signature, e.g. with C objects. + # In this case, we assume no info argument is present: + return False + n_positional = count_positional_required_params(sig) + if mode == 'wrap': + if n_positional == 3: + return True + elif n_positional == 2: + return False + else: + assert mode in {'before', 'after', 'plain'}, f"invalid mode: {mode!r}, expected 'before', 'after' or 'plain" + if n_positional == 2: + return True + elif n_positional == 1: + return False + + raise PydanticUserError( + f'Unrecognized {type} validator function signature for {validator} with `mode={mode}`: {sig}', + code='validator-signature', + ) + + +def inspect_field_serializer(serializer: Callable[..., Any], mode: Literal['plain', 'wrap']) -> tuple[bool, bool]: + """Look at a field serializer function and determine if it is a field serializer, + and whether it takes an info argument. + + An error is raised if the function has an invalid signature. + + Args: + serializer: The serializer function to inspect. + mode: The serializer mode, either 'plain' or 'wrap'. + + Returns: + Tuple of (is_field_serializer, info_arg). + """ + try: + sig = _signature_no_eval(serializer) + except (ValueError, TypeError): + # `inspect.signature` might not be able to infer a signature, e.g. with C objects. + # In this case, we assume no info argument is present and this is not a method: + return (False, False) + + first = next(iter(sig.parameters.values()), None) + is_field_serializer = first is not None and first.name == 'self' + + n_positional = count_positional_required_params(sig) + if is_field_serializer: + # -1 to correct for self parameter + info_arg = _serializer_info_arg(mode, n_positional - 1) + else: + info_arg = _serializer_info_arg(mode, n_positional) + + if info_arg is None: + raise PydanticUserError( + f'Unrecognized field_serializer function signature for {serializer} with `mode={mode}`:{sig}', + code='field-serializer-signature', + ) + + return is_field_serializer, info_arg + + +def inspect_annotated_serializer(serializer: Callable[..., Any], mode: Literal['plain', 'wrap']) -> bool: + """Look at a serializer function used via `Annotated` and determine whether it takes an info argument. + + An error is raised if the function has an invalid signature. + + Args: + serializer: The serializer function to check. + mode: The serializer mode, either 'plain' or 'wrap'. + + Returns: + info_arg + """ + try: + sig = _signature_no_eval(serializer) + except (ValueError, TypeError): + # `inspect.signature` might not be able to infer a signature, e.g. with C objects. + # In this case, we assume no info argument is present: + return False + info_arg = _serializer_info_arg(mode, count_positional_required_params(sig)) + if info_arg is None: + raise PydanticUserError( + f'Unrecognized field_serializer function signature for {serializer} with `mode={mode}`:{sig}', + code='field-serializer-signature', + ) + else: + return info_arg + + +def inspect_model_serializer(serializer: Callable[..., Any], mode: Literal['plain', 'wrap']) -> bool: + """Look at a model serializer function and determine whether it takes an info argument. + + An error is raised if the function has an invalid signature. + + Args: + serializer: The serializer function to check. + mode: The serializer mode, either 'plain' or 'wrap'. + + Returns: + `info_arg` - whether the function expects an info argument. + """ + if isinstance(serializer, (staticmethod, classmethod)) or not is_instance_method_from_sig(serializer): + raise PydanticUserError( + '`@model_serializer` must be applied to instance methods', code='model-serializer-instance-method' + ) + + sig = _signature_no_eval(serializer) + info_arg = _serializer_info_arg(mode, count_positional_required_params(sig)) + if info_arg is None: + raise PydanticUserError( + f'Unrecognized model_serializer function signature for {serializer} with `mode={mode}`:{sig}', + code='model-serializer-signature', + ) + else: + return info_arg + + +def _serializer_info_arg(mode: Literal['plain', 'wrap'], n_positional: int) -> bool | None: + if mode == 'plain': + if n_positional == 1: + # (input_value: Any, /) -> Any + return False + elif n_positional == 2: + # (model: Any, input_value: Any, /) -> Any + return True + else: + assert mode == 'wrap', f"invalid mode: {mode!r}, expected 'plain' or 'wrap'" + if n_positional == 2: + # (input_value: Any, serializer: SerializerFunctionWrapHandler, /) -> Any + return False + elif n_positional == 3: + # (input_value: Any, serializer: SerializerFunctionWrapHandler, info: SerializationInfo, /) -> Any + return True + + return None + + +AnyDecoratorCallable: TypeAlias = ( + 'Union[classmethod[Any, Any, Any], staticmethod[Any, Any], partialmethod[Any], Callable[..., Any]]' +) + + +def is_instance_method_from_sig(function: AnyDecoratorCallable) -> bool: + """Whether the function is an instance method. + + It will consider a function as instance method if the first parameter of + function is `self`. + + Args: + function: The function to check. + + Returns: + `True` if the function is an instance method, `False` otherwise. + """ + sig = _signature_no_eval(unwrap_wrapped_function(function)) + first = next(iter(sig.parameters.values()), None) + if first and first.name == 'self': + return True + return False + + +def ensure_classmethod_based_on_signature(function: AnyDecoratorCallable) -> Any: + """Apply the `@classmethod` decorator on the function. + + Args: + function: The function to apply the decorator on. + + Return: + The `@classmethod` decorator applied function. + """ + if not isinstance( + unwrap_wrapped_function(function, unwrap_class_static_method=False), classmethod + ) and _is_classmethod_from_sig(function): + return classmethod(function) # type: ignore[arg-type] + return function + + +def _is_classmethod_from_sig(function: AnyDecoratorCallable) -> bool: + sig = _signature_no_eval(unwrap_wrapped_function(function)) + first = next(iter(sig.parameters.values()), None) + if first and first.name == 'cls': + return True + return False + + +def unwrap_wrapped_function( + func: Any, + *, + unwrap_partial: bool = True, + unwrap_class_static_method: bool = True, +) -> Any: + """Recursively unwraps a wrapped function until the underlying function is reached. + This handles property, functools.partial, functools.partialmethod, staticmethod, and classmethod. + + Args: + func: The function to unwrap. + unwrap_partial: If True (default), unwrap partial and partialmethod decorators. + unwrap_class_static_method: If True (default), also unwrap classmethod and staticmethod + decorators. If False, only unwrap partial and partialmethod decorators. + + Returns: + The underlying function of the wrapped function. + """ + # Define the types we want to check against as a single tuple. + unwrap_types = ( + (property, cached_property) + + ((partial, partialmethod) if unwrap_partial else ()) + + ((staticmethod, classmethod) if unwrap_class_static_method else ()) + ) + + while isinstance(func, unwrap_types): + if unwrap_class_static_method and isinstance(func, (classmethod, staticmethod)): + func = func.__func__ + elif isinstance(func, (partial, partialmethod)): + func = func.func + elif isinstance(func, property): + func = func.fget # arbitrary choice, convenient for computed fields + else: + # Make coverage happy as it can only get here in the last possible case + assert isinstance(func, cached_property) + func = func.func # type: ignore + + return func + + +_function_like = ( + partial, + partialmethod, + types.FunctionType, + types.BuiltinFunctionType, + types.MethodType, + types.WrapperDescriptorType, + types.MethodWrapperType, + types.MemberDescriptorType, +) + + +def get_callable_return_type( + callable_obj: Any, + globalns: GlobalsNamespace | None = None, + localns: MappingNamespace | None = None, +) -> Any | PydanticUndefinedType: + """Get the callable return type. + + Args: + callable_obj: The callable to analyze. + globalns: The globals namespace to use during type annotation evaluation. + localns: The locals namespace to use during type annotation evaluation. + + Returns: + The function return type. + """ + if isinstance(callable_obj, type): + # types are callables, and we assume the return type + # is the type itself (e.g. `int()` results in an instance of `int`). + return callable_obj + + if not isinstance(callable_obj, _function_like): + call_func = getattr(type(callable_obj), '__call__', None) # noqa: B004 + if call_func is not None: + callable_obj = call_func + + hints = get_function_type_hints( + unwrap_wrapped_function(callable_obj), + include_keys={'return'}, + globalns=globalns, + localns=localns, + ) + return hints.get('return', PydanticUndefined) + + +def count_positional_required_params(sig: Signature) -> int: + """Get the number of positional (required) arguments of a signature. + + This function should only be used to inspect signatures of validation and serialization functions. + The first argument (the value being serialized or validated) is counted as a required argument + even if a default value exists. + + Returns: + The number of positional arguments of a signature. + """ + parameters = list(sig.parameters.values()) + return sum( + 1 + for param in parameters + if can_be_positional(param) + # First argument is the value being validated/serialized, and can have a default value + # (e.g. `float`, which has signature `(x=0, /)`). We assume other parameters (the info arg + # for instance) should be required, and thus without any default value. + and (param.default is Parameter.empty or param is parameters[0]) + ) + + +def ensure_property(f: Any) -> Any: + """Ensure that a function is a `property` or `cached_property`, or is a valid descriptor. + + Args: + f: The function to check. + + Returns: + The function, or a `property` or `cached_property` instance wrapping the function. + """ + if ismethoddescriptor(f) or isdatadescriptor(f): + return f + else: + return property(f) + + +def _signature_no_eval(f: Callable[..., Any]) -> Signature: + """Get the signature of a callable without evaluating any annotations.""" + if sys.version_info >= (3, 14): + from annotationlib import Format + + return signature(f, annotation_format=Format.FORWARDREF) + else: + return signature(f) diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_decorators_v1.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_decorators_v1.py new file mode 100644 index 0000000..3427377 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_decorators_v1.py @@ -0,0 +1,174 @@ +"""Logic for V1 validators, e.g. `@validator` and `@root_validator`.""" + +from __future__ import annotations as _annotations + +from inspect import Parameter, signature +from typing import Any, Union, cast + +from pydantic_core import core_schema +from typing_extensions import Protocol + +from ..errors import PydanticUserError +from ._utils import can_be_positional + + +class V1OnlyValueValidator(Protocol): + """A simple validator, supported for V1 validators and V2 validators.""" + + def __call__(self, __value: Any) -> Any: ... + + +class V1ValidatorWithValues(Protocol): + """A validator with `values` argument, supported for V1 validators and V2 validators.""" + + def __call__(self, __value: Any, values: dict[str, Any]) -> Any: ... + + +class V1ValidatorWithValuesKwOnly(Protocol): + """A validator with keyword only `values` argument, supported for V1 validators and V2 validators.""" + + def __call__(self, __value: Any, *, values: dict[str, Any]) -> Any: ... + + +class V1ValidatorWithKwargs(Protocol): + """A validator with `kwargs` argument, supported for V1 validators and V2 validators.""" + + def __call__(self, __value: Any, **kwargs: Any) -> Any: ... + + +class V1ValidatorWithValuesAndKwargs(Protocol): + """A validator with `values` and `kwargs` arguments, supported for V1 validators and V2 validators.""" + + def __call__(self, __value: Any, values: dict[str, Any], **kwargs: Any) -> Any: ... + + +V1Validator = Union[ + V1ValidatorWithValues, V1ValidatorWithValuesKwOnly, V1ValidatorWithKwargs, V1ValidatorWithValuesAndKwargs +] + + +def can_be_keyword(param: Parameter) -> bool: + return param.kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY) + + +def make_generic_v1_field_validator(validator: V1Validator) -> core_schema.WithInfoValidatorFunction: + """Wrap a V1 style field validator for V2 compatibility. + + Args: + validator: The V1 style field validator. + + Returns: + A wrapped V2 style field validator. + + Raises: + PydanticUserError: If the signature is not supported or the parameters are + not available in Pydantic V2. + """ + sig = signature(validator) + + needs_values_kw = False + + for param_num, (param_name, parameter) in enumerate(sig.parameters.items()): + if can_be_keyword(parameter) and param_name in ('field', 'config'): + raise PydanticUserError( + 'The `field` and `config` parameters are not available in Pydantic V2, ' + 'please use the `info` parameter instead.', + code='validator-field-config-info', + ) + if parameter.kind is Parameter.VAR_KEYWORD: + needs_values_kw = True + elif can_be_keyword(parameter) and param_name == 'values': + needs_values_kw = True + elif can_be_positional(parameter) and param_num == 0: + # value + continue + elif parameter.default is Parameter.empty: # ignore params with defaults e.g. bound by functools.partial + raise PydanticUserError( + f'Unsupported signature for V1 style validator {validator}: {sig} is not supported.', + code='validator-v1-signature', + ) + + if needs_values_kw: + # (v, **kwargs), (v, values, **kwargs), (v, *, values, **kwargs) or (v, *, values) + val1 = cast(V1ValidatorWithValues, validator) + + def wrapper1(value: Any, info: core_schema.ValidationInfo) -> Any: + return val1(value, values=info.data) + + return wrapper1 + else: + val2 = cast(V1OnlyValueValidator, validator) + + def wrapper2(value: Any, _: core_schema.ValidationInfo) -> Any: + return val2(value) + + return wrapper2 + + +RootValidatorValues = dict[str, Any] +# technically tuple[model_dict, model_extra, fields_set] | tuple[dataclass_dict, init_vars] +RootValidatorFieldsTuple = tuple[Any, ...] + + +class V1RootValidatorFunction(Protocol): + """A simple root validator, supported for V1 validators and V2 validators.""" + + def __call__(self, __values: RootValidatorValues) -> RootValidatorValues: ... + + +class V2CoreBeforeRootValidator(Protocol): + """V2 validator with mode='before'.""" + + def __call__(self, __values: RootValidatorValues, __info: core_schema.ValidationInfo) -> RootValidatorValues: ... + + +class V2CoreAfterRootValidator(Protocol): + """V2 validator with mode='after'.""" + + def __call__( + self, __fields_tuple: RootValidatorFieldsTuple, __info: core_schema.ValidationInfo + ) -> RootValidatorFieldsTuple: ... + + +def make_v1_generic_root_validator( + validator: V1RootValidatorFunction, pre: bool +) -> V2CoreBeforeRootValidator | V2CoreAfterRootValidator: + """Wrap a V1 style root validator for V2 compatibility. + + Args: + validator: The V1 style field validator. + pre: Whether the validator is a pre validator. + + Returns: + A wrapped V2 style validator. + """ + if pre is True: + # mode='before' for pydantic-core + def _wrapper1(values: RootValidatorValues, _: core_schema.ValidationInfo) -> RootValidatorValues: + return validator(values) + + return _wrapper1 + + # mode='after' for pydantic-core + def _wrapper2(fields_tuple: RootValidatorFieldsTuple, _: core_schema.ValidationInfo) -> RootValidatorFieldsTuple: + if len(fields_tuple) == 2: + # dataclass, this is easy + values, init_vars = fields_tuple + values = validator(values) + return values, init_vars + else: + # ugly hack: to match v1 behaviour, we merge values and model_extra, then split them up based on fields + # afterwards + model_dict, model_extra, fields_set = fields_tuple + if model_extra: + fields = set(model_dict.keys()) + model_dict.update(model_extra) + model_dict_new = validator(model_dict) + for k in list(model_dict_new.keys()): + if k not in fields: + model_extra[k] = model_dict_new.pop(k) + else: + model_dict_new = validator(model_dict) + return model_dict_new, model_extra, fields_set + + return _wrapper2 diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_discriminated_union.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_discriminated_union.py new file mode 100644 index 0000000..5dd6fda --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_discriminated_union.py @@ -0,0 +1,479 @@ +from __future__ import annotations as _annotations + +from collections.abc import Hashable, Sequence +from typing import TYPE_CHECKING, Any, cast + +from pydantic_core import CoreSchema, core_schema + +from ..errors import PydanticUserError +from . import _core_utils +from ._core_utils import ( + CoreSchemaField, +) + +if TYPE_CHECKING: + from ..types import Discriminator + from ._core_metadata import CoreMetadata + + +class MissingDefinitionForUnionRef(Exception): + """Raised when applying a discriminated union discriminator to a schema + requires a definition that is not yet defined + """ + + def __init__(self, ref: str) -> None: + self.ref = ref + super().__init__(f'Missing definition for ref {self.ref!r}') + + +def set_discriminator_in_metadata(schema: CoreSchema, discriminator: Any) -> None: + metadata = cast('CoreMetadata', schema.setdefault('metadata', {})) + metadata['pydantic_internal_union_discriminator'] = discriminator + + +def apply_discriminator( + schema: core_schema.CoreSchema, + discriminator: str | Discriminator, + definitions: dict[str, core_schema.CoreSchema] | None = None, +) -> core_schema.CoreSchema: + """Applies the discriminator and returns a new core schema. + + Args: + schema: The input schema. + discriminator: The name of the field which will serve as the discriminator. + definitions: A mapping of schema ref to schema. + + Returns: + The new core schema. + + Raises: + TypeError: + - If `discriminator` is used with invalid union variant. + - If `discriminator` is used with `Union` type with one variant. + - If `discriminator` value mapped to multiple choices. + MissingDefinitionForUnionRef: + If the definition for ref is missing. + PydanticUserError: + - If a model in union doesn't have a discriminator field. + - If discriminator field has a non-string alias. + - If discriminator fields have different aliases. + - If discriminator field not of type `Literal`. + """ + from ..types import Discriminator + + if isinstance(discriminator, Discriminator): + if isinstance(discriminator.discriminator, str): + discriminator = discriminator.discriminator + else: + return discriminator._convert_schema(schema) + + return _ApplyInferredDiscriminator(discriminator, definitions or {}).apply(schema) + + +class _ApplyInferredDiscriminator: + """This class is used to convert an input schema containing a union schema into one where that union is + replaced with a tagged-union, with all the associated debugging and performance benefits. + + This is done by: + * Validating that the input schema is compatible with the provided discriminator + * Introspecting the schema to determine which discriminator values should map to which union choices + * Handling various edge cases such as 'definitions', 'default', 'nullable' schemas, and more + + I have chosen to implement the conversion algorithm in this class, rather than a function, + to make it easier to maintain state while recursively walking the provided CoreSchema. + """ + + def __init__(self, discriminator: str, definitions: dict[str, core_schema.CoreSchema]): + # `discriminator` should be the name of the field which will serve as the discriminator. + # It must be the python name of the field, and *not* the field's alias. Note that as of now, + # all members of a discriminated union _must_ use a field with the same name as the discriminator. + # This may change if/when we expose a way to manually specify the TaggedUnionSchema's choices. + self.discriminator = discriminator + + # `definitions` should contain a mapping of schema ref to schema for all schemas which might + # be referenced by some choice + self.definitions = definitions + + # `_discriminator_alias` will hold the value, if present, of the alias for the discriminator + # + # Note: following the v1 implementation, we currently disallow the use of different aliases + # for different choices. This is not a limitation of pydantic_core, but if we try to handle + # this, the inference logic gets complicated very quickly, and could result in confusing + # debugging challenges for users making subtle mistakes. + # + # Rather than trying to do the most powerful inference possible, I think we should eventually + # expose a way to more-manually control the way the TaggedUnionSchema is constructed through + # the use of a new type which would be placed as an Annotation on the Union type. This would + # provide the full flexibility/power of pydantic_core's TaggedUnionSchema where necessary for + # more complex cases, without over-complicating the inference logic for the common cases. + self._discriminator_alias: str | None = None + + # `_should_be_nullable` indicates whether the converted union has `None` as an allowed value. + # If `None` is an acceptable value of the (possibly-wrapped) union, we ignore it while + # constructing the TaggedUnionSchema, but set the `_should_be_nullable` attribute to True. + # Once we have constructed the TaggedUnionSchema, if `_should_be_nullable` is True, we ensure + # that the final schema gets wrapped as a NullableSchema. This has the same semantics on the + # python side, but resolves the issue that `None` cannot correspond to any discriminator values. + self._should_be_nullable = False + + # `_is_nullable` is used to track if the final produced schema will definitely be nullable; + # we set it to True if the input schema is wrapped in a nullable schema that we know will be preserved + # as an indication that, even if None is discovered as one of the union choices, we will not need to wrap + # the final value in another nullable schema. + # + # This is more complicated than just checking for the final outermost schema having type 'nullable' thanks + # to the possible presence of other wrapper schemas such as DefinitionsSchema, WithDefaultSchema, etc. + self._is_nullable = False + + # `_choices_to_handle` serves as a stack of choices to add to the tagged union. Initially, choices + # from the union in the wrapped schema will be appended to this list, and the recursive choice-handling + # algorithm may add more choices to this stack as (nested) unions are encountered. + self._choices_to_handle: list[core_schema.CoreSchema] = [] + + # `_tagged_union_choices` is built during the call to `apply`, and will hold the choices to be included + # in the output TaggedUnionSchema that will replace the union from the input schema + self._tagged_union_choices: dict[Hashable, core_schema.CoreSchema] = {} + + # `_used` is changed to True after applying the discriminator to prevent accidental reuse + self._used = False + + def apply(self, schema: core_schema.CoreSchema) -> core_schema.CoreSchema: + """Return a new CoreSchema based on `schema` that uses a tagged-union with the discriminator provided + to this class. + + Args: + schema: The input schema. + + Returns: + The new core schema. + + Raises: + TypeError: + - If `discriminator` is used with invalid union variant. + - If `discriminator` is used with `Union` type with one variant. + - If `discriminator` value mapped to multiple choices. + ValueError: + If the definition for ref is missing. + PydanticUserError: + - If a model in union doesn't have a discriminator field. + - If discriminator field has a non-string alias. + - If discriminator fields have different aliases. + - If discriminator field not of type `Literal`. + """ + assert not self._used + schema = self._apply_to_root(schema) + if self._should_be_nullable and not self._is_nullable: + schema = core_schema.nullable_schema(schema) + self._used = True + return schema + + def _apply_to_root(self, schema: core_schema.CoreSchema) -> core_schema.CoreSchema: + """This method handles the outer-most stage of recursion over the input schema: + unwrapping nullable or definitions schemas, and calling the `_handle_choice` + method iteratively on the choices extracted (recursively) from the possibly-wrapped union. + """ + if schema['type'] == 'nullable': + self._is_nullable = True + wrapped = self._apply_to_root(schema['schema']) + nullable_wrapper = schema.copy() + nullable_wrapper['schema'] = wrapped + return nullable_wrapper + + if schema['type'] == 'definitions': + wrapped = self._apply_to_root(schema['schema']) + definitions_wrapper = schema.copy() + definitions_wrapper['schema'] = wrapped + return definitions_wrapper + + if schema['type'] != 'union': + # If the schema is not a union, it probably means it just had a single member and + # was flattened by pydantic_core. + # However, it still may make sense to apply the discriminator to this schema, + # as a way to get discriminated-union-style error messages, so we allow this here. + schema = core_schema.union_schema([schema]) + + # Reverse the choices list before extending the stack so that they get handled in the order they occur + choices_schemas = [v[0] if isinstance(v, tuple) else v for v in schema['choices'][::-1]] + self._choices_to_handle.extend(choices_schemas) + while self._choices_to_handle: + choice = self._choices_to_handle.pop() + self._handle_choice(choice) + + if self._discriminator_alias is not None and self._discriminator_alias != self.discriminator: + # * We need to annotate `discriminator` as a union here to handle both branches of this conditional + # * We need to annotate `discriminator` as list[list[str | int]] and not list[list[str]] due to the + # invariance of list, and because list[list[str | int]] is the type of the discriminator argument + # to tagged_union_schema below + # * See the docstring of pydantic_core.core_schema.tagged_union_schema for more details about how to + # interpret the value of the discriminator argument to tagged_union_schema. (The list[list[str]] here + # is the appropriate way to provide a list of fallback attributes to check for a discriminator value.) + discriminator: str | list[list[str | int]] = [[self.discriminator], [self._discriminator_alias]] + else: + discriminator = self.discriminator + return core_schema.tagged_union_schema( + choices=self._tagged_union_choices, + discriminator=discriminator, + custom_error_type=schema.get('custom_error_type'), + custom_error_message=schema.get('custom_error_message'), + custom_error_context=schema.get('custom_error_context'), + strict=False, + from_attributes=True, + ref=schema.get('ref'), + metadata=schema.get('metadata'), + serialization=schema.get('serialization'), + ) + + def _handle_choice(self, choice: core_schema.CoreSchema) -> None: + """This method handles the "middle" stage of recursion over the input schema. + Specifically, it is responsible for handling each choice of the outermost union + (and any "coalesced" choices obtained from inner unions). + + Here, "handling" entails: + * Coalescing nested unions and compatible tagged-unions + * Tracking the presence of 'none' and 'nullable' schemas occurring as choices + * Validating that each allowed discriminator value maps to a unique choice + * Updating the _tagged_union_choices mapping that will ultimately be used to build the TaggedUnionSchema. + """ + if choice['type'] == 'definition-ref': + if choice['schema_ref'] not in self.definitions: + raise MissingDefinitionForUnionRef(choice['schema_ref']) + + if choice['type'] == 'none': + self._should_be_nullable = True + elif choice['type'] == 'definitions': + self._handle_choice(choice['schema']) + elif choice['type'] == 'nullable': + self._should_be_nullable = True + self._handle_choice(choice['schema']) # unwrap the nullable schema + elif choice['type'] == 'union': + # Reverse the choices list before extending the stack so that they get handled in the order they occur + choices_schemas = [v[0] if isinstance(v, tuple) else v for v in choice['choices'][::-1]] + self._choices_to_handle.extend(choices_schemas) + elif choice['type'] not in { + 'model', + 'typed-dict', + 'tagged-union', + 'lax-or-strict', + 'dataclass', + 'dataclass-args', + 'definition-ref', + } and not _core_utils.is_function_with_inner_schema(choice): + # We should eventually handle 'definition-ref' as well + err_str = f'The core schema type {choice["type"]!r} is not a valid discriminated union variant.' + if choice['type'] == 'list': + err_str += ( + ' If you are making use of a list of union types, make sure the discriminator is applied to the ' + 'union type and not the list (e.g. `list[Annotated[ | , Field(discriminator=...)]]`).' + ) + raise TypeError(err_str) + else: + if choice['type'] == 'tagged-union' and self._is_discriminator_shared(choice): + # In this case, this inner tagged-union is compatible with the outer tagged-union, + # and its choices can be coalesced into the outer TaggedUnionSchema. + subchoices = [x for x in choice['choices'].values() if not isinstance(x, (str, int))] + # Reverse the choices list before extending the stack so that they get handled in the order they occur + self._choices_to_handle.extend(subchoices[::-1]) + return + + inferred_discriminator_values = self._infer_discriminator_values_for_choice(choice, source_name=None) + self._set_unique_choice_for_values(choice, inferred_discriminator_values) + + def _is_discriminator_shared(self, choice: core_schema.TaggedUnionSchema) -> bool: + """This method returns a boolean indicating whether the discriminator for the `choice` + is the same as that being used for the outermost tagged union. This is used to + determine whether this TaggedUnionSchema choice should be "coalesced" into the top level, + or whether it should be treated as a separate (nested) choice. + """ + inner_discriminator = choice['discriminator'] + return inner_discriminator == self.discriminator or ( + isinstance(inner_discriminator, list) + and (self.discriminator in inner_discriminator or [self.discriminator] in inner_discriminator) + ) + + def _infer_discriminator_values_for_choice( # noqa C901 + self, choice: core_schema.CoreSchema, source_name: str | None + ) -> list[str | int]: + """This function recurses over `choice`, extracting all discriminator values that should map to this choice. + + `model_name` is accepted for the purpose of producing useful error messages. + """ + if choice['type'] == 'definitions': + return self._infer_discriminator_values_for_choice(choice['schema'], source_name=source_name) + + elif _core_utils.is_function_with_inner_schema(choice): + return self._infer_discriminator_values_for_choice(choice['schema'], source_name=source_name) + + elif choice['type'] == 'lax-or-strict': + return sorted( + set( + self._infer_discriminator_values_for_choice(choice['lax_schema'], source_name=None) + + self._infer_discriminator_values_for_choice(choice['strict_schema'], source_name=None) + ) + ) + + elif choice['type'] == 'tagged-union': + values: list[str | int] = [] + # Ignore str/int "choices" since these are just references to other choices + subchoices = [x for x in choice['choices'].values() if not isinstance(x, (str, int))] + for subchoice in subchoices: + subchoice_values = self._infer_discriminator_values_for_choice(subchoice, source_name=None) + values.extend(subchoice_values) + return values + + elif choice['type'] == 'union': + values = [] + for subchoice in choice['choices']: + subchoice_schema = subchoice[0] if isinstance(subchoice, tuple) else subchoice + subchoice_values = self._infer_discriminator_values_for_choice(subchoice_schema, source_name=None) + values.extend(subchoice_values) + return values + + elif choice['type'] == 'nullable': + self._should_be_nullable = True + return self._infer_discriminator_values_for_choice(choice['schema'], source_name=None) + + elif choice['type'] == 'model': + return self._infer_discriminator_values_for_choice(choice['schema'], source_name=choice['cls'].__name__) + + elif choice['type'] == 'dataclass': + return self._infer_discriminator_values_for_choice(choice['schema'], source_name=choice['cls'].__name__) + + elif choice['type'] == 'model-fields': + return self._infer_discriminator_values_for_model_choice(choice, source_name=source_name) + + elif choice['type'] == 'dataclass-args': + return self._infer_discriminator_values_for_dataclass_choice(choice, source_name=source_name) + + elif choice['type'] == 'typed-dict': + return self._infer_discriminator_values_for_typed_dict_choice(choice, source_name=source_name) + + elif choice['type'] == 'definition-ref': + schema_ref = choice['schema_ref'] + if schema_ref not in self.definitions: + raise MissingDefinitionForUnionRef(schema_ref) + return self._infer_discriminator_values_for_choice(self.definitions[schema_ref], source_name=source_name) + else: + err_str = f'The core schema type {choice["type"]!r} is not a valid discriminated union variant.' + if choice['type'] == 'list': + err_str += ( + ' If you are making use of a list of union types, make sure the discriminator is applied to the ' + 'union type and not the list (e.g. `list[Annotated[ | , Field(discriminator=...)]]`).' + ) + raise TypeError(err_str) + + def _infer_discriminator_values_for_typed_dict_choice( + self, choice: core_schema.TypedDictSchema, source_name: str | None = None + ) -> list[str | int]: + """This method just extracts the _infer_discriminator_values_for_choice logic specific to TypedDictSchema + for the sake of readability. + """ + source = 'TypedDict' if source_name is None else f'TypedDict {source_name!r}' + field = choice['fields'].get(self.discriminator) + if field is None: + raise PydanticUserError( + f'{source} needs a discriminator field for key {self.discriminator!r}', code='discriminator-no-field' + ) + return self._infer_discriminator_values_for_field(field, source) + + def _infer_discriminator_values_for_model_choice( + self, choice: core_schema.ModelFieldsSchema, source_name: str | None = None + ) -> list[str | int]: + source = 'ModelFields' if source_name is None else f'Model {source_name!r}' + field = choice['fields'].get(self.discriminator) + if field is None: + raise PydanticUserError( + f'{source} needs a discriminator field for key {self.discriminator!r}', code='discriminator-no-field' + ) + return self._infer_discriminator_values_for_field(field, source) + + def _infer_discriminator_values_for_dataclass_choice( + self, choice: core_schema.DataclassArgsSchema, source_name: str | None = None + ) -> list[str | int]: + source = 'DataclassArgs' if source_name is None else f'Dataclass {source_name!r}' + for field in choice['fields']: + if field['name'] == self.discriminator: + break + else: + raise PydanticUserError( + f'{source} needs a discriminator field for key {self.discriminator!r}', code='discriminator-no-field' + ) + return self._infer_discriminator_values_for_field(field, source) + + def _infer_discriminator_values_for_field(self, field: CoreSchemaField, source: str) -> list[str | int]: + if field['type'] == 'computed-field': + # This should never occur as a discriminator, as it is only relevant to serialization + return [] + alias = field.get('validation_alias', self.discriminator) + if not isinstance(alias, str): + raise PydanticUserError( + f'Alias {alias!r} is not supported in a discriminated union', code='discriminator-alias-type' + ) + if self._discriminator_alias is None: + self._discriminator_alias = alias + elif self._discriminator_alias != alias: + raise PydanticUserError( + f'Aliases for discriminator {self.discriminator!r} must be the same ' + f'(got {alias}, {self._discriminator_alias})', + code='discriminator-alias', + ) + return self._infer_discriminator_values_for_inner_schema(field['schema'], source) + + def _infer_discriminator_values_for_inner_schema( + self, schema: core_schema.CoreSchema, source: str + ) -> list[str | int]: + """When inferring discriminator values for a field, we typically extract the expected values from a literal + schema. This function does that, but also handles nested unions and defaults. + """ + if schema['type'] == 'literal': + return schema['expected'] + + elif schema['type'] == 'union': + # Generally when multiple values are allowed they should be placed in a single `Literal`, but + # we add this case to handle the situation where a field is annotated as a `Union` of `Literal`s. + # For example, this lets us handle `Union[Literal['key'], Union[Literal['Key'], Literal['KEY']]]` + values: list[Any] = [] + for choice in schema['choices']: + choice_schema = choice[0] if isinstance(choice, tuple) else choice + choice_values = self._infer_discriminator_values_for_inner_schema(choice_schema, source) + values.extend(choice_values) + return values + + elif schema['type'] == 'default': + # This will happen if the field has a default value; we ignore it while extracting the discriminator values + return self._infer_discriminator_values_for_inner_schema(schema['schema'], source) + + elif schema['type'] == 'function-after': + # After validators don't affect the discriminator values + return self._infer_discriminator_values_for_inner_schema(schema['schema'], source) + + elif schema['type'] in {'function-before', 'function-wrap', 'function-plain'}: + validator_type = repr(schema['type'].split('-')[1]) + raise PydanticUserError( + f'Cannot use a mode={validator_type} validator in the' + f' discriminator field {self.discriminator!r} of {source}', + code='discriminator-validator', + ) + + else: + raise PydanticUserError( + f'{source} needs field {self.discriminator!r} to be of type `Literal`', + code='discriminator-needs-literal', + ) + + def _set_unique_choice_for_values(self, choice: core_schema.CoreSchema, values: Sequence[str | int]) -> None: + """This method updates `self.tagged_union_choices` so that all provided (discriminator) `values` map to the + provided `choice`, validating that none of these values already map to another (different) choice. + """ + for discriminator_value in values: + if discriminator_value in self._tagged_union_choices: + # It is okay if `value` is already in tagged_union_choices as long as it maps to the same value. + # Because tagged_union_choices may map values to other values, we need to walk the choices dict + # until we get to a "real" choice, and confirm that is equal to the one assigned. + existing_choice = self._tagged_union_choices[discriminator_value] + if existing_choice != choice: + raise TypeError( + f'Value {discriminator_value!r} for discriminator ' + f'{self.discriminator!r} mapped to multiple choices' + ) + else: + self._tagged_union_choices[discriminator_value] = choice diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_docs_extraction.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_docs_extraction.py new file mode 100644 index 0000000..6df77bf --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_docs_extraction.py @@ -0,0 +1,113 @@ +"""Utilities related to attribute docstring extraction.""" + +from __future__ import annotations + +import ast +import inspect +import sys +import textwrap +from typing import Any + + +class DocstringVisitor(ast.NodeVisitor): + def __init__(self) -> None: + super().__init__() + + self.target: str | None = None + self.attrs: dict[str, str] = {} + self.previous_node_type: type[ast.AST] | None = None + + def visit(self, node: ast.AST) -> Any: + node_result = super().visit(node) + self.previous_node_type = type(node) + return node_result + + def visit_AnnAssign(self, node: ast.AnnAssign) -> Any: + if isinstance(node.target, ast.Name): + self.target = node.target.id + + def visit_Expr(self, node: ast.Expr) -> Any: + if ( + isinstance(node.value, ast.Constant) + and isinstance(node.value.value, str) + and self.previous_node_type is ast.AnnAssign + ): + docstring = inspect.cleandoc(node.value.value) + if self.target: + self.attrs[self.target] = docstring + self.target = None + + +def _dedent_source_lines(source: list[str]) -> str: + # Required for nested class definitions, e.g. in a function block + dedent_source = textwrap.dedent(''.join(source)) + if dedent_source.startswith((' ', '\t')): + # We are in the case where there's a dedented (usually multiline) string + # at a lower indentation level than the class itself. We wrap our class + # in a function as a workaround. + dedent_source = f'def dedent_workaround():\n{dedent_source}' + return dedent_source + + +def _extract_source_from_frame(cls: type[Any]) -> list[str] | None: + frame = inspect.currentframe() + + while frame: + if inspect.getmodule(frame) is inspect.getmodule(cls): + lnum = frame.f_lineno + try: + lines, _ = inspect.findsource(frame) + except OSError: # pragma: no cover + # Source can't be retrieved (maybe because running in an interactive terminal), + # we don't want to error here. + pass + else: + block_lines = inspect.getblock(lines[lnum - 1 :]) + dedent_source = _dedent_source_lines(block_lines) + try: + block_tree = ast.parse(dedent_source) + except SyntaxError: + pass + else: + stmt = block_tree.body[0] + if isinstance(stmt, ast.FunctionDef) and stmt.name == 'dedent_workaround': + # `_dedent_source_lines` wrapped the class around the workaround function + stmt = stmt.body[0] + if isinstance(stmt, ast.ClassDef) and stmt.name == cls.__name__: + return block_lines + + frame = frame.f_back + + +def extract_docstrings_from_cls(cls: type[Any], use_inspect: bool = False) -> dict[str, str]: + """Map model attributes and their corresponding docstring. + + Args: + cls: The class of the Pydantic model to inspect. + use_inspect: Whether to skip usage of frames to find the object and use + the `inspect` module instead. + + Returns: + A mapping containing attribute names and their corresponding docstring. + """ + if use_inspect or sys.version_info >= (3, 13): + # On Python < 3.13, `inspect.getsourcelines()` might not work as expected + # if two classes have the same name in the same source file. + # On Python 3.13+, it will use the new `__firstlineno__` class attribute, + # making it way more robust. + try: + source, _ = inspect.getsourcelines(cls) + except OSError: # pragma: no cover + return {} + else: + # TODO remove this implementation when we drop support for Python 3.12: + source = _extract_source_from_frame(cls) + + if not source: + return {} + + dedent_source = _dedent_source_lines(source) + + visitor = DocstringVisitor() + visitor.visit(ast.parse(dedent_source)) + return visitor.attrs diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_fields.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_fields.py new file mode 100644 index 0000000..aad2ac9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_fields.py @@ -0,0 +1,635 @@ +"""Private logic related to fields (the `Field()` function and `FieldInfo` class), and arguments to `Annotated`.""" + +from __future__ import annotations as _annotations + +import dataclasses +import warnings +from collections.abc import Mapping +from functools import cache +from inspect import Parameter, ismethoddescriptor, signature +from re import Pattern +from typing import TYPE_CHECKING, Any, Callable, TypeVar + +from pydantic_core import PydanticUndefined +from typing_extensions import TypeIs +from typing_inspection.introspection import AnnotationSource + +from pydantic import PydanticDeprecatedSince211 +from pydantic.errors import PydanticUserError + +from ..aliases import AliasGenerator +from . import _generics, _typing_extra +from ._config import ConfigWrapper +from ._docs_extraction import extract_docstrings_from_cls +from ._import_utils import import_cached_base_model, import_cached_field_info +from ._namespace_utils import NsResolver +from ._repr import Representation +from ._utils import can_be_positional, get_first_not_none + +if TYPE_CHECKING: + from annotated_types import BaseMetadata + + from ..fields import FieldInfo + from ..main import BaseModel + from ._dataclasses import PydanticDataclass, StandardDataclass + from ._decorators import DecoratorInfos + + +class PydanticMetadata(Representation): + """Base class for annotation markers like `Strict`.""" + + __slots__ = () + + +def pydantic_general_metadata(**metadata: Any) -> BaseMetadata: + """Create a new `_PydanticGeneralMetadata` class with the given metadata. + + Args: + **metadata: The metadata to add. + + Returns: + The new `_PydanticGeneralMetadata` class. + """ + return _general_metadata_cls()(metadata) # type: ignore + + +@cache +def _general_metadata_cls() -> type[BaseMetadata]: + """Do it this way to avoid importing `annotated_types` at import time.""" + from annotated_types import BaseMetadata + + class _PydanticGeneralMetadata(PydanticMetadata, BaseMetadata): + """Pydantic general metadata like `max_digits`.""" + + def __init__(self, metadata: Any): + self.__dict__ = metadata + + return _PydanticGeneralMetadata # type: ignore + + +def _check_protected_namespaces( + protected_namespaces: tuple[str | Pattern[str], ...], + ann_name: str, + bases: tuple[type[Any], ...], + cls_name: str, +) -> None: + BaseModel = import_cached_base_model() + + for protected_namespace in protected_namespaces: + ns_violation = False + if isinstance(protected_namespace, Pattern): + ns_violation = protected_namespace.match(ann_name) is not None + elif isinstance(protected_namespace, str): + ns_violation = ann_name.startswith(protected_namespace) + + if ns_violation: + for b in bases: + if hasattr(b, ann_name): + if not (issubclass(b, BaseModel) and ann_name in getattr(b, '__pydantic_fields__', {})): + raise ValueError( + f'Field {ann_name!r} conflicts with member {getattr(b, ann_name)}' + f' of protected namespace {protected_namespace!r}.' + ) + else: + valid_namespaces: list[str] = [] + for pn in protected_namespaces: + if isinstance(pn, Pattern): + if not pn.match(ann_name): + valid_namespaces.append(f're.compile({pn.pattern!r})') + else: + if not ann_name.startswith(pn): + valid_namespaces.append(f"'{pn}'") + + valid_namespaces_str = f'({", ".join(valid_namespaces)}{",)" if len(valid_namespaces) == 1 else ")"}' + + warnings.warn( + f'Field {ann_name!r} in {cls_name!r} conflicts with protected namespace {protected_namespace!r}.\n\n' + f"You may be able to solve this by setting the 'protected_namespaces' configuration to {valid_namespaces_str}.", + UserWarning, + stacklevel=5, + ) + + +def _update_fields_from_docstrings(cls: type[Any], fields: dict[str, FieldInfo], use_inspect: bool = False) -> None: + fields_docs = extract_docstrings_from_cls(cls, use_inspect=use_inspect) + for ann_name, field_info in fields.items(): + if field_info.description is None and ann_name in fields_docs: + field_info.description = fields_docs[ann_name] + + +def _apply_field_title_generator_to_field_info( + title_generator: Callable[[str, FieldInfo], str], + field_name: str, + field_info: FieldInfo, +): + if field_info.title is None: + title = title_generator(field_name, field_info) + if not isinstance(title, str): + raise TypeError(f'field_title_generator {title_generator} must return str, not {title.__class__}') + + field_info.title = title + + +def _apply_alias_generator_to_field_info( + alias_generator: Callable[[str], str] | AliasGenerator, field_name: str, field_info: FieldInfo +): + """Apply an alias generator to aliases on a `FieldInfo` instance if appropriate. + + Args: + alias_generator: A callable that takes a string and returns a string, or an `AliasGenerator` instance. + field_name: The name of the field from which to generate the alias. + field_info: The `FieldInfo` instance to which the alias generator is (maybe) applied. + """ + # Apply an alias_generator if + # 1. An alias is not specified + # 2. An alias is specified, but the priority is <= 1 + if ( + field_info.alias_priority is None + or field_info.alias_priority <= 1 + or field_info.alias is None + or field_info.validation_alias is None + or field_info.serialization_alias is None + ): + alias, validation_alias, serialization_alias = None, None, None + + if isinstance(alias_generator, AliasGenerator): + alias, validation_alias, serialization_alias = alias_generator.generate_aliases(field_name) + elif callable(alias_generator): + alias = alias_generator(field_name) + if not isinstance(alias, str): + raise TypeError(f'alias_generator {alias_generator} must return str, not {alias.__class__}') + + # if priority is not set, we set to 1 + # which supports the case where the alias_generator from a child class is used + # to generate an alias for a field in a parent class + if field_info.alias_priority is None or field_info.alias_priority <= 1: + field_info.alias_priority = 1 + + # if the priority is 1, then we set the aliases to the generated alias + if field_info.alias_priority == 1: + field_info.serialization_alias = get_first_not_none(serialization_alias, alias) + field_info.validation_alias = get_first_not_none(validation_alias, alias) + field_info.alias = alias + + # if any of the aliases are not set, then we set them to the corresponding generated alias + if field_info.alias is None: + field_info.alias = alias + if field_info.serialization_alias is None: + field_info.serialization_alias = get_first_not_none(serialization_alias, alias) + if field_info.validation_alias is None: + field_info.validation_alias = get_first_not_none(validation_alias, alias) + + +def update_field_from_config(config_wrapper: ConfigWrapper, field_name: str, field_info: FieldInfo) -> None: + """Update the `FieldInfo` instance from the configuration set on the model it belongs to. + + This will apply the title and alias generators from the configuration. + + Args: + config_wrapper: The configuration from the model. + field_name: The field name the `FieldInfo` instance is attached to. + field_info: The `FieldInfo` instance to update. + """ + field_title_generator = field_info.field_title_generator or config_wrapper.field_title_generator + if field_title_generator is not None: + _apply_field_title_generator_to_field_info(field_title_generator, field_name, field_info) + if config_wrapper.alias_generator is not None: + _apply_alias_generator_to_field_info(config_wrapper.alias_generator, field_name, field_info) + + +_deprecated_method_names = {'dict', 'json', 'copy', '_iter', '_copy_and_set_values', '_calculate_keys'} + +_deprecated_classmethod_names = { + 'parse_obj', + 'parse_raw', + 'parse_file', + 'from_orm', + 'construct', + 'schema', + 'schema_json', + 'validate', + 'update_forward_refs', + '_get_value', +} + + +def collect_model_fields( # noqa: C901 + cls: type[BaseModel], + config_wrapper: ConfigWrapper, + ns_resolver: NsResolver | None, + *, + typevars_map: Mapping[TypeVar, Any] | None = None, +) -> tuple[dict[str, FieldInfo], set[str]]: + """Collect the fields and class variables names of a nascent Pydantic model. + + The fields collection process is *lenient*, meaning it won't error if string annotations + fail to evaluate. If this happens, the original annotation (and assigned value, if any) + is stored on the created `FieldInfo` instance. + + The `rebuild_model_fields()` should be called at a later point (e.g. when rebuilding the model), + and will make use of these stored attributes. + + Args: + cls: BaseModel or dataclass. + config_wrapper: The config wrapper instance. + ns_resolver: Namespace resolver to use when getting model annotations. + typevars_map: A dictionary mapping type variables to their concrete types. + + Returns: + A two-tuple containing model fields and class variables names. + + Raises: + NameError: + - If there is a conflict between a field name and protected namespaces. + - If there is a field other than `root` in `RootModel`. + - If a field shadows an attribute in the parent model. + """ + FieldInfo_ = import_cached_field_info() + BaseModel_ = import_cached_base_model() + + bases = cls.__bases__ + parent_fields_lookup: dict[str, FieldInfo] = {} + for base in reversed(bases): + if model_fields := getattr(base, '__pydantic_fields__', None): + parent_fields_lookup.update(model_fields) + + type_hints = _typing_extra.get_model_type_hints(cls, ns_resolver=ns_resolver) + + # https://docs.python.org/3/howto/annotations.html#accessing-the-annotations-dict-of-an-object-in-python-3-9-and-older + # annotations is only used for finding fields in parent classes + annotations = _typing_extra.safe_get_annotations(cls) + + fields: dict[str, FieldInfo] = {} + + class_vars: set[str] = set() + for ann_name, (ann_type, evaluated) in type_hints.items(): + if ann_name == 'model_config': + # We never want to treat `model_config` as a field + # Note: we may need to change this logic if/when we introduce a `BareModel` class with no + # protected namespaces (where `model_config` might be allowed as a field name) + continue + + _check_protected_namespaces( + protected_namespaces=config_wrapper.protected_namespaces, + ann_name=ann_name, + bases=bases, + cls_name=cls.__name__, + ) + + if _typing_extra.is_classvar_annotation(ann_type): + class_vars.add(ann_name) + continue + + assigned_value = getattr(cls, ann_name, PydanticUndefined) + if assigned_value is not PydanticUndefined and ( + # One of the deprecated instance methods was used as a field name (e.g. `dict()`): + any(getattr(BaseModel_, depr_name, None) is assigned_value for depr_name in _deprecated_method_names) + # One of the deprecated class methods was used as a field name (e.g. `schema()`): + or ( + hasattr(assigned_value, '__func__') + and any( + getattr(getattr(BaseModel_, depr_name, None), '__func__', None) is assigned_value.__func__ # pyright: ignore[reportAttributeAccessIssue] + for depr_name in _deprecated_classmethod_names + ) + ) + ): + # Then `assigned_value` would be the method, even though no default was specified: + assigned_value = PydanticUndefined + + if not is_valid_field_name(ann_name): + continue + if cls.__pydantic_root_model__ and ann_name != 'root': + raise NameError( + f"Unexpected field with name {ann_name!r}; only 'root' is allowed as a field of a `RootModel`" + ) + + # when building a generic model with `MyModel[int]`, the generic_origin check makes sure we don't get + # "... shadows an attribute" warnings + generic_origin = getattr(cls, '__pydantic_generic_metadata__', {}).get('origin') + for base in bases: + dataclass_fields = { + field.name for field in (dataclasses.fields(base) if dataclasses.is_dataclass(base) else ()) + } + if hasattr(base, ann_name): + if base is generic_origin: + # Don't warn when "shadowing" of attributes in parametrized generics + continue + + if ann_name in dataclass_fields: + # Don't warn when inheriting stdlib dataclasses whose fields are "shadowed" by defaults being set + # on the class instance. + continue + + if ann_name not in annotations: + # Don't warn when a field exists in a parent class but has not been defined in the current class + continue + + warnings.warn( + f'Field name "{ann_name}" in "{cls.__qualname__}" shadows an attribute in parent ' + f'"{base.__qualname__}"', + UserWarning, + stacklevel=4, + ) + + if assigned_value is PydanticUndefined: # no assignment, just a plain annotation + if ann_name in annotations or ann_name not in parent_fields_lookup: + # field is either: + # - present in the current model's annotations (and *not* from parent classes) + # - not found on any base classes; this seems to be caused by fields bot getting + # generated due to models not being fully defined while initializing recursive models. + # Nothing stops us from just creating a `FieldInfo` for this type hint, so we do this. + field_info = FieldInfo_.from_annotation(ann_type, _source=AnnotationSource.CLASS) + if not evaluated: + field_info._complete = False + # Store the original annotation that should be used to rebuild + # the field info later: + field_info._original_annotation = ann_type + else: + # The field was present on one of the (possibly multiple) base classes + # copy the field to make sure typevar substitutions don't cause issues with the base classes + field_info = parent_fields_lookup[ann_name]._copy() + + else: # An assigned value is present (either the default value, or a `Field()` function) + if isinstance(assigned_value, FieldInfo_) and ismethoddescriptor(assigned_value.default): + # `assigned_value` was fetched using `getattr`, which triggers a call to `__get__` + # for descriptors, so we do the same if the `= field(default=...)` form is used. + # Note that we only do this for method descriptors for now, we might want to + # extend this to any descriptor in the future (by simply checking for + # `hasattr(assigned_value.default, '__get__')`). + default = assigned_value.default.__get__(None, cls) + assigned_value.default = default + assigned_value._attributes_set['default'] = default + + field_info = FieldInfo_.from_annotated_attribute(ann_type, assigned_value, _source=AnnotationSource.CLASS) + # Store the original annotation and assignment value that should be used to rebuild the field info later. + # Note that the assignment is always stored as the annotation might contain a type var that is later + # parameterized with an unknown forward reference (and we'll need it to rebuild the field info): + field_info._original_assignment = assigned_value + if not evaluated: + field_info._complete = False + field_info._original_annotation = ann_type + elif 'final' in field_info._qualifiers and not field_info.is_required(): + warnings.warn( + f'Annotation {ann_name!r} is marked as final and has a default value. Pydantic treats {ann_name!r} as a ' + 'class variable, but it will be considered as a normal field in V3 to be aligned with dataclasses. If you ' + f'still want {ann_name!r} to be considered as a class variable, annotate it as: `ClassVar[] = .`', + category=PydanticDeprecatedSince211, + # Incorrect when `create_model` is used, but the chance that final with a default is used is low in that case: + stacklevel=4, + ) + class_vars.add(ann_name) + continue + + # attributes which are fields are removed from the class namespace: + # 1. To match the behaviour of annotation-only fields + # 2. To avoid false positives in the NameError check above + try: + delattr(cls, ann_name) + except AttributeError: + pass # indicates the attribute was on a parent class + + # Use cls.__dict__['__pydantic_decorators__'] instead of cls.__pydantic_decorators__ + # to make sure the decorators have already been built for this exact class + decorators: DecoratorInfos = cls.__dict__['__pydantic_decorators__'] + if ann_name in decorators.computed_fields: + raise TypeError( + f'Field {ann_name!r} of class {cls.__name__!r} overrides symbol of same name in a parent class. ' + 'This override with a computed_field is incompatible.' + ) + fields[ann_name] = field_info + + if field_info._complete: + # If not complete, this will be called in `rebuild_model_fields()`: + update_field_from_config(config_wrapper, ann_name, field_info) + + if typevars_map: + for field in fields.values(): + if field._complete: + field.apply_typevars_map(typevars_map) + + if config_wrapper.use_attribute_docstrings: + _update_fields_from_docstrings(cls, fields) + return fields, class_vars + + +def rebuild_model_fields( + cls: type[BaseModel], + *, + config_wrapper: ConfigWrapper, + ns_resolver: NsResolver, + typevars_map: Mapping[TypeVar, Any], +) -> dict[str, FieldInfo]: + """Rebuild the (already present) model fields by trying to reevaluate annotations. + + This function should be called whenever a model with incomplete fields is encountered. + + Raises: + NameError: If one of the annotations failed to evaluate. + + Note: + This function *doesn't* mutate the model fields in place, as it can be called during + schema generation, where you don't want to mutate other model's fields. + """ + FieldInfo_ = import_cached_field_info() + + rebuilt_fields: dict[str, FieldInfo] = {} + with ns_resolver.push(cls): + for f_name, field_info in cls.__pydantic_fields__.items(): + if field_info._complete: + rebuilt_fields[f_name] = field_info + else: + existing_desc = field_info.description + ann = _typing_extra.eval_type( + field_info._original_annotation, + *ns_resolver.types_namespace, + ) + ann = _generics.replace_types(ann, typevars_map) + + if (assign := field_info._original_assignment) is PydanticUndefined: + new_field = FieldInfo_.from_annotation(ann, _source=AnnotationSource.CLASS) + else: + new_field = FieldInfo_.from_annotated_attribute(ann, assign, _source=AnnotationSource.CLASS) + # The description might come from the docstring if `use_attribute_docstrings` was `True`: + new_field.description = new_field.description if new_field.description is not None else existing_desc + update_field_from_config(config_wrapper, f_name, new_field) + rebuilt_fields[f_name] = new_field + + return rebuilt_fields + + +def collect_dataclass_fields( + cls: type[StandardDataclass], + *, + config_wrapper: ConfigWrapper, + ns_resolver: NsResolver | None = None, + typevars_map: dict[Any, Any] | None = None, +) -> dict[str, FieldInfo]: + """Collect the fields of a dataclass. + + Args: + cls: dataclass. + config_wrapper: The config wrapper instance. + ns_resolver: Namespace resolver to use when getting dataclass annotations. + Defaults to an empty instance. + typevars_map: A dictionary mapping type variables to their concrete types. + + Returns: + The dataclass fields. + """ + FieldInfo_ = import_cached_field_info() + + fields: dict[str, FieldInfo] = {} + ns_resolver = ns_resolver or NsResolver() + dataclass_fields = cls.__dataclass_fields__ + + # The logic here is similar to `_typing_extra.get_cls_type_hints`, + # although we do it manually as stdlib dataclasses already have annotations + # collected in each class: + for base in reversed(cls.__mro__): + if not dataclasses.is_dataclass(base): + continue + + with ns_resolver.push(base): + for ann_name, dataclass_field in dataclass_fields.items(): + base_anns = _typing_extra.safe_get_annotations(base) + + if ann_name not in base_anns: + # `__dataclass_fields__`contains every field, even the ones from base classes. + # Only collect the ones defined on `base`. + continue + + globalns, localns = ns_resolver.types_namespace + ann_type, evaluated = _typing_extra.try_eval_type(dataclass_field.type, globalns, localns) + + if _typing_extra.is_classvar_annotation(ann_type): + continue + + if ( + not dataclass_field.init + and dataclass_field.default is dataclasses.MISSING + and dataclass_field.default_factory is dataclasses.MISSING + ): + # TODO: We should probably do something with this so that validate_assignment behaves properly + # Issue: https://github.com/pydantic/pydantic/issues/5470 + continue + + if isinstance(dataclass_field.default, FieldInfo_): + if dataclass_field.default.init_var: + if dataclass_field.default.init is False: + raise PydanticUserError( + f'Dataclass field {ann_name} has init=False and init_var=True, but these are mutually exclusive.', + code='clashing-init-and-init-var', + ) + + # TODO: same note as above re validate_assignment + continue + field_info = FieldInfo_.from_annotated_attribute( + ann_type, dataclass_field.default, _source=AnnotationSource.DATACLASS + ) + field_info._original_assignment = dataclass_field.default + else: + field_info = FieldInfo_.from_annotated_attribute( + ann_type, dataclass_field, _source=AnnotationSource.DATACLASS + ) + field_info._original_assignment = dataclass_field + + if not evaluated: + field_info._complete = False + field_info._original_annotation = ann_type + + fields[ann_name] = field_info + update_field_from_config(config_wrapper, ann_name, field_info) + + if field_info.default is not PydanticUndefined and isinstance( + getattr(cls, ann_name, field_info), FieldInfo_ + ): + # We need this to fix the default when the "default" from __dataclass_fields__ is a pydantic.FieldInfo + setattr(cls, ann_name, field_info.default) + + if typevars_map: + for field in fields.values(): + # We don't pass any ns, as `field.annotation` + # was already evaluated. TODO: is this method relevant? + # Can't we juste use `_generics.replace_types`? + field.apply_typevars_map(typevars_map) + + if config_wrapper.use_attribute_docstrings: + _update_fields_from_docstrings( + cls, + fields, + # We can't rely on the (more reliable) frame inspection method + # for stdlib dataclasses: + use_inspect=not hasattr(cls, '__is_pydantic_dataclass__'), + ) + + return fields + + +def rebuild_dataclass_fields( + cls: type[PydanticDataclass], + *, + config_wrapper: ConfigWrapper, + ns_resolver: NsResolver, + typevars_map: Mapping[TypeVar, Any], +) -> dict[str, FieldInfo]: + """Rebuild the (already present) dataclass fields by trying to reevaluate annotations. + + This function should be called whenever a dataclass with incomplete fields is encountered. + + Raises: + NameError: If one of the annotations failed to evaluate. + + Note: + This function *doesn't* mutate the dataclass fields in place, as it can be called during + schema generation, where you don't want to mutate other dataclass's fields. + """ + FieldInfo_ = import_cached_field_info() + + rebuilt_fields: dict[str, FieldInfo] = {} + with ns_resolver.push(cls): + for f_name, field_info in cls.__pydantic_fields__.items(): + if field_info._complete: + rebuilt_fields[f_name] = field_info + else: + existing_desc = field_info.description + ann = _typing_extra.eval_type( + field_info._original_annotation, + *ns_resolver.types_namespace, + ) + ann = _generics.replace_types(ann, typevars_map) + new_field = FieldInfo_.from_annotated_attribute( + ann, + field_info._original_assignment, + _source=AnnotationSource.DATACLASS, + ) + + # The description might come from the docstring if `use_attribute_docstrings` was `True`: + new_field.description = new_field.description if new_field.description is not None else existing_desc + update_field_from_config(config_wrapper, f_name, new_field) + rebuilt_fields[f_name] = new_field + + return rebuilt_fields + + +def is_valid_field_name(name: str) -> bool: + return not name.startswith('_') + + +def is_valid_privateattr_name(name: str) -> bool: + return name.startswith('_') and not name.startswith('__') + + +def takes_validated_data_argument( + default_factory: Callable[[], Any] | Callable[[dict[str, Any]], Any], +) -> TypeIs[Callable[[dict[str, Any]], Any]]: + """Whether the provided default factory callable has a validated data parameter.""" + try: + sig = signature(default_factory) + except (ValueError, TypeError): + # `inspect.signature` might not be able to infer a signature, e.g. with C objects. + # In this case, we assume no data argument is present: + return False + + parameters = list(sig.parameters.values()) + + return len(parameters) == 1 and can_be_positional(parameters[0]) and parameters[0].default is Parameter.empty diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_forward_ref.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_forward_ref.py new file mode 100644 index 0000000..231f81d --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_forward_ref.py @@ -0,0 +1,23 @@ +from __future__ import annotations as _annotations + +from dataclasses import dataclass +from typing import Union + + +@dataclass +class PydanticRecursiveRef: + type_ref: str + + __name__ = 'PydanticRecursiveRef' + __hash__ = object.__hash__ + + def __call__(self) -> None: + """Defining __call__ is necessary for the `typing` module to let you use an instance of + this class as the result of resolving a standard ForwardRef. + """ + + def __or__(self, other): + return Union[self, other] # type: ignore + + def __ror__(self, other): + return Union[other, self] # type: ignore diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_generate_schema.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_generate_schema.py new file mode 100644 index 0000000..839764c --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_generate_schema.py @@ -0,0 +1,2867 @@ +"""Convert python types to pydantic-core schema.""" + +from __future__ import annotations as _annotations + +import collections.abc +import dataclasses +import datetime +import inspect +import os +import pathlib +import re +import sys +import typing +import warnings +from collections.abc import Generator, Iterable, Iterator, Mapping +from contextlib import contextmanager +from copy import copy +from decimal import Decimal +from enum import Enum +from fractions import Fraction +from functools import partial +from inspect import Parameter, _ParameterKind, signature +from ipaddress import IPv4Address, IPv4Interface, IPv4Network, IPv6Address, IPv6Interface, IPv6Network +from itertools import chain +from operator import attrgetter +from types import FunctionType, GenericAlias, LambdaType, MethodType +from typing import ( + TYPE_CHECKING, + Any, + Callable, + Final, + ForwardRef, + Literal, + TypeVar, + Union, + cast, + overload, +) +from uuid import UUID +from zoneinfo import ZoneInfo + +import typing_extensions +from pydantic_core import ( + MISSING, + CoreSchema, + MultiHostUrl, + PydanticCustomError, + PydanticSerializationUnexpectedValue, + PydanticUndefined, + Url, + core_schema, + to_jsonable_python, +) +from typing_extensions import TypeAlias, TypeAliasType, get_args, get_origin, is_typeddict +from typing_inspection import typing_objects +from typing_inspection.introspection import AnnotationSource, get_literal_values, is_union_origin + +from ..aliases import AliasChoices, AliasPath +from ..annotated_handlers import GetCoreSchemaHandler, GetJsonSchemaHandler +from ..config import ConfigDict, JsonDict, JsonEncoder, JsonSchemaExtraCallable +from ..errors import PydanticSchemaGenerationError, PydanticUndefinedAnnotation, PydanticUserError +from ..functional_validators import AfterValidator, BeforeValidator, FieldValidatorModes, PlainValidator, WrapValidator +from ..json_schema import JsonSchemaValue +from ..version import version_short +from ..warnings import ( + ArbitraryTypeWarning, + PydanticDeprecatedSince20, + TypedDictExtraConfigWarning, + UnsupportedFieldAttributeWarning, +) +from . import _decorators, _discriminated_union, _known_annotated_metadata, _repr, _typing_extra +from ._config import ConfigWrapper, ConfigWrapperStack +from ._core_metadata import CoreMetadata, update_core_metadata +from ._core_utils import ( + get_ref, + get_type_ref, + is_list_like_schema_with_items_schema, +) +from ._decorators import ( + Decorator, + DecoratorInfos, + FieldSerializerDecoratorInfo, + FieldValidatorDecoratorInfo, + ModelSerializerDecoratorInfo, + ModelValidatorDecoratorInfo, + RootValidatorDecoratorInfo, + ValidatorDecoratorInfo, + get_attribute_from_bases, + inspect_field_serializer, + inspect_model_serializer, + inspect_validator, +) +from ._docs_extraction import extract_docstrings_from_cls +from ._fields import ( + collect_dataclass_fields, + rebuild_dataclass_fields, + rebuild_model_fields, + takes_validated_data_argument, + update_field_from_config, +) +from ._forward_ref import PydanticRecursiveRef +from ._generics import get_standard_typevars_map, replace_types +from ._import_utils import import_cached_base_model, import_cached_field_info +from ._mock_val_ser import MockCoreSchema +from ._namespace_utils import NamespacesTuple, NsResolver +from ._schema_gather import MissingDefinitionError, gather_schemas_for_cleaning +from ._schema_generation_shared import CallbackGetCoreSchemaHandler +from ._utils import lenient_issubclass, smart_deepcopy + +if TYPE_CHECKING: + from ..fields import ComputedFieldInfo, FieldInfo + from ..main import BaseModel + from ..types import Discriminator + from ._dataclasses import StandardDataclass + from ._schema_generation_shared import GetJsonSchemaFunction + +_SUPPORTS_TYPEDDICT = sys.version_info >= (3, 12) + +FieldDecoratorInfo = Union[ValidatorDecoratorInfo, FieldValidatorDecoratorInfo, FieldSerializerDecoratorInfo] +FieldDecoratorInfoType = TypeVar('FieldDecoratorInfoType', bound=FieldDecoratorInfo) +AnyFieldDecorator = Union[ + Decorator[ValidatorDecoratorInfo], + Decorator[FieldValidatorDecoratorInfo], + Decorator[FieldSerializerDecoratorInfo], +] + +ModifyCoreSchemaWrapHandler: TypeAlias = GetCoreSchemaHandler +GetCoreSchemaFunction: TypeAlias = Callable[[Any, ModifyCoreSchemaWrapHandler], core_schema.CoreSchema] +ParametersCallback: TypeAlias = "Callable[[int, str, Any], Literal['skip'] | None]" + +TUPLE_TYPES: list[type] = [typing.Tuple, tuple] # noqa: UP006 +LIST_TYPES: list[type] = [typing.List, list, collections.abc.MutableSequence] # noqa: UP006 +SET_TYPES: list[type] = [typing.Set, set, collections.abc.MutableSet] # noqa: UP006 +FROZEN_SET_TYPES: list[type] = [typing.FrozenSet, frozenset, collections.abc.Set] # noqa: UP006 +DICT_TYPES: list[type] = [typing.Dict, dict] # noqa: UP006 +IP_TYPES: list[type] = [IPv4Address, IPv4Interface, IPv4Network, IPv6Address, IPv6Interface, IPv6Network] +SEQUENCE_TYPES: list[type] = [typing.Sequence, collections.abc.Sequence] +ITERABLE_TYPES: list[type] = [typing.Iterable, collections.abc.Iterable, typing.Generator, collections.abc.Generator] +TYPE_TYPES: list[type] = [typing.Type, type] # noqa: UP006 +PATTERN_TYPES: list[type] = [typing.Pattern, re.Pattern] +PATH_TYPES: list[type] = [ + os.PathLike, + pathlib.Path, + pathlib.PurePath, + pathlib.PosixPath, + pathlib.PurePosixPath, + pathlib.PureWindowsPath, +] +MAPPING_TYPES = [ + typing.Mapping, + typing.MutableMapping, + collections.abc.Mapping, + collections.abc.MutableMapping, + collections.OrderedDict, + typing_extensions.OrderedDict, + typing.DefaultDict, # noqa: UP006 + collections.defaultdict, +] +COUNTER_TYPES = [collections.Counter, typing.Counter] +DEQUE_TYPES: list[type] = [collections.deque, typing.Deque] # noqa: UP006 + +# Note: This does not play very well with type checkers. For example, +# `a: LambdaType = lambda x: x` will raise a type error by Pyright. +ValidateCallSupportedTypes = Union[ + LambdaType, + FunctionType, + MethodType, + partial, +] + +VALIDATE_CALL_SUPPORTED_TYPES = get_args(ValidateCallSupportedTypes) +UNSUPPORTED_STANDALONE_FIELDINFO_ATTRIBUTES: list[tuple[str, Any]] = [ + ('alias', None), + ('validation_alias', None), + ('serialization_alias', None), + # will be set if any alias is set, so disable it to avoid double warnings: + # 'alias_priority', + ('default', PydanticUndefined), + ('default_factory', None), + ('exclude', None), + ('deprecated', None), + ('repr', True), + ('validate_default', None), + ('frozen', None), + ('init', None), + ('init_var', None), + ('kw_only', None), +] +"""`FieldInfo` attributes (and their default value) that can't be used outside of a model (e.g. in a type adapter or a PEP 695 type alias).""" + +_mode_to_validator: dict[ + FieldValidatorModes, type[BeforeValidator | AfterValidator | PlainValidator | WrapValidator] +] = {'before': BeforeValidator, 'after': AfterValidator, 'plain': PlainValidator, 'wrap': WrapValidator} + + +def check_validator_fields_against_field_name( + info: FieldDecoratorInfo, + field: str, +) -> bool: + """Check if field name is in validator fields. + + Args: + info: The field info. + field: The field name to check. + + Returns: + `True` if field name is in validator fields, `False` otherwise. + """ + fields = info.fields + return '*' in fields or field in fields + + +def check_decorator_fields_exist(decorators: Iterable[AnyFieldDecorator], fields: Iterable[str]) -> None: + """Check if the defined fields in decorators exist in `fields` param. + + It ignores the check for a decorator if the decorator has `*` as field or `check_fields=False`. + + Args: + decorators: An iterable of decorators. + fields: An iterable of fields name. + + Raises: + PydanticUserError: If one of the field names does not exist in `fields` param. + """ + fields = set(fields) + for dec in decorators: + if '*' in dec.info.fields: + continue + if dec.info.check_fields is False: + continue + for field in dec.info.fields: + if field not in fields: + raise PydanticUserError( + f'Decorators defined with incorrect fields: {dec.cls_ref}.{dec.cls_var_name}' + " (use check_fields=False if you're inheriting from the model and intended this)", + code='decorator-missing-field', + ) + + +def filter_field_decorator_info_by_field( + validator_functions: Iterable[Decorator[FieldDecoratorInfoType]], field: str +) -> list[Decorator[FieldDecoratorInfoType]]: + return [dec for dec in validator_functions if check_validator_fields_against_field_name(dec.info, field)] + + +def apply_each_item_validators( + schema: core_schema.CoreSchema, + each_item_validators: list[Decorator[ValidatorDecoratorInfo]], +) -> core_schema.CoreSchema: + # This V1 compatibility shim should eventually be removed + + # fail early if each_item_validators is empty + if not each_item_validators: + return schema + + # push down any `each_item=True` validators + # note that this won't work for any Annotated types that get wrapped by a function validator + # but that's okay because that didn't exist in V1 + if schema['type'] == 'nullable': + schema['schema'] = apply_each_item_validators(schema['schema'], each_item_validators) + return schema + elif schema['type'] == 'tuple': + if (variadic_item_index := schema.get('variadic_item_index')) is not None: + schema['items_schema'][variadic_item_index] = apply_validators( + schema['items_schema'][variadic_item_index], + each_item_validators, + ) + elif is_list_like_schema_with_items_schema(schema): + inner_schema = schema.get('items_schema', core_schema.any_schema()) + schema['items_schema'] = apply_validators(inner_schema, each_item_validators) + elif schema['type'] == 'dict': + inner_schema = schema.get('values_schema', core_schema.any_schema()) + schema['values_schema'] = apply_validators(inner_schema, each_item_validators) + else: + raise TypeError( + f'`@validator(..., each_item=True)` cannot be applied to fields with a schema of {schema["type"]}' + ) + return schema + + +def _extract_json_schema_info_from_field_info( + info: FieldInfo | ComputedFieldInfo, +) -> tuple[JsonDict | None, JsonDict | JsonSchemaExtraCallable | None]: + json_schema_updates = { + 'title': info.title, + 'description': info.description, + 'deprecated': bool(info.deprecated) or info.deprecated == '' or None, + 'examples': to_jsonable_python(info.examples), + } + json_schema_updates = {k: v for k, v in json_schema_updates.items() if v is not None} + return (json_schema_updates or None, info.json_schema_extra) + + +JsonEncoders = dict[type[Any], JsonEncoder] + + +def _add_custom_serialization_from_json_encoders( + json_encoders: JsonEncoders | None, tp: Any, schema: CoreSchema +) -> CoreSchema: + """Iterate over the json_encoders and add the first matching encoder to the schema. + + Args: + json_encoders: A dictionary of types and their encoder functions. + tp: The type to check for a matching encoder. + schema: The schema to add the encoder to. + """ + if not json_encoders: + return schema + if 'serialization' in schema: + return schema + # Check the class type and its superclasses for a matching encoder + # Decimal.__class__.__mro__ (and probably other cases) doesn't include Decimal itself + # if the type is a GenericAlias (e.g. from list[int]) we need to use __class__ instead of .__mro__ + for base in (tp, *getattr(tp, '__mro__', tp.__class__.__mro__)[:-1]): + encoder = json_encoders.get(base) + if encoder is None: + continue + + warnings.warn( + f'`json_encoders` is deprecated. See https://docs.pydantic.dev/{version_short()}/concepts/serialization/#custom-serializers for alternatives', + PydanticDeprecatedSince20, + ) + + # TODO: in theory we should check that the schema accepts a serialization key + schema['serialization'] = core_schema.plain_serializer_function_ser_schema(encoder, when_used='json') + return schema + + return schema + + +class InvalidSchemaError(Exception): + """The core schema is invalid.""" + + +class GenerateSchema: + """Generate core schema for a Pydantic model, dataclass and types like `str`, `datetime`, ... .""" + + __slots__ = ( + '_config_wrapper_stack', + '_ns_resolver', + '_typevars_map', + 'field_name_stack', + 'model_type_stack', + 'defs', + ) + + def __init__( + self, + config_wrapper: ConfigWrapper, + ns_resolver: NsResolver | None = None, + typevars_map: Mapping[TypeVar, Any] | None = None, + ) -> None: + # we need a stack for recursing into nested models + self._config_wrapper_stack = ConfigWrapperStack(config_wrapper) + self._ns_resolver = ns_resolver or NsResolver() + self._typevars_map = typevars_map + self.field_name_stack = _FieldNameStack() + self.model_type_stack = _ModelTypeStack() + self.defs = _Definitions() + + def __init_subclass__(cls) -> None: + super().__init_subclass__() + warnings.warn( + 'Subclassing `GenerateSchema` is not supported. The API is highly subject to change in minor versions.', + UserWarning, + stacklevel=2, + ) + + @property + def _config_wrapper(self) -> ConfigWrapper: + return self._config_wrapper_stack.tail + + @property + def _types_namespace(self) -> NamespacesTuple: + return self._ns_resolver.types_namespace + + @property + def _arbitrary_types(self) -> bool: + return self._config_wrapper.arbitrary_types_allowed + + # the following methods can be overridden but should be considered + # unstable / private APIs + def _list_schema(self, items_type: Any) -> CoreSchema: + return core_schema.list_schema(self.generate_schema(items_type)) + + def _dict_schema(self, keys_type: Any, values_type: Any) -> CoreSchema: + return core_schema.dict_schema(self.generate_schema(keys_type), self.generate_schema(values_type)) + + def _set_schema(self, items_type: Any) -> CoreSchema: + return core_schema.set_schema(self.generate_schema(items_type)) + + def _frozenset_schema(self, items_type: Any) -> CoreSchema: + return core_schema.frozenset_schema(self.generate_schema(items_type)) + + def _enum_schema(self, enum_type: type[Enum]) -> CoreSchema: + cases: list[Any] = list(enum_type.__members__.values()) + + enum_ref = get_type_ref(enum_type) + description = None if not enum_type.__doc__ else inspect.cleandoc(enum_type.__doc__) + if ( + description == 'An enumeration.' + ): # This is the default value provided by enum.EnumMeta.__new__; don't use it + description = None + js_updates = {'title': enum_type.__name__, 'description': description} + js_updates = {k: v for k, v in js_updates.items() if v is not None} + + sub_type: Literal['str', 'int', 'float'] | None = None + if issubclass(enum_type, int): + sub_type = 'int' + value_ser_type: core_schema.SerSchema = core_schema.simple_ser_schema('int') + elif issubclass(enum_type, str): + # this handles `StrEnum` (3.11 only), and also `Foobar(str, Enum)` + sub_type = 'str' + value_ser_type = core_schema.simple_ser_schema('str') + elif issubclass(enum_type, float): + sub_type = 'float' + value_ser_type = core_schema.simple_ser_schema('float') + else: + # TODO this is an ugly hack, how do we trigger an Any schema for serialization? + value_ser_type = core_schema.plain_serializer_function_ser_schema(lambda x: x) + + if cases: + + def get_json_schema(schema: CoreSchema, handler: GetJsonSchemaHandler) -> JsonSchemaValue: + json_schema = handler(schema) + original_schema = handler.resolve_ref_schema(json_schema) + original_schema.update(js_updates) + return json_schema + + # we don't want to add the missing to the schema if it's the default one + default_missing = getattr(enum_type._missing_, '__func__', None) is Enum._missing_.__func__ # pyright: ignore[reportFunctionMemberAccess] + enum_schema = core_schema.enum_schema( + enum_type, + cases, + sub_type=sub_type, + missing=None if default_missing else enum_type._missing_, + ref=enum_ref, + metadata={'pydantic_js_functions': [get_json_schema]}, + ) + + if self._config_wrapper.use_enum_values: + enum_schema = core_schema.no_info_after_validator_function( + attrgetter('value'), enum_schema, serialization=value_ser_type + ) + + return enum_schema + + else: + + def get_json_schema_no_cases(_, handler: GetJsonSchemaHandler) -> JsonSchemaValue: + json_schema = handler(core_schema.enum_schema(enum_type, cases, sub_type=sub_type, ref=enum_ref)) + original_schema = handler.resolve_ref_schema(json_schema) + original_schema.update(js_updates) + return json_schema + + # Use an isinstance check for enums with no cases. + # The most important use case for this is creating TypeVar bounds for generics that should + # be restricted to enums. This is more consistent than it might seem at first, since you can only + # subclass enum.Enum (or subclasses of enum.Enum) if all parent classes have no cases. + # We use the get_json_schema function when an Enum subclass has been declared with no cases + # so that we can still generate a valid json schema. + return core_schema.is_instance_schema( + enum_type, + metadata={'pydantic_js_functions': [get_json_schema_no_cases]}, + ) + + def _ip_schema(self, tp: Any) -> CoreSchema: + from ._validators import IP_VALIDATOR_LOOKUP, IpType + + ip_type_json_schema_format: dict[type[IpType], str] = { + IPv4Address: 'ipv4', + IPv4Network: 'ipv4network', + IPv4Interface: 'ipv4interface', + IPv6Address: 'ipv6', + IPv6Network: 'ipv6network', + IPv6Interface: 'ipv6interface', + } + + def ser_ip(ip: Any, info: core_schema.SerializationInfo) -> str | IpType: + if not isinstance(ip, (tp, str)): + raise PydanticSerializationUnexpectedValue( + f"Expected `{tp}` but got `{type(ip)}` with value `'{ip}'` - serialized value may not be as expected." + ) + if info.mode == 'python': + return ip + return str(ip) + + return core_schema.lax_or_strict_schema( + lax_schema=core_schema.no_info_plain_validator_function(IP_VALIDATOR_LOOKUP[tp]), + strict_schema=core_schema.json_or_python_schema( + json_schema=core_schema.no_info_after_validator_function(tp, core_schema.str_schema()), + python_schema=core_schema.is_instance_schema(tp), + ), + serialization=core_schema.plain_serializer_function_ser_schema(ser_ip, info_arg=True, when_used='always'), + metadata={ + 'pydantic_js_functions': [lambda _1, _2: {'type': 'string', 'format': ip_type_json_schema_format[tp]}] + }, + ) + + def _path_schema(self, tp: Any, path_type: Any) -> CoreSchema: + if tp is os.PathLike and (path_type not in {str, bytes} and not typing_objects.is_any(path_type)): + raise PydanticUserError( + '`os.PathLike` can only be used with `str`, `bytes` or `Any`', code='schema-for-unknown-type' + ) + + path_constructor = pathlib.PurePath if tp is os.PathLike else tp + strict_inner_schema = ( + core_schema.bytes_schema(strict=True) if (path_type is bytes) else core_schema.str_schema(strict=True) + ) + lax_inner_schema = core_schema.bytes_schema() if (path_type is bytes) else core_schema.str_schema() + + def path_validator(input_value: str | bytes) -> os.PathLike[Any]: # type: ignore + try: + if path_type is bytes: + if isinstance(input_value, bytes): + try: + input_value = input_value.decode() + except UnicodeDecodeError as e: + raise PydanticCustomError('bytes_type', 'Input must be valid bytes') from e + else: + raise PydanticCustomError('bytes_type', 'Input must be bytes') + elif not isinstance(input_value, str): + raise PydanticCustomError('path_type', 'Input is not a valid path') + + return path_constructor(input_value) # type: ignore + except TypeError as e: + raise PydanticCustomError('path_type', 'Input is not a valid path') from e + + def ser_path(path: Any, info: core_schema.SerializationInfo) -> str | os.PathLike[Any]: + if not isinstance(path, (tp, str)): + raise PydanticSerializationUnexpectedValue( + f"Expected `{tp}` but got `{type(path)}` with value `'{path}'` - serialized value may not be as expected." + ) + if info.mode == 'python': + return path + return str(path) + + instance_schema = core_schema.json_or_python_schema( + json_schema=core_schema.no_info_after_validator_function(path_validator, lax_inner_schema), + python_schema=core_schema.is_instance_schema(tp), + ) + + schema = core_schema.lax_or_strict_schema( + lax_schema=core_schema.union_schema( + [ + instance_schema, + core_schema.no_info_after_validator_function(path_validator, strict_inner_schema), + ], + custom_error_type='path_type', + custom_error_message=f'Input is not a valid path for {tp}', + ), + strict_schema=instance_schema, + serialization=core_schema.plain_serializer_function_ser_schema(ser_path, info_arg=True, when_used='always'), + metadata={'pydantic_js_functions': [lambda source, handler: {**handler(source), 'format': 'path'}]}, + ) + return schema + + def _deque_schema(self, items_type: Any) -> CoreSchema: + from ._serializers import serialize_sequence_via_list + from ._validators import deque_validator + + item_type_schema = self.generate_schema(items_type) + + # we have to use a lax list schema here, because we need to validate the deque's + # items via a list schema, but it's ok if the deque itself is not a list + list_schema = core_schema.list_schema(item_type_schema, strict=False) + + check_instance = core_schema.json_or_python_schema( + json_schema=list_schema, + python_schema=core_schema.is_instance_schema(collections.deque, cls_repr='Deque'), + ) + + lax_schema = core_schema.no_info_wrap_validator_function(deque_validator, list_schema) + + return core_schema.lax_or_strict_schema( + lax_schema=lax_schema, + strict_schema=core_schema.chain_schema([check_instance, lax_schema]), + serialization=core_schema.wrap_serializer_function_ser_schema( + serialize_sequence_via_list, schema=item_type_schema, info_arg=True + ), + ) + + def _mapping_schema(self, tp: Any, keys_type: Any, values_type: Any) -> CoreSchema: + from ._validators import MAPPING_ORIGIN_MAP, defaultdict_validator, get_defaultdict_default_default_factory + + mapped_origin = MAPPING_ORIGIN_MAP[tp] + keys_schema = self.generate_schema(keys_type) + with warnings.catch_warnings(): + # We kind of abused `Field()` default factories to be able to specify + # the `defaultdict`'s `default_factory`. As a consequence, we get warnings + # as normally `FieldInfo.default_factory` is unsupported in the context where + # `Field()` is used and our only solution is to ignore them (note that this might + # wrongfully ignore valid warnings, e.g. if the `value_type` is a PEP 695 type alias + # with unsupported metadata). + warnings.simplefilter('ignore', category=UnsupportedFieldAttributeWarning) + values_schema = self.generate_schema(values_type) + dict_schema = core_schema.dict_schema(keys_schema, values_schema, strict=False) + + if mapped_origin is dict: + schema = dict_schema + else: + check_instance = core_schema.json_or_python_schema( + json_schema=dict_schema, + python_schema=core_schema.is_instance_schema(mapped_origin), + ) + + if tp is collections.defaultdict: + default_default_factory = get_defaultdict_default_default_factory(values_type) + coerce_instance_wrap = partial( + core_schema.no_info_wrap_validator_function, + partial(defaultdict_validator, default_default_factory=default_default_factory), + ) + else: + coerce_instance_wrap = partial(core_schema.no_info_after_validator_function, mapped_origin) + + lax_schema = coerce_instance_wrap(dict_schema) + strict_schema = core_schema.chain_schema([check_instance, lax_schema]) + + schema = core_schema.lax_or_strict_schema( + lax_schema=lax_schema, + strict_schema=strict_schema, + serialization=core_schema.wrap_serializer_function_ser_schema( + lambda v, h: h(v), schema=dict_schema, info_arg=False + ), + ) + + return schema + + def _fraction_schema(self) -> CoreSchema: + """Support for [`fractions.Fraction`][fractions.Fraction].""" + from ._validators import fraction_validator + + # TODO: note, this is a fairly common pattern, re lax / strict for attempted type coercion, + # can we use a helper function to reduce boilerplate? + return core_schema.lax_or_strict_schema( + lax_schema=core_schema.no_info_plain_validator_function(fraction_validator), + strict_schema=core_schema.json_or_python_schema( + json_schema=core_schema.no_info_plain_validator_function(fraction_validator), + python_schema=core_schema.is_instance_schema(Fraction), + ), + # use str serialization to guarantee round trip behavior + serialization=core_schema.to_string_ser_schema(when_used='always'), + metadata={'pydantic_js_functions': [lambda _1, _2: {'type': 'string', 'format': 'fraction'}]}, + ) + + def _arbitrary_type_schema(self, tp: Any) -> CoreSchema: + if not isinstance(tp, type): + warnings.warn( + f'{tp!r} is not a Python type (it may be an instance of an object),' + ' Pydantic will allow any object with no validation since we cannot even' + ' enforce that the input is an instance of the given type.' + ' To get rid of this error wrap the type with `pydantic.SkipValidation`.', + ArbitraryTypeWarning, + ) + return core_schema.any_schema() + return core_schema.is_instance_schema(tp) + + def _unknown_type_schema(self, obj: Any) -> CoreSchema: + raise PydanticSchemaGenerationError( + f'Unable to generate pydantic-core schema for {obj!r}. ' + 'Set `arbitrary_types_allowed=True` in the model_config to ignore this error' + ' or implement `__get_pydantic_core_schema__` on your type to fully support it.' + '\n\nIf you got this error by calling handler() within' + ' `__get_pydantic_core_schema__` then you likely need to call' + ' `handler.generate_schema()` since we do not call' + ' `__get_pydantic_core_schema__` on `` otherwise to avoid infinite recursion.' + ) + + def _apply_discriminator_to_union( + self, schema: CoreSchema, discriminator: str | Discriminator | None + ) -> CoreSchema: + if discriminator is None: + return schema + try: + return _discriminated_union.apply_discriminator( + schema, + discriminator, + self.defs._definitions, + ) + except _discriminated_union.MissingDefinitionForUnionRef: + # defer until defs are resolved + _discriminated_union.set_discriminator_in_metadata( + schema, + discriminator, + ) + return schema + + def clean_schema(self, schema: CoreSchema) -> CoreSchema: + return self.defs.finalize_schema(schema) + + def _add_js_function(self, metadata_schema: CoreSchema, js_function: Callable[..., Any]) -> None: + metadata = metadata_schema.get('metadata', {}) + pydantic_js_functions = metadata.setdefault('pydantic_js_functions', []) + # because of how we generate core schemas for nested generic models + # we can end up adding `BaseModel.__get_pydantic_json_schema__` multiple times + # this check may fail to catch duplicates if the function is a `functools.partial` + # or something like that, but if it does it'll fail by inserting the duplicate + if js_function not in pydantic_js_functions: + pydantic_js_functions.append(js_function) + metadata_schema['metadata'] = metadata + + def generate_schema( + self, + obj: Any, + ) -> core_schema.CoreSchema: + """Generate core schema. + + Args: + obj: The object to generate core schema for. + + Returns: + The generated core schema. + + Raises: + PydanticUndefinedAnnotation: + If it is not possible to evaluate forward reference. + PydanticSchemaGenerationError: + If it is not possible to generate pydantic-core schema. + TypeError: + - If `alias_generator` returns a disallowed type (must be str, AliasPath or AliasChoices). + - If V1 style validator with `each_item=True` applied on a wrong field. + PydanticUserError: + - If `typing.TypedDict` is used instead of `typing_extensions.TypedDict` on Python < 3.12. + - If `__modify_schema__` method is used instead of `__get_pydantic_json_schema__`. + """ + schema = self._generate_schema_from_get_schema_method(obj, obj) + + if schema is None: + schema = self._generate_schema_inner(obj) + + metadata_js_function = _extract_get_pydantic_json_schema(obj) + if metadata_js_function is not None: + metadata_schema = resolve_original_schema(schema, self.defs) + if metadata_schema: + self._add_js_function(metadata_schema, metadata_js_function) + + schema = _add_custom_serialization_from_json_encoders(self._config_wrapper.json_encoders, obj, schema) + + return schema + + def _model_schema(self, cls: type[BaseModel]) -> core_schema.CoreSchema: + """Generate schema for a Pydantic model.""" + BaseModel_ = import_cached_base_model() + + with self.defs.get_schema_or_ref(cls) as (model_ref, maybe_schema): + if maybe_schema is not None: + return maybe_schema + + schema = cls.__dict__.get('__pydantic_core_schema__') + if schema is not None and not isinstance(schema, MockCoreSchema): + if schema['type'] == 'definitions': + schema = self.defs.unpack_definitions(schema) + ref = get_ref(schema) + if ref: + return self.defs.create_definition_reference_schema(schema) + else: + return schema + + config_wrapper = ConfigWrapper(cls.model_config, check=False) + + with self._config_wrapper_stack.push(config_wrapper), self._ns_resolver.push(cls): + core_config = self._config_wrapper.core_config(title=cls.__name__) + + if cls.__pydantic_fields_complete__ or cls is BaseModel_: + fields = getattr(cls, '__pydantic_fields__', {}) + else: + if '__pydantic_fields__' not in cls.__dict__: + # This happens when we have a loop in the schema generation: + # class Base[T](BaseModel): + # t: T + # + # class Other(BaseModel): + # b: 'Base[Other]' + # When we build fields for `Other`, we evaluate the forward annotation. + # At this point, `Other` doesn't have the model fields set. We create + # `Base[Other]`; model fields are successfully built, and we try to generate + # a schema for `t: Other`. As `Other.__pydantic_fields__` aren't set, we abort. + raise PydanticUndefinedAnnotation( + name=cls.__name__, + message=f'Class {cls.__name__!r} is not defined', + ) + try: + fields = rebuild_model_fields( + cls, + config_wrapper=self._config_wrapper, + ns_resolver=self._ns_resolver, + typevars_map=self._typevars_map or {}, + ) + except NameError as e: + raise PydanticUndefinedAnnotation.from_name_error(e) from e + + decorators = cls.__pydantic_decorators__ + computed_fields = decorators.computed_fields + check_decorator_fields_exist( + chain( + decorators.field_validators.values(), + decorators.field_serializers.values(), + decorators.validators.values(), + ), + {*fields.keys(), *computed_fields.keys()}, + ) + + model_validators = decorators.model_validators.values() + + extras_schema = None + extras_keys_schema = None + if core_config.get('extra_fields_behavior') == 'allow': + assert cls.__mro__[0] is cls + assert cls.__mro__[-1] is object + for candidate_cls in cls.__mro__[:-1]: + extras_annotation = getattr(candidate_cls, '__annotations__', {}).get( + '__pydantic_extra__', None + ) + if extras_annotation is not None: + if isinstance(extras_annotation, str): + extras_annotation = _typing_extra.eval_type_backport( + _typing_extra._make_forward_ref( + extras_annotation, is_argument=False, is_class=True + ), + *self._types_namespace, + ) + tp = get_origin(extras_annotation) + if tp not in DICT_TYPES: + raise PydanticSchemaGenerationError( + 'The type annotation for `__pydantic_extra__` must be `dict[str, ...]`' + ) + extra_keys_type, extra_items_type = self._get_args_resolving_forward_refs( + extras_annotation, + required=True, + ) + if extra_keys_type is not str: + extras_keys_schema = self.generate_schema(extra_keys_type) + if not typing_objects.is_any(extra_items_type): + extras_schema = self.generate_schema(extra_items_type) + if extras_keys_schema is not None or extras_schema is not None: + break + + generic_origin: type[BaseModel] | None = getattr(cls, '__pydantic_generic_metadata__', {}).get('origin') + + if cls.__pydantic_root_model__: + # FIXME: should the common field metadata be used here? + inner_schema, _ = self._common_field_schema('root', fields['root'], decorators) + inner_schema = apply_model_validators(inner_schema, model_validators, 'inner') + model_schema = core_schema.model_schema( + cls, + inner_schema, + generic_origin=generic_origin, + custom_init=getattr(cls, '__pydantic_custom_init__', None), + root_model=True, + post_init=getattr(cls, '__pydantic_post_init__', None), + config=core_config, + ref=model_ref, + ) + else: + fields_schema: core_schema.CoreSchema = core_schema.model_fields_schema( + {k: self._generate_md_field_schema(k, v, decorators) for k, v in fields.items()}, + computed_fields=[ + self._computed_field_schema(d, decorators.field_serializers) + for d in computed_fields.values() + ], + extras_schema=extras_schema, + extras_keys_schema=extras_keys_schema, + model_name=cls.__name__, + ) + inner_schema = apply_validators(fields_schema, decorators.root_validators.values()) + inner_schema = apply_model_validators(inner_schema, model_validators, 'inner') + + model_schema = core_schema.model_schema( + cls, + inner_schema, + generic_origin=generic_origin, + custom_init=getattr(cls, '__pydantic_custom_init__', None), + root_model=False, + post_init=getattr(cls, '__pydantic_post_init__', None), + config=core_config, + ref=model_ref, + ) + + schema = self._apply_model_serializers(model_schema, decorators.model_serializers.values()) + schema = apply_model_validators(schema, model_validators, 'outer') + return self.defs.create_definition_reference_schema(schema) + + def _resolve_self_type(self, obj: Any) -> Any: + obj = self.model_type_stack.get() + if obj is None: + raise PydanticUserError('`typing.Self` is invalid in this context', code='invalid-self-type') + return obj + + def _generate_schema_from_get_schema_method(self, obj: Any, source: Any) -> core_schema.CoreSchema | None: + BaseModel_ = import_cached_base_model() + + get_schema = getattr(obj, '__get_pydantic_core_schema__', None) + is_base_model_get_schema = ( + getattr(get_schema, '__func__', None) is BaseModel_.__get_pydantic_core_schema__.__func__ # pyright: ignore[reportFunctionMemberAccess] + ) + + if ( + get_schema is not None + # BaseModel.__get_pydantic_core_schema__ is defined for backwards compatibility, + # to allow existing code to call `super().__get_pydantic_core_schema__` in Pydantic + # model that overrides `__get_pydantic_core_schema__`. However, it raises a deprecation + # warning stating that the method will be removed, and during the core schema gen we actually + # don't call the method: + and not is_base_model_get_schema + ): + # Some referenceable types might have a `__get_pydantic_core_schema__` method + # defined on it by users (e.g. on a dataclass). This generally doesn't play well + # as these types are already recognized by the `GenerateSchema` class and isn't ideal + # as we might end up calling `get_schema_or_ref` (expensive) on types that are actually + # not referenceable: + with self.defs.get_schema_or_ref(obj) as (_, maybe_schema): + if maybe_schema is not None: + return maybe_schema + + if obj is source: + ref_mode = 'unpack' + else: + ref_mode = 'to-def' + schema = get_schema( + source, CallbackGetCoreSchemaHandler(self._generate_schema_inner, self, ref_mode=ref_mode) + ) + if schema['type'] == 'definitions': + schema = self.defs.unpack_definitions(schema) + + ref = get_ref(schema) + if ref: + return self.defs.create_definition_reference_schema(schema) + + # Note: if schema is of type `'definition-ref'`, we might want to copy it as a + # safety measure (because these are inlined in place -- i.e. mutated directly) + return schema + + if get_schema is None and (validators := getattr(obj, '__get_validators__', None)) is not None: + from pydantic.v1 import BaseModel as BaseModelV1 + + if issubclass(obj, BaseModelV1): + warnings.warn( + f'Mixing V1 models and V2 models (or constructs, like `TypeAdapter`) is not supported. Please upgrade `{obj.__name__}` to V2.', + UserWarning, + ) + else: + warnings.warn( + '`__get_validators__` is deprecated and will be removed, use `__get_pydantic_core_schema__` instead.', + PydanticDeprecatedSince20, + ) + return core_schema.chain_schema([core_schema.with_info_plain_validator_function(v) for v in validators()]) + + def _resolve_forward_ref(self, obj: Any) -> Any: + # we assume that types_namespace has the target of forward references in its scope, + # but this could fail, for example, if calling Validator on an imported type which contains + # forward references to other types only defined in the module from which it was imported + # `Validator(SomeImportedTypeAliasWithAForwardReference)` + # or the equivalent for BaseModel + # class Model(BaseModel): + # x: SomeImportedTypeAliasWithAForwardReference + try: + obj = _typing_extra.eval_type_backport(obj, *self._types_namespace) + except NameError as e: + raise PydanticUndefinedAnnotation.from_name_error(e) from e + + # if obj is still a ForwardRef, it means we can't evaluate it, raise PydanticUndefinedAnnotation + if isinstance(obj, ForwardRef): + raise PydanticUndefinedAnnotation(obj.__forward_arg__, f'Unable to evaluate forward reference {obj}') + + if self._typevars_map: + obj = replace_types(obj, self._typevars_map) + + return obj + + @overload + def _get_args_resolving_forward_refs(self, obj: Any, required: Literal[True]) -> tuple[Any, ...]: ... + + @overload + def _get_args_resolving_forward_refs(self, obj: Any) -> tuple[Any, ...] | None: ... + + def _get_args_resolving_forward_refs(self, obj: Any, required: bool = False) -> tuple[Any, ...] | None: + args = get_args(obj) + if args: + if isinstance(obj, GenericAlias): + # PEP 585 generic aliases don't convert args to ForwardRefs, unlike `typing.List/Dict` etc. + args = (_typing_extra._make_forward_ref(a) if isinstance(a, str) else a for a in args) + args = tuple(self._resolve_forward_ref(a) if isinstance(a, ForwardRef) else a for a in args) + elif required: # pragma: no cover + raise TypeError(f'Expected {obj} to have generic parameters but it had none') + return args + + def _get_first_arg_or_any(self, obj: Any) -> Any: + args = self._get_args_resolving_forward_refs(obj) + if not args: + return Any + return args[0] + + def _get_first_two_args_or_any(self, obj: Any) -> tuple[Any, Any]: + args = self._get_args_resolving_forward_refs(obj) + if not args: + return (Any, Any) + if len(args) < 2: + origin = get_origin(obj) + raise TypeError(f'Expected two type arguments for {origin}, got 1') + return args[0], args[1] + + def _generate_schema_inner(self, obj: Any) -> core_schema.CoreSchema: + if typing_objects.is_self(obj): + obj = self._resolve_self_type(obj) + + if typing_objects.is_annotated(get_origin(obj)): + return self._annotated_schema(obj) + + if isinstance(obj, dict): + # we assume this is already a valid schema + return obj # type: ignore[return-value] + + if isinstance(obj, str): + obj = ForwardRef(obj) + + if isinstance(obj, ForwardRef): + return self.generate_schema(self._resolve_forward_ref(obj)) + + BaseModel = import_cached_base_model() + + if lenient_issubclass(obj, BaseModel): + with self.model_type_stack.push(obj): + return self._model_schema(obj) + + if isinstance(obj, PydanticRecursiveRef): + return core_schema.definition_reference_schema(schema_ref=obj.type_ref) + + return self.match_type(obj) + + def match_type(self, obj: Any) -> core_schema.CoreSchema: # noqa: C901 + """Main mapping of types to schemas. + + The general structure is a series of if statements starting with the simple cases + (non-generic primitive types) and then handling generics and other more complex cases. + + Each case either generates a schema directly, calls into a public user-overridable method + (like `GenerateSchema.tuple_variable_schema`) or calls into a private method that handles some + boilerplate before calling into the user-facing method (e.g. `GenerateSchema._tuple_schema`). + + The idea is that we'll evolve this into adding more and more user facing methods over time + as they get requested and we figure out what the right API for them is. + """ + if obj is str: + return core_schema.str_schema() + elif obj is bytes: + return core_schema.bytes_schema() + elif obj is int: + return core_schema.int_schema() + elif obj is float: + return core_schema.float_schema() + elif obj is bool: + return core_schema.bool_schema() + elif obj is complex: + return core_schema.complex_schema() + elif typing_objects.is_any(obj) or obj is object: + return core_schema.any_schema() + elif obj is datetime.date: + return core_schema.date_schema() + elif obj is datetime.datetime: + return core_schema.datetime_schema() + elif obj is datetime.time: + return core_schema.time_schema() + elif obj is datetime.timedelta: + return core_schema.timedelta_schema() + elif obj is Decimal: + return core_schema.decimal_schema() + elif obj is UUID: + return core_schema.uuid_schema() + elif obj is Url: + return core_schema.url_schema() + elif obj is Fraction: + return self._fraction_schema() + elif obj is MultiHostUrl: + return core_schema.multi_host_url_schema() + elif obj is None or obj is _typing_extra.NoneType: + return core_schema.none_schema() + if obj is MISSING: + return core_schema.missing_sentinel_schema() + elif obj in IP_TYPES: + return self._ip_schema(obj) + elif obj in TUPLE_TYPES: + return self._tuple_schema(obj) + elif obj in LIST_TYPES: + return self._list_schema(Any) + elif obj in SET_TYPES: + return self._set_schema(Any) + elif obj in FROZEN_SET_TYPES: + return self._frozenset_schema(Any) + elif obj in SEQUENCE_TYPES: + return self._sequence_schema(Any) + elif obj in ITERABLE_TYPES: + return self._iterable_schema(obj) + elif obj in DICT_TYPES: + return self._dict_schema(Any, Any) + elif obj in PATH_TYPES: + return self._path_schema(obj, Any) + elif obj in DEQUE_TYPES: + return self._deque_schema(Any) + elif obj in MAPPING_TYPES: + return self._mapping_schema(obj, Any, Any) + elif obj in COUNTER_TYPES: + return self._mapping_schema(obj, Any, int) + elif typing_objects.is_typealiastype(obj): + return self._type_alias_type_schema(obj) + elif obj is type: + return self._type_schema() + elif _typing_extra.is_callable(obj): + return core_schema.callable_schema() + elif typing_objects.is_literal(get_origin(obj)): + return self._literal_schema(obj) + elif is_typeddict(obj): + return self._typed_dict_schema(obj, None) + elif _typing_extra.is_namedtuple(obj): + return self._namedtuple_schema(obj, None) + elif typing_objects.is_newtype(obj): + # NewType, can't use isinstance because it fails <3.10 + return self.generate_schema(obj.__supertype__) + elif obj in PATTERN_TYPES: + return self._pattern_schema(obj) + elif _typing_extra.is_hashable(obj): + return self._hashable_schema() + elif isinstance(obj, typing.TypeVar): + return self._unsubstituted_typevar_schema(obj) + elif _typing_extra.is_finalvar(obj): + if obj is Final: + return core_schema.any_schema() + return self.generate_schema( + self._get_first_arg_or_any(obj), + ) + elif isinstance(obj, VALIDATE_CALL_SUPPORTED_TYPES): + return self._call_schema(obj) + elif inspect.isclass(obj) and issubclass(obj, Enum): + return self._enum_schema(obj) + elif obj is ZoneInfo: + return self._zoneinfo_schema() + + # dataclasses.is_dataclass coerces dc instances to types, but we only handle + # the case of a dc type here + if dataclasses.is_dataclass(obj): + return self._dataclass_schema(obj, None) # pyright: ignore[reportArgumentType] + + origin = get_origin(obj) + if origin is not None: + return self._match_generic_type(obj, origin) + + if self._arbitrary_types: + return self._arbitrary_type_schema(obj) + return self._unknown_type_schema(obj) + + def _match_generic_type(self, obj: Any, origin: Any) -> CoreSchema: # noqa: C901 + # Need to handle generic dataclasses before looking for the schema properties because attribute accesses + # on _GenericAlias delegate to the origin type, so lose the information about the concrete parametrization + # As a result, currently, there is no way to cache the schema for generic dataclasses. This may be possible + # to resolve by modifying the value returned by `Generic.__class_getitem__`, but that is a dangerous game. + if dataclasses.is_dataclass(origin): + return self._dataclass_schema(obj, origin) # pyright: ignore[reportArgumentType] + if _typing_extra.is_namedtuple(origin): + return self._namedtuple_schema(obj, origin) + + schema = self._generate_schema_from_get_schema_method(origin, obj) + if schema is not None: + return schema + + if typing_objects.is_typealiastype(origin): + return self._type_alias_type_schema(obj) + elif is_union_origin(origin): + return self._union_schema(obj) + elif origin in TUPLE_TYPES: + return self._tuple_schema(obj) + elif origin in LIST_TYPES: + return self._list_schema(self._get_first_arg_or_any(obj)) + elif origin in SET_TYPES: + return self._set_schema(self._get_first_arg_or_any(obj)) + elif origin in FROZEN_SET_TYPES: + return self._frozenset_schema(self._get_first_arg_or_any(obj)) + elif origin in DICT_TYPES: + return self._dict_schema(*self._get_first_two_args_or_any(obj)) + elif origin in PATH_TYPES: + return self._path_schema(origin, self._get_first_arg_or_any(obj)) + elif origin in DEQUE_TYPES: + return self._deque_schema(self._get_first_arg_or_any(obj)) + elif origin in MAPPING_TYPES: + return self._mapping_schema(origin, *self._get_first_two_args_or_any(obj)) + elif origin in COUNTER_TYPES: + return self._mapping_schema(origin, self._get_first_arg_or_any(obj), int) + elif is_typeddict(origin): + return self._typed_dict_schema(obj, origin) + elif origin in TYPE_TYPES: + return self._subclass_schema(obj) + elif origin in SEQUENCE_TYPES: + return self._sequence_schema(self._get_first_arg_or_any(obj)) + elif origin in ITERABLE_TYPES: + return self._iterable_schema(obj) + elif origin in PATTERN_TYPES: + return self._pattern_schema(obj) + + if self._arbitrary_types: + return self._arbitrary_type_schema(origin) + return self._unknown_type_schema(obj) + + def _generate_td_field_schema( + self, + name: str, + field_info: FieldInfo, + decorators: DecoratorInfos, + *, + required: bool = True, + ) -> core_schema.TypedDictField: + """Prepare a TypedDictField to represent a model or typeddict field.""" + schema, metadata = self._common_field_schema(name, field_info, decorators) + return core_schema.typed_dict_field( + schema, + required=False if not field_info.is_required() else required, + serialization_exclude=field_info.exclude, + validation_alias=_convert_to_aliases(field_info.validation_alias), + serialization_alias=field_info.serialization_alias, + serialization_exclude_if=field_info.exclude_if, + metadata=metadata, + ) + + def _generate_md_field_schema( + self, + name: str, + field_info: FieldInfo, + decorators: DecoratorInfos, + ) -> core_schema.ModelField: + """Prepare a ModelField to represent a model field.""" + schema, metadata = self._common_field_schema(name, field_info, decorators) + return core_schema.model_field( + schema, + serialization_exclude=field_info.exclude, + validation_alias=_convert_to_aliases(field_info.validation_alias), + serialization_alias=field_info.serialization_alias, + serialization_exclude_if=field_info.exclude_if, + frozen=field_info.frozen, + metadata=metadata, + ) + + def _generate_dc_field_schema( + self, + name: str, + field_info: FieldInfo, + decorators: DecoratorInfos, + ) -> core_schema.DataclassField: + """Prepare a DataclassField to represent the parameter/field, of a dataclass.""" + schema, metadata = self._common_field_schema(name, field_info, decorators) + return core_schema.dataclass_field( + name, + schema, + init=field_info.init, + init_only=field_info.init_var or None, + kw_only=None if field_info.kw_only else False, + serialization_exclude=field_info.exclude, + validation_alias=_convert_to_aliases(field_info.validation_alias), + serialization_alias=field_info.serialization_alias, + serialization_exclude_if=field_info.exclude_if, + frozen=field_info.frozen, + metadata=metadata, + ) + + def _common_field_schema( # C901 + self, name: str, field_info: FieldInfo, decorators: DecoratorInfos + ) -> tuple[CoreSchema, dict[str, Any]]: + source_type, annotations = field_info.annotation, field_info.metadata + + def set_discriminator(schema: CoreSchema) -> CoreSchema: + schema = self._apply_discriminator_to_union(schema, field_info.discriminator) + return schema + + # Convert `@field_validator` decorators to `Before/After/Plain/WrapValidator` instances: + validators_from_decorators = [ + _mode_to_validator[decorator.info.mode]._from_decorator(decorator) + for decorator in filter_field_decorator_info_by_field(decorators.field_validators.values(), name) + ] + + with self.field_name_stack.push(name): + if field_info.discriminator is not None: + schema = self._apply_annotations( + source_type, annotations + validators_from_decorators, transform_inner_schema=set_discriminator + ) + else: + schema = self._apply_annotations( + source_type, + annotations + validators_from_decorators, + ) + + # This V1 compatibility shim should eventually be removed + # push down any `each_item=True` validators + # note that this won't work for any Annotated types that get wrapped by a function validator + # but that's okay because that didn't exist in V1 + this_field_validators = filter_field_decorator_info_by_field(decorators.validators.values(), name) + if _validators_require_validate_default(this_field_validators): + field_info.validate_default = True + each_item_validators = [v for v in this_field_validators if v.info.each_item is True] + this_field_validators = [v for v in this_field_validators if v not in each_item_validators] + schema = apply_each_item_validators(schema, each_item_validators) + + schema = apply_validators(schema, this_field_validators) + + # the default validator needs to go outside of any other validators + # so that it is the topmost validator for the field validator + # which uses it to check if the field has a default value or not + if not field_info.is_required(): + schema = wrap_default(field_info, schema) + + schema = self._apply_field_serializers( + schema, filter_field_decorator_info_by_field(decorators.field_serializers.values(), name) + ) + + pydantic_js_updates, pydantic_js_extra = _extract_json_schema_info_from_field_info(field_info) + core_metadata: dict[str, Any] = {} + update_core_metadata( + core_metadata, pydantic_js_updates=pydantic_js_updates, pydantic_js_extra=pydantic_js_extra + ) + + return schema, core_metadata + + def _union_schema(self, union_type: Any) -> core_schema.CoreSchema: + """Generate schema for a Union.""" + args = self._get_args_resolving_forward_refs(union_type, required=True) + choices: list[CoreSchema] = [] + nullable = False + for arg in args: + if arg is None or arg is _typing_extra.NoneType: + nullable = True + else: + choices.append(self.generate_schema(arg)) + + if len(choices) == 1: + s = choices[0] + else: + choices_with_tags: list[CoreSchema | tuple[CoreSchema, str]] = [] + for choice in choices: + tag = cast(CoreMetadata, choice.get('metadata', {})).get('pydantic_internal_union_tag_key') + if tag is not None: + choices_with_tags.append((choice, tag)) + else: + choices_with_tags.append(choice) + s = core_schema.union_schema(choices_with_tags) + + if nullable: + s = core_schema.nullable_schema(s) + return s + + def _type_alias_type_schema(self, obj: TypeAliasType) -> CoreSchema: + with self.defs.get_schema_or_ref(obj) as (ref, maybe_schema): + if maybe_schema is not None: + return maybe_schema + + origin: TypeAliasType = get_origin(obj) or obj + typevars_map = get_standard_typevars_map(obj) + + with self._ns_resolver.push(origin): + try: + annotation = _typing_extra.eval_type(origin.__value__, *self._types_namespace) + except NameError as e: + raise PydanticUndefinedAnnotation.from_name_error(e) from e + annotation = replace_types(annotation, typevars_map) + schema = self.generate_schema(annotation) + assert schema['type'] != 'definitions' + schema['ref'] = ref # type: ignore + return self.defs.create_definition_reference_schema(schema) + + def _literal_schema(self, literal_type: Any) -> CoreSchema: + """Generate schema for a Literal.""" + expected = list(get_literal_values(literal_type, type_check=False, unpack_type_aliases='eager')) + assert expected, f'literal "expected" cannot be empty, obj={literal_type}' + schema = core_schema.literal_schema(expected) + + if self._config_wrapper.use_enum_values and any(isinstance(v, Enum) for v in expected): + schema = core_schema.no_info_after_validator_function( + lambda v: v.value if isinstance(v, Enum) else v, schema + ) + + return schema + + def _typed_dict_schema(self, typed_dict_cls: Any, origin: Any) -> core_schema.CoreSchema: + """Generate a core schema for a `TypedDict` class. + + To be able to build a `DecoratorInfos` instance for the `TypedDict` class (which will include + validators, serializers, etc.), we need to have access to the original bases of the class + (see https://docs.python.org/3/library/types.html#types.get_original_bases). + However, the `__orig_bases__` attribute was only added in 3.12 (https://github.com/python/cpython/pull/103698). + + For this reason, we require Python 3.12 (or using the `typing_extensions` backport). + """ + FieldInfo = import_cached_field_info() + + with ( + self.model_type_stack.push(typed_dict_cls), + self.defs.get_schema_or_ref(typed_dict_cls) as ( + typed_dict_ref, + maybe_schema, + ), + ): + if maybe_schema is not None: + return maybe_schema + + typevars_map = get_standard_typevars_map(typed_dict_cls) + if origin is not None: + typed_dict_cls = origin + + if not _SUPPORTS_TYPEDDICT and type(typed_dict_cls).__module__ == 'typing': + raise PydanticUserError( + 'Please use `typing_extensions.TypedDict` instead of `typing.TypedDict` on Python < 3.12.', + code='typed-dict-version', + ) + + try: + # if a typed dictionary class doesn't have config, we use the parent's config, hence a default of `None` + # see https://github.com/pydantic/pydantic/issues/10917 + config: ConfigDict | None = get_attribute_from_bases(typed_dict_cls, '__pydantic_config__') + except AttributeError: + config = None + + with self._config_wrapper_stack.push(config): + core_config = self._config_wrapper.core_config(title=typed_dict_cls.__name__) + + required_keys: frozenset[str] = typed_dict_cls.__required_keys__ + + fields: dict[str, core_schema.TypedDictField] = {} + + decorators = DecoratorInfos.build(typed_dict_cls) + decorators.update_from_config(self._config_wrapper) + + if self._config_wrapper.use_attribute_docstrings: + field_docstrings = extract_docstrings_from_cls(typed_dict_cls, use_inspect=True) + else: + field_docstrings = None + + try: + annotations = _typing_extra.get_cls_type_hints(typed_dict_cls, ns_resolver=self._ns_resolver) + except NameError as e: + raise PydanticUndefinedAnnotation.from_name_error(e) from e + + readonly_fields: list[str] = [] + + for field_name, annotation in annotations.items(): + field_info = FieldInfo.from_annotation(annotation, _source=AnnotationSource.TYPED_DICT) + field_info.annotation = replace_types(field_info.annotation, typevars_map) + + required = ( + field_name in required_keys or 'required' in field_info._qualifiers + ) and 'not_required' not in field_info._qualifiers + if 'read_only' in field_info._qualifiers: + readonly_fields.append(field_name) + + if ( + field_docstrings is not None + and field_info.description is None + and field_name in field_docstrings + ): + field_info.description = field_docstrings[field_name] + update_field_from_config(self._config_wrapper, field_name, field_info) + + fields[field_name] = self._generate_td_field_schema( + field_name, field_info, decorators, required=required + ) + + if readonly_fields: + fields_repr = ', '.join(repr(f) for f in readonly_fields) + plural = len(readonly_fields) >= 2 + warnings.warn( + f'Item{"s" if plural else ""} {fields_repr} on TypedDict class {typed_dict_cls.__name__!r} ' + f'{"are" if plural else "is"} using the `ReadOnly` qualifier. Pydantic will not protect items ' + 'from any mutation on dictionary instances.', + UserWarning, + ) + + extra_behavior: core_schema.ExtraBehavior = 'ignore' + extras_schema: CoreSchema | None = None # For 'allow', equivalent to `Any` - no validation performed. + + # `__closed__` is `None` when not specified (equivalent to `False`): + is_closed = bool(getattr(typed_dict_cls, '__closed__', False)) + extra_items = getattr(typed_dict_cls, '__extra_items__', typing_extensions.NoExtraItems) + if is_closed: + extra_behavior = 'forbid' + extras_schema = None + elif not typing_objects.is_noextraitems(extra_items): + extra_behavior = 'allow' + extras_schema = self.generate_schema(replace_types(extra_items, typevars_map)) + + if (config_extra := self._config_wrapper.extra) in ('allow', 'forbid'): + if is_closed and config_extra == 'allow': + warnings.warn( + f"TypedDict class {typed_dict_cls.__qualname__!r} is closed, but 'extra' configuration " + "is set to `'allow'`. The 'extra' configuration value will be ignored.", + category=TypedDictExtraConfigWarning, + ) + elif not typing_objects.is_noextraitems(extra_items) and config_extra == 'forbid': + warnings.warn( + f"TypedDict class {typed_dict_cls.__qualname__!r} allows extra items, but 'extra' configuration " + "is set to `'forbid'`. The 'extra' configuration value will be ignored.", + category=TypedDictExtraConfigWarning, + ) + else: + extra_behavior = config_extra + + td_schema = core_schema.typed_dict_schema( + fields, + cls=typed_dict_cls, + computed_fields=[ + self._computed_field_schema(d, decorators.field_serializers) + for d in decorators.computed_fields.values() + ], + extra_behavior=extra_behavior, + extras_schema=extras_schema, + ref=typed_dict_ref, + config=core_config, + ) + + schema = self._apply_model_serializers(td_schema, decorators.model_serializers.values()) + schema = apply_model_validators(schema, decorators.model_validators.values(), 'all') + return self.defs.create_definition_reference_schema(schema) + + def _namedtuple_schema(self, namedtuple_cls: Any, origin: Any) -> core_schema.CoreSchema: + """Generate schema for a NamedTuple.""" + with ( + self.model_type_stack.push(namedtuple_cls), + self.defs.get_schema_or_ref(namedtuple_cls) as ( + namedtuple_ref, + maybe_schema, + ), + ): + if maybe_schema is not None: + return maybe_schema + typevars_map = get_standard_typevars_map(namedtuple_cls) + if origin is not None: + namedtuple_cls = origin + + try: + annotations = _typing_extra.get_cls_type_hints(namedtuple_cls, ns_resolver=self._ns_resolver) + except NameError as e: + raise PydanticUndefinedAnnotation.from_name_error(e) from e + if not annotations: + # annotations is empty, happens if namedtuple_cls defined via collections.namedtuple(...) + annotations: dict[str, Any] = dict.fromkeys(namedtuple_cls._fields, Any) + + if typevars_map: + annotations = { + field_name: replace_types(annotation, typevars_map) + for field_name, annotation in annotations.items() + } + + arguments_schema = core_schema.arguments_schema( + [ + self._generate_parameter_schema( + field_name, + annotation, + source=AnnotationSource.NAMED_TUPLE, + default=namedtuple_cls._field_defaults.get(field_name, Parameter.empty), + ) + for field_name, annotation in annotations.items() + ], + metadata={'pydantic_js_prefer_positional_arguments': True}, + ) + schema = core_schema.call_schema(arguments_schema, namedtuple_cls, ref=namedtuple_ref) + return self.defs.create_definition_reference_schema(schema) + + def _generate_parameter_schema( + self, + name: str, + annotation: type[Any], + source: AnnotationSource, + default: Any = Parameter.empty, + mode: Literal['positional_only', 'positional_or_keyword', 'keyword_only'] | None = None, + ) -> core_schema.ArgumentsParameter: + """Generate the definition of a field in a namedtuple or a parameter in a function signature. + + This definition is meant to be used for the `'arguments'` core schema, which will be replaced + in V3 by the `'arguments-v3`'. + """ + FieldInfo = import_cached_field_info() + + if default is Parameter.empty: + field = FieldInfo.from_annotation(annotation, _source=source) + else: + field = FieldInfo.from_annotated_attribute(annotation, default, _source=source) + + assert field.annotation is not None, 'field.annotation should not be None when generating a schema' + update_field_from_config(self._config_wrapper, name, field) + + with self.field_name_stack.push(name): + schema = self._apply_annotations( + field.annotation, + [field], + # Because we pass `field` as metadata above (required for attributes relevant for + # JSON Scheme generation), we need to ignore the potential warnings about `FieldInfo` + # attributes that will not be used: + check_unsupported_field_info_attributes=False, + ) + + if not field.is_required(): + schema = wrap_default(field, schema) + + parameter_schema = core_schema.arguments_parameter( + name, + schema, + mode=mode, + alias=_convert_to_aliases(field.validation_alias), + ) + + return parameter_schema + + def _generate_parameter_v3_schema( + self, + name: str, + annotation: Any, + source: AnnotationSource, + mode: Literal[ + 'positional_only', + 'positional_or_keyword', + 'keyword_only', + 'var_args', + 'var_kwargs_uniform', + 'var_kwargs_unpacked_typed_dict', + ], + default: Any = Parameter.empty, + ) -> core_schema.ArgumentsV3Parameter: + """Generate the definition of a parameter in a function signature. + + This definition is meant to be used for the `'arguments-v3'` core schema, which will replace + the `'arguments`' schema in V3. + """ + FieldInfo = import_cached_field_info() + + if default is Parameter.empty: + field = FieldInfo.from_annotation(annotation, _source=source) + else: + field = FieldInfo.from_annotated_attribute(annotation, default, _source=source) + update_field_from_config(self._config_wrapper, name, field) + + with self.field_name_stack.push(name): + schema = self._apply_annotations( + field.annotation, + [field], + # Because we pass `field` as metadata above (required for attributes relevant for + # JSON Scheme generation), we need to ignore the potential warnings about `FieldInfo` + # attributes that will not be used: + check_unsupported_field_info_attributes=False, + ) + + if not field.is_required(): + schema = wrap_default(field, schema) + + parameter_schema = core_schema.arguments_v3_parameter( + name=name, + schema=schema, + mode=mode, + alias=_convert_to_aliases(field.validation_alias), + ) + + return parameter_schema + + def _tuple_schema(self, tuple_type: Any) -> core_schema.CoreSchema: + """Generate schema for a Tuple, e.g. `tuple[int, str]` or `tuple[int, ...]`.""" + # TODO: do we really need to resolve type vars here? + typevars_map = get_standard_typevars_map(tuple_type) + params = self._get_args_resolving_forward_refs(tuple_type) + + if typevars_map and params: + params = tuple(replace_types(param, typevars_map) for param in params) + + # NOTE: subtle difference: `tuple[()]` gives `params=()`, whereas `typing.Tuple[()]` gives `params=((),)` + # This is only true for <3.11, on Python 3.11+ `typing.Tuple[()]` gives `params=()` + if not params: + if tuple_type in TUPLE_TYPES: + return core_schema.tuple_schema([core_schema.any_schema()], variadic_item_index=0) + else: + # special case for `tuple[()]` which means `tuple[]` - an empty tuple + return core_schema.tuple_schema([]) + elif params[-1] is Ellipsis: + if len(params) == 2: + return core_schema.tuple_schema([self.generate_schema(params[0])], variadic_item_index=0) + else: + # TODO: something like https://github.com/pydantic/pydantic/issues/5952 + raise ValueError('Variable tuples can only have one type') + elif len(params) == 1 and params[0] == (): + # special case for `tuple[()]` which means `tuple[]` - an empty tuple + # NOTE: This conditional can be removed when we drop support for Python 3.10. + return core_schema.tuple_schema([]) + else: + return core_schema.tuple_schema([self.generate_schema(param) for param in params]) + + def _type_schema(self) -> core_schema.CoreSchema: + return core_schema.custom_error_schema( + core_schema.is_instance_schema(type), + custom_error_type='is_type', + custom_error_message='Input should be a type', + ) + + def _zoneinfo_schema(self) -> core_schema.CoreSchema: + """Generate schema for a zone_info.ZoneInfo object""" + from ._validators import validate_str_is_valid_iana_tz + + metadata = {'pydantic_js_functions': [lambda _1, _2: {'type': 'string', 'format': 'zoneinfo'}]} + return core_schema.no_info_plain_validator_function( + validate_str_is_valid_iana_tz, + serialization=core_schema.to_string_ser_schema(), + metadata=metadata, + ) + + def _union_is_subclass_schema(self, union_type: Any) -> core_schema.CoreSchema: + """Generate schema for `type[Union[X, ...]]`.""" + args = self._get_args_resolving_forward_refs(union_type, required=True) + return core_schema.union_schema([self.generate_schema(type[args]) for args in args]) + + def _subclass_schema(self, type_: Any) -> core_schema.CoreSchema: + """Generate schema for a type, e.g. `type[int]`.""" + type_param = self._get_first_arg_or_any(type_) + + # Assume `type[Annotated[, ...]]` is equivalent to `type[]`: + type_param = _typing_extra.annotated_type(type_param) or type_param + + if typing_objects.is_any(type_param): + return self._type_schema() + elif typing_objects.is_typealiastype(type_param): + return self.generate_schema(type[type_param.__value__]) + elif typing_objects.is_typevar(type_param): + if type_param.__bound__: + if is_union_origin(get_origin(type_param.__bound__)): + return self._union_is_subclass_schema(type_param.__bound__) + return core_schema.is_subclass_schema(type_param.__bound__) + elif type_param.__constraints__: + return core_schema.union_schema([self.generate_schema(type[c]) for c in type_param.__constraints__]) + else: + return self._type_schema() + elif is_union_origin(get_origin(type_param)): + return self._union_is_subclass_schema(type_param) + else: + if typing_objects.is_self(type_param): + type_param = self._resolve_self_type(type_param) + if _typing_extra.is_generic_alias(type_param): + raise PydanticUserError( + 'Subscripting `type[]` with an already parametrized type is not supported. ' + f'Instead of using type[{type_param!r}], use type[{_repr.display_as_type(get_origin(type_param))}].', + code=None, + ) + if not inspect.isclass(type_param): + # when using type[None], this doesn't type convert to type[NoneType], and None isn't a class + # so we handle it manually here + if type_param is None: + return core_schema.is_subclass_schema(_typing_extra.NoneType) + raise TypeError(f'Expected a class, got {type_param!r}') + return core_schema.is_subclass_schema(type_param) + + def _sequence_schema(self, items_type: Any) -> core_schema.CoreSchema: + """Generate schema for a Sequence, e.g. `Sequence[int]`.""" + from ._serializers import serialize_sequence_via_list + + item_type_schema = self.generate_schema(items_type) + list_schema = core_schema.list_schema(item_type_schema) + + json_schema = smart_deepcopy(list_schema) + python_schema = core_schema.is_instance_schema(typing.Sequence, cls_repr='Sequence') + if not typing_objects.is_any(items_type): + from ._validators import sequence_validator + + python_schema = core_schema.chain_schema( + [python_schema, core_schema.no_info_wrap_validator_function(sequence_validator, list_schema)], + ) + + serialization = core_schema.wrap_serializer_function_ser_schema( + serialize_sequence_via_list, schema=item_type_schema, info_arg=True + ) + return core_schema.json_or_python_schema( + json_schema=json_schema, python_schema=python_schema, serialization=serialization + ) + + def _iterable_schema(self, type_: Any) -> core_schema.GeneratorSchema: + """Generate a schema for an `Iterable`.""" + item_type = self._get_first_arg_or_any(type_) + + return core_schema.generator_schema(self.generate_schema(item_type)) + + def _pattern_schema(self, pattern_type: Any) -> core_schema.CoreSchema: + from . import _validators + + metadata = {'pydantic_js_functions': [lambda _1, _2: {'type': 'string', 'format': 'regex'}]} + ser = core_schema.plain_serializer_function_ser_schema( + attrgetter('pattern'), when_used='json', return_schema=core_schema.str_schema() + ) + if pattern_type is typing.Pattern or pattern_type is re.Pattern: + # bare type + return core_schema.no_info_plain_validator_function( + _validators.pattern_either_validator, serialization=ser, metadata=metadata + ) + + param = self._get_args_resolving_forward_refs( + pattern_type, + required=True, + )[0] + if param is str: + return core_schema.no_info_plain_validator_function( + _validators.pattern_str_validator, serialization=ser, metadata=metadata + ) + elif param is bytes: + return core_schema.no_info_plain_validator_function( + _validators.pattern_bytes_validator, serialization=ser, metadata=metadata + ) + else: + raise PydanticSchemaGenerationError(f'Unable to generate pydantic-core schema for {pattern_type!r}.') + + def _hashable_schema(self) -> core_schema.CoreSchema: + return core_schema.custom_error_schema( + schema=core_schema.json_or_python_schema( + json_schema=core_schema.chain_schema( + [core_schema.any_schema(), core_schema.is_instance_schema(collections.abc.Hashable)] + ), + python_schema=core_schema.is_instance_schema(collections.abc.Hashable), + ), + custom_error_type='is_hashable', + custom_error_message='Input should be hashable', + ) + + def _dataclass_schema( + self, dataclass: type[StandardDataclass], origin: type[StandardDataclass] | None + ) -> core_schema.CoreSchema: + """Generate schema for a dataclass.""" + with ( + self.model_type_stack.push(dataclass), + self.defs.get_schema_or_ref(dataclass) as ( + dataclass_ref, + maybe_schema, + ), + ): + if maybe_schema is not None: + return maybe_schema + + schema = dataclass.__dict__.get('__pydantic_core_schema__') + if schema is not None and not isinstance(schema, MockCoreSchema): + if schema['type'] == 'definitions': + schema = self.defs.unpack_definitions(schema) + ref = get_ref(schema) + if ref: + return self.defs.create_definition_reference_schema(schema) + else: + return schema + + typevars_map = get_standard_typevars_map(dataclass) + if origin is not None: + dataclass = origin + + # if (plain) dataclass doesn't have config, we use the parent's config, hence a default of `None` + # (Pydantic dataclasses have an empty dict config by default). + # see https://github.com/pydantic/pydantic/issues/10917 + config = getattr(dataclass, '__pydantic_config__', None) + + from ..dataclasses import is_pydantic_dataclass + + with self._ns_resolver.push(dataclass), self._config_wrapper_stack.push(config): + if is_pydantic_dataclass(dataclass): + if dataclass.__pydantic_fields_complete__(): + # Copy the field info instances to avoid mutating the `FieldInfo` instances + # of the generic dataclass generic origin (e.g. `apply_typevars_map` below). + # Note that we don't apply `deepcopy` on `__pydantic_fields__` because we + # don't want to copy the `FieldInfo` attributes: + fields = { + f_name: copy(field_info) for f_name, field_info in dataclass.__pydantic_fields__.items() + } + if typevars_map: + for field in fields.values(): + field.apply_typevars_map(typevars_map, *self._types_namespace) + else: + try: + fields = rebuild_dataclass_fields( + dataclass, + config_wrapper=self._config_wrapper, + ns_resolver=self._ns_resolver, + typevars_map=typevars_map or {}, + ) + except NameError as e: + raise PydanticUndefinedAnnotation.from_name_error(e) from e + else: + fields = collect_dataclass_fields( + dataclass, + typevars_map=typevars_map, + config_wrapper=self._config_wrapper, + ) + + if self._config_wrapper.extra == 'allow': + # disallow combination of init=False on a dataclass field and extra='allow' on a dataclass + for field_name, field in fields.items(): + if field.init is False: + raise PydanticUserError( + f'Field {field_name} has `init=False` and dataclass has config setting `extra="allow"`. ' + f'This combination is not allowed.', + code='dataclass-init-false-extra-allow', + ) + + decorators = dataclass.__dict__.get('__pydantic_decorators__') + if decorators is None: + decorators = DecoratorInfos.build(dataclass) + decorators.update_from_config(self._config_wrapper) + # Move kw_only=False args to the start of the list, as this is how vanilla dataclasses work. + # Note that when kw_only is missing or None, it is treated as equivalent to kw_only=True + args = sorted( + (self._generate_dc_field_schema(k, v, decorators) for k, v in fields.items()), + key=lambda a: a.get('kw_only') is not False, + ) + has_post_init = hasattr(dataclass, '__post_init__') + has_slots = hasattr(dataclass, '__slots__') + + args_schema = core_schema.dataclass_args_schema( + dataclass.__name__, + args, + computed_fields=[ + self._computed_field_schema(d, decorators.field_serializers) + for d in decorators.computed_fields.values() + ], + collect_init_only=has_post_init, + ) + + inner_schema = apply_validators(args_schema, decorators.root_validators.values()) + + model_validators = decorators.model_validators.values() + inner_schema = apply_model_validators(inner_schema, model_validators, 'inner') + + core_config = self._config_wrapper.core_config(title=dataclass.__name__) + + dc_schema = core_schema.dataclass_schema( + dataclass, + inner_schema, + generic_origin=origin, + post_init=has_post_init, + ref=dataclass_ref, + fields=[field.name for field in dataclasses.fields(dataclass)], + slots=has_slots, + config=core_config, + # we don't use a custom __setattr__ for dataclasses, so we must + # pass along the frozen config setting to the pydantic-core schema + frozen=self._config_wrapper_stack.tail.frozen, + ) + schema = self._apply_model_serializers(dc_schema, decorators.model_serializers.values()) + schema = apply_model_validators(schema, model_validators, 'outer') + return self.defs.create_definition_reference_schema(schema) + + def _call_schema(self, function: ValidateCallSupportedTypes) -> core_schema.CallSchema: + """Generate schema for a Callable. + + TODO support functional validators once we support them in Config + """ + arguments_schema = self._arguments_schema(function) + + return_schema: core_schema.CoreSchema | None = None + config_wrapper = self._config_wrapper + if config_wrapper.validate_return: + sig = signature(function) + return_hint = sig.return_annotation + if return_hint is not sig.empty: + globalns, localns = self._types_namespace + type_hints = _typing_extra.get_function_type_hints( + function, globalns=globalns, localns=localns, include_keys={'return'} + ) + return_schema = self.generate_schema(type_hints['return']) + + return core_schema.call_schema( + arguments_schema, + function, + return_schema=return_schema, + ) + + def _arguments_schema( + self, function: ValidateCallSupportedTypes, parameters_callback: ParametersCallback | None = None + ) -> core_schema.ArgumentsSchema: + """Generate schema for a Signature.""" + mode_lookup: dict[_ParameterKind, Literal['positional_only', 'positional_or_keyword', 'keyword_only']] = { + Parameter.POSITIONAL_ONLY: 'positional_only', + Parameter.POSITIONAL_OR_KEYWORD: 'positional_or_keyword', + Parameter.KEYWORD_ONLY: 'keyword_only', + } + + sig = signature(function) + globalns, localns = self._types_namespace + type_hints = _typing_extra.get_function_type_hints(function, globalns=globalns, localns=localns) + + arguments_list: list[core_schema.ArgumentsParameter] = [] + var_args_schema: core_schema.CoreSchema | None = None + var_kwargs_schema: core_schema.CoreSchema | None = None + var_kwargs_mode: core_schema.VarKwargsMode | None = None + + for i, (name, p) in enumerate(sig.parameters.items()): + if p.annotation is sig.empty: + annotation = typing.cast(Any, Any) + else: + annotation = type_hints[name] + + if parameters_callback is not None: + result = parameters_callback(i, name, annotation) + if result == 'skip': + continue + + parameter_mode = mode_lookup.get(p.kind) + if parameter_mode is not None: + arg_schema = self._generate_parameter_schema( + name, annotation, AnnotationSource.FUNCTION, p.default, parameter_mode + ) + arguments_list.append(arg_schema) + elif p.kind == Parameter.VAR_POSITIONAL: + var_args_schema = self.generate_schema(annotation) + else: + assert p.kind == Parameter.VAR_KEYWORD, p.kind + + unpack_type = _typing_extra.unpack_type(annotation) + if unpack_type is not None: + origin = get_origin(unpack_type) or unpack_type + if not is_typeddict(origin): + raise PydanticUserError( + f'Expected a `TypedDict` class inside `Unpack[...]`, got {unpack_type!r}', + code='unpack-typed-dict', + ) + non_pos_only_param_names = { + name for name, p in sig.parameters.items() if p.kind != Parameter.POSITIONAL_ONLY + } + overlapping_params = non_pos_only_param_names.intersection(origin.__annotations__) + if overlapping_params: + raise PydanticUserError( + f'Typed dictionary {origin.__name__!r} overlaps with parameter' + f'{"s" if len(overlapping_params) >= 2 else ""} ' + f'{", ".join(repr(p) for p in sorted(overlapping_params))}', + code='overlapping-unpack-typed-dict', + ) + + var_kwargs_mode = 'unpacked-typed-dict' + var_kwargs_schema = self._typed_dict_schema(unpack_type, get_origin(unpack_type)) + else: + var_kwargs_mode = 'uniform' + var_kwargs_schema = self.generate_schema(annotation) + + return core_schema.arguments_schema( + arguments_list, + var_args_schema=var_args_schema, + var_kwargs_mode=var_kwargs_mode, + var_kwargs_schema=var_kwargs_schema, + validate_by_name=self._config_wrapper.validate_by_name, + ) + + def _arguments_v3_schema( + self, function: ValidateCallSupportedTypes, parameters_callback: ParametersCallback | None = None + ) -> core_schema.ArgumentsV3Schema: + mode_lookup: dict[ + _ParameterKind, Literal['positional_only', 'positional_or_keyword', 'var_args', 'keyword_only'] + ] = { + Parameter.POSITIONAL_ONLY: 'positional_only', + Parameter.POSITIONAL_OR_KEYWORD: 'positional_or_keyword', + Parameter.VAR_POSITIONAL: 'var_args', + Parameter.KEYWORD_ONLY: 'keyword_only', + } + + sig = signature(function) + globalns, localns = self._types_namespace + type_hints = _typing_extra.get_function_type_hints(function, globalns=globalns, localns=localns) + + parameters_list: list[core_schema.ArgumentsV3Parameter] = [] + + for i, (name, p) in enumerate(sig.parameters.items()): + if parameters_callback is not None: + result = parameters_callback(i, name, p.annotation) + if result == 'skip': + continue + + if p.annotation is Parameter.empty: + annotation = typing.cast(Any, Any) + else: + annotation = type_hints[name] + + parameter_mode = mode_lookup.get(p.kind) + if parameter_mode is None: + assert p.kind == Parameter.VAR_KEYWORD, p.kind + + unpack_type = _typing_extra.unpack_type(annotation) + if unpack_type is not None: + origin = get_origin(unpack_type) or unpack_type + if not is_typeddict(origin): + raise PydanticUserError( + f'Expected a `TypedDict` class inside `Unpack[...]`, got {unpack_type!r}', + code='unpack-typed-dict', + ) + non_pos_only_param_names = { + name for name, p in sig.parameters.items() if p.kind != Parameter.POSITIONAL_ONLY + } + overlapping_params = non_pos_only_param_names.intersection(origin.__annotations__) + if overlapping_params: + raise PydanticUserError( + f'Typed dictionary {origin.__name__!r} overlaps with parameter' + f'{"s" if len(overlapping_params) >= 2 else ""} ' + f'{", ".join(repr(p) for p in sorted(overlapping_params))}', + code='overlapping-unpack-typed-dict', + ) + parameter_mode = 'var_kwargs_unpacked_typed_dict' + annotation = unpack_type + else: + parameter_mode = 'var_kwargs_uniform' + + parameters_list.append( + self._generate_parameter_v3_schema( + name, annotation, AnnotationSource.FUNCTION, parameter_mode, default=p.default + ) + ) + + return core_schema.arguments_v3_schema( + parameters_list, + validate_by_name=self._config_wrapper.validate_by_name, + ) + + def _unsubstituted_typevar_schema(self, typevar: typing.TypeVar) -> core_schema.CoreSchema: + try: + has_default = typevar.has_default() # pyright: ignore[reportAttributeAccessIssue] + except AttributeError: + # Happens if using `typing.TypeVar` (and not `typing_extensions`) on Python < 3.13 + pass + else: + if has_default: + return self.generate_schema(typevar.__default__) # pyright: ignore[reportAttributeAccessIssue] + + if constraints := typevar.__constraints__: + return self._union_schema(typing.Union[constraints]) + + if bound := typevar.__bound__: + schema = self.generate_schema(bound) + schema['serialization'] = core_schema.simple_ser_schema('any') + return schema + + return core_schema.any_schema() + + def _computed_field_schema( + self, + d: Decorator[ComputedFieldInfo], + field_serializers: dict[str, Decorator[FieldSerializerDecoratorInfo]], + ) -> core_schema.ComputedField: + if d.info.return_type is not PydanticUndefined: + return_type = d.info.return_type + else: + try: + # Do not pass in globals as the function could be defined in a different module. + # Instead, let `get_callable_return_type` infer the globals to use, but still pass + # in locals that may contain a parent/rebuild namespace: + return_type = _decorators.get_callable_return_type(d.func, localns=self._types_namespace.locals) + except NameError as e: + raise PydanticUndefinedAnnotation.from_name_error(e) from e + if return_type is PydanticUndefined: + raise PydanticUserError( + 'Computed field is missing return type annotation or specifying `return_type`' + ' to the `@computed_field` decorator (e.g. `@computed_field(return_type=int | str)`)', + code='model-field-missing-annotation', + ) + + return_type = replace_types(return_type, self._typevars_map) + # Create a new ComputedFieldInfo so that different type parametrizations of the same + # generic model's computed field can have different return types. + d.info = dataclasses.replace(d.info, return_type=return_type) + return_type_schema = self.generate_schema(return_type) + # Apply serializers to computed field if there exist + return_type_schema = self._apply_field_serializers( + return_type_schema, + filter_field_decorator_info_by_field(field_serializers.values(), d.cls_var_name), + ) + + pydantic_js_updates, pydantic_js_extra = _extract_json_schema_info_from_field_info(d.info) + core_metadata: dict[str, Any] = {} + update_core_metadata( + core_metadata, + pydantic_js_updates={'readOnly': True, **(pydantic_js_updates if pydantic_js_updates else {})}, + pydantic_js_extra=pydantic_js_extra, + ) + return core_schema.computed_field( + d.cls_var_name, return_schema=return_type_schema, alias=d.info.alias, metadata=core_metadata + ) + + def _annotated_schema(self, annotated_type: Any) -> core_schema.CoreSchema: + """Generate schema for an Annotated type, e.g. `Annotated[int, Field(...)]` or `Annotated[int, Gt(0)]`.""" + FieldInfo = import_cached_field_info() + source_type, *annotations = self._get_args_resolving_forward_refs( + annotated_type, + required=True, + ) + schema = self._apply_annotations(source_type, annotations) + # put the default validator last so that TypeAdapter.get_default_value() works + # even if there are function validators involved + for annotation in annotations: + if isinstance(annotation, FieldInfo): + schema = wrap_default(annotation, schema) + return schema + + def _apply_annotations( + self, + source_type: Any, + annotations: list[Any], + transform_inner_schema: Callable[[CoreSchema], CoreSchema] = lambda x: x, + check_unsupported_field_info_attributes: bool = True, + ) -> CoreSchema: + """Apply arguments from `Annotated` or from `FieldInfo` to a schema. + + This gets called by `GenerateSchema._annotated_schema` but differs from it in that it does + not expect `source_type` to be an `Annotated` object, it expects it to be the first argument of that + (in other words, `GenerateSchema._annotated_schema` just unpacks `Annotated`, this process it). + """ + annotations = list(_known_annotated_metadata.expand_grouped_metadata(annotations)) + + pydantic_js_annotation_functions: list[GetJsonSchemaFunction] = [] + + def inner_handler(obj: Any) -> CoreSchema: + schema = self._generate_schema_from_get_schema_method(obj, source_type) + + if schema is None: + schema = self._generate_schema_inner(obj) + + metadata_js_function = _extract_get_pydantic_json_schema(obj) + if metadata_js_function is not None: + metadata_schema = resolve_original_schema(schema, self.defs) + if metadata_schema is not None: + self._add_js_function(metadata_schema, metadata_js_function) + return transform_inner_schema(schema) + + get_inner_schema = CallbackGetCoreSchemaHandler(inner_handler, self) + + for annotation in annotations: + if annotation is None: + continue + get_inner_schema = self._get_wrapped_inner_schema( + get_inner_schema, + annotation, + pydantic_js_annotation_functions, + check_unsupported_field_info_attributes=check_unsupported_field_info_attributes, + ) + + schema = get_inner_schema(source_type) + if pydantic_js_annotation_functions: + core_metadata = schema.setdefault('metadata', {}) + update_core_metadata(core_metadata, pydantic_js_annotation_functions=pydantic_js_annotation_functions) + return _add_custom_serialization_from_json_encoders(self._config_wrapper.json_encoders, source_type, schema) + + def _apply_single_annotation( + self, + schema: core_schema.CoreSchema, + metadata: Any, + check_unsupported_field_info_attributes: bool = True, + ) -> core_schema.CoreSchema: + FieldInfo = import_cached_field_info() + + if isinstance(metadata, FieldInfo): + if ( + check_unsupported_field_info_attributes + # HACK: we don't want to emit the warning for `FieldInfo` subclasses, because FastAPI does weird manipulations + # with its subclasses and their annotations: + and type(metadata) is FieldInfo + ): + for attr, value in (unsupported_attributes := self._get_unsupported_field_info_attributes(metadata)): + warnings.warn( + f'The {attr!r} attribute with value {value!r} was provided to the `Field()` function, ' + f'which has no effect in the context it was used. {attr!r} is field-specific metadata, ' + 'and can only be attached to a model field using `Annotated` metadata or by assignment. ' + 'This may have happened because an `Annotated` type alias using the `type` statement was ' + 'used, or if the `Field()` function was attached to a single member of a union type.', + category=UnsupportedFieldAttributeWarning, + ) + + if ( + metadata.default_factory_takes_validated_data + and self.model_type_stack.get() is None + and 'defaut_factory' not in unsupported_attributes + ): + warnings.warn( + "A 'default_factory' taking validated data as an argument was provided to the `Field()` function, " + 'but no validated data is available in the context it was used.', + category=UnsupportedFieldAttributeWarning, + ) + + for field_metadata in metadata.metadata: + schema = self._apply_single_annotation(schema, field_metadata) + + if metadata.discriminator is not None: + schema = self._apply_discriminator_to_union(schema, metadata.discriminator) + return schema + + if schema['type'] == 'nullable': + # for nullable schemas, metadata is automatically applied to the inner schema + inner = schema.get('schema', core_schema.any_schema()) + inner = self._apply_single_annotation(inner, metadata) + if inner: + schema['schema'] = inner + return schema + + original_schema = schema + ref = schema.get('ref') + if ref is not None: + schema = schema.copy() + new_ref = ref + f'_{repr(metadata)}' + if (existing := self.defs.get_schema_from_ref(new_ref)) is not None: + return existing + schema['ref'] = new_ref # pyright: ignore[reportGeneralTypeIssues] + elif schema['type'] == 'definition-ref': + ref = schema['schema_ref'] + if (referenced_schema := self.defs.get_schema_from_ref(ref)) is not None: + schema = referenced_schema.copy() + new_ref = ref + f'_{repr(metadata)}' + if (existing := self.defs.get_schema_from_ref(new_ref)) is not None: + return existing + schema['ref'] = new_ref # pyright: ignore[reportGeneralTypeIssues] + + maybe_updated_schema = _known_annotated_metadata.apply_known_metadata(metadata, schema) + + if maybe_updated_schema is not None: + return maybe_updated_schema + return original_schema + + def _apply_single_annotation_json_schema( + self, schema: core_schema.CoreSchema, metadata: Any + ) -> core_schema.CoreSchema: + FieldInfo = import_cached_field_info() + + if isinstance(metadata, FieldInfo): + for field_metadata in metadata.metadata: + schema = self._apply_single_annotation_json_schema(schema, field_metadata) + + pydantic_js_updates, pydantic_js_extra = _extract_json_schema_info_from_field_info(metadata) + core_metadata = schema.setdefault('metadata', {}) + update_core_metadata( + core_metadata, pydantic_js_updates=pydantic_js_updates, pydantic_js_extra=pydantic_js_extra + ) + return schema + + def _get_unsupported_field_info_attributes(self, field_info: FieldInfo) -> list[tuple[str, Any]]: + """Get the list of unsupported `FieldInfo` attributes when not directly used in `Annotated` for field annotations.""" + unused_metadata: list[tuple[str, Any]] = [] + for unused_metadata_name, unset_value in UNSUPPORTED_STANDALONE_FIELDINFO_ATTRIBUTES: + if ( + (unused_metadata_value := getattr(field_info, unused_metadata_name)) is not unset_value + # `default` and `default_factory` can still be used with a type adapter, so only include them + # if used with a model-like class: + and ( + unused_metadata_name not in ('default', 'default_factory') + or self.model_type_stack.get() is not None + ) + # Setting `alias` will set `validation/serialization_alias` as well, so we want to avoid duplicate warnings: + and ( + unused_metadata_name not in ('validation_alias', 'serialization_alias') + or 'alias' not in field_info._attributes_set + ) + ): + unused_metadata.append((unused_metadata_name, unused_metadata_value)) + + return unused_metadata + + def _get_wrapped_inner_schema( + self, + get_inner_schema: GetCoreSchemaHandler, + annotation: Any, + pydantic_js_annotation_functions: list[GetJsonSchemaFunction], + check_unsupported_field_info_attributes: bool = False, + ) -> CallbackGetCoreSchemaHandler: + annotation_get_schema: GetCoreSchemaFunction | None = getattr(annotation, '__get_pydantic_core_schema__', None) + + def new_handler(source: Any) -> core_schema.CoreSchema: + if annotation_get_schema is not None: + schema = annotation_get_schema(source, get_inner_schema) + else: + schema = get_inner_schema(source) + schema = self._apply_single_annotation( + schema, + annotation, + check_unsupported_field_info_attributes=check_unsupported_field_info_attributes, + ) + schema = self._apply_single_annotation_json_schema(schema, annotation) + + metadata_js_function = _extract_get_pydantic_json_schema(annotation) + if metadata_js_function is not None: + pydantic_js_annotation_functions.append(metadata_js_function) + return schema + + return CallbackGetCoreSchemaHandler(new_handler, self) + + def _apply_field_serializers( + self, + schema: core_schema.CoreSchema, + serializers: list[Decorator[FieldSerializerDecoratorInfo]], + ) -> core_schema.CoreSchema: + """Apply field serializers to a schema.""" + if serializers: + schema = copy(schema) + if schema['type'] == 'definitions': + inner_schema = schema['schema'] + schema['schema'] = self._apply_field_serializers(inner_schema, serializers) + return schema + elif 'ref' in schema: + schema = self.defs.create_definition_reference_schema(schema) + + # use the last serializer to make it easy to override a serializer set on a parent model + serializer = serializers[-1] + is_field_serializer, info_arg = inspect_field_serializer(serializer.func, serializer.info.mode) + + if serializer.info.return_type is not PydanticUndefined: + return_type = serializer.info.return_type + else: + try: + # Do not pass in globals as the function could be defined in a different module. + # Instead, let `get_callable_return_type` infer the globals to use, but still pass + # in locals that may contain a parent/rebuild namespace: + return_type = _decorators.get_callable_return_type( + serializer.func, localns=self._types_namespace.locals + ) + except NameError as e: + raise PydanticUndefinedAnnotation.from_name_error(e) from e + + if return_type is PydanticUndefined: + return_schema = None + else: + return_schema = self.generate_schema(return_type) + + if serializer.info.mode == 'wrap': + schema['serialization'] = core_schema.wrap_serializer_function_ser_schema( + serializer.func, + is_field_serializer=is_field_serializer, + info_arg=info_arg, + return_schema=return_schema, + when_used=serializer.info.when_used, + ) + else: + assert serializer.info.mode == 'plain' + schema['serialization'] = core_schema.plain_serializer_function_ser_schema( + serializer.func, + is_field_serializer=is_field_serializer, + info_arg=info_arg, + return_schema=return_schema, + when_used=serializer.info.when_used, + ) + return schema + + def _apply_model_serializers( + self, schema: core_schema.CoreSchema, serializers: Iterable[Decorator[ModelSerializerDecoratorInfo]] + ) -> core_schema.CoreSchema: + """Apply model serializers to a schema.""" + ref: str | None = schema.pop('ref', None) # type: ignore + if serializers: + serializer = list(serializers)[-1] + info_arg = inspect_model_serializer(serializer.func, serializer.info.mode) + + if serializer.info.return_type is not PydanticUndefined: + return_type = serializer.info.return_type + else: + try: + # Do not pass in globals as the function could be defined in a different module. + # Instead, let `get_callable_return_type` infer the globals to use, but still pass + # in locals that may contain a parent/rebuild namespace: + return_type = _decorators.get_callable_return_type( + serializer.func, localns=self._types_namespace.locals + ) + except NameError as e: + raise PydanticUndefinedAnnotation.from_name_error(e) from e + + if return_type is PydanticUndefined: + return_schema = None + else: + return_schema = self.generate_schema(return_type) + + if serializer.info.mode == 'wrap': + ser_schema: core_schema.SerSchema = core_schema.wrap_serializer_function_ser_schema( + serializer.func, + info_arg=info_arg, + return_schema=return_schema, + when_used=serializer.info.when_used, + ) + else: + # plain + ser_schema = core_schema.plain_serializer_function_ser_schema( + serializer.func, + info_arg=info_arg, + return_schema=return_schema, + when_used=serializer.info.when_used, + ) + schema['serialization'] = ser_schema + if ref: + schema['ref'] = ref # type: ignore + return schema + + +_VALIDATOR_F_MATCH: Mapping[ + tuple[FieldValidatorModes, Literal['no-info', 'with-info']], + Callable[[Callable[..., Any], core_schema.CoreSchema], core_schema.CoreSchema], +] = { + ('before', 'no-info'): lambda f, schema: core_schema.no_info_before_validator_function(f, schema), + ('after', 'no-info'): lambda f, schema: core_schema.no_info_after_validator_function(f, schema), + ('plain', 'no-info'): lambda f, _: core_schema.no_info_plain_validator_function(f), + ('wrap', 'no-info'): lambda f, schema: core_schema.no_info_wrap_validator_function(f, schema), + ('before', 'with-info'): lambda f, schema: core_schema.with_info_before_validator_function(f, schema), + ('after', 'with-info'): lambda f, schema: core_schema.with_info_after_validator_function(f, schema), + ('plain', 'with-info'): lambda f, _: core_schema.with_info_plain_validator_function(f), + ('wrap', 'with-info'): lambda f, schema: core_schema.with_info_wrap_validator_function(f, schema), +} + + +# TODO V3: this function is only used for deprecated decorators. It should +# be removed once we drop support for those. +def apply_validators( + schema: core_schema.CoreSchema, + validators: Iterable[Decorator[RootValidatorDecoratorInfo]] + | Iterable[Decorator[ValidatorDecoratorInfo]] + | Iterable[Decorator[FieldValidatorDecoratorInfo]], +) -> core_schema.CoreSchema: + """Apply validators to a schema. + + Args: + schema: The schema to apply validators on. + validators: An iterable of validators. + field_name: The name of the field if validators are being applied to a model field. + + Returns: + The updated schema. + """ + for validator in validators: + # Actually, type could be 'field' or 'model', but this is only used for deprecated + # decorators, so let's not worry about it. + info_arg = inspect_validator(validator.func, mode=validator.info.mode, type='field') + val_type = 'with-info' if info_arg else 'no-info' + + schema = _VALIDATOR_F_MATCH[(validator.info.mode, val_type)](validator.func, schema) + return schema + + +def _validators_require_validate_default(validators: Iterable[Decorator[ValidatorDecoratorInfo]]) -> bool: + """In v1, if any of the validators for a field had `always=True`, the default value would be validated. + + This serves as an auxiliary function for re-implementing that logic, by looping over a provided + collection of (v1-style) ValidatorDecoratorInfo's and checking if any of them have `always=True`. + + We should be able to drop this function and the associated logic calling it once we drop support + for v1-style validator decorators. (Or we can extend it and keep it if we add something equivalent + to the v1-validator `always` kwarg to `field_validator`.) + """ + for validator in validators: + if validator.info.always: + return True + return False + + +def _convert_to_aliases( + alias: str | AliasChoices | AliasPath | None, +) -> str | list[str | int] | list[list[str | int]] | None: + if isinstance(alias, (AliasChoices, AliasPath)): + return alias.convert_to_aliases() + else: + return alias + + +def apply_model_validators( + schema: core_schema.CoreSchema, + validators: Iterable[Decorator[ModelValidatorDecoratorInfo]], + mode: Literal['inner', 'outer', 'all'], +) -> core_schema.CoreSchema: + """Apply model validators to a schema. + + If mode == 'inner', only "before" validators are applied + If mode == 'outer', validators other than "before" are applied + If mode == 'all', all validators are applied + + Args: + schema: The schema to apply validators on. + validators: An iterable of validators. + mode: The validator mode. + + Returns: + The updated schema. + """ + ref: str | None = schema.pop('ref', None) # type: ignore + for validator in validators: + if mode == 'inner' and validator.info.mode != 'before': + continue + if mode == 'outer' and validator.info.mode == 'before': + continue + info_arg = inspect_validator(validator.func, mode=validator.info.mode, type='model') + if validator.info.mode == 'wrap': + if info_arg: + schema = core_schema.with_info_wrap_validator_function(function=validator.func, schema=schema) + else: + schema = core_schema.no_info_wrap_validator_function(function=validator.func, schema=schema) + elif validator.info.mode == 'before': + if info_arg: + schema = core_schema.with_info_before_validator_function(function=validator.func, schema=schema) + else: + schema = core_schema.no_info_before_validator_function(function=validator.func, schema=schema) + else: + assert validator.info.mode == 'after' + if info_arg: + schema = core_schema.with_info_after_validator_function(function=validator.func, schema=schema) + else: + schema = core_schema.no_info_after_validator_function(function=validator.func, schema=schema) + if ref: + schema['ref'] = ref # type: ignore + return schema + + +def wrap_default(field_info: FieldInfo, schema: core_schema.CoreSchema) -> core_schema.CoreSchema: + """Wrap schema with default schema if default value or `default_factory` are available. + + Args: + field_info: The field info object. + schema: The schema to apply default on. + + Returns: + Updated schema by default value or `default_factory`. + """ + if field_info.default_factory: + return core_schema.with_default_schema( + schema, + default_factory=field_info.default_factory, + default_factory_takes_data=takes_validated_data_argument(field_info.default_factory), + validate_default=field_info.validate_default, + ) + elif field_info.default is not PydanticUndefined: + return core_schema.with_default_schema( + schema, default=field_info.default, validate_default=field_info.validate_default + ) + else: + return schema + + +def _extract_get_pydantic_json_schema(tp: Any) -> GetJsonSchemaFunction | None: + """Extract `__get_pydantic_json_schema__` from a type, handling the deprecated `__modify_schema__`.""" + js_modify_function = getattr(tp, '__get_pydantic_json_schema__', None) + + if hasattr(tp, '__modify_schema__'): + BaseModel = import_cached_base_model() + + has_custom_v2_modify_js_func = ( + js_modify_function is not None + and BaseModel.__get_pydantic_json_schema__.__func__ # type: ignore + not in (js_modify_function, getattr(js_modify_function, '__func__', None)) + ) + + if not has_custom_v2_modify_js_func: + cls_name = getattr(tp, '__name__', None) + raise PydanticUserError( + f'The `__modify_schema__` method is not supported in Pydantic v2. ' + f'Use `__get_pydantic_json_schema__` instead{f" in class `{cls_name}`" if cls_name else ""}.', + code='custom-json-schema', + ) + + if (origin := get_origin(tp)) is not None: + # Generic aliases proxy attribute access to the origin, *except* dunder attributes, + # such as `__get_pydantic_json_schema__`, hence the explicit check. + return _extract_get_pydantic_json_schema(origin) + + if js_modify_function is None: + return None + + return js_modify_function + + +def resolve_original_schema(schema: CoreSchema, definitions: _Definitions) -> CoreSchema | None: + if schema['type'] == 'definition-ref': + return definitions.get_schema_from_ref(schema['schema_ref']) + elif schema['type'] == 'definitions': + return schema['schema'] + else: + return schema + + +def _inlining_behavior( + def_ref: core_schema.DefinitionReferenceSchema, +) -> Literal['inline', 'keep', 'preserve_metadata']: + """Determine the inlining behavior of the `'definition-ref'` schema. + + - If no `'serialization'` schema and no metadata is attached, the schema can safely be inlined. + - If it has metadata but only related to the deferred discriminator application, it can be inlined + provided that such metadata is kept. + - Otherwise, the schema should not be inlined. Doing so would remove the `'serialization'` schema or metadata. + """ + if 'serialization' in def_ref: + return 'keep' + metadata = def_ref.get('metadata') + if not metadata: + return 'inline' + if len(metadata) == 1 and 'pydantic_internal_union_discriminator' in metadata: + return 'preserve_metadata' + return 'keep' + + +class _Definitions: + """Keeps track of references and definitions.""" + + _recursively_seen: set[str] + """A set of recursively seen references. + + When a referenceable type is encountered, the `get_schema_or_ref` context manager is + entered to compute the reference. If the type references itself by some way (e.g. for + a dataclass a Pydantic model, the class can be referenced as a field annotation), + entering the context manager again will yield a `'definition-ref'` schema that should + short-circuit the normal generation process, as the reference was already in this set. + """ + + _definitions: dict[str, core_schema.CoreSchema] + """A mapping of references to their corresponding schema. + + When a schema for a referenceable type is generated, it is stored in this mapping. If the + same type is encountered again, the reference is yielded by the `get_schema_or_ref` context + manager. + """ + + def __init__(self) -> None: + self._recursively_seen = set() + self._definitions = {} + + @contextmanager + def get_schema_or_ref(self, tp: Any, /) -> Generator[tuple[str, core_schema.DefinitionReferenceSchema | None]]: + """Get a definition for `tp` if one exists. + + If a definition exists, a tuple of `(ref_string, CoreSchema)` is returned. + If no definition exists yet, a tuple of `(ref_string, None)` is returned. + + Note that the returned `CoreSchema` will always be a `DefinitionReferenceSchema`, + not the actual definition itself. + + This should be called for any type that can be identified by reference. + This includes any recursive types. + + At present the following types can be named/recursive: + + - Pydantic model + - Pydantic and stdlib dataclasses + - Typed dictionaries + - Named tuples + - `TypeAliasType` instances + - Enums + """ + ref = get_type_ref(tp) + # return the reference if we're either (1) in a cycle or (2) it the reference was already encountered: + if ref in self._recursively_seen or ref in self._definitions: + yield (ref, core_schema.definition_reference_schema(ref)) + else: + self._recursively_seen.add(ref) + try: + yield (ref, None) + finally: + self._recursively_seen.discard(ref) + + def get_schema_from_ref(self, ref: str) -> CoreSchema | None: + """Resolve the schema from the given reference.""" + return self._definitions.get(ref) + + def create_definition_reference_schema(self, schema: CoreSchema) -> core_schema.DefinitionReferenceSchema: + """Store the schema as a definition and return a `'definition-reference'` schema pointing to it. + + The schema must have a reference attached to it. + """ + ref = schema['ref'] # pyright: ignore + self._definitions[ref] = schema + return core_schema.definition_reference_schema(ref) + + def unpack_definitions(self, schema: core_schema.DefinitionsSchema) -> CoreSchema: + """Store the definitions of the `'definitions'` core schema and return the inner core schema.""" + for def_schema in schema['definitions']: + self._definitions[def_schema['ref']] = def_schema # pyright: ignore + return schema['schema'] + + def finalize_schema(self, schema: CoreSchema) -> CoreSchema: + """Finalize the core schema. + + This traverses the core schema and referenced definitions, replaces `'definition-ref'` schemas + by the referenced definition if possible, and applies deferred discriminators. + """ + definitions = self._definitions + try: + gather_result = gather_schemas_for_cleaning( + schema, + definitions=definitions, + ) + except MissingDefinitionError as e: + raise InvalidSchemaError from e + + remaining_defs: dict[str, CoreSchema] = {} + + # Note: this logic doesn't play well when core schemas with deferred discriminator metadata + # and references are encountered. See the `test_deferred_discriminated_union_and_references()` test. + for ref, inlinable_def_ref in gather_result['collected_references'].items(): + if inlinable_def_ref is not None and (inlining_behavior := _inlining_behavior(inlinable_def_ref)) != 'keep': + if inlining_behavior == 'inline': + # `ref` was encountered, and only once: + # - `inlinable_def_ref` is a `'definition-ref'` schema and is guaranteed to be + # the only one. Transform it into the definition it points to. + # - Do not store the definition in the `remaining_defs`. + inlinable_def_ref.clear() # pyright: ignore[reportAttributeAccessIssue] + inlinable_def_ref.update(self._resolve_definition(ref, definitions)) # pyright: ignore + elif inlining_behavior == 'preserve_metadata': + # `ref` was encountered, and only once, but contains discriminator metadata. + # We will do the same thing as if `inlining_behavior` was `'inline'`, but make + # sure to keep the metadata for the deferred discriminator application logic below. + meta = inlinable_def_ref.pop('metadata') + inlinable_def_ref.clear() # pyright: ignore[reportAttributeAccessIssue] + inlinable_def_ref.update(self._resolve_definition(ref, definitions)) # pyright: ignore + inlinable_def_ref['metadata'] = meta + else: + # `ref` was encountered, at least two times (or only once, but with metadata or a serialization schema): + # - Do not inline the `'definition-ref'` schemas (they are not provided in the gather result anyway). + # - Store the the definition in the `remaining_defs` + remaining_defs[ref] = self._resolve_definition(ref, definitions) + + for cs in gather_result['deferred_discriminator_schemas']: + discriminator: str | None = cs['metadata'].pop('pydantic_internal_union_discriminator', None) # pyright: ignore[reportTypedDictNotRequiredAccess] + if discriminator is None: + # This can happen in rare scenarios, when a deferred schema is present multiple times in the + # gather result (e.g. when using the `Sequence` type -- see `test_sequence_discriminated_union()`). + # In this case, a previous loop iteration applied the discriminator and so we can just skip it here. + continue + applied = _discriminated_union.apply_discriminator(cs.copy(), discriminator, remaining_defs) + # Mutate the schema directly to have the discriminator applied + cs.clear() # pyright: ignore[reportAttributeAccessIssue] + cs.update(applied) # pyright: ignore + + if remaining_defs: + schema = core_schema.definitions_schema(schema=schema, definitions=[*remaining_defs.values()]) + return schema + + def _resolve_definition(self, ref: str, definitions: dict[str, CoreSchema]) -> CoreSchema: + definition = definitions[ref] + if definition['type'] != 'definition-ref': + return definition + + # Some `'definition-ref'` schemas might act as "intermediate" references (e.g. when using + # a PEP 695 type alias (which is referenceable) that references another PEP 695 type alias): + visited: set[str] = set() + while definition['type'] == 'definition-ref' and _inlining_behavior(definition) == 'inline': + schema_ref = definition['schema_ref'] + if schema_ref in visited: + raise PydanticUserError( + f'{ref} contains a circular reference to itself.', code='circular-reference-schema' + ) + visited.add(schema_ref) + definition = definitions[schema_ref] + return {**definition, 'ref': ref} # pyright: ignore[reportReturnType] + + +class _FieldNameStack: + __slots__ = ('_stack',) + + def __init__(self) -> None: + self._stack: list[str] = [] + + @contextmanager + def push(self, field_name: str) -> Iterator[None]: + self._stack.append(field_name) + yield + self._stack.pop() + + def get(self) -> str | None: + if self._stack: + return self._stack[-1] + else: + return None + + +class _ModelTypeStack: + __slots__ = ('_stack',) + + def __init__(self) -> None: + self._stack: list[type] = [] + + @contextmanager + def push(self, type_obj: type) -> Iterator[None]: + self._stack.append(type_obj) + yield + self._stack.pop() + + def get(self) -> type | None: + if self._stack: + return self._stack[-1] + else: + return None diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_generics.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_generics.py new file mode 100644 index 0000000..f9f88a6 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_generics.py @@ -0,0 +1,543 @@ +from __future__ import annotations + +import operator +import sys +import types +import typing +from collections import ChainMap +from collections.abc import Iterator, Mapping +from contextlib import contextmanager +from contextvars import ContextVar +from functools import reduce +from itertools import zip_longest +from types import prepare_class +from typing import TYPE_CHECKING, Annotated, Any, TypedDict, TypeVar, cast +from weakref import WeakValueDictionary + +import typing_extensions +from typing_inspection import typing_objects +from typing_inspection.introspection import is_union_origin + +from . import _typing_extra +from ._core_utils import get_type_ref +from ._forward_ref import PydanticRecursiveRef +from ._utils import all_identical, is_model_class + +if TYPE_CHECKING: + from ..main import BaseModel + +GenericTypesCacheKey = tuple[Any, Any, tuple[Any, ...]] + +# Note: We want to remove LimitedDict, but to do this, we'd need to improve the handling of generics caching. +# Right now, to handle recursive generics, we some types must remain cached for brief periods without references. +# By chaining the WeakValuesDict with a LimitedDict, we have a way to retain caching for all types with references, +# while also retaining a limited number of types even without references. This is generally enough to build +# specific recursive generic models without losing required items out of the cache. + +KT = TypeVar('KT') +VT = TypeVar('VT') +_LIMITED_DICT_SIZE = 100 + + +class LimitedDict(dict[KT, VT]): + def __init__(self, size_limit: int = _LIMITED_DICT_SIZE) -> None: + self.size_limit = size_limit + super().__init__() + + def __setitem__(self, key: KT, value: VT, /) -> None: + super().__setitem__(key, value) + if len(self) > self.size_limit: + excess = len(self) - self.size_limit + self.size_limit // 10 + to_remove = list(self.keys())[:excess] + for k in to_remove: + del self[k] + + +# weak dictionaries allow the dynamically created parametrized versions of generic models to get collected +# once they are no longer referenced by the caller. +GenericTypesCache = WeakValueDictionary[GenericTypesCacheKey, 'type[BaseModel]'] + +if TYPE_CHECKING: + + class DeepChainMap(ChainMap[KT, VT]): # type: ignore + ... + +else: + + class DeepChainMap(ChainMap): + """Variant of ChainMap that allows direct updates to inner scopes. + + Taken from https://docs.python.org/3/library/collections.html#collections.ChainMap, + with some light modifications for this use case. + """ + + def clear(self) -> None: + for mapping in self.maps: + mapping.clear() + + def __setitem__(self, key: KT, value: VT) -> None: + for mapping in self.maps: + mapping[key] = value + + def __delitem__(self, key: KT) -> None: + hit = False + for mapping in self.maps: + if key in mapping: + del mapping[key] + hit = True + if not hit: + raise KeyError(key) + + +# Despite the fact that LimitedDict _seems_ no longer necessary, I'm very nervous to actually remove it +# and discover later on that we need to re-add all this infrastructure... +# _GENERIC_TYPES_CACHE = DeepChainMap(GenericTypesCache(), LimitedDict()) + +_GENERIC_TYPES_CACHE: ContextVar[GenericTypesCache | None] = ContextVar('_GENERIC_TYPES_CACHE', default=None) + + +class PydanticGenericMetadata(TypedDict): + origin: type[BaseModel] | None # analogous to typing._GenericAlias.__origin__ + args: tuple[Any, ...] # analogous to typing._GenericAlias.__args__ + parameters: tuple[TypeVar, ...] # analogous to typing.Generic.__parameters__ + + +def create_generic_submodel( + model_name: str, origin: type[BaseModel], args: tuple[Any, ...], params: tuple[Any, ...] +) -> type[BaseModel]: + """Dynamically create a submodel of a provided (generic) BaseModel. + + This is used when producing concrete parametrizations of generic models. This function + only *creates* the new subclass; the schema/validators/serialization must be updated to + reflect a concrete parametrization elsewhere. + + Args: + model_name: The name of the newly created model. + origin: The base class for the new model to inherit from. + args: A tuple of generic metadata arguments. + params: A tuple of generic metadata parameters. + + Returns: + The created submodel. + """ + namespace: dict[str, Any] = {'__module__': origin.__module__} + bases = (origin,) + meta, ns, kwds = prepare_class(model_name, bases) + namespace.update(ns) + created_model = meta( + model_name, + bases, + namespace, + __pydantic_generic_metadata__={ + 'origin': origin, + 'args': args, + 'parameters': params, + }, + __pydantic_reset_parent_namespace__=False, + **kwds, + ) + + model_module, called_globally = _get_caller_frame_info(depth=3) + if called_globally: # create global reference and therefore allow pickling + object_by_reference = None + reference_name = model_name + reference_module_globals = sys.modules[created_model.__module__].__dict__ + while object_by_reference is not created_model: + object_by_reference = reference_module_globals.setdefault(reference_name, created_model) + reference_name += '_' + + return created_model + + +def _get_caller_frame_info(depth: int = 2) -> tuple[str | None, bool]: + """Used inside a function to check whether it was called globally. + + Args: + depth: The depth to get the frame. + + Returns: + A tuple contains `module_name` and `called_globally`. + + Raises: + RuntimeError: If the function is not called inside a function. + """ + try: + previous_caller_frame = sys._getframe(depth) + except ValueError as e: + raise RuntimeError('This function must be used inside another function') from e + except AttributeError: # sys module does not have _getframe function, so there's nothing we can do about it + return None, False + frame_globals = previous_caller_frame.f_globals + return frame_globals.get('__name__'), previous_caller_frame.f_locals is frame_globals + + +DictValues: type[Any] = {}.values().__class__ + + +def iter_contained_typevars(v: Any) -> Iterator[TypeVar]: + """Recursively iterate through all subtypes and type args of `v` and yield any typevars that are found. + + This is inspired as an alternative to directly accessing the `__parameters__` attribute of a GenericAlias, + since __parameters__ of (nested) generic BaseModel subclasses won't show up in that list. + """ + if isinstance(v, TypeVar): + yield v + elif is_model_class(v): + yield from v.__pydantic_generic_metadata__['parameters'] + elif isinstance(v, (DictValues, list)): + for var in v: + yield from iter_contained_typevars(var) + else: + args = get_args(v) + for arg in args: + yield from iter_contained_typevars(arg) + + +def get_args(v: Any) -> Any: + pydantic_generic_metadata: PydanticGenericMetadata | None = getattr(v, '__pydantic_generic_metadata__', None) + if pydantic_generic_metadata: + return pydantic_generic_metadata.get('args') + return typing_extensions.get_args(v) + + +def get_origin(v: Any) -> Any: + pydantic_generic_metadata: PydanticGenericMetadata | None = getattr(v, '__pydantic_generic_metadata__', None) + if pydantic_generic_metadata: + return pydantic_generic_metadata.get('origin') + return typing_extensions.get_origin(v) + + +def get_standard_typevars_map(cls: Any) -> dict[TypeVar, Any] | None: + """Package a generic type's typevars and parametrization (if present) into a dictionary compatible with the + `replace_types` function. Specifically, this works with standard typing generics and typing._GenericAlias. + """ + origin = get_origin(cls) + if origin is None: + return None + if not hasattr(origin, '__parameters__'): + return None + + # In this case, we know that cls is a _GenericAlias, and origin is the generic type + # So it is safe to access cls.__args__ and origin.__parameters__ + args: tuple[Any, ...] = cls.__args__ # type: ignore + parameters: tuple[TypeVar, ...] = origin.__parameters__ + return dict(zip(parameters, args)) + + +def get_model_typevars_map(cls: type[BaseModel]) -> dict[TypeVar, Any]: + """Package a generic BaseModel's typevars and concrete parametrization (if present) into a dictionary compatible + with the `replace_types` function. + + Since BaseModel.__class_getitem__ does not produce a typing._GenericAlias, and the BaseModel generic info is + stored in the __pydantic_generic_metadata__ attribute, we need special handling here. + """ + # TODO: This could be unified with `get_standard_typevars_map` if we stored the generic metadata + # in the __origin__, __args__, and __parameters__ attributes of the model. + generic_metadata = cls.__pydantic_generic_metadata__ + origin = generic_metadata['origin'] + args = generic_metadata['args'] + if not args: + # No need to go into `iter_contained_typevars`: + return {} + return dict(zip(iter_contained_typevars(origin), args)) + + +def replace_types(type_: Any, type_map: Mapping[TypeVar, Any] | None) -> Any: + """Return type with all occurrences of `type_map` keys recursively replaced with their values. + + Args: + type_: The class or generic alias. + type_map: Mapping from `TypeVar` instance to concrete types. + + Returns: + A new type representing the basic structure of `type_` with all + `typevar_map` keys recursively replaced. + + Example: + ```python + from typing import Union + + from pydantic._internal._generics import replace_types + + replace_types(tuple[str, Union[list[str], float]], {str: int}) + #> tuple[int, Union[list[int], float]] + ``` + """ + if not type_map: + return type_ + + type_args = get_args(type_) + origin_type = get_origin(type_) + + if typing_objects.is_annotated(origin_type): + annotated_type, *annotations = type_args + annotated_type = replace_types(annotated_type, type_map) + # TODO remove parentheses when we drop support for Python 3.10: + return Annotated[(annotated_type, *annotations)] + + # Having type args is a good indicator that this is a typing special form + # instance or a generic alias of some sort. + if type_args: + resolved_type_args = tuple(replace_types(arg, type_map) for arg in type_args) + if all_identical(type_args, resolved_type_args): + # If all arguments are the same, there is no need to modify the + # type or create a new object at all + return type_ + + if ( + origin_type is not None + and isinstance(type_, _typing_extra.typing_base) + and not isinstance(origin_type, _typing_extra.typing_base) + and getattr(type_, '_name', None) is not None + ): + # In python < 3.9 generic aliases don't exist so any of these like `list`, + # `type` or `collections.abc.Callable` need to be translated. + # See: https://www.python.org/dev/peps/pep-0585 + origin_type = getattr(typing, type_._name) + assert origin_type is not None + + if is_union_origin(origin_type): + if any(typing_objects.is_any(arg) for arg in resolved_type_args): + # `Any | T` ~ `Any`: + resolved_type_args = (Any,) + # `Never | T` ~ `T`: + resolved_type_args = tuple( + arg + for arg in resolved_type_args + if not (typing_objects.is_noreturn(arg) or typing_objects.is_never(arg)) + ) + + # PEP-604 syntax (Ex.: list | str) is represented with a types.UnionType object that does not have __getitem__. + # We also cannot use isinstance() since we have to compare types. + if sys.version_info >= (3, 10) and origin_type is types.UnionType: + return reduce(operator.or_, resolved_type_args) + # NotRequired[T] and Required[T] don't support tuple type resolved_type_args, hence the condition below + return origin_type[resolved_type_args[0] if len(resolved_type_args) == 1 else resolved_type_args] + + # We handle pydantic generic models separately as they don't have the same + # semantics as "typing" classes or generic aliases + + if not origin_type and is_model_class(type_): + parameters = type_.__pydantic_generic_metadata__['parameters'] + if not parameters: + return type_ + resolved_type_args = tuple(replace_types(t, type_map) for t in parameters) + if all_identical(parameters, resolved_type_args): + return type_ + return type_[resolved_type_args] + + # Handle special case for typehints that can have lists as arguments. + # `typing.Callable[[int, str], int]` is an example for this. + if isinstance(type_, list): + resolved_list = [replace_types(element, type_map) for element in type_] + if all_identical(type_, resolved_list): + return type_ + return resolved_list + + # If all else fails, we try to resolve the type directly and otherwise just + # return the input with no modifications. + return type_map.get(type_, type_) + + +def map_generic_model_arguments(cls: type[BaseModel], args: tuple[Any, ...]) -> dict[TypeVar, Any]: + """Return a mapping between the parameters of a generic model and the provided arguments during parameterization. + + Raises: + TypeError: If the number of arguments does not match the parameters (i.e. if providing too few or too many arguments). + + Example: + ```python {test="skip" lint="skip"} + class Model[T, U, V = int](BaseModel): ... + + map_generic_model_arguments(Model, (str, bytes)) + #> {T: str, U: bytes, V: int} + + map_generic_model_arguments(Model, (str,)) + #> TypeError: Too few arguments for ; actual 1, expected at least 2 + + map_generic_model_arguments(Model, (str, bytes, int, complex)) + #> TypeError: Too many arguments for ; actual 4, expected 3 + ``` + + Note: + This function is analogous to the private `typing._check_generic_specialization` function. + """ + parameters = cls.__pydantic_generic_metadata__['parameters'] + expected_len = len(parameters) + typevars_map: dict[TypeVar, Any] = {} + + _missing = object() + for parameter, argument in zip_longest(parameters, args, fillvalue=_missing): + if parameter is _missing: + raise TypeError(f'Too many arguments for {cls}; actual {len(args)}, expected {expected_len}') + + if argument is _missing: + param = cast(TypeVar, parameter) + try: + has_default = param.has_default() # pyright: ignore[reportAttributeAccessIssue] + except AttributeError: + # Happens if using `typing.TypeVar` (and not `typing_extensions`) on Python < 3.13. + has_default = False + if has_default: + # The default might refer to other type parameters. For an example, see: + # https://typing.python.org/en/latest/spec/generics.html#type-parameters-as-parameters-to-generics + typevars_map[param] = replace_types(param.__default__, typevars_map) # pyright: ignore[reportAttributeAccessIssue] + else: + expected_len -= sum(hasattr(p, 'has_default') and p.has_default() for p in parameters) # pyright: ignore[reportAttributeAccessIssue] + raise TypeError(f'Too few arguments for {cls}; actual {len(args)}, expected at least {expected_len}') + else: + param = cast(TypeVar, parameter) + typevars_map[param] = argument + + return typevars_map + + +_generic_recursion_cache: ContextVar[set[str] | None] = ContextVar('_generic_recursion_cache', default=None) + + +@contextmanager +def generic_recursion_self_type( + origin: type[BaseModel], args: tuple[Any, ...] +) -> Iterator[PydanticRecursiveRef | None]: + """This contextmanager should be placed around the recursive calls used to build a generic type, + and accept as arguments the generic origin type and the type arguments being passed to it. + + If the same origin and arguments are observed twice, it implies that a self-reference placeholder + can be used while building the core schema, and will produce a schema_ref that will be valid in the + final parent schema. + """ + previously_seen_type_refs = _generic_recursion_cache.get() + if previously_seen_type_refs is None: + previously_seen_type_refs = set() + token = _generic_recursion_cache.set(previously_seen_type_refs) + else: + token = None + + try: + type_ref = get_type_ref(origin, args_override=args) + if type_ref in previously_seen_type_refs: + self_type = PydanticRecursiveRef(type_ref=type_ref) + yield self_type + else: + previously_seen_type_refs.add(type_ref) + yield + previously_seen_type_refs.remove(type_ref) + finally: + if token: + _generic_recursion_cache.reset(token) + + +def recursively_defined_type_refs() -> set[str]: + visited = _generic_recursion_cache.get() + if not visited: + return set() # not in a generic recursion, so there are no types + + return visited.copy() # don't allow modifications + + +def get_cached_generic_type_early(parent: type[BaseModel], typevar_values: Any) -> type[BaseModel] | None: + """The use of a two-stage cache lookup approach was necessary to have the highest performance possible for + repeated calls to `__class_getitem__` on generic types (which may happen in tighter loops during runtime), + while still ensuring that certain alternative parametrizations ultimately resolve to the same type. + + As a concrete example, this approach was necessary to make Model[List[T]][int] equal to Model[List[int]]. + The approach could be modified to not use two different cache keys at different points, but the + _early_cache_key is optimized to be as quick to compute as possible (for repeated-access speed), and the + _late_cache_key is optimized to be as "correct" as possible, so that two types that will ultimately be the + same after resolving the type arguments will always produce cache hits. + + If we wanted to move to only using a single cache key per type, we would either need to always use the + slower/more computationally intensive logic associated with _late_cache_key, or would need to accept + that Model[List[T]][int] is a different type than Model[List[T]][int]. Because we rely on subclass relationships + during validation, I think it is worthwhile to ensure that types that are functionally equivalent are actually + equal. + """ + generic_types_cache = _GENERIC_TYPES_CACHE.get() + if generic_types_cache is None: + generic_types_cache = GenericTypesCache() + _GENERIC_TYPES_CACHE.set(generic_types_cache) + return generic_types_cache.get(_early_cache_key(parent, typevar_values)) + + +def get_cached_generic_type_late( + parent: type[BaseModel], typevar_values: Any, origin: type[BaseModel], args: tuple[Any, ...] +) -> type[BaseModel] | None: + """See the docstring of `get_cached_generic_type_early` for more information about the two-stage cache lookup.""" + generic_types_cache = _GENERIC_TYPES_CACHE.get() + if ( + generic_types_cache is None + ): # pragma: no cover (early cache is guaranteed to run first and initialize the cache) + generic_types_cache = GenericTypesCache() + _GENERIC_TYPES_CACHE.set(generic_types_cache) + cached = generic_types_cache.get(_late_cache_key(origin, args, typevar_values)) + if cached is not None: + set_cached_generic_type(parent, typevar_values, cached, origin, args) + return cached + + +def set_cached_generic_type( + parent: type[BaseModel], + typevar_values: tuple[Any, ...], + type_: type[BaseModel], + origin: type[BaseModel] | None = None, + args: tuple[Any, ...] | None = None, +) -> None: + """See the docstring of `get_cached_generic_type_early` for more information about why items are cached with + two different keys. + """ + generic_types_cache = _GENERIC_TYPES_CACHE.get() + if ( + generic_types_cache is None + ): # pragma: no cover (cache lookup is guaranteed to run first and initialize the cache) + generic_types_cache = GenericTypesCache() + _GENERIC_TYPES_CACHE.set(generic_types_cache) + generic_types_cache[_early_cache_key(parent, typevar_values)] = type_ + if len(typevar_values) == 1: + generic_types_cache[_early_cache_key(parent, typevar_values[0])] = type_ + if origin and args: + generic_types_cache[_late_cache_key(origin, args, typevar_values)] = type_ + + +def _union_orderings_key(typevar_values: Any) -> Any: + """This is intended to help differentiate between Union types with the same arguments in different order. + + Thanks to caching internal to the `typing` module, it is not possible to distinguish between + List[Union[int, float]] and List[Union[float, int]] (and similarly for other "parent" origins besides List) + because `typing` considers Union[int, float] to be equal to Union[float, int]. + + However, you _can_ distinguish between (top-level) Union[int, float] vs. Union[float, int]. + Because we parse items as the first Union type that is successful, we get slightly more consistent behavior + if we make an effort to distinguish the ordering of items in a union. It would be best if we could _always_ + get the exact-correct order of items in the union, but that would require a change to the `typing` module itself. + (See https://github.com/python/cpython/issues/86483 for reference.) + """ + if isinstance(typevar_values, tuple): + return tuple(_union_orderings_key(value) for value in typevar_values) + elif typing_objects.is_union(typing_extensions.get_origin(typevar_values)): + return get_args(typevar_values) + else: + return () + + +def _early_cache_key(cls: type[BaseModel], typevar_values: Any) -> GenericTypesCacheKey: + """This is intended for minimal computational overhead during lookups of cached types. + + Note that this is overly simplistic, and it's possible that two different cls/typevar_values + inputs would ultimately result in the same type being created in BaseModel.__class_getitem__. + To handle this, we have a fallback _late_cache_key that is checked later if the _early_cache_key + lookup fails, and should result in a cache hit _precisely_ when the inputs to __class_getitem__ + would result in the same type. + """ + return cls, typevar_values, _union_orderings_key(typevar_values) + + +def _late_cache_key(origin: type[BaseModel], args: tuple[Any, ...], typevar_values: Any) -> GenericTypesCacheKey: + """This is intended for use later in the process of creating a new type, when we have more information + about the exact args that will be passed. If it turns out that a different set of inputs to + __class_getitem__ resulted in the same inputs to the generic type creation process, we can still + return the cached type, and update the cache with the _early_cache_key as well. + """ + # The _union_orderings_key is placed at the start here to ensure there cannot be a collision with an + # _early_cache_key, as that function will always produce a BaseModel subclass as the first item in the key, + # whereas this function will always produce a tuple as the first item in the key. + return _union_orderings_key(typevar_values), origin, args diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_git.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_git.py new file mode 100644 index 0000000..96dcda2 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_git.py @@ -0,0 +1,27 @@ +"""Git utilities, adopted from mypy's git utilities (https://github.com/python/mypy/blob/master/mypy/git.py).""" + +from __future__ import annotations + +import subprocess +from pathlib import Path + + +def is_git_repo(dir: Path) -> bool: + """Is the given directory version-controlled with git?""" + return dir.joinpath('.git').exists() + + +def have_git() -> bool: # pragma: no cover + """Can we run the git executable?""" + try: + subprocess.check_output(['git', '--help']) + return True + except subprocess.CalledProcessError: + return False + except OSError: + return False + + +def git_revision(dir: Path) -> str: + """Get the SHA-1 of the HEAD of a git repository.""" + return subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD'], cwd=dir).decode('utf-8').strip() diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_import_utils.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_import_utils.py new file mode 100644 index 0000000..638102f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_import_utils.py @@ -0,0 +1,20 @@ +from functools import cache +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from pydantic import BaseModel + from pydantic.fields import FieldInfo + + +@cache +def import_cached_base_model() -> type['BaseModel']: + from pydantic import BaseModel + + return BaseModel + + +@cache +def import_cached_field_info() -> type['FieldInfo']: + from pydantic.fields import FieldInfo + + return FieldInfo diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_internal_dataclass.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_internal_dataclass.py new file mode 100644 index 0000000..33e152c --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_internal_dataclass.py @@ -0,0 +1,7 @@ +import sys + +# `slots` is available on Python >= 3.10 +if sys.version_info >= (3, 10): + slots_true = {'slots': True} +else: + slots_true = {} diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_known_annotated_metadata.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_known_annotated_metadata.py new file mode 100644 index 0000000..7d61f4a --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_known_annotated_metadata.py @@ -0,0 +1,401 @@ +from __future__ import annotations + +from collections import defaultdict +from collections.abc import Iterable +from copy import copy +from functools import lru_cache, partial +from typing import TYPE_CHECKING, Any + +from pydantic_core import CoreSchema, PydanticCustomError, ValidationError, to_jsonable_python +from pydantic_core import core_schema as cs + +from ._fields import PydanticMetadata +from ._import_utils import import_cached_field_info + +if TYPE_CHECKING: + pass + +STRICT = {'strict'} +FAIL_FAST = {'fail_fast'} +LENGTH_CONSTRAINTS = {'min_length', 'max_length'} +INEQUALITY = {'le', 'ge', 'lt', 'gt'} +NUMERIC_CONSTRAINTS = {'multiple_of', *INEQUALITY} +ALLOW_INF_NAN = {'allow_inf_nan'} + +STR_CONSTRAINTS = { + *LENGTH_CONSTRAINTS, + *STRICT, + 'strip_whitespace', + 'to_lower', + 'to_upper', + 'pattern', + 'coerce_numbers_to_str', +} +BYTES_CONSTRAINTS = {*LENGTH_CONSTRAINTS, *STRICT} + +LIST_CONSTRAINTS = {*LENGTH_CONSTRAINTS, *STRICT, *FAIL_FAST} +TUPLE_CONSTRAINTS = {*LENGTH_CONSTRAINTS, *STRICT, *FAIL_FAST} +SET_CONSTRAINTS = {*LENGTH_CONSTRAINTS, *STRICT, *FAIL_FAST} +DICT_CONSTRAINTS = {*LENGTH_CONSTRAINTS, *STRICT} +GENERATOR_CONSTRAINTS = {*LENGTH_CONSTRAINTS, *STRICT} +SEQUENCE_CONSTRAINTS = {*LENGTH_CONSTRAINTS, *FAIL_FAST} + +FLOAT_CONSTRAINTS = {*NUMERIC_CONSTRAINTS, *ALLOW_INF_NAN, *STRICT} +DECIMAL_CONSTRAINTS = {'max_digits', 'decimal_places', *FLOAT_CONSTRAINTS} +INT_CONSTRAINTS = {*NUMERIC_CONSTRAINTS, *ALLOW_INF_NAN, *STRICT} +BOOL_CONSTRAINTS = STRICT +UUID_CONSTRAINTS = STRICT + +DATE_TIME_CONSTRAINTS = {*NUMERIC_CONSTRAINTS, *STRICT} +TIMEDELTA_CONSTRAINTS = {*NUMERIC_CONSTRAINTS, *STRICT} +TIME_CONSTRAINTS = {*NUMERIC_CONSTRAINTS, *STRICT} +LAX_OR_STRICT_CONSTRAINTS = STRICT +ENUM_CONSTRAINTS = STRICT +COMPLEX_CONSTRAINTS = STRICT + +UNION_CONSTRAINTS = {'union_mode'} +URL_CONSTRAINTS = { + 'max_length', + 'allowed_schemes', + 'host_required', + 'default_host', + 'default_port', + 'default_path', +} + +TEXT_SCHEMA_TYPES = ('str', 'bytes', 'url', 'multi-host-url') +SEQUENCE_SCHEMA_TYPES = ('list', 'tuple', 'set', 'frozenset', 'generator', *TEXT_SCHEMA_TYPES) +NUMERIC_SCHEMA_TYPES = ('float', 'int', 'date', 'time', 'timedelta', 'datetime') + +CONSTRAINTS_TO_ALLOWED_SCHEMAS: dict[str, set[str]] = defaultdict(set) + +constraint_schema_pairings: list[tuple[set[str], tuple[str, ...]]] = [ + (STR_CONSTRAINTS, TEXT_SCHEMA_TYPES), + (BYTES_CONSTRAINTS, ('bytes',)), + (LIST_CONSTRAINTS, ('list',)), + (TUPLE_CONSTRAINTS, ('tuple',)), + (SET_CONSTRAINTS, ('set', 'frozenset')), + (DICT_CONSTRAINTS, ('dict',)), + (GENERATOR_CONSTRAINTS, ('generator',)), + (FLOAT_CONSTRAINTS, ('float',)), + (INT_CONSTRAINTS, ('int',)), + (DATE_TIME_CONSTRAINTS, ('date', 'time', 'datetime', 'timedelta')), + # TODO: this is a bit redundant, we could probably avoid some of these + (STRICT, (*TEXT_SCHEMA_TYPES, *SEQUENCE_SCHEMA_TYPES, *NUMERIC_SCHEMA_TYPES, 'typed-dict', 'model')), + (UNION_CONSTRAINTS, ('union',)), + (URL_CONSTRAINTS, ('url', 'multi-host-url')), + (BOOL_CONSTRAINTS, ('bool',)), + (UUID_CONSTRAINTS, ('uuid',)), + (LAX_OR_STRICT_CONSTRAINTS, ('lax-or-strict',)), + (ENUM_CONSTRAINTS, ('enum',)), + (DECIMAL_CONSTRAINTS, ('decimal',)), + (COMPLEX_CONSTRAINTS, ('complex',)), +] + +for constraints, schemas in constraint_schema_pairings: + for c in constraints: + CONSTRAINTS_TO_ALLOWED_SCHEMAS[c].update(schemas) + + +def as_jsonable_value(v: Any) -> Any: + if type(v) not in (int, str, float, bytes, bool, type(None)): + return to_jsonable_python(v) + return v + + +def expand_grouped_metadata(annotations: Iterable[Any]) -> Iterable[Any]: + """Expand the annotations. + + Args: + annotations: An iterable of annotations. + + Returns: + An iterable of expanded annotations. + + Example: + ```python + from annotated_types import Ge, Len + + from pydantic._internal._known_annotated_metadata import expand_grouped_metadata + + print(list(expand_grouped_metadata([Ge(4), Len(5)]))) + #> [Ge(ge=4), MinLen(min_length=5)] + ``` + """ + import annotated_types as at + + FieldInfo = import_cached_field_info() + + for annotation in annotations: + if isinstance(annotation, at.GroupedMetadata): + yield from annotation + elif isinstance(annotation, FieldInfo): + yield from annotation.metadata + # this is a bit problematic in that it results in duplicate metadata + # all of our "consumers" can handle it, but it is not ideal + # we probably should split up FieldInfo into: + # - annotated types metadata + # - individual metadata known only to Pydantic + annotation = copy(annotation) + annotation.metadata = [] + yield annotation + else: + yield annotation + + +@lru_cache +def _get_at_to_constraint_map() -> dict[type, str]: + """Return a mapping of annotated types to constraints. + + Normally, we would define a mapping like this in the module scope, but we can't do that + because we don't permit module level imports of `annotated_types`, in an attempt to speed up + the import time of `pydantic`. We still only want to have this dictionary defined in one place, + so we use this function to cache the result. + """ + import annotated_types as at + + return { + at.Gt: 'gt', + at.Ge: 'ge', + at.Lt: 'lt', + at.Le: 'le', + at.MultipleOf: 'multiple_of', + at.MinLen: 'min_length', + at.MaxLen: 'max_length', + } + + +def apply_known_metadata(annotation: Any, schema: CoreSchema) -> CoreSchema | None: # noqa: C901 + """Apply `annotation` to `schema` if it is an annotation we know about (Gt, Le, etc.). + Otherwise return `None`. + + This does not handle all known annotations. If / when it does, it can always + return a CoreSchema and return the unmodified schema if the annotation should be ignored. + + Assumes that GroupedMetadata has already been expanded via `expand_grouped_metadata`. + + Args: + annotation: The annotation. + schema: The schema. + + Returns: + An updated schema with annotation if it is an annotation we know about, `None` otherwise. + + Raises: + RuntimeError: If a constraint can't be applied to a specific schema type. + ValueError: If an unknown constraint is encountered. + """ + import annotated_types as at + + from ._validators import NUMERIC_VALIDATOR_LOOKUP, forbid_inf_nan_check + + schema = schema.copy() + schema_update, other_metadata = collect_known_metadata([annotation]) + schema_type = schema['type'] + + chain_schema_constraints: set[str] = { + 'pattern', + 'strip_whitespace', + 'to_lower', + 'to_upper', + 'coerce_numbers_to_str', + } + chain_schema_steps: list[CoreSchema] = [] + + for constraint, value in schema_update.items(): + if constraint not in CONSTRAINTS_TO_ALLOWED_SCHEMAS: + raise ValueError(f'Unknown constraint {constraint}') + allowed_schemas = CONSTRAINTS_TO_ALLOWED_SCHEMAS[constraint] + + # if it becomes necessary to handle more than one constraint + # in this recursive case with function-after or function-wrap, we should refactor + # this is a bit challenging because we sometimes want to apply constraints to the inner schema, + # whereas other times we want to wrap the existing schema with a new one that enforces a new constraint. + if schema_type in {'function-before', 'function-wrap', 'function-after'} and constraint == 'strict': + schema['schema'] = apply_known_metadata(annotation, schema['schema']) # type: ignore # schema is function schema + return schema + + # if we're allowed to apply constraint directly to the schema, like le to int, do that + if schema_type in allowed_schemas: + if constraint == 'union_mode' and schema_type == 'union': + schema['mode'] = value # type: ignore # schema is UnionSchema + else: + schema[constraint] = value + continue + + # else, apply a function after validator to the schema to enforce the corresponding constraint + if constraint in chain_schema_constraints: + + def _apply_constraint_with_incompatibility_info( + value: Any, handler: cs.ValidatorFunctionWrapHandler + ) -> Any: + try: + x = handler(value) + except ValidationError as ve: + # if the error is about the type, it's likely that the constraint is incompatible the type of the field + # for example, the following invalid schema wouldn't be caught during schema build, but rather at this point + # with a cryptic 'string_type' error coming from the string validator, + # that we'd rather express as a constraint incompatibility error (TypeError) + # Annotated[list[int], Field(pattern='abc')] + if 'type' in ve.errors()[0]['type']: + raise TypeError( + f"Unable to apply constraint '{constraint}' to supplied value {value} for schema of type '{schema_type}'" # noqa: B023 + ) + raise ve + return x + + chain_schema_steps.append( + cs.no_info_wrap_validator_function( + _apply_constraint_with_incompatibility_info, cs.str_schema(**{constraint: value}) + ) + ) + elif constraint in NUMERIC_VALIDATOR_LOOKUP: + if constraint in LENGTH_CONSTRAINTS: + inner_schema = schema + while inner_schema['type'] in {'function-before', 'function-wrap', 'function-after'}: + inner_schema = inner_schema['schema'] # type: ignore + inner_schema_type = inner_schema['type'] + if inner_schema_type == 'list' or ( + inner_schema_type == 'json-or-python' and inner_schema['json_schema']['type'] == 'list' # type: ignore + ): + js_constraint_key = 'minItems' if constraint == 'min_length' else 'maxItems' + else: + js_constraint_key = 'minLength' if constraint == 'min_length' else 'maxLength' + else: + js_constraint_key = constraint + + schema = cs.no_info_after_validator_function( + partial(NUMERIC_VALIDATOR_LOOKUP[constraint], **{constraint: value}), schema + ) + metadata = schema.get('metadata', {}) + if (existing_json_schema_updates := metadata.get('pydantic_js_updates')) is not None: + metadata['pydantic_js_updates'] = { + **existing_json_schema_updates, + **{js_constraint_key: as_jsonable_value(value)}, + } + else: + metadata['pydantic_js_updates'] = {js_constraint_key: as_jsonable_value(value)} + schema['metadata'] = metadata + elif constraint == 'allow_inf_nan' and value is False: + schema = cs.no_info_after_validator_function( + forbid_inf_nan_check, + schema, + ) + else: + # It's rare that we'd get here, but it's possible if we add a new constraint and forget to handle it + # Most constraint errors are caught at runtime during attempted application + raise RuntimeError(f"Unable to apply constraint '{constraint}' to schema of type '{schema_type}'") + + for annotation in other_metadata: + if (annotation_type := type(annotation)) in (at_to_constraint_map := _get_at_to_constraint_map()): + constraint = at_to_constraint_map[annotation_type] + validator = NUMERIC_VALIDATOR_LOOKUP.get(constraint) + if validator is None: + raise ValueError(f'Unknown constraint {constraint}') + schema = cs.no_info_after_validator_function( + partial(validator, {constraint: getattr(annotation, constraint)}), schema + ) + continue + elif isinstance(annotation, (at.Predicate, at.Not)): + predicate_name = f'{annotation.func.__qualname__!r} ' if hasattr(annotation.func, '__qualname__') else '' + + # Note: B023 is ignored because even though we iterate over `other_metadata`, it is guaranteed + # to be of length 1. `apply_known_metadata()` is called from `GenerateSchema`, where annotations + # were already expanded via `expand_grouped_metadata()`. Confusing, but this falls into the annotations + # refactor. + if isinstance(annotation, at.Predicate): + + def val_func(v: Any) -> Any: + predicate_satisfied = annotation.func(v) # noqa: B023 + if not predicate_satisfied: + raise PydanticCustomError( + 'predicate_failed', + f'Predicate {predicate_name}failed', # pyright: ignore[reportArgumentType] # noqa: B023 + ) + return v + + else: + + def val_func(v: Any) -> Any: + predicate_satisfied = annotation.func(v) # noqa: B023 + if predicate_satisfied: + raise PydanticCustomError( + 'not_operation_failed', + f'Not of {predicate_name}failed', # pyright: ignore[reportArgumentType] # noqa: B023 + ) + return v + + schema = cs.no_info_after_validator_function(val_func, schema) + else: + # ignore any other unknown metadata + return None + + if chain_schema_steps: + chain_schema_steps = [schema] + chain_schema_steps + return cs.chain_schema(chain_schema_steps) + + return schema + + +def collect_known_metadata(annotations: Iterable[Any]) -> tuple[dict[str, Any], list[Any]]: + """Split `annotations` into known metadata and unknown annotations. + + Args: + annotations: An iterable of annotations. + + Returns: + A tuple contains a dict of known metadata and a list of unknown annotations. + + Example: + ```python + from annotated_types import Gt, Len + + from pydantic._internal._known_annotated_metadata import collect_known_metadata + + print(collect_known_metadata([Gt(1), Len(42), ...])) + #> ({'gt': 1, 'min_length': 42}, [Ellipsis]) + ``` + """ + annotations = expand_grouped_metadata(annotations) + + res: dict[str, Any] = {} + remaining: list[Any] = [] + + for annotation in annotations: + # isinstance(annotation, PydanticMetadata) also covers ._fields:_PydanticGeneralMetadata + if isinstance(annotation, PydanticMetadata): + res.update(annotation.__dict__) + # we don't use dataclasses.asdict because that recursively calls asdict on the field values + elif (annotation_type := type(annotation)) in (at_to_constraint_map := _get_at_to_constraint_map()): + constraint = at_to_constraint_map[annotation_type] + res[constraint] = getattr(annotation, constraint) + elif isinstance(annotation, type) and issubclass(annotation, PydanticMetadata): + # also support PydanticMetadata classes being used without initialisation, + # e.g. `Annotated[int, Strict]` as well as `Annotated[int, Strict()]` + res.update({k: v for k, v in vars(annotation).items() if not k.startswith('_')}) + else: + remaining.append(annotation) + # Nones can sneak in but pydantic-core will reject them + # it'd be nice to clean things up so we don't put in None (we probably don't _need_ to, it was just easier) + # but this is simple enough to kick that can down the road + res = {k: v for k, v in res.items() if v is not None} + return res, remaining + + +def check_metadata(metadata: dict[str, Any], allowed: Iterable[str], source_type: Any) -> None: + """A small utility function to validate that the given metadata can be applied to the target. + More than saving lines of code, this gives us a consistent error message for all of our internal implementations. + + Args: + metadata: A dict of metadata. + allowed: An iterable of allowed metadata. + source_type: The source type. + + Raises: + TypeError: If there is metadatas that can't be applied on source type. + """ + unknown = metadata.keys() - set(allowed) + if unknown: + raise TypeError( + f'The following constraints cannot be applied to {source_type!r}: {", ".join([f"{k!r}" for k in unknown])}' + ) diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_mock_val_ser.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_mock_val_ser.py new file mode 100644 index 0000000..9125ab3 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_mock_val_ser.py @@ -0,0 +1,228 @@ +from __future__ import annotations + +from collections.abc import Iterator, Mapping +from typing import TYPE_CHECKING, Any, Callable, Generic, Literal, TypeVar, Union + +from pydantic_core import CoreSchema, SchemaSerializer, SchemaValidator + +from ..errors import PydanticErrorCodes, PydanticUserError +from ..plugin._schema_validator import PluggableSchemaValidator + +if TYPE_CHECKING: + from ..dataclasses import PydanticDataclass + from ..main import BaseModel + from ..type_adapter import TypeAdapter + + +ValSer = TypeVar('ValSer', bound=Union[SchemaValidator, PluggableSchemaValidator, SchemaSerializer]) +T = TypeVar('T') + + +class MockCoreSchema(Mapping[str, Any]): + """Mocker for `pydantic_core.CoreSchema` which optionally attempts to + rebuild the thing it's mocking when one of its methods is accessed and raises an error if that fails. + """ + + __slots__ = '_error_message', '_code', '_attempt_rebuild', '_built_memo' + + def __init__( + self, + error_message: str, + *, + code: PydanticErrorCodes, + attempt_rebuild: Callable[[], CoreSchema | None] | None = None, + ) -> None: + self._error_message = error_message + self._code: PydanticErrorCodes = code + self._attempt_rebuild = attempt_rebuild + self._built_memo: CoreSchema | None = None + + def __getitem__(self, key: str) -> Any: + return self._get_built().__getitem__(key) + + def __len__(self) -> int: + return self._get_built().__len__() + + def __iter__(self) -> Iterator[str]: + return self._get_built().__iter__() + + def _get_built(self) -> CoreSchema: + if self._built_memo is not None: + return self._built_memo + + if self._attempt_rebuild: + schema = self._attempt_rebuild() + if schema is not None: + self._built_memo = schema + return schema + raise PydanticUserError(self._error_message, code=self._code) + + def rebuild(self) -> CoreSchema | None: + self._built_memo = None + if self._attempt_rebuild: + schema = self._attempt_rebuild() + if schema is not None: + return schema + else: + raise PydanticUserError(self._error_message, code=self._code) + return None + + +class MockValSer(Generic[ValSer]): + """Mocker for `pydantic_core.SchemaValidator` or `pydantic_core.SchemaSerializer` which optionally attempts to + rebuild the thing it's mocking when one of its methods is accessed and raises an error if that fails. + """ + + __slots__ = '_error_message', '_code', '_val_or_ser', '_attempt_rebuild' + + def __init__( + self, + error_message: str, + *, + code: PydanticErrorCodes, + val_or_ser: Literal['validator', 'serializer'], + attempt_rebuild: Callable[[], ValSer | None] | None = None, + ) -> None: + self._error_message = error_message + self._val_or_ser = SchemaValidator if val_or_ser == 'validator' else SchemaSerializer + self._code: PydanticErrorCodes = code + self._attempt_rebuild = attempt_rebuild + + def __getattr__(self, item: str) -> None: + __tracebackhide__ = True + if self._attempt_rebuild: + val_ser = self._attempt_rebuild() + if val_ser is not None: + return getattr(val_ser, item) + + # raise an AttributeError if `item` doesn't exist + getattr(self._val_or_ser, item) + raise PydanticUserError(self._error_message, code=self._code) + + def rebuild(self) -> ValSer | None: + if self._attempt_rebuild: + val_ser = self._attempt_rebuild() + if val_ser is not None: + return val_ser + else: + raise PydanticUserError(self._error_message, code=self._code) + return None + + +def set_type_adapter_mocks(adapter: TypeAdapter) -> None: + """Set `core_schema`, `validator` and `serializer` to mock core types on a type adapter instance. + + Args: + adapter: The type adapter instance to set the mocks on + """ + type_repr = str(adapter._type) + undefined_type_error_message = ( + f'`TypeAdapter[{type_repr}]` is not fully defined; you should define `{type_repr}` and all referenced types,' + f' then call `.rebuild()` on the instance.' + ) + + def attempt_rebuild_fn(attr_fn: Callable[[TypeAdapter], T]) -> Callable[[], T | None]: + def handler() -> T | None: + if adapter.rebuild(raise_errors=False, _parent_namespace_depth=5) is not False: + return attr_fn(adapter) + return None + + return handler + + adapter.core_schema = MockCoreSchema( # pyright: ignore[reportAttributeAccessIssue] + undefined_type_error_message, + code='class-not-fully-defined', + attempt_rebuild=attempt_rebuild_fn(lambda ta: ta.core_schema), + ) + adapter.validator = MockValSer( # pyright: ignore[reportAttributeAccessIssue] + undefined_type_error_message, + code='class-not-fully-defined', + val_or_ser='validator', + attempt_rebuild=attempt_rebuild_fn(lambda ta: ta.validator), + ) + adapter.serializer = MockValSer( # pyright: ignore[reportAttributeAccessIssue] + undefined_type_error_message, + code='class-not-fully-defined', + val_or_ser='serializer', + attempt_rebuild=attempt_rebuild_fn(lambda ta: ta.serializer), + ) + + +def set_model_mocks(cls: type[BaseModel], undefined_name: str = 'all referenced types') -> None: + """Set `__pydantic_core_schema__`, `__pydantic_validator__` and `__pydantic_serializer__` to mock core types on a model. + + Args: + cls: The model class to set the mocks on + undefined_name: Name of the undefined thing, used in error messages + """ + undefined_type_error_message = ( + f'`{cls.__name__}` is not fully defined; you should define {undefined_name},' + f' then call `{cls.__name__}.model_rebuild()`.' + ) + + def attempt_rebuild_fn(attr_fn: Callable[[type[BaseModel]], T]) -> Callable[[], T | None]: + def handler() -> T | None: + if cls.model_rebuild(raise_errors=False, _parent_namespace_depth=5) is not False: + return attr_fn(cls) + return None + + return handler + + cls.__pydantic_core_schema__ = MockCoreSchema( # pyright: ignore[reportAttributeAccessIssue] + undefined_type_error_message, + code='class-not-fully-defined', + attempt_rebuild=attempt_rebuild_fn(lambda c: c.__pydantic_core_schema__), + ) + cls.__pydantic_validator__ = MockValSer( # pyright: ignore[reportAttributeAccessIssue] + undefined_type_error_message, + code='class-not-fully-defined', + val_or_ser='validator', + attempt_rebuild=attempt_rebuild_fn(lambda c: c.__pydantic_validator__), + ) + cls.__pydantic_serializer__ = MockValSer( # pyright: ignore[reportAttributeAccessIssue] + undefined_type_error_message, + code='class-not-fully-defined', + val_or_ser='serializer', + attempt_rebuild=attempt_rebuild_fn(lambda c: c.__pydantic_serializer__), + ) + + +def set_dataclass_mocks(cls: type[PydanticDataclass], undefined_name: str = 'all referenced types') -> None: + """Set `__pydantic_validator__` and `__pydantic_serializer__` to `MockValSer`s on a dataclass. + + Args: + cls: The model class to set the mocks on + undefined_name: Name of the undefined thing, used in error messages + """ + from ..dataclasses import rebuild_dataclass + + undefined_type_error_message = ( + f'`{cls.__name__}` is not fully defined; you should define {undefined_name},' + f' then call `pydantic.dataclasses.rebuild_dataclass({cls.__name__})`.' + ) + + def attempt_rebuild_fn(attr_fn: Callable[[type[PydanticDataclass]], T]) -> Callable[[], T | None]: + def handler() -> T | None: + if rebuild_dataclass(cls, raise_errors=False, _parent_namespace_depth=5) is not False: + return attr_fn(cls) + return None + + return handler + + cls.__pydantic_core_schema__ = MockCoreSchema( # pyright: ignore[reportAttributeAccessIssue] + undefined_type_error_message, + code='class-not-fully-defined', + attempt_rebuild=attempt_rebuild_fn(lambda c: c.__pydantic_core_schema__), + ) + cls.__pydantic_validator__ = MockValSer( # pyright: ignore[reportAttributeAccessIssue] + undefined_type_error_message, + code='class-not-fully-defined', + val_or_ser='validator', + attempt_rebuild=attempt_rebuild_fn(lambda c: c.__pydantic_validator__), + ) + cls.__pydantic_serializer__ = MockValSer( # pyright: ignore[reportAttributeAccessIssue] + undefined_type_error_message, + code='class-not-fully-defined', + val_or_ser='serializer', + attempt_rebuild=attempt_rebuild_fn(lambda c: c.__pydantic_serializer__), + ) diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_model_construction.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_model_construction.py new file mode 100644 index 0000000..4fe223c --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_model_construction.py @@ -0,0 +1,848 @@ +"""Private logic for creating models.""" + +from __future__ import annotations as _annotations + +import operator +import sys +import typing +import warnings +import weakref +from abc import ABCMeta +from functools import cache, partial, wraps +from types import FunctionType +from typing import TYPE_CHECKING, Any, Callable, Generic, Literal, NoReturn, TypeVar, cast + +from pydantic_core import PydanticUndefined, SchemaSerializer +from typing_extensions import TypeAliasType, dataclass_transform, deprecated, get_args, get_origin +from typing_inspection import typing_objects + +from ..errors import PydanticUndefinedAnnotation, PydanticUserError +from ..plugin._schema_validator import create_schema_validator +from ..warnings import GenericBeforeBaseModelWarning, PydanticDeprecatedSince20 +from ._config import ConfigWrapper +from ._decorators import DecoratorInfos, PydanticDescriptorProxy, get_attribute_from_bases, unwrap_wrapped_function +from ._fields import collect_model_fields, is_valid_field_name, is_valid_privateattr_name, rebuild_model_fields +from ._generate_schema import GenerateSchema, InvalidSchemaError +from ._generics import PydanticGenericMetadata, get_model_typevars_map +from ._import_utils import import_cached_base_model, import_cached_field_info +from ._mock_val_ser import set_model_mocks +from ._namespace_utils import NsResolver +from ._signature import generate_pydantic_signature +from ._typing_extra import ( + _make_forward_ref, + eval_type_backport, + is_classvar_annotation, + parent_frame_namespace, +) +from ._utils import LazyClassAttribute, SafeGetItemProxy + +if TYPE_CHECKING: + from ..fields import Field as PydanticModelField + from ..fields import FieldInfo, ModelPrivateAttr + from ..fields import PrivateAttr as PydanticModelPrivateAttr + from ..main import BaseModel +else: + PydanticModelField = object() + PydanticModelPrivateAttr = object() + +object_setattr = object.__setattr__ + + +class _ModelNamespaceDict(dict): + """A dictionary subclass that intercepts attribute setting on model classes and + warns about overriding of decorators. + """ + + def __setitem__(self, k: str, v: object) -> None: + existing: Any = self.get(k, None) + if existing and v is not existing and isinstance(existing, PydanticDescriptorProxy): + warnings.warn( + f'`{k}` overrides an existing Pydantic `{existing.decorator_info.decorator_repr}` decorator', + stacklevel=2, + ) + + return super().__setitem__(k, v) + + +def NoInitField( + *, + init: Literal[False] = False, +) -> Any: + """Only for typing purposes. Used as default value of `__pydantic_fields_set__`, + `__pydantic_extra__`, `__pydantic_private__`, so they could be ignored when + synthesizing the `__init__` signature. + """ + + +# For ModelMetaclass.register(): +_T = TypeVar('_T') + + +@dataclass_transform(kw_only_default=True, field_specifiers=(PydanticModelField, PydanticModelPrivateAttr, NoInitField)) +class ModelMetaclass(ABCMeta): + def __new__( + mcs, + cls_name: str, + bases: tuple[type[Any], ...], + namespace: dict[str, Any], + __pydantic_generic_metadata__: PydanticGenericMetadata | None = None, + __pydantic_reset_parent_namespace__: bool = True, + _create_model_module: str | None = None, + **kwargs: Any, + ) -> type: + """Metaclass for creating Pydantic models. + + Args: + cls_name: The name of the class to be created. + bases: The base classes of the class to be created. + namespace: The attribute dictionary of the class to be created. + __pydantic_generic_metadata__: Metadata for generic models. + __pydantic_reset_parent_namespace__: Reset parent namespace. + _create_model_module: The module of the class to be created, if created by `create_model`. + **kwargs: Catch-all for any other keyword arguments. + + Returns: + The new class created by the metaclass. + """ + # Note `ModelMetaclass` refers to `BaseModel`, but is also used to *create* `BaseModel`, so we rely on the fact + # that `BaseModel` itself won't have any bases, but any subclass of it will, to determine whether the `__new__` + # call we're in the middle of is for the `BaseModel` class. + if bases: + raw_annotations: dict[str, Any] + if sys.version_info >= (3, 14): + if ( + '__annotations__' in namespace + ): # `from __future__ import annotations` was used in the model's module + raw_annotations = namespace['__annotations__'] + else: + # See https://docs.python.org/3.14/library/annotationlib.html#using-annotations-in-a-metaclass: + from annotationlib import Format, call_annotate_function, get_annotate_from_class_namespace + + if annotate := get_annotate_from_class_namespace(namespace): + raw_annotations = call_annotate_function(annotate, format=Format.FORWARDREF) + else: + raw_annotations = {} + else: + raw_annotations = namespace.get('__annotations__', {}) + + base_field_names, class_vars, base_private_attributes = mcs._collect_bases_data(bases) + + config_wrapper = ConfigWrapper.for_model(bases, namespace, raw_annotations, kwargs) + namespace['model_config'] = config_wrapper.config_dict + private_attributes = inspect_namespace( + namespace, raw_annotations, config_wrapper.ignored_types, class_vars, base_field_names + ) + if private_attributes or base_private_attributes: + original_model_post_init = get_model_post_init(namespace, bases) + if original_model_post_init is not None: + # if there are private_attributes and a model_post_init function, we handle both + + @wraps(original_model_post_init) + def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None: + """We need to both initialize private attributes and call the user-defined model_post_init + method. + """ + init_private_attributes(self, context) + original_model_post_init(self, context) + + namespace['model_post_init'] = wrapped_model_post_init + else: + namespace['model_post_init'] = init_private_attributes + + namespace['__class_vars__'] = class_vars + namespace['__private_attributes__'] = {**base_private_attributes, **private_attributes} + + cls = cast('type[BaseModel]', super().__new__(mcs, cls_name, bases, namespace, **kwargs)) + BaseModel_ = import_cached_base_model() + + mro = cls.__mro__ + if Generic in mro and mro.index(Generic) < mro.index(BaseModel_): + warnings.warn( + GenericBeforeBaseModelWarning( + 'Classes should inherit from `BaseModel` before generic classes (e.g. `typing.Generic[T]`) ' + 'for pydantic generics to work properly.' + ), + stacklevel=2, + ) + + cls.__pydantic_custom_init__ = not getattr(cls.__init__, '__pydantic_base_init__', False) + cls.__pydantic_post_init__ = ( + None if cls.model_post_init is BaseModel_.model_post_init else 'model_post_init' + ) + + cls.__pydantic_setattr_handlers__ = {} + + cls.__pydantic_decorators__ = DecoratorInfos.build(cls) + cls.__pydantic_decorators__.update_from_config(config_wrapper) + + # Use the getattr below to grab the __parameters__ from the `typing.Generic` parent class + if __pydantic_generic_metadata__: + cls.__pydantic_generic_metadata__ = __pydantic_generic_metadata__ + else: + parent_parameters = getattr(cls, '__pydantic_generic_metadata__', {}).get('parameters', ()) + parameters = getattr(cls, '__parameters__', None) or parent_parameters + if parameters and parent_parameters and not all(x in parameters for x in parent_parameters): + from ..root_model import RootModelRootType + + missing_parameters = tuple(x for x in parameters if x not in parent_parameters) + if RootModelRootType in parent_parameters and RootModelRootType not in parameters: + # This is a special case where the user has subclassed `RootModel`, but has not parametrized + # RootModel with the generic type identifiers being used. Ex: + # class MyModel(RootModel, Generic[T]): + # root: T + # Should instead just be: + # class MyModel(RootModel[T]): + # root: T + parameters_str = ', '.join([x.__name__ for x in missing_parameters]) + error_message = ( + f'{cls.__name__} is a subclass of `RootModel`, but does not include the generic type identifier(s) ' + f'{parameters_str} in its parameters. ' + f'You should parametrize RootModel directly, e.g., `class {cls.__name__}(RootModel[{parameters_str}]): ...`.' + ) + else: + combined_parameters = parent_parameters + missing_parameters + parameters_str = ', '.join([str(x) for x in combined_parameters]) + generic_type_label = f'typing.Generic[{parameters_str}]' + error_message = ( + f'All parameters must be present on typing.Generic;' + f' you should inherit from {generic_type_label}.' + ) + if Generic not in bases: # pragma: no cover + # We raise an error here not because it is desirable, but because some cases are mishandled. + # It would be nice to remove this error and still have things behave as expected, it's just + # challenging because we are using a custom `__class_getitem__` to parametrize generic models, + # and not returning a typing._GenericAlias from it. + bases_str = ', '.join([x.__name__ for x in bases] + [generic_type_label]) + error_message += ( + f' Note: `typing.Generic` must go last: `class {cls.__name__}({bases_str}): ...`)' + ) + raise TypeError(error_message) + + cls.__pydantic_generic_metadata__ = { + 'origin': None, + 'args': (), + 'parameters': parameters, + } + + cls.__pydantic_complete__ = False # Ensure this specific class gets completed + + # preserve `__set_name__` protocol defined in https://peps.python.org/pep-0487 + # for attributes not in `new_namespace` (e.g. private attributes) + for name, obj in private_attributes.items(): + obj.__set_name__(cls, name) + + if __pydantic_reset_parent_namespace__: + cls.__pydantic_parent_namespace__ = build_lenient_weakvaluedict(parent_frame_namespace()) + parent_namespace: dict[str, Any] | None = getattr(cls, '__pydantic_parent_namespace__', None) + if isinstance(parent_namespace, dict): + parent_namespace = unpack_lenient_weakvaluedict(parent_namespace) + + ns_resolver = NsResolver(parent_namespace=parent_namespace) + + set_model_fields(cls, config_wrapper=config_wrapper, ns_resolver=ns_resolver) + + # This is also set in `complete_model_class()`, after schema gen because they are recreated. + # We set them here as well for backwards compatibility: + cls.__pydantic_computed_fields__ = { + k: v.info for k, v in cls.__pydantic_decorators__.computed_fields.items() + } + + if config_wrapper.defer_build: + set_model_mocks(cls) + else: + # Any operation that requires accessing the field infos instances should be put inside + # `complete_model_class()`: + complete_model_class( + cls, + config_wrapper, + ns_resolver, + raise_errors=False, + create_model_module=_create_model_module, + ) + + if config_wrapper.frozen and '__hash__' not in namespace: + set_default_hash_func(cls, bases) + + # using super(cls, cls) on the next line ensures we only call the parent class's __pydantic_init_subclass__ + # I believe the `type: ignore` is only necessary because mypy doesn't realize that this code branch is + # only hit for _proper_ subclasses of BaseModel + super(cls, cls).__pydantic_init_subclass__(**kwargs) # type: ignore[misc] + return cls + else: + # These are instance variables, but have been assigned to `NoInitField` to trick the type checker. + for instance_slot in '__pydantic_fields_set__', '__pydantic_extra__', '__pydantic_private__': + namespace.pop( + instance_slot, + None, # In case the metaclass is used with a class other than `BaseModel`. + ) + namespace.get('__annotations__', {}).clear() + return super().__new__(mcs, cls_name, bases, namespace, **kwargs) + + if not TYPE_CHECKING: # pragma: no branch + # We put `__getattr__` in a non-TYPE_CHECKING block because otherwise, mypy allows arbitrary attribute access + + def __getattr__(self, item: str) -> Any: + """This is necessary to keep attribute access working for class attribute access.""" + private_attributes = self.__dict__.get('__private_attributes__') + if private_attributes and item in private_attributes: + return private_attributes[item] + raise AttributeError(item) + + @classmethod + def __prepare__(cls, *args: Any, **kwargs: Any) -> dict[str, object]: + return _ModelNamespaceDict() + + # Due to performance and memory issues, in the ABCMeta.__subclasscheck__ implementation, we don't support + # registered virtual subclasses. See https://github.com/python/cpython/issues/92810#issuecomment-2762454345. + # This may change once the CPython gets fixed (possibly in 3.15), in which case we should conditionally + # define `register()`. + def register(self, subclass: type[_T]) -> type[_T]: + warnings.warn( + f"For performance reasons, virtual subclasses registered using '{self.__qualname__}.register()' " + "are not supported in 'isinstance()' and 'issubclass()' checks.", + stacklevel=2, + ) + return super().register(subclass) + + __instancecheck__ = type.__instancecheck__ # pyright: ignore[reportAssignmentType] + __subclasscheck__ = type.__subclasscheck__ # pyright: ignore[reportAssignmentType] + + @staticmethod + def _collect_bases_data(bases: tuple[type[Any], ...]) -> tuple[set[str], set[str], dict[str, ModelPrivateAttr]]: + BaseModel = import_cached_base_model() + + field_names: set[str] = set() + class_vars: set[str] = set() + private_attributes: dict[str, ModelPrivateAttr] = {} + for base in bases: + if issubclass(base, BaseModel) and base is not BaseModel: + # model_fields might not be defined yet in the case of generics, so we use getattr here: + field_names.update(getattr(base, '__pydantic_fields__', {}).keys()) + class_vars.update(base.__class_vars__) + private_attributes.update(base.__private_attributes__) + return field_names, class_vars, private_attributes + + @property + @deprecated( + 'The `__fields__` attribute is deprecated, use the `model_fields` class property instead.', category=None + ) + def __fields__(self) -> dict[str, FieldInfo]: + warnings.warn( + 'The `__fields__` attribute is deprecated, use the `model_fields` class property instead.', + PydanticDeprecatedSince20, + stacklevel=2, + ) + return getattr(self, '__pydantic_fields__', {}) + + @property + def __pydantic_fields_complete__(self) -> bool: + """Whether the fields where successfully collected (i.e. type hints were successfully resolves). + + This is a private attribute, not meant to be used outside Pydantic. + """ + if '__pydantic_fields__' not in self.__dict__: + return False + + field_infos = cast('dict[str, FieldInfo]', self.__pydantic_fields__) # pyright: ignore[reportAttributeAccessIssue] + + return all(field_info._complete for field_info in field_infos.values()) + + def __dir__(self) -> list[str]: + attributes = list(super().__dir__()) + if '__fields__' in attributes: + attributes.remove('__fields__') + return attributes + + +def init_private_attributes(self: BaseModel, context: Any, /) -> None: + """This function is meant to behave like a BaseModel method to initialise private attributes. + + It takes context as an argument since that's what pydantic-core passes when calling it. + + Args: + self: The BaseModel instance. + context: The context. + """ + if getattr(self, '__pydantic_private__', None) is None: + pydantic_private = {} + for name, private_attr in self.__private_attributes__.items(): + default = private_attr.get_default() + if default is not PydanticUndefined: + pydantic_private[name] = default + object_setattr(self, '__pydantic_private__', pydantic_private) + + +def get_model_post_init(namespace: dict[str, Any], bases: tuple[type[Any], ...]) -> Callable[..., Any] | None: + """Get the `model_post_init` method from the namespace or the class bases, or `None` if not defined.""" + if 'model_post_init' in namespace: + return namespace['model_post_init'] + + BaseModel = import_cached_base_model() + + model_post_init = get_attribute_from_bases(bases, 'model_post_init') + if model_post_init is not BaseModel.model_post_init: + return model_post_init + + +def inspect_namespace( # noqa C901 + namespace: dict[str, Any], + raw_annotations: dict[str, Any], + ignored_types: tuple[type[Any], ...], + base_class_vars: set[str], + base_class_fields: set[str], +) -> dict[str, ModelPrivateAttr]: + """Iterate over the namespace and: + * gather private attributes + * check for items which look like fields but are not (e.g. have no annotation) and warn. + + Args: + namespace: The attribute dictionary of the class to be created. + raw_annotations: The (non-evaluated) annotations of the model. + ignored_types: A tuple of ignore types. + base_class_vars: A set of base class class variables. + base_class_fields: A set of base class fields. + + Returns: + A dict contains private attributes info. + + Raises: + TypeError: If there is a `__root__` field in model. + NameError: If private attribute name is invalid. + PydanticUserError: + - If a field does not have a type annotation. + - If a field on base class was overridden by a non-annotated attribute. + """ + from ..fields import ModelPrivateAttr, PrivateAttr + + FieldInfo = import_cached_field_info() + + all_ignored_types = ignored_types + default_ignored_types() + + private_attributes: dict[str, ModelPrivateAttr] = {} + + if '__root__' in raw_annotations or '__root__' in namespace: + raise TypeError("To define root models, use `pydantic.RootModel` rather than a field called '__root__'") + + ignored_names: set[str] = set() + for var_name, value in list(namespace.items()): + if var_name == 'model_config' or var_name == '__pydantic_extra__': + continue + elif ( + isinstance(value, type) + and value.__module__ == namespace['__module__'] + and '__qualname__' in namespace + and value.__qualname__.startswith(f'{namespace["__qualname__"]}.') + ): + # `value` is a nested type defined in this namespace; don't error + continue + elif isinstance(value, all_ignored_types) or value.__class__.__module__ == 'functools': + ignored_names.add(var_name) + continue + elif isinstance(value, ModelPrivateAttr): + if var_name.startswith('__'): + raise NameError( + 'Private attributes must not use dunder names;' + f' use a single underscore prefix instead of {var_name!r}.' + ) + elif is_valid_field_name(var_name): + raise NameError( + 'Private attributes must not use valid field names;' + f' use sunder names, e.g. {"_" + var_name!r} instead of {var_name!r}.' + ) + private_attributes[var_name] = value + del namespace[var_name] + elif isinstance(value, FieldInfo) and not is_valid_field_name(var_name): + suggested_name = var_name.lstrip('_') or 'my_field' # don't suggest '' for all-underscore name + raise NameError( + f'Fields must not use names with leading underscores;' + f' e.g., use {suggested_name!r} instead of {var_name!r}.' + ) + + elif var_name.startswith('__'): + continue + elif is_valid_privateattr_name(var_name): + if var_name not in raw_annotations or not is_classvar_annotation(raw_annotations[var_name]): + private_attributes[var_name] = cast(ModelPrivateAttr, PrivateAttr(default=value)) + del namespace[var_name] + elif var_name in base_class_vars: + continue + elif var_name not in raw_annotations: + if var_name in base_class_fields: + raise PydanticUserError( + f'Field {var_name!r} defined on a base class was overridden by a non-annotated attribute. ' + f'All field definitions, including overrides, require a type annotation.', + code='model-field-overridden', + ) + elif isinstance(value, FieldInfo): + raise PydanticUserError( + f'Field {var_name!r} requires a type annotation', code='model-field-missing-annotation' + ) + else: + raise PydanticUserError( + f'A non-annotated attribute was detected: `{var_name} = {value!r}`. All model fields require a ' + f'type annotation; if `{var_name}` is not meant to be a field, you may be able to resolve this ' + f"error by annotating it as a `ClassVar` or updating `model_config['ignored_types']`.", + code='model-field-missing-annotation', + ) + + for ann_name, ann_type in raw_annotations.items(): + if ( + is_valid_privateattr_name(ann_name) + and ann_name not in private_attributes + and ann_name not in ignored_names + # This condition can be a false negative when `ann_type` is stringified, + # but it is handled in most cases in `set_model_fields`: + and not is_classvar_annotation(ann_type) + and ann_type not in all_ignored_types + and getattr(ann_type, '__module__', None) != 'functools' + ): + if isinstance(ann_type, str): + # Walking up the frames to get the module namespace where the model is defined + # (as the model class wasn't created yet, we unfortunately can't use `cls.__module__`): + frame = sys._getframe(2) + if frame is not None: + try: + ann_type = eval_type_backport( + _make_forward_ref(ann_type, is_argument=False, is_class=True), + globalns=frame.f_globals, + localns=frame.f_locals, + ) + except (NameError, TypeError): + pass + + if typing_objects.is_annotated(get_origin(ann_type)): + _, *metadata = get_args(ann_type) + private_attr = next((v for v in metadata if isinstance(v, ModelPrivateAttr)), None) + if private_attr is not None: + private_attributes[ann_name] = private_attr + continue + private_attributes[ann_name] = PrivateAttr() + + return private_attributes + + +def set_default_hash_func(cls: type[BaseModel], bases: tuple[type[Any], ...]) -> None: + base_hash_func = get_attribute_from_bases(bases, '__hash__') + new_hash_func = make_hash_func(cls) + if base_hash_func in {None, object.__hash__} or getattr(base_hash_func, '__code__', None) == new_hash_func.__code__: + # If `__hash__` is some default, we generate a hash function. + # It will be `None` if not overridden from BaseModel. + # It may be `object.__hash__` if there is another + # parent class earlier in the bases which doesn't override `__hash__` (e.g. `typing.Generic`). + # It may be a value set by `set_default_hash_func` if `cls` is a subclass of another frozen model. + # In the last case we still need a new hash function to account for new `model_fields`. + cls.__hash__ = new_hash_func + + +def make_hash_func(cls: type[BaseModel]) -> Any: + getter = operator.itemgetter(*cls.__pydantic_fields__.keys()) if cls.__pydantic_fields__ else lambda _: 0 + + def hash_func(self: Any) -> int: + try: + return hash(getter(self.__dict__)) + except KeyError: + # In rare cases (such as when using the deprecated copy method), the __dict__ may not contain + # all model fields, which is how we can get here. + # getter(self.__dict__) is much faster than any 'safe' method that accounts for missing keys, + # and wrapping it in a `try` doesn't slow things down much in the common case. + return hash(getter(SafeGetItemProxy(self.__dict__))) + + return hash_func + + +def set_model_fields( + cls: type[BaseModel], + config_wrapper: ConfigWrapper, + ns_resolver: NsResolver | None, +) -> None: + """Collect and set `cls.__pydantic_fields__` and `cls.__class_vars__`. + + Args: + cls: BaseModel or dataclass. + config_wrapper: The config wrapper instance. + ns_resolver: Namespace resolver to use when getting model annotations. + """ + typevars_map = get_model_typevars_map(cls) + fields, class_vars = collect_model_fields(cls, config_wrapper, ns_resolver, typevars_map=typevars_map) + + cls.__pydantic_fields__ = fields + cls.__class_vars__.update(class_vars) + + for k in class_vars: + # Class vars should not be private attributes + # We remove them _here_ and not earlier because we rely on inspecting the class to determine its classvars, + # but private attributes are determined by inspecting the namespace _prior_ to class creation. + # In the case that a classvar with a leading-'_' is defined via a ForwardRef (e.g., when using + # `__future__.annotations`), we want to remove the private attribute which was detected _before_ we knew it + # evaluated to a classvar + + value = cls.__private_attributes__.pop(k, None) + if value is not None and value.default is not PydanticUndefined: + setattr(cls, k, value.default) + + +def complete_model_class( + cls: type[BaseModel], + config_wrapper: ConfigWrapper, + ns_resolver: NsResolver, + *, + raise_errors: bool = True, + call_on_complete_hook: bool = True, + create_model_module: str | None = None, +) -> bool: + """Finish building a model class. + + This logic must be called after class has been created since validation functions must be bound + and `get_type_hints` requires a class object. + + Args: + cls: BaseModel or dataclass. + config_wrapper: The config wrapper instance. + ns_resolver: The namespace resolver instance to use during schema building. + raise_errors: Whether to raise errors. + call_on_complete_hook: Whether to call the `__pydantic_on_complete__` hook. + create_model_module: The module of the class to be created, if created by `create_model`. + + Returns: + `True` if the model is successfully completed, else `False`. + + Raises: + PydanticUndefinedAnnotation: If `PydanticUndefinedAnnotation` occurs in`__get_pydantic_core_schema__` + and `raise_errors=True`. + """ + typevars_map = get_model_typevars_map(cls) + + if not cls.__pydantic_fields_complete__: + # Note: when coming from `ModelMetaclass.__new__()`, this results in fields being built twice. + # We do so a second time here so that we can get the `NameError` for the specific undefined annotation. + # Alternatively, we could let `GenerateSchema()` raise the error, but there are cases where incomplete + # fields are inherited in `collect_model_fields()` and can actually have their annotation resolved in the + # generate schema process. As we want to avoid having `__pydantic_fields_complete__` set to `False` + # when `__pydantic_complete__` is `True`, we rebuild here: + try: + cls.__pydantic_fields__ = rebuild_model_fields( + cls, + config_wrapper=config_wrapper, + ns_resolver=ns_resolver, + typevars_map=typevars_map, + ) + except NameError as e: + exc = PydanticUndefinedAnnotation.from_name_error(e) + set_model_mocks(cls, f'`{exc.name}`') + if raise_errors: + raise exc from e + + if not raise_errors and not cls.__pydantic_fields_complete__: + # No need to continue with schema gen, it is guaranteed to fail + return False + + assert cls.__pydantic_fields_complete__ + + gen_schema = GenerateSchema( + config_wrapper, + ns_resolver, + typevars_map, + ) + + try: + schema = gen_schema.generate_schema(cls) + except PydanticUndefinedAnnotation as e: + if raise_errors: + raise + set_model_mocks(cls, f'`{e.name}`') + return False + + core_config = config_wrapper.core_config(title=cls.__name__) + + try: + schema = gen_schema.clean_schema(schema) + except InvalidSchemaError: + set_model_mocks(cls) + return False + + # This needs to happen *after* model schema generation, as the return type + # of the properties are evaluated and the `ComputedFieldInfo` are recreated: + cls.__pydantic_computed_fields__ = {k: v.info for k, v in cls.__pydantic_decorators__.computed_fields.items()} + + set_deprecated_descriptors(cls) + + cls.__pydantic_core_schema__ = schema + + cls.__pydantic_validator__ = create_schema_validator( + schema, + cls, + create_model_module or cls.__module__, + cls.__qualname__, + 'create_model' if create_model_module else 'BaseModel', + core_config, + config_wrapper.plugin_settings, + ) + cls.__pydantic_serializer__ = SchemaSerializer(schema, core_config) + + # set __signature__ attr only for model class, but not for its instances + # (because instances can define `__call__`, and `inspect.signature` shouldn't + # use the `__signature__` attribute and instead generate from `__call__`). + cls.__signature__ = LazyClassAttribute( + '__signature__', + partial( + generate_pydantic_signature, + init=cls.__init__, + fields=cls.__pydantic_fields__, + validate_by_name=config_wrapper.validate_by_name, + extra=config_wrapper.extra, + ), + ) + + cls.__pydantic_complete__ = True + + if call_on_complete_hook: + cls.__pydantic_on_complete__() + + return True + + +def set_deprecated_descriptors(cls: type[BaseModel]) -> None: + """Set data descriptors on the class for deprecated fields.""" + for field, field_info in cls.__pydantic_fields__.items(): + if (msg := field_info.deprecation_message) is not None: + desc = _DeprecatedFieldDescriptor(msg) + desc.__set_name__(cls, field) + setattr(cls, field, desc) + + for field, computed_field_info in cls.__pydantic_computed_fields__.items(): + if ( + (msg := computed_field_info.deprecation_message) is not None + # Avoid having two warnings emitted: + and not hasattr(unwrap_wrapped_function(computed_field_info.wrapped_property), '__deprecated__') + ): + desc = _DeprecatedFieldDescriptor(msg, computed_field_info.wrapped_property) + desc.__set_name__(cls, field) + setattr(cls, field, desc) + + +class _DeprecatedFieldDescriptor: + """Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field. + + Attributes: + msg: The deprecation message to be emitted. + wrapped_property: The property instance if the deprecated field is a computed field, or `None`. + field_name: The name of the field being deprecated. + """ + + field_name: str + + def __init__(self, msg: str, wrapped_property: property | None = None) -> None: + self.msg = msg + self.wrapped_property = wrapped_property + + def __set_name__(self, cls: type[BaseModel], name: str) -> None: + self.field_name = name + + def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any: + if obj is None: + if self.wrapped_property is not None: + return self.wrapped_property.__get__(None, obj_type) + raise AttributeError(self.field_name) + + warnings.warn(self.msg, DeprecationWarning, stacklevel=2) + + if self.wrapped_property is not None: + return self.wrapped_property.__get__(obj, obj_type) + return obj.__dict__[self.field_name] + + # Defined to make it a data descriptor and take precedence over the instance's dictionary. + # Note that it will not be called when setting a value on a model instance + # as `BaseModel.__setattr__` is defined and takes priority. + def __set__(self, obj: Any, value: Any) -> NoReturn: + raise AttributeError(self.field_name) + + +class _PydanticWeakRef: + """Wrapper for `weakref.ref` that enables `pickle` serialization. + + Cloudpickle fails to serialize `weakref.ref` objects due to an arcane error related + to abstract base classes (`abc.ABC`). This class works around the issue by wrapping + `weakref.ref` instead of subclassing it. + + See https://github.com/pydantic/pydantic/issues/6763 for context. + + Semantics: + - If not pickled, behaves the same as a `weakref.ref`. + - If pickled along with the referenced object, the same `weakref.ref` behavior + will be maintained between them after unpickling. + - If pickled without the referenced object, after unpickling the underlying + reference will be cleared (`__call__` will always return `None`). + """ + + def __init__(self, obj: Any): + if obj is None: + # The object will be `None` upon deserialization if the serialized weakref + # had lost its underlying object. + self._wr = None + else: + self._wr = weakref.ref(obj) + + def __call__(self) -> Any: + if self._wr is None: + return None + else: + return self._wr() + + def __reduce__(self) -> tuple[Callable, tuple[weakref.ReferenceType | None]]: + return _PydanticWeakRef, (self(),) + + +def build_lenient_weakvaluedict(d: dict[str, Any] | None) -> dict[str, Any] | None: + """Takes an input dictionary, and produces a new value that (invertibly) replaces the values with weakrefs. + + We can't just use a WeakValueDictionary because many types (including int, str, etc.) can't be stored as values + in a WeakValueDictionary. + + The `unpack_lenient_weakvaluedict` function can be used to reverse this operation. + """ + if d is None: + return None + result = {} + for k, v in d.items(): + try: + proxy = _PydanticWeakRef(v) + except TypeError: + proxy = v + result[k] = proxy + return result + + +def unpack_lenient_weakvaluedict(d: dict[str, Any] | None) -> dict[str, Any] | None: + """Inverts the transform performed by `build_lenient_weakvaluedict`.""" + if d is None: + return None + + result = {} + for k, v in d.items(): + if isinstance(v, _PydanticWeakRef): + v = v() + if v is not None: + result[k] = v + else: + result[k] = v + return result + + +@cache +def default_ignored_types() -> tuple[type[Any], ...]: + from ..fields import ComputedFieldInfo + + ignored_types = [ + FunctionType, + property, + classmethod, + staticmethod, + PydanticDescriptorProxy, + ComputedFieldInfo, + TypeAliasType, # from `typing_extensions` + ] + + if sys.version_info >= (3, 12): + ignored_types.append(typing.TypeAliasType) + + return tuple(ignored_types) diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_namespace_utils.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_namespace_utils.py new file mode 100644 index 0000000..af0cddb --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_namespace_utils.py @@ -0,0 +1,293 @@ +from __future__ import annotations + +import sys +from collections.abc import Generator, Iterator, Mapping +from contextlib import contextmanager +from functools import cached_property +from typing import Any, Callable, NamedTuple, TypeVar + +from typing_extensions import ParamSpec, TypeAlias, TypeAliasType, TypeVarTuple + +GlobalsNamespace: TypeAlias = 'dict[str, Any]' +"""A global namespace. + +In most cases, this is a reference to the `__dict__` attribute of a module. +This namespace type is expected as the `globals` argument during annotations evaluation. +""" + +MappingNamespace: TypeAlias = Mapping[str, Any] +"""Any kind of namespace. + +In most cases, this is a local namespace (e.g. the `__dict__` attribute of a class, +the [`f_locals`][frame.f_locals] attribute of a frame object, when dealing with types +defined inside functions). +This namespace type is expected as the `locals` argument during annotations evaluation. +""" + +_TypeVarLike: TypeAlias = 'TypeVar | ParamSpec | TypeVarTuple' + + +class NamespacesTuple(NamedTuple): + """A tuple of globals and locals to be used during annotations evaluation. + + This datastructure is defined as a named tuple so that it can easily be unpacked: + + ```python {lint="skip" test="skip"} + def eval_type(typ: type[Any], ns: NamespacesTuple) -> None: + return eval(typ, *ns) + ``` + """ + + globals: GlobalsNamespace + """The namespace to be used as the `globals` argument during annotations evaluation.""" + + locals: MappingNamespace + """The namespace to be used as the `locals` argument during annotations evaluation.""" + + +def get_module_ns_of(obj: Any) -> dict[str, Any]: + """Get the namespace of the module where the object is defined. + + Caution: this function does not return a copy of the module namespace, so the result + should not be mutated. The burden of enforcing this is on the caller. + """ + module_name = getattr(obj, '__module__', None) + if module_name: + try: + return sys.modules[module_name].__dict__ + except KeyError: + # happens occasionally, see https://github.com/pydantic/pydantic/issues/2363 + return {} + return {} + + +# Note that this class is almost identical to `collections.ChainMap`, but need to enforce +# immutable mappings here: +class LazyLocalNamespace(Mapping[str, Any]): + """A lazily evaluated mapping, to be used as the `locals` argument during annotations evaluation. + + While the [`eval`][eval] function expects a mapping as the `locals` argument, it only + performs `__getitem__` calls. The [`Mapping`][collections.abc.Mapping] abstract base class + is fully implemented only for type checking purposes. + + Args: + *namespaces: The namespaces to consider, in ascending order of priority. + + Example: + ```python {lint="skip" test="skip"} + ns = LazyLocalNamespace({'a': 1, 'b': 2}, {'a': 3}) + ns['a'] + #> 3 + ns['b'] + #> 2 + ``` + """ + + def __init__(self, *namespaces: MappingNamespace) -> None: + self._namespaces = namespaces + + @cached_property + def data(self) -> dict[str, Any]: + return {k: v for ns in self._namespaces for k, v in ns.items()} + + def __len__(self) -> int: + return len(self.data) + + def __getitem__(self, key: str) -> Any: + return self.data[key] + + def __contains__(self, key: object) -> bool: + return key in self.data + + def __iter__(self) -> Iterator[str]: + return iter(self.data) + + +def ns_for_function(obj: Callable[..., Any], parent_namespace: MappingNamespace | None = None) -> NamespacesTuple: + """Return the global and local namespaces to be used when evaluating annotations for the provided function. + + The global namespace will be the `__dict__` attribute of the module the function was defined in. + The local namespace will contain the `__type_params__` introduced by PEP 695. + + Args: + obj: The object to use when building namespaces. + parent_namespace: Optional namespace to be added with the lowest priority in the local namespace. + If the passed function is a method, the `parent_namespace` will be the namespace of the class + the method is defined in. Thus, we also fetch type `__type_params__` from there (i.e. the + class-scoped type variables). + """ + locals_list: list[MappingNamespace] = [] + if parent_namespace is not None: + locals_list.append(parent_namespace) + + # Get the `__type_params__` attribute introduced by PEP 695. + # Note that the `typing._eval_type` function expects type params to be + # passed as a separate argument. However, internally, `_eval_type` calls + # `ForwardRef._evaluate` which will merge type params with the localns, + # essentially mimicking what we do here. + type_params: tuple[_TypeVarLike, ...] = getattr(obj, '__type_params__', ()) + if parent_namespace is not None: + # We also fetch type params from the parent namespace. If present, it probably + # means the function was defined in a class. This is to support the following: + # https://github.com/python/cpython/issues/124089. + type_params += parent_namespace.get('__type_params__', ()) + + locals_list.append({t.__name__: t for t in type_params}) + + # What about short-circuiting to `obj.__globals__`? + globalns = get_module_ns_of(obj) + + return NamespacesTuple(globalns, LazyLocalNamespace(*locals_list)) + + +class NsResolver: + """A class responsible for the namespaces resolving logic for annotations evaluation. + + This class handles the namespace logic when evaluating annotations mainly for class objects. + + It holds a stack of classes that are being inspected during the core schema building, + and the `types_namespace` property exposes the globals and locals to be used for + type annotation evaluation. Additionally -- if no class is present in the stack -- a + fallback globals and locals can be provided using the `namespaces_tuple` argument + (this is useful when generating a schema for a simple annotation, e.g. when using + `TypeAdapter`). + + The namespace creation logic is unfortunately flawed in some cases, for backwards + compatibility reasons and to better support valid edge cases. See the description + for the `parent_namespace` argument and the example for more details. + + Args: + namespaces_tuple: The default globals and locals to use if no class is present + on the stack. This can be useful when using the `GenerateSchema` class + with `TypeAdapter`, where the "type" being analyzed is a simple annotation. + parent_namespace: An optional parent namespace that will be added to the locals + with the lowest priority. For a given class defined in a function, the locals + of this function are usually used as the parent namespace: + + ```python {lint="skip" test="skip"} + from pydantic import BaseModel + + def func() -> None: + SomeType = int + + class Model(BaseModel): + f: 'SomeType' + + # when collecting fields, an namespace resolver instance will be created + # this way: + # ns_resolver = NsResolver(parent_namespace={'SomeType': SomeType}) + ``` + + For backwards compatibility reasons and to support valid edge cases, this parent + namespace will be used for *every* type being pushed to the stack. In the future, + we might want to be smarter by only doing so when the type being pushed is defined + in the same module as the parent namespace. + + Example: + ```python {lint="skip" test="skip"} + ns_resolver = NsResolver( + parent_namespace={'fallback': 1}, + ) + + class Sub: + m: 'Model' + + class Model: + some_local = 1 + sub: Sub + + ns_resolver = NsResolver() + + # This is roughly what happens when we build a core schema for `Model`: + with ns_resolver.push(Model): + ns_resolver.types_namespace + #> NamespacesTuple({'Sub': Sub}, {'Model': Model, 'some_local': 1}) + # First thing to notice here, the model being pushed is added to the locals. + # Because `NsResolver` is being used during the model definition, it is not + # yet added to the globals. This is useful when resolving self-referencing annotations. + + with ns_resolver.push(Sub): + ns_resolver.types_namespace + #> NamespacesTuple({'Sub': Sub}, {'Sub': Sub, 'Model': Model}) + # Second thing to notice: `Sub` is present in both the globals and locals. + # This is not an issue, just that as described above, the model being pushed + # is added to the locals, but it happens to be present in the globals as well + # because it is already defined. + # Third thing to notice: `Model` is also added in locals. This is a backwards + # compatibility workaround that allows for `Sub` to be able to resolve `'Model'` + # correctly (as otherwise models would have to be rebuilt even though this + # doesn't look necessary). + ``` + """ + + def __init__( + self, + namespaces_tuple: NamespacesTuple | None = None, + parent_namespace: MappingNamespace | None = None, + ) -> None: + self._base_ns_tuple = namespaces_tuple or NamespacesTuple({}, {}) + self._parent_ns = parent_namespace + self._types_stack: list[type[Any] | TypeAliasType] = [] + + @cached_property + def types_namespace(self) -> NamespacesTuple: + """The current global and local namespaces to be used for annotations evaluation.""" + if not self._types_stack: + # TODO: should we merge the parent namespace here? + # This is relevant for TypeAdapter, where there are no types on the stack, and we might + # need access to the parent_ns. Right now, we sidestep this in `type_adapter.py` by passing + # locals to both parent_ns and the base_ns_tuple, but this is a bit hacky. + # we might consider something like: + # if self._parent_ns is not None: + # # Hacky workarounds, see class docstring: + # # An optional parent namespace that will be added to the locals with the lowest priority + # locals_list: list[MappingNamespace] = [self._parent_ns, self._base_ns_tuple.locals] + # return NamespacesTuple(self._base_ns_tuple.globals, LazyLocalNamespace(*locals_list)) + return self._base_ns_tuple + + typ = self._types_stack[-1] + + globalns = get_module_ns_of(typ) + + locals_list: list[MappingNamespace] = [] + # Hacky workarounds, see class docstring: + # An optional parent namespace that will be added to the locals with the lowest priority + if self._parent_ns is not None: + locals_list.append(self._parent_ns) + if len(self._types_stack) > 1: + first_type = self._types_stack[0] + locals_list.append({first_type.__name__: first_type}) + + # Adding `__type_params__` *before* `vars(typ)`, as the latter takes priority + # (see https://github.com/python/cpython/pull/120272). + # TODO `typ.__type_params__` when we drop support for Python 3.11: + type_params: tuple[_TypeVarLike, ...] = getattr(typ, '__type_params__', ()) + if type_params: + # Adding `__type_params__` is mostly useful for generic classes defined using + # PEP 695 syntax *and* using forward annotations (see the example in + # https://github.com/python/cpython/issues/114053). For TypeAliasType instances, + # it is way less common, but still required if using a string annotation in the alias + # value, e.g. `type A[T] = 'T'` (which is not necessary in most cases). + locals_list.append({t.__name__: t for t in type_params}) + + # TypeAliasType instances don't have a `__dict__` attribute, so the check + # is necessary: + if hasattr(typ, '__dict__'): + locals_list.append(vars(typ)) + + # The `len(self._types_stack) > 1` check above prevents this from being added twice: + locals_list.append({typ.__name__: typ}) + + return NamespacesTuple(globalns, LazyLocalNamespace(*locals_list)) + + @contextmanager + def push(self, typ: type[Any] | TypeAliasType, /) -> Generator[None]: + """Push a type to the stack.""" + self._types_stack.append(typ) + # Reset the cached property: + self.__dict__.pop('types_namespace', None) + try: + yield + finally: + self._types_stack.pop() + self.__dict__.pop('types_namespace', None) diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_repr.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_repr.py new file mode 100644 index 0000000..7e80a9c --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_repr.py @@ -0,0 +1,124 @@ +"""Tools to provide pretty/human-readable display of objects.""" + +from __future__ import annotations as _annotations + +import types +from collections.abc import Callable, Collection, Generator, Iterable +from typing import TYPE_CHECKING, Any, ForwardRef, cast + +import typing_extensions +from typing_extensions import TypeAlias +from typing_inspection import typing_objects +from typing_inspection.introspection import is_union_origin + +from . import _typing_extra + +if TYPE_CHECKING: + # TODO remove type error comments when we drop support for Python 3.9 + ReprArgs: TypeAlias = Iterable[tuple[str | None, Any]] # pyright: ignore[reportGeneralTypeIssues] + RichReprResult: TypeAlias = Iterable[Any | tuple[Any] | tuple[str, Any] | tuple[str, Any, Any]] # pyright: ignore[reportGeneralTypeIssues] + + +class PlainRepr(str): + """String class where repr doesn't include quotes. Useful with Representation when you want to return a string + representation of something that is valid (or pseudo-valid) python. + """ + + def __repr__(self) -> str: + return str(self) + + +class Representation: + # Mixin to provide `__str__`, `__repr__`, and `__pretty__` and `__rich_repr__` methods. + # `__pretty__` is used by [devtools](https://python-devtools.helpmanual.io/). + # `__rich_repr__` is used by [rich](https://rich.readthedocs.io/en/stable/pretty.html). + # (this is not a docstring to avoid adding a docstring to classes which inherit from Representation) + + __slots__ = () + + def __repr_args__(self) -> ReprArgs: + """Returns the attributes to show in __str__, __repr__, and __pretty__ this is generally overridden. + + Can either return: + * name - value pairs, e.g.: `[('foo_name', 'foo'), ('bar_name', ['b', 'a', 'r'])]` + * or, just values, e.g.: `[(None, 'foo'), (None, ['b', 'a', 'r'])]` + """ + attrs_names = cast(Collection[str], self.__slots__) + if not attrs_names and hasattr(self, '__dict__'): + attrs_names = self.__dict__.keys() + attrs = ((s, getattr(self, s)) for s in attrs_names) + return [(a, v if v is not self else self.__repr_recursion__(v)) for a, v in attrs if v is not None] + + def __repr_name__(self) -> str: + """Name of the instance's class, used in __repr__.""" + return self.__class__.__name__ + + def __repr_recursion__(self, object: Any) -> str: + """Returns the string representation of a recursive object.""" + # This is copied over from the stdlib `pprint` module: + return f'' + + def __repr_str__(self, join_str: str) -> str: + return join_str.join(repr(v) if a is None else f'{a}={v!r}' for a, v in self.__repr_args__()) + + def __pretty__(self, fmt: Callable[[Any], Any], **kwargs: Any) -> Generator[Any]: + """Used by devtools (https://python-devtools.helpmanual.io/) to pretty print objects.""" + yield self.__repr_name__() + '(' + yield 1 + for name, value in self.__repr_args__(): + if name is not None: + yield name + '=' + yield fmt(value) + yield ',' + yield 0 + yield -1 + yield ')' + + def __rich_repr__(self) -> RichReprResult: + """Used by Rich (https://rich.readthedocs.io/en/stable/pretty.html) to pretty print objects.""" + for name, field_repr in self.__repr_args__(): + if name is None: + yield field_repr + else: + yield name, field_repr + + def __str__(self) -> str: + return self.__repr_str__(' ') + + def __repr__(self) -> str: + return f'{self.__repr_name__()}({self.__repr_str__(", ")})' + + +def display_as_type(obj: Any) -> str: + """Pretty representation of a type, should be as close as possible to the original type definition string. + + Takes some logic from `typing._type_repr`. + """ + if isinstance(obj, (types.FunctionType, types.BuiltinFunctionType)): + return obj.__name__ + elif obj is ...: + return '...' + elif isinstance(obj, Representation): + return repr(obj) + elif isinstance(obj, ForwardRef) or typing_objects.is_typealiastype(obj): + return str(obj) + + if not isinstance(obj, (_typing_extra.typing_base, _typing_extra.WithArgsTypes, type)): + obj = obj.__class__ + + if is_union_origin(typing_extensions.get_origin(obj)): + args = ', '.join(map(display_as_type, typing_extensions.get_args(obj))) + return f'Union[{args}]' + elif isinstance(obj, _typing_extra.WithArgsTypes): + if typing_objects.is_literal(typing_extensions.get_origin(obj)): + args = ', '.join(map(repr, typing_extensions.get_args(obj))) + else: + args = ', '.join(map(display_as_type, typing_extensions.get_args(obj))) + try: + return f'{obj.__qualname__}[{args}]' + except AttributeError: + return str(obj).replace('typing.', '').replace('typing_extensions.', '') # handles TypeAliasType in 3.12 + elif isinstance(obj, type): + return obj.__qualname__ + else: + return repr(obj).replace('typing.', '').replace('typing_extensions.', '') diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_schema_gather.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_schema_gather.py new file mode 100644 index 0000000..fc2d806 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_schema_gather.py @@ -0,0 +1,209 @@ +# pyright: reportTypedDictNotRequiredAccess=false, reportGeneralTypeIssues=false, reportArgumentType=false, reportAttributeAccessIssue=false +from __future__ import annotations + +from dataclasses import dataclass, field +from typing import TypedDict + +from pydantic_core.core_schema import ComputedField, CoreSchema, DefinitionReferenceSchema, SerSchema +from typing_extensions import TypeAlias + +AllSchemas: TypeAlias = 'CoreSchema | SerSchema | ComputedField' + + +class GatherResult(TypedDict): + """Schema traversing result.""" + + collected_references: dict[str, DefinitionReferenceSchema | None] + """The collected definition references. + + If a definition reference schema can be inlined, it means that there is + only one in the whole core schema. As such, it is stored as the value. + Otherwise, the value is set to `None`. + """ + + deferred_discriminator_schemas: list[CoreSchema] + """The list of core schemas having the discriminator application deferred.""" + + +class MissingDefinitionError(LookupError): + """A reference was pointing to a non-existing core schema.""" + + def __init__(self, schema_reference: str, /) -> None: + self.schema_reference = schema_reference + + +@dataclass +class GatherContext: + """The current context used during core schema traversing. + + Context instances should only be used during schema traversing. + """ + + definitions: dict[str, CoreSchema] + """The available definitions.""" + + deferred_discriminator_schemas: list[CoreSchema] = field(init=False, default_factory=list) + """The list of core schemas having the discriminator application deferred. + + Internally, these core schemas have a specific key set in the core metadata dict. + """ + + collected_references: dict[str, DefinitionReferenceSchema | None] = field(init=False, default_factory=dict) + """The collected definition references. + + If a definition reference schema can be inlined, it means that there is + only one in the whole core schema. As such, it is stored as the value. + Otherwise, the value is set to `None`. + + During schema traversing, definition reference schemas can be added as candidates, or removed + (by setting the value to `None`). + """ + + +def traverse_metadata(schema: AllSchemas, ctx: GatherContext) -> None: + meta = schema.get('metadata') + if meta is not None and 'pydantic_internal_union_discriminator' in meta: + ctx.deferred_discriminator_schemas.append(schema) # pyright: ignore[reportArgumentType] + + +def traverse_definition_ref(def_ref_schema: DefinitionReferenceSchema, ctx: GatherContext) -> None: + schema_ref = def_ref_schema['schema_ref'] + + if schema_ref not in ctx.collected_references: + definition = ctx.definitions.get(schema_ref) + if definition is None: + raise MissingDefinitionError(schema_ref) + + # The `'definition-ref'` schema was only encountered once, make it + # a candidate to be inlined: + ctx.collected_references[schema_ref] = def_ref_schema + traverse_schema(definition, ctx) + if 'serialization' in def_ref_schema: + traverse_schema(def_ref_schema['serialization'], ctx) + traverse_metadata(def_ref_schema, ctx) + else: + # The `'definition-ref'` schema was already encountered, meaning + # the previously encountered schema (and this one) can't be inlined: + ctx.collected_references[schema_ref] = None + + +def traverse_schema(schema: AllSchemas, context: GatherContext) -> None: + # TODO When we drop 3.9, use a match statement to get better type checking and remove + # file-level type ignore. + # (the `'type'` could also be fetched in every `if/elif` statement, but this alters performance). + schema_type = schema['type'] + + if schema_type == 'definition-ref': + traverse_definition_ref(schema, context) + # `traverse_definition_ref` handles the possible serialization and metadata schemas: + return + elif schema_type == 'definitions': + traverse_schema(schema['schema'], context) + for definition in schema['definitions']: + traverse_schema(definition, context) + elif schema_type in {'list', 'set', 'frozenset', 'generator'}: + if 'items_schema' in schema: + traverse_schema(schema['items_schema'], context) + elif schema_type == 'tuple': + if 'items_schema' in schema: + for s in schema['items_schema']: + traverse_schema(s, context) + elif schema_type == 'dict': + if 'keys_schema' in schema: + traverse_schema(schema['keys_schema'], context) + if 'values_schema' in schema: + traverse_schema(schema['values_schema'], context) + elif schema_type == 'union': + for choice in schema['choices']: + if isinstance(choice, tuple): + traverse_schema(choice[0], context) + else: + traverse_schema(choice, context) + elif schema_type == 'tagged-union': + for v in schema['choices'].values(): + traverse_schema(v, context) + elif schema_type == 'chain': + for step in schema['steps']: + traverse_schema(step, context) + elif schema_type == 'lax-or-strict': + traverse_schema(schema['lax_schema'], context) + traverse_schema(schema['strict_schema'], context) + elif schema_type == 'json-or-python': + traverse_schema(schema['json_schema'], context) + traverse_schema(schema['python_schema'], context) + elif schema_type in {'model-fields', 'typed-dict'}: + if 'extras_schema' in schema: + traverse_schema(schema['extras_schema'], context) + if 'computed_fields' in schema: + for s in schema['computed_fields']: + traverse_schema(s, context) + for s in schema['fields'].values(): + traverse_schema(s, context) + elif schema_type == 'dataclass-args': + if 'computed_fields' in schema: + for s in schema['computed_fields']: + traverse_schema(s, context) + for s in schema['fields']: + traverse_schema(s, context) + elif schema_type == 'arguments': + for s in schema['arguments_schema']: + traverse_schema(s['schema'], context) + if 'var_args_schema' in schema: + traverse_schema(schema['var_args_schema'], context) + if 'var_kwargs_schema' in schema: + traverse_schema(schema['var_kwargs_schema'], context) + elif schema_type == 'arguments-v3': + for s in schema['arguments_schema']: + traverse_schema(s['schema'], context) + elif schema_type == 'call': + traverse_schema(schema['arguments_schema'], context) + if 'return_schema' in schema: + traverse_schema(schema['return_schema'], context) + elif schema_type == 'computed-field': + traverse_schema(schema['return_schema'], context) + elif schema_type == 'function-before': + if 'schema' in schema: + traverse_schema(schema['schema'], context) + if 'json_schema_input_schema' in schema: + traverse_schema(schema['json_schema_input_schema'], context) + elif schema_type == 'function-plain': + # TODO duplicate schema types for serializers and validators, needs to be deduplicated. + if 'return_schema' in schema: + traverse_schema(schema['return_schema'], context) + if 'json_schema_input_schema' in schema: + traverse_schema(schema['json_schema_input_schema'], context) + elif schema_type == 'function-wrap': + # TODO duplicate schema types for serializers and validators, needs to be deduplicated. + if 'return_schema' in schema: + traverse_schema(schema['return_schema'], context) + if 'schema' in schema: + traverse_schema(schema['schema'], context) + if 'json_schema_input_schema' in schema: + traverse_schema(schema['json_schema_input_schema'], context) + else: + if 'schema' in schema: + traverse_schema(schema['schema'], context) + + if 'serialization' in schema: + traverse_schema(schema['serialization'], context) + traverse_metadata(schema, context) + + +def gather_schemas_for_cleaning(schema: CoreSchema, definitions: dict[str, CoreSchema]) -> GatherResult: + """Traverse the core schema and definitions and return the necessary information for schema cleaning. + + During the core schema traversing, any `'definition-ref'` schema is: + + - Validated: the reference must point to an existing definition. If this is not the case, a + `MissingDefinitionError` exception is raised. + - Stored in the context: the actual reference is stored in the context. Depending on whether + the `'definition-ref'` schema is encountered more that once, the schema itself is also + saved in the context to be inlined (i.e. replaced by the definition it points to). + """ + context = GatherContext(definitions) + traverse_schema(schema, context) + + return { + 'collected_references': context.collected_references, + 'deferred_discriminator_schemas': context.deferred_discriminator_schemas, + } diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_schema_generation_shared.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_schema_generation_shared.py new file mode 100644 index 0000000..b231a82 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_schema_generation_shared.py @@ -0,0 +1,125 @@ +"""Types and utility functions used by various other internal tools.""" + +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Callable, Literal + +from pydantic_core import core_schema + +from ..annotated_handlers import GetCoreSchemaHandler, GetJsonSchemaHandler + +if TYPE_CHECKING: + from ..json_schema import GenerateJsonSchema, JsonSchemaValue + from ._core_utils import CoreSchemaOrField + from ._generate_schema import GenerateSchema + from ._namespace_utils import NamespacesTuple + + GetJsonSchemaFunction = Callable[[CoreSchemaOrField, GetJsonSchemaHandler], JsonSchemaValue] + HandlerOverride = Callable[[CoreSchemaOrField], JsonSchemaValue] + + +class GenerateJsonSchemaHandler(GetJsonSchemaHandler): + """JsonSchemaHandler implementation that doesn't do ref unwrapping by default. + + This is used for any Annotated metadata so that we don't end up with conflicting + modifications to the definition schema. + + Used internally by Pydantic, please do not rely on this implementation. + See `GetJsonSchemaHandler` for the handler API. + """ + + def __init__(self, generate_json_schema: GenerateJsonSchema, handler_override: HandlerOverride | None) -> None: + self.generate_json_schema = generate_json_schema + self.handler = handler_override or generate_json_schema.generate_inner + self.mode = generate_json_schema.mode + + def __call__(self, core_schema: CoreSchemaOrField, /) -> JsonSchemaValue: + return self.handler(core_schema) + + def resolve_ref_schema(self, maybe_ref_json_schema: JsonSchemaValue) -> JsonSchemaValue: + """Resolves `$ref` in the json schema. + + This returns the input json schema if there is no `$ref` in json schema. + + Args: + maybe_ref_json_schema: The input json schema that may contains `$ref`. + + Returns: + Resolved json schema. + + Raises: + LookupError: If it can't find the definition for `$ref`. + """ + if '$ref' not in maybe_ref_json_schema: + return maybe_ref_json_schema + ref = maybe_ref_json_schema['$ref'] + json_schema = self.generate_json_schema.get_schema_from_definitions(ref) + if json_schema is None: + raise LookupError( + f'Could not find a ref for {ref}.' + ' Maybe you tried to call resolve_ref_schema from within a recursive model?' + ) + return json_schema + + +class CallbackGetCoreSchemaHandler(GetCoreSchemaHandler): + """Wrapper to use an arbitrary function as a `GetCoreSchemaHandler`. + + Used internally by Pydantic, please do not rely on this implementation. + See `GetCoreSchemaHandler` for the handler API. + """ + + def __init__( + self, + handler: Callable[[Any], core_schema.CoreSchema], + generate_schema: GenerateSchema, + ref_mode: Literal['to-def', 'unpack'] = 'to-def', + ) -> None: + self._handler = handler + self._generate_schema = generate_schema + self._ref_mode = ref_mode + + def __call__(self, source_type: Any, /) -> core_schema.CoreSchema: + schema = self._handler(source_type) + if self._ref_mode == 'to-def': + ref = schema.get('ref') + if ref is not None: + return self._generate_schema.defs.create_definition_reference_schema(schema) + return schema + else: # ref_mode = 'unpack' + return self.resolve_ref_schema(schema) + + def _get_types_namespace(self) -> NamespacesTuple: + return self._generate_schema._types_namespace + + def generate_schema(self, source_type: Any, /) -> core_schema.CoreSchema: + return self._generate_schema.generate_schema(source_type) + + @property + def field_name(self) -> str | None: + return self._generate_schema.field_name_stack.get() + + def resolve_ref_schema(self, maybe_ref_schema: core_schema.CoreSchema) -> core_schema.CoreSchema: + """Resolves reference in the core schema. + + Args: + maybe_ref_schema: The input core schema that may contains reference. + + Returns: + Resolved core schema. + + Raises: + LookupError: If it can't find the definition for reference. + """ + if maybe_ref_schema['type'] == 'definition-ref': + ref = maybe_ref_schema['schema_ref'] + definition = self._generate_schema.defs.get_schema_from_ref(ref) + if definition is None: + raise LookupError( + f'Could not find a ref for {ref}.' + ' Maybe you tried to call resolve_ref_schema from within a recursive model?' + ) + return definition + elif maybe_ref_schema['type'] == 'definitions': + return self.resolve_ref_schema(maybe_ref_schema['schema']) + return maybe_ref_schema diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_serializers.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_serializers.py new file mode 100644 index 0000000..a4058e0 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_serializers.py @@ -0,0 +1,53 @@ +from __future__ import annotations + +import collections +import collections.abc +import typing +from typing import Any + +from pydantic_core import PydanticOmit, core_schema + +SEQUENCE_ORIGIN_MAP: dict[Any, Any] = { + typing.Deque: collections.deque, # noqa: UP006 + collections.deque: collections.deque, + list: list, + typing.List: list, # noqa: UP006 + tuple: tuple, + typing.Tuple: tuple, # noqa: UP006 + set: set, + typing.AbstractSet: set, + typing.Set: set, # noqa: UP006 + frozenset: frozenset, + typing.FrozenSet: frozenset, # noqa: UP006 + typing.Sequence: list, + typing.MutableSequence: list, + typing.MutableSet: set, + # this doesn't handle subclasses of these + # parametrized typing.Set creates one of these + collections.abc.MutableSet: set, + collections.abc.Set: frozenset, +} + + +def serialize_sequence_via_list( + v: Any, handler: core_schema.SerializerFunctionWrapHandler, info: core_schema.SerializationInfo +) -> Any: + items: list[Any] = [] + + mapped_origin = SEQUENCE_ORIGIN_MAP.get(type(v), None) + if mapped_origin is None: + # we shouldn't hit this branch, should probably add a serialization error or something + return v + + for index, item in enumerate(v): + try: + v = handler(item, index) + except PydanticOmit: # noqa: PERF203 + pass + else: + items.append(v) + + if info.mode_is_json(): + return items + else: + return mapped_origin(items) diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_signature.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_signature.py new file mode 100644 index 0000000..977e5d2 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_signature.py @@ -0,0 +1,188 @@ +from __future__ import annotations + +import dataclasses +from inspect import Parameter, Signature, signature +from typing import TYPE_CHECKING, Any, Callable + +from pydantic_core import PydanticUndefined + +from ._utils import is_valid_identifier + +if TYPE_CHECKING: + from ..config import ExtraValues + from ..fields import FieldInfo + + +# Copied over from stdlib dataclasses +class _HAS_DEFAULT_FACTORY_CLASS: + def __repr__(self): + return '' + + +_HAS_DEFAULT_FACTORY = _HAS_DEFAULT_FACTORY_CLASS() + + +def _field_name_for_signature(field_name: str, field_info: FieldInfo) -> str: + """Extract the correct name to use for the field when generating a signature. + + Assuming the field has a valid alias, this will return the alias. Otherwise, it will return the field name. + First priority is given to the alias, then the validation_alias, then the field name. + + Args: + field_name: The name of the field + field_info: The corresponding FieldInfo object. + + Returns: + The correct name to use when generating a signature. + """ + if isinstance(field_info.alias, str) and is_valid_identifier(field_info.alias): + return field_info.alias + if isinstance(field_info.validation_alias, str) and is_valid_identifier(field_info.validation_alias): + return field_info.validation_alias + + return field_name + + +def _process_param_defaults(param: Parameter) -> Parameter: + """Modify the signature for a parameter in a dataclass where the default value is a FieldInfo instance. + + Args: + param (Parameter): The parameter + + Returns: + Parameter: The custom processed parameter + """ + from ..fields import FieldInfo + + param_default = param.default + if isinstance(param_default, FieldInfo): + annotation = param.annotation + # Replace the annotation if appropriate + # inspect does "clever" things to show annotations as strings because we have + # `from __future__ import annotations` in main, we don't want that + if annotation == 'Any': + annotation = Any + + # Replace the field default + default = param_default.default + if default is PydanticUndefined: + if param_default.default_factory is PydanticUndefined: + default = Signature.empty + else: + # this is used by dataclasses to indicate a factory exists: + default = dataclasses._HAS_DEFAULT_FACTORY # type: ignore + return param.replace( + annotation=annotation, name=_field_name_for_signature(param.name, param_default), default=default + ) + return param + + +def _generate_signature_parameters( # noqa: C901 (ignore complexity, could use a refactor) + init: Callable[..., None], + fields: dict[str, FieldInfo], + validate_by_name: bool, + extra: ExtraValues | None, +) -> dict[str, Parameter]: + """Generate a mapping of parameter names to Parameter objects for a pydantic BaseModel or dataclass.""" + from itertools import islice + + present_params = signature(init).parameters.values() + merged_params: dict[str, Parameter] = {} + var_kw = None + use_var_kw = False + + for param in islice(present_params, 1, None): # skip self arg + # inspect does "clever" things to show annotations as strings because we have + # `from __future__ import annotations` in main, we don't want that + if fields.get(param.name): + # exclude params with init=False + if getattr(fields[param.name], 'init', True) is False: + continue + param = param.replace(name=_field_name_for_signature(param.name, fields[param.name])) + if param.annotation == 'Any': + param = param.replace(annotation=Any) + if param.kind is param.VAR_KEYWORD: + var_kw = param + continue + merged_params[param.name] = param + + if var_kw: # if custom init has no var_kw, fields which are not declared in it cannot be passed through + allow_names = validate_by_name + for field_name, field in fields.items(): + # when alias is a str it should be used for signature generation + param_name = _field_name_for_signature(field_name, field) + + if field_name in merged_params or param_name in merged_params: + continue + + if not is_valid_identifier(param_name): + if allow_names: + param_name = field_name + else: + use_var_kw = True + continue + + if field.is_required(): + default = Parameter.empty + elif field.default_factory is not None: + # Mimics stdlib dataclasses: + default = _HAS_DEFAULT_FACTORY + else: + default = field.default + merged_params[param_name] = Parameter( + param_name, + Parameter.KEYWORD_ONLY, + annotation=field.rebuild_annotation(), + default=default, + ) + + if extra == 'allow': + use_var_kw = True + + if var_kw and use_var_kw: + # Make sure the parameter for extra kwargs + # does not have the same name as a field + default_model_signature = [ + ('self', Parameter.POSITIONAL_ONLY), + ('data', Parameter.VAR_KEYWORD), + ] + if [(p.name, p.kind) for p in present_params] == default_model_signature: + # if this is the standard model signature, use extra_data as the extra args name + var_kw_name = 'extra_data' + else: + # else start from var_kw + var_kw_name = var_kw.name + + # generate a name that's definitely unique + while var_kw_name in fields: + var_kw_name += '_' + merged_params[var_kw_name] = var_kw.replace(name=var_kw_name) + + return merged_params + + +def generate_pydantic_signature( + init: Callable[..., None], + fields: dict[str, FieldInfo], + validate_by_name: bool, + extra: ExtraValues | None, + is_dataclass: bool = False, +) -> Signature: + """Generate signature for a pydantic BaseModel or dataclass. + + Args: + init: The class init. + fields: The model fields. + validate_by_name: The `validate_by_name` value of the config. + extra: The `extra` value of the config. + is_dataclass: Whether the model is a dataclass. + + Returns: + The dataclass/BaseModel subclass signature. + """ + merged_params = _generate_signature_parameters(init, fields, validate_by_name, extra) + + if is_dataclass: + merged_params = {k: _process_param_defaults(v) for k, v in merged_params.items()} + + return Signature(parameters=list(merged_params.values()), return_annotation=None) diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_typing_extra.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_typing_extra.py new file mode 100644 index 0000000..986ee42 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_typing_extra.py @@ -0,0 +1,760 @@ +"""Logic for interacting with type annotations, mostly extensions, shims and hacks to wrap Python's typing module.""" + +from __future__ import annotations + +import collections.abc +import re +import sys +import types +import typing +from functools import partial +from typing import TYPE_CHECKING, Any, Callable, cast + +import typing_extensions +from typing_extensions import deprecated, get_args, get_origin +from typing_inspection import typing_objects +from typing_inspection.introspection import is_union_origin + +from pydantic.version import version_short + +from ._namespace_utils import GlobalsNamespace, MappingNamespace, NsResolver, get_module_ns_of + +if sys.version_info < (3, 10): + NoneType = type(None) + EllipsisType = type(Ellipsis) +else: + from types import EllipsisType as EllipsisType + from types import NoneType as NoneType + +if sys.version_info >= (3, 14): + import annotationlib + +if TYPE_CHECKING: + from pydantic import BaseModel + +# As per https://typing-extensions.readthedocs.io/en/latest/#runtime-use-of-types, +# always check for both `typing` and `typing_extensions` variants of a typing construct. +# (this is implemented differently than the suggested approach in the `typing_extensions` +# docs for performance). + + +_t_annotated = typing.Annotated +_te_annotated = typing_extensions.Annotated + + +def is_annotated(tp: Any, /) -> bool: + """Return whether the provided argument is a `Annotated` special form. + + ```python {test="skip" lint="skip"} + is_annotated(Annotated[int, ...]) + #> True + ``` + """ + origin = get_origin(tp) + return origin is _t_annotated or origin is _te_annotated + + +def annotated_type(tp: Any, /) -> Any | None: + """Return the type of the `Annotated` special form, or `None`.""" + return tp.__origin__ if typing_objects.is_annotated(get_origin(tp)) else None + + +def unpack_type(tp: Any, /) -> Any | None: + """Return the type wrapped by the `Unpack` special form, or `None`.""" + return get_args(tp)[0] if typing_objects.is_unpack(get_origin(tp)) else None + + +def is_hashable(tp: Any, /) -> bool: + """Return whether the provided argument is the `Hashable` class. + + ```python {test="skip" lint="skip"} + is_hashable(Hashable) + #> True + ``` + """ + # `get_origin` is documented as normalizing any typing-module aliases to `collections` classes, + # hence the second check: + return tp is collections.abc.Hashable or get_origin(tp) is collections.abc.Hashable + + +def is_callable(tp: Any, /) -> bool: + """Return whether the provided argument is a `Callable`, parametrized or not. + + ```python {test="skip" lint="skip"} + is_callable(Callable[[int], str]) + #> True + is_callable(typing.Callable) + #> True + is_callable(collections.abc.Callable) + #> True + ``` + """ + # `get_origin` is documented as normalizing any typing-module aliases to `collections` classes, + # hence the second check: + return tp is collections.abc.Callable or get_origin(tp) is collections.abc.Callable + + +_classvar_re = re.compile(r'((\w+\.)?Annotated\[)?(\w+\.)?ClassVar\[') + + +def is_classvar_annotation(tp: Any, /) -> bool: + """Return whether the provided argument represents a class variable annotation. + + Although not explicitly stated by the typing specification, `ClassVar` can be used + inside `Annotated` and as such, this function checks for this specific scenario. + + Because this function is used to detect class variables before evaluating forward references + (or because evaluation failed), we also implement a naive regex match implementation. This is + required because class variables are inspected before fields are collected, so we try to be + as accurate as possible. + """ + if typing_objects.is_classvar(tp): + return True + + origin = get_origin(tp) + + if typing_objects.is_classvar(origin): + return True + + if typing_objects.is_annotated(origin): + annotated_type = tp.__origin__ + if typing_objects.is_classvar(annotated_type) or typing_objects.is_classvar(get_origin(annotated_type)): + return True + + str_ann: str | None = None + if isinstance(tp, typing.ForwardRef): + str_ann = tp.__forward_arg__ + if isinstance(tp, str): + str_ann = tp + + if str_ann is not None and _classvar_re.match(str_ann): + # stdlib dataclasses do something similar, although a bit more advanced + # (see `dataclass._is_type`). + return True + + return False + + +_t_final = typing.Final +_te_final = typing_extensions.Final + + +# TODO implement `is_finalvar_annotation` as Final can be wrapped with other special forms: +def is_finalvar(tp: Any, /) -> bool: + """Return whether the provided argument is a `Final` special form, parametrized or not. + + ```python {test="skip" lint="skip"} + is_finalvar(Final[int]) + #> True + is_finalvar(Final) + #> True + """ + # Final is not necessarily parametrized: + if tp is _t_final or tp is _te_final: + return True + origin = get_origin(tp) + return origin is _t_final or origin is _te_final + + +_NONE_TYPES: tuple[Any, ...] = (None, NoneType, typing.Literal[None], typing_extensions.Literal[None]) + + +def is_none_type(tp: Any, /) -> bool: + """Return whether the argument represents the `None` type as part of an annotation. + + ```python {test="skip" lint="skip"} + is_none_type(None) + #> True + is_none_type(NoneType) + #> True + is_none_type(Literal[None]) + #> True + is_none_type(type[None]) + #> False + """ + return tp in _NONE_TYPES + + +def is_namedtuple(tp: Any, /) -> bool: + """Return whether the provided argument is a named tuple class. + + The class can be created using `typing.NamedTuple` or `collections.namedtuple`. + Parametrized generic classes are *not* assumed to be named tuples. + """ + from ._utils import lenient_issubclass # circ. import + + return lenient_issubclass(tp, tuple) and hasattr(tp, '_fields') + + +# TODO In 2.12, delete this export. It is currently defined only to not break +# pydantic-settings which relies on it: +origin_is_union = is_union_origin + + +def is_generic_alias(tp: Any, /) -> bool: + return isinstance(tp, (types.GenericAlias, typing._GenericAlias)) # pyright: ignore[reportAttributeAccessIssue] + + +# TODO: Ideally, we should avoid relying on the private `typing` constructs: + +if sys.version_info < (3, 10): + WithArgsTypes: tuple[Any, ...] = (typing._GenericAlias, types.GenericAlias) # pyright: ignore[reportAttributeAccessIssue] +else: + WithArgsTypes: tuple[Any, ...] = (typing._GenericAlias, types.GenericAlias, types.UnionType) # pyright: ignore[reportAttributeAccessIssue] + + +# Similarly, we shouldn't rely on this `_Final` class, which is even more private than `_GenericAlias`: +typing_base: Any = typing._Final # pyright: ignore[reportAttributeAccessIssue] + + +### Annotation evaluations functions: + + +def parent_frame_namespace(*, parent_depth: int = 2, force: bool = False) -> dict[str, Any] | None: + """Fetch the local namespace of the parent frame where this function is called. + + Using this function is mostly useful to resolve forward annotations pointing to members defined in a local namespace, + such as assignments inside a function. Using the standard library tools, it is currently not possible to resolve + such annotations: + + ```python {lint="skip" test="skip"} + from typing import get_type_hints + + def func() -> None: + Alias = int + + class C: + a: 'Alias' + + # Raises a `NameError: 'Alias' is not defined` + get_type_hints(C) + ``` + + Pydantic uses this function when a Pydantic model is being defined to fetch the parent frame locals. However, + this only allows us to fetch the parent frame namespace and not other parents (e.g. a model defined in a function, + itself defined in another function). Inspecting the next outer frames (using `f_back`) is not reliable enough + (see https://discuss.python.org/t/20659). + + Because this function is mostly used to better resolve forward annotations, nothing is returned if the parent frame's + code object is defined at the module level. In this case, the locals of the frame will be the same as the module + globals where the class is defined (see `_namespace_utils.get_module_ns_of`). However, if you still want to fetch + the module globals (e.g. when rebuilding a model, where the frame where the rebuild call is performed might contain + members that you want to use for forward annotations evaluation), you can use the `force` parameter. + + Args: + parent_depth: The depth at which to get the frame. Defaults to 2, meaning the parent frame where this function + is called will be used. + force: Whether to always return the frame locals, even if the frame's code object is defined at the module level. + + Returns: + The locals of the namespace, or `None` if it was skipped as per the described logic. + """ + frame = sys._getframe(parent_depth) + + if frame.f_code.co_name.startswith('`, + # and we need to skip this frame as it is irrelevant. + frame = cast(types.FrameType, frame.f_back) # guaranteed to not be `None` + + # note, we don't copy frame.f_locals here (or during the last return call), because we don't expect the namespace to be + # modified down the line if this becomes a problem, we could implement some sort of frozen mapping structure to enforce this. + if force: + return frame.f_locals + + # If either of the following conditions are true, the class is defined at the top module level. + # To better understand why we need both of these checks, see + # https://github.com/pydantic/pydantic/pull/10113#discussion_r1714981531. + if frame.f_back is None or frame.f_code.co_name == '': + return None + + return frame.f_locals + + +def _type_convert(arg: Any) -> Any: + """Convert `None` to `NoneType` and strings to `ForwardRef` instances. + + This is a backport of the private `typing._type_convert` function. When + evaluating a type, `ForwardRef._evaluate` ends up being called, and is + responsible for making this conversion. However, we still have to apply + it for the first argument passed to our type evaluation functions, similarly + to the `typing.get_type_hints` function. + """ + if arg is None: + return NoneType + if isinstance(arg, str): + # Like `typing.get_type_hints`, assume the arg can be in any context, + # hence the proper `is_argument` and `is_class` args: + return _make_forward_ref(arg, is_argument=False, is_class=True) + return arg + + +def safe_get_annotations(cls: type[Any]) -> dict[str, Any]: + """Get the annotations for the provided class, accounting for potential deferred forward references. + + Starting with Python 3.14, accessing the `__annotations__` attribute might raise a `NameError` if + a referenced symbol isn't defined yet. In this case, we return the annotation in the *forward ref* + format. + """ + if sys.version_info >= (3, 14): + return annotationlib.get_annotations(cls, format=annotationlib.Format.FORWARDREF) + else: + return cls.__dict__.get('__annotations__', {}) + + +def get_model_type_hints( + obj: type[BaseModel], + *, + ns_resolver: NsResolver | None = None, +) -> dict[str, tuple[Any, bool]]: + """Collect annotations from a Pydantic model class, including those from parent classes. + + Args: + obj: The Pydantic model to inspect. + ns_resolver: A namespace resolver instance to use. Defaults to an empty instance. + + Returns: + A dictionary mapping annotation names to a two-tuple: the first element is the evaluated + type or the original annotation if a `NameError` occurred, the second element is a boolean + indicating if whether the evaluation succeeded. + """ + hints: dict[str, Any] | dict[str, tuple[Any, bool]] = {} + ns_resolver = ns_resolver or NsResolver() + + for base in reversed(obj.__mro__): + # For Python 3.14, we could also use `Format.VALUE` and pass the globals/locals + # from the ns_resolver, but we want to be able to know which specific field failed + # to evaluate: + ann = safe_get_annotations(base) + + if not ann: + continue + + with ns_resolver.push(base): + globalns, localns = ns_resolver.types_namespace + for name, value in ann.items(): + if name.startswith('_'): + # For private attributes, we only need the annotation to detect the `ClassVar` special form. + # For this reason, we still try to evaluate it, but we also catch any possible exception (on + # top of the `NameError`s caught in `try_eval_type`) that could happen so that users are free + # to use any kind of forward annotation for private fields (e.g. circular imports, new typing + # syntax, etc). + try: + hints[name] = try_eval_type(value, globalns, localns) + except Exception: + hints[name] = (value, False) + else: + hints[name] = try_eval_type(value, globalns, localns) + return hints + + +def get_cls_type_hints( + obj: type[Any], + *, + ns_resolver: NsResolver | None = None, +) -> dict[str, Any]: + """Collect annotations from a class, including those from parent classes. + + Args: + obj: The class to inspect. + ns_resolver: A namespace resolver instance to use. Defaults to an empty instance. + """ + hints: dict[str, Any] = {} + ns_resolver = ns_resolver or NsResolver() + + for base in reversed(obj.__mro__): + # For Python 3.14, we could also use `Format.VALUE` and pass the globals/locals + # from the ns_resolver, but we want to be able to know which specific field failed + # to evaluate: + ann = safe_get_annotations(base) + + if not ann: + continue + + with ns_resolver.push(base): + globalns, localns = ns_resolver.types_namespace + for name, value in ann.items(): + hints[name] = eval_type(value, globalns, localns) + return hints + + +def try_eval_type( + value: Any, + globalns: GlobalsNamespace | None = None, + localns: MappingNamespace | None = None, +) -> tuple[Any, bool]: + """Try evaluating the annotation using the provided namespaces. + + Args: + value: The value to evaluate. If `None`, it will be replaced by `type[None]`. If an instance + of `str`, it will be converted to a `ForwardRef`. + localns: The global namespace to use during annotation evaluation. + globalns: The local namespace to use during annotation evaluation. + + Returns: + A two-tuple containing the possibly evaluated type and a boolean indicating + whether the evaluation succeeded or not. + """ + value = _type_convert(value) + + try: + return eval_type_backport(value, globalns, localns), True + except NameError: + return value, False + + +def eval_type( + value: Any, + globalns: GlobalsNamespace | None = None, + localns: MappingNamespace | None = None, +) -> Any: + """Evaluate the annotation using the provided namespaces. + + Args: + value: The value to evaluate. If `None`, it will be replaced by `type[None]`. If an instance + of `str`, it will be converted to a `ForwardRef`. + localns: The global namespace to use during annotation evaluation. + globalns: The local namespace to use during annotation evaluation. + """ + value = _type_convert(value) + return eval_type_backport(value, globalns, localns) + + +@deprecated( + '`eval_type_lenient` is deprecated, use `try_eval_type` instead.', + category=None, +) +def eval_type_lenient( + value: Any, + globalns: GlobalsNamespace | None = None, + localns: MappingNamespace | None = None, +) -> Any: + ev, _ = try_eval_type(value, globalns, localns) + return ev + + +def eval_type_backport( + value: Any, + globalns: GlobalsNamespace | None = None, + localns: MappingNamespace | None = None, + type_params: tuple[Any, ...] | None = None, +) -> Any: + """An enhanced version of `typing._eval_type` which will fall back to using the `eval_type_backport` + package if it's installed to let older Python versions use newer typing constructs. + + Specifically, this transforms `X | Y` into `typing.Union[X, Y]` and `list[X]` into `typing.List[X]` + (as well as all the types made generic in PEP 585) if the original syntax is not supported in the + current Python version. + + This function will also display a helpful error if the value passed fails to evaluate. + """ + try: + return _eval_type_backport(value, globalns, localns, type_params) + except TypeError as e: + if 'Unable to evaluate type annotation' in str(e): + raise + + # If it is a `TypeError` and value isn't a `ForwardRef`, it would have failed during annotation definition. + # Thus we assert here for type checking purposes: + assert isinstance(value, typing.ForwardRef) + + message = f'Unable to evaluate type annotation {value.__forward_arg__!r}.' + if sys.version_info >= (3, 11): + e.add_note(message) + raise + else: + raise TypeError(message) from e + except RecursionError as e: + # TODO ideally recursion errors should be checked in `eval_type` above, but `eval_type_backport` + # is used directly in some places. + message = ( + "If you made use of an implicit recursive type alias (e.g. `MyType = list['MyType']), " + 'consider using PEP 695 type aliases instead. For more details, refer to the documentation: ' + f'https://docs.pydantic.dev/{version_short()}/concepts/types/#named-recursive-types' + ) + if sys.version_info >= (3, 11): + e.add_note(message) + raise + else: + raise RecursionError(f'{e.args[0]}\n{message}') + + +def _eval_type_backport( + value: Any, + globalns: GlobalsNamespace | None = None, + localns: MappingNamespace | None = None, + type_params: tuple[Any, ...] | None = None, +) -> Any: + try: + return _eval_type(value, globalns, localns, type_params) + except TypeError as e: + if not (isinstance(value, typing.ForwardRef) and is_backport_fixable_error(e)): + raise + + try: + from eval_type_backport import eval_type_backport + except ImportError: + raise TypeError( + f'Unable to evaluate type annotation {value.__forward_arg__!r}. If you are making use ' + 'of the new typing syntax (unions using `|` since Python 3.10 or builtins subscripting ' + 'since Python 3.9), you should either replace the use of new syntax with the existing ' + '`typing` constructs or install the `eval_type_backport` package.' + ) from e + + return eval_type_backport( + value, + globalns, + localns, # pyright: ignore[reportArgumentType], waiting on a new `eval_type_backport` release. + try_default=False, + ) + + +def _eval_type( + value: Any, + globalns: GlobalsNamespace | None = None, + localns: MappingNamespace | None = None, + type_params: tuple[Any, ...] | None = None, +) -> Any: + if sys.version_info >= (3, 14): + # Starting in 3.14, `_eval_type()` does *not* apply `_type_convert()` + # anymore. This means the `None` -> `type(None)` conversion does not apply: + evaluated = typing._eval_type( # type: ignore + value, + globalns, + localns, + type_params=type_params, + # This is relevant when evaluating types from `TypedDict` classes, where string annotations + # are automatically converted to `ForwardRef` instances with a module set. In this case, + # Our `globalns` is irrelevant and we need to indicate `typing._eval_type()` that it should + # infer it from the `ForwardRef.__forward_module__` attribute instead (`typing.get_type_hints()` + # does the same). Note that this would probably be unnecessary if we properly iterated over the + # `__orig_bases__` for TypedDicts in `get_cls_type_hints()`: + prefer_fwd_module=True, + ) + if evaluated is None: + evaluated = type(None) + return evaluated + elif sys.version_info >= (3, 13): + return typing._eval_type( # type: ignore + value, globalns, localns, type_params=type_params + ) + else: + return typing._eval_type( # type: ignore + value, globalns, localns + ) + + +def is_backport_fixable_error(e: TypeError) -> bool: + msg = str(e) + + return sys.version_info < (3, 10) and msg.startswith('unsupported operand type(s) for |: ') + + +def get_function_type_hints( + function: Callable[..., Any], + *, + include_keys: set[str] | None = None, + globalns: GlobalsNamespace | None = None, + localns: MappingNamespace | None = None, +) -> dict[str, Any]: + """Return type hints for a function. + + This is similar to the `typing.get_type_hints` function, with a few differences: + - Support `functools.partial` by using the underlying `func` attribute. + - Do not wrap type annotation of a parameter with `Optional` if it has a default value of `None` + (related bug: https://github.com/python/cpython/issues/90353, only fixed in 3.11+). + """ + try: + if isinstance(function, partial): + annotations = function.func.__annotations__ + else: + annotations = function.__annotations__ + except AttributeError: + # Some functions (e.g. builtins) don't have annotations: + return {} + + if globalns is None: + globalns = get_module_ns_of(function) + type_params: tuple[Any, ...] | None = None + if localns is None: + # If localns was specified, it is assumed to already contain type params. This is because + # Pydantic has more advanced logic to do so (see `_namespace_utils.ns_for_function`). + type_params = getattr(function, '__type_params__', ()) + + type_hints = {} + for name, value in annotations.items(): + if include_keys is not None and name not in include_keys: + continue + if value is None: + value = NoneType + elif isinstance(value, str): + value = _make_forward_ref(value) + + type_hints[name] = eval_type_backport(value, globalns, localns, type_params) + + return type_hints + + +# TODO use typing.ForwardRef directly when we stop supporting 3.9: +if sys.version_info < (3, 9, 8) or (3, 10) <= sys.version_info < (3, 10, 1): + + def _make_forward_ref( + arg: Any, + is_argument: bool = True, + *, + is_class: bool = False, + ) -> typing.ForwardRef: + """Wrapper for ForwardRef that accounts for the `is_class` argument missing in older versions. + The `module` argument is omitted as it breaks <3.9.8, =3.10.0 and isn't used in the calls below. + + See https://github.com/python/cpython/pull/28560 for some background. + The backport happened on 3.9.8, see: + https://github.com/pydantic/pydantic/discussions/6244#discussioncomment-6275458, + and on 3.10.1 for the 3.10 branch, see: + https://github.com/pydantic/pydantic/issues/6912 + + Implemented as EAFP with memory. + """ + return typing.ForwardRef(arg, is_argument) # pyright: ignore[reportCallIssue] + +else: + _make_forward_ref = typing.ForwardRef # pyright: ignore[reportAssignmentType] + + +if sys.version_info >= (3, 10): + get_type_hints = typing.get_type_hints + +else: + """ + For older versions of python, we have a custom implementation of `get_type_hints` which is a close as possible to + the implementation in CPython 3.10.8. + """ + + @typing.no_type_check + def get_type_hints( # noqa: C901 + obj: Any, + globalns: dict[str, Any] | None = None, + localns: dict[str, Any] | None = None, + include_extras: bool = False, + ) -> dict[str, Any]: # pragma: no cover + """Taken verbatim from python 3.10.8 unchanged, except: + * type annotations of the function definition above. + * prefixing `typing.` where appropriate + * Use `_make_forward_ref` instead of `typing.ForwardRef` to handle the `is_class` argument. + + https://github.com/python/cpython/blob/aaaf5174241496afca7ce4d4584570190ff972fe/Lib/typing.py#L1773-L1875 + + DO NOT CHANGE THIS METHOD UNLESS ABSOLUTELY NECESSARY. + ====================================================== + + Return type hints for an object. + + This is often the same as obj.__annotations__, but it handles + forward references encoded as string literals, adds Optional[t] if a + default value equal to None is set and recursively replaces all + 'Annotated[T, ...]' with 'T' (unless 'include_extras=True'). + + The argument may be a module, class, method, or function. The annotations + are returned as a dictionary. For classes, annotations include also + inherited members. + + TypeError is raised if the argument is not of a type that can contain + annotations, and an empty dictionary is returned if no annotations are + present. + + BEWARE -- the behavior of globalns and localns is counterintuitive + (unless you are familiar with how eval() and exec() work). The + search order is locals first, then globals. + + - If no dict arguments are passed, an attempt is made to use the + globals from obj (or the respective module's globals for classes), + and these are also used as the locals. If the object does not appear + to have globals, an empty dictionary is used. For classes, the search + order is globals first then locals. + + - If one dict argument is passed, it is used for both globals and + locals. + + - If two dict arguments are passed, they specify globals and + locals, respectively. + """ + if getattr(obj, '__no_type_check__', None): + return {} + # Classes require a special treatment. + if isinstance(obj, type): + hints = {} + for base in reversed(obj.__mro__): + if globalns is None: + base_globals = getattr(sys.modules.get(base.__module__, None), '__dict__', {}) + else: + base_globals = globalns + ann = base.__dict__.get('__annotations__', {}) + if isinstance(ann, types.GetSetDescriptorType): + ann = {} + base_locals = dict(vars(base)) if localns is None else localns + if localns is None and globalns is None: + # This is surprising, but required. Before Python 3.10, + # get_type_hints only evaluated the globalns of + # a class. To maintain backwards compatibility, we reverse + # the globalns and localns order so that eval() looks into + # *base_globals* first rather than *base_locals*. + # This only affects ForwardRefs. + base_globals, base_locals = base_locals, base_globals + for name, value in ann.items(): + if value is None: + value = type(None) + if isinstance(value, str): + value = _make_forward_ref(value, is_argument=False, is_class=True) + + value = eval_type_backport(value, base_globals, base_locals) + hints[name] = value + if not include_extras and hasattr(typing, '_strip_annotations'): + return { + k: typing._strip_annotations(t) # type: ignore + for k, t in hints.items() + } + else: + return hints + + if globalns is None: + if isinstance(obj, types.ModuleType): + globalns = obj.__dict__ + else: + nsobj = obj + # Find globalns for the unwrapped object. + while hasattr(nsobj, '__wrapped__'): + nsobj = nsobj.__wrapped__ + globalns = getattr(nsobj, '__globals__', {}) + if localns is None: + localns = globalns + elif localns is None: + localns = globalns + hints = getattr(obj, '__annotations__', None) + if hints is None: + # Return empty annotations for something that _could_ have them. + if isinstance(obj, typing._allowed_types): # type: ignore + return {} + else: + raise TypeError(f'{obj!r} is not a module, class, method, or function.') + defaults = typing._get_defaults(obj) # type: ignore + hints = dict(hints) + for name, value in hints.items(): + if value is None: + value = type(None) + if isinstance(value, str): + # class-level forward refs were handled above, this must be either + # a module-level annotation or a function argument annotation + + value = _make_forward_ref( + value, + is_argument=not isinstance(obj, types.ModuleType), + is_class=False, + ) + value = eval_type_backport(value, globalns, localns) + if name in defaults and defaults[name] is None: + value = typing.Optional[value] + hints[name] = value + return hints if include_extras else {k: typing._strip_annotations(t) for k, t in hints.items()} # type: ignore diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_utils.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_utils.py new file mode 100644 index 0000000..7eae1b7 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_utils.py @@ -0,0 +1,446 @@ +"""Bucket of reusable internal utilities. + +This should be reduced as much as possible with functions only used in one place, moved to that place. +""" + +from __future__ import annotations as _annotations + +import dataclasses +import keyword +import sys +import warnings +import weakref +from collections import OrderedDict, defaultdict, deque +from collections.abc import Callable, Iterable, Mapping +from collections.abc import Set as AbstractSet +from copy import deepcopy +from functools import cached_property +from inspect import Parameter +from itertools import zip_longest +from types import BuiltinFunctionType, CodeType, FunctionType, GeneratorType, LambdaType, ModuleType +from typing import TYPE_CHECKING, Any, Generic, TypeVar, overload + +from pydantic_core import MISSING +from typing_extensions import TypeAlias, TypeGuard, deprecated + +from pydantic import PydanticDeprecatedSince211 + +from . import _repr, _typing_extra +from ._import_utils import import_cached_base_model + +if TYPE_CHECKING: + # TODO remove type error comments when we drop support for Python 3.9 + MappingIntStrAny: TypeAlias = Mapping[int, Any] | Mapping[str, Any] # pyright: ignore[reportGeneralTypeIssues] + AbstractSetIntStr: TypeAlias = AbstractSet[int] | AbstractSet[str] # pyright: ignore[reportGeneralTypeIssues] + from ..main import BaseModel + + +# these are types that are returned unchanged by deepcopy +IMMUTABLE_NON_COLLECTIONS_TYPES: set[type[Any]] = { + int, + float, + complex, + str, + bool, + bytes, + type, + _typing_extra.NoneType, + FunctionType, + BuiltinFunctionType, + LambdaType, + weakref.ref, + CodeType, + # note: including ModuleType will differ from behaviour of deepcopy by not producing error. + # It might be not a good idea in general, but considering that this function used only internally + # against default values of fields, this will allow to actually have a field with module as default value + ModuleType, + NotImplemented.__class__, + Ellipsis.__class__, +} + +# these are types that if empty, might be copied with simple copy() instead of deepcopy() +BUILTIN_COLLECTIONS: set[type[Any]] = { + list, + set, + tuple, + frozenset, + dict, + OrderedDict, + defaultdict, + deque, +} + + +def can_be_positional(param: Parameter) -> bool: + """Return whether the parameter accepts a positional argument. + + ```python {test="skip" lint="skip"} + def func(a, /, b, *, c): + pass + + params = inspect.signature(func).parameters + can_be_positional(params['a']) + #> True + can_be_positional(params['b']) + #> True + can_be_positional(params['c']) + #> False + ``` + """ + return param.kind in (Parameter.POSITIONAL_ONLY, Parameter.POSITIONAL_OR_KEYWORD) + + +def sequence_like(v: Any) -> bool: + return isinstance(v, (list, tuple, set, frozenset, GeneratorType, deque)) + + +def lenient_isinstance(o: Any, class_or_tuple: type[Any] | tuple[type[Any], ...] | None) -> bool: # pragma: no cover + try: + return isinstance(o, class_or_tuple) # type: ignore[arg-type] + except TypeError: + return False + + +def lenient_issubclass(cls: Any, class_or_tuple: Any) -> bool: # pragma: no cover + try: + return isinstance(cls, type) and issubclass(cls, class_or_tuple) + except TypeError: + if isinstance(cls, _typing_extra.WithArgsTypes): + return False + raise # pragma: no cover + + +def is_model_class(cls: Any) -> TypeGuard[type[BaseModel]]: + """Returns true if cls is a _proper_ subclass of BaseModel, and provides proper type-checking, + unlike raw calls to lenient_issubclass. + """ + BaseModel = import_cached_base_model() + + return lenient_issubclass(cls, BaseModel) and cls is not BaseModel + + +def is_valid_identifier(identifier: str) -> bool: + """Checks that a string is a valid identifier and not a Python keyword. + :param identifier: The identifier to test. + :return: True if the identifier is valid. + """ + return identifier.isidentifier() and not keyword.iskeyword(identifier) + + +KeyType = TypeVar('KeyType') + + +def deep_update(mapping: dict[KeyType, Any], *updating_mappings: dict[KeyType, Any]) -> dict[KeyType, Any]: + updated_mapping = mapping.copy() + for updating_mapping in updating_mappings: + for k, v in updating_mapping.items(): + if k in updated_mapping and isinstance(updated_mapping[k], dict) and isinstance(v, dict): + updated_mapping[k] = deep_update(updated_mapping[k], v) + else: + updated_mapping[k] = v + return updated_mapping + + +def update_not_none(mapping: dict[Any, Any], **update: Any) -> None: + mapping.update({k: v for k, v in update.items() if v is not None}) + + +T = TypeVar('T') + + +def unique_list( + input_list: list[T] | tuple[T, ...], + *, + name_factory: Callable[[T], str] = str, +) -> list[T]: + """Make a list unique while maintaining order. + We update the list if another one with the same name is set + (e.g. model validator overridden in subclass). + """ + result: list[T] = [] + result_names: list[str] = [] + for v in input_list: + v_name = name_factory(v) + if v_name not in result_names: + result_names.append(v_name) + result.append(v) + else: + result[result_names.index(v_name)] = v + + return result + + +class ValueItems(_repr.Representation): + """Class for more convenient calculation of excluded or included fields on values.""" + + __slots__ = ('_items', '_type') + + def __init__(self, value: Any, items: AbstractSetIntStr | MappingIntStrAny) -> None: + items = self._coerce_items(items) + + if isinstance(value, (list, tuple)): + items = self._normalize_indexes(items, len(value)) # type: ignore + + self._items: MappingIntStrAny = items # type: ignore + + def is_excluded(self, item: Any) -> bool: + """Check if item is fully excluded. + + :param item: key or index of a value + """ + return self.is_true(self._items.get(item)) + + def is_included(self, item: Any) -> bool: + """Check if value is contained in self._items. + + :param item: key or index of value + """ + return item in self._items + + def for_element(self, e: int | str) -> AbstractSetIntStr | MappingIntStrAny | None: + """:param e: key or index of element on value + :return: raw values for element if self._items is dict and contain needed element + """ + item = self._items.get(e) # type: ignore + return item if not self.is_true(item) else None + + def _normalize_indexes(self, items: MappingIntStrAny, v_length: int) -> dict[int | str, Any]: + """:param items: dict or set of indexes which will be normalized + :param v_length: length of sequence indexes of which will be + + >>> self._normalize_indexes({0: True, -2: True, -1: True}, 4) + {0: True, 2: True, 3: True} + >>> self._normalize_indexes({'__all__': True}, 4) + {0: True, 1: True, 2: True, 3: True} + """ + normalized_items: dict[int | str, Any] = {} + all_items = None + for i, v in items.items(): + if not (isinstance(v, Mapping) or isinstance(v, AbstractSet) or self.is_true(v)): + raise TypeError(f'Unexpected type of exclude value for index "{i}" {v.__class__}') + if i == '__all__': + all_items = self._coerce_value(v) + continue + if not isinstance(i, int): + raise TypeError( + 'Excluding fields from a sequence of sub-models or dicts must be performed index-wise: ' + 'expected integer keys or keyword "__all__"' + ) + normalized_i = v_length + i if i < 0 else i + normalized_items[normalized_i] = self.merge(v, normalized_items.get(normalized_i)) + + if not all_items: + return normalized_items + if self.is_true(all_items): + for i in range(v_length): + normalized_items.setdefault(i, ...) + return normalized_items + for i in range(v_length): + normalized_item = normalized_items.setdefault(i, {}) + if not self.is_true(normalized_item): + normalized_items[i] = self.merge(all_items, normalized_item) + return normalized_items + + @classmethod + def merge(cls, base: Any, override: Any, intersect: bool = False) -> Any: + """Merge a `base` item with an `override` item. + + Both `base` and `override` are converted to dictionaries if possible. + Sets are converted to dictionaries with the sets entries as keys and + Ellipsis as values. + + Each key-value pair existing in `base` is merged with `override`, + while the rest of the key-value pairs are updated recursively with this function. + + Merging takes place based on the "union" of keys if `intersect` is + set to `False` (default) and on the intersection of keys if + `intersect` is set to `True`. + """ + override = cls._coerce_value(override) + base = cls._coerce_value(base) + if override is None: + return base + if cls.is_true(base) or base is None: + return override + if cls.is_true(override): + return base if intersect else override + + # intersection or union of keys while preserving ordering: + if intersect: + merge_keys = [k for k in base if k in override] + [k for k in override if k in base] + else: + merge_keys = list(base) + [k for k in override if k not in base] + + merged: dict[int | str, Any] = {} + for k in merge_keys: + merged_item = cls.merge(base.get(k), override.get(k), intersect=intersect) + if merged_item is not None: + merged[k] = merged_item + + return merged + + @staticmethod + def _coerce_items(items: AbstractSetIntStr | MappingIntStrAny) -> MappingIntStrAny: + if isinstance(items, Mapping): + pass + elif isinstance(items, AbstractSet): + items = dict.fromkeys(items, ...) # type: ignore + else: + class_name = getattr(items, '__class__', '???') + raise TypeError(f'Unexpected type of exclude value {class_name}') + return items # type: ignore + + @classmethod + def _coerce_value(cls, value: Any) -> Any: + if value is None or cls.is_true(value): + return value + return cls._coerce_items(value) + + @staticmethod + def is_true(v: Any) -> bool: + return v is True or v is ... + + def __repr_args__(self) -> _repr.ReprArgs: + return [(None, self._items)] + + +if TYPE_CHECKING: + + def LazyClassAttribute(name: str, get_value: Callable[[], T]) -> T: ... + +else: + + class LazyClassAttribute: + """A descriptor exposing an attribute only accessible on a class (hidden from instances). + + The attribute is lazily computed and cached during the first access. + """ + + def __init__(self, name: str, get_value: Callable[[], Any]) -> None: + self.name = name + self.get_value = get_value + + @cached_property + def value(self) -> Any: + return self.get_value() + + def __get__(self, instance: Any, owner: type[Any]) -> None: + if instance is None: + return self.value + raise AttributeError(f'{self.name!r} attribute of {owner.__name__!r} is class-only') + + +Obj = TypeVar('Obj') + + +def smart_deepcopy(obj: Obj) -> Obj: + """Return type as is for immutable built-in types + Use obj.copy() for built-in empty collections + Use copy.deepcopy() for non-empty collections and unknown objects. + """ + if obj is MISSING: + return obj # pyright: ignore[reportReturnType] + obj_type = obj.__class__ + if obj_type in IMMUTABLE_NON_COLLECTIONS_TYPES: + return obj # fastest case: obj is immutable and not collection therefore will not be copied anyway + try: + if not obj and obj_type in BUILTIN_COLLECTIONS: + # faster way for empty collections, no need to copy its members + return obj if obj_type is tuple else obj.copy() # tuple doesn't have copy method # type: ignore + except (TypeError, ValueError, RuntimeError): + # do we really dare to catch ALL errors? Seems a bit risky + pass + + return deepcopy(obj) # slowest way when we actually might need a deepcopy + + +_SENTINEL = object() + + +def all_identical(left: Iterable[Any], right: Iterable[Any]) -> bool: + """Check that the items of `left` are the same objects as those in `right`. + + >>> a, b = object(), object() + >>> all_identical([a, b, a], [a, b, a]) + True + >>> all_identical([a, b, [a]], [a, b, [a]]) # new list object, while "equal" is not "identical" + False + """ + for left_item, right_item in zip_longest(left, right, fillvalue=_SENTINEL): + if left_item is not right_item: + return False + return True + + +def get_first_not_none(a: Any, b: Any) -> Any: + """Return the first argument if it is not `None`, otherwise return the second argument.""" + return a if a is not None else b + + +@dataclasses.dataclass(frozen=True) +class SafeGetItemProxy: + """Wrapper redirecting `__getitem__` to `get` with a sentinel value as default + + This makes is safe to use in `operator.itemgetter` when some keys may be missing + """ + + # Define __slots__manually for performances + # @dataclasses.dataclass() only support slots=True in python>=3.10 + __slots__ = ('wrapped',) + + wrapped: Mapping[str, Any] + + def __getitem__(self, key: str, /) -> Any: + return self.wrapped.get(key, _SENTINEL) + + # required to pass the object to operator.itemgetter() instances due to a quirk of typeshed + # https://github.com/python/mypy/issues/13713 + # https://github.com/python/typeshed/pull/8785 + # Since this is typing-only, hide it in a typing.TYPE_CHECKING block + if TYPE_CHECKING: + + def __contains__(self, key: str, /) -> bool: + return self.wrapped.__contains__(key) + + +_ModelT = TypeVar('_ModelT', bound='BaseModel') +_RT = TypeVar('_RT') + + +class deprecated_instance_property(Generic[_ModelT, _RT]): + """A decorator exposing the decorated class method as a property, with a warning on instance access. + + This decorator takes a class method defined on the `BaseModel` class and transforms it into + an attribute. The attribute can be accessed on both the class and instances of the class. If accessed + via an instance, a deprecation warning is emitted stating that instance access will be removed in V3. + """ + + def __init__(self, fget: Callable[[type[_ModelT]], _RT], /) -> None: + # Note: fget should be a classmethod: + self.fget = fget + + @overload + def __get__(self, instance: None, objtype: type[_ModelT]) -> _RT: ... + @overload + @deprecated( + 'Accessing this attribute on the instance is deprecated, and will be removed in Pydantic V3. ' + 'Instead, you should access this attribute from the model class.', + category=None, + ) + def __get__(self, instance: _ModelT, objtype: type[_ModelT]) -> _RT: ... + def __get__(self, instance: _ModelT | None, objtype: type[_ModelT]) -> _RT: + if instance is not None: + # fmt: off + attr_name = ( + self.fget.__name__ + if sys.version_info >= (3, 10) + else self.fget.__func__.__name__ # pyright: ignore[reportFunctionMemberAccess] + ) + # fmt: on + warnings.warn( + f'Accessing the {attr_name!r} attribute on the instance is deprecated. ' + 'Instead, you should access this attribute from the model class.', + category=PydanticDeprecatedSince211, + stacklevel=2, + ) + return self.fget.__get__(instance, objtype)() diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_validate_call.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_validate_call.py new file mode 100644 index 0000000..ab82832 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_validate_call.py @@ -0,0 +1,140 @@ +from __future__ import annotations as _annotations + +import functools +import inspect +from collections.abc import Awaitable +from functools import partial +from typing import Any, Callable + +import pydantic_core + +from ..config import ConfigDict +from ..plugin._schema_validator import create_schema_validator +from ._config import ConfigWrapper +from ._generate_schema import GenerateSchema, ValidateCallSupportedTypes +from ._namespace_utils import MappingNamespace, NsResolver, ns_for_function + + +def extract_function_name(func: ValidateCallSupportedTypes) -> str: + """Extract the name of a `ValidateCallSupportedTypes` object.""" + return f'partial({func.func.__name__})' if isinstance(func, functools.partial) else func.__name__ + + +def extract_function_qualname(func: ValidateCallSupportedTypes) -> str: + """Extract the qualname of a `ValidateCallSupportedTypes` object.""" + return f'partial({func.func.__qualname__})' if isinstance(func, functools.partial) else func.__qualname__ + + +def update_wrapper_attributes(wrapped: ValidateCallSupportedTypes, wrapper: Callable[..., Any]): + """Update the `wrapper` function with the attributes of the `wrapped` function. Return the updated function.""" + if inspect.iscoroutinefunction(wrapped): + + @functools.wraps(wrapped) + async def wrapper_function(*args, **kwargs): # type: ignore + return await wrapper(*args, **kwargs) + else: + + @functools.wraps(wrapped) + def wrapper_function(*args, **kwargs): + return wrapper(*args, **kwargs) + + # We need to manually update this because `partial` object has no `__name__` and `__qualname__`. + wrapper_function.__name__ = extract_function_name(wrapped) + wrapper_function.__qualname__ = extract_function_qualname(wrapped) + wrapper_function.raw_function = wrapped # type: ignore + + return wrapper_function + + +class ValidateCallWrapper: + """This is a wrapper around a function that validates the arguments passed to it, and optionally the return value.""" + + __slots__ = ( + 'function', + 'validate_return', + 'schema_type', + 'module', + 'qualname', + 'ns_resolver', + 'config_wrapper', + '__pydantic_complete__', + '__pydantic_validator__', + '__return_pydantic_validator__', + ) + + def __init__( + self, + function: ValidateCallSupportedTypes, + config: ConfigDict | None, + validate_return: bool, + parent_namespace: MappingNamespace | None, + ) -> None: + self.function = function + self.validate_return = validate_return + if isinstance(function, partial): + self.schema_type = function.func + self.module = function.func.__module__ + else: + self.schema_type = function + self.module = function.__module__ + self.qualname = extract_function_qualname(function) + + self.ns_resolver = NsResolver( + namespaces_tuple=ns_for_function(self.schema_type, parent_namespace=parent_namespace) + ) + self.config_wrapper = ConfigWrapper(config) + if not self.config_wrapper.defer_build: + self._create_validators() + else: + self.__pydantic_complete__ = False + + def _create_validators(self) -> None: + gen_schema = GenerateSchema(self.config_wrapper, self.ns_resolver) + schema = gen_schema.clean_schema(gen_schema.generate_schema(self.function)) + core_config = self.config_wrapper.core_config(title=self.qualname) + + self.__pydantic_validator__ = create_schema_validator( + schema, + self.schema_type, + self.module, + self.qualname, + 'validate_call', + core_config, + self.config_wrapper.plugin_settings, + ) + if self.validate_return: + signature = inspect.signature(self.function) + return_type = signature.return_annotation if signature.return_annotation is not signature.empty else Any + gen_schema = GenerateSchema(self.config_wrapper, self.ns_resolver) + schema = gen_schema.clean_schema(gen_schema.generate_schema(return_type)) + validator = create_schema_validator( + schema, + self.schema_type, + self.module, + self.qualname, + 'validate_call', + core_config, + self.config_wrapper.plugin_settings, + ) + if inspect.iscoroutinefunction(self.function): + + async def return_val_wrapper(aw: Awaitable[Any]) -> None: + return validator.validate_python(await aw) + + self.__return_pydantic_validator__ = return_val_wrapper + else: + self.__return_pydantic_validator__ = validator.validate_python + else: + self.__return_pydantic_validator__ = None + + self.__pydantic_complete__ = True + + def __call__(self, *args: Any, **kwargs: Any) -> Any: + if not self.__pydantic_complete__: + self._create_validators() + + res = self.__pydantic_validator__.validate_python(pydantic_core.ArgsKwargs(args, kwargs)) + if self.__return_pydantic_validator__: + return self.__return_pydantic_validator__(res) + else: + return res diff --git a/backend/.venv/Lib/site-packages/pydantic/_internal/_validators.py b/backend/.venv/Lib/site-packages/pydantic/_internal/_validators.py new file mode 100644 index 0000000..2c7fab6 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_internal/_validators.py @@ -0,0 +1,533 @@ +"""Validator functions for standard library types. + +Import of this module is deferred since it contains imports of many standard library modules. +""" + +from __future__ import annotations as _annotations + +import collections.abc +import math +import re +import typing +from collections.abc import Sequence +from decimal import Decimal +from fractions import Fraction +from ipaddress import IPv4Address, IPv4Interface, IPv4Network, IPv6Address, IPv6Interface, IPv6Network +from typing import Any, Callable, TypeVar, Union, cast +from zoneinfo import ZoneInfo, ZoneInfoNotFoundError + +import typing_extensions +from pydantic_core import PydanticCustomError, PydanticKnownError, core_schema +from typing_extensions import get_args, get_origin +from typing_inspection import typing_objects + +from pydantic._internal._import_utils import import_cached_field_info +from pydantic.errors import PydanticSchemaGenerationError + + +def sequence_validator( + input_value: Sequence[Any], + /, + validator: core_schema.ValidatorFunctionWrapHandler, +) -> Sequence[Any]: + """Validator for `Sequence` types, isinstance(v, Sequence) has already been called.""" + value_type = type(input_value) + + # We don't accept any plain string as a sequence + # Relevant issue: https://github.com/pydantic/pydantic/issues/5595 + if issubclass(value_type, (str, bytes)): + raise PydanticCustomError( + 'sequence_str', + "'{type_name}' instances are not allowed as a Sequence value", + {'type_name': value_type.__name__}, + ) + + # TODO: refactor sequence validation to validate with either a list or a tuple + # schema, depending on the type of the value. + # Additionally, we should be able to remove one of either this validator or the + # SequenceValidator in _std_types_schema.py (preferably this one, while porting over some logic). + # Effectively, a refactor for sequence validation is needed. + if value_type is tuple: + input_value = list(input_value) + + v_list = validator(input_value) + + # the rest of the logic is just re-creating the original type from `v_list` + if value_type is list: + return v_list + elif issubclass(value_type, range): + # return the list as we probably can't re-create the range + return v_list + elif value_type is tuple: + return tuple(v_list) + else: + # best guess at how to re-create the original type, more custom construction logic might be required + return value_type(v_list) # type: ignore[call-arg] + + +def import_string(value: Any) -> Any: + if isinstance(value, str): + try: + return _import_string_logic(value) + except ImportError as e: + raise PydanticCustomError('import_error', 'Invalid python path: {error}', {'error': str(e)}) from e + else: + # otherwise we just return the value and let the next validator do the rest of the work + return value + + +def _import_string_logic(dotted_path: str) -> Any: + """Inspired by uvicorn — dotted paths should include a colon before the final item if that item is not a module. + (This is necessary to distinguish between a submodule and an attribute when there is a conflict.). + + If the dotted path does not include a colon and the final item is not a valid module, importing as an attribute + rather than a submodule will be attempted automatically. + + So, for example, the following values of `dotted_path` result in the following returned values: + * 'collections': + * 'collections.abc': + * 'collections.abc:Mapping': + * `collections.abc.Mapping`: (though this is a bit slower than the previous line) + + An error will be raised under any of the following scenarios: + * `dotted_path` contains more than one colon (e.g., 'collections:abc:Mapping') + * the substring of `dotted_path` before the colon is not a valid module in the environment (e.g., '123:Mapping') + * the substring of `dotted_path` after the colon is not an attribute of the module (e.g., 'collections:abc123') + """ + from importlib import import_module + + components = dotted_path.strip().split(':') + if len(components) > 2: + raise ImportError(f"Import strings should have at most one ':'; received {dotted_path!r}") + + module_path = components[0] + if not module_path: + raise ImportError(f'Import strings should have a nonempty module name; received {dotted_path!r}') + + try: + module = import_module(module_path) + except ModuleNotFoundError as e: + if '.' in module_path: + # Check if it would be valid if the final item was separated from its module with a `:` + maybe_module_path, maybe_attribute = dotted_path.strip().rsplit('.', 1) + try: + return _import_string_logic(f'{maybe_module_path}:{maybe_attribute}') + except ImportError: + pass + raise ImportError(f'No module named {module_path!r}') from e + raise e + + if len(components) > 1: + attribute = components[1] + try: + return getattr(module, attribute) + except AttributeError as e: + raise ImportError(f'cannot import name {attribute!r} from {module_path!r}') from e + else: + return module + + +def pattern_either_validator(input_value: Any, /) -> re.Pattern[Any]: + if isinstance(input_value, re.Pattern): + return input_value + elif isinstance(input_value, (str, bytes)): + # todo strict mode + return compile_pattern(input_value) # type: ignore + else: + raise PydanticCustomError('pattern_type', 'Input should be a valid pattern') + + +def pattern_str_validator(input_value: Any, /) -> re.Pattern[str]: + if isinstance(input_value, re.Pattern): + if isinstance(input_value.pattern, str): + return input_value + else: + raise PydanticCustomError('pattern_str_type', 'Input should be a string pattern') + elif isinstance(input_value, str): + return compile_pattern(input_value) + elif isinstance(input_value, bytes): + raise PydanticCustomError('pattern_str_type', 'Input should be a string pattern') + else: + raise PydanticCustomError('pattern_type', 'Input should be a valid pattern') + + +def pattern_bytes_validator(input_value: Any, /) -> re.Pattern[bytes]: + if isinstance(input_value, re.Pattern): + if isinstance(input_value.pattern, bytes): + return input_value + else: + raise PydanticCustomError('pattern_bytes_type', 'Input should be a bytes pattern') + elif isinstance(input_value, bytes): + return compile_pattern(input_value) + elif isinstance(input_value, str): + raise PydanticCustomError('pattern_bytes_type', 'Input should be a bytes pattern') + else: + raise PydanticCustomError('pattern_type', 'Input should be a valid pattern') + + +PatternType = TypeVar('PatternType', str, bytes) + + +def compile_pattern(pattern: PatternType) -> re.Pattern[PatternType]: + try: + return re.compile(pattern) + except re.error: + raise PydanticCustomError('pattern_regex', 'Input should be a valid regular expression') + + +def ip_v4_address_validator(input_value: Any, /) -> IPv4Address: + if isinstance(input_value, IPv4Address): + return input_value + + try: + return IPv4Address(input_value) + except ValueError: + raise PydanticCustomError('ip_v4_address', 'Input is not a valid IPv4 address') + + +def ip_v6_address_validator(input_value: Any, /) -> IPv6Address: + if isinstance(input_value, IPv6Address): + return input_value + + try: + return IPv6Address(input_value) + except ValueError: + raise PydanticCustomError('ip_v6_address', 'Input is not a valid IPv6 address') + + +def ip_v4_network_validator(input_value: Any, /) -> IPv4Network: + """Assume IPv4Network initialised with a default `strict` argument. + + See more: + https://docs.python.org/library/ipaddress.html#ipaddress.IPv4Network + """ + if isinstance(input_value, IPv4Network): + return input_value + + try: + return IPv4Network(input_value) + except ValueError: + raise PydanticCustomError('ip_v4_network', 'Input is not a valid IPv4 network') + + +def ip_v6_network_validator(input_value: Any, /) -> IPv6Network: + """Assume IPv6Network initialised with a default `strict` argument. + + See more: + https://docs.python.org/library/ipaddress.html#ipaddress.IPv6Network + """ + if isinstance(input_value, IPv6Network): + return input_value + + try: + return IPv6Network(input_value) + except ValueError: + raise PydanticCustomError('ip_v6_network', 'Input is not a valid IPv6 network') + + +def ip_v4_interface_validator(input_value: Any, /) -> IPv4Interface: + if isinstance(input_value, IPv4Interface): + return input_value + + try: + return IPv4Interface(input_value) + except ValueError: + raise PydanticCustomError('ip_v4_interface', 'Input is not a valid IPv4 interface') + + +def ip_v6_interface_validator(input_value: Any, /) -> IPv6Interface: + if isinstance(input_value, IPv6Interface): + return input_value + + try: + return IPv6Interface(input_value) + except ValueError: + raise PydanticCustomError('ip_v6_interface', 'Input is not a valid IPv6 interface') + + +def fraction_validator(input_value: Any, /) -> Fraction: + if isinstance(input_value, Fraction): + return input_value + + try: + return Fraction(input_value) + except ValueError: + raise PydanticCustomError('fraction_parsing', 'Input is not a valid fraction') + + +def forbid_inf_nan_check(x: Any) -> Any: + if not math.isfinite(x): + raise PydanticKnownError('finite_number') + return x + + +def _safe_repr(v: Any) -> int | float | str: + """The context argument for `PydanticKnownError` requires a number or str type, so we do a simple repr() coercion for types like timedelta. + + See tests/test_types.py::test_annotated_metadata_any_order for some context. + """ + if isinstance(v, (int, float, str)): + return v + return repr(v) + + +def greater_than_validator(x: Any, gt: Any) -> Any: + try: + if not (x > gt): + raise PydanticKnownError('greater_than', {'gt': _safe_repr(gt)}) + return x + except TypeError: + raise TypeError(f"Unable to apply constraint 'gt' to supplied value {x}") + + +def greater_than_or_equal_validator(x: Any, ge: Any) -> Any: + try: + if not (x >= ge): + raise PydanticKnownError('greater_than_equal', {'ge': _safe_repr(ge)}) + return x + except TypeError: + raise TypeError(f"Unable to apply constraint 'ge' to supplied value {x}") + + +def less_than_validator(x: Any, lt: Any) -> Any: + try: + if not (x < lt): + raise PydanticKnownError('less_than', {'lt': _safe_repr(lt)}) + return x + except TypeError: + raise TypeError(f"Unable to apply constraint 'lt' to supplied value {x}") + + +def less_than_or_equal_validator(x: Any, le: Any) -> Any: + try: + if not (x <= le): + raise PydanticKnownError('less_than_equal', {'le': _safe_repr(le)}) + return x + except TypeError: + raise TypeError(f"Unable to apply constraint 'le' to supplied value {x}") + + +def multiple_of_validator(x: Any, multiple_of: Any) -> Any: + try: + if x % multiple_of: + raise PydanticKnownError('multiple_of', {'multiple_of': _safe_repr(multiple_of)}) + return x + except TypeError: + raise TypeError(f"Unable to apply constraint 'multiple_of' to supplied value {x}") + + +def min_length_validator(x: Any, min_length: Any) -> Any: + try: + if not (len(x) >= min_length): + raise PydanticKnownError( + 'too_short', {'field_type': 'Value', 'min_length': min_length, 'actual_length': len(x)} + ) + return x + except TypeError: + raise TypeError(f"Unable to apply constraint 'min_length' to supplied value {x}") + + +def max_length_validator(x: Any, max_length: Any) -> Any: + try: + if len(x) > max_length: + raise PydanticKnownError( + 'too_long', + {'field_type': 'Value', 'max_length': max_length, 'actual_length': len(x)}, + ) + return x + except TypeError: + raise TypeError(f"Unable to apply constraint 'max_length' to supplied value {x}") + + +def _extract_decimal_digits_info(decimal: Decimal) -> tuple[int, int]: + """Compute the total number of digits and decimal places for a given [`Decimal`][decimal.Decimal] instance. + + This function handles both normalized and non-normalized Decimal instances. + Example: Decimal('1.230') -> 4 digits, 3 decimal places + + Args: + decimal (Decimal): The decimal number to analyze. + + Returns: + tuple[int, int]: A tuple containing the number of decimal places and total digits. + + Though this could be divided into two separate functions, the logic is easier to follow if we couple the computation + of the number of decimals and digits together. + """ + try: + decimal_tuple = decimal.as_tuple() + + assert isinstance(decimal_tuple.exponent, int) + + exponent = decimal_tuple.exponent + num_digits = len(decimal_tuple.digits) + + if exponent >= 0: + # A positive exponent adds that many trailing zeros + # Ex: digit_tuple=(1, 2, 3), exponent=2 -> 12300 -> 0 decimal places, 5 digits + num_digits += exponent + decimal_places = 0 + else: + # If the absolute value of the negative exponent is larger than the + # number of digits, then it's the same as the number of digits, + # because it'll consume all the digits in digit_tuple and then + # add abs(exponent) - len(digit_tuple) leading zeros after the decimal point. + # Ex: digit_tuple=(1, 2, 3), exponent=-2 -> 1.23 -> 2 decimal places, 3 digits + # Ex: digit_tuple=(1, 2, 3), exponent=-4 -> 0.0123 -> 4 decimal places, 4 digits + decimal_places = abs(exponent) + num_digits = max(num_digits, decimal_places) + + return decimal_places, num_digits + except (AssertionError, AttributeError): + raise TypeError(f'Unable to extract decimal digits info from supplied value {decimal}') + + +def max_digits_validator(x: Any, max_digits: Any) -> Any: + try: + _, num_digits = _extract_decimal_digits_info(x) + _, normalized_num_digits = _extract_decimal_digits_info(x.normalize()) + if (num_digits > max_digits) and (normalized_num_digits > max_digits): + raise PydanticKnownError( + 'decimal_max_digits', + {'max_digits': max_digits}, + ) + return x + except TypeError: + raise TypeError(f"Unable to apply constraint 'max_digits' to supplied value {x}") + + +def decimal_places_validator(x: Any, decimal_places: Any) -> Any: + try: + decimal_places_, _ = _extract_decimal_digits_info(x) + if decimal_places_ > decimal_places: + normalized_decimal_places, _ = _extract_decimal_digits_info(x.normalize()) + if normalized_decimal_places > decimal_places: + raise PydanticKnownError( + 'decimal_max_places', + {'decimal_places': decimal_places}, + ) + return x + except TypeError: + raise TypeError(f"Unable to apply constraint 'decimal_places' to supplied value {x}") + + +def deque_validator(input_value: Any, handler: core_schema.ValidatorFunctionWrapHandler) -> collections.deque[Any]: + return collections.deque(handler(input_value), maxlen=getattr(input_value, 'maxlen', None)) + + +def defaultdict_validator( + input_value: Any, handler: core_schema.ValidatorFunctionWrapHandler, default_default_factory: Callable[[], Any] +) -> collections.defaultdict[Any, Any]: + if isinstance(input_value, collections.defaultdict): + default_factory = input_value.default_factory + return collections.defaultdict(default_factory, handler(input_value)) + else: + return collections.defaultdict(default_default_factory, handler(input_value)) + + +def get_defaultdict_default_default_factory(values_source_type: Any) -> Callable[[], Any]: + FieldInfo = import_cached_field_info() + + values_type_origin = get_origin(values_source_type) + + def infer_default() -> Callable[[], Any]: + allowed_default_types: dict[Any, Any] = { + tuple: tuple, + collections.abc.Sequence: tuple, + collections.abc.MutableSequence: list, + list: list, + typing.Sequence: list, + set: set, + typing.MutableSet: set, + collections.abc.MutableSet: set, + collections.abc.Set: frozenset, + typing.MutableMapping: dict, + typing.Mapping: dict, + collections.abc.Mapping: dict, + collections.abc.MutableMapping: dict, + float: float, + int: int, + str: str, + bool: bool, + } + values_type = values_type_origin or values_source_type + instructions = 'set using `DefaultDict[..., Annotated[..., Field(default_factory=...)]]`' + if typing_objects.is_typevar(values_type): + + def type_var_default_factory() -> None: + raise RuntimeError( + 'Generic defaultdict cannot be used without a concrete value type or an' + ' explicit default factory, ' + instructions + ) + + return type_var_default_factory + elif values_type not in allowed_default_types: + # a somewhat subjective set of types that have reasonable default values + allowed_msg = ', '.join([t.__name__ for t in set(allowed_default_types.values())]) + raise PydanticSchemaGenerationError( + f'Unable to infer a default factory for keys of type {values_source_type}.' + f' Only {allowed_msg} are supported, other types require an explicit default factory' + ' ' + instructions + ) + return allowed_default_types[values_type] + + # Assume Annotated[..., Field(...)] + if typing_objects.is_annotated(values_type_origin): + field_info = next((v for v in get_args(values_source_type) if isinstance(v, FieldInfo)), None) + else: + field_info = None + if field_info and field_info.default_factory: + # Assume the default factory does not take any argument: + default_default_factory = cast(Callable[[], Any], field_info.default_factory) + else: + default_default_factory = infer_default() + return default_default_factory + + +def validate_str_is_valid_iana_tz(value: Any, /) -> ZoneInfo: + if isinstance(value, ZoneInfo): + return value + try: + return ZoneInfo(value) + except (ZoneInfoNotFoundError, ValueError, TypeError): + raise PydanticCustomError('zoneinfo_str', 'invalid timezone: {value}', {'value': value}) + + +NUMERIC_VALIDATOR_LOOKUP: dict[str, Callable] = { + 'gt': greater_than_validator, + 'ge': greater_than_or_equal_validator, + 'lt': less_than_validator, + 'le': less_than_or_equal_validator, + 'multiple_of': multiple_of_validator, + 'min_length': min_length_validator, + 'max_length': max_length_validator, + 'max_digits': max_digits_validator, + 'decimal_places': decimal_places_validator, +} + +IpType = Union[IPv4Address, IPv6Address, IPv4Network, IPv6Network, IPv4Interface, IPv6Interface] + +IP_VALIDATOR_LOOKUP: dict[type[IpType], Callable] = { + IPv4Address: ip_v4_address_validator, + IPv6Address: ip_v6_address_validator, + IPv4Network: ip_v4_network_validator, + IPv6Network: ip_v6_network_validator, + IPv4Interface: ip_v4_interface_validator, + IPv6Interface: ip_v6_interface_validator, +} + +MAPPING_ORIGIN_MAP: dict[Any, Any] = { + typing.DefaultDict: collections.defaultdict, # noqa: UP006 + collections.defaultdict: collections.defaultdict, + typing.OrderedDict: collections.OrderedDict, # noqa: UP006 + collections.OrderedDict: collections.OrderedDict, + typing_extensions.OrderedDict: collections.OrderedDict, + typing.Counter: collections.Counter, + collections.Counter: collections.Counter, + # this doesn't handle subclasses of these + typing.Mapping: dict, + typing.MutableMapping: dict, + # parametrized typing.{Mutable}Mapping creates one of these + collections.abc.Mapping: dict, + collections.abc.MutableMapping: dict, +} diff --git a/backend/.venv/Lib/site-packages/pydantic/_migration.py b/backend/.venv/Lib/site-packages/pydantic/_migration.py new file mode 100644 index 0000000..b4ecd28 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/_migration.py @@ -0,0 +1,316 @@ +import sys +from typing import Any, Callable + +from pydantic.warnings import PydanticDeprecatedSince20 + +from .version import version_short + +MOVED_IN_V2 = { + 'pydantic.utils:version_info': 'pydantic.version:version_info', + 'pydantic.error_wrappers:ValidationError': 'pydantic:ValidationError', + 'pydantic.utils:to_camel': 'pydantic.alias_generators:to_pascal', + 'pydantic.utils:to_lower_camel': 'pydantic.alias_generators:to_camel', + 'pydantic:PyObject': 'pydantic.types:ImportString', + 'pydantic.types:PyObject': 'pydantic.types:ImportString', + 'pydantic.generics:GenericModel': 'pydantic.BaseModel', +} + +DEPRECATED_MOVED_IN_V2 = { + 'pydantic.tools:schema_of': 'pydantic.deprecated.tools:schema_of', + 'pydantic.tools:parse_obj_as': 'pydantic.deprecated.tools:parse_obj_as', + 'pydantic.tools:schema_json_of': 'pydantic.deprecated.tools:schema_json_of', + 'pydantic.json:pydantic_encoder': 'pydantic.deprecated.json:pydantic_encoder', + 'pydantic:validate_arguments': 'pydantic.deprecated.decorator:validate_arguments', + 'pydantic.json:custom_pydantic_encoder': 'pydantic.deprecated.json:custom_pydantic_encoder', + 'pydantic.json:timedelta_isoformat': 'pydantic.deprecated.json:timedelta_isoformat', + 'pydantic.decorator:validate_arguments': 'pydantic.deprecated.decorator:validate_arguments', + 'pydantic.class_validators:validator': 'pydantic.deprecated.class_validators:validator', + 'pydantic.class_validators:root_validator': 'pydantic.deprecated.class_validators:root_validator', + 'pydantic.config:BaseConfig': 'pydantic.deprecated.config:BaseConfig', + 'pydantic.config:Extra': 'pydantic.deprecated.config:Extra', +} + +REDIRECT_TO_V1 = { + f'pydantic.utils:{obj}': f'pydantic.v1.utils:{obj}' + for obj in ( + 'deep_update', + 'GetterDict', + 'lenient_issubclass', + 'lenient_isinstance', + 'is_valid_field', + 'update_not_none', + 'import_string', + 'Representation', + 'ROOT_KEY', + 'smart_deepcopy', + 'sequence_like', + ) +} + + +REMOVED_IN_V2 = { + 'pydantic:ConstrainedBytes', + 'pydantic:ConstrainedDate', + 'pydantic:ConstrainedDecimal', + 'pydantic:ConstrainedFloat', + 'pydantic:ConstrainedFrozenSet', + 'pydantic:ConstrainedInt', + 'pydantic:ConstrainedList', + 'pydantic:ConstrainedSet', + 'pydantic:ConstrainedStr', + 'pydantic:JsonWrapper', + 'pydantic:NoneBytes', + 'pydantic:NoneStr', + 'pydantic:NoneStrBytes', + 'pydantic:Protocol', + 'pydantic:Required', + 'pydantic:StrBytes', + 'pydantic:compiled', + 'pydantic.config:get_config', + 'pydantic.config:inherit_config', + 'pydantic.config:prepare_config', + 'pydantic:create_model_from_namedtuple', + 'pydantic:create_model_from_typeddict', + 'pydantic.dataclasses:create_pydantic_model_from_dataclass', + 'pydantic.dataclasses:make_dataclass_validator', + 'pydantic.dataclasses:set_validation', + 'pydantic.datetime_parse:parse_date', + 'pydantic.datetime_parse:parse_time', + 'pydantic.datetime_parse:parse_datetime', + 'pydantic.datetime_parse:parse_duration', + 'pydantic.error_wrappers:ErrorWrapper', + 'pydantic.errors:AnyStrMaxLengthError', + 'pydantic.errors:AnyStrMinLengthError', + 'pydantic.errors:ArbitraryTypeError', + 'pydantic.errors:BoolError', + 'pydantic.errors:BytesError', + 'pydantic.errors:CallableError', + 'pydantic.errors:ClassError', + 'pydantic.errors:ColorError', + 'pydantic.errors:ConfigError', + 'pydantic.errors:DataclassTypeError', + 'pydantic.errors:DateError', + 'pydantic.errors:DateNotInTheFutureError', + 'pydantic.errors:DateNotInThePastError', + 'pydantic.errors:DateTimeError', + 'pydantic.errors:DecimalError', + 'pydantic.errors:DecimalIsNotFiniteError', + 'pydantic.errors:DecimalMaxDigitsError', + 'pydantic.errors:DecimalMaxPlacesError', + 'pydantic.errors:DecimalWholeDigitsError', + 'pydantic.errors:DictError', + 'pydantic.errors:DurationError', + 'pydantic.errors:EmailError', + 'pydantic.errors:EnumError', + 'pydantic.errors:EnumMemberError', + 'pydantic.errors:ExtraError', + 'pydantic.errors:FloatError', + 'pydantic.errors:FrozenSetError', + 'pydantic.errors:FrozenSetMaxLengthError', + 'pydantic.errors:FrozenSetMinLengthError', + 'pydantic.errors:HashableError', + 'pydantic.errors:IPv4AddressError', + 'pydantic.errors:IPv4InterfaceError', + 'pydantic.errors:IPv4NetworkError', + 'pydantic.errors:IPv6AddressError', + 'pydantic.errors:IPv6InterfaceError', + 'pydantic.errors:IPv6NetworkError', + 'pydantic.errors:IPvAnyAddressError', + 'pydantic.errors:IPvAnyInterfaceError', + 'pydantic.errors:IPvAnyNetworkError', + 'pydantic.errors:IntEnumError', + 'pydantic.errors:IntegerError', + 'pydantic.errors:InvalidByteSize', + 'pydantic.errors:InvalidByteSizeUnit', + 'pydantic.errors:InvalidDiscriminator', + 'pydantic.errors:InvalidLengthForBrand', + 'pydantic.errors:JsonError', + 'pydantic.errors:JsonTypeError', + 'pydantic.errors:ListError', + 'pydantic.errors:ListMaxLengthError', + 'pydantic.errors:ListMinLengthError', + 'pydantic.errors:ListUniqueItemsError', + 'pydantic.errors:LuhnValidationError', + 'pydantic.errors:MissingDiscriminator', + 'pydantic.errors:MissingError', + 'pydantic.errors:NoneIsAllowedError', + 'pydantic.errors:NoneIsNotAllowedError', + 'pydantic.errors:NotDigitError', + 'pydantic.errors:NotNoneError', + 'pydantic.errors:NumberNotGeError', + 'pydantic.errors:NumberNotGtError', + 'pydantic.errors:NumberNotLeError', + 'pydantic.errors:NumberNotLtError', + 'pydantic.errors:NumberNotMultipleError', + 'pydantic.errors:PathError', + 'pydantic.errors:PathNotADirectoryError', + 'pydantic.errors:PathNotAFileError', + 'pydantic.errors:PathNotExistsError', + 'pydantic.errors:PatternError', + 'pydantic.errors:PyObjectError', + 'pydantic.errors:PydanticTypeError', + 'pydantic.errors:PydanticValueError', + 'pydantic.errors:SequenceError', + 'pydantic.errors:SetError', + 'pydantic.errors:SetMaxLengthError', + 'pydantic.errors:SetMinLengthError', + 'pydantic.errors:StrError', + 'pydantic.errors:StrRegexError', + 'pydantic.errors:StrictBoolError', + 'pydantic.errors:SubclassError', + 'pydantic.errors:TimeError', + 'pydantic.errors:TupleError', + 'pydantic.errors:TupleLengthError', + 'pydantic.errors:UUIDError', + 'pydantic.errors:UUIDVersionError', + 'pydantic.errors:UrlError', + 'pydantic.errors:UrlExtraError', + 'pydantic.errors:UrlHostError', + 'pydantic.errors:UrlHostTldError', + 'pydantic.errors:UrlPortError', + 'pydantic.errors:UrlSchemeError', + 'pydantic.errors:UrlSchemePermittedError', + 'pydantic.errors:UrlUserInfoError', + 'pydantic.errors:WrongConstantError', + 'pydantic.main:validate_model', + 'pydantic.networks:stricturl', + 'pydantic:parse_file_as', + 'pydantic:parse_raw_as', + 'pydantic:stricturl', + 'pydantic.tools:parse_file_as', + 'pydantic.tools:parse_raw_as', + 'pydantic.types:ConstrainedBytes', + 'pydantic.types:ConstrainedDate', + 'pydantic.types:ConstrainedDecimal', + 'pydantic.types:ConstrainedFloat', + 'pydantic.types:ConstrainedFrozenSet', + 'pydantic.types:ConstrainedInt', + 'pydantic.types:ConstrainedList', + 'pydantic.types:ConstrainedSet', + 'pydantic.types:ConstrainedStr', + 'pydantic.types:JsonWrapper', + 'pydantic.types:NoneBytes', + 'pydantic.types:NoneStr', + 'pydantic.types:NoneStrBytes', + 'pydantic.types:StrBytes', + 'pydantic.typing:evaluate_forwardref', + 'pydantic.typing:AbstractSetIntStr', + 'pydantic.typing:AnyCallable', + 'pydantic.typing:AnyClassMethod', + 'pydantic.typing:CallableGenerator', + 'pydantic.typing:DictAny', + 'pydantic.typing:DictIntStrAny', + 'pydantic.typing:DictStrAny', + 'pydantic.typing:IntStr', + 'pydantic.typing:ListStr', + 'pydantic.typing:MappingIntStrAny', + 'pydantic.typing:NoArgAnyCallable', + 'pydantic.typing:NoneType', + 'pydantic.typing:ReprArgs', + 'pydantic.typing:SetStr', + 'pydantic.typing:StrPath', + 'pydantic.typing:TupleGenerator', + 'pydantic.typing:WithArgsTypes', + 'pydantic.typing:all_literal_values', + 'pydantic.typing:display_as_type', + 'pydantic.typing:get_all_type_hints', + 'pydantic.typing:get_args', + 'pydantic.typing:get_origin', + 'pydantic.typing:get_sub_types', + 'pydantic.typing:is_callable_type', + 'pydantic.typing:is_classvar', + 'pydantic.typing:is_finalvar', + 'pydantic.typing:is_literal_type', + 'pydantic.typing:is_namedtuple', + 'pydantic.typing:is_new_type', + 'pydantic.typing:is_none_type', + 'pydantic.typing:is_typeddict', + 'pydantic.typing:is_typeddict_special', + 'pydantic.typing:is_union', + 'pydantic.typing:new_type_supertype', + 'pydantic.typing:resolve_annotations', + 'pydantic.typing:typing_base', + 'pydantic.typing:update_field_forward_refs', + 'pydantic.typing:update_model_forward_refs', + 'pydantic.utils:ClassAttribute', + 'pydantic.utils:DUNDER_ATTRIBUTES', + 'pydantic.utils:PyObjectStr', + 'pydantic.utils:ValueItems', + 'pydantic.utils:almost_equal_floats', + 'pydantic.utils:get_discriminator_alias_and_values', + 'pydantic.utils:get_model', + 'pydantic.utils:get_unique_discriminator_alias', + 'pydantic.utils:in_ipython', + 'pydantic.utils:is_valid_identifier', + 'pydantic.utils:path_type', + 'pydantic.utils:validate_field_name', + 'pydantic:validate_model', +} + + +def getattr_migration(module: str) -> Callable[[str], Any]: + """Implement PEP 562 for objects that were either moved or removed on the migration + to V2. + + Args: + module: The module name. + + Returns: + A callable that will raise an error if the object is not found. + """ + # This avoids circular import with errors.py. + from .errors import PydanticImportError + + def wrapper(name: str) -> object: + """Raise an error if the object is not found, or warn if it was moved. + + In case it was moved, it still returns the object. + + Args: + name: The object name. + + Returns: + The object. + """ + if name == '__path__': + raise AttributeError(f'module {module!r} has no attribute {name!r}') + + import warnings + + from ._internal._validators import import_string + + import_path = f'{module}:{name}' + if import_path in MOVED_IN_V2.keys(): + new_location = MOVED_IN_V2[import_path] + warnings.warn( + f'`{import_path}` has been moved to `{new_location}`.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + return import_string(MOVED_IN_V2[import_path]) + if import_path in DEPRECATED_MOVED_IN_V2: + # skip the warning here because a deprecation warning will be raised elsewhere + return import_string(DEPRECATED_MOVED_IN_V2[import_path]) + if import_path in REDIRECT_TO_V1: + new_location = REDIRECT_TO_V1[import_path] + warnings.warn( + f'`{import_path}` has been removed. We are importing from `{new_location}` instead.' + 'See the migration guide for more details: https://docs.pydantic.dev/latest/migration/', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + return import_string(REDIRECT_TO_V1[import_path]) + if import_path == 'pydantic:BaseSettings': + raise PydanticImportError( + '`BaseSettings` has been moved to the `pydantic-settings` package. ' + f'See https://docs.pydantic.dev/{version_short()}/migration/#basesettings-has-moved-to-pydantic-settings ' + 'for more details.' + ) + if import_path in REMOVED_IN_V2: + raise PydanticImportError(f'`{import_path}` has been removed in V2.') + globals: dict[str, Any] = sys.modules[module].__dict__ + if name in globals: + return globals[name] + raise AttributeError(f'module {module!r} has no attribute {name!r}') + + return wrapper diff --git a/backend/.venv/Lib/site-packages/pydantic/alias_generators.py b/backend/.venv/Lib/site-packages/pydantic/alias_generators.py new file mode 100644 index 0000000..0b7653f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/alias_generators.py @@ -0,0 +1,62 @@ +"""Alias generators for converting between different capitalization conventions.""" + +import re + +__all__ = ('to_pascal', 'to_camel', 'to_snake') + +# TODO: in V3, change the argument names to be more descriptive +# Generally, don't only convert from snake_case, or name the functions +# more specifically like snake_to_camel. + + +def to_pascal(snake: str) -> str: + """Convert a snake_case string to PascalCase. + + Args: + snake: The string to convert. + + Returns: + The PascalCase string. + """ + camel = snake.title() + return re.sub('([0-9A-Za-z])_(?=[0-9A-Z])', lambda m: m.group(1), camel) + + +def to_camel(snake: str) -> str: + """Convert a snake_case string to camelCase. + + Args: + snake: The string to convert. + + Returns: + The converted camelCase string. + """ + # If the string is already in camelCase and does not contain a digit followed + # by a lowercase letter, return it as it is + if re.match('^[a-z]+[A-Za-z0-9]*$', snake) and not re.search(r'\d[a-z]', snake): + return snake + + camel = to_pascal(snake) + return re.sub('(^_*[A-Z])', lambda m: m.group(1).lower(), camel) + + +def to_snake(camel: str) -> str: + """Convert a PascalCase, camelCase, or kebab-case string to snake_case. + + Args: + camel: The string to convert. + + Returns: + The converted string in snake_case. + """ + # Handle the sequence of uppercase letters followed by a lowercase letter + snake = re.sub(r'([A-Z]+)([A-Z][a-z])', lambda m: f'{m.group(1)}_{m.group(2)}', camel) + # Insert an underscore between a lowercase letter and an uppercase letter + snake = re.sub(r'([a-z])([A-Z])', lambda m: f'{m.group(1)}_{m.group(2)}', snake) + # Insert an underscore between a digit and an uppercase letter + snake = re.sub(r'([0-9])([A-Z])', lambda m: f'{m.group(1)}_{m.group(2)}', snake) + # Insert an underscore between a lowercase letter and a digit + snake = re.sub(r'([a-z])([0-9])', lambda m: f'{m.group(1)}_{m.group(2)}', snake) + # Replace hyphens with underscores to handle kebab-case + snake = snake.replace('-', '_') + return snake.lower() diff --git a/backend/.venv/Lib/site-packages/pydantic/aliases.py b/backend/.venv/Lib/site-packages/pydantic/aliases.py new file mode 100644 index 0000000..ac22737 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/aliases.py @@ -0,0 +1,135 @@ +"""Support for alias configurations.""" + +from __future__ import annotations + +import dataclasses +from typing import Any, Callable, Literal + +from pydantic_core import PydanticUndefined + +from ._internal import _internal_dataclass + +__all__ = ('AliasGenerator', 'AliasPath', 'AliasChoices') + + +@dataclasses.dataclass(**_internal_dataclass.slots_true) +class AliasPath: + """!!! abstract "Usage Documentation" + [`AliasPath` and `AliasChoices`](../concepts/alias.md#aliaspath-and-aliaschoices) + + A data class used by `validation_alias` as a convenience to create aliases. + + Attributes: + path: A list of string or integer aliases. + """ + + path: list[int | str] + + def __init__(self, first_arg: str, *args: str | int) -> None: + self.path = [first_arg] + list(args) + + def convert_to_aliases(self) -> list[str | int]: + """Converts arguments to a list of string or integer aliases. + + Returns: + The list of aliases. + """ + return self.path + + def search_dict_for_path(self, d: dict) -> Any: + """Searches a dictionary for the path specified by the alias. + + Returns: + The value at the specified path, or `PydanticUndefined` if the path is not found. + """ + v = d + for k in self.path: + if isinstance(v, str): + # disallow indexing into a str, like for AliasPath('x', 0) and x='abc' + return PydanticUndefined + try: + v = v[k] + except (KeyError, IndexError, TypeError): + return PydanticUndefined + return v + + +@dataclasses.dataclass(**_internal_dataclass.slots_true) +class AliasChoices: + """!!! abstract "Usage Documentation" + [`AliasPath` and `AliasChoices`](../concepts/alias.md#aliaspath-and-aliaschoices) + + A data class used by `validation_alias` as a convenience to create aliases. + + Attributes: + choices: A list containing a string or `AliasPath`. + """ + + choices: list[str | AliasPath] + + def __init__(self, first_choice: str | AliasPath, *choices: str | AliasPath) -> None: + self.choices = [first_choice] + list(choices) + + def convert_to_aliases(self) -> list[list[str | int]]: + """Converts arguments to a list of lists containing string or integer aliases. + + Returns: + The list of aliases. + """ + aliases: list[list[str | int]] = [] + for c in self.choices: + if isinstance(c, AliasPath): + aliases.append(c.convert_to_aliases()) + else: + aliases.append([c]) + return aliases + + +@dataclasses.dataclass(**_internal_dataclass.slots_true) +class AliasGenerator: + """!!! abstract "Usage Documentation" + [Using an `AliasGenerator`](../concepts/alias.md#using-an-aliasgenerator) + + A data class used by `alias_generator` as a convenience to create various aliases. + + Attributes: + alias: A callable that takes a field name and returns an alias for it. + validation_alias: A callable that takes a field name and returns a validation alias for it. + serialization_alias: A callable that takes a field name and returns a serialization alias for it. + """ + + alias: Callable[[str], str] | None = None + validation_alias: Callable[[str], str | AliasPath | AliasChoices] | None = None + serialization_alias: Callable[[str], str] | None = None + + def _generate_alias( + self, + alias_kind: Literal['alias', 'validation_alias', 'serialization_alias'], + allowed_types: tuple[type[str] | type[AliasPath] | type[AliasChoices], ...], + field_name: str, + ) -> str | AliasPath | AliasChoices | None: + """Generate an alias of the specified kind. Returns None if the alias generator is None. + + Raises: + TypeError: If the alias generator produces an invalid type. + """ + alias = None + if alias_generator := getattr(self, alias_kind): + alias = alias_generator(field_name) + if alias and not isinstance(alias, allowed_types): + raise TypeError( + f'Invalid `{alias_kind}` type. `{alias_kind}` generator must produce one of `{allowed_types}`' + ) + return alias + + def generate_aliases(self, field_name: str) -> tuple[str | None, str | AliasPath | AliasChoices | None, str | None]: + """Generate `alias`, `validation_alias`, and `serialization_alias` for a field. + + Returns: + A tuple of three aliases - validation, alias, and serialization. + """ + alias = self._generate_alias('alias', (str,), field_name) + validation_alias = self._generate_alias('validation_alias', (str, AliasChoices, AliasPath), field_name) + serialization_alias = self._generate_alias('serialization_alias', (str,), field_name) + + return alias, validation_alias, serialization_alias # type: ignore diff --git a/backend/.venv/Lib/site-packages/pydantic/annotated_handlers.py b/backend/.venv/Lib/site-packages/pydantic/annotated_handlers.py new file mode 100644 index 0000000..d0cb5d3 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/annotated_handlers.py @@ -0,0 +1,122 @@ +"""Type annotations to use with `__get_pydantic_core_schema__` and `__get_pydantic_json_schema__`.""" + +from __future__ import annotations as _annotations + +from typing import TYPE_CHECKING, Any, Union + +from pydantic_core import core_schema + +if TYPE_CHECKING: + from ._internal._namespace_utils import NamespacesTuple + from .json_schema import JsonSchemaMode, JsonSchemaValue + + CoreSchemaOrField = Union[ + core_schema.CoreSchema, + core_schema.ModelField, + core_schema.DataclassField, + core_schema.TypedDictField, + core_schema.ComputedField, + ] + +__all__ = 'GetJsonSchemaHandler', 'GetCoreSchemaHandler' + + +class GetJsonSchemaHandler: + """Handler to call into the next JSON schema generation function. + + Attributes: + mode: Json schema mode, can be `validation` or `serialization`. + """ + + mode: JsonSchemaMode + + def __call__(self, core_schema: CoreSchemaOrField, /) -> JsonSchemaValue: + """Call the inner handler and get the JsonSchemaValue it returns. + This will call the next JSON schema modifying function up until it calls + into `pydantic.json_schema.GenerateJsonSchema`, which will raise a + `pydantic.errors.PydanticInvalidForJsonSchema` error if it cannot generate + a JSON schema. + + Args: + core_schema: A `pydantic_core.core_schema.CoreSchema`. + + Returns: + JsonSchemaValue: The JSON schema generated by the inner JSON schema modify + functions. + """ + raise NotImplementedError + + def resolve_ref_schema(self, maybe_ref_json_schema: JsonSchemaValue, /) -> JsonSchemaValue: + """Get the real schema for a `{"$ref": ...}` schema. + If the schema given is not a `$ref` schema, it will be returned as is. + This means you don't have to check before calling this function. + + Args: + maybe_ref_json_schema: A JsonSchemaValue which may be a `$ref` schema. + + Raises: + LookupError: If the ref is not found. + + Returns: + JsonSchemaValue: A JsonSchemaValue that has no `$ref`. + """ + raise NotImplementedError + + +class GetCoreSchemaHandler: + """Handler to call into the next CoreSchema schema generation function.""" + + def __call__(self, source_type: Any, /) -> core_schema.CoreSchema: + """Call the inner handler and get the CoreSchema it returns. + This will call the next CoreSchema modifying function up until it calls + into Pydantic's internal schema generation machinery, which will raise a + `pydantic.errors.PydanticSchemaGenerationError` error if it cannot generate + a CoreSchema for the given source type. + + Args: + source_type: The input type. + + Returns: + CoreSchema: The `pydantic-core` CoreSchema generated. + """ + raise NotImplementedError + + def generate_schema(self, source_type: Any, /) -> core_schema.CoreSchema: + """Generate a schema unrelated to the current context. + Use this function if e.g. you are handling schema generation for a sequence + and want to generate a schema for its items. + Otherwise, you may end up doing something like applying a `min_length` constraint + that was intended for the sequence itself to its items! + + Args: + source_type: The input type. + + Returns: + CoreSchema: The `pydantic-core` CoreSchema generated. + """ + raise NotImplementedError + + def resolve_ref_schema(self, maybe_ref_schema: core_schema.CoreSchema, /) -> core_schema.CoreSchema: + """Get the real schema for a `definition-ref` schema. + If the schema given is not a `definition-ref` schema, it will be returned as is. + This means you don't have to check before calling this function. + + Args: + maybe_ref_schema: A `CoreSchema`, `ref`-based or not. + + Raises: + LookupError: If the `ref` is not found. + + Returns: + A concrete `CoreSchema`. + """ + raise NotImplementedError + + @property + def field_name(self) -> str | None: + """Get the name of the closest field to this validator.""" + raise NotImplementedError + + def _get_types_namespace(self) -> NamespacesTuple: + """Internal method used during type resolution for serializer annotations.""" + raise NotImplementedError diff --git a/backend/.venv/Lib/site-packages/pydantic/class_validators.py b/backend/.venv/Lib/site-packages/pydantic/class_validators.py new file mode 100644 index 0000000..9977150 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/class_validators.py @@ -0,0 +1,5 @@ +"""`class_validators` module is a backport module from V1.""" + +from ._migration import getattr_migration + +__getattr__ = getattr_migration(__name__) diff --git a/backend/.venv/Lib/site-packages/pydantic/color.py b/backend/.venv/Lib/site-packages/pydantic/color.py new file mode 100644 index 0000000..9a42d58 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/color.py @@ -0,0 +1,604 @@ +"""Color definitions are used as per the CSS3 +[CSS Color Module Level 3](http://www.w3.org/TR/css3-color/#svg-color) specification. + +A few colors have multiple names referring to the sames colors, eg. `grey` and `gray` or `aqua` and `cyan`. + +In these cases the _last_ color when sorted alphabetically takes preferences, +eg. `Color((0, 255, 255)).as_named() == 'cyan'` because "cyan" comes after "aqua". + +Warning: Deprecated + The `Color` class is deprecated, use `pydantic_extra_types` instead. + See [`pydantic-extra-types.Color`](../usage/types/extra_types/color_types.md) + for more information. +""" + +import math +import re +from colorsys import hls_to_rgb, rgb_to_hls +from typing import Any, Callable, Optional, Union, cast + +from pydantic_core import CoreSchema, PydanticCustomError, core_schema +from typing_extensions import deprecated + +from ._internal import _repr +from ._internal._schema_generation_shared import GetJsonSchemaHandler as _GetJsonSchemaHandler +from .json_schema import JsonSchemaValue +from .warnings import PydanticDeprecatedSince20 + +ColorTuple = Union[tuple[int, int, int], tuple[int, int, int, float]] +ColorType = Union[ColorTuple, str] +HslColorTuple = Union[tuple[float, float, float], tuple[float, float, float, float]] + + +class RGBA: + """Internal use only as a representation of a color.""" + + __slots__ = 'r', 'g', 'b', 'alpha', '_tuple' + + def __init__(self, r: float, g: float, b: float, alpha: Optional[float]): + self.r = r + self.g = g + self.b = b + self.alpha = alpha + + self._tuple: tuple[float, float, float, Optional[float]] = (r, g, b, alpha) + + def __getitem__(self, item: Any) -> Any: + return self._tuple[item] + + +# these are not compiled here to avoid import slowdown, they'll be compiled the first time they're used, then cached +_r_255 = r'(\d{1,3}(?:\.\d+)?)' +_r_comma = r'\s*,\s*' +_r_alpha = r'(\d(?:\.\d+)?|\.\d+|\d{1,2}%)' +_r_h = r'(-?\d+(?:\.\d+)?|-?\.\d+)(deg|rad|turn)?' +_r_sl = r'(\d{1,3}(?:\.\d+)?)%' +r_hex_short = r'\s*(?:#|0x)?([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])?\s*' +r_hex_long = r'\s*(?:#|0x)?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})?\s*' +# CSS3 RGB examples: rgb(0, 0, 0), rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 50%) +r_rgb = rf'\s*rgba?\(\s*{_r_255}{_r_comma}{_r_255}{_r_comma}{_r_255}(?:{_r_comma}{_r_alpha})?\s*\)\s*' +# CSS3 HSL examples: hsl(270, 60%, 50%), hsla(270, 60%, 50%, 0.5), hsla(270, 60%, 50%, 50%) +r_hsl = rf'\s*hsla?\(\s*{_r_h}{_r_comma}{_r_sl}{_r_comma}{_r_sl}(?:{_r_comma}{_r_alpha})?\s*\)\s*' +# CSS4 RGB examples: rgb(0 0 0), rgb(0 0 0 / 0.5), rgb(0 0 0 / 50%), rgba(0 0 0 / 50%) +r_rgb_v4_style = rf'\s*rgba?\(\s*{_r_255}\s+{_r_255}\s+{_r_255}(?:\s*/\s*{_r_alpha})?\s*\)\s*' +# CSS4 HSL examples: hsl(270 60% 50%), hsl(270 60% 50% / 0.5), hsl(270 60% 50% / 50%), hsla(270 60% 50% / 50%) +r_hsl_v4_style = rf'\s*hsla?\(\s*{_r_h}\s+{_r_sl}\s+{_r_sl}(?:\s*/\s*{_r_alpha})?\s*\)\s*' + +# colors where the two hex characters are the same, if all colors match this the short version of hex colors can be used +repeat_colors = {int(c * 2, 16) for c in '0123456789abcdef'} +rads = 2 * math.pi + + +@deprecated( + 'The `Color` class is deprecated, use `pydantic_extra_types` instead. ' + 'See https://docs.pydantic.dev/latest/api/pydantic_extra_types_color/.', + category=PydanticDeprecatedSince20, +) +class Color(_repr.Representation): + """Represents a color.""" + + __slots__ = '_original', '_rgba' + + def __init__(self, value: ColorType) -> None: + self._rgba: RGBA + self._original: ColorType + if isinstance(value, (tuple, list)): + self._rgba = parse_tuple(value) + elif isinstance(value, str): + self._rgba = parse_str(value) + elif isinstance(value, Color): + self._rgba = value._rgba + value = value._original + else: + raise PydanticCustomError( + 'color_error', 'value is not a valid color: value must be a tuple, list or string' + ) + + # if we've got here value must be a valid color + self._original = value + + @classmethod + def __get_pydantic_json_schema__( + cls, core_schema: core_schema.CoreSchema, handler: _GetJsonSchemaHandler + ) -> JsonSchemaValue: + field_schema = {} + field_schema.update(type='string', format='color') + return field_schema + + def original(self) -> ColorType: + """Original value passed to `Color`.""" + return self._original + + def as_named(self, *, fallback: bool = False) -> str: + """Returns the name of the color if it can be found in `COLORS_BY_VALUE` dictionary, + otherwise returns the hexadecimal representation of the color or raises `ValueError`. + + Args: + fallback: If True, falls back to returning the hexadecimal representation of + the color instead of raising a ValueError when no named color is found. + + Returns: + The name of the color, or the hexadecimal representation of the color. + + Raises: + ValueError: When no named color is found and fallback is `False`. + """ + if self._rgba.alpha is None: + rgb = cast(tuple[int, int, int], self.as_rgb_tuple()) + try: + return COLORS_BY_VALUE[rgb] + except KeyError as e: + if fallback: + return self.as_hex() + else: + raise ValueError('no named color found, use fallback=True, as_hex() or as_rgb()') from e + else: + return self.as_hex() + + def as_hex(self) -> str: + """Returns the hexadecimal representation of the color. + + Hex string representing the color can be 3, 4, 6, or 8 characters depending on whether the string + a "short" representation of the color is possible and whether there's an alpha channel. + + Returns: + The hexadecimal representation of the color. + """ + values = [float_to_255(c) for c in self._rgba[:3]] + if self._rgba.alpha is not None: + values.append(float_to_255(self._rgba.alpha)) + + as_hex = ''.join(f'{v:02x}' for v in values) + if all(c in repeat_colors for c in values): + as_hex = ''.join(as_hex[c] for c in range(0, len(as_hex), 2)) + return '#' + as_hex + + def as_rgb(self) -> str: + """Color as an `rgb(, , )` or `rgba(, , , )` string.""" + if self._rgba.alpha is None: + return f'rgb({float_to_255(self._rgba.r)}, {float_to_255(self._rgba.g)}, {float_to_255(self._rgba.b)})' + else: + return ( + f'rgba({float_to_255(self._rgba.r)}, {float_to_255(self._rgba.g)}, {float_to_255(self._rgba.b)}, ' + f'{round(self._alpha_float(), 2)})' + ) + + def as_rgb_tuple(self, *, alpha: Optional[bool] = None) -> ColorTuple: + """Returns the color as an RGB or RGBA tuple. + + Args: + alpha: Whether to include the alpha channel. There are three options for this input: + + - `None` (default): Include alpha only if it's set. (e.g. not `None`) + - `True`: Always include alpha. + - `False`: Always omit alpha. + + Returns: + A tuple that contains the values of the red, green, and blue channels in the range 0 to 255. + If alpha is included, it is in the range 0 to 1. + """ + r, g, b = (float_to_255(c) for c in self._rgba[:3]) + if alpha is None: + if self._rgba.alpha is None: + return r, g, b + else: + return r, g, b, self._alpha_float() + elif alpha: + return r, g, b, self._alpha_float() + else: + # alpha is False + return r, g, b + + def as_hsl(self) -> str: + """Color as an `hsl(, , )` or `hsl(, , , )` string.""" + if self._rgba.alpha is None: + h, s, li = self.as_hsl_tuple(alpha=False) # type: ignore + return f'hsl({h * 360:0.0f}, {s:0.0%}, {li:0.0%})' + else: + h, s, li, a = self.as_hsl_tuple(alpha=True) # type: ignore + return f'hsl({h * 360:0.0f}, {s:0.0%}, {li:0.0%}, {round(a, 2)})' + + def as_hsl_tuple(self, *, alpha: Optional[bool] = None) -> HslColorTuple: + """Returns the color as an HSL or HSLA tuple. + + Args: + alpha: Whether to include the alpha channel. + + - `None` (default): Include the alpha channel only if it's set (e.g. not `None`). + - `True`: Always include alpha. + - `False`: Always omit alpha. + + Returns: + The color as a tuple of hue, saturation, lightness, and alpha (if included). + All elements are in the range 0 to 1. + + Note: + This is HSL as used in HTML and most other places, not HLS as used in Python's `colorsys`. + """ + h, l, s = rgb_to_hls(self._rgba.r, self._rgba.g, self._rgba.b) # noqa: E741 + if alpha is None: + if self._rgba.alpha is None: + return h, s, l + else: + return h, s, l, self._alpha_float() + if alpha: + return h, s, l, self._alpha_float() + else: + # alpha is False + return h, s, l + + def _alpha_float(self) -> float: + return 1 if self._rgba.alpha is None else self._rgba.alpha + + @classmethod + def __get_pydantic_core_schema__( + cls, source: type[Any], handler: Callable[[Any], CoreSchema] + ) -> core_schema.CoreSchema: + return core_schema.with_info_plain_validator_function( + cls._validate, serialization=core_schema.to_string_ser_schema() + ) + + @classmethod + def _validate(cls, __input_value: Any, _: Any) -> 'Color': + return cls(__input_value) + + def __str__(self) -> str: + return self.as_named(fallback=True) + + def __repr_args__(self) -> '_repr.ReprArgs': + return [(None, self.as_named(fallback=True))] + [('rgb', self.as_rgb_tuple())] + + def __eq__(self, other: Any) -> bool: + return isinstance(other, Color) and self.as_rgb_tuple() == other.as_rgb_tuple() + + def __hash__(self) -> int: + return hash(self.as_rgb_tuple()) + + +def parse_tuple(value: tuple[Any, ...]) -> RGBA: + """Parse a tuple or list to get RGBA values. + + Args: + value: A tuple or list. + + Returns: + An `RGBA` tuple parsed from the input tuple. + + Raises: + PydanticCustomError: If tuple is not valid. + """ + if len(value) == 3: + r, g, b = (parse_color_value(v) for v in value) + return RGBA(r, g, b, None) + elif len(value) == 4: + r, g, b = (parse_color_value(v) for v in value[:3]) + return RGBA(r, g, b, parse_float_alpha(value[3])) + else: + raise PydanticCustomError('color_error', 'value is not a valid color: tuples must have length 3 or 4') + + +def parse_str(value: str) -> RGBA: + """Parse a string representing a color to an RGBA tuple. + + Possible formats for the input string include: + + * named color, see `COLORS_BY_NAME` + * hex short eg. `fff` (prefix can be `#`, `0x` or nothing) + * hex long eg. `ffffff` (prefix can be `#`, `0x` or nothing) + * `rgb(, , )` + * `rgba(, , , )` + + Args: + value: A string representing a color. + + Returns: + An `RGBA` tuple parsed from the input string. + + Raises: + ValueError: If the input string cannot be parsed to an RGBA tuple. + """ + value_lower = value.lower() + try: + r, g, b = COLORS_BY_NAME[value_lower] + except KeyError: + pass + else: + return ints_to_rgba(r, g, b, None) + + m = re.fullmatch(r_hex_short, value_lower) + if m: + *rgb, a = m.groups() + r, g, b = (int(v * 2, 16) for v in rgb) + if a: + alpha: Optional[float] = int(a * 2, 16) / 255 + else: + alpha = None + return ints_to_rgba(r, g, b, alpha) + + m = re.fullmatch(r_hex_long, value_lower) + if m: + *rgb, a = m.groups() + r, g, b = (int(v, 16) for v in rgb) + if a: + alpha = int(a, 16) / 255 + else: + alpha = None + return ints_to_rgba(r, g, b, alpha) + + m = re.fullmatch(r_rgb, value_lower) or re.fullmatch(r_rgb_v4_style, value_lower) + if m: + return ints_to_rgba(*m.groups()) # type: ignore + + m = re.fullmatch(r_hsl, value_lower) or re.fullmatch(r_hsl_v4_style, value_lower) + if m: + return parse_hsl(*m.groups()) # type: ignore + + raise PydanticCustomError('color_error', 'value is not a valid color: string not recognised as a valid color') + + +def ints_to_rgba(r: Union[int, str], g: Union[int, str], b: Union[int, str], alpha: Optional[float] = None) -> RGBA: + """Converts integer or string values for RGB color and an optional alpha value to an `RGBA` object. + + Args: + r: An integer or string representing the red color value. + g: An integer or string representing the green color value. + b: An integer or string representing the blue color value. + alpha: A float representing the alpha value. Defaults to None. + + Returns: + An instance of the `RGBA` class with the corresponding color and alpha values. + """ + return RGBA(parse_color_value(r), parse_color_value(g), parse_color_value(b), parse_float_alpha(alpha)) + + +def parse_color_value(value: Union[int, str], max_val: int = 255) -> float: + """Parse the color value provided and return a number between 0 and 1. + + Args: + value: An integer or string color value. + max_val: Maximum range value. Defaults to 255. + + Raises: + PydanticCustomError: If the value is not a valid color. + + Returns: + A number between 0 and 1. + """ + try: + color = float(value) + except ValueError: + raise PydanticCustomError('color_error', 'value is not a valid color: color values must be a valid number') + if 0 <= color <= max_val: + return color / max_val + else: + raise PydanticCustomError( + 'color_error', + 'value is not a valid color: color values must be in the range 0 to {max_val}', + {'max_val': max_val}, + ) + + +def parse_float_alpha(value: Union[None, str, float, int]) -> Optional[float]: + """Parse an alpha value checking it's a valid float in the range 0 to 1. + + Args: + value: The input value to parse. + + Returns: + The parsed value as a float, or `None` if the value was None or equal 1. + + Raises: + PydanticCustomError: If the input value cannot be successfully parsed as a float in the expected range. + """ + if value is None: + return None + try: + if isinstance(value, str) and value.endswith('%'): + alpha = float(value[:-1]) / 100 + else: + alpha = float(value) + except ValueError: + raise PydanticCustomError('color_error', 'value is not a valid color: alpha values must be a valid float') + + if math.isclose(alpha, 1): + return None + elif 0 <= alpha <= 1: + return alpha + else: + raise PydanticCustomError('color_error', 'value is not a valid color: alpha values must be in the range 0 to 1') + + +def parse_hsl(h: str, h_units: str, sat: str, light: str, alpha: Optional[float] = None) -> RGBA: + """Parse raw hue, saturation, lightness, and alpha values and convert to RGBA. + + Args: + h: The hue value. + h_units: The unit for hue value. + sat: The saturation value. + light: The lightness value. + alpha: Alpha value. + + Returns: + An instance of `RGBA`. + """ + s_value, l_value = parse_color_value(sat, 100), parse_color_value(light, 100) + + h_value = float(h) + if h_units in {None, 'deg'}: + h_value = h_value % 360 / 360 + elif h_units == 'rad': + h_value = h_value % rads / rads + else: + # turns + h_value = h_value % 1 + + r, g, b = hls_to_rgb(h_value, l_value, s_value) + return RGBA(r, g, b, parse_float_alpha(alpha)) + + +def float_to_255(c: float) -> int: + """Converts a float value between 0 and 1 (inclusive) to an integer between 0 and 255 (inclusive). + + Args: + c: The float value to be converted. Must be between 0 and 1 (inclusive). + + Returns: + The integer equivalent of the given float value rounded to the nearest whole number. + + Raises: + ValueError: If the given float value is outside the acceptable range of 0 to 1 (inclusive). + """ + return int(round(c * 255)) + + +COLORS_BY_NAME = { + 'aliceblue': (240, 248, 255), + 'antiquewhite': (250, 235, 215), + 'aqua': (0, 255, 255), + 'aquamarine': (127, 255, 212), + 'azure': (240, 255, 255), + 'beige': (245, 245, 220), + 'bisque': (255, 228, 196), + 'black': (0, 0, 0), + 'blanchedalmond': (255, 235, 205), + 'blue': (0, 0, 255), + 'blueviolet': (138, 43, 226), + 'brown': (165, 42, 42), + 'burlywood': (222, 184, 135), + 'cadetblue': (95, 158, 160), + 'chartreuse': (127, 255, 0), + 'chocolate': (210, 105, 30), + 'coral': (255, 127, 80), + 'cornflowerblue': (100, 149, 237), + 'cornsilk': (255, 248, 220), + 'crimson': (220, 20, 60), + 'cyan': (0, 255, 255), + 'darkblue': (0, 0, 139), + 'darkcyan': (0, 139, 139), + 'darkgoldenrod': (184, 134, 11), + 'darkgray': (169, 169, 169), + 'darkgreen': (0, 100, 0), + 'darkgrey': (169, 169, 169), + 'darkkhaki': (189, 183, 107), + 'darkmagenta': (139, 0, 139), + 'darkolivegreen': (85, 107, 47), + 'darkorange': (255, 140, 0), + 'darkorchid': (153, 50, 204), + 'darkred': (139, 0, 0), + 'darksalmon': (233, 150, 122), + 'darkseagreen': (143, 188, 143), + 'darkslateblue': (72, 61, 139), + 'darkslategray': (47, 79, 79), + 'darkslategrey': (47, 79, 79), + 'darkturquoise': (0, 206, 209), + 'darkviolet': (148, 0, 211), + 'deeppink': (255, 20, 147), + 'deepskyblue': (0, 191, 255), + 'dimgray': (105, 105, 105), + 'dimgrey': (105, 105, 105), + 'dodgerblue': (30, 144, 255), + 'firebrick': (178, 34, 34), + 'floralwhite': (255, 250, 240), + 'forestgreen': (34, 139, 34), + 'fuchsia': (255, 0, 255), + 'gainsboro': (220, 220, 220), + 'ghostwhite': (248, 248, 255), + 'gold': (255, 215, 0), + 'goldenrod': (218, 165, 32), + 'gray': (128, 128, 128), + 'green': (0, 128, 0), + 'greenyellow': (173, 255, 47), + 'grey': (128, 128, 128), + 'honeydew': (240, 255, 240), + 'hotpink': (255, 105, 180), + 'indianred': (205, 92, 92), + 'indigo': (75, 0, 130), + 'ivory': (255, 255, 240), + 'khaki': (240, 230, 140), + 'lavender': (230, 230, 250), + 'lavenderblush': (255, 240, 245), + 'lawngreen': (124, 252, 0), + 'lemonchiffon': (255, 250, 205), + 'lightblue': (173, 216, 230), + 'lightcoral': (240, 128, 128), + 'lightcyan': (224, 255, 255), + 'lightgoldenrodyellow': (250, 250, 210), + 'lightgray': (211, 211, 211), + 'lightgreen': (144, 238, 144), + 'lightgrey': (211, 211, 211), + 'lightpink': (255, 182, 193), + 'lightsalmon': (255, 160, 122), + 'lightseagreen': (32, 178, 170), + 'lightskyblue': (135, 206, 250), + 'lightslategray': (119, 136, 153), + 'lightslategrey': (119, 136, 153), + 'lightsteelblue': (176, 196, 222), + 'lightyellow': (255, 255, 224), + 'lime': (0, 255, 0), + 'limegreen': (50, 205, 50), + 'linen': (250, 240, 230), + 'magenta': (255, 0, 255), + 'maroon': (128, 0, 0), + 'mediumaquamarine': (102, 205, 170), + 'mediumblue': (0, 0, 205), + 'mediumorchid': (186, 85, 211), + 'mediumpurple': (147, 112, 219), + 'mediumseagreen': (60, 179, 113), + 'mediumslateblue': (123, 104, 238), + 'mediumspringgreen': (0, 250, 154), + 'mediumturquoise': (72, 209, 204), + 'mediumvioletred': (199, 21, 133), + 'midnightblue': (25, 25, 112), + 'mintcream': (245, 255, 250), + 'mistyrose': (255, 228, 225), + 'moccasin': (255, 228, 181), + 'navajowhite': (255, 222, 173), + 'navy': (0, 0, 128), + 'oldlace': (253, 245, 230), + 'olive': (128, 128, 0), + 'olivedrab': (107, 142, 35), + 'orange': (255, 165, 0), + 'orangered': (255, 69, 0), + 'orchid': (218, 112, 214), + 'palegoldenrod': (238, 232, 170), + 'palegreen': (152, 251, 152), + 'paleturquoise': (175, 238, 238), + 'palevioletred': (219, 112, 147), + 'papayawhip': (255, 239, 213), + 'peachpuff': (255, 218, 185), + 'peru': (205, 133, 63), + 'pink': (255, 192, 203), + 'plum': (221, 160, 221), + 'powderblue': (176, 224, 230), + 'purple': (128, 0, 128), + 'red': (255, 0, 0), + 'rosybrown': (188, 143, 143), + 'royalblue': (65, 105, 225), + 'saddlebrown': (139, 69, 19), + 'salmon': (250, 128, 114), + 'sandybrown': (244, 164, 96), + 'seagreen': (46, 139, 87), + 'seashell': (255, 245, 238), + 'sienna': (160, 82, 45), + 'silver': (192, 192, 192), + 'skyblue': (135, 206, 235), + 'slateblue': (106, 90, 205), + 'slategray': (112, 128, 144), + 'slategrey': (112, 128, 144), + 'snow': (255, 250, 250), + 'springgreen': (0, 255, 127), + 'steelblue': (70, 130, 180), + 'tan': (210, 180, 140), + 'teal': (0, 128, 128), + 'thistle': (216, 191, 216), + 'tomato': (255, 99, 71), + 'turquoise': (64, 224, 208), + 'violet': (238, 130, 238), + 'wheat': (245, 222, 179), + 'white': (255, 255, 255), + 'whitesmoke': (245, 245, 245), + 'yellow': (255, 255, 0), + 'yellowgreen': (154, 205, 50), +} + +COLORS_BY_VALUE = {v: k for k, v in COLORS_BY_NAME.items()} diff --git a/backend/.venv/Lib/site-packages/pydantic/config.py b/backend/.venv/Lib/site-packages/pydantic/config.py new file mode 100644 index 0000000..bbf57aa --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/config.py @@ -0,0 +1,1288 @@ +"""Configuration for Pydantic models.""" + +from __future__ import annotations as _annotations + +import warnings +from re import Pattern +from typing import TYPE_CHECKING, Any, Callable, Literal, TypeVar, Union, cast, overload + +from typing_extensions import TypeAlias, TypedDict, Unpack, deprecated + +from ._migration import getattr_migration +from .aliases import AliasGenerator +from .errors import PydanticUserError +from .warnings import PydanticDeprecatedSince211 + +if TYPE_CHECKING: + from ._internal._generate_schema import GenerateSchema as _GenerateSchema + from .fields import ComputedFieldInfo, FieldInfo + +__all__ = ('ConfigDict', 'with_config') + + +JsonValue: TypeAlias = Union[int, float, str, bool, None, list['JsonValue'], 'JsonDict'] +JsonDict: TypeAlias = dict[str, JsonValue] + +JsonEncoder = Callable[[Any], Any] + +JsonSchemaExtraCallable: TypeAlias = Union[ + Callable[[JsonDict], None], + Callable[[JsonDict, type[Any]], None], +] + +ExtraValues = Literal['allow', 'ignore', 'forbid'] + + +class ConfigDict(TypedDict, total=False): + """A TypedDict for configuring Pydantic behaviour.""" + + title: str | None + """The title for the generated JSON schema, defaults to the model's name""" + + model_title_generator: Callable[[type], str] | None + """A callable that takes a model class and returns the title for it. Defaults to `None`.""" + + field_title_generator: Callable[[str, FieldInfo | ComputedFieldInfo], str] | None + """A callable that takes a field's name and info and returns title for it. Defaults to `None`.""" + + str_to_lower: bool + """Whether to convert all characters to lowercase for str types. Defaults to `False`.""" + + str_to_upper: bool + """Whether to convert all characters to uppercase for str types. Defaults to `False`.""" + + str_strip_whitespace: bool + """Whether to strip leading and trailing whitespace for str types.""" + + str_min_length: int + """The minimum length for str types. Defaults to `None`.""" + + str_max_length: int | None + """The maximum length for str types. Defaults to `None`.""" + + extra: ExtraValues | None + ''' + Whether to ignore, allow, or forbid extra data during model initialization. Defaults to `'ignore'`. + + Three configuration values are available: + + - `'ignore'`: Providing extra data is ignored (the default): + ```python + from pydantic import BaseModel, ConfigDict + + class User(BaseModel): + model_config = ConfigDict(extra='ignore') # (1)! + + name: str + + user = User(name='John Doe', age=20) # (2)! + print(user) + #> name='John Doe' + ``` + + 1. This is the default behaviour. + 2. The `age` argument is ignored. + + - `'forbid'`: Providing extra data is not permitted, and a [`ValidationError`][pydantic_core.ValidationError] + will be raised if this is the case: + ```python + from pydantic import BaseModel, ConfigDict, ValidationError + + + class Model(BaseModel): + x: int + + model_config = ConfigDict(extra='forbid') + + + try: + Model(x=1, y='a') + except ValidationError as exc: + print(exc) + """ + 1 validation error for Model + y + Extra inputs are not permitted [type=extra_forbidden, input_value='a', input_type=str] + """ + ``` + + - `'allow'`: Providing extra data is allowed and stored in the `__pydantic_extra__` dictionary attribute: + ```python + from pydantic import BaseModel, ConfigDict + + + class Model(BaseModel): + x: int + + model_config = ConfigDict(extra='allow') + + + m = Model(x=1, y='a') + assert m.__pydantic_extra__ == {'y': 'a'} + ``` + By default, no validation will be applied to these extra items, but you can set a type for the values by overriding + the type annotation for `__pydantic_extra__`: + ```python + from pydantic import BaseModel, ConfigDict, Field, ValidationError + + + class Model(BaseModel): + __pydantic_extra__: dict[str, int] = Field(init=False) # (1)! + + x: int + + model_config = ConfigDict(extra='allow') + + + try: + Model(x=1, y='a') + except ValidationError as exc: + print(exc) + """ + 1 validation error for Model + y + Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='a', input_type=str] + """ + + m = Model(x=1, y='2') + assert m.x == 1 + assert m.y == 2 + assert m.model_dump() == {'x': 1, 'y': 2} + assert m.__pydantic_extra__ == {'y': 2} + ``` + + 1. The `= Field(init=False)` does not have any effect at runtime, but prevents the `__pydantic_extra__` field from + being included as a parameter to the model's `__init__` method by type checkers. + + As well as specifying an `extra` configuration value on the model, you can also provide it as an argument to the validation methods. + This will override any `extra` configuration value set on the model: + ```python + from pydantic import BaseModel, ConfigDict, ValidationError + + class Model(BaseModel): + x: int + model_config = ConfigDict(extra="allow") + + try: + # Override model config and forbid extra fields just this time + Model.model_validate({"x": 1, "y": 2}, extra="forbid") + except ValidationError as exc: + print(exc) + """ + 1 validation error for Model + y + Extra inputs are not permitted [type=extra_forbidden, input_value=2, input_type=int] + """ + ``` + ''' + + frozen: bool + """ + Whether models are faux-immutable, i.e. whether `__setattr__` is allowed, and also generates + a `__hash__()` method for the model. This makes instances of the model potentially hashable if all the + attributes are hashable. Defaults to `False`. + + Note: + On V1, the inverse of this setting was called `allow_mutation`, and was `True` by default. + """ + + populate_by_name: bool + """ + Whether an aliased field may be populated by its name as given by the model + attribute, as well as the alias. Defaults to `False`. + + !!! warning + `populate_by_name` usage is not recommended in v2.11+ and will be deprecated in v3. + Instead, you should use the [`validate_by_name`][pydantic.config.ConfigDict.validate_by_name] configuration setting. + + When `validate_by_name=True` and `validate_by_alias=True`, this is strictly equivalent to the + previous behavior of `populate_by_name=True`. + + In v2.11, we also introduced a [`validate_by_alias`][pydantic.config.ConfigDict.validate_by_alias] setting that introduces more fine grained + control for validation behavior. + + Here's how you might go about using the new settings to achieve the same behavior: + + ```python + from pydantic import BaseModel, ConfigDict, Field + + class Model(BaseModel): + model_config = ConfigDict(validate_by_name=True, validate_by_alias=True) + + my_field: str = Field(alias='my_alias') # (1)! + + m = Model(my_alias='foo') # (2)! + print(m) + #> my_field='foo' + + m = Model(my_field='foo') # (3)! + print(m) + #> my_field='foo' + ``` + + 1. The field `'my_field'` has an alias `'my_alias'`. + 2. The model is populated by the alias `'my_alias'`. + 3. The model is populated by the attribute name `'my_field'`. + """ + + use_enum_values: bool + """ + Whether to populate models with the `value` property of enums, rather than the raw enum. + This may be useful if you want to serialize `model.model_dump()` later. Defaults to `False`. + + !!! note + If you have an `Optional[Enum]` value that you set a default for, you need to use `validate_default=True` + for said Field to ensure that the `use_enum_values` flag takes effect on the default, as extracting an + enum's value occurs during validation, not serialization. + + ```python + from enum import Enum + from typing import Optional + + from pydantic import BaseModel, ConfigDict, Field + + class SomeEnum(Enum): + FOO = 'foo' + BAR = 'bar' + BAZ = 'baz' + + class SomeModel(BaseModel): + model_config = ConfigDict(use_enum_values=True) + + some_enum: SomeEnum + another_enum: Optional[SomeEnum] = Field( + default=SomeEnum.FOO, validate_default=True + ) + + model1 = SomeModel(some_enum=SomeEnum.BAR) + print(model1.model_dump()) + #> {'some_enum': 'bar', 'another_enum': 'foo'} + + model2 = SomeModel(some_enum=SomeEnum.BAR, another_enum=SomeEnum.BAZ) + print(model2.model_dump()) + #> {'some_enum': 'bar', 'another_enum': 'baz'} + ``` + """ + + validate_assignment: bool + """ + Whether to validate the data when the model is changed. Defaults to `False`. + + The default behavior of Pydantic is to validate the data when the model is created. + + In case the user changes the data after the model is created, the model is _not_ revalidated. + + ```python + from pydantic import BaseModel + + class User(BaseModel): + name: str + + user = User(name='John Doe') # (1)! + print(user) + #> name='John Doe' + user.name = 123 # (1)! + print(user) + #> name=123 + ``` + + 1. The validation happens only when the model is created. + 2. The validation does not happen when the data is changed. + + In case you want to revalidate the model when the data is changed, you can use `validate_assignment=True`: + + ```python + from pydantic import BaseModel, ValidationError + + class User(BaseModel, validate_assignment=True): # (1)! + name: str + + user = User(name='John Doe') # (2)! + print(user) + #> name='John Doe' + try: + user.name = 123 # (3)! + except ValidationError as e: + print(e) + ''' + 1 validation error for User + name + Input should be a valid string [type=string_type, input_value=123, input_type=int] + ''' + ``` + + 1. You can either use class keyword arguments, or `model_config` to set `validate_assignment=True`. + 2. The validation happens when the model is created. + 3. The validation _also_ happens when the data is changed. + """ + + arbitrary_types_allowed: bool + """ + Whether arbitrary types are allowed for field types. Defaults to `False`. + + ```python + from pydantic import BaseModel, ConfigDict, ValidationError + + # This is not a pydantic model, it's an arbitrary class + class Pet: + def __init__(self, name: str): + self.name = name + + class Model(BaseModel): + model_config = ConfigDict(arbitrary_types_allowed=True) + + pet: Pet + owner: str + + pet = Pet(name='Hedwig') + # A simple check of instance type is used to validate the data + model = Model(owner='Harry', pet=pet) + print(model) + #> pet=<__main__.Pet object at 0x0123456789ab> owner='Harry' + print(model.pet) + #> <__main__.Pet object at 0x0123456789ab> + print(model.pet.name) + #> Hedwig + print(type(model.pet)) + #> + try: + # If the value is not an instance of the type, it's invalid + Model(owner='Harry', pet='Hedwig') + except ValidationError as e: + print(e) + ''' + 1 validation error for Model + pet + Input should be an instance of Pet [type=is_instance_of, input_value='Hedwig', input_type=str] + ''' + + # Nothing in the instance of the arbitrary type is checked + # Here name probably should have been a str, but it's not validated + pet2 = Pet(name=42) + model2 = Model(owner='Harry', pet=pet2) + print(model2) + #> pet=<__main__.Pet object at 0x0123456789ab> owner='Harry' + print(model2.pet) + #> <__main__.Pet object at 0x0123456789ab> + print(model2.pet.name) + #> 42 + print(type(model2.pet)) + #> + ``` + """ + + from_attributes: bool + """ + Whether to build models and look up discriminators of tagged unions using python object attributes. + """ + + loc_by_alias: bool + """Whether to use the actual key provided in the data (e.g. alias) for error `loc`s rather than the field's name. Defaults to `True`.""" + + alias_generator: Callable[[str], str] | AliasGenerator | None + """ + A callable that takes a field name and returns an alias for it + or an instance of [`AliasGenerator`][pydantic.aliases.AliasGenerator]. Defaults to `None`. + + When using a callable, the alias generator is used for both validation and serialization. + If you want to use different alias generators for validation and serialization, you can use + [`AliasGenerator`][pydantic.aliases.AliasGenerator] instead. + + If data source field names do not match your code style (e.g. CamelCase fields), + you can automatically generate aliases using `alias_generator`. Here's an example with + a basic callable: + + ```python + from pydantic import BaseModel, ConfigDict + from pydantic.alias_generators import to_pascal + + class Voice(BaseModel): + model_config = ConfigDict(alias_generator=to_pascal) + + name: str + language_code: str + + voice = Voice(Name='Filiz', LanguageCode='tr-TR') + print(voice.language_code) + #> tr-TR + print(voice.model_dump(by_alias=True)) + #> {'Name': 'Filiz', 'LanguageCode': 'tr-TR'} + ``` + + If you want to use different alias generators for validation and serialization, you can use + [`AliasGenerator`][pydantic.aliases.AliasGenerator]. + + ```python + from pydantic import AliasGenerator, BaseModel, ConfigDict + from pydantic.alias_generators import to_camel, to_pascal + + class Athlete(BaseModel): + first_name: str + last_name: str + sport: str + + model_config = ConfigDict( + alias_generator=AliasGenerator( + validation_alias=to_camel, + serialization_alias=to_pascal, + ) + ) + + athlete = Athlete(firstName='John', lastName='Doe', sport='track') + print(athlete.model_dump(by_alias=True)) + #> {'FirstName': 'John', 'LastName': 'Doe', 'Sport': 'track'} + ``` + + Note: + Pydantic offers three built-in alias generators: [`to_pascal`][pydantic.alias_generators.to_pascal], + [`to_camel`][pydantic.alias_generators.to_camel], and [`to_snake`][pydantic.alias_generators.to_snake]. + """ + + ignored_types: tuple[type, ...] + """A tuple of types that may occur as values of class attributes without annotations. This is + typically used for custom descriptors (classes that behave like `property`). If an attribute is set on a + class without an annotation and has a type that is not in this tuple (or otherwise recognized by + _pydantic_), an error will be raised. Defaults to `()`. + """ + + allow_inf_nan: bool + """Whether to allow infinity (`+inf` an `-inf`) and NaN values to float and decimal fields. Defaults to `True`.""" + + json_schema_extra: JsonDict | JsonSchemaExtraCallable | None + """A dict or callable to provide extra JSON schema properties. Defaults to `None`.""" + + json_encoders: dict[type[object], JsonEncoder] | None + """ + A `dict` of custom JSON encoders for specific types. Defaults to `None`. + + /// version-deprecated | v2 + This configuration option is a carryover from v1. We originally planned to remove it in v2 but didn't have a 1:1 replacement + so we are keeping it for now. It is still deprecated and will likely be removed in the future. + /// + """ + + # new in V2 + strict: bool + """ + Whether strict validation is applied to all fields on the model. + + By default, Pydantic attempts to coerce values to the correct type, when possible. + + There are situations in which you may want to disable this behavior, and instead raise an error if a value's type + does not match the field's type annotation. + + To configure strict mode for all fields on a model, you can set `strict=True` on the model. + + ```python + from pydantic import BaseModel, ConfigDict + + class Model(BaseModel): + model_config = ConfigDict(strict=True) + + name: str + age: int + ``` + + See [Strict Mode](../concepts/strict_mode.md) for more details. + + See the [Conversion Table](../concepts/conversion_table.md) for more details on how Pydantic converts data in both + strict and lax modes. + + /// version-added | v2 + /// + """ + # whether instances of models and dataclasses (including subclass instances) should re-validate, default 'never' + revalidate_instances: Literal['always', 'never', 'subclass-instances'] + """ + When and how to revalidate models and dataclasses during validation. Can be one of: + + - `'never'`: will *not* revalidate models and dataclasses during validation + - `'always'`: will revalidate models and dataclasses during validation + - `'subclass-instances'`: will revalidate models and dataclasses during validation if the instance is a + subclass of the model or dataclass + + The default is `'never'` (no revalidation). + + This configuration only affects *the current model* it is applied on, and does *not* populate to the models + referenced in fields. + + ```python + from pydantic import BaseModel + + class User(BaseModel, revalidate_instances='never'): # (1)! + name: str + + class Transaction(BaseModel): + user: User + + my_user = User(name='John') + t = Transaction(user=my_user) + + my_user.name = 1 # (2)! + t = Transaction(user=my_user) # (3)! + print(t) + #> user=User(name=1) + ``` + + 1. This is the default behavior. + 2. The assignment is *not* validated, unless you set [`validate_assignment`][pydantic.ConfigDict.validate_assignment] in the configuration. + 3. Since `revalidate_instances` is set to `'never'`, the user instance is not revalidated. + + Here is an example demonstrating the behavior of `'subclass-instances'`: + + ```python + from pydantic import BaseModel + + class User(BaseModel, revalidate_instances='subclass-instances'): + name: str + + class SubUser(User): + age: int + + class Transaction(BaseModel): + user: User + + my_user = User(name='John') + my_user.name = 1 # (1)! + t = Transaction(user=my_user) # (2)! + print(t) + #> user=User(name=1) + + my_sub_user = SubUser(name='John', age=20) + t = Transaction(user=my_sub_user) + print(t) # (3)! + #> user=User(name='John') + ``` + + 1. The assignment is *not* validated, unless you set [`validate_assignment`][pydantic.ConfigDict.validate_assignment] in the configuration. + 2. Because `my_user` is a "direct" instance of `User`, it is *not* being revalidated. It would have been the case if + `revalidate_instances` was set to `'always'`. + 3. Because `my_sub_user` is an instance of a `User` subclass, it is being revalidated. In this case, Pydantic coerces `my_sub_user` to the defined + `User` class defined on `Transaction`. If one of its fields had an invalid value, a validation error would have been raised. + + /// version-added | v2 + /// + """ + + ser_json_timedelta: Literal['iso8601', 'float'] + """ + The format of JSON serialized timedeltas. Accepts the string values of `'iso8601'` and + `'float'`. Defaults to `'iso8601'`. + + - `'iso8601'` will serialize timedeltas to [ISO 8601 text format](https://en.wikipedia.org/wiki/ISO_8601#Durations). + - `'float'` will serialize timedeltas to the total number of seconds. + + /// version-changed | v2.12 + It is now recommended to use the [`ser_json_temporal`][pydantic.config.ConfigDict.ser_json_temporal] + setting. `ser_json_timedelta` will be deprecated in v3. + /// + """ + + ser_json_temporal: Literal['iso8601', 'seconds', 'milliseconds'] + """ + The format of JSON serialized temporal types from the [`datetime`][] module. This includes: + + - [`datetime.datetime`][] + - [`datetime.date`][] + - [`datetime.time`][] + - [`datetime.timedelta`][] + + Can be one of: + + - `'iso8601'` will serialize date-like types to [ISO 8601 text format](https://en.wikipedia.org/wiki/ISO_8601#Durations). + - `'milliseconds'` will serialize date-like types to a floating point number of milliseconds since the epoch. + - `'seconds'` will serialize date-like types to a floating point number of seconds since the epoch. + + Defaults to `'iso8601'`. + + /// version-added | v2.12 + This setting replaces [`ser_json_timedelta`][pydantic.config.ConfigDict.ser_json_timedelta], + which will be deprecated in v3. `ser_json_temporal` adds more configurability for the other temporal types. + /// + """ + + val_temporal_unit: Literal['seconds', 'milliseconds', 'infer'] + """ + The unit to assume for validating numeric input for datetime-like types ([`datetime.datetime`][] and [`datetime.date`][]). Can be one of: + + - `'seconds'` will validate date or time numeric inputs as seconds since the [epoch]. + - `'milliseconds'` will validate date or time numeric inputs as milliseconds since the [epoch]. + - `'infer'` will infer the unit from the string numeric input on unix time as: + + * seconds since the [epoch] if $-2^{10} <= v <= 2^{10}$ + * milliseconds since the [epoch] (if $v < -2^{10}$ or $v > 2^{10}$). + + Defaults to `'infer'`. + + /// version-added | v2.12 + /// + + [epoch]: https://en.wikipedia.org/wiki/Unix_time + """ + + ser_json_bytes: Literal['utf8', 'base64', 'hex'] + """ + The encoding of JSON serialized bytes. Defaults to `'utf8'`. + Set equal to `val_json_bytes` to get back an equal value after serialization round trip. + + - `'utf8'` will serialize bytes to UTF-8 strings. + - `'base64'` will serialize bytes to URL safe base64 strings. + - `'hex'` will serialize bytes to hexadecimal strings. + """ + + val_json_bytes: Literal['utf8', 'base64', 'hex'] + """ + The encoding of JSON serialized bytes to decode. Defaults to `'utf8'`. + Set equal to `ser_json_bytes` to get back an equal value after serialization round trip. + + - `'utf8'` will deserialize UTF-8 strings to bytes. + - `'base64'` will deserialize URL safe base64 strings to bytes. + - `'hex'` will deserialize hexadecimal strings to bytes. + """ + + ser_json_inf_nan: Literal['null', 'constants', 'strings'] + """ + The encoding of JSON serialized infinity and NaN float values. Defaults to `'null'`. + + - `'null'` will serialize infinity and NaN values as `null`. + - `'constants'` will serialize infinity and NaN values as `Infinity` and `NaN`. + - `'strings'` will serialize infinity as string `"Infinity"` and NaN as string `"NaN"`. + """ + + # whether to validate default values during validation, default False + validate_default: bool + """Whether to validate default values during validation. Defaults to `False`.""" + + validate_return: bool + """Whether to validate the return value from call validators. Defaults to `False`.""" + + protected_namespaces: tuple[str | Pattern[str], ...] + """ + A tuple of strings and/or regex patterns that prevent models from having fields with names that conflict with its existing members/methods. + + Strings are matched on a prefix basis. For instance, with `'dog'`, having a field named `'dog_name'` will be disallowed. + + Regex patterns are matched on the entire field name. For instance, with the pattern `'^dog$'`, having a field named `'dog'` will be disallowed, + but `'dog_name'` will be accepted. + + Defaults to `('model_validate', 'model_dump')`. This default is used to prevent collisions with the existing (and possibly future) + [validation](../concepts/models.md#validating-data) and [serialization](../concepts/serialization.md#serializing-data) methods. + + ```python + import warnings + + from pydantic import BaseModel + + warnings.filterwarnings('error') # Raise warnings as errors + + try: + + class Model(BaseModel): + model_dump_something: str + + except UserWarning as e: + print(e) + ''' + Field 'model_dump_something' in 'Model' conflicts with protected namespace 'model_dump'. + + You may be able to solve this by setting the 'protected_namespaces' configuration to ('model_validate',). + ''' + ``` + + You can customize this behavior using the `protected_namespaces` setting: + + ```python {test="skip"} + import re + import warnings + + from pydantic import BaseModel, ConfigDict + + with warnings.catch_warnings(record=True) as caught_warnings: + warnings.simplefilter('always') # Catch all warnings + + class Model(BaseModel): + safe_field: str + also_protect_field: str + protect_this: str + + model_config = ConfigDict( + protected_namespaces=( + 'protect_me_', + 'also_protect_', + re.compile('^protect_this$'), + ) + ) + + for warning in caught_warnings: + print(f'{warning.message}') + ''' + Field 'also_protect_field' in 'Model' conflicts with protected namespace 'also_protect_'. + You may be able to solve this by setting the 'protected_namespaces' configuration to ('protect_me_', re.compile('^protect_this$'))`. + + Field 'protect_this' in 'Model' conflicts with protected namespace 're.compile('^protect_this$')'. + You may be able to solve this by setting the 'protected_namespaces' configuration to ('protect_me_', 'also_protect_')`. + ''' + ``` + + While Pydantic will only emit a warning when an item is in a protected namespace but does not actually have a collision, + an error _is_ raised if there is an actual collision with an existing attribute: + + ```python + from pydantic import BaseModel, ConfigDict + + try: + + class Model(BaseModel): + model_validate: str + + model_config = ConfigDict(protected_namespaces=('model_',)) + + except ValueError as e: + print(e) + ''' + Field 'model_validate' conflicts with member > of protected namespace 'model_'. + ''' + ``` + + /// version-changed | v2.10 + The default protected namespaces was changed from `('model_',)` to `('model_validate', 'model_dump')`, to allow + for fields like `model_id`, `model_name` to be used. + /// + """ + + hide_input_in_errors: bool + """ + Whether to hide inputs when printing errors. Defaults to `False`. + + Pydantic shows the input value and type when it raises `ValidationError` during the validation. + + ```python + from pydantic import BaseModel, ValidationError + + class Model(BaseModel): + a: str + + try: + Model(a=123) + except ValidationError as e: + print(e) + ''' + 1 validation error for Model + a + Input should be a valid string [type=string_type, input_value=123, input_type=int] + ''' + ``` + + You can hide the input value and type by setting the `hide_input_in_errors` config to `True`. + + ```python + from pydantic import BaseModel, ConfigDict, ValidationError + + class Model(BaseModel): + a: str + model_config = ConfigDict(hide_input_in_errors=True) + + try: + Model(a=123) + except ValidationError as e: + print(e) + ''' + 1 validation error for Model + a + Input should be a valid string [type=string_type] + ''' + ``` + """ + + defer_build: bool + """ + Whether to defer model validator and serializer construction until the first model validation. Defaults to False. + + This can be useful to avoid the overhead of building models which are only + used nested within other models, or when you want to manually define type namespace via + [`Model.model_rebuild(_types_namespace=...)`][pydantic.BaseModel.model_rebuild]. + + /// version-changed | v2.10 + The setting also applies to [Pydantic dataclasses](../concepts/dataclasses.md) and [type adapters](../concepts/type_adapter.md). + /// + """ + + plugin_settings: dict[str, object] | None + """A `dict` of settings for plugins. Defaults to `None`.""" + + schema_generator: type[_GenerateSchema] | None + """ + The `GenerateSchema` class to use during core schema generation. + + /// version-deprecated | v2.10 + The `GenerateSchema` class is private and highly subject to change. + /// + """ + + json_schema_serialization_defaults_required: bool + """ + Whether fields with default values should be marked as required in the serialization schema. Defaults to `False`. + + This ensures that the serialization schema will reflect the fact a field with a default will always be present + when serializing the model, even though it is not required for validation. + + However, there are scenarios where this may be undesirable — in particular, if you want to share the schema + between validation and serialization, and don't mind fields with defaults being marked as not required during + serialization. See [#7209](https://github.com/pydantic/pydantic/issues/7209) for more details. + + ```python + from pydantic import BaseModel, ConfigDict + + class Model(BaseModel): + a: str = 'a' + + model_config = ConfigDict(json_schema_serialization_defaults_required=True) + + print(Model.model_json_schema(mode='validation')) + ''' + { + 'properties': {'a': {'default': 'a', 'title': 'A', 'type': 'string'}}, + 'title': 'Model', + 'type': 'object', + } + ''' + print(Model.model_json_schema(mode='serialization')) + ''' + { + 'properties': {'a': {'default': 'a', 'title': 'A', 'type': 'string'}}, + 'required': ['a'], + 'title': 'Model', + 'type': 'object', + } + ''' + ``` + + /// version-added | v2.4 + /// + """ + + json_schema_mode_override: Literal['validation', 'serialization', None] + """ + If not `None`, the specified mode will be used to generate the JSON schema regardless of what `mode` was passed to + the function call. Defaults to `None`. + + This provides a way to force the JSON schema generation to reflect a specific mode, e.g., to always use the + validation schema. + + It can be useful when using frameworks (such as FastAPI) that may generate different schemas for validation + and serialization that must both be referenced from the same schema; when this happens, we automatically append + `-Input` to the definition reference for the validation schema and `-Output` to the definition reference for the + serialization schema. By specifying a `json_schema_mode_override` though, this prevents the conflict between + the validation and serialization schemas (since both will use the specified schema), and so prevents the suffixes + from being added to the definition references. + + ```python + from pydantic import BaseModel, ConfigDict, Json + + class Model(BaseModel): + a: Json[int] # requires a string to validate, but will dump an int + + print(Model.model_json_schema(mode='serialization')) + ''' + { + 'properties': {'a': {'title': 'A', 'type': 'integer'}}, + 'required': ['a'], + 'title': 'Model', + 'type': 'object', + } + ''' + + class ForceInputModel(Model): + # the following ensures that even with mode='serialization', we + # will get the schema that would be generated for validation. + model_config = ConfigDict(json_schema_mode_override='validation') + + print(ForceInputModel.model_json_schema(mode='serialization')) + ''' + { + 'properties': { + 'a': { + 'contentMediaType': 'application/json', + 'contentSchema': {'type': 'integer'}, + 'title': 'A', + 'type': 'string', + } + }, + 'required': ['a'], + 'title': 'ForceInputModel', + 'type': 'object', + } + ''' + ``` + + /// version-added | v2.4 + /// + """ + + coerce_numbers_to_str: bool + """ + If `True`, enables automatic coercion of any `Number` type to `str` in "lax" (non-strict) mode. Defaults to `False`. + + Pydantic doesn't allow number types (`int`, `float`, `Decimal`) to be coerced as type `str` by default. + + ```python + from decimal import Decimal + + from pydantic import BaseModel, ConfigDict, ValidationError + + class Model(BaseModel): + value: str + + try: + print(Model(value=42)) + except ValidationError as e: + print(e) + ''' + 1 validation error for Model + value + Input should be a valid string [type=string_type, input_value=42, input_type=int] + ''' + + class Model(BaseModel): + model_config = ConfigDict(coerce_numbers_to_str=True) + + value: str + + repr(Model(value=42).value) + #> "42" + repr(Model(value=42.13).value) + #> "42.13" + repr(Model(value=Decimal('42.13')).value) + #> "42.13" + ``` + """ + + regex_engine: Literal['rust-regex', 'python-re'] + """ + The regex engine to be used for pattern validation. + Defaults to `'rust-regex'`. + + - `'rust-regex'` uses the [`regex`](https://docs.rs/regex) Rust crate, + which is non-backtracking and therefore more DDoS resistant, but does not support all regex features. + - `'python-re'` use the [`re`][] module, which supports all regex features, but may be slower. + + !!! note + If you use a compiled regex pattern, the `'python-re'` engine will be used regardless of this setting. + This is so that flags such as [`re.IGNORECASE`][] are respected. + + ```python + from pydantic import BaseModel, ConfigDict, Field, ValidationError + + class Model(BaseModel): + model_config = ConfigDict(regex_engine='python-re') + + value: str = Field(pattern=r'^abc(?=def)') + + print(Model(value='abcdef').value) + #> abcdef + + try: + print(Model(value='abxyzcdef')) + except ValidationError as e: + print(e) + ''' + 1 validation error for Model + value + String should match pattern '^abc(?=def)' [type=string_pattern_mismatch, input_value='abxyzcdef', input_type=str] + ''' + ``` + + /// version-added | v2.5 + /// + """ + + validation_error_cause: bool + """ + If `True`, Python exceptions that were part of a validation failure will be shown as an exception group as a cause. Can be useful for debugging. Defaults to `False`. + + Note: + Python 3.10 and older don't support exception groups natively. <=3.10, backport must be installed: `pip install exceptiongroup`. + + Note: + The structure of validation errors are likely to change in future Pydantic versions. Pydantic offers no guarantees about their structure. Should be used for visual traceback debugging only. + + /// version-added | v2.5 + /// + """ + + use_attribute_docstrings: bool + ''' + Whether docstrings of attributes (bare string literals immediately following the attribute declaration) + should be used for field descriptions. Defaults to `False`. + + ```python + from pydantic import BaseModel, ConfigDict, Field + + + class Model(BaseModel): + model_config = ConfigDict(use_attribute_docstrings=True) + + x: str + """ + Example of an attribute docstring + """ + + y: int = Field(description="Description in Field") + """ + Description in Field overrides attribute docstring + """ + + + print(Model.model_fields["x"].description) + # > Example of an attribute docstring + print(Model.model_fields["y"].description) + # > Description in Field + ``` + This requires the source code of the class to be available at runtime. + + !!! warning "Usage with `TypedDict` and stdlib dataclasses" + Due to current limitations, attribute docstrings detection may not work as expected when using + [`TypedDict`][typing.TypedDict] and stdlib dataclasses, in particular when: + + - inheritance is being used. + - multiple classes have the same name in the same source file (unless Python 3.13 or greater is used). + + /// version-added | v2.7 + /// + ''' + + cache_strings: bool | Literal['all', 'keys', 'none'] + """ + Whether to cache strings to avoid constructing new Python objects. Defaults to True. + + Enabling this setting should significantly improve validation performance while increasing memory usage slightly. + + - `True` or `'all'` (the default): cache all strings + - `'keys'`: cache only dictionary keys + - `False` or `'none'`: no caching + + !!! note + `True` or `'all'` is required to cache strings during general validation because + validators don't know if they're in a key or a value. + + !!! tip + If repeated strings are rare, it's recommended to use `'keys'` or `'none'` to reduce memory usage, + as the performance difference is minimal if repeated strings are rare. + + /// version-added | v2.7 + /// + """ + + validate_by_alias: bool + """ + Whether an aliased field may be populated by its alias. Defaults to `True`. + + Here's an example of disabling validation by alias: + + ```py + from pydantic import BaseModel, ConfigDict, Field + + class Model(BaseModel): + model_config = ConfigDict(validate_by_name=True, validate_by_alias=False) + + my_field: str = Field(validation_alias='my_alias') # (1)! + + m = Model(my_field='foo') # (2)! + print(m) + #> my_field='foo' + ``` + + 1. The field `'my_field'` has an alias `'my_alias'`. + 2. The model can only be populated by the attribute name `'my_field'`. + + !!! warning + You cannot set both `validate_by_alias` and `validate_by_name` to `False`. + This would make it impossible to populate an attribute. + + See [usage errors](../errors/usage_errors.md#validate-by-alias-and-name-false) for an example. + + If you set `validate_by_alias` to `False`, under the hood, Pydantic dynamically sets + `validate_by_name` to `True` to ensure that validation can still occur. + + /// version-added | v2.11 + This setting was introduced in conjunction with [`validate_by_name`][pydantic.ConfigDict.validate_by_name] + to empower users with more fine grained validation control. + /// + """ + + validate_by_name: bool + """ + Whether an aliased field may be populated by its name as given by the model + attribute. Defaults to `False`. + + ```python + from pydantic import BaseModel, ConfigDict, Field + + class Model(BaseModel): + model_config = ConfigDict(validate_by_name=True, validate_by_alias=True) + + my_field: str = Field(validation_alias='my_alias') # (1)! + + m = Model(my_alias='foo') # (2)! + print(m) + #> my_field='foo' + + m = Model(my_field='foo') # (3)! + print(m) + #> my_field='foo' + ``` + + 1. The field `'my_field'` has an alias `'my_alias'`. + 2. The model is populated by the alias `'my_alias'`. + 3. The model is populated by the attribute name `'my_field'`. + + !!! warning + You cannot set both `validate_by_alias` and `validate_by_name` to `False`. + This would make it impossible to populate an attribute. + + See [usage errors](../errors/usage_errors.md#validate-by-alias-and-name-false) for an example. + + /// version-added | v2.11 + This setting was introduced in conjunction with [`validate_by_alias`][pydantic.ConfigDict.validate_by_alias] + to empower users with more fine grained validation control. It is an alternative to [`populate_by_name`][pydantic.ConfigDict.populate_by_name], + that enables validation by name **and** by alias. + /// + """ + + serialize_by_alias: bool + """ + Whether an aliased field should be serialized by its alias. Defaults to `False`. + + Note: In v2.11, `serialize_by_alias` was introduced to address the + [popular request](https://github.com/pydantic/pydantic/issues/8379) + for consistency with alias behavior for validation and serialization settings. + In v3, the default value is expected to change to `True` for consistency with the validation default. + + ```python + from pydantic import BaseModel, ConfigDict, Field + + class Model(BaseModel): + model_config = ConfigDict(serialize_by_alias=True) + + my_field: str = Field(serialization_alias='my_alias') # (1)! + + m = Model(my_field='foo') + print(m.model_dump()) # (2)! + #> {'my_alias': 'foo'} + ``` + + 1. The field `'my_field'` has an alias `'my_alias'`. + 2. The model is serialized using the alias `'my_alias'` for the `'my_field'` attribute. + + + /// version-added | v2.11 + This setting was introduced to address the [popular request](https://github.com/pydantic/pydantic/issues/8379) + for consistency with alias behavior for validation and serialization. + + In v3, the default value is expected to change to `True` for consistency with the validation default. + /// + """ + + url_preserve_empty_path: bool + """ + Whether to preserve empty URL paths when validating values for a URL type. Defaults to `False`. + + ```python + from pydantic import AnyUrl, BaseModel, ConfigDict + + class Model(BaseModel): + model_config = ConfigDict(url_preserve_empty_path=True) + + url: AnyUrl + + m = Model(url='http://example.com') + print(m.url) + #> http://example.com + ``` + + /// version-added | v2.12 + /// + """ + + +_TypeT = TypeVar('_TypeT', bound=type) + + +@overload +@deprecated('Passing `config` as a keyword argument is deprecated. Pass `config` as a positional argument instead.') +def with_config(*, config: ConfigDict) -> Callable[[_TypeT], _TypeT]: ... + + +@overload +def with_config(config: ConfigDict, /) -> Callable[[_TypeT], _TypeT]: ... + + +@overload +def with_config(**config: Unpack[ConfigDict]) -> Callable[[_TypeT], _TypeT]: ... + + +def with_config(config: ConfigDict | None = None, /, **kwargs: Any) -> Callable[[_TypeT], _TypeT]: + """!!! abstract "Usage Documentation" + [Configuration with other types](../concepts/config.md#configuration-on-other-supported-types) + + A convenience decorator to set a [Pydantic configuration](config.md) on a `TypedDict` or a `dataclass` from the standard library. + + Although the configuration can be set using the `__pydantic_config__` attribute, it does not play well with type checkers, + especially with `TypedDict`. + + !!! example "Usage" + + ```python + from typing_extensions import TypedDict + + from pydantic import ConfigDict, TypeAdapter, with_config + + @with_config(ConfigDict(str_to_lower=True)) + class TD(TypedDict): + x: str + + ta = TypeAdapter(TD) + + print(ta.validate_python({'x': 'ABC'})) + #> {'x': 'abc'} + ``` + + /// deprecated-removed | v2.11 v3 + Passing `config` as a keyword argument. + /// + + /// version-changed | v2.11 + Keyword arguments can be provided directly instead of a config dictionary. + /// + """ + if config is not None and kwargs: + raise ValueError('Cannot specify both `config` and keyword arguments') + + if len(kwargs) == 1 and (kwargs_conf := kwargs.get('config')) is not None: + warnings.warn( + 'Passing `config` as a keyword argument is deprecated. Pass `config` as a positional argument instead', + category=PydanticDeprecatedSince211, + stacklevel=2, + ) + final_config = cast(ConfigDict, kwargs_conf) + else: + final_config = config if config is not None else cast(ConfigDict, kwargs) + + def inner(class_: _TypeT, /) -> _TypeT: + # Ideally, we would check for `class_` to either be a `TypedDict` or a stdlib dataclass. + # However, the `@with_config` decorator can be applied *after* `@dataclass`. To avoid + # common mistakes, we at least check for `class_` to not be a Pydantic model. + from ._internal._utils import is_model_class + + if is_model_class(class_): + raise PydanticUserError( + f'Cannot use `with_config` on {class_.__name__} as it is a Pydantic model', + code='with-config-on-model', + ) + class_.__pydantic_config__ = final_config + return class_ + + return inner + + +__getattr__ = getattr_migration(__name__) diff --git a/backend/.venv/Lib/site-packages/pydantic/dataclasses.py b/backend/.venv/Lib/site-packages/pydantic/dataclasses.py new file mode 100644 index 0000000..cecd540 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/dataclasses.py @@ -0,0 +1,413 @@ +"""Provide an enhanced dataclass that performs validation.""" + +from __future__ import annotations as _annotations + +import dataclasses +import functools +import sys +import types +from typing import TYPE_CHECKING, Any, Callable, Generic, Literal, NoReturn, TypeVar, overload +from warnings import warn + +from typing_extensions import TypeGuard, dataclass_transform + +from ._internal import _config, _decorators, _mock_val_ser, _namespace_utils, _typing_extra +from ._internal import _dataclasses as _pydantic_dataclasses +from ._migration import getattr_migration +from .config import ConfigDict +from .errors import PydanticUserError +from .fields import Field, FieldInfo, PrivateAttr + +if TYPE_CHECKING: + from ._internal._dataclasses import PydanticDataclass + from ._internal._namespace_utils import MappingNamespace + +__all__ = 'dataclass', 'rebuild_dataclass' + +_T = TypeVar('_T') + +if sys.version_info >= (3, 10): + + @dataclass_transform(field_specifiers=(dataclasses.field, Field, PrivateAttr)) + @overload + def dataclass( + *, + init: Literal[False] = False, + repr: bool = True, + eq: bool = True, + order: bool = False, + unsafe_hash: bool = False, + frozen: bool = False, + config: ConfigDict | type[object] | None = None, + validate_on_init: bool | None = None, + kw_only: bool = ..., + slots: bool = ..., + ) -> Callable[[type[_T]], type[PydanticDataclass]]: # type: ignore + ... + + @dataclass_transform(field_specifiers=(dataclasses.field, Field, PrivateAttr)) + @overload + def dataclass( + _cls: type[_T], # type: ignore + *, + init: Literal[False] = False, + repr: bool = True, + eq: bool = True, + order: bool = False, + unsafe_hash: bool = False, + frozen: bool | None = None, + config: ConfigDict | type[object] | None = None, + validate_on_init: bool | None = None, + kw_only: bool = ..., + slots: bool = ..., + ) -> type[PydanticDataclass]: ... + +else: + + @dataclass_transform(field_specifiers=(dataclasses.field, Field, PrivateAttr)) + @overload + def dataclass( + *, + init: Literal[False] = False, + repr: bool = True, + eq: bool = True, + order: bool = False, + unsafe_hash: bool = False, + frozen: bool | None = None, + config: ConfigDict | type[object] | None = None, + validate_on_init: bool | None = None, + ) -> Callable[[type[_T]], type[PydanticDataclass]]: # type: ignore + ... + + @dataclass_transform(field_specifiers=(dataclasses.field, Field, PrivateAttr)) + @overload + def dataclass( + _cls: type[_T], # type: ignore + *, + init: Literal[False] = False, + repr: bool = True, + eq: bool = True, + order: bool = False, + unsafe_hash: bool = False, + frozen: bool | None = None, + config: ConfigDict | type[object] | None = None, + validate_on_init: bool | None = None, + ) -> type[PydanticDataclass]: ... + + +@dataclass_transform(field_specifiers=(dataclasses.field, Field, PrivateAttr)) +def dataclass( + _cls: type[_T] | None = None, + *, + init: Literal[False] = False, + repr: bool = True, + eq: bool = True, + order: bool = False, + unsafe_hash: bool = False, + frozen: bool | None = None, + config: ConfigDict | type[object] | None = None, + validate_on_init: bool | None = None, + kw_only: bool = False, + slots: bool = False, +) -> Callable[[type[_T]], type[PydanticDataclass]] | type[PydanticDataclass]: + """!!! abstract "Usage Documentation" + [`dataclasses`](../concepts/dataclasses.md) + + A decorator used to create a Pydantic-enhanced dataclass, similar to the standard Python `dataclass`, + but with added validation. + + This function should be used similarly to `dataclasses.dataclass`. + + Args: + _cls: The target `dataclass`. + init: Included for signature compatibility with `dataclasses.dataclass`, and is passed through to + `dataclasses.dataclass` when appropriate. If specified, must be set to `False`, as pydantic inserts its + own `__init__` function. + repr: A boolean indicating whether to include the field in the `__repr__` output. + eq: Determines if a `__eq__` method should be generated for the class. + order: Determines if comparison magic methods should be generated, such as `__lt__`, but not `__eq__`. + unsafe_hash: Determines if a `__hash__` method should be included in the class, as in `dataclasses.dataclass`. + frozen: Determines if the generated class should be a 'frozen' `dataclass`, which does not allow its + attributes to be modified after it has been initialized. If not set, the value from the provided `config` argument will be used (and will default to `False` otherwise). + config: The Pydantic config to use for the `dataclass`. + validate_on_init: A deprecated parameter included for backwards compatibility; in V2, all Pydantic dataclasses + are validated on init. + kw_only: Determines if `__init__` method parameters must be specified by keyword only. Defaults to `False`. + slots: Determines if the generated class should be a 'slots' `dataclass`, which does not allow the addition of + new attributes after instantiation. + + Returns: + A decorator that accepts a class as its argument and returns a Pydantic `dataclass`. + + Raises: + AssertionError: Raised if `init` is not `False` or `validate_on_init` is `False`. + """ + assert init is False, 'pydantic.dataclasses.dataclass only supports init=False' + assert validate_on_init is not False, 'validate_on_init=False is no longer supported' + + if sys.version_info >= (3, 10): + kwargs = {'kw_only': kw_only, 'slots': slots} + else: + kwargs = {} + + def create_dataclass(cls: type[Any]) -> type[PydanticDataclass]: + """Create a Pydantic dataclass from a regular dataclass. + + Args: + cls: The class to create the Pydantic dataclass from. + + Returns: + A Pydantic dataclass. + """ + from ._internal._utils import is_model_class + + if is_model_class(cls): + raise PydanticUserError( + f'Cannot create a Pydantic dataclass from {cls.__name__} as it is already a Pydantic model', + code='dataclass-on-model', + ) + + original_cls = cls + + # we warn on conflicting config specifications, but only if the class doesn't have a dataclass base + # because a dataclass base might provide a __pydantic_config__ attribute that we don't want to warn about + has_dataclass_base = any(dataclasses.is_dataclass(base) for base in cls.__bases__) + if not has_dataclass_base and config is not None and hasattr(cls, '__pydantic_config__'): + warn( + f'`config` is set via both the `dataclass` decorator and `__pydantic_config__` for dataclass {cls.__name__}. ' + f'The `config` specification from `dataclass` decorator will take priority.', + category=UserWarning, + stacklevel=2, + ) + + # if config is not explicitly provided, try to read it from the type + config_dict = config if config is not None else getattr(cls, '__pydantic_config__', None) + config_wrapper = _config.ConfigWrapper(config_dict) + decorators = _decorators.DecoratorInfos.build(cls) + decorators.update_from_config(config_wrapper) + + # Keep track of the original __doc__ so that we can restore it after applying the dataclasses decorator + # Otherwise, classes with no __doc__ will have their signature added into the JSON schema description, + # since dataclasses.dataclass will set this as the __doc__ + original_doc = cls.__doc__ + + if _pydantic_dataclasses.is_stdlib_dataclass(cls): + # Vanilla dataclasses include a default docstring (representing the class signature), + # which we don't want to preserve. + original_doc = None + + # We don't want to add validation to the existing std lib dataclass, so we will subclass it + # If the class is generic, we need to make sure the subclass also inherits from Generic + # with all the same parameters. + bases = (cls,) + if issubclass(cls, Generic): + generic_base = Generic[cls.__parameters__] # type: ignore + bases = bases + (generic_base,) + cls = types.new_class(cls.__name__, bases) + + # Respect frozen setting from dataclass constructor and fallback to config setting if not provided + if frozen is not None: + frozen_ = frozen + if config_wrapper.frozen: + # It's not recommended to define both, as the setting from the dataclass decorator will take priority. + warn( + f'`frozen` is set via both the `dataclass` decorator and `config` for dataclass {cls.__name__!r}.' + 'This is not recommended. The `frozen` specification on `dataclass` will take priority.', + category=UserWarning, + stacklevel=2, + ) + else: + frozen_ = config_wrapper.frozen or False + + # Make Pydantic's `Field()` function compatible with stdlib dataclasses. As we'll decorate + # `cls` with the stdlib `@dataclass` decorator first, there are two attributes, `kw_only` and + # `repr` that need to be understood *during* the stdlib creation. We do so in two steps: + + # 1. On the decorated class, wrap `Field()` assignment with `dataclass.field()`, with the + # two attributes set (done in `as_dataclass_field()`) + cls_anns = _typing_extra.safe_get_annotations(cls) + for field_name in cls_anns: + # We should look for assignments in `__dict__` instead, but for now we follow + # the same behavior as stdlib dataclasses (see https://github.com/python/cpython/issues/88609) + field_value = getattr(cls, field_name, None) + if isinstance(field_value, FieldInfo): + setattr(cls, field_name, _pydantic_dataclasses.as_dataclass_field(field_value)) + + # 2. For bases of `cls` that are stdlib dataclasses, we temporarily patch their fields + # (see the docstring of the context manager): + with _pydantic_dataclasses.patch_base_fields(cls): + cls = dataclasses.dataclass( # pyright: ignore[reportCallIssue] + cls, + # the value of init here doesn't affect anything except that it makes it easier to generate a signature + init=True, + repr=repr, + eq=eq, + order=order, + unsafe_hash=unsafe_hash, + frozen=frozen_, + **kwargs, + ) + + if config_wrapper.validate_assignment: + original_setattr = cls.__setattr__ + + @functools.wraps(cls.__setattr__) + def validated_setattr(instance: PydanticDataclass, name: str, value: Any, /) -> None: + if frozen_: + return original_setattr(instance, name, value) # pyright: ignore[reportCallIssue] + inst_cls = type(instance) + attr = getattr(inst_cls, name, None) + + if isinstance(attr, property): + attr.__set__(instance, value) + elif isinstance(attr, functools.cached_property): + instance.__dict__.__setitem__(name, value) + else: + inst_cls.__pydantic_validator__.validate_assignment(instance, name, value) + + cls.__setattr__ = validated_setattr.__get__(None, cls) # type: ignore + + if slots and not hasattr(cls, '__setstate__'): + # If slots is set, `pickle` (relied on by `copy.copy()`) will use + # `__setattr__()` to reconstruct the dataclass. However, the custom + # `__setattr__()` set above relies on `validate_assignment()`, which + # in turn expects all the field values to be already present on the + # instance, resulting in attribute errors. + # As such, we make use of `object.__setattr__()` instead. + # Note that we do so only if `__setstate__()` isn't already set (this is the + # case if on top of `slots`, `frozen` is used). + + # Taken from `dataclasses._dataclass_get/setstate()`: + def _dataclass_getstate(self: Any) -> list[Any]: + return [getattr(self, f.name) for f in dataclasses.fields(self)] + + def _dataclass_setstate(self: Any, state: list[Any]) -> None: + for field, value in zip(dataclasses.fields(self), state): + object.__setattr__(self, field.name, value) + + cls.__getstate__ = _dataclass_getstate # pyright: ignore[reportAttributeAccessIssue] + cls.__setstate__ = _dataclass_setstate # pyright: ignore[reportAttributeAccessIssue] + + # This is an undocumented attribute to distinguish stdlib/Pydantic dataclasses. + # It should be set as early as possible: + cls.__is_pydantic_dataclass__ = True + cls.__pydantic_decorators__ = decorators # type: ignore + cls.__doc__ = original_doc + # Can be non-existent for dynamically created classes: + firstlineno = getattr(original_cls, '__firstlineno__', None) + cls.__module__ = original_cls.__module__ + if sys.version_info >= (3, 13) and firstlineno is not None: + # As per https://docs.python.org/3/reference/datamodel.html#type.__firstlineno__: + # Setting the `__module__` attribute removes the `__firstlineno__` item from the type’s dictionary. + original_cls.__firstlineno__ = firstlineno + cls.__firstlineno__ = firstlineno + cls.__qualname__ = original_cls.__qualname__ + cls.__pydantic_fields_complete__ = classmethod(_pydantic_fields_complete) + cls.__pydantic_complete__ = False # `complete_dataclass` will set it to `True` if successful. + # TODO `parent_namespace` is currently None, but we could do the same thing as Pydantic models: + # fetch the parent ns using `parent_frame_namespace` (if the dataclass was defined in a function), + # and possibly cache it (see the `__pydantic_parent_namespace__` logic for models). + _pydantic_dataclasses.complete_dataclass(cls, config_wrapper, raise_errors=False) + return cls + + return create_dataclass if _cls is None else create_dataclass(_cls) + + +def _pydantic_fields_complete(cls: type[PydanticDataclass]) -> bool: + """Return whether the fields where successfully collected (i.e. type hints were successfully resolves). + + This is a private property, not meant to be used outside Pydantic. + """ + return all(field_info._complete for field_info in cls.__pydantic_fields__.values()) + + +__getattr__ = getattr_migration(__name__) + +if sys.version_info < (3, 11): + # Monkeypatch dataclasses.InitVar so that typing doesn't error if it occurs as a type when evaluating type hints + # Starting in 3.11, typing.get_type_hints will not raise an error if the retrieved type hints are not callable. + + def _call_initvar(*args: Any, **kwargs: Any) -> NoReturn: + """This function does nothing but raise an error that is as similar as possible to what you'd get + if you were to try calling `InitVar[int]()` without this monkeypatch. The whole purpose is just + to ensure typing._type_check does not error if the type hint evaluates to `InitVar[]`. + """ + raise TypeError("'InitVar' object is not callable") + + dataclasses.InitVar.__call__ = _call_initvar + + +def rebuild_dataclass( + cls: type[PydanticDataclass], + *, + force: bool = False, + raise_errors: bool = True, + _parent_namespace_depth: int = 2, + _types_namespace: MappingNamespace | None = None, +) -> bool | None: + """Try to rebuild the pydantic-core schema for the dataclass. + + This may be necessary when one of the annotations is a ForwardRef which could not be resolved during + the initial attempt to build the schema, and automatic rebuilding fails. + + This is analogous to `BaseModel.model_rebuild`. + + Args: + cls: The class to rebuild the pydantic-core schema for. + force: Whether to force the rebuilding of the schema, defaults to `False`. + raise_errors: Whether to raise errors, defaults to `True`. + _parent_namespace_depth: The depth level of the parent namespace, defaults to 2. + _types_namespace: The types namespace, defaults to `None`. + + Returns: + Returns `None` if the schema is already "complete" and rebuilding was not required. + If rebuilding _was_ required, returns `True` if rebuilding was successful, otherwise `False`. + """ + if not force and cls.__pydantic_complete__: + return None + + for attr in ('__pydantic_core_schema__', '__pydantic_validator__', '__pydantic_serializer__'): + if attr in cls.__dict__ and not isinstance(getattr(cls, attr), _mock_val_ser.MockValSer): + # Deleting the validator/serializer is necessary as otherwise they can get reused in + # pydantic-core. Same applies for the core schema that can be reused in schema generation. + delattr(cls, attr) + + cls.__pydantic_complete__ = False + + if _types_namespace is not None: + rebuild_ns = _types_namespace + elif _parent_namespace_depth > 0: + rebuild_ns = _typing_extra.parent_frame_namespace(parent_depth=_parent_namespace_depth, force=True) or {} + else: + rebuild_ns = {} + + ns_resolver = _namespace_utils.NsResolver( + parent_namespace=rebuild_ns, + ) + + return _pydantic_dataclasses.complete_dataclass( + cls, + _config.ConfigWrapper(cls.__pydantic_config__, check=False), + raise_errors=raise_errors, + ns_resolver=ns_resolver, + # We could provide a different config instead (with `'defer_build'` set to `True`) + # of this explicit `_force_build` argument, but because config can come from the + # decorator parameter or the `__pydantic_config__` attribute, `complete_dataclass` + # will overwrite `__pydantic_config__` with the provided config above: + _force_build=True, + ) + + +def is_pydantic_dataclass(class_: type[Any], /) -> TypeGuard[type[PydanticDataclass]]: + """Whether a class is a pydantic dataclass. + + Args: + class_: The class. + + Returns: + `True` if the class is a pydantic dataclass, `False` otherwise. + """ + try: + return '__is_pydantic_dataclass__' in class_.__dict__ and dataclasses.is_dataclass(class_) + except AttributeError: + return False diff --git a/backend/.venv/Lib/site-packages/pydantic/datetime_parse.py b/backend/.venv/Lib/site-packages/pydantic/datetime_parse.py new file mode 100644 index 0000000..53d5264 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/datetime_parse.py @@ -0,0 +1,5 @@ +"""The `datetime_parse` module is a backport module from V1.""" + +from ._migration import getattr_migration + +__getattr__ = getattr_migration(__name__) diff --git a/backend/.venv/Lib/site-packages/pydantic/decorator.py b/backend/.venv/Lib/site-packages/pydantic/decorator.py new file mode 100644 index 0000000..0d97560 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/decorator.py @@ -0,0 +1,5 @@ +"""The `decorator` module is a backport module from V1.""" + +from ._migration import getattr_migration + +__getattr__ = getattr_migration(__name__) diff --git a/backend/.venv/Lib/site-packages/pydantic/deprecated/__init__.py b/backend/.venv/Lib/site-packages/pydantic/deprecated/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/pydantic/deprecated/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/deprecated/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..060217198682fd40652201d32a5fb7ba6353a5f7 GIT binary patch literal 194 zcmX@j%ge<81couTnIQTxh(HIQS%4zb87dhx8U0o=6fpsLpFwJVB|2Nhl;;;^7Z)TZ zr^e)El@#kHCMV~Y=9OgTrRyf=7p2A|B_?O5=B32wm8IsD#rR|<#S~|jr0N1SWGAMl z7RMA+rX&KDC+nxA78Io>Czhn9=*P!r=4F<|$LkeT-r}&y%}*)KNwq6t1=`36#Kj=S NM`lJw#v*1Q3jkHHH0l5V literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/deprecated/__pycache__/class_validators.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/deprecated/__pycache__/class_validators.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..941b5cfd24188beb4d02e093ed45bd44b0d42f18 GIT binary patch literal 11752 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 auZn^otcFCIzB#r^;IR@0!!jCp#Qy>JIJIH` literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/deprecated/__pycache__/copy_internals.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/deprecated/__pycache__/copy_internals.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d504c4f795f8ac97ddc2901a6a6b41968d9e5396 GIT binary patch literal 8658 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/deprecated/__pycache__/decorator.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/deprecated/__pycache__/decorator.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2f83c11f7a11ea9ed8c0c173e285c14a81d1ebed GIT binary patch literal 14022 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/deprecated/__pycache__/parse.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/deprecated/__pycache__/parse.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0b14bc80be1b5167589a082e910cb40b81c89bdf GIT binary patch literal 3400 zcmb_e-ESMm5#RgZ@kky?k)mYl!xF8wiJ4eZ8p(+**9H`QSpBf#M0V2Bbm8Z1OJW+P7 z7AU#|XXo}~W_EUdv-6j5IEbMAFmo#Z*8oD_kPol@dCLL#y8c{+Ddso_E-7$q#!tjr%Y~dBp_(rcp zKl269em|vIX}TtC)R(6dRC?_HCOx6V_egIkv#FNvh^`dlgk)VeEZNE%x;Y8o{Fpvh zB>g$r`Y6RY;q$*ZHvXlHA7airiHW9 zWlJ?LC-Y{qA+ZnKC=#b$F>u-8=d79I<8WpvXXuuyTUo1IQXNs%bA|$jJH8TelOw^k z7z)k$c+_SJb%?q%E>-xAx?IfYZ`wTW*=L<^cU{a9JqZPx4!ke7U*hzLMO;gpBG}At z(eGGq_a}_aU1iKB2JMkTuK$I$#M#_`UNL(F?kHu&yp1-p;vVlo9mi}`Xz@lHy}fJC z5@M0e8-j|$@>K(OtGh`j`Br1My|0m3Uv52*i9tEq~yuFRyODju)74k+4 z?Hh3lO5I^Qx9&Dexcw<$2l6;e5%W zAY5#{pwH^Yf}X60aW4tuq2%J=d0d7tPFe;)076<#F66C`l5QNk{NBhuH7;wWx)}GQ z(cp(1F_cV29C1O$ItVizo^Y6)m>@+liA)!uBqKP1^PqeTV*}T%&6{~04grbE@li}V zf@_T)MxH1NXZI?oDiUo!U-xuD!eZ?#kHXct@pc@LuNLWTkUtGd^08M!%L~52T)3 zKVQ4FdTDv=Yrk|$Tnn#;ANUV#hgxpRpS5g-x~omGHE~s3Ke*Y{bA9+>v~B(Hr%M&F zvl@upI#-5&n)#GQ$apIm3R zqb)b=6?^@i&1iQ;?0y_MP-#DU`@-!rm4kzukz*C{7|n+}?QSZZ$!qG1S@5~MMY03U zTXD!N|9jrDcC%Fjol6Li1BJ(nt$`eySw0PGUV>YNpGP=mkz7w(;iXwe@7`y(kK(>* z&;BM)QlnqutY+`a7HrODY}V#&-(6utaL1=m%0G$w;e(~5^4g1Cq5{~jR(HkiB=P7tf`P}Kop&dto^uevDOeOzh$0uJ~Rlnnbq z0Urfv|Bi(K#R9o}JO~R;l0{`8&%vN?>%{w&?By?bc{>!n$$vTo52`5Lh^|C8#kS?) zs=vA7@2G~NH%_jcthB#&KlB za5T%jO*nde#|cOB4L(805Fu1tD=Cg<=0H9aN0_|bjhcwww!^DX?_u)BJAQJ1T7KHS zcL9 z0r!+c?CBZ{+>>`0s`bdd!7b+aK3WruPz@$(9Q1XqgmbkL&ecjdS1aLMt%P&60!Or- Kc)|il9r-UVLG%a! literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/deprecated/__pycache__/tools.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/deprecated/__pycache__/tools.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..669e46a935d6af982dcebca02d3288289b79a452 GIT binary patch literal 3536 zcmb_e-ESMm5#Rgdk$3#kCuPg-$&FL9iR4&vQPgmqx{91ul@!II6NHvaop>vm^6`$? zJ1U{T0&*LmF$&arOMvFV1^Qsu{v-O{7a2|v;wqyKf}qG76}dp6r_S7w6z$dtl6DEs z&fd<>%e{lBjkNz5|gt?nagt=>b%A0`Jfl_ z0`!6_ODo6o@p2-c2*wdBSx)6sfv#9W zIh{{)gi038LhkDPK?53Vp+1zI4fk6|g>L(h8$R!=vUG`0`oa?|WtH!ud-xxx&S%3x(X&?EK96+?3z* zDzzyCyJ^?47m8PD*}(AV@VseMJj!4=G+#3f+bb1c>3Cfz*+n}3QdaP_iosl3aF*8! zhU-V&z(>JZ@e?g|4LswR%k96u)NQ<^mt6fI(J}p!OZBBnE7n+74rA+vRWc#VLZ#+i zb!=E^yB;;nG00BA*Iad2tthn46*~$3Fy{9D49fe&Yr%q$wH6rAsNGD?6FWM8Pq^Fi z#F09GefVqEie8H#1juktI#}yP+dk{04a+sP{p_HxbM4s$l9lIJFHA9{;~k#$LFdO@ z&nRBA=sLAF-pF00x(CNou#Ga+VLzdRV|scoyEj_59o=&5Rj?{D3cKa%9xYcKX0V!G zc1&uycQ`f(p|Y~CylpVMWUsouh#E^^20iVQ2Y9_1&NC-zpLC(kUt?XYWZ#VFE6d(Cr4jbhQM0>13k(W1lX;xfD~wavw`b!x9K&XkrH z-I7N~VZk+HmAZ>d5EO)F@V@Ze;h(n;bb09X!;~0_Rzn#54+fXj=q`%+j z?fYj$l;mcNDCzCU@Q#wY8NU&4Xy%S~v@w{0$!HALXoFkT2kMbe)Y1Fu=@Qf%?B-@a>`QMexnAb-}d*;czCH?|yev}Z z>XIp)MeowW*U?e-5OqNVN=4d{IKmU~(;-v0$E>ok(5_{=p-(ToHm8TXrk^mN%#?~= zR$poXRD^n3(_4EC(~eEY*fGc=AR`+9Ei16&_~3geo=5Q< zh>eT$;1J*ofzb&T1dN`i&0SA-+=(u9O|$p z*TotjhB~lCAH;?~iJiC~JJCoFHHNZ{{*h*csM$Rts`BO}QY*e4$?T~8TlB+)kJORI zVg0?yt;mg;W{POZ&FRN+67Rn`dti@&p(72%{HmBJL z-rop+Lsyis&KFMfI(IZ zX%egmxH67wkAv{VWw=p7j=z8pkvsdDAW*x`On1JSuCNK1-bi4XxeO$HQHL+IE7`;| z-Luo^GazNhJNp4XJB1=h2wgIq%^vn+g~Cb|@}`9X!<&?yM1cqA%a9Y)9wy?GU?Gy5 zVKrw6LO&fE6zDr1wO#zAWC(YbMFF5E4C}S8;ky-#@T)HBsBFLt|aoj_4>@%YNjU@k0 zUjCT8{5d)C5AxH8rB5S$O_>~;*cJyK#eTRMd6ekgn*1Ph>-25mk3YKg!fki^ z*!caSiS53L`-#(=>aI*A?Y+t0%xrR?@>)ZDvk^}}mIR*PQ#5X3FA7={wcVq^^n81| znII#_8~sC#%!`dvle_UFToP(eQ-B^4(2h1Es3|1b+l-2<*ZNtH literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/deprecated/class_validators.py b/backend/.venv/Lib/site-packages/pydantic/deprecated/class_validators.py new file mode 100644 index 0000000..f1a331d --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/deprecated/class_validators.py @@ -0,0 +1,256 @@ +"""Old `@validator` and `@root_validator` function validators from V1.""" + +from __future__ import annotations as _annotations + +from functools import partial, partialmethod +from types import FunctionType +from typing import TYPE_CHECKING, Any, Callable, Literal, TypeVar, Union, overload +from warnings import warn + +from typing_extensions import Protocol, TypeAlias, deprecated + +from .._internal import _decorators, _decorators_v1 +from ..errors import PydanticUserError +from ..warnings import PydanticDeprecatedSince20 + +_ALLOW_REUSE_WARNING_MESSAGE = '`allow_reuse` is deprecated and will be ignored; it should no longer be necessary' + + +if TYPE_CHECKING: + + class _OnlyValueValidatorClsMethod(Protocol): + def __call__(self, __cls: Any, __value: Any) -> Any: ... + + class _V1ValidatorWithValuesClsMethod(Protocol): + def __call__(self, __cls: Any, __value: Any, values: dict[str, Any]) -> Any: ... + + class _V1ValidatorWithValuesKwOnlyClsMethod(Protocol): + def __call__(self, __cls: Any, __value: Any, *, values: dict[str, Any]) -> Any: ... + + class _V1ValidatorWithKwargsClsMethod(Protocol): + def __call__(self, __cls: Any, **kwargs: Any) -> Any: ... + + class _V1ValidatorWithValuesAndKwargsClsMethod(Protocol): + def __call__(self, __cls: Any, values: dict[str, Any], **kwargs: Any) -> Any: ... + + class _V1RootValidatorClsMethod(Protocol): + def __call__( + self, __cls: Any, __values: _decorators_v1.RootValidatorValues + ) -> _decorators_v1.RootValidatorValues: ... + + V1Validator = Union[ + _OnlyValueValidatorClsMethod, + _V1ValidatorWithValuesClsMethod, + _V1ValidatorWithValuesKwOnlyClsMethod, + _V1ValidatorWithKwargsClsMethod, + _V1ValidatorWithValuesAndKwargsClsMethod, + _decorators_v1.V1ValidatorWithValues, + _decorators_v1.V1ValidatorWithValuesKwOnly, + _decorators_v1.V1ValidatorWithKwargs, + _decorators_v1.V1ValidatorWithValuesAndKwargs, + ] + + V1RootValidator = Union[ + _V1RootValidatorClsMethod, + _decorators_v1.V1RootValidatorFunction, + ] + + _PartialClsOrStaticMethod: TypeAlias = Union[classmethod[Any, Any, Any], staticmethod[Any, Any], partialmethod[Any]] + + # Allow both a V1 (assumed pre=False) or V2 (assumed mode='after') validator + # We lie to type checkers and say we return the same thing we get + # but in reality we return a proxy object that _mostly_ behaves like the wrapped thing + _V1ValidatorType = TypeVar('_V1ValidatorType', V1Validator, _PartialClsOrStaticMethod) + _V1RootValidatorFunctionType = TypeVar( + '_V1RootValidatorFunctionType', + _decorators_v1.V1RootValidatorFunction, + _V1RootValidatorClsMethod, + _PartialClsOrStaticMethod, + ) +else: + # See PyCharm issues https://youtrack.jetbrains.com/issue/PY-21915 + # and https://youtrack.jetbrains.com/issue/PY-51428 + DeprecationWarning = PydanticDeprecatedSince20 + + +@deprecated( + 'Pydantic V1 style `@validator` validators are deprecated.' + ' You should migrate to Pydantic V2 style `@field_validator` validators,' + ' see the migration guide for more details', + category=None, +) +def validator( + __field: str, + *fields: str, + pre: bool = False, + each_item: bool = False, + always: bool = False, + check_fields: bool | None = None, + allow_reuse: bool = False, +) -> Callable[[_V1ValidatorType], _V1ValidatorType]: + """Decorate methods on the class indicating that they should be used to validate fields. + + Args: + __field (str): The first field the validator should be called on; this is separate + from `fields` to ensure an error is raised if you don't pass at least one. + *fields (str): Additional field(s) the validator should be called on. + pre (bool, optional): Whether this validator should be called before the standard + validators (else after). Defaults to False. + each_item (bool, optional): For complex objects (sets, lists etc.) whether to validate + individual elements rather than the whole object. Defaults to False. + always (bool, optional): Whether this method and other validators should be called even if + the value is missing. Defaults to False. + check_fields (bool | None, optional): Whether to check that the fields actually exist on the model. + Defaults to None. + allow_reuse (bool, optional): Whether to track and raise an error if another validator refers to + the decorated function. Defaults to False. + + Returns: + Callable: A decorator that can be used to decorate a + function to be used as a validator. + """ + warn( + 'Pydantic V1 style `@validator` validators are deprecated.' + ' You should migrate to Pydantic V2 style `@field_validator` validators,' + ' see the migration guide for more details', + DeprecationWarning, + stacklevel=2, + ) + + if allow_reuse is True: # pragma: no cover + warn(_ALLOW_REUSE_WARNING_MESSAGE, DeprecationWarning, stacklevel=2) + fields = __field, *fields + if isinstance(fields[0], FunctionType): + raise PydanticUserError( + '`@validator` should be used with fields and keyword arguments, not bare. ' + "E.g. usage should be `@validator('', ...)`", + code='validator-no-fields', + ) + elif not all(isinstance(field, str) for field in fields): + raise PydanticUserError( + '`@validator` fields should be passed as separate string args. ' + "E.g. usage should be `@validator('', '', ...)`", + code='validator-invalid-fields', + ) + + mode: Literal['before', 'after'] = 'before' if pre is True else 'after' + + def dec(f: Any) -> _decorators.PydanticDescriptorProxy[Any]: + if _decorators.is_instance_method_from_sig(f): + raise PydanticUserError( + '`@validator` cannot be applied to instance methods', code='validator-instance-method' + ) + # auto apply the @classmethod decorator + f = _decorators.ensure_classmethod_based_on_signature(f) + wrap = _decorators_v1.make_generic_v1_field_validator + validator_wrapper_info = _decorators.ValidatorDecoratorInfo( + fields=fields, + mode=mode, + each_item=each_item, + always=always, + check_fields=check_fields, + ) + return _decorators.PydanticDescriptorProxy(f, validator_wrapper_info, shim=wrap) + + return dec # type: ignore[return-value] + + +@overload +def root_validator( + *, + # if you don't specify `pre` the default is `pre=False` + # which means you need to specify `skip_on_failure=True` + skip_on_failure: Literal[True], + allow_reuse: bool = ..., +) -> Callable[ + [_V1RootValidatorFunctionType], + _V1RootValidatorFunctionType, +]: ... + + +@overload +def root_validator( + *, + # if you specify `pre=True` then you don't need to specify + # `skip_on_failure`, in fact it is not allowed as an argument! + pre: Literal[True], + allow_reuse: bool = ..., +) -> Callable[ + [_V1RootValidatorFunctionType], + _V1RootValidatorFunctionType, +]: ... + + +@overload +def root_validator( + *, + # if you explicitly specify `pre=False` then you + # MUST specify `skip_on_failure=True` + pre: Literal[False], + skip_on_failure: Literal[True], + allow_reuse: bool = ..., +) -> Callable[ + [_V1RootValidatorFunctionType], + _V1RootValidatorFunctionType, +]: ... + + +@deprecated( + 'Pydantic V1 style `@root_validator` validators are deprecated.' + ' You should migrate to Pydantic V2 style `@model_validator` validators,' + ' see the migration guide for more details', + category=None, +) +def root_validator( + *__args, + pre: bool = False, + skip_on_failure: bool = False, + allow_reuse: bool = False, +) -> Any: + """Decorate methods on a model indicating that they should be used to validate (and perhaps + modify) data either before or after standard model parsing/validation is performed. + + Args: + pre (bool, optional): Whether this validator should be called before the standard + validators (else after). Defaults to False. + skip_on_failure (bool, optional): Whether to stop validation and return as soon as a + failure is encountered. Defaults to False. + allow_reuse (bool, optional): Whether to track and raise an error if another validator + refers to the decorated function. Defaults to False. + + Returns: + Any: A decorator that can be used to decorate a function to be used as a root_validator. + """ + warn( + 'Pydantic V1 style `@root_validator` validators are deprecated.' + ' You should migrate to Pydantic V2 style `@model_validator` validators,' + ' see the migration guide for more details', + DeprecationWarning, + stacklevel=2, + ) + + if __args: + # Ensure a nice error is raised if someone attempts to use the bare decorator + return root_validator()(*__args) # type: ignore + + if allow_reuse is True: # pragma: no cover + warn(_ALLOW_REUSE_WARNING_MESSAGE, DeprecationWarning, stacklevel=2) + mode: Literal['before', 'after'] = 'before' if pre is True else 'after' + if pre is False and skip_on_failure is not True: + raise PydanticUserError( + 'If you use `@root_validator` with pre=False (the default) you MUST specify `skip_on_failure=True`.' + ' Note that `@root_validator` is deprecated and should be replaced with `@model_validator`.', + code='root-validator-pre-skip', + ) + + wrap = partial(_decorators_v1.make_v1_generic_root_validator, pre=pre) + + def dec(f: Callable[..., Any] | classmethod[Any, Any, Any] | staticmethod[Any, Any]) -> Any: + if _decorators.is_instance_method_from_sig(f): + raise TypeError('`@root_validator` cannot be applied to instance methods') + # auto apply the @classmethod decorator + res = _decorators.ensure_classmethod_based_on_signature(f) + dec_info = _decorators.RootValidatorDecoratorInfo(mode=mode) + return _decorators.PydanticDescriptorProxy(res, dec_info, shim=wrap) + + return dec diff --git a/backend/.venv/Lib/site-packages/pydantic/deprecated/config.py b/backend/.venv/Lib/site-packages/pydantic/deprecated/config.py new file mode 100644 index 0000000..bd4692a --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/deprecated/config.py @@ -0,0 +1,72 @@ +from __future__ import annotations as _annotations + +import warnings +from typing import TYPE_CHECKING, Any, Literal + +from typing_extensions import deprecated + +from .._internal import _config +from ..warnings import PydanticDeprecatedSince20 + +if not TYPE_CHECKING: + # See PyCharm issues https://youtrack.jetbrains.com/issue/PY-21915 + # and https://youtrack.jetbrains.com/issue/PY-51428 + DeprecationWarning = PydanticDeprecatedSince20 + +__all__ = 'BaseConfig', 'Extra' + + +class _ConfigMetaclass(type): + def __getattr__(self, item: str) -> Any: + try: + obj = _config.config_defaults[item] + warnings.warn(_config.DEPRECATION_MESSAGE, DeprecationWarning) + return obj + except KeyError as exc: + raise AttributeError(f"type object '{self.__name__}' has no attribute {exc}") from exc + + +@deprecated('BaseConfig is deprecated. Use the `pydantic.ConfigDict` instead.', category=PydanticDeprecatedSince20) +class BaseConfig(metaclass=_ConfigMetaclass): + """This class is only retained for backwards compatibility. + + !!! Warning "Deprecated" + BaseConfig is deprecated. Use the [`pydantic.ConfigDict`][pydantic.ConfigDict] instead. + """ + + def __getattr__(self, item: str) -> Any: + try: + obj = super().__getattribute__(item) + warnings.warn(_config.DEPRECATION_MESSAGE, DeprecationWarning) + return obj + except AttributeError as exc: + try: + return getattr(type(self), item) + except AttributeError: + # re-raising changes the displayed text to reflect that `self` is not a type + raise AttributeError(str(exc)) from exc + + def __init_subclass__(cls, **kwargs: Any) -> None: + warnings.warn(_config.DEPRECATION_MESSAGE, DeprecationWarning) + return super().__init_subclass__(**kwargs) + + +class _ExtraMeta(type): + def __getattribute__(self, __name: str) -> Any: + # The @deprecated decorator accesses other attributes, so we only emit a warning for the expected ones + if __name in {'allow', 'ignore', 'forbid'}: + warnings.warn( + "`pydantic.config.Extra` is deprecated, use literal values instead (e.g. `extra='allow'`)", + DeprecationWarning, + stacklevel=2, + ) + return super().__getattribute__(__name) + + +@deprecated( + "Extra is deprecated. Use literal values instead (e.g. `extra='allow'`)", category=PydanticDeprecatedSince20 +) +class Extra(metaclass=_ExtraMeta): + allow: Literal['allow'] = 'allow' + ignore: Literal['ignore'] = 'ignore' + forbid: Literal['forbid'] = 'forbid' diff --git a/backend/.venv/Lib/site-packages/pydantic/deprecated/copy_internals.py b/backend/.venv/Lib/site-packages/pydantic/deprecated/copy_internals.py new file mode 100644 index 0000000..0170dc0 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/deprecated/copy_internals.py @@ -0,0 +1,224 @@ +from __future__ import annotations as _annotations + +import typing +from copy import deepcopy +from enum import Enum +from typing import Any + +import typing_extensions + +from .._internal import ( + _model_construction, + _typing_extra, + _utils, +) + +if typing.TYPE_CHECKING: + from .. import BaseModel + from .._internal._utils import AbstractSetIntStr, MappingIntStrAny + + AnyClassMethod = classmethod[Any, Any, Any] + TupleGenerator = typing.Generator[tuple[str, Any], None, None] + Model = typing.TypeVar('Model', bound='BaseModel') + # should be `set[int] | set[str] | dict[int, IncEx] | dict[str, IncEx] | None`, but mypy can't cope + IncEx: typing_extensions.TypeAlias = 'set[int] | set[str] | dict[int, Any] | dict[str, Any] | None' + +_object_setattr = _model_construction.object_setattr + + +def _iter( + self: BaseModel, + to_dict: bool = False, + by_alias: bool = False, + include: AbstractSetIntStr | MappingIntStrAny | None = None, + exclude: AbstractSetIntStr | MappingIntStrAny | None = None, + exclude_unset: bool = False, + exclude_defaults: bool = False, + exclude_none: bool = False, +) -> TupleGenerator: + # Merge field set excludes with explicit exclude parameter with explicit overriding field set options. + # The extra "is not None" guards are not logically necessary but optimizes performance for the simple case. + if exclude is not None: + exclude = _utils.ValueItems.merge( + {k: v.exclude for k, v in self.__pydantic_fields__.items() if v.exclude is not None}, exclude + ) + + if include is not None: + include = _utils.ValueItems.merge(dict.fromkeys(self.__pydantic_fields__, True), include, intersect=True) + + allowed_keys = _calculate_keys(self, include=include, exclude=exclude, exclude_unset=exclude_unset) # type: ignore + if allowed_keys is None and not (to_dict or by_alias or exclude_unset or exclude_defaults or exclude_none): + # huge boost for plain _iter() + yield from self.__dict__.items() + if self.__pydantic_extra__: + yield from self.__pydantic_extra__.items() + return + + value_exclude = _utils.ValueItems(self, exclude) if exclude is not None else None + value_include = _utils.ValueItems(self, include) if include is not None else None + + if self.__pydantic_extra__ is None: + items = self.__dict__.items() + else: + items = list(self.__dict__.items()) + list(self.__pydantic_extra__.items()) + + for field_key, v in items: + if (allowed_keys is not None and field_key not in allowed_keys) or (exclude_none and v is None): + continue + + if exclude_defaults: + try: + field = self.__pydantic_fields__[field_key] + except KeyError: + pass + else: + if not field.is_required() and field.default == v: + continue + + if by_alias and field_key in self.__pydantic_fields__: + dict_key = self.__pydantic_fields__[field_key].alias or field_key + else: + dict_key = field_key + + if to_dict or value_include or value_exclude: + v = _get_value( + type(self), + v, + to_dict=to_dict, + by_alias=by_alias, + include=value_include and value_include.for_element(field_key), + exclude=value_exclude and value_exclude.for_element(field_key), + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + yield dict_key, v + + +def _copy_and_set_values( + self: Model, + values: dict[str, Any], + fields_set: set[str], + extra: dict[str, Any] | None = None, + private: dict[str, Any] | None = None, + *, + deep: bool, # UP006 +) -> Model: + if deep: + # chances of having empty dict here are quite low for using smart_deepcopy + values = deepcopy(values) + extra = deepcopy(extra) + private = deepcopy(private) + + cls = self.__class__ + m = cls.__new__(cls) + _object_setattr(m, '__dict__', values) + _object_setattr(m, '__pydantic_extra__', extra) + _object_setattr(m, '__pydantic_fields_set__', fields_set) + _object_setattr(m, '__pydantic_private__', private) + + return m + + +@typing.no_type_check +def _get_value( + cls: type[BaseModel], + v: Any, + to_dict: bool, + by_alias: bool, + include: AbstractSetIntStr | MappingIntStrAny | None, + exclude: AbstractSetIntStr | MappingIntStrAny | None, + exclude_unset: bool, + exclude_defaults: bool, + exclude_none: bool, +) -> Any: + from .. import BaseModel + + if isinstance(v, BaseModel): + if to_dict: + return v.model_dump( + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + include=include, # type: ignore + exclude=exclude, # type: ignore + exclude_none=exclude_none, + ) + else: + return v.copy(include=include, exclude=exclude) + + value_exclude = _utils.ValueItems(v, exclude) if exclude else None + value_include = _utils.ValueItems(v, include) if include else None + + if isinstance(v, dict): + return { + k_: _get_value( + cls, + v_, + to_dict=to_dict, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + include=value_include and value_include.for_element(k_), + exclude=value_exclude and value_exclude.for_element(k_), + exclude_none=exclude_none, + ) + for k_, v_ in v.items() + if (not value_exclude or not value_exclude.is_excluded(k_)) + and (not value_include or value_include.is_included(k_)) + } + + elif _utils.sequence_like(v): + seq_args = ( + _get_value( + cls, + v_, + to_dict=to_dict, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + include=value_include and value_include.for_element(i), + exclude=value_exclude and value_exclude.for_element(i), + exclude_none=exclude_none, + ) + for i, v_ in enumerate(v) + if (not value_exclude or not value_exclude.is_excluded(i)) + and (not value_include or value_include.is_included(i)) + ) + + return v.__class__(*seq_args) if _typing_extra.is_namedtuple(v.__class__) else v.__class__(seq_args) + + elif isinstance(v, Enum) and getattr(cls.model_config, 'use_enum_values', False): + return v.value + + else: + return v + + +def _calculate_keys( + self: BaseModel, + include: MappingIntStrAny | None, + exclude: MappingIntStrAny | None, + exclude_unset: bool, + update: dict[str, Any] | None = None, # noqa UP006 +) -> typing.AbstractSet[str] | None: + if include is None and exclude is None and exclude_unset is False: + return None + + keys: typing.AbstractSet[str] + if exclude_unset: + keys = self.__pydantic_fields_set__.copy() + else: + keys = set(self.__dict__.keys()) + keys = keys | (self.__pydantic_extra__ or {}).keys() + + if include is not None: + keys &= include.keys() + + if update: + keys -= update.keys() + + if exclude: + keys -= {k for k, v in exclude.items() if _utils.ValueItems.is_true(v)} + + return keys diff --git a/backend/.venv/Lib/site-packages/pydantic/deprecated/decorator.py b/backend/.venv/Lib/site-packages/pydantic/deprecated/decorator.py new file mode 100644 index 0000000..e73ad20 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/deprecated/decorator.py @@ -0,0 +1,284 @@ +import warnings +from collections.abc import Mapping +from functools import wraps +from typing import TYPE_CHECKING, Any, Callable, Optional, TypeVar, Union, overload + +from typing_extensions import deprecated + +from .._internal import _config, _typing_extra +from ..alias_generators import to_pascal +from ..errors import PydanticUserError +from ..functional_validators import field_validator +from ..main import BaseModel, create_model +from ..warnings import PydanticDeprecatedSince20 + +if not TYPE_CHECKING: + # See PyCharm issues https://youtrack.jetbrains.com/issue/PY-21915 + # and https://youtrack.jetbrains.com/issue/PY-51428 + DeprecationWarning = PydanticDeprecatedSince20 + +__all__ = ('validate_arguments',) + +if TYPE_CHECKING: + AnyCallable = Callable[..., Any] + + AnyCallableT = TypeVar('AnyCallableT', bound=AnyCallable) + ConfigType = Union[None, type[Any], dict[str, Any]] + + +@overload +def validate_arguments( + func: None = None, *, config: 'ConfigType' = None +) -> Callable[['AnyCallableT'], 'AnyCallableT']: ... + + +@overload +def validate_arguments(func: 'AnyCallableT') -> 'AnyCallableT': ... + + +@deprecated( + 'The `validate_arguments` method is deprecated; use `validate_call` instead.', + category=None, +) +def validate_arguments(func: Optional['AnyCallableT'] = None, *, config: 'ConfigType' = None) -> Any: + """Decorator to validate the arguments passed to a function.""" + warnings.warn( + 'The `validate_arguments` method is deprecated; use `validate_call` instead.', + PydanticDeprecatedSince20, + stacklevel=2, + ) + + def validate(_func: 'AnyCallable') -> 'AnyCallable': + vd = ValidatedFunction(_func, config) + + @wraps(_func) + def wrapper_function(*args: Any, **kwargs: Any) -> Any: + return vd.call(*args, **kwargs) + + wrapper_function.vd = vd # type: ignore + wrapper_function.validate = vd.init_model_instance # type: ignore + wrapper_function.raw_function = vd.raw_function # type: ignore + wrapper_function.model = vd.model # type: ignore + return wrapper_function + + if func: + return validate(func) + else: + return validate + + +ALT_V_ARGS = 'v__args' +ALT_V_KWARGS = 'v__kwargs' +V_POSITIONAL_ONLY_NAME = 'v__positional_only' +V_DUPLICATE_KWARGS = 'v__duplicate_kwargs' + + +class ValidatedFunction: + def __init__(self, function: 'AnyCallable', config: 'ConfigType'): + from inspect import Parameter, signature + + parameters: Mapping[str, Parameter] = signature(function).parameters + + if parameters.keys() & {ALT_V_ARGS, ALT_V_KWARGS, V_POSITIONAL_ONLY_NAME, V_DUPLICATE_KWARGS}: + raise PydanticUserError( + f'"{ALT_V_ARGS}", "{ALT_V_KWARGS}", "{V_POSITIONAL_ONLY_NAME}" and "{V_DUPLICATE_KWARGS}" ' + f'are not permitted as argument names when using the "{validate_arguments.__name__}" decorator', + code=None, + ) + + self.raw_function = function + self.arg_mapping: dict[int, str] = {} + self.positional_only_args: set[str] = set() + self.v_args_name = 'args' + self.v_kwargs_name = 'kwargs' + + type_hints = _typing_extra.get_type_hints(function, include_extras=True) + takes_args = False + takes_kwargs = False + fields: dict[str, tuple[Any, Any]] = {} + for i, (name, p) in enumerate(parameters.items()): + if p.annotation is p.empty: + annotation = Any + else: + annotation = type_hints[name] + + default = ... if p.default is p.empty else p.default + if p.kind == Parameter.POSITIONAL_ONLY: + self.arg_mapping[i] = name + fields[name] = annotation, default + fields[V_POSITIONAL_ONLY_NAME] = list[str], None + self.positional_only_args.add(name) + elif p.kind == Parameter.POSITIONAL_OR_KEYWORD: + self.arg_mapping[i] = name + fields[name] = annotation, default + fields[V_DUPLICATE_KWARGS] = list[str], None + elif p.kind == Parameter.KEYWORD_ONLY: + fields[name] = annotation, default + elif p.kind == Parameter.VAR_POSITIONAL: + self.v_args_name = name + fields[name] = tuple[annotation, ...], None + takes_args = True + else: + assert p.kind == Parameter.VAR_KEYWORD, p.kind + self.v_kwargs_name = name + fields[name] = dict[str, annotation], None + takes_kwargs = True + + # these checks avoid a clash between "args" and a field with that name + if not takes_args and self.v_args_name in fields: + self.v_args_name = ALT_V_ARGS + + # same with "kwargs" + if not takes_kwargs and self.v_kwargs_name in fields: + self.v_kwargs_name = ALT_V_KWARGS + + if not takes_args: + # we add the field so validation below can raise the correct exception + fields[self.v_args_name] = list[Any], None + + if not takes_kwargs: + # same with kwargs + fields[self.v_kwargs_name] = dict[Any, Any], None + + self.create_model(fields, takes_args, takes_kwargs, config) + + def init_model_instance(self, *args: Any, **kwargs: Any) -> BaseModel: + values = self.build_values(args, kwargs) + return self.model(**values) + + def call(self, *args: Any, **kwargs: Any) -> Any: + m = self.init_model_instance(*args, **kwargs) + return self.execute(m) + + def build_values(self, args: tuple[Any, ...], kwargs: dict[str, Any]) -> dict[str, Any]: + values: dict[str, Any] = {} + if args: + arg_iter = enumerate(args) + while True: + try: + i, a = next(arg_iter) + except StopIteration: + break + arg_name = self.arg_mapping.get(i) + if arg_name is not None: + values[arg_name] = a + else: + values[self.v_args_name] = [a] + [a for _, a in arg_iter] + break + + var_kwargs: dict[str, Any] = {} + wrong_positional_args = [] + duplicate_kwargs = [] + fields_alias = [ + field.alias + for name, field in self.model.__pydantic_fields__.items() + if name not in (self.v_args_name, self.v_kwargs_name) + ] + non_var_fields = set(self.model.__pydantic_fields__) - {self.v_args_name, self.v_kwargs_name} + for k, v in kwargs.items(): + if k in non_var_fields or k in fields_alias: + if k in self.positional_only_args: + wrong_positional_args.append(k) + if k in values: + duplicate_kwargs.append(k) + values[k] = v + else: + var_kwargs[k] = v + + if var_kwargs: + values[self.v_kwargs_name] = var_kwargs + if wrong_positional_args: + values[V_POSITIONAL_ONLY_NAME] = wrong_positional_args + if duplicate_kwargs: + values[V_DUPLICATE_KWARGS] = duplicate_kwargs + return values + + def execute(self, m: BaseModel) -> Any: + d = { + k: v + for k, v in m.__dict__.items() + if k in m.__pydantic_fields_set__ or m.__pydantic_fields__[k].default_factory + } + var_kwargs = d.pop(self.v_kwargs_name, {}) + + if self.v_args_name in d: + args_: list[Any] = [] + in_kwargs = False + kwargs = {} + for name, value in d.items(): + if in_kwargs: + kwargs[name] = value + elif name == self.v_args_name: + args_ += value + in_kwargs = True + else: + args_.append(value) + return self.raw_function(*args_, **kwargs, **var_kwargs) + elif self.positional_only_args: + args_ = [] + kwargs = {} + for name, value in d.items(): + if name in self.positional_only_args: + args_.append(value) + else: + kwargs[name] = value + return self.raw_function(*args_, **kwargs, **var_kwargs) + else: + return self.raw_function(**d, **var_kwargs) + + def create_model(self, fields: dict[str, Any], takes_args: bool, takes_kwargs: bool, config: 'ConfigType') -> None: + pos_args = len(self.arg_mapping) + + config_wrapper = _config.ConfigWrapper(config) + + if config_wrapper.alias_generator: + raise PydanticUserError( + 'Setting the "alias_generator" property on custom Config for ' + '@validate_arguments is not yet supported, please remove.', + code=None, + ) + if config_wrapper.extra is None: + config_wrapper.config_dict['extra'] = 'forbid' + + class DecoratorBaseModel(BaseModel): + @field_validator(self.v_args_name, check_fields=False) + @classmethod + def check_args(cls, v: Optional[list[Any]]) -> Optional[list[Any]]: + if takes_args or v is None: + return v + + raise TypeError(f'{pos_args} positional arguments expected but {pos_args + len(v)} given') + + @field_validator(self.v_kwargs_name, check_fields=False) + @classmethod + def check_kwargs(cls, v: Optional[dict[str, Any]]) -> Optional[dict[str, Any]]: + if takes_kwargs or v is None: + return v + + plural = '' if len(v) == 1 else 's' + keys = ', '.join(map(repr, v.keys())) + raise TypeError(f'unexpected keyword argument{plural}: {keys}') + + @field_validator(V_POSITIONAL_ONLY_NAME, check_fields=False) + @classmethod + def check_positional_only(cls, v: Optional[list[str]]) -> None: + if v is None: + return + + plural = '' if len(v) == 1 else 's' + keys = ', '.join(map(repr, v)) + raise TypeError(f'positional-only argument{plural} passed as keyword argument{plural}: {keys}') + + @field_validator(V_DUPLICATE_KWARGS, check_fields=False) + @classmethod + def check_duplicate_kwargs(cls, v: Optional[list[str]]) -> None: + if v is None: + return + + plural = '' if len(v) == 1 else 's' + keys = ', '.join(map(repr, v)) + raise TypeError(f'multiple values for argument{plural}: {keys}') + + model_config = config_wrapper.config_dict + + self.model = create_model(to_pascal(self.raw_function.__name__), __base__=DecoratorBaseModel, **fields) diff --git a/backend/.venv/Lib/site-packages/pydantic/deprecated/json.py b/backend/.venv/Lib/site-packages/pydantic/deprecated/json.py new file mode 100644 index 0000000..1e216a7 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/deprecated/json.py @@ -0,0 +1,141 @@ +import datetime +import warnings +from collections import deque +from decimal import Decimal +from enum import Enum +from ipaddress import IPv4Address, IPv4Interface, IPv4Network, IPv6Address, IPv6Interface, IPv6Network +from pathlib import Path +from re import Pattern +from types import GeneratorType +from typing import TYPE_CHECKING, Any, Callable, Union +from uuid import UUID + +from typing_extensions import deprecated + +from .._internal._import_utils import import_cached_base_model +from ..color import Color +from ..networks import NameEmail +from ..types import SecretBytes, SecretStr +from ..warnings import PydanticDeprecatedSince20 + +if not TYPE_CHECKING: + # See PyCharm issues https://youtrack.jetbrains.com/issue/PY-21915 + # and https://youtrack.jetbrains.com/issue/PY-51428 + DeprecationWarning = PydanticDeprecatedSince20 + +__all__ = 'pydantic_encoder', 'custom_pydantic_encoder', 'timedelta_isoformat' + + +def isoformat(o: Union[datetime.date, datetime.time]) -> str: + return o.isoformat() + + +def decimal_encoder(dec_value: Decimal) -> Union[int, float]: + """Encodes a Decimal as int of there's no exponent, otherwise float. + + This is useful when we use ConstrainedDecimal to represent Numeric(x,0) + where a integer (but not int typed) is used. Encoding this as a float + results in failed round-tripping between encode and parse. + Our Id type is a prime example of this. + + >>> decimal_encoder(Decimal("1.0")) + 1.0 + + >>> decimal_encoder(Decimal("1")) + 1 + """ + exponent = dec_value.as_tuple().exponent + if isinstance(exponent, int) and exponent >= 0: + return int(dec_value) + else: + return float(dec_value) + + +ENCODERS_BY_TYPE: dict[type[Any], Callable[[Any], Any]] = { + bytes: lambda o: o.decode(), + Color: str, + datetime.date: isoformat, + datetime.datetime: isoformat, + datetime.time: isoformat, + datetime.timedelta: lambda td: td.total_seconds(), + Decimal: decimal_encoder, + Enum: lambda o: o.value, + frozenset: list, + deque: list, + GeneratorType: list, + IPv4Address: str, + IPv4Interface: str, + IPv4Network: str, + IPv6Address: str, + IPv6Interface: str, + IPv6Network: str, + NameEmail: str, + Path: str, + Pattern: lambda o: o.pattern, + SecretBytes: str, + SecretStr: str, + set: list, + UUID: str, +} + + +@deprecated( + '`pydantic_encoder` is deprecated, use `pydantic_core.to_jsonable_python` instead.', + category=None, +) +def pydantic_encoder(obj: Any) -> Any: + warnings.warn( + '`pydantic_encoder` is deprecated, use `pydantic_core.to_jsonable_python` instead.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + from dataclasses import asdict, is_dataclass + + BaseModel = import_cached_base_model() + + if isinstance(obj, BaseModel): + return obj.model_dump() + elif is_dataclass(obj): + return asdict(obj) # type: ignore + + # Check the class type and its superclasses for a matching encoder + for base in obj.__class__.__mro__[:-1]: + try: + encoder = ENCODERS_BY_TYPE[base] + except KeyError: + continue + return encoder(obj) + else: # We have exited the for loop without finding a suitable encoder + raise TypeError(f"Object of type '{obj.__class__.__name__}' is not JSON serializable") + + +# TODO: Add a suggested migration path once there is a way to use custom encoders +@deprecated( + '`custom_pydantic_encoder` is deprecated, use `BaseModel.model_dump` instead.', + category=None, +) +def custom_pydantic_encoder(type_encoders: dict[Any, Callable[[type[Any]], Any]], obj: Any) -> Any: + warnings.warn( + '`custom_pydantic_encoder` is deprecated, use `BaseModel.model_dump` instead.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + # Check the class type and its superclasses for a matching encoder + for base in obj.__class__.__mro__[:-1]: + try: + encoder = type_encoders[base] + except KeyError: + continue + + return encoder(obj) + else: # We have exited the for loop without finding a suitable encoder + return pydantic_encoder(obj) + + +@deprecated('`timedelta_isoformat` is deprecated.', category=None) +def timedelta_isoformat(td: datetime.timedelta) -> str: + """ISO 8601 encoding for Python timedelta object.""" + warnings.warn('`timedelta_isoformat` is deprecated.', category=PydanticDeprecatedSince20, stacklevel=2) + minutes, seconds = divmod(td.seconds, 60) + hours, minutes = divmod(minutes, 60) + return f'{"-" if td.days < 0 else ""}P{abs(td.days)}DT{hours:d}H{minutes:d}M{seconds:d}.{td.microseconds:06d}S' diff --git a/backend/.venv/Lib/site-packages/pydantic/deprecated/parse.py b/backend/.venv/Lib/site-packages/pydantic/deprecated/parse.py new file mode 100644 index 0000000..2a92e62 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/deprecated/parse.py @@ -0,0 +1,80 @@ +from __future__ import annotations + +import json +import pickle +import warnings +from enum import Enum +from pathlib import Path +from typing import TYPE_CHECKING, Any, Callable + +from typing_extensions import deprecated + +from ..warnings import PydanticDeprecatedSince20 + +if not TYPE_CHECKING: + # See PyCharm issues https://youtrack.jetbrains.com/issue/PY-21915 + # and https://youtrack.jetbrains.com/issue/PY-51428 + DeprecationWarning = PydanticDeprecatedSince20 + + +class Protocol(str, Enum): + json = 'json' + pickle = 'pickle' + + +@deprecated('`load_str_bytes` is deprecated.', category=None) +def load_str_bytes( + b: str | bytes, + *, + content_type: str | None = None, + encoding: str = 'utf8', + proto: Protocol | None = None, + allow_pickle: bool = False, + json_loads: Callable[[str], Any] = json.loads, +) -> Any: + warnings.warn('`load_str_bytes` is deprecated.', category=PydanticDeprecatedSince20, stacklevel=2) + if proto is None and content_type: + if content_type.endswith(('json', 'javascript')): + pass + elif allow_pickle and content_type.endswith('pickle'): + proto = Protocol.pickle + else: + raise TypeError(f'Unknown content-type: {content_type}') + + proto = proto or Protocol.json + + if proto == Protocol.json: + if isinstance(b, bytes): + b = b.decode(encoding) + return json_loads(b) # type: ignore + elif proto == Protocol.pickle: + if not allow_pickle: + raise RuntimeError('Trying to decode with pickle with allow_pickle=False') + bb = b if isinstance(b, bytes) else b.encode() # type: ignore + return pickle.loads(bb) + else: + raise TypeError(f'Unknown protocol: {proto}') + + +@deprecated('`load_file` is deprecated.', category=None) +def load_file( + path: str | Path, + *, + content_type: str | None = None, + encoding: str = 'utf8', + proto: Protocol | None = None, + allow_pickle: bool = False, + json_loads: Callable[[str], Any] = json.loads, +) -> Any: + warnings.warn('`load_file` is deprecated.', category=PydanticDeprecatedSince20, stacklevel=2) + path = Path(path) + b = path.read_bytes() + if content_type is None: + if path.suffix in ('.js', '.json'): + proto = Protocol.json + elif path.suffix == '.pkl': + proto = Protocol.pickle + + return load_str_bytes( + b, proto=proto, content_type=content_type, encoding=encoding, allow_pickle=allow_pickle, json_loads=json_loads + ) diff --git a/backend/.venv/Lib/site-packages/pydantic/deprecated/tools.py b/backend/.venv/Lib/site-packages/pydantic/deprecated/tools.py new file mode 100644 index 0000000..5ad7fae --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/deprecated/tools.py @@ -0,0 +1,103 @@ +from __future__ import annotations + +import json +import warnings +from typing import TYPE_CHECKING, Any, Callable, TypeVar, Union + +from typing_extensions import deprecated + +from ..json_schema import DEFAULT_REF_TEMPLATE, GenerateJsonSchema +from ..type_adapter import TypeAdapter +from ..warnings import PydanticDeprecatedSince20 + +if not TYPE_CHECKING: + # See PyCharm issues https://youtrack.jetbrains.com/issue/PY-21915 + # and https://youtrack.jetbrains.com/issue/PY-51428 + DeprecationWarning = PydanticDeprecatedSince20 + +__all__ = 'parse_obj_as', 'schema_of', 'schema_json_of' + +NameFactory = Union[str, Callable[[type[Any]], str]] + + +T = TypeVar('T') + + +@deprecated( + '`parse_obj_as` is deprecated. Use `pydantic.TypeAdapter.validate_python` instead.', + category=None, +) +def parse_obj_as(type_: type[T], obj: Any, type_name: NameFactory | None = None) -> T: + warnings.warn( + '`parse_obj_as` is deprecated. Use `pydantic.TypeAdapter.validate_python` instead.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + if type_name is not None: # pragma: no cover + warnings.warn( + 'The type_name parameter is deprecated. parse_obj_as no longer creates temporary models', + DeprecationWarning, + stacklevel=2, + ) + return TypeAdapter(type_).validate_python(obj) + + +@deprecated( + '`schema_of` is deprecated. Use `pydantic.TypeAdapter.json_schema` instead.', + category=None, +) +def schema_of( + type_: Any, + *, + title: NameFactory | None = None, + by_alias: bool = True, + ref_template: str = DEFAULT_REF_TEMPLATE, + schema_generator: type[GenerateJsonSchema] = GenerateJsonSchema, +) -> dict[str, Any]: + """Generate a JSON schema (as dict) for the passed model or dynamically generated one.""" + warnings.warn( + '`schema_of` is deprecated. Use `pydantic.TypeAdapter.json_schema` instead.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + res = TypeAdapter(type_).json_schema( + by_alias=by_alias, + schema_generator=schema_generator, + ref_template=ref_template, + ) + if title is not None: + if isinstance(title, str): + res['title'] = title + else: + warnings.warn( + 'Passing a callable for the `title` parameter is deprecated and no longer supported', + DeprecationWarning, + stacklevel=2, + ) + res['title'] = title(type_) + return res + + +@deprecated( + '`schema_json_of` is deprecated. Use `pydantic.TypeAdapter.json_schema` instead.', + category=None, +) +def schema_json_of( + type_: Any, + *, + title: NameFactory | None = None, + by_alias: bool = True, + ref_template: str = DEFAULT_REF_TEMPLATE, + schema_generator: type[GenerateJsonSchema] = GenerateJsonSchema, + **dumps_kwargs: Any, +) -> str: + """Generate a JSON schema (as JSON) for the passed model or dynamically generated one.""" + warnings.warn( + '`schema_json_of` is deprecated. Use `pydantic.TypeAdapter.json_schema` instead.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + return json.dumps( + schema_of(type_, title=title, by_alias=by_alias, ref_template=ref_template, schema_generator=schema_generator), + **dumps_kwargs, + ) diff --git a/backend/.venv/Lib/site-packages/pydantic/env_settings.py b/backend/.venv/Lib/site-packages/pydantic/env_settings.py new file mode 100644 index 0000000..cd0b04e --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/env_settings.py @@ -0,0 +1,5 @@ +"""The `env_settings` module is a backport module from V1.""" + +from ._migration import getattr_migration + +__getattr__ = getattr_migration(__name__) diff --git a/backend/.venv/Lib/site-packages/pydantic/error_wrappers.py b/backend/.venv/Lib/site-packages/pydantic/error_wrappers.py new file mode 100644 index 0000000..2985419 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/error_wrappers.py @@ -0,0 +1,5 @@ +"""The `error_wrappers` module is a backport module from V1.""" + +from ._migration import getattr_migration + +__getattr__ = getattr_migration(__name__) diff --git a/backend/.venv/Lib/site-packages/pydantic/errors.py b/backend/.venv/Lib/site-packages/pydantic/errors.py new file mode 100644 index 0000000..f227068 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/errors.py @@ -0,0 +1,189 @@ +"""Pydantic-specific errors.""" + +from __future__ import annotations as _annotations + +import re +from typing import Any, ClassVar, Literal + +from typing_extensions import Self +from typing_inspection.introspection import Qualifier + +from pydantic._internal import _repr + +from ._migration import getattr_migration +from .version import version_short + +__all__ = ( + 'PydanticUserError', + 'PydanticUndefinedAnnotation', + 'PydanticImportError', + 'PydanticSchemaGenerationError', + 'PydanticInvalidForJsonSchema', + 'PydanticForbiddenQualifier', + 'PydanticErrorCodes', +) + +# We use this URL to allow for future flexibility about how we host the docs, while allowing for Pydantic +# code in the while with "old" URLs to still work. +# 'u' refers to "user errors" - e.g. errors caused by developers using pydantic, as opposed to validation errors. +DEV_ERROR_DOCS_URL = f'https://errors.pydantic.dev/{version_short()}/u/' +PydanticErrorCodes = Literal[ + 'class-not-fully-defined', + 'custom-json-schema', + 'decorator-missing-field', + 'discriminator-no-field', + 'discriminator-alias-type', + 'discriminator-needs-literal', + 'discriminator-alias', + 'discriminator-validator', + 'callable-discriminator-no-tag', + 'typed-dict-version', + 'model-field-overridden', + 'model-field-missing-annotation', + 'config-both', + 'removed-kwargs', + 'circular-reference-schema', + 'invalid-for-json-schema', + 'json-schema-already-used', + 'base-model-instantiated', + 'undefined-annotation', + 'schema-for-unknown-type', + 'import-error', + 'create-model-field-definitions', + 'validator-no-fields', + 'validator-invalid-fields', + 'validator-instance-method', + 'validator-input-type', + 'root-validator-pre-skip', + 'model-serializer-instance-method', + 'validator-field-config-info', + 'validator-v1-signature', + 'validator-signature', + 'field-serializer-signature', + 'model-serializer-signature', + 'multiple-field-serializers', + 'invalid-annotated-type', + 'type-adapter-config-unused', + 'root-model-extra', + 'unevaluable-type-annotation', + 'dataclass-init-false-extra-allow', + 'clashing-init-and-init-var', + 'model-config-invalid-field-name', + 'with-config-on-model', + 'dataclass-on-model', + 'validate-call-type', + 'unpack-typed-dict', + 'overlapping-unpack-typed-dict', + 'invalid-self-type', + 'validate-by-alias-and-name-false', +] + + +class PydanticErrorMixin: + """A mixin class for common functionality shared by all Pydantic-specific errors. + + Attributes: + message: A message describing the error. + code: An optional error code from PydanticErrorCodes enum. + """ + + def __init__(self, message: str, *, code: PydanticErrorCodes | None) -> None: + self.message = message + self.code = code + + def __str__(self) -> str: + if self.code is None: + return self.message + else: + return f'{self.message}\n\nFor further information visit {DEV_ERROR_DOCS_URL}{self.code}' + + +class PydanticUserError(PydanticErrorMixin, TypeError): + """An error raised due to incorrect use of Pydantic.""" + + +class PydanticUndefinedAnnotation(PydanticErrorMixin, NameError): + """A subclass of `NameError` raised when handling undefined annotations during `CoreSchema` generation. + + Attributes: + name: Name of the error. + message: Description of the error. + """ + + def __init__(self, name: str, message: str) -> None: + self.name = name + super().__init__(message=message, code='undefined-annotation') + + @classmethod + def from_name_error(cls, name_error: NameError) -> Self: + """Convert a `NameError` to a `PydanticUndefinedAnnotation` error. + + Args: + name_error: `NameError` to be converted. + + Returns: + Converted `PydanticUndefinedAnnotation` error. + """ + try: + name = name_error.name # type: ignore # python > 3.10 + except AttributeError: + name = re.search(r".*'(.+?)'", str(name_error)).group(1) # type: ignore[union-attr] + return cls(name=name, message=str(name_error)) + + +class PydanticImportError(PydanticErrorMixin, ImportError): + """An error raised when an import fails due to module changes between V1 and V2. + + Attributes: + message: Description of the error. + """ + + def __init__(self, message: str) -> None: + super().__init__(message, code='import-error') + + +class PydanticSchemaGenerationError(PydanticUserError): + """An error raised during failures to generate a `CoreSchema` for some type. + + Attributes: + message: Description of the error. + """ + + def __init__(self, message: str) -> None: + super().__init__(message, code='schema-for-unknown-type') + + +class PydanticInvalidForJsonSchema(PydanticUserError): + """An error raised during failures to generate a JSON schema for some `CoreSchema`. + + Attributes: + message: Description of the error. + """ + + def __init__(self, message: str) -> None: + super().__init__(message, code='invalid-for-json-schema') + + +class PydanticForbiddenQualifier(PydanticUserError): + """An error raised if a forbidden type qualifier is found in a type annotation.""" + + _qualifier_repr_map: ClassVar[dict[Qualifier, str]] = { + 'required': 'typing.Required', + 'not_required': 'typing.NotRequired', + 'read_only': 'typing.ReadOnly', + 'class_var': 'typing.ClassVar', + 'init_var': 'dataclasses.InitVar', + 'final': 'typing.Final', + } + + def __init__(self, qualifier: Qualifier, annotation: Any) -> None: + super().__init__( + message=( + f'The annotation {_repr.display_as_type(annotation)!r} contains the {self._qualifier_repr_map[qualifier]!r} ' + f'type qualifier, which is invalid in the context it is defined.' + ), + code=None, + ) + + +__getattr__ = getattr_migration(__name__) diff --git a/backend/.venv/Lib/site-packages/pydantic/experimental/__init__.py b/backend/.venv/Lib/site-packages/pydantic/experimental/__init__.py new file mode 100644 index 0000000..5b5add1 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/experimental/__init__.py @@ -0,0 +1 @@ +"""The "experimental" module of pydantic contains potential new features that are subject to change.""" diff --git a/backend/.venv/Lib/site-packages/pydantic/experimental/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/experimental/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..51c3c3f1c0bf0c9207264fc5c5199b62b05a18e2 GIT binary patch literal 308 zcmYjNOHRWu5VZk8h15HYy6YmT*dk!V7O`T5ELoGuG;x#Kk?pjEi*N?c!VR+J0!ZDl z!Vy&BZDyY4_uhQW=a(YkO5K_|#m|WxA^(!YEG2KE6whLi%ad1psu>pi(y=#Nwh`L} zY+c#63~mkGP@;{7fLtmW8=!MBbs22I@*dWVvG*Jx)))ajL+FbQQ-tV%YP1#Sk4rgT zXk9we`du6*9p7|+t@h40p+jP2H!);Lf1BGITISpik5N?O`VAji>WvO9J*-VZao z>(*63J#c^Hl`Yp1C*dNy+o?ph}Yb3MO2W{`PlcXE$92 z4j*$acAH}~spfJRz8Y(JYeM29&Y?AY7qs5Urb+Z_tQNUc^Lrf{X>*AmCwVtwr$QKIkSSi36Bl?bs({5IaM8(0SR zNt?n;FiJ6_-vlNDoS5-z;*Ctlp!b)A$XSVr18VRJ;vS<=m_WY>rfhEClDDW*yW{t^ zw>C}3>rmaVzP7T3%_fGJ0&Edk)Tr{iwzG9>US&`-WTyDd=En$j)31rbEkHeA{1IrXNKQ`69EN7>6ixOuzs;FU- zLxlM;j)!xx$41-@)nTeD%DYQIHB$9>YT~rS_}}*WTH~I}+9LfmoIT%LCc5qh4tK;d zPuUF~57aRl)h>0qjT`1p!-JH&4EeH6TGVTFdIo{*`U;eQxGb!^e#dI37oLp`dVQ6h z2a{&t-{TeTA$s*bI#WJ6z1ly$`YcmC%AD(G&i&Fn%)Iw(e(`92r9Z#&r1s@ejr42e zV5fOlYdx9YeU(a_Q6JtMEp|WQS zT)h-gj+eIKdZ4S6c%;YvLGw)dRiqrI^(r2 zR3X2B!x=AMjMF15NVh`aWK`gW89B#zQ4CMXVO4`$PzDJ>goFqd5eUMqzaw^m!=B?h znXA$7g-=-phP)bjThI&=ilRJ4doR(uFVW(2bOG9z=)!Y!y^pSgN3UE{j_-bbj28#l q^U4Ruxwi)i=wFmp2Px5+OJx;DR6*r>fswOfiHESeK_@>fUs5~LbU886%v~qBHJ6kMf^Xp||9a|_aN8i57 z5O&e7G#~c52xF!x#$8;sj5s32R2yzWNA*P_CC0B{>!rWN^c+2CQ`m}7j?{f^Q$ne3 z{QG(8b!bIs!4*TJHCJnNBUZ?Ynx{@skepkz?=p5%ADoO!VZ8%<7`1A<{>8t)OXL3y Zx@C{t_7g$~-@)_?oPG?BpCi+Emw&%9Y7_tf literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/experimental/__pycache__/pipeline.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/experimental/__pycache__/pipeline.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3768412b7c6da2e73fb61450687960111a7af10d GIT binary patch literal 34457 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/experimental/arguments_schema.py b/backend/.venv/Lib/site-packages/pydantic/experimental/arguments_schema.py new file mode 100644 index 0000000..af4a8f3 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/experimental/arguments_schema.py @@ -0,0 +1,44 @@ +"""Experimental module exposing a function to generate a core schema that validates callable arguments.""" + +from __future__ import annotations + +from collections.abc import Callable +from typing import Any, Literal + +from pydantic_core import CoreSchema + +from pydantic import ConfigDict +from pydantic._internal import _config, _generate_schema, _namespace_utils + + +def generate_arguments_schema( + func: Callable[..., Any], + schema_type: Literal['arguments', 'arguments-v3'] = 'arguments-v3', + parameters_callback: Callable[[int, str, Any], Literal['skip'] | None] | None = None, + config: ConfigDict | None = None, +) -> CoreSchema: + """Generate the schema for the arguments of a function. + + Args: + func: The function to generate the schema for. + schema_type: The type of schema to generate. + parameters_callback: A callable that will be invoked for each parameter. The callback + should take three required arguments: the index, the name and the type annotation + (or [`Parameter.empty`][inspect.Parameter.empty] if not annotated) of the parameter. + The callback can optionally return `'skip'`, so that the parameter gets excluded + from the resulting schema. + config: The configuration to use. + + Returns: + The generated schema. + """ + generate_schema = _generate_schema.GenerateSchema( + _config.ConfigWrapper(config), + ns_resolver=_namespace_utils.NsResolver(namespaces_tuple=_namespace_utils.ns_for_function(func)), + ) + + if schema_type == 'arguments': + schema = generate_schema._arguments_schema(func, parameters_callback) # pyright: ignore[reportArgumentType] + else: + schema = generate_schema._arguments_v3_schema(func, parameters_callback) # pyright: ignore[reportArgumentType] + return generate_schema.clean_schema(schema) diff --git a/backend/.venv/Lib/site-packages/pydantic/experimental/missing_sentinel.py b/backend/.venv/Lib/site-packages/pydantic/experimental/missing_sentinel.py new file mode 100644 index 0000000..3e7f820 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/experimental/missing_sentinel.py @@ -0,0 +1,5 @@ +"""Experimental module exposing a function a `MISSING` sentinel.""" + +from pydantic_core import MISSING + +__all__ = ('MISSING',) diff --git a/backend/.venv/Lib/site-packages/pydantic/experimental/pipeline.py b/backend/.venv/Lib/site-packages/pydantic/experimental/pipeline.py new file mode 100644 index 0000000..633fb00 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/experimental/pipeline.py @@ -0,0 +1,654 @@ +"""Experimental pipeline API functionality. Be careful with this API, it's subject to change.""" + +from __future__ import annotations + +import datetime +import operator +import re +import sys +from collections import deque +from collections.abc import Container +from dataclasses import dataclass +from decimal import Decimal +from functools import cached_property, partial +from re import Pattern +from typing import TYPE_CHECKING, Annotated, Any, Callable, Generic, Protocol, TypeVar, Union, overload + +import annotated_types + +if TYPE_CHECKING: + from pydantic import GetCoreSchemaHandler + +from pydantic_core import PydanticCustomError +from pydantic_core import core_schema as cs + +from pydantic import Strict +from pydantic._internal._internal_dataclass import slots_true as _slots_true + +if sys.version_info < (3, 10): + EllipsisType = type(Ellipsis) +else: + from types import EllipsisType + +__all__ = ['validate_as', 'validate_as_deferred', 'transform'] + +_slots_frozen = {**_slots_true, 'frozen': True} + + +@dataclass(**_slots_frozen) +class _ValidateAs: + tp: type[Any] + strict: bool = False + + +@dataclass +class _ValidateAsDefer: + func: Callable[[], type[Any]] + + @cached_property + def tp(self) -> type[Any]: + return self.func() + + +@dataclass(**_slots_frozen) +class _Transform: + func: Callable[[Any], Any] + + +@dataclass(**_slots_frozen) +class _PipelineOr: + left: _Pipeline[Any, Any] + right: _Pipeline[Any, Any] + + +@dataclass(**_slots_frozen) +class _PipelineAnd: + left: _Pipeline[Any, Any] + right: _Pipeline[Any, Any] + + +@dataclass(**_slots_frozen) +class _Eq: + value: Any + + +@dataclass(**_slots_frozen) +class _NotEq: + value: Any + + +@dataclass(**_slots_frozen) +class _In: + values: Container[Any] + + +@dataclass(**_slots_frozen) +class _NotIn: + values: Container[Any] + + +_ConstraintAnnotation = Union[ + annotated_types.Le, + annotated_types.Ge, + annotated_types.Lt, + annotated_types.Gt, + annotated_types.Len, + annotated_types.MultipleOf, + annotated_types.Timezone, + annotated_types.Interval, + annotated_types.Predicate, + # common predicates not included in annotated_types + _Eq, + _NotEq, + _In, + _NotIn, + # regular expressions + Pattern[str], +] + + +@dataclass(**_slots_frozen) +class _Constraint: + constraint: _ConstraintAnnotation + + +_Step = Union[_ValidateAs, _ValidateAsDefer, _Transform, _PipelineOr, _PipelineAnd, _Constraint] + +_InT = TypeVar('_InT') +_OutT = TypeVar('_OutT') +_NewOutT = TypeVar('_NewOutT') + + +class _FieldTypeMarker: + pass + + +# TODO: ultimately, make this public, see https://github.com/pydantic/pydantic/pull/9459#discussion_r1628197626 +# Also, make this frozen eventually, but that doesn't work right now because of the generic base +# Which attempts to modify __orig_base__ and such. +# We could go with a manual freeze, but that seems overkill for now. +@dataclass(**_slots_true) +class _Pipeline(Generic[_InT, _OutT]): + """Abstract representation of a chain of validation, transformation, and parsing steps.""" + + _steps: tuple[_Step, ...] + + def transform( + self, + func: Callable[[_OutT], _NewOutT], + ) -> _Pipeline[_InT, _NewOutT]: + """Transform the output of the previous step. + + If used as the first step in a pipeline, the type of the field is used. + That is, the transformation is applied to after the value is parsed to the field's type. + """ + return _Pipeline[_InT, _NewOutT](self._steps + (_Transform(func),)) + + @overload + def validate_as(self, tp: type[_NewOutT], *, strict: bool = ...) -> _Pipeline[_InT, _NewOutT]: ... + + @overload + def validate_as(self, tp: EllipsisType, *, strict: bool = ...) -> _Pipeline[_InT, Any]: # type: ignore + ... + + def validate_as(self, tp: type[_NewOutT] | EllipsisType, *, strict: bool = False) -> _Pipeline[_InT, Any]: # type: ignore + """Validate / parse the input into a new type. + + If no type is provided, the type of the field is used. + + Types are parsed in Pydantic's `lax` mode by default, + but you can enable `strict` mode by passing `strict=True`. + """ + if isinstance(tp, EllipsisType): + return _Pipeline[_InT, Any](self._steps + (_ValidateAs(_FieldTypeMarker, strict=strict),)) + return _Pipeline[_InT, _NewOutT](self._steps + (_ValidateAs(tp, strict=strict),)) + + def validate_as_deferred(self, func: Callable[[], type[_NewOutT]]) -> _Pipeline[_InT, _NewOutT]: + """Parse the input into a new type, deferring resolution of the type until the current class + is fully defined. + + This is useful when you need to reference the class in it's own type annotations. + """ + return _Pipeline[_InT, _NewOutT](self._steps + (_ValidateAsDefer(func),)) + + # constraints + @overload + def constrain(self: _Pipeline[_InT, _NewOutGe], constraint: annotated_types.Ge) -> _Pipeline[_InT, _NewOutGe]: ... + + @overload + def constrain(self: _Pipeline[_InT, _NewOutGt], constraint: annotated_types.Gt) -> _Pipeline[_InT, _NewOutGt]: ... + + @overload + def constrain(self: _Pipeline[_InT, _NewOutLe], constraint: annotated_types.Le) -> _Pipeline[_InT, _NewOutLe]: ... + + @overload + def constrain(self: _Pipeline[_InT, _NewOutLt], constraint: annotated_types.Lt) -> _Pipeline[_InT, _NewOutLt]: ... + + @overload + def constrain( + self: _Pipeline[_InT, _NewOutLen], constraint: annotated_types.Len + ) -> _Pipeline[_InT, _NewOutLen]: ... + + @overload + def constrain( + self: _Pipeline[_InT, _NewOutT], constraint: annotated_types.MultipleOf + ) -> _Pipeline[_InT, _NewOutT]: ... + + @overload + def constrain( + self: _Pipeline[_InT, _NewOutDatetime], constraint: annotated_types.Timezone + ) -> _Pipeline[_InT, _NewOutDatetime]: ... + + @overload + def constrain(self: _Pipeline[_InT, _OutT], constraint: annotated_types.Predicate) -> _Pipeline[_InT, _OutT]: ... + + @overload + def constrain( + self: _Pipeline[_InT, _NewOutInterval], constraint: annotated_types.Interval + ) -> _Pipeline[_InT, _NewOutInterval]: ... + + @overload + def constrain(self: _Pipeline[_InT, _OutT], constraint: _Eq) -> _Pipeline[_InT, _OutT]: ... + + @overload + def constrain(self: _Pipeline[_InT, _OutT], constraint: _NotEq) -> _Pipeline[_InT, _OutT]: ... + + @overload + def constrain(self: _Pipeline[_InT, _OutT], constraint: _In) -> _Pipeline[_InT, _OutT]: ... + + @overload + def constrain(self: _Pipeline[_InT, _OutT], constraint: _NotIn) -> _Pipeline[_InT, _OutT]: ... + + @overload + def constrain(self: _Pipeline[_InT, _NewOutT], constraint: Pattern[str]) -> _Pipeline[_InT, _NewOutT]: ... + + def constrain(self, constraint: _ConstraintAnnotation) -> Any: + """Constrain a value to meet a certain condition. + + We support most conditions from `annotated_types`, as well as regular expressions. + + Most of the time you'll be calling a shortcut method like `gt`, `lt`, `len`, etc + so you don't need to call this directly. + """ + return _Pipeline[_InT, _OutT](self._steps + (_Constraint(constraint),)) + + def predicate(self: _Pipeline[_InT, _NewOutT], func: Callable[[_NewOutT], bool]) -> _Pipeline[_InT, _NewOutT]: + """Constrain a value to meet a certain predicate.""" + return self.constrain(annotated_types.Predicate(func)) + + def gt(self: _Pipeline[_InT, _NewOutGt], gt: _NewOutGt) -> _Pipeline[_InT, _NewOutGt]: + """Constrain a value to be greater than a certain value.""" + return self.constrain(annotated_types.Gt(gt)) + + def lt(self: _Pipeline[_InT, _NewOutLt], lt: _NewOutLt) -> _Pipeline[_InT, _NewOutLt]: + """Constrain a value to be less than a certain value.""" + return self.constrain(annotated_types.Lt(lt)) + + def ge(self: _Pipeline[_InT, _NewOutGe], ge: _NewOutGe) -> _Pipeline[_InT, _NewOutGe]: + """Constrain a value to be greater than or equal to a certain value.""" + return self.constrain(annotated_types.Ge(ge)) + + def le(self: _Pipeline[_InT, _NewOutLe], le: _NewOutLe) -> _Pipeline[_InT, _NewOutLe]: + """Constrain a value to be less than or equal to a certain value.""" + return self.constrain(annotated_types.Le(le)) + + def len(self: _Pipeline[_InT, _NewOutLen], min_len: int, max_len: int | None = None) -> _Pipeline[_InT, _NewOutLen]: + """Constrain a value to have a certain length.""" + return self.constrain(annotated_types.Len(min_len, max_len)) + + @overload + def multiple_of(self: _Pipeline[_InT, _NewOutDiv], multiple_of: _NewOutDiv) -> _Pipeline[_InT, _NewOutDiv]: ... + + @overload + def multiple_of(self: _Pipeline[_InT, _NewOutMod], multiple_of: _NewOutMod) -> _Pipeline[_InT, _NewOutMod]: ... + + def multiple_of(self: _Pipeline[_InT, Any], multiple_of: Any) -> _Pipeline[_InT, Any]: + """Constrain a value to be a multiple of a certain number.""" + return self.constrain(annotated_types.MultipleOf(multiple_of)) + + def eq(self: _Pipeline[_InT, _OutT], value: _OutT) -> _Pipeline[_InT, _OutT]: + """Constrain a value to be equal to a certain value.""" + return self.constrain(_Eq(value)) + + def not_eq(self: _Pipeline[_InT, _OutT], value: _OutT) -> _Pipeline[_InT, _OutT]: + """Constrain a value to not be equal to a certain value.""" + return self.constrain(_NotEq(value)) + + def in_(self: _Pipeline[_InT, _OutT], values: Container[_OutT]) -> _Pipeline[_InT, _OutT]: + """Constrain a value to be in a certain set.""" + return self.constrain(_In(values)) + + def not_in(self: _Pipeline[_InT, _OutT], values: Container[_OutT]) -> _Pipeline[_InT, _OutT]: + """Constrain a value to not be in a certain set.""" + return self.constrain(_NotIn(values)) + + # timezone methods + def datetime_tz_naive(self: _Pipeline[_InT, datetime.datetime]) -> _Pipeline[_InT, datetime.datetime]: + return self.constrain(annotated_types.Timezone(None)) + + def datetime_tz_aware(self: _Pipeline[_InT, datetime.datetime]) -> _Pipeline[_InT, datetime.datetime]: + return self.constrain(annotated_types.Timezone(...)) + + def datetime_tz( + self: _Pipeline[_InT, datetime.datetime], tz: datetime.tzinfo + ) -> _Pipeline[_InT, datetime.datetime]: + return self.constrain(annotated_types.Timezone(tz)) # type: ignore + + def datetime_with_tz( + self: _Pipeline[_InT, datetime.datetime], tz: datetime.tzinfo | None + ) -> _Pipeline[_InT, datetime.datetime]: + return self.transform(partial(datetime.datetime.replace, tzinfo=tz)) + + # string methods + def str_lower(self: _Pipeline[_InT, str]) -> _Pipeline[_InT, str]: + return self.transform(str.lower) + + def str_upper(self: _Pipeline[_InT, str]) -> _Pipeline[_InT, str]: + return self.transform(str.upper) + + def str_title(self: _Pipeline[_InT, str]) -> _Pipeline[_InT, str]: + return self.transform(str.title) + + def str_strip(self: _Pipeline[_InT, str]) -> _Pipeline[_InT, str]: + return self.transform(str.strip) + + def str_pattern(self: _Pipeline[_InT, str], pattern: str) -> _Pipeline[_InT, str]: + return self.constrain(re.compile(pattern)) + + def str_contains(self: _Pipeline[_InT, str], substring: str) -> _Pipeline[_InT, str]: + return self.predicate(lambda v: substring in v) + + def str_starts_with(self: _Pipeline[_InT, str], prefix: str) -> _Pipeline[_InT, str]: + return self.predicate(lambda v: v.startswith(prefix)) + + def str_ends_with(self: _Pipeline[_InT, str], suffix: str) -> _Pipeline[_InT, str]: + return self.predicate(lambda v: v.endswith(suffix)) + + # operators + def otherwise(self, other: _Pipeline[_OtherIn, _OtherOut]) -> _Pipeline[_InT | _OtherIn, _OutT | _OtherOut]: + """Combine two validation chains, returning the result of the first chain if it succeeds, and the second chain if it fails.""" + return _Pipeline((_PipelineOr(self, other),)) + + __or__ = otherwise + + def then(self, other: _Pipeline[_OutT, _OtherOut]) -> _Pipeline[_InT, _OtherOut]: + """Pipe the result of one validation chain into another.""" + return _Pipeline((_PipelineAnd(self, other),)) + + __and__ = then + + def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> cs.CoreSchema: + queue = deque(self._steps) + + s = None + + while queue: + step = queue.popleft() + s = _apply_step(step, s, handler, source_type) + + s = s or cs.any_schema() + return s + + def __supports_type__(self, _: _OutT) -> bool: + raise NotImplementedError + + +validate_as = _Pipeline[Any, Any](()).validate_as +validate_as_deferred = _Pipeline[Any, Any](()).validate_as_deferred +transform = _Pipeline[Any, Any]((_ValidateAs(_FieldTypeMarker),)).transform + + +def _check_func( + func: Callable[[Any], bool], predicate_err: str | Callable[[], str], s: cs.CoreSchema | None +) -> cs.CoreSchema: + def handler(v: Any) -> Any: + if func(v): + return v + raise ValueError(f'Expected {predicate_err if isinstance(predicate_err, str) else predicate_err()}') + + if s is None: + return cs.no_info_plain_validator_function(handler) + else: + return cs.no_info_after_validator_function(handler, s) + + +def _apply_step(step: _Step, s: cs.CoreSchema | None, handler: GetCoreSchemaHandler, source_type: Any) -> cs.CoreSchema: + if isinstance(step, _ValidateAs): + s = _apply_parse(s, step.tp, step.strict, handler, source_type) + elif isinstance(step, _ValidateAsDefer): + s = _apply_parse(s, step.tp, False, handler, source_type) + elif isinstance(step, _Transform): + s = _apply_transform(s, step.func, handler) + elif isinstance(step, _Constraint): + s = _apply_constraint(s, step.constraint) + elif isinstance(step, _PipelineOr): + s = cs.union_schema([handler(step.left), handler(step.right)]) + else: + assert isinstance(step, _PipelineAnd) + s = cs.chain_schema([handler(step.left), handler(step.right)]) + return s + + +def _apply_parse( + s: cs.CoreSchema | None, + tp: type[Any], + strict: bool, + handler: GetCoreSchemaHandler, + source_type: Any, +) -> cs.CoreSchema: + if tp is _FieldTypeMarker: + return cs.chain_schema([s, handler(source_type)]) if s else handler(source_type) + + if strict: + tp = Annotated[tp, Strict()] # type: ignore + + if s and s['type'] == 'any': + return handler(tp) + else: + return cs.chain_schema([s, handler(tp)]) if s else handler(tp) + + +def _apply_transform( + s: cs.CoreSchema | None, func: Callable[[Any], Any], handler: GetCoreSchemaHandler +) -> cs.CoreSchema: + if s is None: + return cs.no_info_plain_validator_function(func) + + if s['type'] == 'str': + if func is str.strip: + s = s.copy() + s['strip_whitespace'] = True + return s + elif func is str.lower: + s = s.copy() + s['to_lower'] = True + return s + elif func is str.upper: + s = s.copy() + s['to_upper'] = True + return s + + return cs.no_info_after_validator_function(func, s) + + +def _apply_constraint( # noqa: C901 + s: cs.CoreSchema | None, constraint: _ConstraintAnnotation +) -> cs.CoreSchema: + """Apply a single constraint to a schema.""" + if isinstance(constraint, annotated_types.Gt): + gt = constraint.gt + if s and s['type'] in {'int', 'float', 'decimal'}: + s = s.copy() + if s['type'] == 'int' and isinstance(gt, int): + s['gt'] = gt + elif s['type'] == 'float' and isinstance(gt, float): + s['gt'] = gt + elif s['type'] == 'decimal' and isinstance(gt, Decimal): + s['gt'] = gt + else: + + def check_gt(v: Any) -> bool: + return v > gt + + s = _check_func(check_gt, f'> {gt}', s) + elif isinstance(constraint, annotated_types.Ge): + ge = constraint.ge + if s and s['type'] in {'int', 'float', 'decimal'}: + s = s.copy() + if s['type'] == 'int' and isinstance(ge, int): + s['ge'] = ge + elif s['type'] == 'float' and isinstance(ge, float): + s['ge'] = ge + elif s['type'] == 'decimal' and isinstance(ge, Decimal): + s['ge'] = ge + + def check_ge(v: Any) -> bool: + return v >= ge + + s = _check_func(check_ge, f'>= {ge}', s) + elif isinstance(constraint, annotated_types.Lt): + lt = constraint.lt + if s and s['type'] in {'int', 'float', 'decimal'}: + s = s.copy() + if s['type'] == 'int' and isinstance(lt, int): + s['lt'] = lt + elif s['type'] == 'float' and isinstance(lt, float): + s['lt'] = lt + elif s['type'] == 'decimal' and isinstance(lt, Decimal): + s['lt'] = lt + + def check_lt(v: Any) -> bool: + return v < lt + + s = _check_func(check_lt, f'< {lt}', s) + elif isinstance(constraint, annotated_types.Le): + le = constraint.le + if s and s['type'] in {'int', 'float', 'decimal'}: + s = s.copy() + if s['type'] == 'int' and isinstance(le, int): + s['le'] = le + elif s['type'] == 'float' and isinstance(le, float): + s['le'] = le + elif s['type'] == 'decimal' and isinstance(le, Decimal): + s['le'] = le + + def check_le(v: Any) -> bool: + return v <= le + + s = _check_func(check_le, f'<= {le}', s) + elif isinstance(constraint, annotated_types.Len): + min_len = constraint.min_length + max_len = constraint.max_length + + if s and s['type'] in {'str', 'list', 'tuple', 'set', 'frozenset', 'dict'}: + assert ( + s['type'] == 'str' + or s['type'] == 'list' + or s['type'] == 'tuple' + or s['type'] == 'set' + or s['type'] == 'dict' + or s['type'] == 'frozenset' + ) + s = s.copy() + if min_len != 0: + s['min_length'] = min_len + if max_len is not None: + s['max_length'] = max_len + + def check_len(v: Any) -> bool: + if max_len is not None: + return (min_len <= len(v)) and (len(v) <= max_len) + return min_len <= len(v) + + s = _check_func(check_len, f'length >= {min_len} and length <= {max_len}', s) + elif isinstance(constraint, annotated_types.MultipleOf): + multiple_of = constraint.multiple_of + if s and s['type'] in {'int', 'float', 'decimal'}: + s = s.copy() + if s['type'] == 'int' and isinstance(multiple_of, int): + s['multiple_of'] = multiple_of + elif s['type'] == 'float' and isinstance(multiple_of, float): + s['multiple_of'] = multiple_of + elif s['type'] == 'decimal' and isinstance(multiple_of, Decimal): + s['multiple_of'] = multiple_of + + def check_multiple_of(v: Any) -> bool: + return v % multiple_of == 0 + + s = _check_func(check_multiple_of, f'% {multiple_of} == 0', s) + elif isinstance(constraint, annotated_types.Timezone): + tz = constraint.tz + + if tz is ...: + if s and s['type'] == 'datetime': + s = s.copy() + s['tz_constraint'] = 'aware' + else: + + def check_tz_aware(v: object) -> bool: + assert isinstance(v, datetime.datetime) + return v.tzinfo is not None + + s = _check_func(check_tz_aware, 'timezone aware', s) + elif tz is None: + if s and s['type'] == 'datetime': + s = s.copy() + s['tz_constraint'] = 'naive' + else: + + def check_tz_naive(v: object) -> bool: + assert isinstance(v, datetime.datetime) + return v.tzinfo is None + + s = _check_func(check_tz_naive, 'timezone naive', s) + else: + raise NotImplementedError('Constraining to a specific timezone is not yet supported') + elif isinstance(constraint, annotated_types.Interval): + if constraint.ge: + s = _apply_constraint(s, annotated_types.Ge(constraint.ge)) + if constraint.gt: + s = _apply_constraint(s, annotated_types.Gt(constraint.gt)) + if constraint.le: + s = _apply_constraint(s, annotated_types.Le(constraint.le)) + if constraint.lt: + s = _apply_constraint(s, annotated_types.Lt(constraint.lt)) + assert s is not None + elif isinstance(constraint, annotated_types.Predicate): + func = constraint.func + # Same logic as in `_known_annotated_metadata.apply_known_metadata()`: + predicate_name = f'{func.__qualname__!r} ' if hasattr(func, '__qualname__') else '' + + def predicate_func(v: Any) -> Any: + if not func(v): + raise PydanticCustomError( + 'predicate_failed', + f'Predicate {predicate_name}failed', # pyright: ignore[reportArgumentType] + ) + return v + + if s is None: + s = cs.no_info_plain_validator_function(predicate_func) + else: + s = cs.no_info_after_validator_function(predicate_func, s) + elif isinstance(constraint, _NotEq): + value = constraint.value + + def check_not_eq(v: Any) -> bool: + return operator.__ne__(v, value) + + s = _check_func(check_not_eq, f'!= {value}', s) + elif isinstance(constraint, _Eq): + value = constraint.value + + def check_eq(v: Any) -> bool: + return operator.__eq__(v, value) + + s = _check_func(check_eq, f'== {value}', s) + elif isinstance(constraint, _In): + values = constraint.values + + def check_in(v: Any) -> bool: + return operator.__contains__(values, v) + + s = _check_func(check_in, f'in {values}', s) + elif isinstance(constraint, _NotIn): + values = constraint.values + + def check_not_in(v: Any) -> bool: + return operator.__not__(operator.__contains__(values, v)) + + s = _check_func(check_not_in, f'not in {values}', s) + else: + assert isinstance(constraint, Pattern) + if s and s['type'] == 'str': + s = s.copy() + s['pattern'] = constraint.pattern + else: + + def check_pattern(v: object) -> bool: + assert isinstance(v, str) + return constraint.match(v) is not None + + s = _check_func(check_pattern, f'~ {constraint.pattern}', s) + return s + + +class _SupportsRange(annotated_types.SupportsLe, annotated_types.SupportsGe, Protocol): + pass + + +class _SupportsLen(Protocol): + def __len__(self) -> int: ... + + +_NewOutGt = TypeVar('_NewOutGt', bound=annotated_types.SupportsGt) +_NewOutGe = TypeVar('_NewOutGe', bound=annotated_types.SupportsGe) +_NewOutLt = TypeVar('_NewOutLt', bound=annotated_types.SupportsLt) +_NewOutLe = TypeVar('_NewOutLe', bound=annotated_types.SupportsLe) +_NewOutLen = TypeVar('_NewOutLen', bound=_SupportsLen) +_NewOutDiv = TypeVar('_NewOutDiv', bound=annotated_types.SupportsDiv) +_NewOutMod = TypeVar('_NewOutMod', bound=annotated_types.SupportsMod) +_NewOutDatetime = TypeVar('_NewOutDatetime', bound=datetime.datetime) +_NewOutInterval = TypeVar('_NewOutInterval', bound=_SupportsRange) +_OtherIn = TypeVar('_OtherIn') +_OtherOut = TypeVar('_OtherOut') diff --git a/backend/.venv/Lib/site-packages/pydantic/fields.py b/backend/.venv/Lib/site-packages/pydantic/fields.py new file mode 100644 index 0000000..b091710 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/fields.py @@ -0,0 +1,1834 @@ +"""Defining fields on models.""" + +from __future__ import annotations as _annotations + +import dataclasses +import inspect +import re +import sys +from collections.abc import Callable, Mapping +from copy import copy +from dataclasses import Field as DataclassField +from functools import cached_property +from typing import TYPE_CHECKING, Annotated, Any, ClassVar, Literal, TypeVar, cast, final, overload +from warnings import warn + +import annotated_types +import typing_extensions +from pydantic_core import MISSING, PydanticUndefined +from typing_extensions import Self, TypeAlias, TypedDict, Unpack, deprecated +from typing_inspection import typing_objects +from typing_inspection.introspection import UNKNOWN, AnnotationSource, ForbiddenQualifier, Qualifier, inspect_annotation + +from . import types +from ._internal import _decorators, _fields, _generics, _internal_dataclass, _repr, _typing_extra, _utils +from ._internal._namespace_utils import GlobalsNamespace, MappingNamespace +from .aliases import AliasChoices, AliasGenerator, AliasPath +from .config import JsonDict +from .errors import PydanticForbiddenQualifier, PydanticUserError +from .json_schema import PydanticJsonSchemaWarning +from .warnings import PydanticDeprecatedSince20 + +if TYPE_CHECKING: + from ._internal._config import ConfigWrapper + from ._internal._repr import ReprArgs + + +__all__ = 'Field', 'FieldInfo', 'PrivateAttr', 'computed_field' + + +_Unset: Any = PydanticUndefined + +if sys.version_info >= (3, 13): + import warnings + + Deprecated: TypeAlias = warnings.deprecated | deprecated +else: + Deprecated: TypeAlias = deprecated + + +class _FromFieldInfoInputs(TypedDict, total=False): + """This class exists solely to add type checking for the `**kwargs` in `FieldInfo.from_field`.""" + + # TODO PEP 747: use TypeForm: + annotation: type[Any] | None + default_factory: Callable[[], Any] | Callable[[dict[str, Any]], Any] | None + alias: str | None + alias_priority: int | None + validation_alias: str | AliasPath | AliasChoices | None + serialization_alias: str | None + title: str | None + field_title_generator: Callable[[str, FieldInfo], str] | None + description: str | None + examples: list[Any] | None + exclude: bool | None + exclude_if: Callable[[Any], bool] | None + gt: annotated_types.SupportsGt | None + ge: annotated_types.SupportsGe | None + lt: annotated_types.SupportsLt | None + le: annotated_types.SupportsLe | None + multiple_of: float | None + strict: bool | None + min_length: int | None + max_length: int | None + pattern: str | re.Pattern[str] | None + allow_inf_nan: bool | None + max_digits: int | None + decimal_places: int | None + union_mode: Literal['smart', 'left_to_right'] | None + discriminator: str | types.Discriminator | None + deprecated: Deprecated | str | bool | None + json_schema_extra: JsonDict | Callable[[JsonDict], None] | None + frozen: bool | None + validate_default: bool | None + repr: bool + init: bool | None + init_var: bool | None + kw_only: bool | None + coerce_numbers_to_str: bool | None + fail_fast: bool | None + + +class _FieldInfoInputs(_FromFieldInfoInputs, total=False): + """This class exists solely to add type checking for the `**kwargs` in `FieldInfo.__init__`.""" + + default: Any + + +class _FieldInfoAsDict(TypedDict, closed=True): + # TODO PEP 747: use TypeForm: + annotation: Any + metadata: list[Any] + attributes: dict[str, Any] + + +@final +class FieldInfo(_repr.Representation): + """This class holds information about a field. + + `FieldInfo` is used for any field definition regardless of whether the [`Field()`][pydantic.fields.Field] + function is explicitly used. + + !!! warning + The `FieldInfo` class is meant to expose information about a field in a Pydantic model or dataclass. + `FieldInfo` instances shouldn't be instantiated directly, nor mutated. + + If you need to derive a new model from another one and are willing to alter `FieldInfo` instances, + refer to this [dynamic model example](../examples/dynamic_models.md). + + Attributes: + annotation: The type annotation of the field. + default: The default value of the field. + default_factory: A callable to generate the default value. The callable can either take 0 arguments + (in which case it is called as is) or a single argument containing the already validated data. + alias: The alias name of the field. + alias_priority: The priority of the field's alias. + validation_alias: The validation alias of the field. + serialization_alias: The serialization alias of the field. + title: The title of the field. + field_title_generator: A callable that takes a field name and returns title for it. + description: The description of the field. + examples: List of examples of the field. + exclude: Whether to exclude the field from the model serialization. + exclude_if: A callable that determines whether to exclude a field during serialization based on its value. + discriminator: Field name or Discriminator for discriminating the type in a tagged union. + deprecated: A deprecation message, an instance of `warnings.deprecated` or the `typing_extensions.deprecated` backport, + or a boolean. If `True`, a default deprecation message will be emitted when accessing the field. + json_schema_extra: A dict or callable to provide extra JSON schema properties. + frozen: Whether the field is frozen. + validate_default: Whether to validate the default value of the field. + repr: Whether to include the field in representation of the model. + init: Whether the field should be included in the constructor of the dataclass. + init_var: Whether the field should _only_ be included in the constructor of the dataclass, and not stored. + kw_only: Whether the field should be a keyword-only argument in the constructor of the dataclass. + metadata: The metadata list. Contains all the data that isn't expressed as direct `FieldInfo` attributes, including: + + * Type-specific constraints, such as `gt` or `min_length` (these are converted to metadata classes such as `annotated_types.Gt`). + * Any other arbitrary object used within [`Annotated`][typing.Annotated] metadata + (e.g. [custom types handlers](../concepts/types.md#as-an-annotation) or any object not recognized by Pydantic). + """ + + # TODO PEP 747: use TypeForm: + annotation: type[Any] | None + default: Any + default_factory: Callable[[], Any] | Callable[[dict[str, Any]], Any] | None + alias: str | None + alias_priority: int | None + validation_alias: str | AliasPath | AliasChoices | None + serialization_alias: str | None + title: str | None + field_title_generator: Callable[[str, FieldInfo], str] | None + description: str | None + examples: list[Any] | None + exclude: bool | None + exclude_if: Callable[[Any], bool] | None + discriminator: str | types.Discriminator | None + deprecated: Deprecated | str | bool | None + json_schema_extra: JsonDict | Callable[[JsonDict], None] | None + frozen: bool | None + validate_default: bool | None + repr: bool + init: bool | None + init_var: bool | None + kw_only: bool | None + metadata: list[Any] + + __slots__ = ( + 'annotation', + 'default', + 'default_factory', + 'alias', + 'alias_priority', + 'validation_alias', + 'serialization_alias', + 'title', + 'field_title_generator', + 'description', + 'examples', + 'exclude', + 'exclude_if', + 'discriminator', + 'deprecated', + 'json_schema_extra', + 'frozen', + 'validate_default', + 'repr', + 'init', + 'init_var', + 'kw_only', + 'metadata', + '_attributes_set', + '_qualifiers', + '_complete', + '_original_assignment', + '_original_annotation', + '_final', + ) + + # used to convert kwargs to metadata/constraints, + # None has a special meaning - these items are collected into a `PydanticGeneralMetadata` + metadata_lookup: ClassVar[dict[str, Callable[[Any], Any] | None]] = { + 'strict': types.Strict, + 'gt': annotated_types.Gt, + 'ge': annotated_types.Ge, + 'lt': annotated_types.Lt, + 'le': annotated_types.Le, + 'multiple_of': annotated_types.MultipleOf, + 'min_length': annotated_types.MinLen, + 'max_length': annotated_types.MaxLen, + 'pattern': None, + 'allow_inf_nan': None, + 'max_digits': None, + 'decimal_places': None, + 'union_mode': None, + 'coerce_numbers_to_str': None, + 'fail_fast': types.FailFast, + } + + def __init__(self, **kwargs: Unpack[_FieldInfoInputs]) -> None: + """This class should generally not be initialized directly; instead, use the `pydantic.fields.Field` function + or one of the constructor classmethods. + + See the signature of `pydantic.fields.Field` for more details about the expected arguments. + """ + # Tracking the explicitly set attributes is necessary to correctly merge `Field()` functions + # (e.g. with `Annotated[int, Field(alias='a'), Field(alias=None)]`, even though `None` is the default value, + # we need to track that `alias=None` was explicitly set): + self._attributes_set = {k: v for k, v in kwargs.items() if v is not _Unset and k not in self.metadata_lookup} + kwargs = {k: _DefaultValues.get(k) if v is _Unset else v for k, v in kwargs.items()} # type: ignore + self.annotation = kwargs.get('annotation') + + # Note: in theory, the second `pop()` arguments are not required below, as defaults are already set from `_DefaultsValues`. + default = kwargs.pop('default', PydanticUndefined) + if default is Ellipsis: + self.default = PydanticUndefined + self._attributes_set.pop('default', None) + else: + self.default = default + + self.default_factory = kwargs.pop('default_factory', None) + + if self.default is not PydanticUndefined and self.default_factory is not None: + raise TypeError('cannot specify both default and default_factory') + + self.alias = kwargs.pop('alias', None) + self.validation_alias = kwargs.pop('validation_alias', None) + self.serialization_alias = kwargs.pop('serialization_alias', None) + alias_is_set = any(alias is not None for alias in (self.alias, self.validation_alias, self.serialization_alias)) + self.alias_priority = kwargs.pop('alias_priority', None) or 2 if alias_is_set else None + self.title = kwargs.pop('title', None) + self.field_title_generator = kwargs.pop('field_title_generator', None) + self.description = kwargs.pop('description', None) + self.examples = kwargs.pop('examples', None) + self.exclude = kwargs.pop('exclude', None) + self.exclude_if = kwargs.pop('exclude_if', None) + self.discriminator = kwargs.pop('discriminator', None) + # For compatibility with FastAPI<=0.110.0, we preserve the existing value if it is not overridden + self.deprecated = kwargs.pop('deprecated', getattr(self, 'deprecated', None)) + self.repr = kwargs.pop('repr', True) + self.json_schema_extra = kwargs.pop('json_schema_extra', None) + self.validate_default = kwargs.pop('validate_default', None) + self.frozen = kwargs.pop('frozen', None) + # currently only used on dataclasses + self.init = kwargs.pop('init', None) + self.init_var = kwargs.pop('init_var', None) + self.kw_only = kwargs.pop('kw_only', None) + + self.metadata = self._collect_metadata(kwargs) # type: ignore + + # Private attributes: + self._qualifiers: set[Qualifier] = set() + # Used to rebuild FieldInfo instances: + self._complete = True + self._original_annotation: Any = PydanticUndefined + self._original_assignment: Any = PydanticUndefined + # Used to track whether the `FieldInfo` instance represents the data about a field (and is exposed in `model_fields`/`__pydantic_fields__`), + # or if it is the result of the `Field()` function being used as metadata in an `Annotated` type/as an assignment + # (not an ideal pattern, see https://github.com/pydantic/pydantic/issues/11122): + self._final = False + + @staticmethod + def from_field(default: Any = PydanticUndefined, **kwargs: Unpack[_FromFieldInfoInputs]) -> FieldInfo: + """Create a new `FieldInfo` object with the `Field` function. + + Args: + default: The default value for the field. Defaults to Undefined. + **kwargs: Additional arguments dictionary. + + Raises: + TypeError: If 'annotation' is passed as a keyword argument. + + Returns: + A new FieldInfo object with the given parameters. + + Example: + This is how you can create a field with default value like this: + + ```python + import pydantic + + class MyModel(pydantic.BaseModel): + foo: int = pydantic.Field(4) + ``` + """ + if 'annotation' in kwargs: + raise TypeError('"annotation" is not permitted as a Field keyword argument') + return FieldInfo(default=default, **kwargs) + + @staticmethod + def from_annotation(annotation: type[Any], *, _source: AnnotationSource = AnnotationSource.ANY) -> FieldInfo: + """Creates a `FieldInfo` instance from a bare annotation. + + This function is used internally to create a `FieldInfo` from a bare annotation like this: + + ```python + import pydantic + + class MyModel(pydantic.BaseModel): + foo: int # <-- like this + ``` + + We also account for the case where the annotation can be an instance of `Annotated` and where + one of the (not first) arguments in `Annotated` is an instance of `FieldInfo`, e.g.: + + ```python + from typing import Annotated + + import annotated_types + + import pydantic + + class MyModel(pydantic.BaseModel): + foo: Annotated[int, annotated_types.Gt(42)] + bar: Annotated[int, pydantic.Field(gt=42)] + ``` + + Args: + annotation: An annotation object. + + Returns: + An instance of the field metadata. + """ + try: + inspected_ann = inspect_annotation( + annotation, + annotation_source=_source, + unpack_type_aliases='skip', + ) + except ForbiddenQualifier as e: + raise PydanticForbiddenQualifier(e.qualifier, annotation) + + # TODO check for classvar and error? + + # No assigned value, this happens when using a bare `Final` qualifier (also for other + # qualifiers, but they shouldn't appear here). In this case we infer the type as `Any` + # because we don't have any assigned value. + type_expr: Any = Any if inspected_ann.type is UNKNOWN else inspected_ann.type + final = 'final' in inspected_ann.qualifiers + metadata = inspected_ann.metadata + + attr_overrides = {'annotation': type_expr} + if final: + attr_overrides['frozen'] = True + field_info = FieldInfo._construct(metadata, **attr_overrides) + field_info._qualifiers = inspected_ann.qualifiers + field_info._final = True + return field_info + + @staticmethod + def from_annotated_attribute( + annotation: type[Any], default: Any, *, _source: AnnotationSource = AnnotationSource.ANY + ) -> FieldInfo: + """Create `FieldInfo` from an annotation with a default value. + + This is used in cases like the following: + + ```python + from typing import Annotated + + import annotated_types + + import pydantic + + class MyModel(pydantic.BaseModel): + foo: int = 4 # <-- like this + bar: Annotated[int, annotated_types.Gt(4)] = 4 # <-- or this + spam: Annotated[int, pydantic.Field(gt=4)] = 4 # <-- or this + ``` + + Args: + annotation: The type annotation of the field. + default: The default value of the field. + + Returns: + A field object with the passed values. + """ + if annotation is not MISSING and annotation is default: + raise PydanticUserError( + 'Error when building FieldInfo from annotated attribute. ' + "Make sure you don't have any field name clashing with a type annotation.", + code='unevaluable-type-annotation', + ) + + try: + inspected_ann = inspect_annotation( + annotation, + annotation_source=_source, + unpack_type_aliases='skip', + ) + except ForbiddenQualifier as e: + raise PydanticForbiddenQualifier(e.qualifier, annotation) + + # TODO check for classvar and error? + + # TODO infer from the default, this can be done in v3 once we treat final fields with + # a default as proper fields and not class variables: + type_expr: Any = Any if inspected_ann.type is UNKNOWN else inspected_ann.type + final = 'final' in inspected_ann.qualifiers + metadata = inspected_ann.metadata + + # HACK 1: the order in which the metadata is merged is inconsistent; we need to prepend + # metadata from the assignment at the beginning of the metadata. Changing this is only + # possible in v3 (at least). See https://github.com/pydantic/pydantic/issues/10507 + prepend_metadata: list[Any] | None = None + attr_overrides = {'annotation': type_expr} + if final: + attr_overrides['frozen'] = True + + # HACK 2: FastAPI is subclassing `FieldInfo` and historically expected the actual + # instance's type to be preserved when constructing new models with its subclasses as assignments. + # This code is never reached by Pydantic itself, and in an ideal world this shouldn't be necessary. + if not metadata and isinstance(default, FieldInfo) and type(default) is not FieldInfo: + field_info = default._copy() + field_info._attributes_set.update(attr_overrides) + for k, v in attr_overrides.items(): + setattr(field_info, k, v) + return field_info + + if isinstance(default, FieldInfo): + default_copy = default._copy() # Copy unnecessary when we remove HACK 1. + prepend_metadata = default_copy.metadata + default_copy.metadata = [] + metadata = metadata + [default_copy] + elif isinstance(default, dataclasses.Field): + from_field = FieldInfo._from_dataclass_field(default) + prepend_metadata = from_field.metadata # Unnecessary when we remove HACK 1. + from_field.metadata = [] + metadata = metadata + [from_field] + if 'init_var' in inspected_ann.qualifiers: + attr_overrides['init_var'] = True + if (init := getattr(default, 'init', None)) is not None: + attr_overrides['init'] = init + if (kw_only := getattr(default, 'kw_only', None)) is not None: + attr_overrides['kw_only'] = kw_only + else: + # `default` is the actual default value + attr_overrides['default'] = default + + field_info = FieldInfo._construct( + prepend_metadata + metadata if prepend_metadata is not None else metadata, **attr_overrides + ) + field_info._qualifiers = inspected_ann.qualifiers + field_info._final = True + return field_info + + @classmethod + def _construct(cls, metadata: list[Any], **attr_overrides: Any) -> Self: + """Construct the final `FieldInfo` instance, by merging the possibly existing `FieldInfo` instances from the metadata. + + With the following example: + + ```python {test="skip" lint="skip"} + class Model(BaseModel): + f: Annotated[int, Gt(1), Field(description='desc', lt=2)] + ``` + + `metadata` refers to the metadata elements of the `Annotated` form. This metadata is iterated over from left to right: + + - If the element is a `Field()` function (which is itself a `FieldInfo` instance), the field attributes (such as + `description`) are saved to be set on the final `FieldInfo` instance. + On the other hand, some kwargs (such as `lt`) are stored as `metadata` (see `FieldInfo.__init__()`, calling + `FieldInfo._collect_metadata()`). In this case, the final metadata list is extended with the one from this instance. + - Else, the element is considered as a single metadata object, and is appended to the final metadata list. + + Args: + metadata: The list of metadata elements to merge together. If the `FieldInfo` instance to be constructed is for + a field with an assigned `Field()`, this `Field()` assignment should be added as the last element of the + provided metadata. + **attr_overrides: Extra attributes that should be set on the final merged `FieldInfo` instance. + + Returns: + The final merged `FieldInfo` instance. + """ + merged_metadata: list[Any] = [] + merged_kwargs: dict[str, Any] = {} + + for meta in metadata: + if isinstance(meta, FieldInfo): + merged_metadata.extend(meta.metadata) + + new_js_extra: JsonDict | None = None + current_js_extra = meta.json_schema_extra + if current_js_extra is not None and 'json_schema_extra' in merged_kwargs: + # We need to merge `json_schema_extra`'s: + existing_js_extra = merged_kwargs['json_schema_extra'] + if isinstance(existing_js_extra, dict): + if isinstance(current_js_extra, dict): + new_js_extra = { + **existing_js_extra, + **current_js_extra, + } + elif callable(current_js_extra): + warn( + 'Composing `dict` and `callable` type `json_schema_extra` is not supported. ' + 'The `callable` type is being ignored. ' + "If you'd like support for this behavior, please open an issue on pydantic.", + UserWarning, + ) + elif callable(existing_js_extra) and isinstance(current_js_extra, dict): + warn( + 'Composing `dict` and `callable` type `json_schema_extra` is not supported. ' + 'The `callable` type is being ignored. ' + "If you'd like support for this behavior, please open an issue on pydantic.", + UserWarning, + ) + + # HACK: It is common for users to define "make model partial" (or similar) utilities, that + # convert all model fields to be optional (i.e. have a default value). To do so, they mutate + # each `FieldInfo` instance from `model_fields` to set a `default`, and use `create_model()` + # with `Annotated[ | None, mutated_field_info]`` as an annotation. However, such + # mutations (by doing simple assignments) are only accidentally working, because we also + # need to track attributes explicitly set in `_attributes_set` (relying on default values for + # each attribute is *not* enough, for instance with `Annotated[int, Field(alias='a'), Field(alias=None)]` + # the resulting `FieldInfo` should have `alias=None`). + # To mitigate this, we add a special case when a "final" `FieldInfo` instance (that is an instance coming + # from `model_fields`) is used in annotated metadata (or assignment). In this case, we assume *all* attributes + # were explicitly set, and as such we use all of them (and this will correctly pick up the mutations). + # In theory, this shouldn't really be supported, you are only supposed to use the `Field()` function, not + # a `FieldInfo` instance directly (granted, `Field()` returns a `FieldInfo`, see + # https://github.com/pydantic/pydantic/issues/11122): + if meta._final: + merged_kwargs.update({attr: getattr(meta, attr) for attr in _Attrs}) + else: + merged_kwargs.update(meta._attributes_set) + + if new_js_extra is not None: + merged_kwargs['json_schema_extra'] = new_js_extra + elif typing_objects.is_deprecated(meta): + merged_kwargs['deprecated'] = meta + else: + merged_metadata.append(meta) + + merged_kwargs.update(attr_overrides) + merged_field_info = cls(**merged_kwargs) + merged_field_info.metadata = merged_metadata + return merged_field_info + + @staticmethod + @typing_extensions.deprecated( + "The 'merge_field_infos()' method is deprecated and will be removed in a future version. " + 'If you relied on this method, please open an issue in the Pydantic issue tracker.', + category=None, + ) + def merge_field_infos(*field_infos: FieldInfo, **overrides: Any) -> FieldInfo: + """Merge `FieldInfo` instances keeping only explicitly set attributes. + + Later `FieldInfo` instances override earlier ones. + + Returns: + FieldInfo: A merged FieldInfo instance. + """ + if len(field_infos) == 1: + # No merging necessary, but we still need to make a copy and apply the overrides + field_info = field_infos[0]._copy() + field_info._attributes_set.update(overrides) + + default_override = overrides.pop('default', PydanticUndefined) + if default_override is Ellipsis: + default_override = PydanticUndefined + if default_override is not PydanticUndefined: + field_info.default = default_override + + for k, v in overrides.items(): + setattr(field_info, k, v) + return field_info # type: ignore + + merged_field_info_kwargs: dict[str, Any] = {} + metadata = {} + for field_info in field_infos: + attributes_set = field_info._attributes_set.copy() + + try: + json_schema_extra = attributes_set.pop('json_schema_extra') + existing_json_schema_extra = merged_field_info_kwargs.get('json_schema_extra') + + if existing_json_schema_extra is None: + merged_field_info_kwargs['json_schema_extra'] = json_schema_extra + if isinstance(existing_json_schema_extra, dict): + if isinstance(json_schema_extra, dict): + merged_field_info_kwargs['json_schema_extra'] = { + **existing_json_schema_extra, + **json_schema_extra, + } + if callable(json_schema_extra): + warn( + 'Composing `dict` and `callable` type `json_schema_extra` is not supported.' + 'The `callable` type is being ignored.' + "If you'd like support for this behavior, please open an issue on pydantic.", + PydanticJsonSchemaWarning, + ) + elif callable(json_schema_extra): + # if ever there's a case of a callable, we'll just keep the last json schema extra spec + merged_field_info_kwargs['json_schema_extra'] = json_schema_extra + except KeyError: + pass + + # later FieldInfo instances override everything except json_schema_extra from earlier FieldInfo instances + merged_field_info_kwargs.update(attributes_set) + + for x in field_info.metadata: + if not isinstance(x, FieldInfo): + metadata[type(x)] = x + + merged_field_info_kwargs.update(overrides) + field_info = FieldInfo(**merged_field_info_kwargs) + field_info.metadata = list(metadata.values()) + return field_info + + @staticmethod + def _from_dataclass_field(dc_field: DataclassField[Any]) -> FieldInfo: + """Return a new `FieldInfo` instance from a `dataclasses.Field` instance. + + Args: + dc_field: The `dataclasses.Field` instance to convert. + + Returns: + The corresponding `FieldInfo` instance. + + Raises: + TypeError: If any of the `FieldInfo` kwargs does not match the `dataclass.Field` kwargs. + """ + default = dc_field.default + if default is dataclasses.MISSING: + default = _Unset + + if dc_field.default_factory is dataclasses.MISSING: + default_factory = _Unset + else: + default_factory = dc_field.default_factory + + # use the `Field` function so in correct kwargs raise the correct `TypeError` + dc_field_metadata = {k: v for k, v in dc_field.metadata.items() if k in _FIELD_ARG_NAMES} + if sys.version_info >= (3, 14) and dc_field.doc is not None: + dc_field_metadata['description'] = dc_field.doc + return Field(default=default, default_factory=default_factory, repr=dc_field.repr, **dc_field_metadata) # pyright: ignore[reportCallIssue] + + @staticmethod + def _collect_metadata(kwargs: dict[str, Any]) -> list[Any]: + """Collect annotations from kwargs. + + Args: + kwargs: Keyword arguments passed to the function. + + Returns: + A list of metadata objects - a combination of `annotated_types.BaseMetadata` and + `PydanticMetadata`. + """ + metadata: list[Any] = [] + general_metadata = {} + for key, value in list(kwargs.items()): + try: + marker = FieldInfo.metadata_lookup[key] + except KeyError: + continue + + del kwargs[key] + if value is not None: + if marker is None: + general_metadata[key] = value + else: + metadata.append(marker(value)) + if general_metadata: + metadata.append(_fields.pydantic_general_metadata(**general_metadata)) + return metadata + + @property + def deprecation_message(self) -> str | None: + """The deprecation message to be emitted, or `None` if not set.""" + if self.deprecated is None: + return None + if isinstance(self.deprecated, bool): + return 'deprecated' if self.deprecated else None + return self.deprecated if isinstance(self.deprecated, str) else self.deprecated.message + + @property + def default_factory_takes_validated_data(self) -> bool | None: + """Whether the provided default factory callable has a validated data parameter. + + Returns `None` if no default factory is set. + """ + if self.default_factory is not None: + return _fields.takes_validated_data_argument(self.default_factory) + + @overload + def get_default( + self, *, call_default_factory: Literal[True], validated_data: dict[str, Any] | None = None + ) -> Any: ... + + @overload + def get_default(self, *, call_default_factory: Literal[False] = ...) -> Any: ... + + def get_default(self, *, call_default_factory: bool = False, validated_data: dict[str, Any] | None = None) -> Any: + """Get the default value. + + We expose an option for whether to call the default_factory (if present), as calling it may + result in side effects that we want to avoid. However, there are times when it really should + be called (namely, when instantiating a model via `model_construct`). + + Args: + call_default_factory: Whether to call the default factory or not. + validated_data: The already validated data to be passed to the default factory. + + Returns: + The default value, calling the default factory if requested or `None` if not set. + """ + if self.default_factory is None: + return _utils.smart_deepcopy(self.default) + elif call_default_factory: + if self.default_factory_takes_validated_data: + fac = cast('Callable[[dict[str, Any]], Any]', self.default_factory) + if validated_data is None: + raise ValueError( + "The default factory requires the 'validated_data' argument, which was not provided when calling 'get_default'." + ) + return fac(validated_data) + else: + fac = cast('Callable[[], Any]', self.default_factory) + return fac() + else: + return None + + def is_required(self) -> bool: + """Check if the field is required (i.e., does not have a default value or factory). + + Returns: + `True` if the field is required, `False` otherwise. + """ + return self.default is PydanticUndefined and self.default_factory is None + + def rebuild_annotation(self) -> Any: + """Attempts to rebuild the original annotation for use in function signatures. + + If metadata is present, it adds it to the original annotation using + `Annotated`. Otherwise, it returns the original annotation as-is. + + Note that because the metadata has been flattened, the original annotation + may not be reconstructed exactly as originally provided, e.g. if the original + type had unrecognized annotations, or was annotated with a call to `pydantic.Field`. + + Returns: + The rebuilt annotation. + """ + if not self.metadata: + return self.annotation + else: + # Annotated arguments must be a tuple + return Annotated[(self.annotation, *self.metadata)] # type: ignore + + def apply_typevars_map( + self, + typevars_map: Mapping[TypeVar, Any] | None, + globalns: GlobalsNamespace | None = None, + localns: MappingNamespace | None = None, + ) -> None: + """Apply a `typevars_map` to the annotation. + + This method is used when analyzing parametrized generic types to replace typevars with their concrete types. + + This method applies the `typevars_map` to the annotation in place. + + Args: + typevars_map: A dictionary mapping type variables to their concrete types. + globalns: The globals namespace to use during type annotation evaluation. + localns: The locals namespace to use during type annotation evaluation. + + See Also: + pydantic._internal._generics.replace_types is used for replacing the typevars with + their concrete types. + """ + annotation = _generics.replace_types(self.annotation, typevars_map) + annotation, evaluated = _typing_extra.try_eval_type(annotation, globalns, localns) + self.annotation = annotation + if not evaluated: + self._complete = False + self._original_annotation = self.annotation + + def asdict(self) -> _FieldInfoAsDict: + """Return a dictionary representation of the `FieldInfo` instance. + + The returned value is a dictionary with three items: + + * `annotation`: The type annotation of the field. + * `metadata`: The metadata list. + * `attributes`: A mapping of the remaining `FieldInfo` attributes to their values (e.g. `alias`, `title`). + """ + return { + 'annotation': self.annotation, + 'metadata': self.metadata, + 'attributes': {attr: getattr(self, attr) for attr in _Attrs}, + } + + def _copy(self) -> Self: + """Return a copy of the `FieldInfo` instance.""" + # Note: we can't define a custom `__copy__()`, as `FieldInfo` is being subclassed + # by some third-party libraries with extra attributes defined (and as `FieldInfo` + # is slotted, we can't make a copy of the `__dict__`). + copied = copy(self) + for attr_name in ('metadata', '_attributes_set', '_qualifiers'): + # Apply "deep-copy" behavior on collections attributes: + value = getattr(copied, attr_name).copy() + setattr(copied, attr_name, value) + + return copied + + def __repr_args__(self) -> ReprArgs: + yield 'annotation', _repr.PlainRepr(_repr.display_as_type(self.annotation)) + yield 'required', self.is_required() + + for s in self.__slots__: + # TODO: properly make use of the protocol (https://rich.readthedocs.io/en/stable/pretty.html#rich-repr-protocol) + # By yielding a three-tuple: + if s in ( + 'annotation', + '_attributes_set', + '_qualifiers', + '_complete', + '_original_assignment', + '_original_annotation', + '_final', + ): + continue + elif s == 'metadata' and not self.metadata: + continue + elif s == 'repr' and self.repr is True: + continue + if s == 'frozen' and self.frozen is False: + continue + if s == 'validation_alias' and self.validation_alias == self.alias: + continue + if s == 'serialization_alias' and self.serialization_alias == self.alias: + continue + if s == 'default' and self.default is not PydanticUndefined: + yield 'default', self.default + elif s == 'default_factory' and self.default_factory is not None: + yield 'default_factory', _repr.PlainRepr(_repr.display_as_type(self.default_factory)) + else: + value = getattr(self, s) + if value is not None and value is not PydanticUndefined: + yield s, value + + +class _EmptyKwargs(TypedDict): + """This class exists solely to ensure that type checking warns about passing `**extra` in `Field`.""" + + +_Attrs = { + 'default': ..., + 'default_factory': None, + 'alias': None, + 'alias_priority': None, + 'validation_alias': None, + 'serialization_alias': None, + 'title': None, + 'field_title_generator': None, + 'description': None, + 'examples': None, + 'exclude': None, + 'exclude_if': None, + 'discriminator': None, + 'deprecated': None, + 'json_schema_extra': None, + 'frozen': None, + 'validate_default': None, + 'repr': True, + 'init': None, + 'init_var': None, + 'kw_only': None, +} + +_DefaultValues = { + **_Attrs, + 'kw_only': None, + 'pattern': None, + 'strict': None, + 'gt': None, + 'ge': None, + 'lt': None, + 'le': None, + 'multiple_of': None, + 'allow_inf_nan': None, + 'max_digits': None, + 'decimal_places': None, + 'min_length': None, + 'max_length': None, + 'coerce_numbers_to_str': None, +} + + +_T = TypeVar('_T') + + +# NOTE: Actual return type is 'FieldInfo', but we want to help type checkers +# to understand the magic that happens at runtime with the following overloads: +@overload # type hint the return value as `Any` to avoid type checking regressions when using `...`. +def Field( + default: ellipsis, # noqa: F821 # TODO: use `_typing_extra.EllipsisType` when we drop Py3.9 + *, + alias: str | None = _Unset, + alias_priority: int | None = _Unset, + validation_alias: str | AliasPath | AliasChoices | None = _Unset, + serialization_alias: str | None = _Unset, + title: str | None = _Unset, + field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset, + description: str | None = _Unset, + examples: list[Any] | None = _Unset, + exclude: bool | None = _Unset, + exclude_if: Callable[[Any], bool] | None = _Unset, + discriminator: str | types.Discriminator | None = _Unset, + deprecated: Deprecated | str | bool | None = _Unset, + json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset, + frozen: bool | None = _Unset, + validate_default: bool | None = _Unset, + repr: bool = _Unset, + init: bool | None = _Unset, + init_var: bool | None = _Unset, + kw_only: bool | None = _Unset, + pattern: str | re.Pattern[str] | None = _Unset, + strict: bool | None = _Unset, + coerce_numbers_to_str: bool | None = _Unset, + gt: annotated_types.SupportsGt | None = _Unset, + ge: annotated_types.SupportsGe | None = _Unset, + lt: annotated_types.SupportsLt | None = _Unset, + le: annotated_types.SupportsLe | None = _Unset, + multiple_of: float | None = _Unset, + allow_inf_nan: bool | None = _Unset, + max_digits: int | None = _Unset, + decimal_places: int | None = _Unset, + min_length: int | None = _Unset, + max_length: int | None = _Unset, + union_mode: Literal['smart', 'left_to_right'] = _Unset, + fail_fast: bool | None = _Unset, + **extra: Unpack[_EmptyKwargs], +) -> Any: ... +@overload # `default` argument set, validate_default=True (no type checking on the default value) +def Field( + default: Any, + *, + alias: str | None = _Unset, + alias_priority: int | None = _Unset, + validation_alias: str | AliasPath | AliasChoices | None = _Unset, + serialization_alias: str | None = _Unset, + title: str | None = _Unset, + field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset, + description: str | None = _Unset, + examples: list[Any] | None = _Unset, + exclude: bool | None = _Unset, + exclude_if: Callable[[Any], bool] | None = _Unset, + discriminator: str | types.Discriminator | None = _Unset, + deprecated: Deprecated | str | bool | None = _Unset, + json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset, + frozen: bool | None = _Unset, + validate_default: Literal[True], + repr: bool = _Unset, + init: bool | None = _Unset, + init_var: bool | None = _Unset, + kw_only: bool | None = _Unset, + pattern: str | re.Pattern[str] | None = _Unset, + strict: bool | None = _Unset, + coerce_numbers_to_str: bool | None = _Unset, + gt: annotated_types.SupportsGt | None = _Unset, + ge: annotated_types.SupportsGe | None = _Unset, + lt: annotated_types.SupportsLt | None = _Unset, + le: annotated_types.SupportsLe | None = _Unset, + multiple_of: float | None = _Unset, + allow_inf_nan: bool | None = _Unset, + max_digits: int | None = _Unset, + decimal_places: int | None = _Unset, + min_length: int | None = _Unset, + max_length: int | None = _Unset, + union_mode: Literal['smart', 'left_to_right'] = _Unset, + fail_fast: bool | None = _Unset, + **extra: Unpack[_EmptyKwargs], +) -> Any: ... +@overload # `default` argument set, validate_default=False or unset +def Field( + default: _T, + *, + alias: str | None = _Unset, + alias_priority: int | None = _Unset, + validation_alias: str | AliasPath | AliasChoices | None = _Unset, + serialization_alias: str | None = _Unset, + title: str | None = _Unset, + field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset, + description: str | None = _Unset, + examples: list[Any] | None = _Unset, + exclude: bool | None = _Unset, + # NOTE: to get proper type checking on `exclude_if`'s argument, we could use `_T` instead of `Any`. However, + # this requires (at least for pyright) adding an additional overload where `exclude_if` is required (otherwise + # `a: int = Field(default_factory=str)` results in a false negative). + exclude_if: Callable[[Any], bool] | None = _Unset, + discriminator: str | types.Discriminator | None = _Unset, + deprecated: Deprecated | str | bool | None = _Unset, + json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset, + frozen: bool | None = _Unset, + validate_default: Literal[False] = ..., + repr: bool = _Unset, + init: bool | None = _Unset, + init_var: bool | None = _Unset, + kw_only: bool | None = _Unset, + pattern: str | re.Pattern[str] | None = _Unset, + strict: bool | None = _Unset, + coerce_numbers_to_str: bool | None = _Unset, + gt: annotated_types.SupportsGt | None = _Unset, + ge: annotated_types.SupportsGe | None = _Unset, + lt: annotated_types.SupportsLt | None = _Unset, + le: annotated_types.SupportsLe | None = _Unset, + multiple_of: float | None = _Unset, + allow_inf_nan: bool | None = _Unset, + max_digits: int | None = _Unset, + decimal_places: int | None = _Unset, + min_length: int | None = _Unset, + max_length: int | None = _Unset, + union_mode: Literal['smart', 'left_to_right'] = _Unset, + fail_fast: bool | None = _Unset, + **extra: Unpack[_EmptyKwargs], +) -> _T: ... +@overload # `default_factory` argument set, validate_default=True (no type checking on the default value) +def Field( # pyright: ignore[reportOverlappingOverload] + *, + default_factory: Callable[[], Any] | Callable[[dict[str, Any]], Any], + alias: str | None = _Unset, + alias_priority: int | None = _Unset, + validation_alias: str | AliasPath | AliasChoices | None = _Unset, + serialization_alias: str | None = _Unset, + title: str | None = _Unset, + field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset, + description: str | None = _Unset, + examples: list[Any] | None = _Unset, + exclude: bool | None = _Unset, + exclude_if: Callable[[Any], bool] | None = _Unset, + discriminator: str | types.Discriminator | None = _Unset, + deprecated: Deprecated | str | bool | None = _Unset, + json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset, + frozen: bool | None = _Unset, + validate_default: Literal[True], + repr: bool = _Unset, + init: bool | None = _Unset, + init_var: bool | None = _Unset, + kw_only: bool | None = _Unset, + pattern: str | re.Pattern[str] | None = _Unset, + strict: bool | None = _Unset, + coerce_numbers_to_str: bool | None = _Unset, + gt: annotated_types.SupportsGt | None = _Unset, + ge: annotated_types.SupportsGe | None = _Unset, + lt: annotated_types.SupportsLt | None = _Unset, + le: annotated_types.SupportsLe | None = _Unset, + multiple_of: float | None = _Unset, + allow_inf_nan: bool | None = _Unset, + max_digits: int | None = _Unset, + decimal_places: int | None = _Unset, + min_length: int | None = _Unset, + max_length: int | None = _Unset, + union_mode: Literal['smart', 'left_to_right'] = _Unset, + fail_fast: bool | None = _Unset, + **extra: Unpack[_EmptyKwargs], +) -> Any: ... +@overload # `default_factory` argument set, validate_default=False or unset +def Field( + *, + default_factory: Callable[[], _T] | Callable[[dict[str, Any]], _T], + alias: str | None = _Unset, + alias_priority: int | None = _Unset, + validation_alias: str | AliasPath | AliasChoices | None = _Unset, + serialization_alias: str | None = _Unset, + title: str | None = _Unset, + field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset, + description: str | None = _Unset, + examples: list[Any] | None = _Unset, + exclude: bool | None = _Unset, + # NOTE: to get proper type checking on `exclude_if`'s argument, we could use `_T` instead of `Any`. However, + # this requires (at least for pyright) adding an additional overload where `exclude_if` is required (otherwise + # `a: int = Field(default_factory=str)` results in a false negative). + exclude_if: Callable[[Any], bool] | None = _Unset, + discriminator: str | types.Discriminator | None = _Unset, + deprecated: Deprecated | str | bool | None = _Unset, + json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset, + frozen: bool | None = _Unset, + validate_default: Literal[False] | None = _Unset, + repr: bool = _Unset, + init: bool | None = _Unset, + init_var: bool | None = _Unset, + kw_only: bool | None = _Unset, + pattern: str | re.Pattern[str] | None = _Unset, + strict: bool | None = _Unset, + coerce_numbers_to_str: bool | None = _Unset, + gt: annotated_types.SupportsGt | None = _Unset, + ge: annotated_types.SupportsGe | None = _Unset, + lt: annotated_types.SupportsLt | None = _Unset, + le: annotated_types.SupportsLe | None = _Unset, + multiple_of: float | None = _Unset, + allow_inf_nan: bool | None = _Unset, + max_digits: int | None = _Unset, + decimal_places: int | None = _Unset, + min_length: int | None = _Unset, + max_length: int | None = _Unset, + union_mode: Literal['smart', 'left_to_right'] = _Unset, + fail_fast: bool | None = _Unset, + **extra: Unpack[_EmptyKwargs], +) -> _T: ... +@overload +def Field( # No default set + *, + alias: str | None = _Unset, + alias_priority: int | None = _Unset, + validation_alias: str | AliasPath | AliasChoices | None = _Unset, + serialization_alias: str | None = _Unset, + title: str | None = _Unset, + field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset, + description: str | None = _Unset, + examples: list[Any] | None = _Unset, + exclude: bool | None = _Unset, + exclude_if: Callable[[Any], bool] | None = _Unset, + discriminator: str | types.Discriminator | None = _Unset, + deprecated: Deprecated | str | bool | None = _Unset, + json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset, + frozen: bool | None = _Unset, + validate_default: bool | None = _Unset, + repr: bool = _Unset, + init: bool | None = _Unset, + init_var: bool | None = _Unset, + kw_only: bool | None = _Unset, + pattern: str | re.Pattern[str] | None = _Unset, + strict: bool | None = _Unset, + coerce_numbers_to_str: bool | None = _Unset, + gt: annotated_types.SupportsGt | None = _Unset, + ge: annotated_types.SupportsGe | None = _Unset, + lt: annotated_types.SupportsLt | None = _Unset, + le: annotated_types.SupportsLe | None = _Unset, + multiple_of: float | None = _Unset, + allow_inf_nan: bool | None = _Unset, + max_digits: int | None = _Unset, + decimal_places: int | None = _Unset, + min_length: int | None = _Unset, + max_length: int | None = _Unset, + union_mode: Literal['smart', 'left_to_right'] = _Unset, + fail_fast: bool | None = _Unset, + **extra: Unpack[_EmptyKwargs], +) -> Any: ... +def Field( # noqa: C901 + default: Any = PydanticUndefined, + *, + default_factory: Callable[[], Any] | Callable[[dict[str, Any]], Any] | None = _Unset, + alias: str | None = _Unset, + alias_priority: int | None = _Unset, + validation_alias: str | AliasPath | AliasChoices | None = _Unset, + serialization_alias: str | None = _Unset, + title: str | None = _Unset, + field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset, + description: str | None = _Unset, + examples: list[Any] | None = _Unset, + exclude: bool | None = _Unset, + exclude_if: Callable[[Any], bool] | None = _Unset, + discriminator: str | types.Discriminator | None = _Unset, + deprecated: Deprecated | str | bool | None = _Unset, + json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset, + frozen: bool | None = _Unset, + validate_default: bool | None = _Unset, + repr: bool = _Unset, + init: bool | None = _Unset, + init_var: bool | None = _Unset, + kw_only: bool | None = _Unset, + pattern: str | re.Pattern[str] | None = _Unset, + strict: bool | None = _Unset, + coerce_numbers_to_str: bool | None = _Unset, + gt: annotated_types.SupportsGt | None = _Unset, + ge: annotated_types.SupportsGe | None = _Unset, + lt: annotated_types.SupportsLt | None = _Unset, + le: annotated_types.SupportsLe | None = _Unset, + multiple_of: float | None = _Unset, + allow_inf_nan: bool | None = _Unset, + max_digits: int | None = _Unset, + decimal_places: int | None = _Unset, + min_length: int | None = _Unset, + max_length: int | None = _Unset, + union_mode: Literal['smart', 'left_to_right'] = _Unset, + fail_fast: bool | None = _Unset, + **extra: Unpack[_EmptyKwargs], +) -> Any: + """!!! abstract "Usage Documentation" + [Fields](../concepts/fields.md) + + Create a field for objects that can be configured. + + Used to provide extra information about a field, either for the model schema or complex validation. Some arguments + apply only to number fields (`int`, `float`, `Decimal`) and some apply only to `str`. + + Note: + - Any `_Unset` objects will be replaced by the corresponding value defined in the `_DefaultValues` dictionary. If a key for the `_Unset` object is not found in the `_DefaultValues` dictionary, it will default to `None` + + Args: + default: Default value if the field is not set. + default_factory: A callable to generate the default value. The callable can either take 0 arguments + (in which case it is called as is) or a single argument containing the already validated data. + alias: The name to use for the attribute when validating or serializing by alias. + This is often used for things like converting between snake and camel case. + alias_priority: Priority of the alias. This affects whether an alias generator is used. + validation_alias: Like `alias`, but only affects validation, not serialization. + serialization_alias: Like `alias`, but only affects serialization, not validation. + title: Human-readable title. + field_title_generator: A callable that takes a field name and returns title for it. + description: Human-readable description. + examples: Example values for this field. + exclude: Whether to exclude the field from the model serialization. + exclude_if: A callable that determines whether to exclude a field during serialization based on its value. + discriminator: Field name or Discriminator for discriminating the type in a tagged union. + deprecated: A deprecation message, an instance of `warnings.deprecated` or the `typing_extensions.deprecated` backport, + or a boolean. If `True`, a default deprecation message will be emitted when accessing the field. + json_schema_extra: A dict or callable to provide extra JSON schema properties. + frozen: Whether the field is frozen. If true, attempts to change the value on an instance will raise an error. + validate_default: If `True`, apply validation to the default value every time you create an instance. + Otherwise, for performance reasons, the default value of the field is trusted and not validated. + repr: A boolean indicating whether to include the field in the `__repr__` output. + init: Whether the field should be included in the constructor of the dataclass. + (Only applies to dataclasses.) + init_var: Whether the field should _only_ be included in the constructor of the dataclass. + (Only applies to dataclasses.) + kw_only: Whether the field should be a keyword-only argument in the constructor of the dataclass. + (Only applies to dataclasses.) + coerce_numbers_to_str: Whether to enable coercion of any `Number` type to `str` (not applicable in `strict` mode). + strict: If `True`, strict validation is applied to the field. + See [Strict Mode](../concepts/strict_mode.md) for details. + gt: Greater than. If set, value must be greater than this. Only applicable to numbers. + ge: Greater than or equal. If set, value must be greater than or equal to this. Only applicable to numbers. + lt: Less than. If set, value must be less than this. Only applicable to numbers. + le: Less than or equal. If set, value must be less than or equal to this. Only applicable to numbers. + multiple_of: Value must be a multiple of this. Only applicable to numbers. + min_length: Minimum length for iterables. + max_length: Maximum length for iterables. + pattern: Pattern for strings (a regular expression). + allow_inf_nan: Allow `inf`, `-inf`, `nan`. Only applicable to float and [`Decimal`][decimal.Decimal] numbers. + max_digits: Maximum number of allow digits for strings. + decimal_places: Maximum number of decimal places allowed for numbers. + union_mode: The strategy to apply when validating a union. Can be `smart` (the default), or `left_to_right`. + See [Union Mode](../concepts/unions.md#union-modes) for details. + fail_fast: If `True`, validation will stop on the first error. If `False`, all validation errors will be collected. + This option can be applied only to iterable types (list, tuple, set, and frozenset). + extra: (Deprecated) Extra fields that will be included in the JSON schema. + + !!! warning Deprecated + The `extra` kwargs is deprecated. Use `json_schema_extra` instead. + + Returns: + A new [`FieldInfo`][pydantic.fields.FieldInfo]. The return annotation is `Any` so `Field` can be used on + type-annotated fields without causing a type error. + """ + # Check deprecated and removed params from V1. This logic should eventually be removed. + const = extra.pop('const', None) # type: ignore + if const is not None: + raise PydanticUserError('`const` is removed, use `Literal` instead', code='removed-kwargs') + + min_items = extra.pop('min_items', None) # type: ignore + if min_items is not None: + warn( + '`min_items` is deprecated and will be removed, use `min_length` instead', + PydanticDeprecatedSince20, + stacklevel=2, + ) + if min_length in (None, _Unset): + min_length = min_items # type: ignore + + max_items = extra.pop('max_items', None) # type: ignore + if max_items is not None: + warn( + '`max_items` is deprecated and will be removed, use `max_length` instead', + PydanticDeprecatedSince20, + stacklevel=2, + ) + if max_length in (None, _Unset): + max_length = max_items # type: ignore + + unique_items = extra.pop('unique_items', None) # type: ignore + if unique_items is not None: + raise PydanticUserError( + ( + '`unique_items` is removed, use `Set` instead' + '(this feature is discussed in https://github.com/pydantic/pydantic-core/issues/296)' + ), + code='removed-kwargs', + ) + + allow_mutation = extra.pop('allow_mutation', None) # type: ignore + if allow_mutation is not None: + warn( + '`allow_mutation` is deprecated and will be removed. use `frozen` instead', + PydanticDeprecatedSince20, + stacklevel=2, + ) + if allow_mutation is False: + frozen = True + + regex = extra.pop('regex', None) # type: ignore + if regex is not None: + raise PydanticUserError('`regex` is removed. use `pattern` instead', code='removed-kwargs') + + if extra: + warn( + 'Using extra keyword arguments on `Field` is deprecated and will be removed.' + ' Use `json_schema_extra` instead.' + f' (Extra keys: {", ".join(k.__repr__() for k in extra.keys())})', + PydanticDeprecatedSince20, + stacklevel=2, + ) + if not json_schema_extra or json_schema_extra is _Unset: + json_schema_extra = extra # type: ignore + + if ( + validation_alias + and validation_alias is not _Unset + and not isinstance(validation_alias, (str, AliasChoices, AliasPath)) + ): + raise TypeError('Invalid `validation_alias` type. it should be `str`, `AliasChoices`, or `AliasPath`') + + if serialization_alias in (_Unset, None) and isinstance(alias, str): + serialization_alias = alias + + if validation_alias in (_Unset, None): + validation_alias = alias + + include = extra.pop('include', None) # type: ignore + if include is not None: + warn( + '`include` is deprecated and does nothing. It will be removed, use `exclude` instead', + PydanticDeprecatedSince20, + stacklevel=2, + ) + + return FieldInfo.from_field( + default, + default_factory=default_factory, + alias=alias, + alias_priority=alias_priority, + validation_alias=validation_alias, + serialization_alias=serialization_alias, + title=title, + field_title_generator=field_title_generator, + description=description, + examples=examples, + exclude=exclude, + exclude_if=exclude_if, + discriminator=discriminator, + deprecated=deprecated, + json_schema_extra=json_schema_extra, + frozen=frozen, + pattern=pattern, + validate_default=validate_default, + repr=repr, + init=init, + init_var=init_var, + kw_only=kw_only, + coerce_numbers_to_str=coerce_numbers_to_str, + strict=strict, + gt=gt, + ge=ge, + lt=lt, + le=le, + multiple_of=multiple_of, + min_length=min_length, + max_length=max_length, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, + union_mode=union_mode, + fail_fast=fail_fast, + ) + + +_FIELD_ARG_NAMES = set(inspect.signature(Field).parameters) +_FIELD_ARG_NAMES.remove('extra') # do not include the varkwargs parameter + + +class ModelPrivateAttr(_repr.Representation): + """A descriptor for private attributes in class models. + + !!! warning + You generally shouldn't be creating `ModelPrivateAttr` instances directly, instead use + `pydantic.fields.PrivateAttr`. (This is similar to `FieldInfo` vs. `Field`.) + + Attributes: + default: The default value of the attribute if not provided. + default_factory: A callable function that generates the default value of the + attribute if not provided. + """ + + __slots__ = ('default', 'default_factory') + + def __init__(self, default: Any = PydanticUndefined, *, default_factory: Callable[[], Any] | None = None) -> None: + if default is Ellipsis: + self.default = PydanticUndefined + else: + self.default = default + self.default_factory = default_factory + + if not TYPE_CHECKING: + # We put `__getattr__` in a non-TYPE_CHECKING block because otherwise, mypy allows arbitrary attribute access + + def __getattr__(self, item: str) -> Any: + """This function improves compatibility with custom descriptors by ensuring delegation happens + as expected when the default value of a private attribute is a descriptor. + """ + if item in {'__get__', '__set__', '__delete__'}: + if hasattr(self.default, item): + return getattr(self.default, item) + raise AttributeError(f'{type(self).__name__!r} object has no attribute {item!r}') + + def __set_name__(self, cls: type[Any], name: str) -> None: + """Preserve `__set_name__` protocol defined in https://peps.python.org/pep-0487.""" + default = self.default + if default is PydanticUndefined: + return + set_name = getattr(default, '__set_name__', None) + if callable(set_name): + set_name(cls, name) + + def get_default(self) -> Any: + """Retrieve the default value of the object. + + If `self.default_factory` is `None`, the method will return a deep copy of the `self.default` object. + + If `self.default_factory` is not `None`, it will call `self.default_factory` and return the value returned. + + Returns: + The default value of the object. + """ + return _utils.smart_deepcopy(self.default) if self.default_factory is None else self.default_factory() + + def __eq__(self, other: Any) -> bool: + return isinstance(other, self.__class__) and (self.default, self.default_factory) == ( + other.default, + other.default_factory, + ) + + +# NOTE: Actual return type is 'ModelPrivateAttr', but we want to help type checkers +# to understand the magic that happens at runtime. +@overload # `default` argument set +def PrivateAttr( + default: _T, + *, + init: Literal[False] = False, +) -> _T: ... +@overload # `default_factory` argument set +def PrivateAttr( + *, + default_factory: Callable[[], _T], + init: Literal[False] = False, +) -> _T: ... +@overload # No default set +def PrivateAttr( + *, + init: Literal[False] = False, +) -> Any: ... +def PrivateAttr( + default: Any = PydanticUndefined, + *, + default_factory: Callable[[], Any] | None = None, + init: Literal[False] = False, +) -> Any: + """!!! abstract "Usage Documentation" + [Private Model Attributes](../concepts/models.md#private-model-attributes) + + Indicates that an attribute is intended for private use and not handled during normal validation/serialization. + + Private attributes are not validated by Pydantic, so it's up to you to ensure they are used in a type-safe manner. + + Private attributes are stored in `__private_attributes__` on the model. + + Args: + default: The attribute's default value. Defaults to Undefined. + default_factory: Callable that will be + called when a default value is needed for this attribute. + If both `default` and `default_factory` are set, an error will be raised. + init: Whether the attribute should be included in the constructor of the dataclass. Always `False`. + + Returns: + An instance of [`ModelPrivateAttr`][pydantic.fields.ModelPrivateAttr] class. + + Raises: + ValueError: If both `default` and `default_factory` are set. + """ + if default is not PydanticUndefined and default_factory is not None: + raise TypeError('cannot specify both default and default_factory') + + return ModelPrivateAttr( + default, + default_factory=default_factory, + ) + + +@dataclasses.dataclass(**_internal_dataclass.slots_true) +class ComputedFieldInfo: + """A container for data from `@computed_field` so that we can access it while building the pydantic-core schema. + + Attributes: + decorator_repr: A class variable representing the decorator string, '@computed_field'. + wrapped_property: The wrapped computed field property. + return_type: The type of the computed field property's return value. + alias: The alias of the property to be used during serialization. + alias_priority: The priority of the alias. This affects whether an alias generator is used. + title: Title of the computed field to include in the serialization JSON schema. + field_title_generator: A callable that takes a field name and returns title for it. + description: Description of the computed field to include in the serialization JSON schema. + deprecated: A deprecation message, an instance of `warnings.deprecated` or the `typing_extensions.deprecated` backport, + or a boolean. If `True`, a default deprecation message will be emitted when accessing the field. + examples: Example values of the computed field to include in the serialization JSON schema. + json_schema_extra: A dict or callable to provide extra JSON schema properties. + repr: A boolean indicating whether to include the field in the __repr__ output. + """ + + decorator_repr: ClassVar[str] = '@computed_field' + wrapped_property: property + return_type: Any + alias: str | None + alias_priority: int | None + title: str | None + field_title_generator: Callable[[str, ComputedFieldInfo], str] | None + description: str | None + deprecated: Deprecated | str | bool | None + examples: list[Any] | None + json_schema_extra: JsonDict | Callable[[JsonDict], None] | None + repr: bool + + @property + def deprecation_message(self) -> str | None: + """The deprecation message to be emitted, or `None` if not set.""" + if self.deprecated is None: + return None + if isinstance(self.deprecated, bool): + return 'deprecated' if self.deprecated else None + return self.deprecated if isinstance(self.deprecated, str) else self.deprecated.message + + def _update_from_config(self, config_wrapper: ConfigWrapper, name: str) -> None: + """Update the instance from the configuration set on the class this computed field belongs to.""" + title_generator = self.field_title_generator or config_wrapper.field_title_generator + if title_generator is not None and self.title is None: + self.title = title_generator(name, self) + if config_wrapper.alias_generator is not None: + self._apply_alias_generator(config_wrapper.alias_generator, name) + + def _apply_alias_generator(self, alias_generator: Callable[[str], str] | AliasGenerator, name: str) -> None: + """Apply an alias generator to aliases if appropriate. + + Args: + alias_generator: A callable that takes a string and returns a string, or an `AliasGenerator` instance. + name: The name of the computed field from which to generate the alias. + """ + # Apply an alias_generator if + # 1. An alias is not specified + # 2. An alias is specified, but the priority is <= 1 + + if self.alias_priority is None or self.alias_priority <= 1 or self.alias is None: + alias, _, serialization_alias = None, None, None + + if isinstance(alias_generator, AliasGenerator): + alias, _, serialization_alias = alias_generator.generate_aliases(name) + elif callable(alias_generator): + alias = alias_generator(name) + + # if priority is not set, we set to 1 + # which supports the case where the alias_generator from a child class is used + # to generate an alias for a field in a parent class + if self.alias_priority is None or self.alias_priority <= 1: + self.alias_priority = 1 + + # if the priority is 1, then we set the aliases to the generated alias + # note that we use the serialization_alias with priority over alias, as computed_field + # aliases are used for serialization only (not validation) + if self.alias_priority == 1: + self.alias = _utils.get_first_not_none(serialization_alias, alias) + + +def _wrapped_property_is_private(property_: cached_property | property) -> bool: # type: ignore + """Returns true if provided property is private, False otherwise.""" + wrapped_name: str = '' + + if isinstance(property_, property): + wrapped_name = getattr(property_.fget, '__name__', '') + elif isinstance(property_, cached_property): # type: ignore + wrapped_name = getattr(property_.func, '__name__', '') # type: ignore + + return wrapped_name.startswith('_') and not wrapped_name.startswith('__') + + +# this should really be `property[T], cached_property[T]` but property is not generic unlike cached_property +# See https://github.com/python/typing/issues/985 and linked issues +PropertyT = TypeVar('PropertyT') + + +@overload +def computed_field(func: PropertyT, /) -> PropertyT: ... + + +@overload +def computed_field( + *, + alias: str | None = None, + alias_priority: int | None = None, + title: str | None = None, + field_title_generator: Callable[[str, ComputedFieldInfo], str] | None = None, + description: str | None = None, + deprecated: Deprecated | str | bool | None = None, + examples: list[Any] | None = None, + json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = None, + repr: bool = True, + return_type: Any = PydanticUndefined, +) -> Callable[[PropertyT], PropertyT]: ... + + +def computed_field( + func: PropertyT | None = None, + /, + *, + alias: str | None = None, + alias_priority: int | None = None, + title: str | None = None, + field_title_generator: Callable[[str, ComputedFieldInfo], str] | None = None, + description: str | None = None, + deprecated: Deprecated | str | bool | None = None, + examples: list[Any] | None = None, + json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = None, + repr: bool | None = None, + return_type: Any = PydanticUndefined, +) -> PropertyT | Callable[[PropertyT], PropertyT]: + """!!! abstract "Usage Documentation" + [The `computed_field` decorator](../concepts/fields.md#the-computed_field-decorator) + + Decorator to include `property` and `cached_property` when serializing models or dataclasses. + + This is useful for fields that are computed from other fields, or for fields that are expensive to compute and should be cached. + + ```python + from pydantic import BaseModel, computed_field + + class Rectangle(BaseModel): + width: int + length: int + + @computed_field + @property + def area(self) -> int: + return self.width * self.length + + print(Rectangle(width=3, length=2).model_dump()) + #> {'width': 3, 'length': 2, 'area': 6} + ``` + + If applied to functions not yet decorated with `@property` or `@cached_property`, the function is + automatically wrapped with `property`. Although this is more concise, you will lose IntelliSense in your IDE, + and confuse static type checkers, thus explicit use of `@property` is recommended. + + !!! warning "Mypy Warning" + Even with the `@property` or `@cached_property` applied to your function before `@computed_field`, + mypy may throw a `Decorated property not supported` error. + See [mypy issue #1362](https://github.com/python/mypy/issues/1362), for more information. + To avoid this error message, add `# type: ignore[prop-decorator]` to the `@computed_field` line. + + [pyright](https://github.com/microsoft/pyright) supports `@computed_field` without error. + + ```python + import random + + from pydantic import BaseModel, computed_field + + class Square(BaseModel): + width: float + + @computed_field + def area(self) -> float: # converted to a `property` by `computed_field` + return round(self.width**2, 2) + + @area.setter + def area(self, new_area: float) -> None: + self.width = new_area**0.5 + + @computed_field(alias='the magic number', repr=False) + def random_number(self) -> int: + return random.randint(0, 1_000) + + square = Square(width=1.3) + + # `random_number` does not appear in representation + print(repr(square)) + #> Square(width=1.3, area=1.69) + + print(square.random_number) + #> 3 + + square.area = 4 + + print(square.model_dump_json(by_alias=True)) + #> {"width":2.0,"area":4.0,"the magic number":3} + ``` + + !!! warning "Overriding with `computed_field`" + You can't override a field from a parent class with a `computed_field` in the child class. + `mypy` complains about this behavior if allowed, and `dataclasses` doesn't allow this pattern either. + See the example below: + + ```python + from pydantic import BaseModel, computed_field + + class Parent(BaseModel): + a: str + + try: + + class Child(Parent): + @computed_field + @property + def a(self) -> str: + return 'new a' + + except TypeError as e: + print(e) + ''' + Field 'a' of class 'Child' overrides symbol of same name in a parent class. This override with a computed_field is incompatible. + ''' + ``` + + Private properties decorated with `@computed_field` have `repr=False` by default. + + ```python + from functools import cached_property + + from pydantic import BaseModel, computed_field + + class Model(BaseModel): + foo: int + + @computed_field + @cached_property + def _private_cached_property(self) -> int: + return -self.foo + + @computed_field + @property + def _private_property(self) -> int: + return -self.foo + + m = Model(foo=1) + print(repr(m)) + #> Model(foo=1) + ``` + + Args: + func: the function to wrap. + alias: alias to use when serializing this computed field, only used when `by_alias=True` + alias_priority: priority of the alias. This affects whether an alias generator is used + title: Title to use when including this computed field in JSON Schema + field_title_generator: A callable that takes a field name and returns title for it. + description: Description to use when including this computed field in JSON Schema, defaults to the function's + docstring + deprecated: A deprecation message (or an instance of `warnings.deprecated` or the `typing_extensions.deprecated` backport). + to be emitted when accessing the field. Or a boolean. This will automatically be set if the property is decorated with the + `deprecated` decorator. + examples: Example values to use when including this computed field in JSON Schema + json_schema_extra: A dict or callable to provide extra JSON schema properties. + repr: whether to include this computed field in model repr. + Default is `False` for private properties and `True` for public properties. + return_type: optional return for serialization logic to expect when serializing to JSON, if included + this must be correct, otherwise a `TypeError` is raised. + If you don't include a return type Any is used, which does runtime introspection to handle arbitrary + objects. + + Returns: + A proxy wrapper for the property. + """ + + def dec(f: Any) -> Any: + nonlocal description, deprecated, return_type, alias_priority + unwrapped = _decorators.unwrap_wrapped_function(f) + + if description is None and unwrapped.__doc__: + description = inspect.cleandoc(unwrapped.__doc__) + + if deprecated is None and hasattr(unwrapped, '__deprecated__'): + deprecated = unwrapped.__deprecated__ + + # if the function isn't already decorated with `@property` (or another descriptor), then we wrap it now + f = _decorators.ensure_property(f) + alias_priority = (alias_priority or 2) if alias is not None else None + + if repr is None: + repr_: bool = not _wrapped_property_is_private(property_=f) + else: + repr_ = repr + + dec_info = ComputedFieldInfo( + f, + return_type, + alias, + alias_priority, + title, + field_title_generator, + description, + deprecated, + examples, + json_schema_extra, + repr_, + ) + return _decorators.PydanticDescriptorProxy(f, dec_info) + + if func is None: + return dec + else: + return dec(func) diff --git a/backend/.venv/Lib/site-packages/pydantic/functional_serializers.py b/backend/.venv/Lib/site-packages/pydantic/functional_serializers.py new file mode 100644 index 0000000..0c1522f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/functional_serializers.py @@ -0,0 +1,451 @@ +"""This module contains related classes and functions for serialization.""" + +from __future__ import annotations + +import dataclasses +from functools import partial, partialmethod +from typing import TYPE_CHECKING, Annotated, Any, Callable, Literal, TypeVar, overload + +from pydantic_core import PydanticUndefined, core_schema +from pydantic_core.core_schema import SerializationInfo, SerializerFunctionWrapHandler, WhenUsed +from typing_extensions import TypeAlias + +from . import PydanticUndefinedAnnotation +from ._internal import _decorators, _internal_dataclass +from .annotated_handlers import GetCoreSchemaHandler + + +@dataclasses.dataclass(**_internal_dataclass.slots_true, frozen=True) +class PlainSerializer: + """Plain serializers use a function to modify the output of serialization. + + This is particularly helpful when you want to customize the serialization for annotated types. + Consider an input of `list`, which will be serialized into a space-delimited string. + + ```python + from typing import Annotated + + from pydantic import BaseModel, PlainSerializer + + CustomStr = Annotated[ + list, PlainSerializer(lambda x: ' '.join(x), return_type=str) + ] + + class StudentModel(BaseModel): + courses: CustomStr + + student = StudentModel(courses=['Math', 'Chemistry', 'English']) + print(student.model_dump()) + #> {'courses': 'Math Chemistry English'} + ``` + + Attributes: + func: The serializer function. + return_type: The return type for the function. If omitted it will be inferred from the type annotation. + when_used: Determines when this serializer should be used. Accepts a string with values `'always'`, + `'unless-none'`, `'json'`, and `'json-unless-none'`. Defaults to 'always'. + """ + + func: core_schema.SerializerFunction + return_type: Any = PydanticUndefined + when_used: WhenUsed = 'always' + + def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: + """Gets the Pydantic core schema. + + Args: + source_type: The source type. + handler: The `GetCoreSchemaHandler` instance. + + Returns: + The Pydantic core schema. + """ + schema = handler(source_type) + if self.return_type is not PydanticUndefined: + return_type = self.return_type + else: + try: + # Do not pass in globals as the function could be defined in a different module. + # Instead, let `get_callable_return_type` infer the globals to use, but still pass + # in locals that may contain a parent/rebuild namespace: + return_type = _decorators.get_callable_return_type( + self.func, + localns=handler._get_types_namespace().locals, + ) + except NameError as e: + raise PydanticUndefinedAnnotation.from_name_error(e) from e + + return_schema = None if return_type is PydanticUndefined else handler.generate_schema(return_type) + schema['serialization'] = core_schema.plain_serializer_function_ser_schema( + function=self.func, + info_arg=_decorators.inspect_annotated_serializer(self.func, 'plain'), + return_schema=return_schema, + when_used=self.when_used, + ) + return schema + + +@dataclasses.dataclass(**_internal_dataclass.slots_true, frozen=True) +class WrapSerializer: + """Wrap serializers receive the raw inputs along with a handler function that applies the standard serialization + logic, and can modify the resulting value before returning it as the final output of serialization. + + For example, here's a scenario in which a wrap serializer transforms timezones to UTC **and** utilizes the existing `datetime` serialization logic. + + ```python + from datetime import datetime, timezone + from typing import Annotated, Any + + from pydantic import BaseModel, WrapSerializer + + class EventDatetime(BaseModel): + start: datetime + end: datetime + + def convert_to_utc(value: Any, handler, info) -> dict[str, datetime]: + # Note that `handler` can actually help serialize the `value` for + # further custom serialization in case it's a subclass. + partial_result = handler(value, info) + if info.mode == 'json': + return { + k: datetime.fromisoformat(v).astimezone(timezone.utc) + for k, v in partial_result.items() + } + return {k: v.astimezone(timezone.utc) for k, v in partial_result.items()} + + UTCEventDatetime = Annotated[EventDatetime, WrapSerializer(convert_to_utc)] + + class EventModel(BaseModel): + event_datetime: UTCEventDatetime + + dt = EventDatetime( + start='2024-01-01T07:00:00-08:00', end='2024-01-03T20:00:00+06:00' + ) + event = EventModel(event_datetime=dt) + print(event.model_dump()) + ''' + { + 'event_datetime': { + 'start': datetime.datetime( + 2024, 1, 1, 15, 0, tzinfo=datetime.timezone.utc + ), + 'end': datetime.datetime( + 2024, 1, 3, 14, 0, tzinfo=datetime.timezone.utc + ), + } + } + ''' + + print(event.model_dump_json()) + ''' + {"event_datetime":{"start":"2024-01-01T15:00:00Z","end":"2024-01-03T14:00:00Z"}} + ''' + ``` + + Attributes: + func: The serializer function to be wrapped. + return_type: The return type for the function. If omitted it will be inferred from the type annotation. + when_used: Determines when this serializer should be used. Accepts a string with values `'always'`, + `'unless-none'`, `'json'`, and `'json-unless-none'`. Defaults to 'always'. + """ + + func: core_schema.WrapSerializerFunction + return_type: Any = PydanticUndefined + when_used: WhenUsed = 'always' + + def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: + """This method is used to get the Pydantic core schema of the class. + + Args: + source_type: Source type. + handler: Core schema handler. + + Returns: + The generated core schema of the class. + """ + schema = handler(source_type) + if self.return_type is not PydanticUndefined: + return_type = self.return_type + else: + try: + # Do not pass in globals as the function could be defined in a different module. + # Instead, let `get_callable_return_type` infer the globals to use, but still pass + # in locals that may contain a parent/rebuild namespace: + return_type = _decorators.get_callable_return_type( + self.func, + localns=handler._get_types_namespace().locals, + ) + except NameError as e: + raise PydanticUndefinedAnnotation.from_name_error(e) from e + + return_schema = None if return_type is PydanticUndefined else handler.generate_schema(return_type) + schema['serialization'] = core_schema.wrap_serializer_function_ser_schema( + function=self.func, + info_arg=_decorators.inspect_annotated_serializer(self.func, 'wrap'), + return_schema=return_schema, + when_used=self.when_used, + ) + return schema + + +if TYPE_CHECKING: + _Partial: TypeAlias = 'partial[Any] | partialmethod[Any]' + + FieldPlainSerializer: TypeAlias = 'core_schema.SerializerFunction | _Partial' + """A field serializer method or function in `plain` mode.""" + + FieldWrapSerializer: TypeAlias = 'core_schema.WrapSerializerFunction | _Partial' + """A field serializer method or function in `wrap` mode.""" + + FieldSerializer: TypeAlias = 'FieldPlainSerializer | FieldWrapSerializer' + """A field serializer method or function.""" + + _FieldPlainSerializerT = TypeVar('_FieldPlainSerializerT', bound=FieldPlainSerializer) + _FieldWrapSerializerT = TypeVar('_FieldWrapSerializerT', bound=FieldWrapSerializer) + + +@overload +def field_serializer( + field: str, + /, + *fields: str, + mode: Literal['wrap'], + return_type: Any = ..., + when_used: WhenUsed = ..., + check_fields: bool | None = ..., +) -> Callable[[_FieldWrapSerializerT], _FieldWrapSerializerT]: ... + + +@overload +def field_serializer( + field: str, + /, + *fields: str, + mode: Literal['plain'] = ..., + return_type: Any = ..., + when_used: WhenUsed = ..., + check_fields: bool | None = ..., +) -> Callable[[_FieldPlainSerializerT], _FieldPlainSerializerT]: ... + + +def field_serializer( + *fields: str, + mode: Literal['plain', 'wrap'] = 'plain', + # TODO PEP 747 (grep for 'return_type' on the whole code base): + return_type: Any = PydanticUndefined, + when_used: WhenUsed = 'always', + check_fields: bool | None = None, +) -> ( + Callable[[_FieldWrapSerializerT], _FieldWrapSerializerT] + | Callable[[_FieldPlainSerializerT], _FieldPlainSerializerT] +): + """Decorator that enables custom field serialization. + + In the below example, a field of type `set` is used to mitigate duplication. A `field_serializer` is used to serialize the data as a sorted list. + + ```python + from pydantic import BaseModel, field_serializer + + class StudentModel(BaseModel): + name: str = 'Jane' + courses: set[str] + + @field_serializer('courses', when_used='json') + def serialize_courses_in_order(self, courses: set[str]): + return sorted(courses) + + student = StudentModel(courses={'Math', 'Chemistry', 'English'}) + print(student.model_dump_json()) + #> {"name":"Jane","courses":["Chemistry","English","Math"]} + ``` + + See [the usage documentation](../concepts/serialization.md#serializers) for more information. + + Four signatures are supported: + + - `(self, value: Any, info: FieldSerializationInfo)` + - `(self, value: Any, nxt: SerializerFunctionWrapHandler, info: FieldSerializationInfo)` + - `(value: Any, info: SerializationInfo)` + - `(value: Any, nxt: SerializerFunctionWrapHandler, info: SerializationInfo)` + + Args: + fields: Which field(s) the method should be called on. + mode: The serialization mode. + + - `plain` means the function will be called instead of the default serialization logic, + - `wrap` means the function will be called with an argument to optionally call the + default serialization logic. + return_type: Optional return type for the function, if omitted it will be inferred from the type annotation. + when_used: Determines the serializer will be used for serialization. + check_fields: Whether to check that the fields actually exist on the model. + + Returns: + The decorator function. + """ + + def dec(f: FieldSerializer) -> _decorators.PydanticDescriptorProxy[Any]: + dec_info = _decorators.FieldSerializerDecoratorInfo( + fields=fields, + mode=mode, + return_type=return_type, + when_used=when_used, + check_fields=check_fields, + ) + return _decorators.PydanticDescriptorProxy(f, dec_info) # pyright: ignore[reportArgumentType] + + return dec # pyright: ignore[reportReturnType] + + +if TYPE_CHECKING: + # The first argument in the following callables represent the `self` type: + + ModelPlainSerializerWithInfo: TypeAlias = Callable[[Any, SerializationInfo[Any]], Any] + """A model serializer method with the `info` argument, in `plain` mode.""" + + ModelPlainSerializerWithoutInfo: TypeAlias = Callable[[Any], Any] + """A model serializer method without the `info` argument, in `plain` mode.""" + + ModelPlainSerializer: TypeAlias = 'ModelPlainSerializerWithInfo | ModelPlainSerializerWithoutInfo' + """A model serializer method in `plain` mode.""" + + ModelWrapSerializerWithInfo: TypeAlias = Callable[[Any, SerializerFunctionWrapHandler, SerializationInfo[Any]], Any] + """A model serializer method with the `info` argument, in `wrap` mode.""" + + ModelWrapSerializerWithoutInfo: TypeAlias = Callable[[Any, SerializerFunctionWrapHandler], Any] + """A model serializer method without the `info` argument, in `wrap` mode.""" + + ModelWrapSerializer: TypeAlias = 'ModelWrapSerializerWithInfo | ModelWrapSerializerWithoutInfo' + """A model serializer method in `wrap` mode.""" + + ModelSerializer: TypeAlias = 'ModelPlainSerializer | ModelWrapSerializer' + + _ModelPlainSerializerT = TypeVar('_ModelPlainSerializerT', bound=ModelPlainSerializer) + _ModelWrapSerializerT = TypeVar('_ModelWrapSerializerT', bound=ModelWrapSerializer) + + +@overload +def model_serializer(f: _ModelPlainSerializerT, /) -> _ModelPlainSerializerT: ... + + +@overload +def model_serializer( + *, mode: Literal['wrap'], when_used: WhenUsed = 'always', return_type: Any = ... +) -> Callable[[_ModelWrapSerializerT], _ModelWrapSerializerT]: ... + + +@overload +def model_serializer( + *, + mode: Literal['plain'] = ..., + when_used: WhenUsed = 'always', + return_type: Any = ..., +) -> Callable[[_ModelPlainSerializerT], _ModelPlainSerializerT]: ... + + +def model_serializer( + f: _ModelPlainSerializerT | _ModelWrapSerializerT | None = None, + /, + *, + mode: Literal['plain', 'wrap'] = 'plain', + when_used: WhenUsed = 'always', + return_type: Any = PydanticUndefined, +) -> ( + _ModelPlainSerializerT + | Callable[[_ModelWrapSerializerT], _ModelWrapSerializerT] + | Callable[[_ModelPlainSerializerT], _ModelPlainSerializerT] +): + """Decorator that enables custom model serialization. + + This is useful when a model need to be serialized in a customized manner, allowing for flexibility beyond just specific fields. + + An example would be to serialize temperature to the same temperature scale, such as degrees Celsius. + + ```python + from typing import Literal + + from pydantic import BaseModel, model_serializer + + class TemperatureModel(BaseModel): + unit: Literal['C', 'F'] + value: int + + @model_serializer() + def serialize_model(self): + if self.unit == 'F': + return {'unit': 'C', 'value': int((self.value - 32) / 1.8)} + return {'unit': self.unit, 'value': self.value} + + temperature = TemperatureModel(unit='F', value=212) + print(temperature.model_dump()) + #> {'unit': 'C', 'value': 100} + ``` + + Two signatures are supported for `mode='plain'`, which is the default: + + - `(self)` + - `(self, info: SerializationInfo)` + + And two other signatures for `mode='wrap'`: + + - `(self, nxt: SerializerFunctionWrapHandler)` + - `(self, nxt: SerializerFunctionWrapHandler, info: SerializationInfo)` + + See [the usage documentation](../concepts/serialization.md#serializers) for more information. + + Args: + f: The function to be decorated. + mode: The serialization mode. + + - `'plain'` means the function will be called instead of the default serialization logic + - `'wrap'` means the function will be called with an argument to optionally call the default + serialization logic. + when_used: Determines when this serializer should be used. + return_type: The return type for the function. If omitted it will be inferred from the type annotation. + + Returns: + The decorator function. + """ + + def dec(f: ModelSerializer) -> _decorators.PydanticDescriptorProxy[Any]: + dec_info = _decorators.ModelSerializerDecoratorInfo(mode=mode, return_type=return_type, when_used=when_used) + return _decorators.PydanticDescriptorProxy(f, dec_info) + + if f is None: + return dec # pyright: ignore[reportReturnType] + else: + return dec(f) # pyright: ignore[reportReturnType] + + +AnyType = TypeVar('AnyType') + + +if TYPE_CHECKING: + SerializeAsAny = Annotated[AnyType, ...] # SerializeAsAny[list[str]] will be treated by type checkers as list[str] + """Annotation used to mark a type as having duck-typing serialization behavior. + + See [usage documentation](../concepts/serialization.md#serializing-with-duck-typing) for more details. + """ +else: + + @dataclasses.dataclass(**_internal_dataclass.slots_true) + class SerializeAsAny: + """Annotation used to mark a type as having duck-typing serialization behavior. + + See [usage documentation](../concepts/serialization.md#serializing-with-duck-typing) for more details. + """ + + def __class_getitem__(cls, item: Any) -> Any: + return Annotated[item, SerializeAsAny()] + + def __get_pydantic_core_schema__( + self, source_type: Any, handler: GetCoreSchemaHandler + ) -> core_schema.CoreSchema: + schema = handler(source_type) + schema_to_update = schema + while schema_to_update['type'] == 'definitions': + schema_to_update = schema_to_update.copy() + schema_to_update = schema_to_update['schema'] + schema_to_update['serialization'] = core_schema.simple_ser_schema('any') + return schema + + __hash__ = object.__hash__ diff --git a/backend/.venv/Lib/site-packages/pydantic/functional_validators.py b/backend/.venv/Lib/site-packages/pydantic/functional_validators.py new file mode 100644 index 0000000..fc4bbba --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/functional_validators.py @@ -0,0 +1,893 @@ +"""This module contains related classes and functions for validation.""" + +from __future__ import annotations as _annotations + +import dataclasses +import sys +import warnings +from functools import partialmethod +from types import FunctionType +from typing import TYPE_CHECKING, Annotated, Any, Callable, Literal, TypeVar, Union, cast, overload + +from pydantic_core import PydanticUndefined, core_schema +from typing_extensions import Self, TypeAlias + +from ._internal import _decorators, _generics, _internal_dataclass +from .annotated_handlers import GetCoreSchemaHandler +from .errors import PydanticUserError +from .version import version_short +from .warnings import ArbitraryTypeWarning, PydanticDeprecatedSince212 + +if sys.version_info < (3, 11): + from typing_extensions import Protocol +else: + from typing import Protocol + +_inspect_validator = _decorators.inspect_validator + + +@dataclasses.dataclass(frozen=True, **_internal_dataclass.slots_true) +class AfterValidator: + """!!! abstract "Usage Documentation" + [field *after* validators](../concepts/validators.md#field-after-validator) + + A metadata class that indicates that a validation should be applied **after** the inner validation logic. + + Attributes: + func: The validator function. + + Example: + ```python + from typing import Annotated + + from pydantic import AfterValidator, BaseModel, ValidationError + + MyInt = Annotated[int, AfterValidator(lambda v: v + 1)] + + class Model(BaseModel): + a: MyInt + + print(Model(a=1).a) + #> 2 + + try: + Model(a='a') + except ValidationError as e: + print(e.json(indent=2)) + ''' + [ + { + "type": "int_parsing", + "loc": [ + "a" + ], + "msg": "Input should be a valid integer, unable to parse string as an integer", + "input": "a", + "url": "https://errors.pydantic.dev/2/v/int_parsing" + } + ] + ''' + ``` + """ + + func: core_schema.NoInfoValidatorFunction | core_schema.WithInfoValidatorFunction + + def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: + schema = handler(source_type) + info_arg = _inspect_validator(self.func, mode='after', type='field') + if info_arg: + func = cast(core_schema.WithInfoValidatorFunction, self.func) + return core_schema.with_info_after_validator_function(func, schema=schema) + else: + func = cast(core_schema.NoInfoValidatorFunction, self.func) + return core_schema.no_info_after_validator_function(func, schema=schema) + + @classmethod + def _from_decorator(cls, decorator: _decorators.Decorator[_decorators.FieldValidatorDecoratorInfo]) -> Self: + return cls(func=decorator.func) + + +@dataclasses.dataclass(frozen=True, **_internal_dataclass.slots_true) +class BeforeValidator: + """!!! abstract "Usage Documentation" + [field *before* validators](../concepts/validators.md#field-before-validator) + + A metadata class that indicates that a validation should be applied **before** the inner validation logic. + + Attributes: + func: The validator function. + json_schema_input_type: The input type used to generate the appropriate + JSON Schema (in validation mode). The actual input type is `Any`. + + Example: + ```python + from typing import Annotated + + from pydantic import BaseModel, BeforeValidator + + MyInt = Annotated[int, BeforeValidator(lambda v: v + 1)] + + class Model(BaseModel): + a: MyInt + + print(Model(a=1).a) + #> 2 + + try: + Model(a='a') + except TypeError as e: + print(e) + #> can only concatenate str (not "int") to str + ``` + """ + + func: core_schema.NoInfoValidatorFunction | core_schema.WithInfoValidatorFunction + json_schema_input_type: Any = PydanticUndefined + + def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: + schema = handler(source_type) + input_schema = ( + None + if self.json_schema_input_type is PydanticUndefined + else handler.generate_schema(self.json_schema_input_type) + ) + + info_arg = _inspect_validator(self.func, mode='before', type='field') + if info_arg: + func = cast(core_schema.WithInfoValidatorFunction, self.func) + return core_schema.with_info_before_validator_function( + func, + schema=schema, + json_schema_input_schema=input_schema, + ) + else: + func = cast(core_schema.NoInfoValidatorFunction, self.func) + return core_schema.no_info_before_validator_function( + func, schema=schema, json_schema_input_schema=input_schema + ) + + @classmethod + def _from_decorator(cls, decorator: _decorators.Decorator[_decorators.FieldValidatorDecoratorInfo]) -> Self: + return cls( + func=decorator.func, + json_schema_input_type=decorator.info.json_schema_input_type, + ) + + +@dataclasses.dataclass(frozen=True, **_internal_dataclass.slots_true) +class PlainValidator: + """!!! abstract "Usage Documentation" + [field *plain* validators](../concepts/validators.md#field-plain-validator) + + A metadata class that indicates that a validation should be applied **instead** of the inner validation logic. + + !!! note + Before v2.9, `PlainValidator` wasn't always compatible with JSON Schema generation for `mode='validation'`. + You can now use the `json_schema_input_type` argument to specify the input type of the function + to be used in the JSON schema when `mode='validation'` (the default). See the example below for more details. + + Attributes: + func: The validator function. + json_schema_input_type: The input type used to generate the appropriate + JSON Schema (in validation mode). The actual input type is `Any`. + + Example: + ```python + from typing import Annotated, Union + + from pydantic import BaseModel, PlainValidator + + def validate(v: object) -> int: + if not isinstance(v, (int, str)): + raise ValueError(f'Expected int or str, go {type(v)}') + + return int(v) + 1 + + MyInt = Annotated[ + int, + PlainValidator(validate, json_schema_input_type=Union[str, int]), # (1)! + ] + + class Model(BaseModel): + a: MyInt + + print(Model(a='1').a) + #> 2 + + print(Model(a=1).a) + #> 2 + ``` + + 1. In this example, we've specified the `json_schema_input_type` as `Union[str, int]` which indicates to the JSON schema + generator that in validation mode, the input type for the `a` field can be either a [`str`][] or an [`int`][]. + """ + + func: core_schema.NoInfoValidatorFunction | core_schema.WithInfoValidatorFunction + json_schema_input_type: Any = Any + + def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: + # Note that for some valid uses of PlainValidator, it is not possible to generate a core schema for the + # source_type, so calling `handler(source_type)` will error, which prevents us from generating a proper + # serialization schema. To work around this for use cases that will not involve serialization, we simply + # catch any PydanticSchemaGenerationError that may be raised while attempting to build the serialization schema + # and abort any attempts to handle special serialization. + from pydantic import PydanticSchemaGenerationError + + try: + schema = handler(source_type) + # TODO if `schema['serialization']` is one of `'include-exclude-dict/sequence', + # schema validation will fail. That's why we use 'type ignore' comments below. + serialization = schema.get( + 'serialization', + core_schema.wrap_serializer_function_ser_schema( + function=lambda v, h: h(v), + schema=schema, + return_schema=handler.generate_schema(source_type), + ), + ) + except PydanticSchemaGenerationError: + serialization = None + + input_schema = handler.generate_schema(self.json_schema_input_type) + + info_arg = _inspect_validator(self.func, mode='plain', type='field') + if info_arg: + func = cast(core_schema.WithInfoValidatorFunction, self.func) + return core_schema.with_info_plain_validator_function( + func, + serialization=serialization, # pyright: ignore[reportArgumentType] + json_schema_input_schema=input_schema, + ) + else: + func = cast(core_schema.NoInfoValidatorFunction, self.func) + return core_schema.no_info_plain_validator_function( + func, + serialization=serialization, # pyright: ignore[reportArgumentType] + json_schema_input_schema=input_schema, + ) + + @classmethod + def _from_decorator(cls, decorator: _decorators.Decorator[_decorators.FieldValidatorDecoratorInfo]) -> Self: + return cls( + func=decorator.func, + json_schema_input_type=decorator.info.json_schema_input_type, + ) + + +@dataclasses.dataclass(frozen=True, **_internal_dataclass.slots_true) +class WrapValidator: + """!!! abstract "Usage Documentation" + [field *wrap* validators](../concepts/validators.md#field-wrap-validator) + + A metadata class that indicates that a validation should be applied **around** the inner validation logic. + + Attributes: + func: The validator function. + json_schema_input_type: The input type used to generate the appropriate + JSON Schema (in validation mode). The actual input type is `Any`. + + ```python + from datetime import datetime + from typing import Annotated + + from pydantic import BaseModel, ValidationError, WrapValidator + + def validate_timestamp(v, handler): + if v == 'now': + # we don't want to bother with further validation, just return the new value + return datetime.now() + try: + return handler(v) + except ValidationError: + # validation failed, in this case we want to return a default value + return datetime(2000, 1, 1) + + MyTimestamp = Annotated[datetime, WrapValidator(validate_timestamp)] + + class Model(BaseModel): + a: MyTimestamp + + print(Model(a='now').a) + #> 2032-01-02 03:04:05.000006 + print(Model(a='invalid').a) + #> 2000-01-01 00:00:00 + ``` + """ + + func: core_schema.NoInfoWrapValidatorFunction | core_schema.WithInfoWrapValidatorFunction + json_schema_input_type: Any = PydanticUndefined + + def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: + schema = handler(source_type) + input_schema = ( + None + if self.json_schema_input_type is PydanticUndefined + else handler.generate_schema(self.json_schema_input_type) + ) + + info_arg = _inspect_validator(self.func, mode='wrap', type='field') + if info_arg: + func = cast(core_schema.WithInfoWrapValidatorFunction, self.func) + return core_schema.with_info_wrap_validator_function( + func, + schema=schema, + json_schema_input_schema=input_schema, + ) + else: + func = cast(core_schema.NoInfoWrapValidatorFunction, self.func) + return core_schema.no_info_wrap_validator_function( + func, + schema=schema, + json_schema_input_schema=input_schema, + ) + + @classmethod + def _from_decorator(cls, decorator: _decorators.Decorator[_decorators.FieldValidatorDecoratorInfo]) -> Self: + return cls( + func=decorator.func, + json_schema_input_type=decorator.info.json_schema_input_type, + ) + + +if TYPE_CHECKING: + + class _OnlyValueValidatorClsMethod(Protocol): + def __call__(self, cls: Any, value: Any, /) -> Any: ... + + class _V2ValidatorClsMethod(Protocol): + def __call__(self, cls: Any, value: Any, info: core_schema.ValidationInfo[Any], /) -> Any: ... + + class _OnlyValueWrapValidatorClsMethod(Protocol): + def __call__(self, cls: Any, value: Any, handler: core_schema.ValidatorFunctionWrapHandler, /) -> Any: ... + + class _V2WrapValidatorClsMethod(Protocol): + def __call__( + self, + cls: Any, + value: Any, + handler: core_schema.ValidatorFunctionWrapHandler, + info: core_schema.ValidationInfo[Any], + /, + ) -> Any: ... + + _V2Validator = Union[ + _V2ValidatorClsMethod, + core_schema.WithInfoValidatorFunction, + _OnlyValueValidatorClsMethod, + core_schema.NoInfoValidatorFunction, + ] + + _V2WrapValidator = Union[ + _V2WrapValidatorClsMethod, + core_schema.WithInfoWrapValidatorFunction, + _OnlyValueWrapValidatorClsMethod, + core_schema.NoInfoWrapValidatorFunction, + ] + + _PartialClsOrStaticMethod: TypeAlias = Union[classmethod[Any, Any, Any], staticmethod[Any, Any], partialmethod[Any]] + + _V2BeforeAfterOrPlainValidatorType = TypeVar( + '_V2BeforeAfterOrPlainValidatorType', + bound=Union[_V2Validator, _PartialClsOrStaticMethod], + ) + _V2WrapValidatorType = TypeVar('_V2WrapValidatorType', bound=Union[_V2WrapValidator, _PartialClsOrStaticMethod]) + +FieldValidatorModes: TypeAlias = Literal['before', 'after', 'wrap', 'plain'] + + +@overload +def field_validator( + field: str, + /, + *fields: str, + mode: Literal['wrap'], + check_fields: bool | None = ..., + json_schema_input_type: Any = ..., +) -> Callable[[_V2WrapValidatorType], _V2WrapValidatorType]: ... + + +@overload +def field_validator( + field: str, + /, + *fields: str, + mode: Literal['before', 'plain'], + check_fields: bool | None = ..., + json_schema_input_type: Any = ..., +) -> Callable[[_V2BeforeAfterOrPlainValidatorType], _V2BeforeAfterOrPlainValidatorType]: ... + + +@overload +def field_validator( + field: str, + /, + *fields: str, + mode: Literal['after'] = ..., + check_fields: bool | None = ..., +) -> Callable[[_V2BeforeAfterOrPlainValidatorType], _V2BeforeAfterOrPlainValidatorType]: ... + + +def field_validator( + field: str, + /, + *fields: str, + mode: FieldValidatorModes = 'after', + check_fields: bool | None = None, + json_schema_input_type: Any = PydanticUndefined, +) -> Callable[[Any], Any]: + """!!! abstract "Usage Documentation" + [field validators](../concepts/validators.md#field-validators) + + Decorate methods on the class indicating that they should be used to validate fields. + + Example usage: + ```python + from typing import Any + + from pydantic import ( + BaseModel, + ValidationError, + field_validator, + ) + + class Model(BaseModel): + a: str + + @field_validator('a') + @classmethod + def ensure_foobar(cls, v: Any): + if 'foobar' not in v: + raise ValueError('"foobar" not found in a') + return v + + print(repr(Model(a='this is foobar good'))) + #> Model(a='this is foobar good') + + try: + Model(a='snap') + except ValidationError as exc_info: + print(exc_info) + ''' + 1 validation error for Model + a + Value error, "foobar" not found in a [type=value_error, input_value='snap', input_type=str] + ''' + ``` + + For more in depth examples, see [Field Validators](../concepts/validators.md#field-validators). + + Args: + field: The first field the `field_validator` should be called on; this is separate + from `fields` to ensure an error is raised if you don't pass at least one. + *fields: Additional field(s) the `field_validator` should be called on. + mode: Specifies whether to validate the fields before or after validation. + check_fields: Whether to check that the fields actually exist on the model. + json_schema_input_type: The input type of the function. This is only used to generate + the appropriate JSON Schema (in validation mode) and can only specified + when `mode` is either `'before'`, `'plain'` or `'wrap'`. + + Returns: + A decorator that can be used to decorate a function to be used as a field_validator. + + Raises: + PydanticUserError: + - If `@field_validator` is used bare (with no fields). + - If the args passed to `@field_validator` as fields are not strings. + - If `@field_validator` applied to instance methods. + """ + if isinstance(field, FunctionType): + raise PydanticUserError( + '`@field_validator` should be used with fields and keyword arguments, not bare. ' + "E.g. usage should be `@validator('', ...)`", + code='validator-no-fields', + ) + + if mode not in ('before', 'plain', 'wrap') and json_schema_input_type is not PydanticUndefined: + raise PydanticUserError( + f"`json_schema_input_type` can't be used when mode is set to {mode!r}", + code='validator-input-type', + ) + + if json_schema_input_type is PydanticUndefined and mode == 'plain': + json_schema_input_type = Any + + fields = field, *fields + if not all(isinstance(field, str) for field in fields): + raise PydanticUserError( + '`@field_validator` fields should be passed as separate string args. ' + "E.g. usage should be `@validator('', '', ...)`", + code='validator-invalid-fields', + ) + + def dec( + f: Callable[..., Any] | staticmethod[Any, Any] | classmethod[Any, Any, Any], + ) -> _decorators.PydanticDescriptorProxy[Any]: + if _decorators.is_instance_method_from_sig(f): + raise PydanticUserError( + '`@field_validator` cannot be applied to instance methods', code='validator-instance-method' + ) + + # auto apply the @classmethod decorator + f = _decorators.ensure_classmethod_based_on_signature(f) + + dec_info = _decorators.FieldValidatorDecoratorInfo( + fields=fields, mode=mode, check_fields=check_fields, json_schema_input_type=json_schema_input_type + ) + return _decorators.PydanticDescriptorProxy(f, dec_info) + + return dec + + +_ModelType = TypeVar('_ModelType') +_ModelTypeCo = TypeVar('_ModelTypeCo', covariant=True) + + +class ModelWrapValidatorHandler(core_schema.ValidatorFunctionWrapHandler, Protocol[_ModelTypeCo]): + """`@model_validator` decorated function handler argument type. This is used when `mode='wrap'`.""" + + def __call__( # noqa: D102 + self, + value: Any, + outer_location: str | int | None = None, + /, + ) -> _ModelTypeCo: # pragma: no cover + ... + + +class ModelWrapValidatorWithoutInfo(Protocol[_ModelType]): + """A `@model_validator` decorated function signature. + This is used when `mode='wrap'` and the function does not have info argument. + """ + + def __call__( # noqa: D102 + self, + cls: type[_ModelType], + # this can be a dict, a model instance + # or anything else that gets passed to validate_python + # thus validators _must_ handle all cases + value: Any, + handler: ModelWrapValidatorHandler[_ModelType], + /, + ) -> _ModelType: ... + + +class ModelWrapValidator(Protocol[_ModelType]): + """A `@model_validator` decorated function signature. This is used when `mode='wrap'`.""" + + def __call__( # noqa: D102 + self, + cls: type[_ModelType], + # this can be a dict, a model instance + # or anything else that gets passed to validate_python + # thus validators _must_ handle all cases + value: Any, + handler: ModelWrapValidatorHandler[_ModelType], + info: core_schema.ValidationInfo, + /, + ) -> _ModelType: ... + + +class FreeModelBeforeValidatorWithoutInfo(Protocol): + """A `@model_validator` decorated function signature. + This is used when `mode='before'` and the function does not have info argument. + """ + + def __call__( # noqa: D102 + self, + # this can be a dict, a model instance + # or anything else that gets passed to validate_python + # thus validators _must_ handle all cases + value: Any, + /, + ) -> Any: ... + + +class ModelBeforeValidatorWithoutInfo(Protocol): + """A `@model_validator` decorated function signature. + This is used when `mode='before'` and the function does not have info argument. + """ + + def __call__( # noqa: D102 + self, + cls: Any, + # this can be a dict, a model instance + # or anything else that gets passed to validate_python + # thus validators _must_ handle all cases + value: Any, + /, + ) -> Any: ... + + +class FreeModelBeforeValidator(Protocol): + """A `@model_validator` decorated function signature. This is used when `mode='before'`.""" + + def __call__( # noqa: D102 + self, + # this can be a dict, a model instance + # or anything else that gets passed to validate_python + # thus validators _must_ handle all cases + value: Any, + info: core_schema.ValidationInfo[Any], + /, + ) -> Any: ... + + +class ModelBeforeValidator(Protocol): + """A `@model_validator` decorated function signature. This is used when `mode='before'`.""" + + def __call__( # noqa: D102 + self, + cls: Any, + # this can be a dict, a model instance + # or anything else that gets passed to validate_python + # thus validators _must_ handle all cases + value: Any, + info: core_schema.ValidationInfo[Any], + /, + ) -> Any: ... + + +ModelAfterValidatorWithoutInfo = Callable[[_ModelType], _ModelType] +"""A `@model_validator` decorated function signature. This is used when `mode='after'` and the function does not +have info argument. +""" + +ModelAfterValidator = Callable[[_ModelType, core_schema.ValidationInfo[Any]], _ModelType] +"""A `@model_validator` decorated function signature. This is used when `mode='after'`.""" + +_AnyModelWrapValidator = Union[ModelWrapValidator[_ModelType], ModelWrapValidatorWithoutInfo[_ModelType]] +_AnyModelBeforeValidator = Union[ + FreeModelBeforeValidator, ModelBeforeValidator, FreeModelBeforeValidatorWithoutInfo, ModelBeforeValidatorWithoutInfo +] +_AnyModelAfterValidator = Union[ModelAfterValidator[_ModelType], ModelAfterValidatorWithoutInfo[_ModelType]] + + +@overload +def model_validator( + *, + mode: Literal['wrap'], +) -> Callable[ + [_AnyModelWrapValidator[_ModelType]], _decorators.PydanticDescriptorProxy[_decorators.ModelValidatorDecoratorInfo] +]: ... + + +@overload +def model_validator( + *, + mode: Literal['before'], +) -> Callable[ + [_AnyModelBeforeValidator], _decorators.PydanticDescriptorProxy[_decorators.ModelValidatorDecoratorInfo] +]: ... + + +@overload +def model_validator( + *, + mode: Literal['after'], +) -> Callable[ + [_AnyModelAfterValidator[_ModelType]], _decorators.PydanticDescriptorProxy[_decorators.ModelValidatorDecoratorInfo] +]: ... + + +def model_validator( + *, + mode: Literal['wrap', 'before', 'after'], +) -> Any: + """!!! abstract "Usage Documentation" + [Model Validators](../concepts/validators.md#model-validators) + + Decorate model methods for validation purposes. + + Example usage: + ```python + from typing_extensions import Self + + from pydantic import BaseModel, ValidationError, model_validator + + class Square(BaseModel): + width: float + height: float + + @model_validator(mode='after') + def verify_square(self) -> Self: + if self.width != self.height: + raise ValueError('width and height do not match') + return self + + s = Square(width=1, height=1) + print(repr(s)) + #> Square(width=1.0, height=1.0) + + try: + Square(width=1, height=2) + except ValidationError as e: + print(e) + ''' + 1 validation error for Square + Value error, width and height do not match [type=value_error, input_value={'width': 1, 'height': 2}, input_type=dict] + ''' + ``` + + For more in depth examples, see [Model Validators](../concepts/validators.md#model-validators). + + Args: + mode: A required string literal that specifies the validation mode. + It can be one of the following: 'wrap', 'before', or 'after'. + + Returns: + A decorator that can be used to decorate a function to be used as a model validator. + """ + + def dec(f: Any) -> _decorators.PydanticDescriptorProxy[Any]: + # auto apply the @classmethod decorator. NOTE: in V3, do not apply the conversion for 'after' validators: + f = _decorators.ensure_classmethod_based_on_signature(f) + if mode == 'after' and isinstance(f, classmethod): + warnings.warn( + category=PydanticDeprecatedSince212, + message=( + "Using `@model_validator` with mode='after' on a classmethod is deprecated. Instead, use an instance method. " + f'See the documentation at https://docs.pydantic.dev/{version_short()}/concepts/validators/#model-after-validator.' + ), + stacklevel=2, + ) + + dec_info = _decorators.ModelValidatorDecoratorInfo(mode=mode) + return _decorators.PydanticDescriptorProxy(f, dec_info) + + return dec + + +AnyType = TypeVar('AnyType') + + +if TYPE_CHECKING: + # If we add configurable attributes to IsInstance, we'd probably need to stop hiding it from type checkers like this + InstanceOf = Annotated[AnyType, ...] # `IsInstance[Sequence]` will be recognized by type checkers as `Sequence` + +else: + + @dataclasses.dataclass(**_internal_dataclass.slots_true) + class InstanceOf: + '''Generic type for annotating a type that is an instance of a given class. + + Example: + ```python + from pydantic import BaseModel, InstanceOf + + class Foo: + ... + + class Bar(BaseModel): + foo: InstanceOf[Foo] + + Bar(foo=Foo()) + try: + Bar(foo=42) + except ValidationError as e: + print(e) + """ + [ + │ { + │ │ 'type': 'is_instance_of', + │ │ 'loc': ('foo',), + │ │ 'msg': 'Input should be an instance of Foo', + │ │ 'input': 42, + │ │ 'ctx': {'class': 'Foo'}, + │ │ 'url': 'https://errors.pydantic.dev/0.38.0/v/is_instance_of' + │ } + ] + """ + ``` + ''' + + @classmethod + def __class_getitem__(cls, item: AnyType) -> AnyType: + return Annotated[item, cls()] + + @classmethod + def __get_pydantic_core_schema__(cls, source: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: + from pydantic import PydanticSchemaGenerationError + + # use the generic _origin_ as the second argument to isinstance when appropriate + instance_of_schema = core_schema.is_instance_schema(_generics.get_origin(source) or source) + + try: + # Try to generate the "standard" schema, which will be used when loading from JSON + original_schema = handler(source) + except PydanticSchemaGenerationError: + # If that fails, just produce a schema that can validate from python + return instance_of_schema + else: + # Use the "original" approach to serialization + instance_of_schema['serialization'] = core_schema.wrap_serializer_function_ser_schema( + function=lambda v, h: h(v), schema=original_schema + ) + return core_schema.json_or_python_schema(python_schema=instance_of_schema, json_schema=original_schema) + + __hash__ = object.__hash__ + + +if TYPE_CHECKING: + SkipValidation = Annotated[AnyType, ...] # SkipValidation[list[str]] will be treated by type checkers as list[str] +else: + + @dataclasses.dataclass(**_internal_dataclass.slots_true) + class SkipValidation: + """If this is applied as an annotation (e.g., via `x: Annotated[int, SkipValidation]`), validation will be + skipped. You can also use `SkipValidation[int]` as a shorthand for `Annotated[int, SkipValidation]`. + + This can be useful if you want to use a type annotation for documentation/IDE/type-checking purposes, + and know that it is safe to skip validation for one or more of the fields. + + Because this converts the validation schema to `any_schema`, subsequent annotation-applied transformations + may not have the expected effects. Therefore, when used, this annotation should generally be the final + annotation applied to a type. + """ + + def __class_getitem__(cls, item: Any) -> Any: + return Annotated[item, SkipValidation()] + + @classmethod + def __get_pydantic_core_schema__(cls, source: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: + with warnings.catch_warnings(): + warnings.simplefilter('ignore', ArbitraryTypeWarning) + original_schema = handler(source) + metadata = {'pydantic_js_annotation_functions': [lambda _c, h: h(original_schema)]} + return core_schema.any_schema( + metadata=metadata, + serialization=core_schema.wrap_serializer_function_ser_schema( + function=lambda v, h: h(v), schema=original_schema + ), + ) + + __hash__ = object.__hash__ + + +_FromTypeT = TypeVar('_FromTypeT') + + +class ValidateAs: + """A helper class to validate a custom type from a type that is natively supported by Pydantic. + + Args: + from_type: The type natively supported by Pydantic to use to perform validation. + instantiation_hook: A callable taking the validated type as an argument, and returning + the populated custom type. + + Example: + ```python {lint="skip"} + from typing import Annotated + + from pydantic import BaseModel, TypeAdapter, ValidateAs + + class MyCls: + def __init__(self, a: int) -> None: + self.a = a + + def __repr__(self) -> str: + return f"MyCls(a={self.a})" + + class Model(BaseModel): + a: int + + + ta = TypeAdapter( + Annotated[MyCls, ValidateAs(Model, lambda v: MyCls(a=v.a))] + ) + + print(ta.validate_python({'a': 1})) + #> MyCls(a=1) + ``` + """ + + # TODO: make use of PEP 747 + def __init__(self, from_type: type[_FromTypeT], /, instantiation_hook: Callable[[_FromTypeT], Any]) -> None: + self.from_type = from_type + self.instantiation_hook = instantiation_hook + + def __get_pydantic_core_schema__(self, source: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: + schema = handler(self.from_type) + return core_schema.no_info_after_validator_function( + self.instantiation_hook, + schema=schema, + ) diff --git a/backend/.venv/Lib/site-packages/pydantic/generics.py b/backend/.venv/Lib/site-packages/pydantic/generics.py new file mode 100644 index 0000000..3f1070d --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/generics.py @@ -0,0 +1,5 @@ +"""The `generics` module is a backport module from V1.""" + +from ._migration import getattr_migration + +__getattr__ = getattr_migration(__name__) diff --git a/backend/.venv/Lib/site-packages/pydantic/json.py b/backend/.venv/Lib/site-packages/pydantic/json.py new file mode 100644 index 0000000..bcaff9f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/json.py @@ -0,0 +1,5 @@ +"""The `json` module is a backport module from V1.""" + +from ._migration import getattr_migration + +__getattr__ = getattr_migration(__name__) diff --git a/backend/.venv/Lib/site-packages/pydantic/json_schema.py b/backend/.venv/Lib/site-packages/pydantic/json_schema.py new file mode 100644 index 0000000..a16afb8 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/json_schema.py @@ -0,0 +1,2854 @@ +"""!!! abstract "Usage Documentation" + [JSON Schema](../concepts/json_schema.md) + +The `json_schema` module contains classes and functions to allow the way [JSON Schema](https://json-schema.org/) +is generated to be customized. + +In general you shouldn't need to use this module directly; instead, you can use +[`BaseModel.model_json_schema`][pydantic.BaseModel.model_json_schema] and +[`TypeAdapter.json_schema`][pydantic.TypeAdapter.json_schema]. +""" + +from __future__ import annotations as _annotations + +import dataclasses +import inspect +import math +import os +import re +import warnings +from collections import Counter, defaultdict +from collections.abc import Hashable, Iterable, Sequence +from copy import deepcopy +from enum import Enum +from re import Pattern +from typing import ( + TYPE_CHECKING, + Annotated, + Any, + Callable, + Literal, + NewType, + TypeVar, + Union, + cast, + overload, +) + +import pydantic_core +from pydantic_core import MISSING, CoreSchema, PydanticOmit, core_schema, to_jsonable_python +from pydantic_core.core_schema import ComputedField +from typing_extensions import TypeAlias, assert_never, deprecated, final +from typing_inspection.introspection import get_literal_values + +from pydantic.warnings import PydanticDeprecatedSince26, PydanticDeprecatedSince29 + +from ._internal import ( + _config, + _core_metadata, + _core_utils, + _decorators, + _internal_dataclass, + _mock_val_ser, + _schema_generation_shared, +) +from .annotated_handlers import GetJsonSchemaHandler +from .config import JsonDict, JsonValue +from .errors import PydanticInvalidForJsonSchema, PydanticSchemaGenerationError, PydanticUserError + +if TYPE_CHECKING: + from . import ConfigDict + from ._internal._core_utils import CoreSchemaField, CoreSchemaOrField + from ._internal._dataclasses import PydanticDataclass + from ._internal._schema_generation_shared import GetJsonSchemaFunction + from .main import BaseModel + + +CoreSchemaOrFieldType = Literal[core_schema.CoreSchemaType, core_schema.CoreSchemaFieldType] +""" +A type alias for defined schema types that represents a union of +`core_schema.CoreSchemaType` and +`core_schema.CoreSchemaFieldType`. +""" + +JsonSchemaValue = dict[str, Any] +""" +A type alias for a JSON schema value. This is a dictionary of string keys to arbitrary JSON values. +""" + +JsonSchemaMode = Literal['validation', 'serialization'] +""" +A type alias that represents the mode of a JSON schema; either 'validation' or 'serialization'. + +For some types, the inputs to validation differ from the outputs of serialization. For example, +computed fields will only be present when serializing, and should not be provided when +validating. This flag provides a way to indicate whether you want the JSON schema required +for validation inputs, or that will be matched by serialization outputs. +""" + +_MODE_TITLE_MAPPING: dict[JsonSchemaMode, str] = {'validation': 'Input', 'serialization': 'Output'} + + +JsonSchemaWarningKind = Literal['skipped-choice', 'non-serializable-default', 'skipped-discriminator'] +""" +A type alias representing the kinds of warnings that can be emitted during JSON schema generation. + +See [`GenerateJsonSchema.render_warning_message`][pydantic.json_schema.GenerateJsonSchema.render_warning_message] +for more details. +""" + + +class PydanticJsonSchemaWarning(UserWarning): + """This class is used to emit warnings produced during JSON schema generation. + See the [`GenerateJsonSchema.emit_warning`][pydantic.json_schema.GenerateJsonSchema.emit_warning] and + [`GenerateJsonSchema.render_warning_message`][pydantic.json_schema.GenerateJsonSchema.render_warning_message] + methods for more details; these can be overridden to control warning behavior. + """ + + +NoDefault = object() +"""A sentinel value used to indicate that no default value should be used when generating a JSON Schema +for a core schema with a default value. +""" + + +# ##### JSON Schema Generation ##### +DEFAULT_REF_TEMPLATE = '#/$defs/{model}' +"""The default format string used to generate reference names.""" + +# There are three types of references relevant to building JSON schemas: +# 1. core_schema "ref" values; these are not exposed as part of the JSON schema +# * these might look like the fully qualified path of a model, its id, or something similar +CoreRef = NewType('CoreRef', str) +# 2. keys of the "definitions" object that will eventually go into the JSON schema +# * by default, these look like "MyModel", though may change in the presence of collisions +# * eventually, we may want to make it easier to modify the way these names are generated +DefsRef = NewType('DefsRef', str) +# 3. the values corresponding to the "$ref" key in the schema +# * By default, these look like "#/$defs/MyModel", as in {"$ref": "#/$defs/MyModel"} +JsonRef = NewType('JsonRef', str) + +CoreModeRef = tuple[CoreRef, JsonSchemaMode] +JsonSchemaKeyT = TypeVar('JsonSchemaKeyT', bound=Hashable) + +_PRIMITIVE_JSON_SCHEMA_TYPES = ('string', 'boolean', 'null', 'integer', 'number') + + +@dataclasses.dataclass(**_internal_dataclass.slots_true) +class _DefinitionsRemapping: + defs_remapping: dict[DefsRef, DefsRef] + json_remapping: dict[JsonRef, JsonRef] + + @staticmethod + def from_prioritized_choices( + prioritized_choices: dict[DefsRef, list[DefsRef]], + defs_to_json: dict[DefsRef, JsonRef], + definitions: dict[DefsRef, JsonSchemaValue], + ) -> _DefinitionsRemapping: + """ + This function should produce a remapping that replaces complex DefsRef with the simpler ones from the + prioritized_choices such that applying the name remapping would result in an equivalent JSON schema. + """ + # We need to iteratively simplify the definitions until we reach a fixed point. + # The reason for this is that outer definitions may reference inner definitions that get simplified + # into an equivalent reference, and the outer definitions won't be equivalent until we've simplified + # the inner definitions. + copied_definitions = deepcopy(definitions) + definitions_schema = {'$defs': copied_definitions} + for _iter in range(100): # prevent an infinite loop in the case of a bug, 100 iterations should be enough + # For every possible remapped DefsRef, collect all schemas that that DefsRef might be used for: + schemas_for_alternatives: dict[DefsRef, list[JsonSchemaValue]] = defaultdict(list) + for defs_ref in copied_definitions: + alternatives = prioritized_choices[defs_ref] + for alternative in alternatives: + schemas_for_alternatives[alternative].append(copied_definitions[defs_ref]) + + # Deduplicate the schemas for each alternative; the idea is that we only want to remap to a new DefsRef + # if it introduces no ambiguity, i.e., there is only one distinct schema for that DefsRef. + for defs_ref in schemas_for_alternatives: + schemas_for_alternatives[defs_ref] = _deduplicate_schemas(schemas_for_alternatives[defs_ref]) + + # Build the remapping + defs_remapping: dict[DefsRef, DefsRef] = {} + json_remapping: dict[JsonRef, JsonRef] = {} + for original_defs_ref in definitions: + alternatives = prioritized_choices[original_defs_ref] + # Pick the first alternative that has only one schema, since that means there is no collision + remapped_defs_ref = next(x for x in alternatives if len(schemas_for_alternatives[x]) == 1) + defs_remapping[original_defs_ref] = remapped_defs_ref + json_remapping[defs_to_json[original_defs_ref]] = defs_to_json[remapped_defs_ref] + remapping = _DefinitionsRemapping(defs_remapping, json_remapping) + new_definitions_schema = remapping.remap_json_schema({'$defs': copied_definitions}) + if definitions_schema == new_definitions_schema: + # We've reached the fixed point + return remapping + definitions_schema = new_definitions_schema + + raise PydanticInvalidForJsonSchema('Failed to simplify the JSON schema definitions') + + def remap_defs_ref(self, ref: DefsRef) -> DefsRef: + return self.defs_remapping.get(ref, ref) + + def remap_json_ref(self, ref: JsonRef) -> JsonRef: + return self.json_remapping.get(ref, ref) + + def remap_json_schema(self, schema: Any) -> Any: + """ + Recursively update the JSON schema replacing all $refs + """ + if isinstance(schema, str): + # Note: this may not really be a JsonRef; we rely on having no collisions between JsonRefs and other strings + return self.remap_json_ref(JsonRef(schema)) + elif isinstance(schema, list): + return [self.remap_json_schema(item) for item in schema] + elif isinstance(schema, dict): + for key, value in schema.items(): + if key == '$ref' and isinstance(value, str): + schema['$ref'] = self.remap_json_ref(JsonRef(value)) + elif key == '$defs': + schema['$defs'] = { + self.remap_defs_ref(DefsRef(key)): self.remap_json_schema(value) + for key, value in schema['$defs'].items() + } + else: + schema[key] = self.remap_json_schema(value) + return schema + + +class GenerateJsonSchema: + """!!! abstract "Usage Documentation" + [Customizing the JSON Schema Generation Process](../concepts/json_schema.md#customizing-the-json-schema-generation-process) + + A class for generating JSON schemas. + + This class generates JSON schemas based on configured parameters. The default schema dialect + is [https://json-schema.org/draft/2020-12/schema](https://json-schema.org/draft/2020-12/schema). + The class uses `by_alias` to configure how fields with + multiple names are handled and `ref_template` to format reference names. + + Attributes: + schema_dialect: The JSON schema dialect used to generate the schema. See + [Declaring a Dialect](https://json-schema.org/understanding-json-schema/reference/schema.html#id4) + in the JSON Schema documentation for more information about dialects. + ignored_warning_kinds: Warnings to ignore when generating the schema. `self.render_warning_message` will + do nothing if its argument `kind` is in `ignored_warning_kinds`; + this value can be modified on subclasses to easily control which warnings are emitted. + by_alias: Whether to use field aliases when generating the schema. + ref_template: The format string used when generating reference names. + core_to_json_refs: A mapping of core refs to JSON refs. + core_to_defs_refs: A mapping of core refs to definition refs. + defs_to_core_refs: A mapping of definition refs to core refs. + json_to_defs_refs: A mapping of JSON refs to definition refs. + definitions: Definitions in the schema. + + Args: + by_alias: Whether to use field aliases in the generated schemas. + ref_template: The format string to use when generating reference names. + union_format: The format to use when combining schemas from unions together. Can be one of: + + - `'any_of'`: Use the [`anyOf`](https://json-schema.org/understanding-json-schema/reference/combining#anyOf) + keyword to combine schemas (the default). + - `'primitive_type_array'`: Use the [`type`](https://json-schema.org/understanding-json-schema/reference/type) + keyword as an array of strings, containing each type of the combination. If any of the schemas is not a primitive + type (`string`, `boolean`, `null`, `integer` or `number`) or contains constraints/metadata, falls back to + `any_of`. + + Raises: + JsonSchemaError: If the instance of the class is inadvertently reused after generating a schema. + """ + + schema_dialect = 'https://json-schema.org/draft/2020-12/schema' + + # `self.render_warning_message` will do nothing if its argument `kind` is in `ignored_warning_kinds`; + # this value can be modified on subclasses to easily control which warnings are emitted + ignored_warning_kinds: set[JsonSchemaWarningKind] = {'skipped-choice'} + + def __init__( + self, + by_alias: bool = True, + ref_template: str = DEFAULT_REF_TEMPLATE, + union_format: Literal['any_of', 'primitive_type_array'] = 'any_of', + ) -> None: + self.by_alias = by_alias + self.ref_template = ref_template + self.union_format: Literal['any_of', 'primitive_type_array'] = union_format + + self.core_to_json_refs: dict[CoreModeRef, JsonRef] = {} + self.core_to_defs_refs: dict[CoreModeRef, DefsRef] = {} + self.defs_to_core_refs: dict[DefsRef, CoreModeRef] = {} + self.json_to_defs_refs: dict[JsonRef, DefsRef] = {} + + self.definitions: dict[DefsRef, JsonSchemaValue] = {} + self._config_wrapper_stack = _config.ConfigWrapperStack(_config.ConfigWrapper({})) + + self._mode: JsonSchemaMode = 'validation' + + # The following includes a mapping of a fully-unique defs ref choice to a list of preferred + # alternatives, which are generally simpler, such as only including the class name. + # At the end of schema generation, we use these to produce a JSON schema with more human-readable + # definitions, which would also work better in a generated OpenAPI client, etc. + self._prioritized_defsref_choices: dict[DefsRef, list[DefsRef]] = {} + self._collision_counter: dict[str, int] = defaultdict(int) + self._collision_index: dict[str, int] = {} + + self._schema_type_to_method = self.build_schema_type_to_method() + + # When we encounter definitions we need to try to build them immediately + # so that they are available schemas that reference them + # But it's possible that CoreSchema was never going to be used + # (e.g. because the CoreSchema that references short circuits is JSON schema generation without needing + # the reference) so instead of failing altogether if we can't build a definition we + # store the error raised and re-throw it if we end up needing that def + self._core_defs_invalid_for_json_schema: dict[DefsRef, PydanticInvalidForJsonSchema] = {} + + # This changes to True after generating a schema, to prevent issues caused by accidental reuse + # of a single instance of a schema generator + self._used = False + + @property + def _config(self) -> _config.ConfigWrapper: + return self._config_wrapper_stack.tail + + @property + def mode(self) -> JsonSchemaMode: + if self._config.json_schema_mode_override is not None: + return self._config.json_schema_mode_override + else: + return self._mode + + def build_schema_type_to_method( + self, + ) -> dict[CoreSchemaOrFieldType, Callable[[CoreSchemaOrField], JsonSchemaValue]]: + """Builds a dictionary mapping fields to methods for generating JSON schemas. + + Returns: + A dictionary containing the mapping of `CoreSchemaOrFieldType` to a handler method. + + Raises: + TypeError: If no method has been defined for generating a JSON schema for a given pydantic core schema type. + """ + mapping: dict[CoreSchemaOrFieldType, Callable[[CoreSchemaOrField], JsonSchemaValue]] = {} + core_schema_types: list[CoreSchemaOrFieldType] = list(get_literal_values(CoreSchemaOrFieldType)) + for key in core_schema_types: + method_name = f'{key.replace("-", "_")}_schema' + try: + mapping[key] = getattr(self, method_name) + except AttributeError as e: # pragma: no cover + if os.getenv('PYDANTIC_PRIVATE_ALLOW_UNHANDLED_SCHEMA_TYPES'): + continue + raise TypeError( + f'No method for generating JsonSchema for core_schema.type={key!r} ' + f'(expected: {type(self).__name__}.{method_name})' + ) from e + return mapping + + def generate_definitions( + self, inputs: Sequence[tuple[JsonSchemaKeyT, JsonSchemaMode, core_schema.CoreSchema]] + ) -> tuple[dict[tuple[JsonSchemaKeyT, JsonSchemaMode], JsonSchemaValue], dict[DefsRef, JsonSchemaValue]]: + """Generates JSON schema definitions from a list of core schemas, pairing the generated definitions with a + mapping that links the input keys to the definition references. + + Args: + inputs: A sequence of tuples, where: + + - The first element is a JSON schema key type. + - The second element is the JSON mode: either 'validation' or 'serialization'. + - The third element is a core schema. + + Returns: + A tuple where: + + - The first element is a dictionary whose keys are tuples of JSON schema key type and JSON mode, and + whose values are the JSON schema corresponding to that pair of inputs. (These schemas may have + JsonRef references to definitions that are defined in the second returned element.) + - The second element is a dictionary whose keys are definition references for the JSON schemas + from the first returned element, and whose values are the actual JSON schema definitions. + + Raises: + PydanticUserError: Raised if the JSON schema generator has already been used to generate a JSON schema. + """ + if self._used: + raise PydanticUserError( + 'This JSON schema generator has already been used to generate a JSON schema. ' + f'You must create a new instance of {type(self).__name__} to generate a new JSON schema.', + code='json-schema-already-used', + ) + + for _, mode, schema in inputs: + self._mode = mode + self.generate_inner(schema) + + definitions_remapping = self._build_definitions_remapping() + + json_schemas_map: dict[tuple[JsonSchemaKeyT, JsonSchemaMode], DefsRef] = {} + for key, mode, schema in inputs: + self._mode = mode + json_schema = self.generate_inner(schema) + json_schemas_map[(key, mode)] = definitions_remapping.remap_json_schema(json_schema) + + json_schema = {'$defs': self.definitions} + json_schema = definitions_remapping.remap_json_schema(json_schema) + self._used = True + return json_schemas_map, self.sort(json_schema['$defs']) # type: ignore + + def generate(self, schema: CoreSchema, mode: JsonSchemaMode = 'validation') -> JsonSchemaValue: + """Generates a JSON schema for a specified schema in a specified mode. + + Args: + schema: A Pydantic model. + mode: The mode in which to generate the schema. Defaults to 'validation'. + + Returns: + A JSON schema representing the specified schema. + + Raises: + PydanticUserError: If the JSON schema generator has already been used to generate a JSON schema. + """ + self._mode = mode + if self._used: + raise PydanticUserError( + 'This JSON schema generator has already been used to generate a JSON schema. ' + f'You must create a new instance of {type(self).__name__} to generate a new JSON schema.', + code='json-schema-already-used', + ) + + json_schema: JsonSchemaValue = self.generate_inner(schema) + json_ref_counts = self.get_json_ref_counts(json_schema) + + ref = cast(JsonRef, json_schema.get('$ref')) + while ref is not None: # may need to unpack multiple levels + ref_json_schema = self.get_schema_from_definitions(ref) + if json_ref_counts[ref] == 1 and ref_json_schema is not None and len(json_schema) == 1: + # "Unpack" the ref since this is the only reference and there are no sibling keys + json_schema = ref_json_schema.copy() # copy to prevent recursive dict reference + json_ref_counts[ref] -= 1 + ref = cast(JsonRef, json_schema.get('$ref')) + ref = None + + self._garbage_collect_definitions(json_schema) + definitions_remapping = self._build_definitions_remapping() + + if self.definitions: + json_schema['$defs'] = self.definitions + + json_schema = definitions_remapping.remap_json_schema(json_schema) + + # For now, we will not set the $schema key. However, if desired, this can be easily added by overriding + # this method and adding the following line after a call to super().generate(schema): + # json_schema['$schema'] = self.schema_dialect + + self._used = True + return self.sort(json_schema) + + def generate_inner(self, schema: CoreSchemaOrField) -> JsonSchemaValue: # noqa: C901 + """Generates a JSON schema for a given core schema. + + Args: + schema: The given core schema. + + Returns: + The generated JSON schema. + + TODO: the nested function definitions here seem like bad practice, I'd like to unpack these + in a future PR. It'd be great if we could shorten the call stack a bit for JSON schema generation, + and I think there's potential for that here. + """ + # If a schema with the same CoreRef has been handled, just return a reference to it + # Note that this assumes that it will _never_ be the case that the same CoreRef is used + # on types that should have different JSON schemas + if 'ref' in schema: + core_ref = CoreRef(schema['ref']) # type: ignore[typeddict-item] + core_mode_ref = (core_ref, self.mode) + if core_mode_ref in self.core_to_defs_refs and self.core_to_defs_refs[core_mode_ref] in self.definitions: + return {'$ref': self.core_to_json_refs[core_mode_ref]} + + def populate_defs(core_schema: CoreSchema, json_schema: JsonSchemaValue) -> JsonSchemaValue: + if 'ref' in core_schema: + core_ref = CoreRef(core_schema['ref']) # type: ignore[typeddict-item] + defs_ref, ref_json_schema = self.get_cache_defs_ref_schema(core_ref) + json_ref = JsonRef(ref_json_schema['$ref']) + # Replace the schema if it's not a reference to itself + # What we want to avoid is having the def be just a ref to itself + # which is what would happen if we blindly assigned any + if json_schema.get('$ref', None) != json_ref: + self.definitions[defs_ref] = json_schema + self._core_defs_invalid_for_json_schema.pop(defs_ref, None) + json_schema = ref_json_schema + return json_schema + + def handler_func(schema_or_field: CoreSchemaOrField) -> JsonSchemaValue: + """Generate a JSON schema based on the input schema. + + Args: + schema_or_field: The core schema to generate a JSON schema from. + + Returns: + The generated JSON schema. + + Raises: + TypeError: If an unexpected schema type is encountered. + """ + # Generate the core-schema-type-specific bits of the schema generation: + json_schema: JsonSchemaValue | None = None + if self.mode == 'serialization' and 'serialization' in schema_or_field: + # In this case, we skip the JSON Schema generation of the schema + # and use the `'serialization'` schema instead (canonical example: + # `Annotated[int, PlainSerializer(str)]`). + ser_schema = schema_or_field['serialization'] # type: ignore + json_schema = self.ser_schema(ser_schema) + + # It might be that the 'serialization'` is skipped depending on `when_used`. + # This is only relevant for `nullable` schemas though, so we special case here. + if ( + json_schema is not None + and ser_schema.get('when_used') in ('unless-none', 'json-unless-none') + and schema_or_field['type'] == 'nullable' + ): + json_schema = self.get_union_of_schemas([{'type': 'null'}, json_schema]) + if json_schema is None: + if _core_utils.is_core_schema(schema_or_field) or _core_utils.is_core_schema_field(schema_or_field): + generate_for_schema_type = self._schema_type_to_method[schema_or_field['type']] + json_schema = generate_for_schema_type(schema_or_field) + else: + raise TypeError(f'Unexpected schema type: schema={schema_or_field}') + return json_schema + + current_handler = _schema_generation_shared.GenerateJsonSchemaHandler(self, handler_func) + + metadata = cast(_core_metadata.CoreMetadata, schema.get('metadata', {})) + + # TODO: I dislike that we have to wrap these basic dict updates in callables, is there any way around this? + + if js_updates := metadata.get('pydantic_js_updates'): + + def js_updates_handler_func( + schema_or_field: CoreSchemaOrField, + current_handler: GetJsonSchemaHandler = current_handler, + ) -> JsonSchemaValue: + json_schema = {**current_handler(schema_or_field), **js_updates} + return json_schema + + current_handler = _schema_generation_shared.GenerateJsonSchemaHandler(self, js_updates_handler_func) + + if js_extra := metadata.get('pydantic_js_extra'): + + def js_extra_handler_func( + schema_or_field: CoreSchemaOrField, + current_handler: GetJsonSchemaHandler = current_handler, + ) -> JsonSchemaValue: + json_schema = current_handler(schema_or_field) + if isinstance(js_extra, dict): + json_schema.update(to_jsonable_python(js_extra)) + elif callable(js_extra): + # similar to typing issue in _update_class_schema when we're working with callable js extra + js_extra(json_schema) # type: ignore + return json_schema + + current_handler = _schema_generation_shared.GenerateJsonSchemaHandler(self, js_extra_handler_func) + + for js_modify_function in metadata.get('pydantic_js_functions', ()): + + def new_handler_func( + schema_or_field: CoreSchemaOrField, + current_handler: GetJsonSchemaHandler = current_handler, + js_modify_function: GetJsonSchemaFunction = js_modify_function, + ) -> JsonSchemaValue: + json_schema = js_modify_function(schema_or_field, current_handler) + if _core_utils.is_core_schema(schema_or_field): + json_schema = populate_defs(schema_or_field, json_schema) + original_schema = current_handler.resolve_ref_schema(json_schema) + ref = json_schema.pop('$ref', None) + if ref and json_schema: + original_schema.update(json_schema) + return original_schema + + current_handler = _schema_generation_shared.GenerateJsonSchemaHandler(self, new_handler_func) + + for js_modify_function in metadata.get('pydantic_js_annotation_functions', ()): + + def new_handler_func( + schema_or_field: CoreSchemaOrField, + current_handler: GetJsonSchemaHandler = current_handler, + js_modify_function: GetJsonSchemaFunction = js_modify_function, + ) -> JsonSchemaValue: + return js_modify_function(schema_or_field, current_handler) + + current_handler = _schema_generation_shared.GenerateJsonSchemaHandler(self, new_handler_func) + + json_schema = current_handler(schema) + if _core_utils.is_core_schema(schema): + json_schema = populate_defs(schema, json_schema) + return json_schema + + def sort(self, value: JsonSchemaValue, parent_key: str | None = None) -> JsonSchemaValue: + """Override this method to customize the sorting of the JSON schema (e.g., don't sort at all, sort all keys unconditionally, etc.) + + By default, alphabetically sort the keys in the JSON schema, skipping the 'properties' and 'default' keys to preserve field definition order. + This sort is recursive, so it will sort all nested dictionaries as well. + """ + sorted_dict: dict[str, JsonSchemaValue] = {} + keys = value.keys() + if parent_key not in ('properties', 'default'): + keys = sorted(keys) + for key in keys: + sorted_dict[key] = self._sort_recursive(value[key], parent_key=key) + return sorted_dict + + def _sort_recursive(self, value: Any, parent_key: str | None = None) -> Any: + """Recursively sort a JSON schema value.""" + if isinstance(value, dict): + sorted_dict: dict[str, JsonSchemaValue] = {} + keys = value.keys() + if parent_key not in ('properties', 'default'): + keys = sorted(keys) + for key in keys: + sorted_dict[key] = self._sort_recursive(value[key], parent_key=key) + return sorted_dict + elif isinstance(value, list): + sorted_list: list[JsonSchemaValue] = [self._sort_recursive(item, parent_key) for item in value] + return sorted_list + else: + return value + + # ### Schema generation methods + + def invalid_schema(self, schema: core_schema.InvalidSchema) -> JsonSchemaValue: + """Placeholder - should never be called.""" + + raise RuntimeError('Cannot generate schema for invalid_schema. This is a bug! Please report it.') + + def any_schema(self, schema: core_schema.AnySchema) -> JsonSchemaValue: + """Generates a JSON schema that matches any value. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + return {} + + def none_schema(self, schema: core_schema.NoneSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches `None`. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + return {'type': 'null'} + + def bool_schema(self, schema: core_schema.BoolSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a bool value. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + return {'type': 'boolean'} + + def int_schema(self, schema: core_schema.IntSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches an int value. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + json_schema: dict[str, Any] = {'type': 'integer'} + self.update_with_validations(json_schema, schema, self.ValidationsMapping.numeric) + json_schema = {k: v for k, v in json_schema.items() if v not in {math.inf, -math.inf}} + return json_schema + + def float_schema(self, schema: core_schema.FloatSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a float value. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + json_schema: dict[str, Any] = {'type': 'number'} + self.update_with_validations(json_schema, schema, self.ValidationsMapping.numeric) + json_schema = {k: v for k, v in json_schema.items() if v not in {math.inf, -math.inf}} + return json_schema + + def decimal_schema(self, schema: core_schema.DecimalSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a decimal value. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + + def get_decimal_pattern(schema: core_schema.DecimalSchema) -> str: + max_digits = schema.get('max_digits') + decimal_places = schema.get('decimal_places') + + pattern = ( + r'^(?!^[-+.]*$)[+-]?0*' # check it is not empty string and not one or sequence of ".+-" characters. + ) + + # Case 1: Both max_digits and decimal_places are set + if max_digits is not None and decimal_places is not None: + integer_places = max(0, max_digits - decimal_places) + pattern += ( + rf'(?:' + rf'\d{{0,{integer_places}}}' + rf'|' + rf'(?=[\d.]{{1,{max_digits + 1}}}0*$)' + rf'\d{{0,{integer_places}}}\.\d{{0,{decimal_places}}}0*$' + rf')' + ) + + # Case 2: Only max_digits is set + elif max_digits is not None and decimal_places is None: + pattern += ( + rf'(?:' + rf'\d{{0,{max_digits}}}' + rf'|' + rf'(?=[\d.]{{1,{max_digits + 1}}}0*$)' + rf'\d*\.\d*0*$' + rf')' + ) + + # Case 3: Only decimal_places is set + elif max_digits is None and decimal_places is not None: + pattern += rf'\d*\.?\d{{0,{decimal_places}}}0*$' + + # Case 4: Both are None (no restrictions) + else: + pattern += r'\d*\.?\d*$' # look for arbitrary integer or decimal + + return pattern + + json_schema = self.str_schema(core_schema.str_schema(pattern=get_decimal_pattern(schema))) + if self.mode == 'validation': + multiple_of = schema.get('multiple_of') + le = schema.get('le') + ge = schema.get('ge') + lt = schema.get('lt') + gt = schema.get('gt') + json_schema = { + 'anyOf': [ + self.float_schema( + core_schema.float_schema( + allow_inf_nan=schema.get('allow_inf_nan'), + multiple_of=None if multiple_of is None else float(multiple_of), + le=None if le is None else float(le), + ge=None if ge is None else float(ge), + lt=None if lt is None else float(lt), + gt=None if gt is None else float(gt), + ) + ), + json_schema, + ], + } + return json_schema + + def str_schema(self, schema: core_schema.StringSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a string value. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + json_schema = {'type': 'string'} + self.update_with_validations(json_schema, schema, self.ValidationsMapping.string) + if isinstance(json_schema.get('pattern'), Pattern): + # TODO: should we add regex flags to the pattern? + json_schema['pattern'] = json_schema.get('pattern').pattern # type: ignore + return json_schema + + def bytes_schema(self, schema: core_schema.BytesSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a bytes value. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + json_schema = {'type': 'string', 'format': 'base64url' if self._config.ser_json_bytes == 'base64' else 'binary'} + self.update_with_validations(json_schema, schema, self.ValidationsMapping.bytes) + return json_schema + + def date_schema(self, schema: core_schema.DateSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a date value. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + return {'type': 'string', 'format': 'date'} + + def time_schema(self, schema: core_schema.TimeSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a time value. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + return {'type': 'string', 'format': 'time'} + + def datetime_schema(self, schema: core_schema.DatetimeSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a datetime value. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + return {'type': 'string', 'format': 'date-time'} + + def timedelta_schema(self, schema: core_schema.TimedeltaSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a timedelta value. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + if self._config.ser_json_timedelta == 'float': + return {'type': 'number'} + return {'type': 'string', 'format': 'duration'} + + def literal_schema(self, schema: core_schema.LiteralSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a literal value. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + expected = [to_jsonable_python(v.value if isinstance(v, Enum) else v) for v in schema['expected']] + + result: dict[str, Any] = {} + if len(expected) == 1: + result['const'] = expected[0] + else: + result['enum'] = expected + + types = {type(e) for e in expected} + if types == {str}: + result['type'] = 'string' + elif types == {int}: + result['type'] = 'integer' + elif types == {float}: + result['type'] = 'number' + elif types == {bool}: + result['type'] = 'boolean' + elif types == {list}: + result['type'] = 'array' + elif types == {type(None)}: + result['type'] = 'null' + return result + + def missing_sentinel_schema(self, schema: core_schema.MissingSentinelSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches the `MISSING` sentinel value. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + raise PydanticOmit + + def enum_schema(self, schema: core_schema.EnumSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches an Enum value. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + enum_type = schema['cls'] + description = None if not enum_type.__doc__ else inspect.cleandoc(enum_type.__doc__) + if ( + description == 'An enumeration.' + ): # This is the default value provided by enum.EnumMeta.__new__; don't use it + description = None + result: dict[str, Any] = {'title': enum_type.__name__, 'description': description} + result = {k: v for k, v in result.items() if v is not None} + + expected = [to_jsonable_python(v.value) for v in schema['members']] + + result['enum'] = expected + + types = {type(e) for e in expected} + if isinstance(enum_type, str) or types == {str}: + result['type'] = 'string' + elif isinstance(enum_type, int) or types == {int}: + result['type'] = 'integer' + elif isinstance(enum_type, float) or types == {float}: + result['type'] = 'number' + elif types == {bool}: + result['type'] = 'boolean' + elif types == {list}: + result['type'] = 'array' + + return result + + def is_instance_schema(self, schema: core_schema.IsInstanceSchema) -> JsonSchemaValue: + """Handles JSON schema generation for a core schema that checks if a value is an instance of a class. + + Unless overridden in a subclass, this raises an error. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + return self.handle_invalid_for_json_schema(schema, f'core_schema.IsInstanceSchema ({schema["cls"]})') + + def is_subclass_schema(self, schema: core_schema.IsSubclassSchema) -> JsonSchemaValue: + """Handles JSON schema generation for a core schema that checks if a value is a subclass of a class. + + For backwards compatibility with v1, this does not raise an error, but can be overridden to change this. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + # Note: This is for compatibility with V1; you can override if you want different behavior. + return {} + + def callable_schema(self, schema: core_schema.CallableSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a callable value. + + Unless overridden in a subclass, this raises an error. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + return self.handle_invalid_for_json_schema(schema, 'core_schema.CallableSchema') + + def list_schema(self, schema: core_schema.ListSchema) -> JsonSchemaValue: + """Returns a schema that matches a list schema. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + items_schema = {} if 'items_schema' not in schema else self.generate_inner(schema['items_schema']) + json_schema = {'type': 'array', 'items': items_schema} + self.update_with_validations(json_schema, schema, self.ValidationsMapping.array) + return json_schema + + @deprecated('`tuple_positional_schema` is deprecated. Use `tuple_schema` instead.', category=None) + @final + def tuple_positional_schema(self, schema: core_schema.TupleSchema) -> JsonSchemaValue: + """Replaced by `tuple_schema`.""" + warnings.warn( + '`tuple_positional_schema` is deprecated. Use `tuple_schema` instead.', + PydanticDeprecatedSince26, + stacklevel=2, + ) + return self.tuple_schema(schema) + + @deprecated('`tuple_variable_schema` is deprecated. Use `tuple_schema` instead.', category=None) + @final + def tuple_variable_schema(self, schema: core_schema.TupleSchema) -> JsonSchemaValue: + """Replaced by `tuple_schema`.""" + warnings.warn( + '`tuple_variable_schema` is deprecated. Use `tuple_schema` instead.', + PydanticDeprecatedSince26, + stacklevel=2, + ) + return self.tuple_schema(schema) + + def tuple_schema(self, schema: core_schema.TupleSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a tuple schema e.g. `tuple[int, + str, bool]` or `tuple[int, ...]`. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + json_schema: JsonSchemaValue = {'type': 'array'} + if 'variadic_item_index' in schema: + variadic_item_index = schema['variadic_item_index'] + if variadic_item_index > 0: + json_schema['minItems'] = variadic_item_index + json_schema['prefixItems'] = [ + self.generate_inner(item) for item in schema['items_schema'][:variadic_item_index] + ] + if variadic_item_index + 1 == len(schema['items_schema']): + # if the variadic item is the last item, then represent it faithfully + json_schema['items'] = self.generate_inner(schema['items_schema'][variadic_item_index]) + else: + # otherwise, 'items' represents the schema for the variadic + # item plus the suffix, so just allow anything for simplicity + # for now + json_schema['items'] = True + else: + prefixItems = [self.generate_inner(item) for item in schema['items_schema']] + if prefixItems: + json_schema['prefixItems'] = prefixItems + json_schema['minItems'] = len(prefixItems) + json_schema['maxItems'] = len(prefixItems) + self.update_with_validations(json_schema, schema, self.ValidationsMapping.array) + return json_schema + + def set_schema(self, schema: core_schema.SetSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a set schema. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + return self._common_set_schema(schema) + + def frozenset_schema(self, schema: core_schema.FrozenSetSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a frozenset schema. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + return self._common_set_schema(schema) + + def _common_set_schema(self, schema: core_schema.SetSchema | core_schema.FrozenSetSchema) -> JsonSchemaValue: + items_schema = {} if 'items_schema' not in schema else self.generate_inner(schema['items_schema']) + json_schema = {'type': 'array', 'uniqueItems': True, 'items': items_schema} + self.update_with_validations(json_schema, schema, self.ValidationsMapping.array) + return json_schema + + def generator_schema(self, schema: core_schema.GeneratorSchema) -> JsonSchemaValue: + """Returns a JSON schema that represents the provided GeneratorSchema. + + Args: + schema: The schema. + + Returns: + The generated JSON schema. + """ + items_schema = {} if 'items_schema' not in schema else self.generate_inner(schema['items_schema']) + json_schema = {'type': 'array', 'items': items_schema} + self.update_with_validations(json_schema, schema, self.ValidationsMapping.array) + return json_schema + + def dict_schema(self, schema: core_schema.DictSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a dict schema. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + json_schema: JsonSchemaValue = {'type': 'object'} + + keys_schema = self.generate_inner(schema['keys_schema']).copy() if 'keys_schema' in schema else {} + if '$ref' not in keys_schema: + keys_pattern = keys_schema.pop('pattern', None) + # Don't give a title to patternProperties/propertyNames: + keys_schema.pop('title', None) + else: + # Here, we assume that if the keys schema is a definition reference, + # it can't be a simple string core schema (and thus no pattern can exist). + # However, this is only in practice (in theory, a definition reference core + # schema could be generated for a simple string schema). + # Note that we avoid calling `self.resolve_ref_schema`, as it might not exist yet. + keys_pattern = None + + values_schema = self.generate_inner(schema['values_schema']).copy() if 'values_schema' in schema else {} + # don't give a title to additionalProperties: + values_schema.pop('title', None) + + if values_schema or keys_pattern is not None: + if keys_pattern is None: + json_schema['additionalProperties'] = values_schema + else: + json_schema['patternProperties'] = {keys_pattern: values_schema} + else: # for `dict[str, Any]`, we allow any key and any value, since `str` is the default key type + json_schema['additionalProperties'] = True + + if ( + # The len check indicates that constraints are probably present: + (keys_schema.get('type') == 'string' and len(keys_schema) > 1) + # If this is a definition reference schema, it most likely has constraints: + or '$ref' in keys_schema + ): + keys_schema.pop('type', None) + json_schema['propertyNames'] = keys_schema + + self.update_with_validations(json_schema, schema, self.ValidationsMapping.object) + return json_schema + + def function_before_schema(self, schema: core_schema.BeforeValidatorFunctionSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a function-before schema. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + if self.mode == 'validation' and (input_schema := schema.get('json_schema_input_schema')): + return self.generate_inner(input_schema) + + return self.generate_inner(schema['schema']) + + def function_after_schema(self, schema: core_schema.AfterValidatorFunctionSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a function-after schema. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + return self.generate_inner(schema['schema']) + + def function_plain_schema(self, schema: core_schema.PlainValidatorFunctionSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a function-plain schema. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + if self.mode == 'validation' and (input_schema := schema.get('json_schema_input_schema')): + return self.generate_inner(input_schema) + + return self.handle_invalid_for_json_schema( + schema, f'core_schema.PlainValidatorFunctionSchema ({schema["function"]})' + ) + + def function_wrap_schema(self, schema: core_schema.WrapValidatorFunctionSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a function-wrap schema. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + if self.mode == 'validation' and (input_schema := schema.get('json_schema_input_schema')): + return self.generate_inner(input_schema) + + return self.generate_inner(schema['schema']) + + def default_schema(self, schema: core_schema.WithDefaultSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema with a default value. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + json_schema = self.generate_inner(schema['schema']) + + default = self.get_default_value(schema) + if default is NoDefault or default is MISSING: + return json_schema + + # we reflect the application of custom plain, no-info serializers to defaults for + # JSON Schemas viewed in serialization mode: + # TODO: improvements along with https://github.com/pydantic/pydantic/issues/8208 + if self.mode == 'serialization': + # `_get_ser_schema_for_default_value()` is used to unpack potentially nested validator schemas: + ser_schema = _get_ser_schema_for_default_value(schema['schema']) + if ( + ser_schema is not None + and (ser_func := ser_schema.get('function')) + and not (default is None and ser_schema.get('when_used') in ('unless-none', 'json-unless-none')) + ): + try: + default = ser_func(default) # type: ignore + except Exception: + # It might be that the provided default needs to be validated (read: parsed) first + # (assuming `validate_default` is enabled). However, we can't perform + # such validation during JSON Schema generation so we don't support + # this pattern for now. + # (One example is when using `foo: ByteSize = '1MB'`, which validates and + # serializes as an int. In this case, `ser_func` is `int` and `int('1MB')` fails). + self.emit_warning( + 'non-serializable-default', + f'Unable to serialize value {default!r} with the plain serializer; excluding default from JSON schema', + ) + return json_schema + + try: + encoded_default = self.encode_default(default) + except pydantic_core.PydanticSerializationError: + self.emit_warning( + 'non-serializable-default', + f'Default value {default} is not JSON serializable; excluding default from JSON schema', + ) + # Return the inner schema, as though there was no default + return json_schema + + json_schema['default'] = encoded_default + return json_schema + + def get_default_value(self, schema: core_schema.WithDefaultSchema) -> Any: + """Get the default value to be used when generating a JSON Schema for a core schema with a default. + + The default implementation is to use the statically defined default value. This method can be overridden + if you want to make use of the default factory. + + Args: + schema: The `'with-default'` core schema. + + Returns: + The default value to use, or [`NoDefault`][pydantic.json_schema.NoDefault] if no default + value is available. + """ + return schema.get('default', NoDefault) + + def nullable_schema(self, schema: core_schema.NullableSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that allows null values. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + null_schema = {'type': 'null'} + inner_json_schema = self.generate_inner(schema['schema']) + + if inner_json_schema == null_schema: + return null_schema + else: + return self.get_union_of_schemas([inner_json_schema, null_schema]) + + def union_schema(self, schema: core_schema.UnionSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that allows values matching any of the given schemas. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + generated: list[JsonSchemaValue] = [] + + choices = schema['choices'] + for choice in choices: + # choice will be a tuple if an explicit label was provided + choice_schema = choice[0] if isinstance(choice, tuple) else choice + try: + generated.append(self.generate_inner(choice_schema)) + except PydanticOmit: + continue + except PydanticInvalidForJsonSchema as exc: + self.emit_warning('skipped-choice', exc.message) + if len(generated) == 1: + return generated[0] + return self.get_union_of_schemas(generated) + + def get_union_of_schemas(self, schemas: list[JsonSchemaValue]) -> JsonSchemaValue: + """Returns the JSON Schema representation for the union of the provided JSON Schemas. + + The result depends on the configured `'union_format'`. + + Args: + schemas: The list of JSON Schemas to be included in the union. + + Returns: + The JSON Schema representing the union of schemas. + """ + if self.union_format == 'primitive_type_array': + types: list[str] = [] + for schema in schemas: + schema_types: list[str] | str | None = schema.get('type') + if schema_types is None: + # No type, meaning it can be a ref or an empty schema. + break + if not isinstance(schema_types, list): + schema_types = [schema_types] + if not all(t in _PRIMITIVE_JSON_SCHEMA_TYPES for t in schema_types): + break + if len(schema) != 1: + # We only want to include types that don't have any constraints. For instance, + # if `schemas = [{'type': 'string', 'maxLength': 3}, {'type': 'string', 'minLength': 5}]`, + # we don't want to produce `{'type': 'string', 'maxLength': 3, 'minLength': 5}`. + # Same if we have some metadata (e.g. `title`) on a specific union member, we want to preserve it. + break + + types.extend(schema_types) + else: + # If we got there, all the schemas where valid to be used with the `'primitive_type_array` format + return {'type': list(dict.fromkeys(types))} + + return self.get_flattened_anyof(schemas) + + def tagged_union_schema(self, schema: core_schema.TaggedUnionSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that allows values matching any of the given schemas, where + the schemas are tagged with a discriminator field that indicates which schema should be used to validate + the value. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + generated: dict[str, JsonSchemaValue] = {} + for k, v in schema['choices'].items(): + if isinstance(k, Enum): + k = k.value + try: + # Use str(k) since keys must be strings for json; while not technically correct, + # it's the closest that can be represented in valid JSON + generated[str(k)] = self.generate_inner(v).copy() + except PydanticOmit: + continue + except PydanticInvalidForJsonSchema as exc: + self.emit_warning('skipped-choice', exc.message) + + one_of_choices = _deduplicate_schemas(generated.values()) + json_schema: JsonSchemaValue = {'oneOf': one_of_choices} + + # This reflects the v1 behavior; TODO: we should make it possible to exclude OpenAPI stuff from the JSON schema + openapi_discriminator = self._extract_discriminator(schema, one_of_choices) + if openapi_discriminator is not None: + json_schema['discriminator'] = { + 'propertyName': openapi_discriminator, + 'mapping': {k: v.get('$ref', v) for k, v in generated.items()}, + } + + return json_schema + + def _extract_discriminator( + self, schema: core_schema.TaggedUnionSchema, one_of_choices: list[JsonDict] + ) -> str | None: + """Extract a compatible OpenAPI discriminator from the schema and one_of choices that end up in the final + schema.""" + openapi_discriminator: str | None = None + + if isinstance(schema['discriminator'], str): + return schema['discriminator'] + + if isinstance(schema['discriminator'], list): + # If the discriminator is a single item list containing a string, that is equivalent to the string case + if len(schema['discriminator']) == 1 and isinstance(schema['discriminator'][0], str): + return schema['discriminator'][0] + # When an alias is used that is different from the field name, the discriminator will be a list of single + # str lists, one for the attribute and one for the actual alias. The logic here will work even if there is + # more than one possible attribute, and looks for whether a single alias choice is present as a documented + # property on all choices. If so, that property will be used as the OpenAPI discriminator. + for alias_path in schema['discriminator']: + if not isinstance(alias_path, list): + break # this means that the discriminator is not a list of alias paths + if len(alias_path) != 1: + continue # this means that the "alias" does not represent a single field + alias = alias_path[0] + if not isinstance(alias, str): + continue # this means that the "alias" does not represent a field + alias_is_present_on_all_choices = True + for choice in one_of_choices: + try: + choice = self.resolve_ref_schema(choice) + except RuntimeError as exc: + # TODO: fixme - this is a workaround for the fact that we can't always resolve refs + # for tagged union choices at this point in the schema gen process, we might need to do + # another pass at the end like we do for core schemas + self.emit_warning('skipped-discriminator', str(exc)) + choice = {} + properties = choice.get('properties', {}) + if not isinstance(properties, dict) or alias not in properties: + alias_is_present_on_all_choices = False + break + if alias_is_present_on_all_choices: + openapi_discriminator = alias + break + return openapi_discriminator + + def chain_schema(self, schema: core_schema.ChainSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a core_schema.ChainSchema. + + When generating a schema for validation, we return the validation JSON schema for the first step in the chain. + For serialization, we return the serialization JSON schema for the last step in the chain. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + step_index = 0 if self.mode == 'validation' else -1 # use first step for validation, last for serialization + return self.generate_inner(schema['steps'][step_index]) + + def lax_or_strict_schema(self, schema: core_schema.LaxOrStrictSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that allows values matching either the lax schema or the + strict schema. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + # TODO: Need to read the default value off of model config or whatever + use_strict = schema.get('strict', False) # TODO: replace this default False + # If your JSON schema fails to generate it is probably + # because one of the following two branches failed. + if use_strict: + return self.generate_inner(schema['strict_schema']) + else: + return self.generate_inner(schema['lax_schema']) + + def json_or_python_schema(self, schema: core_schema.JsonOrPythonSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that allows values matching either the JSON schema or the + Python schema. + + The JSON schema is used instead of the Python schema. If you want to use the Python schema, you should override + this method. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + return self.generate_inner(schema['json_schema']) + + def typed_dict_schema(self, schema: core_schema.TypedDictSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that defines a typed dict. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + total = schema.get('total', True) + named_required_fields: list[tuple[str, bool, CoreSchemaField]] = [ + (name, self.field_is_required(field, total), field) + for name, field in schema['fields'].items() + if self.field_is_present(field) + ] + if self.mode == 'serialization': + named_required_fields.extend(self._name_required_computed_fields(schema.get('computed_fields', []))) + cls = schema.get('cls') + config = _get_typed_dict_config(cls) + with self._config_wrapper_stack.push(config): + json_schema = self._named_required_fields_schema(named_required_fields) + + # There's some duplication between `extra_behavior` and + # the config's `extra`/core config's `extra_fields_behavior`. + # However, it is common to manually create TypedDictSchemas, + # where you don't necessarily have a class. + # At runtime, `extra_behavior` takes priority over the config + # for validation, so follow the same for the JSON Schema: + if schema.get('extra_behavior') == 'forbid': + json_schema['additionalProperties'] = False + elif schema.get('extra_behavior') == 'allow': + if 'extras_schema' in schema and schema['extras_schema'] != {'type': 'any'}: + json_schema['additionalProperties'] = self.generate_inner(schema['extras_schema']) + else: + json_schema['additionalProperties'] = True + + if cls is not None: + # `_update_class_schema()` will not override + # `additionalProperties` if already present: + self._update_class_schema(json_schema, cls, config) + elif 'additionalProperties' not in json_schema: + extra = schema.get('config', {}).get('extra_fields_behavior') + if extra == 'forbid': + json_schema['additionalProperties'] = False + elif extra == 'allow': + json_schema['additionalProperties'] = True + + return json_schema + + @staticmethod + def _name_required_computed_fields( + computed_fields: list[ComputedField], + ) -> list[tuple[str, bool, core_schema.ComputedField]]: + return [(field['property_name'], True, field) for field in computed_fields] + + def _named_required_fields_schema( + self, named_required_fields: Sequence[tuple[str, bool, CoreSchemaField]] + ) -> JsonSchemaValue: + properties: dict[str, JsonSchemaValue] = {} + required_fields: list[str] = [] + for name, required, field in named_required_fields: + if self.by_alias: + name = self._get_alias_name(field, name) + try: + field_json_schema = self.generate_inner(field).copy() + except PydanticOmit: + continue + if 'title' not in field_json_schema and self.field_title_should_be_set(field): + title = self.get_title_from_name(name) + field_json_schema['title'] = title + field_json_schema = self.handle_ref_overrides(field_json_schema) + properties[name] = field_json_schema + if required: + required_fields.append(name) + + json_schema = {'type': 'object', 'properties': properties} + if required_fields: + json_schema['required'] = required_fields + return json_schema + + def _get_alias_name(self, field: CoreSchemaField, name: str) -> str: + if field['type'] == 'computed-field': + alias: Any = field.get('alias', name) + elif self.mode == 'validation': + alias = field.get('validation_alias', name) + else: + alias = field.get('serialization_alias', name) + if isinstance(alias, str): + name = alias + elif isinstance(alias, list): + alias = cast('list[str] | str', alias) + for path in alias: + if isinstance(path, list) and len(path) == 1 and isinstance(path[0], str): + # Use the first valid single-item string path; the code that constructs the alias array + # should ensure the first such item is what belongs in the JSON schema + name = path[0] + break + else: + assert_never(alias) + return name + + def typed_dict_field_schema(self, schema: core_schema.TypedDictField) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that defines a typed dict field. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + return self.generate_inner(schema['schema']) + + def dataclass_field_schema(self, schema: core_schema.DataclassField) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that defines a dataclass field. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + return self.generate_inner(schema['schema']) + + def model_field_schema(self, schema: core_schema.ModelField) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that defines a model field. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + return self.generate_inner(schema['schema']) + + def computed_field_schema(self, schema: core_schema.ComputedField) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that defines a computed field. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + return self.generate_inner(schema['return_schema']) + + def model_schema(self, schema: core_schema.ModelSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that defines a model. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + # We do not use schema['model'].model_json_schema() here + # because it could lead to inconsistent refs handling, etc. + cls = cast('type[BaseModel]', schema['cls']) + config = cls.model_config + + with self._config_wrapper_stack.push(config): + json_schema = self.generate_inner(schema['schema']) + + self._update_class_schema(json_schema, cls, config) + + return json_schema + + def _update_class_schema(self, json_schema: JsonSchemaValue, cls: type[Any], config: ConfigDict) -> None: + """Update json_schema with the following, extracted from `config` and `cls`: + + * title + * description + * additional properties + * json_schema_extra + * deprecated + + Done in place, hence there's no return value as the original json_schema is mutated. + No ref resolving is involved here, as that's not appropriate for simple updates. + """ + from .main import BaseModel + from .root_model import RootModel + + if (config_title := config.get('title')) is not None: + json_schema.setdefault('title', config_title) + elif model_title_generator := config.get('model_title_generator'): + title = model_title_generator(cls) + if not isinstance(title, str): + raise TypeError(f'model_title_generator {model_title_generator} must return str, not {title.__class__}') + json_schema.setdefault('title', title) + if 'title' not in json_schema: + json_schema['title'] = cls.__name__ + + # BaseModel and dataclasses; don't use cls.__doc__ as it will contain the verbose class signature by default + docstring = None if cls is BaseModel or dataclasses.is_dataclass(cls) else cls.__doc__ + + if docstring: + json_schema.setdefault('description', inspect.cleandoc(docstring)) + elif issubclass(cls, RootModel) and (root_description := cls.__pydantic_fields__['root'].description): + json_schema.setdefault('description', root_description) + + extra = config.get('extra') + if 'additionalProperties' not in json_schema: # This check is particularly important for `typed_dict_schema()` + if extra == 'allow': + json_schema['additionalProperties'] = True + elif extra == 'forbid': + json_schema['additionalProperties'] = False + + json_schema_extra = config.get('json_schema_extra') + if issubclass(cls, BaseModel) and cls.__pydantic_root_model__: + root_json_schema_extra = cls.model_fields['root'].json_schema_extra + if json_schema_extra and root_json_schema_extra: + raise ValueError( + '"model_config[\'json_schema_extra\']" and "Field.json_schema_extra" on "RootModel.root"' + ' field must not be set simultaneously' + ) + if root_json_schema_extra: + json_schema_extra = root_json_schema_extra + + if isinstance(json_schema_extra, (staticmethod, classmethod)): + # In older versions of python, this is necessary to ensure staticmethod/classmethods are callable + json_schema_extra = json_schema_extra.__get__(cls) + + if isinstance(json_schema_extra, dict): + json_schema.update(json_schema_extra) + elif callable(json_schema_extra): + # FIXME: why are there type ignores here? We support two signatures for json_schema_extra callables... + if len(inspect.signature(json_schema_extra).parameters) > 1: + json_schema_extra(json_schema, cls) # type: ignore + else: + json_schema_extra(json_schema) # type: ignore + elif json_schema_extra is not None: + raise ValueError( + f"model_config['json_schema_extra']={json_schema_extra} should be a dict, callable, or None" + ) + + if hasattr(cls, '__deprecated__'): + json_schema['deprecated'] = True + + def resolve_ref_schema(self, json_schema: JsonSchemaValue) -> JsonSchemaValue: + """Resolve a JsonSchemaValue to the non-ref schema if it is a $ref schema. + + Args: + json_schema: The schema to resolve. + + Returns: + The resolved schema. + + Raises: + RuntimeError: If the schema reference can't be found in definitions. + """ + while '$ref' in json_schema: + ref = json_schema['$ref'] + schema_to_update = self.get_schema_from_definitions(JsonRef(ref)) + if schema_to_update is None: + raise RuntimeError(f'Cannot update undefined schema for $ref={ref}') + json_schema = schema_to_update + return json_schema + + def model_fields_schema(self, schema: core_schema.ModelFieldsSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that defines a model's fields. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + named_required_fields: list[tuple[str, bool, CoreSchemaField]] = [ + (name, self.field_is_required(field, total=True), field) + for name, field in schema['fields'].items() + if self.field_is_present(field) + ] + if self.mode == 'serialization': + named_required_fields.extend(self._name_required_computed_fields(schema.get('computed_fields', []))) + json_schema = self._named_required_fields_schema(named_required_fields) + extras_schema = schema.get('extras_schema', None) + if extras_schema is not None: + schema_to_update = self.resolve_ref_schema(json_schema) + schema_to_update['additionalProperties'] = self.generate_inner(extras_schema) + return json_schema + + def field_is_present(self, field: CoreSchemaField) -> bool: + """Whether the field should be included in the generated JSON schema. + + Args: + field: The schema for the field itself. + + Returns: + `True` if the field should be included in the generated JSON schema, `False` otherwise. + """ + if self.mode == 'serialization': + # If you still want to include the field in the generated JSON schema, + # override this method and return True + return not field.get('serialization_exclude') + elif self.mode == 'validation': + return True + else: + assert_never(self.mode) + + def field_is_required( + self, + field: core_schema.ModelField | core_schema.DataclassField | core_schema.TypedDictField, + total: bool, + ) -> bool: + """Whether the field should be marked as required in the generated JSON schema. + (Note that this is irrelevant if the field is not present in the JSON schema.). + + Args: + field: The schema for the field itself. + total: Only applies to `TypedDictField`s. + Indicates if the `TypedDict` this field belongs to is total, in which case any fields that don't + explicitly specify `required=False` are required. + + Returns: + `True` if the field should be marked as required in the generated JSON schema, `False` otherwise. + """ + if field['type'] == 'typed-dict-field': + required = field.get('required', total) + else: + required = field['schema']['type'] != 'default' + + if self.mode == 'serialization': + has_exclude_if = field.get('serialization_exclude_if') is not None + if self._config.json_schema_serialization_defaults_required: + return not has_exclude_if + else: + return required and not has_exclude_if + else: + return required + + def dataclass_args_schema(self, schema: core_schema.DataclassArgsSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that defines a dataclass's constructor arguments. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + named_required_fields: list[tuple[str, bool, CoreSchemaField]] = [ + (field['name'], self.field_is_required(field, total=True), field) + for field in schema['fields'] + if self.field_is_present(field) + ] + if self.mode == 'serialization': + named_required_fields.extend(self._name_required_computed_fields(schema.get('computed_fields', []))) + return self._named_required_fields_schema(named_required_fields) + + def dataclass_schema(self, schema: core_schema.DataclassSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that defines a dataclass. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + from ._internal._dataclasses import is_stdlib_dataclass + + cls = schema['cls'] + config: ConfigDict = getattr(cls, '__pydantic_config__', cast('ConfigDict', {})) + + with self._config_wrapper_stack.push(config): + json_schema = self.generate_inner(schema['schema']).copy() + + self._update_class_schema(json_schema, cls, config) + + # Dataclass-specific handling of description + if is_stdlib_dataclass(cls): + # vanilla dataclass; don't use cls.__doc__ as it will contain the class signature by default + description = None + else: + description = None if cls.__doc__ is None else inspect.cleandoc(cls.__doc__) + if description: + json_schema['description'] = description + + return json_schema + + def arguments_schema(self, schema: core_schema.ArgumentsSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that defines a function's arguments. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + prefer_positional = schema.get('metadata', {}).get('pydantic_js_prefer_positional_arguments') + + arguments = schema['arguments_schema'] + kw_only_arguments = [a for a in arguments if a.get('mode') == 'keyword_only'] + kw_or_p_arguments = [a for a in arguments if a.get('mode') in {'positional_or_keyword', None}] + p_only_arguments = [a for a in arguments if a.get('mode') == 'positional_only'] + var_args_schema = schema.get('var_args_schema') + var_kwargs_schema = schema.get('var_kwargs_schema') + + if prefer_positional: + positional_possible = not kw_only_arguments and not var_kwargs_schema + if positional_possible: + return self.p_arguments_schema(p_only_arguments + kw_or_p_arguments, var_args_schema) + + keyword_possible = not p_only_arguments and not var_args_schema + if keyword_possible: + return self.kw_arguments_schema(kw_or_p_arguments + kw_only_arguments, var_kwargs_schema) + + if not prefer_positional: + positional_possible = not kw_only_arguments and not var_kwargs_schema + if positional_possible: + return self.p_arguments_schema(p_only_arguments + kw_or_p_arguments, var_args_schema) + + raise PydanticInvalidForJsonSchema( + 'Unable to generate JSON schema for arguments validator with positional-only and keyword-only arguments' + ) + + def kw_arguments_schema( + self, arguments: list[core_schema.ArgumentsParameter], var_kwargs_schema: CoreSchema | None + ) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that defines a function's keyword arguments. + + Args: + arguments: The core schema. + + Returns: + The generated JSON schema. + """ + properties: dict[str, JsonSchemaValue] = {} + required: list[str] = [] + for argument in arguments: + name = self.get_argument_name(argument) + argument_schema = self.generate_inner(argument['schema']).copy() + if 'title' not in argument_schema and self.field_title_should_be_set(argument['schema']): + argument_schema['title'] = self.get_title_from_name(name) + properties[name] = argument_schema + + if argument['schema']['type'] != 'default': + # This assumes that if the argument has a default value, + # the inner schema must be of type WithDefaultSchema. + # I believe this is true, but I am not 100% sure + required.append(name) + + json_schema: JsonSchemaValue = {'type': 'object', 'properties': properties} + if required: + json_schema['required'] = required + + if var_kwargs_schema: + additional_properties_schema = self.generate_inner(var_kwargs_schema) + if additional_properties_schema: + json_schema['additionalProperties'] = additional_properties_schema + else: + json_schema['additionalProperties'] = False + return json_schema + + def p_arguments_schema( + self, arguments: list[core_schema.ArgumentsParameter], var_args_schema: CoreSchema | None + ) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that defines a function's positional arguments. + + Args: + arguments: The core schema. + + Returns: + The generated JSON schema. + """ + prefix_items: list[JsonSchemaValue] = [] + min_items = 0 + + for argument in arguments: + name = self.get_argument_name(argument) + + argument_schema = self.generate_inner(argument['schema']).copy() + if 'title' not in argument_schema and self.field_title_should_be_set(argument['schema']): + argument_schema['title'] = self.get_title_from_name(name) + prefix_items.append(argument_schema) + + if argument['schema']['type'] != 'default': + # This assumes that if the argument has a default value, + # the inner schema must be of type WithDefaultSchema. + # I believe this is true, but I am not 100% sure + min_items += 1 + + json_schema: JsonSchemaValue = {'type': 'array'} + if prefix_items: + json_schema['prefixItems'] = prefix_items + if min_items: + json_schema['minItems'] = min_items + + if var_args_schema: + items_schema = self.generate_inner(var_args_schema) + if items_schema: + json_schema['items'] = items_schema + else: + json_schema['maxItems'] = len(prefix_items) + + return json_schema + + def get_argument_name(self, argument: core_schema.ArgumentsParameter | core_schema.ArgumentsV3Parameter) -> str: + """Retrieves the name of an argument. + + Args: + argument: The core schema. + + Returns: + The name of the argument. + """ + name = argument['name'] + if self.by_alias: + alias = argument.get('alias') + if isinstance(alias, str): + name = alias + else: + pass # might want to do something else? + return name + + def arguments_v3_schema(self, schema: core_schema.ArgumentsV3Schema) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that defines a function's arguments. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + arguments = schema['arguments_schema'] + properties: dict[str, JsonSchemaValue] = {} + required: list[str] = [] + for argument in arguments: + mode = argument.get('mode', 'positional_or_keyword') + name = self.get_argument_name(argument) + argument_schema = self.generate_inner(argument['schema']).copy() + if mode == 'var_args': + argument_schema = {'type': 'array', 'items': argument_schema} + elif mode == 'var_kwargs_uniform': + argument_schema = {'type': 'object', 'additionalProperties': argument_schema} + + argument_schema.setdefault('title', self.get_title_from_name(name)) + properties[name] = argument_schema + + if ( + (mode == 'var_kwargs_unpacked_typed_dict' and 'required' in argument_schema) + or mode not in {'var_args', 'var_kwargs_uniform', 'var_kwargs_unpacked_typed_dict'} + and argument['schema']['type'] != 'default' + ): + # This assumes that if the argument has a default value, + # the inner schema must be of type WithDefaultSchema. + # I believe this is true, but I am not 100% sure + required.append(name) + + json_schema: JsonSchemaValue = {'type': 'object', 'properties': properties} + if required: + json_schema['required'] = required + return json_schema + + def call_schema(self, schema: core_schema.CallSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that defines a function call. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + return self.generate_inner(schema['arguments_schema']) + + def custom_error_schema(self, schema: core_schema.CustomErrorSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that defines a custom error. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + return self.generate_inner(schema['schema']) + + def json_schema(self, schema: core_schema.JsonSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that defines a JSON object. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + content_core_schema = schema.get('schema') or core_schema.any_schema() + content_json_schema = self.generate_inner(content_core_schema) + if self.mode == 'validation': + return {'type': 'string', 'contentMediaType': 'application/json', 'contentSchema': content_json_schema} + else: + # self.mode == 'serialization' + return content_json_schema + + def url_schema(self, schema: core_schema.UrlSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that defines a URL. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + json_schema = {'type': 'string', 'format': 'uri', 'minLength': 1} + self.update_with_validations(json_schema, schema, self.ValidationsMapping.string) + return json_schema + + def multi_host_url_schema(self, schema: core_schema.MultiHostUrlSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that defines a URL that can be used with multiple hosts. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + # Note: 'multi-host-uri' is a custom/pydantic-specific format, not part of the JSON Schema spec + json_schema = {'type': 'string', 'format': 'multi-host-uri', 'minLength': 1} + self.update_with_validations(json_schema, schema, self.ValidationsMapping.string) + return json_schema + + def uuid_schema(self, schema: core_schema.UuidSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a UUID. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + return {'type': 'string', 'format': 'uuid'} + + def definitions_schema(self, schema: core_schema.DefinitionsSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that defines a JSON object with definitions. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + for definition in schema['definitions']: + try: + self.generate_inner(definition) + except PydanticInvalidForJsonSchema as e: # noqa: PERF203 + core_ref: CoreRef = CoreRef(definition['ref']) # type: ignore + self._core_defs_invalid_for_json_schema[self.get_defs_ref((core_ref, self.mode))] = e + continue + return self.generate_inner(schema['schema']) + + def definition_ref_schema(self, schema: core_schema.DefinitionReferenceSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a schema that references a definition. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + core_ref = CoreRef(schema['schema_ref']) + _, ref_json_schema = self.get_cache_defs_ref_schema(core_ref) + return ref_json_schema + + def ser_schema( + self, schema: core_schema.SerSchema | core_schema.IncExSeqSerSchema | core_schema.IncExDictSerSchema + ) -> JsonSchemaValue | None: + """Generates a JSON schema that matches a schema that defines a serialized object. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + schema_type = schema['type'] + if schema_type == 'function-plain' or schema_type == 'function-wrap': + # PlainSerializerFunctionSerSchema or WrapSerializerFunctionSerSchema + return_schema = schema.get('return_schema') + if return_schema is not None: + return self.generate_inner(return_schema) + elif schema_type == 'format' or schema_type == 'to-string': + # FormatSerSchema or ToStringSerSchema + return self.str_schema(core_schema.str_schema()) + elif schema['type'] == 'model': + # ModelSerSchema + return self.generate_inner(schema['schema']) + return None + + def complex_schema(self, schema: core_schema.ComplexSchema) -> JsonSchemaValue: + """Generates a JSON schema that matches a complex number. + + JSON has no standard way to represent complex numbers. Complex number is not a numeric + type. Here we represent complex number as strings following the rule defined by Python. + For instance, '1+2j' is an accepted complex string. Details can be found in + [Python's `complex` documentation][complex]. + + Args: + schema: The core schema. + + Returns: + The generated JSON schema. + """ + return {'type': 'string'} + + # ### Utility methods + + def get_title_from_name(self, name: str) -> str: + """Retrieves a title from a name. + + Args: + name: The name to retrieve a title from. + + Returns: + The title. + """ + return name.title().replace('_', ' ').strip() + + def field_title_should_be_set(self, schema: CoreSchemaOrField) -> bool: + """Returns true if a field with the given schema should have a title set based on the field name. + + Intuitively, we want this to return true for schemas that wouldn't otherwise provide their own title + (e.g., int, float, str), and false for those that would (e.g., BaseModel subclasses). + + Args: + schema: The schema to check. + + Returns: + `True` if the field should have a title set, `False` otherwise. + """ + if _core_utils.is_core_schema_field(schema): + if schema['type'] == 'computed-field': + field_schema = schema['return_schema'] + else: + field_schema = schema['schema'] + return self.field_title_should_be_set(field_schema) + + elif _core_utils.is_core_schema(schema): + if schema.get('ref'): # things with refs, such as models and enums, should not have titles set + return False + if schema['type'] in {'default', 'nullable', 'definitions'}: + return self.field_title_should_be_set(schema['schema']) # type: ignore[typeddict-item] + if _core_utils.is_function_with_inner_schema(schema): + return self.field_title_should_be_set(schema['schema']) + if schema['type'] == 'definition-ref': + # Referenced schemas should not have titles set for the same reason + # schemas with refs should not + return False + return True # anything else should have title set + + else: + raise PydanticInvalidForJsonSchema(f'Unexpected schema type: schema={schema}') # pragma: no cover + + def normalize_name(self, name: str) -> str: + """Normalizes a name to be used as a key in a dictionary. + + Args: + name: The name to normalize. + + Returns: + The normalized name. + """ + return re.sub(r'[^a-zA-Z0-9.\-_]', '_', name).replace('.', '__') + + def get_defs_ref(self, core_mode_ref: CoreModeRef) -> DefsRef: + """Override this method to change the way that definitions keys are generated from a core reference. + + Args: + core_mode_ref: The core reference. + + Returns: + The definitions key. + """ + # Split the core ref into "components"; generic origins and arguments are each separate components + core_ref, mode = core_mode_ref + components = re.split(r'([\][,])', core_ref) + # Remove IDs from each component + components = [x.rsplit(':', 1)[0] for x in components] + core_ref_no_id = ''.join(components) + # Remove everything before the last period from each "component" + components = [re.sub(r'(?:[^.[\]]+\.)+((?:[^.[\]]+))', r'\1', x) for x in components] + short_ref = ''.join(components) + + mode_title = _MODE_TITLE_MAPPING[mode] + + # It is important that the generated defs_ref values be such that at least one choice will not + # be generated for any other core_ref. Currently, this should be the case because we include + # the id of the source type in the core_ref + name = DefsRef(self.normalize_name(short_ref)) + name_mode = DefsRef(self.normalize_name(short_ref) + f'-{mode_title}') + module_qualname = DefsRef(self.normalize_name(core_ref_no_id)) + module_qualname_mode = DefsRef(f'{module_qualname}-{mode_title}') + module_qualname_id = DefsRef(self.normalize_name(core_ref)) + occurrence_index = self._collision_index.get(module_qualname_id) + if occurrence_index is None: + self._collision_counter[module_qualname] += 1 + occurrence_index = self._collision_index[module_qualname_id] = self._collision_counter[module_qualname] + + module_qualname_occurrence = DefsRef(f'{module_qualname}__{occurrence_index}') + module_qualname_occurrence_mode = DefsRef(f'{module_qualname_mode}__{occurrence_index}') + + self._prioritized_defsref_choices[module_qualname_occurrence_mode] = [ + name, + name_mode, + module_qualname, + module_qualname_mode, + module_qualname_occurrence, + module_qualname_occurrence_mode, + ] + + return module_qualname_occurrence_mode + + def get_cache_defs_ref_schema(self, core_ref: CoreRef) -> tuple[DefsRef, JsonSchemaValue]: + """This method wraps the get_defs_ref method with some cache-lookup/population logic, + and returns both the produced defs_ref and the JSON schema that will refer to the right definition. + + Args: + core_ref: The core reference to get the definitions reference for. + + Returns: + A tuple of the definitions reference and the JSON schema that will refer to it. + """ + core_mode_ref = (core_ref, self.mode) + maybe_defs_ref = self.core_to_defs_refs.get(core_mode_ref) + if maybe_defs_ref is not None: + json_ref = self.core_to_json_refs[core_mode_ref] + return maybe_defs_ref, {'$ref': json_ref} + + defs_ref = self.get_defs_ref(core_mode_ref) + + # populate the ref translation mappings + self.core_to_defs_refs[core_mode_ref] = defs_ref + self.defs_to_core_refs[defs_ref] = core_mode_ref + + json_ref = JsonRef(self.ref_template.format(model=defs_ref)) + self.core_to_json_refs[core_mode_ref] = json_ref + self.json_to_defs_refs[json_ref] = defs_ref + ref_json_schema = {'$ref': json_ref} + return defs_ref, ref_json_schema + + def handle_ref_overrides(self, json_schema: JsonSchemaValue) -> JsonSchemaValue: + """Remove any sibling keys that are redundant with the referenced schema. + + Args: + json_schema: The schema to remove redundant sibling keys from. + + Returns: + The schema with redundant sibling keys removed. + """ + if '$ref' in json_schema: + # prevent modifications to the input; this copy may be safe to drop if there is significant overhead + json_schema = json_schema.copy() + + referenced_json_schema = self.get_schema_from_definitions(JsonRef(json_schema['$ref'])) + if referenced_json_schema is None: + # This can happen when building schemas for models with not-yet-defined references. + # It may be a good idea to do a recursive pass at the end of the generation to remove + # any redundant override keys. + return json_schema + for k, v in list(json_schema.items()): + if k == '$ref': + continue + if k in referenced_json_schema and referenced_json_schema[k] == v: + del json_schema[k] # redundant key + + return json_schema + + def get_schema_from_definitions(self, json_ref: JsonRef) -> JsonSchemaValue | None: + try: + def_ref = self.json_to_defs_refs[json_ref] + if def_ref in self._core_defs_invalid_for_json_schema: + raise self._core_defs_invalid_for_json_schema[def_ref] + return self.definitions.get(def_ref, None) + except KeyError: + if json_ref.startswith(('http://', 'https://')): + return None + raise + + def encode_default(self, dft: Any) -> Any: + """Encode a default value to a JSON-serializable value. + + This is used to encode default values for fields in the generated JSON schema. + + Args: + dft: The default value to encode. + + Returns: + The encoded default value. + """ + from .type_adapter import TypeAdapter, _type_has_config + + config = self._config + try: + default = ( + dft + if _type_has_config(type(dft)) + else TypeAdapter(type(dft), config=config.config_dict).dump_python( + dft, by_alias=self.by_alias, mode='json' + ) + ) + except PydanticSchemaGenerationError: + raise pydantic_core.PydanticSerializationError(f'Unable to encode default value {dft}') + + return pydantic_core.to_jsonable_python( + default, timedelta_mode=config.ser_json_timedelta, bytes_mode=config.ser_json_bytes, by_alias=self.by_alias + ) + + def update_with_validations( + self, json_schema: JsonSchemaValue, core_schema: CoreSchema, mapping: dict[str, str] + ) -> None: + """Update the json_schema with the corresponding validations specified in the core_schema, + using the provided mapping to translate keys in core_schema to the appropriate keys for a JSON schema. + + Args: + json_schema: The JSON schema to update. + core_schema: The core schema to get the validations from. + mapping: A mapping from core_schema attribute names to the corresponding JSON schema attribute names. + """ + for core_key, json_schema_key in mapping.items(): + if core_key in core_schema: + json_schema[json_schema_key] = core_schema[core_key] + + class ValidationsMapping: + """This class just contains mappings from core_schema attribute names to the corresponding + JSON schema attribute names. While I suspect it is unlikely to be necessary, you can in + principle override this class in a subclass of GenerateJsonSchema (by inheriting from + GenerateJsonSchema.ValidationsMapping) to change these mappings. + """ + + numeric = { + 'multiple_of': 'multipleOf', + 'le': 'maximum', + 'ge': 'minimum', + 'lt': 'exclusiveMaximum', + 'gt': 'exclusiveMinimum', + } + bytes = { + 'min_length': 'minLength', + 'max_length': 'maxLength', + } + string = { + 'min_length': 'minLength', + 'max_length': 'maxLength', + 'pattern': 'pattern', + } + array = { + 'min_length': 'minItems', + 'max_length': 'maxItems', + } + object = { + 'min_length': 'minProperties', + 'max_length': 'maxProperties', + } + + def get_flattened_anyof(self, schemas: list[JsonSchemaValue]) -> JsonSchemaValue: + members = [] + for schema in schemas: + if len(schema) == 1 and 'anyOf' in schema: + members.extend(schema['anyOf']) + else: + members.append(schema) + members = _deduplicate_schemas(members) + if len(members) == 1: + return members[0] + return {'anyOf': members} + + def get_json_ref_counts(self, json_schema: JsonSchemaValue) -> dict[JsonRef, int]: + """Get all values corresponding to the key '$ref' anywhere in the json_schema.""" + json_refs: dict[JsonRef, int] = Counter() + + def _add_json_refs(schema: Any) -> None: + if isinstance(schema, dict): + if '$ref' in schema: + json_ref = JsonRef(schema['$ref']) + if not isinstance(json_ref, str): + return # in this case, '$ref' might have been the name of a property + already_visited = json_ref in json_refs + json_refs[json_ref] += 1 + if already_visited: + return # prevent recursion on a definition that was already visited + try: + defs_ref = self.json_to_defs_refs[json_ref] + if defs_ref in self._core_defs_invalid_for_json_schema: + raise self._core_defs_invalid_for_json_schema[defs_ref] + _add_json_refs(self.definitions[defs_ref]) + except KeyError: + if not json_ref.startswith(('http://', 'https://')): + raise + + for k, v in schema.items(): + if k == 'examples' and isinstance(v, list): + # Skip examples that may contain arbitrary values and references + # (see the comment in `_get_all_json_refs` for more details). + continue + _add_json_refs(v) + elif isinstance(schema, list): + for v in schema: + _add_json_refs(v) + + _add_json_refs(json_schema) + return json_refs + + def handle_invalid_for_json_schema(self, schema: CoreSchemaOrField, error_info: str) -> JsonSchemaValue: + raise PydanticInvalidForJsonSchema(f'Cannot generate a JsonSchema for {error_info}') + + def emit_warning(self, kind: JsonSchemaWarningKind, detail: str) -> None: + """This method simply emits PydanticJsonSchemaWarnings based on handling in the `warning_message` method.""" + message = self.render_warning_message(kind, detail) + if message is not None: + warnings.warn(message, PydanticJsonSchemaWarning) + + def render_warning_message(self, kind: JsonSchemaWarningKind, detail: str) -> str | None: + """This method is responsible for ignoring warnings as desired, and for formatting the warning messages. + + You can override the value of `ignored_warning_kinds` in a subclass of GenerateJsonSchema + to modify what warnings are generated. If you want more control, you can override this method; + just return None in situations where you don't want warnings to be emitted. + + Args: + kind: The kind of warning to render. It can be one of the following: + + - 'skipped-choice': A choice field was skipped because it had no valid choices. + - 'non-serializable-default': A default value was skipped because it was not JSON-serializable. + detail: A string with additional details about the warning. + + Returns: + The formatted warning message, or `None` if no warning should be emitted. + """ + if kind in self.ignored_warning_kinds: + return None + return f'{detail} [{kind}]' + + def _build_definitions_remapping(self) -> _DefinitionsRemapping: + defs_to_json: dict[DefsRef, JsonRef] = {} + for defs_refs in self._prioritized_defsref_choices.values(): + for defs_ref in defs_refs: + json_ref = JsonRef(self.ref_template.format(model=defs_ref)) + defs_to_json[defs_ref] = json_ref + + return _DefinitionsRemapping.from_prioritized_choices( + self._prioritized_defsref_choices, defs_to_json, self.definitions + ) + + def _garbage_collect_definitions(self, schema: JsonSchemaValue) -> None: + visited_defs_refs: set[DefsRef] = set() + unvisited_json_refs = _get_all_json_refs(schema) + while unvisited_json_refs: + next_json_ref = unvisited_json_refs.pop() + try: + next_defs_ref = self.json_to_defs_refs[next_json_ref] + if next_defs_ref in visited_defs_refs: + continue + visited_defs_refs.add(next_defs_ref) + unvisited_json_refs.update(_get_all_json_refs(self.definitions[next_defs_ref])) + except KeyError: + if not next_json_ref.startswith(('http://', 'https://')): + raise + + self.definitions = {k: v for k, v in self.definitions.items() if k in visited_defs_refs} + + +# ##### Start JSON Schema Generation Functions ##### + + +def model_json_schema( + cls: type[BaseModel] | type[PydanticDataclass], + by_alias: bool = True, + ref_template: str = DEFAULT_REF_TEMPLATE, + union_format: Literal['any_of', 'primitive_type_array'] = 'any_of', + schema_generator: type[GenerateJsonSchema] = GenerateJsonSchema, + mode: JsonSchemaMode = 'validation', +) -> dict[str, Any]: + """Utility function to generate a JSON Schema for a model. + + Args: + cls: The model class to generate a JSON Schema for. + by_alias: If `True` (the default), fields will be serialized according to their alias. + If `False`, fields will be serialized according to their attribute name. + ref_template: The template to use for generating JSON Schema references. + union_format: The format to use when combining schemas from unions together. Can be one of: + + - `'any_of'`: Use the [`anyOf`](https://json-schema.org/understanding-json-schema/reference/combining#anyOf) + keyword to combine schemas (the default). + - `'primitive_type_array'`: Use the [`type`](https://json-schema.org/understanding-json-schema/reference/type) + keyword as an array of strings, containing each type of the combination. If any of the schemas is not a primitive + type (`string`, `boolean`, `null`, `integer` or `number`) or contains constraints/metadata, falls back to + `any_of`. + schema_generator: The class to use for generating the JSON Schema. + mode: The mode to use for generating the JSON Schema. It can be one of the following: + + - 'validation': Generate a JSON Schema for validating data. + - 'serialization': Generate a JSON Schema for serializing data. + + Returns: + The generated JSON Schema. + """ + from .main import BaseModel + + schema_generator_instance = schema_generator( + by_alias=by_alias, ref_template=ref_template, union_format=union_format + ) + + if isinstance(cls.__pydantic_core_schema__, _mock_val_ser.MockCoreSchema): + cls.__pydantic_core_schema__.rebuild() + + if cls is BaseModel: + raise AttributeError('model_json_schema() must be called on a subclass of BaseModel, not BaseModel itself.') + + assert not isinstance(cls.__pydantic_core_schema__, _mock_val_ser.MockCoreSchema), 'this is a bug! please report it' + return schema_generator_instance.generate(cls.__pydantic_core_schema__, mode=mode) + + +def models_json_schema( + models: Sequence[tuple[type[BaseModel] | type[PydanticDataclass], JsonSchemaMode]], + *, + by_alias: bool = True, + title: str | None = None, + description: str | None = None, + ref_template: str = DEFAULT_REF_TEMPLATE, + union_format: Literal['any_of', 'primitive_type_array'] = 'any_of', + schema_generator: type[GenerateJsonSchema] = GenerateJsonSchema, +) -> tuple[dict[tuple[type[BaseModel] | type[PydanticDataclass], JsonSchemaMode], JsonSchemaValue], JsonSchemaValue]: + """Utility function to generate a JSON Schema for multiple models. + + Args: + models: A sequence of tuples of the form (model, mode). + by_alias: Whether field aliases should be used as keys in the generated JSON Schema. + title: The title of the generated JSON Schema. + description: The description of the generated JSON Schema. + ref_template: The reference template to use for generating JSON Schema references. + union_format: The format to use when combining schemas from unions together. Can be one of: + + - `'any_of'`: Use the [`anyOf`](https://json-schema.org/understanding-json-schema/reference/combining#anyOf) + keyword to combine schemas (the default). + - `'primitive_type_array'`: Use the [`type`](https://json-schema.org/understanding-json-schema/reference/type) + keyword as an array of strings, containing each type of the combination. If any of the schemas is not a primitive + type (`string`, `boolean`, `null`, `integer` or `number`) or contains constraints/metadata, falls back to + `any_of`. + schema_generator: The schema generator to use for generating the JSON Schema. + + Returns: + A tuple where: + - The first element is a dictionary whose keys are tuples of JSON schema key type and JSON mode, and + whose values are the JSON schema corresponding to that pair of inputs. (These schemas may have + JsonRef references to definitions that are defined in the second returned element.) + - The second element is a JSON schema containing all definitions referenced in the first returned + element, along with the optional title and description keys. + """ + for cls, _ in models: + if isinstance(cls.__pydantic_core_schema__, _mock_val_ser.MockCoreSchema): + cls.__pydantic_core_schema__.rebuild() + + instance = schema_generator(by_alias=by_alias, ref_template=ref_template, union_format=union_format) + inputs: list[tuple[type[BaseModel] | type[PydanticDataclass], JsonSchemaMode, CoreSchema]] = [ + (m, mode, m.__pydantic_core_schema__) for m, mode in models + ] + json_schemas_map, definitions = instance.generate_definitions(inputs) + + json_schema: dict[str, Any] = {} + if definitions: + json_schema['$defs'] = definitions + if title: + json_schema['title'] = title + if description: + json_schema['description'] = description + + return json_schemas_map, json_schema + + +# ##### End JSON Schema Generation Functions ##### + + +_HashableJsonValue: TypeAlias = Union[ + int, float, str, bool, None, tuple['_HashableJsonValue', ...], tuple[tuple[str, '_HashableJsonValue'], ...] +] + + +def _deduplicate_schemas(schemas: Iterable[JsonDict]) -> list[JsonDict]: + return list({_make_json_hashable(schema): schema for schema in schemas}.values()) + + +def _make_json_hashable(value: JsonValue) -> _HashableJsonValue: + if isinstance(value, dict): + return tuple(sorted((k, _make_json_hashable(v)) for k, v in value.items())) + elif isinstance(value, list): + return tuple(_make_json_hashable(v) for v in value) + else: + return value + + +@dataclasses.dataclass(**_internal_dataclass.slots_true) +class WithJsonSchema: + """!!! abstract "Usage Documentation" + [`WithJsonSchema` Annotation](../concepts/json_schema.md#withjsonschema-annotation) + + Add this as an annotation on a field to override the (base) JSON schema that would be generated for that field. + This provides a way to set a JSON schema for types that would otherwise raise errors when producing a JSON schema, + such as Callable, or types that have an is-instance core schema, without needing to go so far as creating a + custom subclass of pydantic.json_schema.GenerateJsonSchema. + Note that any _modifications_ to the schema that would normally be made (such as setting the title for model fields) + will still be performed. + + If `mode` is set this will only apply to that schema generation mode, allowing you + to set different json schemas for validation and serialization. + """ + + json_schema: JsonSchemaValue | None + mode: Literal['validation', 'serialization'] | None = None + + def __get_pydantic_json_schema__( + self, core_schema: core_schema.CoreSchema, handler: GetJsonSchemaHandler + ) -> JsonSchemaValue: + mode = self.mode or handler.mode + if mode != handler.mode: + return handler(core_schema) + if self.json_schema is None: + # This exception is handled in pydantic.json_schema.GenerateJsonSchema._named_required_fields_schema + raise PydanticOmit + else: + return self.json_schema.copy() + + def __hash__(self) -> int: + return hash(type(self.mode)) + + +class Examples: + """Add examples to a JSON schema. + + If the JSON Schema already contains examples, the provided examples + will be appended. + + If `mode` is set this will only apply to that schema generation mode, + allowing you to add different examples for validation and serialization. + """ + + @overload + @deprecated('Using a dict for `examples` is deprecated since v2.9 and will be removed in v3.0. Use a list instead.') + def __init__( + self, examples: dict[str, Any], mode: Literal['validation', 'serialization'] | None = None + ) -> None: ... + + @overload + def __init__(self, examples: list[Any], mode: Literal['validation', 'serialization'] | None = None) -> None: ... + + def __init__( + self, examples: dict[str, Any] | list[Any], mode: Literal['validation', 'serialization'] | None = None + ) -> None: + if isinstance(examples, dict): + warnings.warn( + 'Using a dict for `examples` is deprecated, use a list instead.', + PydanticDeprecatedSince29, + stacklevel=2, + ) + self.examples = examples + self.mode = mode + + def __get_pydantic_json_schema__( + self, core_schema: core_schema.CoreSchema, handler: GetJsonSchemaHandler + ) -> JsonSchemaValue: + mode = self.mode or handler.mode + json_schema = handler(core_schema) + if mode != handler.mode: + return json_schema + examples = json_schema.get('examples') + if examples is None: + json_schema['examples'] = to_jsonable_python(self.examples) + if isinstance(examples, dict): + if isinstance(self.examples, list): + warnings.warn( + 'Updating existing JSON Schema examples of type dict with examples of type list. ' + 'Only the existing examples values will be retained. Note that dict support for ' + 'examples is deprecated and will be removed in v3.0.', + UserWarning, + ) + json_schema['examples'] = to_jsonable_python( + [ex for value in examples.values() for ex in value] + self.examples + ) + else: + json_schema['examples'] = to_jsonable_python({**examples, **self.examples}) + if isinstance(examples, list): + if isinstance(self.examples, list): + json_schema['examples'] = to_jsonable_python(examples + self.examples) + elif isinstance(self.examples, dict): + warnings.warn( + 'Updating existing JSON Schema examples of type list with examples of type dict. ' + 'Only the examples values will be retained. Note that dict support for ' + 'examples is deprecated and will be removed in v3.0.', + UserWarning, + ) + json_schema['examples'] = to_jsonable_python( + examples + [ex for value in self.examples.values() for ex in value] + ) + + return json_schema + + def __hash__(self) -> int: + return hash(type(self.mode)) + + +def _get_all_json_refs(item: Any) -> set[JsonRef]: + """Get all the definitions references from a JSON schema.""" + refs: set[JsonRef] = set() + stack = [item] + + while stack: + current = stack.pop() + if isinstance(current, dict): + for key, value in current.items(): + if key == 'examples' and isinstance(value, list): + # Skip examples that may contain arbitrary values and references + # (e.g. `{"examples": [{"$ref": "..."}]}`). Note: checking for value + # of type list is necessary to avoid skipping valid portions of the schema, + # for instance when "examples" is used as a property key. A more robust solution + # could be found, but would require more advanced JSON Schema parsing logic. + continue + if key == '$ref' and isinstance(value, str): + refs.add(JsonRef(value)) + elif isinstance(value, dict): + stack.append(value) + elif isinstance(value, list): + stack.extend(value) + elif isinstance(current, list): + stack.extend(current) + + return refs + + +AnyType = TypeVar('AnyType') + +if TYPE_CHECKING: + SkipJsonSchema = Annotated[AnyType, ...] +else: + + @dataclasses.dataclass(**_internal_dataclass.slots_true) + class SkipJsonSchema: + """!!! abstract "Usage Documentation" + [`SkipJsonSchema` Annotation](../concepts/json_schema.md#skipjsonschema-annotation) + + Add this as an annotation on a field to skip generating a JSON schema for that field. + + Example: + ```python + from pprint import pprint + from typing import Union + + from pydantic import BaseModel + from pydantic.json_schema import SkipJsonSchema + + class Model(BaseModel): + a: Union[int, None] = None # (1)! + b: Union[int, SkipJsonSchema[None]] = None # (2)! + c: SkipJsonSchema[Union[int, None]] = None # (3)! + + pprint(Model.model_json_schema()) + ''' + { + 'properties': { + 'a': { + 'anyOf': [ + {'type': 'integer'}, + {'type': 'null'} + ], + 'default': None, + 'title': 'A' + }, + 'b': { + 'default': None, + 'title': 'B', + 'type': 'integer' + } + }, + 'title': 'Model', + 'type': 'object' + } + ''' + ``` + + 1. The integer and null types are both included in the schema for `a`. + 2. The integer type is the only type included in the schema for `b`. + 3. The entirety of the `c` field is omitted from the schema. + """ + + def __class_getitem__(cls, item: AnyType) -> AnyType: + return Annotated[item, cls()] + + def __get_pydantic_json_schema__( + self, core_schema: CoreSchema, handler: GetJsonSchemaHandler + ) -> JsonSchemaValue: + raise PydanticOmit + + def __hash__(self) -> int: + return hash(type(self)) + + +def _get_typed_dict_config(cls: type[Any] | None) -> ConfigDict: + if cls is not None: + try: + return _decorators.get_attribute_from_bases(cls, '__pydantic_config__') + except AttributeError: + pass + return {} + + +def _get_ser_schema_for_default_value(schema: CoreSchema) -> core_schema.PlainSerializerFunctionSerSchema | None: + """Get a `'function-plain'` serialization schema that can be used to serialize a default value. + + This takes into account having the serialization schema nested under validation schema(s). + """ + if ( + (ser_schema := schema.get('serialization')) + and ser_schema['type'] == 'function-plain' + and not ser_schema.get('info_arg') + ): + return ser_schema + if _core_utils.is_function_with_inner_schema(schema): + return _get_ser_schema_for_default_value(schema['schema']) diff --git a/backend/.venv/Lib/site-packages/pydantic/main.py b/backend/.venv/Lib/site-packages/pydantic/main.py new file mode 100644 index 0000000..2b3148e --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/main.py @@ -0,0 +1,1819 @@ +"""Logic for creating models.""" + +# Because `dict` is in the local namespace of the `BaseModel` class, we use `Dict` for annotations. +# TODO v3 fallback to `dict` when the deprecated `dict` method gets removed. +# ruff: noqa: UP035 + +from __future__ import annotations as _annotations + +import operator +import sys +import types +import warnings +from collections.abc import Generator, Mapping +from copy import copy, deepcopy +from functools import cached_property +from typing import ( + TYPE_CHECKING, + Any, + Callable, + ClassVar, + Dict, + Generic, + Literal, + TypeVar, + Union, + cast, + overload, +) + +import pydantic_core +import typing_extensions +from pydantic_core import PydanticUndefined, ValidationError +from typing_extensions import Self, TypeAlias, Unpack + +from . import PydanticDeprecatedSince20, PydanticDeprecatedSince211 +from ._internal import ( + _config, + _decorators, + _fields, + _forward_ref, + _generics, + _mock_val_ser, + _model_construction, + _namespace_utils, + _repr, + _typing_extra, + _utils, +) +from ._migration import getattr_migration +from .aliases import AliasChoices, AliasPath +from .annotated_handlers import GetCoreSchemaHandler, GetJsonSchemaHandler +from .config import ConfigDict, ExtraValues +from .errors import PydanticUndefinedAnnotation, PydanticUserError +from .json_schema import DEFAULT_REF_TEMPLATE, GenerateJsonSchema, JsonSchemaMode, JsonSchemaValue, model_json_schema +from .plugin._schema_validator import PluggableSchemaValidator + +if TYPE_CHECKING: + from inspect import Signature + from pathlib import Path + + from pydantic_core import CoreSchema, SchemaSerializer, SchemaValidator + + from ._internal._namespace_utils import MappingNamespace + from ._internal._utils import AbstractSetIntStr, MappingIntStrAny + from .deprecated.parse import Protocol as DeprecatedParseProtocol + from .fields import ComputedFieldInfo, FieldInfo, ModelPrivateAttr + + +__all__ = 'BaseModel', 'create_model' + +# Keep these type aliases available at runtime: +TupleGenerator: TypeAlias = Generator[tuple[str, Any], None, None] +# NOTE: In reality, `bool` should be replaced by `Literal[True]` but mypy fails to correctly apply bidirectional +# type inference (e.g. when using `{'a': {'b': True}}`): +# NOTE: Keep this type alias in sync with the stub definition in `pydantic-core`: +IncEx: TypeAlias = Union[set[int], set[str], Mapping[int, Union['IncEx', bool]], Mapping[str, Union['IncEx', bool]]] + +_object_setattr = _model_construction.object_setattr + + +def _check_frozen(model_cls: type[BaseModel], name: str, value: Any) -> None: + if model_cls.model_config.get('frozen'): + error_type = 'frozen_instance' + elif getattr(model_cls.__pydantic_fields__.get(name), 'frozen', False): + error_type = 'frozen_field' + else: + return + + raise ValidationError.from_exception_data( + model_cls.__name__, [{'type': error_type, 'loc': (name,), 'input': value}] + ) + + +def _model_field_setattr_handler(model: BaseModel, name: str, val: Any) -> None: + model.__dict__[name] = val + model.__pydantic_fields_set__.add(name) + + +def _private_setattr_handler(model: BaseModel, name: str, val: Any) -> None: + if getattr(model, '__pydantic_private__', None) is None: + # While the attribute should be present at this point, this may not be the case if + # users do unusual stuff with `model_post_init()` (which is where the `__pydantic_private__` + # is initialized, by wrapping the user-defined `model_post_init()`), e.g. if they mock + # the `model_post_init()` call. Ideally we should find a better way to init private attrs. + object.__setattr__(model, '__pydantic_private__', {}) + model.__pydantic_private__[name] = val # pyright: ignore[reportOptionalSubscript] + + +_SIMPLE_SETATTR_HANDLERS: Mapping[str, Callable[[BaseModel, str, Any], None]] = { + 'model_field': _model_field_setattr_handler, + 'validate_assignment': lambda model, name, val: model.__pydantic_validator__.validate_assignment(model, name, val), # pyright: ignore[reportAssignmentType] + 'private': _private_setattr_handler, + 'cached_property': lambda model, name, val: model.__dict__.__setitem__(name, val), + 'extra_known': lambda model, name, val: _object_setattr(model, name, val), +} + + +class BaseModel(metaclass=_model_construction.ModelMetaclass): + """!!! abstract "Usage Documentation" + [Models](../concepts/models.md) + + A base class for creating Pydantic models. + + Attributes: + __class_vars__: The names of the class variables defined on the model. + __private_attributes__: Metadata about the private attributes of the model. + __signature__: The synthesized `__init__` [`Signature`][inspect.Signature] of the model. + + __pydantic_complete__: Whether model building is completed, or if there are still undefined fields. + __pydantic_core_schema__: The core schema of the model. + __pydantic_custom_init__: Whether the model has a custom `__init__` function. + __pydantic_decorators__: Metadata containing the decorators defined on the model. + This replaces `Model.__validators__` and `Model.__root_validators__` from Pydantic V1. + __pydantic_generic_metadata__: Metadata for generic models; contains data used for a similar purpose to + __args__, __origin__, __parameters__ in typing-module generics. May eventually be replaced by these. + __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models. + __pydantic_post_init__: The name of the post-init method for the model, if defined. + __pydantic_root_model__: Whether the model is a [`RootModel`][pydantic.root_model.RootModel]. + __pydantic_serializer__: The `pydantic-core` `SchemaSerializer` used to dump instances of the model. + __pydantic_validator__: The `pydantic-core` `SchemaValidator` used to validate instances of the model. + + __pydantic_fields__: A dictionary of field names and their corresponding [`FieldInfo`][pydantic.fields.FieldInfo] objects. + __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [`ComputedFieldInfo`][pydantic.fields.ComputedFieldInfo] objects. + + __pydantic_extra__: A dictionary containing extra values, if [`extra`][pydantic.config.ConfigDict.extra] + is set to `'allow'`. + __pydantic_fields_set__: The names of fields explicitly set during instantiation. + __pydantic_private__: Values of private attributes set on the model instance. + """ + + # Note: Many of the below class vars are defined in the metaclass, but we define them here for type checking purposes. + + model_config: ClassVar[ConfigDict] = ConfigDict() + """ + Configuration for the model, should be a dictionary conforming to [`ConfigDict`][pydantic.config.ConfigDict]. + """ + + __class_vars__: ClassVar[set[str]] + """The names of the class variables defined on the model.""" + + __private_attributes__: ClassVar[Dict[str, ModelPrivateAttr]] # noqa: UP006 + """Metadata about the private attributes of the model.""" + + __signature__: ClassVar[Signature] + """The synthesized `__init__` [`Signature`][inspect.Signature] of the model.""" + + __pydantic_complete__: ClassVar[bool] = False + """Whether model building is completed, or if there are still undefined fields.""" + + __pydantic_core_schema__: ClassVar[CoreSchema] + """The core schema of the model.""" + + __pydantic_custom_init__: ClassVar[bool] + """Whether the model has a custom `__init__` method.""" + + # Must be set for `GenerateSchema.model_schema` to work for a plain `BaseModel` annotation. + __pydantic_decorators__: ClassVar[_decorators.DecoratorInfos] = _decorators.DecoratorInfos() + """Metadata containing the decorators defined on the model. + This replaces `Model.__validators__` and `Model.__root_validators__` from Pydantic V1.""" + + __pydantic_generic_metadata__: ClassVar[_generics.PydanticGenericMetadata] + """Metadata for generic models; contains data used for a similar purpose to + __args__, __origin__, __parameters__ in typing-module generics. May eventually be replaced by these.""" + + __pydantic_parent_namespace__: ClassVar[Dict[str, Any] | None] = None # noqa: UP006 + """Parent namespace of the model, used for automatic rebuilding of models.""" + + __pydantic_post_init__: ClassVar[None | Literal['model_post_init']] + """The name of the post-init method for the model, if defined.""" + + __pydantic_root_model__: ClassVar[bool] = False + """Whether the model is a [`RootModel`][pydantic.root_model.RootModel].""" + + __pydantic_serializer__: ClassVar[SchemaSerializer] + """The `pydantic-core` `SchemaSerializer` used to dump instances of the model.""" + + __pydantic_validator__: ClassVar[SchemaValidator | PluggableSchemaValidator] + """The `pydantic-core` `SchemaValidator` used to validate instances of the model.""" + + __pydantic_fields__: ClassVar[Dict[str, FieldInfo]] # noqa: UP006 + """A dictionary of field names and their corresponding [`FieldInfo`][pydantic.fields.FieldInfo] objects. + This replaces `Model.__fields__` from Pydantic V1. + """ + + __pydantic_setattr_handlers__: ClassVar[Dict[str, Callable[[BaseModel, str, Any], None]]] # noqa: UP006 + """`__setattr__` handlers. Memoizing the handlers leads to a dramatic performance improvement in `__setattr__`""" + + __pydantic_computed_fields__: ClassVar[Dict[str, ComputedFieldInfo]] # noqa: UP006 + """A dictionary of computed field names and their corresponding [`ComputedFieldInfo`][pydantic.fields.ComputedFieldInfo] objects.""" + + __pydantic_extra__: Dict[str, Any] | None = _model_construction.NoInitField(init=False) # noqa: UP006 + """A dictionary containing extra values, if [`extra`][pydantic.config.ConfigDict.extra] is set to `'allow'`.""" + + __pydantic_fields_set__: set[str] = _model_construction.NoInitField(init=False) + """The names of fields explicitly set during instantiation.""" + + __pydantic_private__: Dict[str, Any] | None = _model_construction.NoInitField(init=False) # noqa: UP006 + """Values of private attributes set on the model instance.""" + + if not TYPE_CHECKING: + # Prevent `BaseModel` from being instantiated directly + # (defined in an `if not TYPE_CHECKING` block for clarity and to avoid type checking errors): + __pydantic_core_schema__ = _mock_val_ser.MockCoreSchema( + 'Pydantic models should inherit from BaseModel, BaseModel cannot be instantiated directly', + code='base-model-instantiated', + ) + __pydantic_validator__ = _mock_val_ser.MockValSer( + 'Pydantic models should inherit from BaseModel, BaseModel cannot be instantiated directly', + val_or_ser='validator', + code='base-model-instantiated', + ) + __pydantic_serializer__ = _mock_val_ser.MockValSer( + 'Pydantic models should inherit from BaseModel, BaseModel cannot be instantiated directly', + val_or_ser='serializer', + code='base-model-instantiated', + ) + + __slots__ = '__dict__', '__pydantic_fields_set__', '__pydantic_extra__', '__pydantic_private__' + + def __init__(self, /, **data: Any) -> None: + """Create a new model by parsing and validating input data from keyword arguments. + + Raises [`ValidationError`][pydantic_core.ValidationError] if the input data cannot be + validated to form a valid model. + + `self` is explicitly positional-only to allow `self` as a field name. + """ + # `__tracebackhide__` tells pytest and some other tools to omit this function from tracebacks + __tracebackhide__ = True + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) + if self is not validated_self: + warnings.warn( + 'A custom validator is returning a value other than `self`.\n' + "Returning anything other than `self` from a top level model validator isn't supported when validating via `__init__`.\n" + 'See the `model_validator` docs (https://docs.pydantic.dev/latest/concepts/validators/#model-validators) for more details.', + stacklevel=2, + ) + + # The following line sets a flag that we use to determine when `__init__` gets overridden by the user + __init__.__pydantic_base_init__ = True # pyright: ignore[reportFunctionMemberAccess] + + @_utils.deprecated_instance_property + @classmethod + def model_fields(cls) -> dict[str, FieldInfo]: + """A mapping of field names to their respective [`FieldInfo`][pydantic.fields.FieldInfo] instances. + + !!! warning + Accessing this attribute from a model instance is deprecated, and will not work in Pydantic V3. + Instead, you should access this attribute from the model class. + """ + return getattr(cls, '__pydantic_fields__', {}) + + @_utils.deprecated_instance_property + @classmethod + def model_computed_fields(cls) -> dict[str, ComputedFieldInfo]: + """A mapping of computed field names to their respective [`ComputedFieldInfo`][pydantic.fields.ComputedFieldInfo] instances. + + !!! warning + Accessing this attribute from a model instance is deprecated, and will not work in Pydantic V3. + Instead, you should access this attribute from the model class. + """ + return getattr(cls, '__pydantic_computed_fields__', {}) + + @property + def model_extra(self) -> dict[str, Any] | None: + """Get extra fields set during validation. + + Returns: + A dictionary of extra fields, or `None` if `config.extra` is not set to `"allow"`. + """ + return self.__pydantic_extra__ + + @property + def model_fields_set(self) -> set[str]: + """Returns the set of fields that have been explicitly set on this model instance. + + Returns: + A set of strings representing the fields that have been set, + i.e. that were not filled from defaults. + """ + return self.__pydantic_fields_set__ + + @classmethod + def model_construct(cls, _fields_set: set[str] | None = None, **values: Any) -> Self: # noqa: C901 + """Creates a new instance of the `Model` class with validated data. + + Creates a new model setting `__dict__` and `__pydantic_fields_set__` from trusted or pre-validated data. + Default values are respected, but no other validation is performed. + + !!! note + `model_construct()` generally respects the `model_config.extra` setting on the provided model. + That is, if `model_config.extra == 'allow'`, then all extra passed values are added to the model instance's `__dict__` + and `__pydantic_extra__` fields. If `model_config.extra == 'ignore'` (the default), then all extra passed values are ignored. + Because no validation is performed with a call to `model_construct()`, having `model_config.extra == 'forbid'` does not result in + an error if extra values are passed, but they will be ignored. + + Args: + _fields_set: A set of field names that were originally explicitly set during instantiation. If provided, + this is directly used for the [`model_fields_set`][pydantic.BaseModel.model_fields_set] attribute. + Otherwise, the field names from the `values` argument will be used. + values: Trusted or pre-validated data dictionary. + + Returns: + A new instance of the `Model` class with validated data. + """ + m = cls.__new__(cls) + fields_values: dict[str, Any] = {} + fields_set = set() + + for name, field in cls.__pydantic_fields__.items(): + if field.alias is not None and field.alias in values: + fields_values[name] = values.pop(field.alias) + fields_set.add(name) + + if (name not in fields_set) and (field.validation_alias is not None): + validation_aliases: list[str | AliasPath] = ( + field.validation_alias.choices + if isinstance(field.validation_alias, AliasChoices) + else [field.validation_alias] + ) + + for alias in validation_aliases: + if isinstance(alias, str) and alias in values: + fields_values[name] = values.pop(alias) + fields_set.add(name) + break + elif isinstance(alias, AliasPath): + value = alias.search_dict_for_path(values) + if value is not PydanticUndefined: + fields_values[name] = value + fields_set.add(name) + break + + if name not in fields_set: + if name in values: + fields_values[name] = values.pop(name) + fields_set.add(name) + elif not field.is_required(): + fields_values[name] = field.get_default(call_default_factory=True, validated_data=fields_values) + if _fields_set is None: + _fields_set = fields_set + + _extra: dict[str, Any] | None = values if cls.model_config.get('extra') == 'allow' else None + _object_setattr(m, '__dict__', fields_values) + _object_setattr(m, '__pydantic_fields_set__', _fields_set) + if not cls.__pydantic_root_model__: + _object_setattr(m, '__pydantic_extra__', _extra) + + if cls.__pydantic_post_init__: + m.model_post_init(None) + # update private attributes with values set + if hasattr(m, '__pydantic_private__') and m.__pydantic_private__ is not None: + for k, v in values.items(): + if k in m.__private_attributes__: + m.__pydantic_private__[k] = v + + elif not cls.__pydantic_root_model__: + # Note: if there are any private attributes, cls.__pydantic_post_init__ would exist + # Since it doesn't, that means that `__pydantic_private__` should be set to None + _object_setattr(m, '__pydantic_private__', None) + + return m + + def model_copy(self, *, update: Mapping[str, Any] | None = None, deep: bool = False) -> Self: + """!!! abstract "Usage Documentation" + [`model_copy`](../concepts/models.md#model-copy) + + Returns a copy of the model. + + !!! note + The underlying instance's [`__dict__`][object.__dict__] attribute is copied. This + might have unexpected side effects if you store anything in it, on top of the model + fields (e.g. the value of [cached properties][functools.cached_property]). + + Args: + update: Values to change/add in the new model. Note: the data is not validated + before creating the new model. You should trust this data. + deep: Set to `True` to make a deep copy of the model. + + Returns: + New model instance. + """ + copied = self.__deepcopy__() if deep else self.__copy__() + if update: + if self.model_config.get('extra') == 'allow': + for k, v in update.items(): + if k in self.__pydantic_fields__: + copied.__dict__[k] = v + else: + if copied.__pydantic_extra__ is None: + copied.__pydantic_extra__ = {} + copied.__pydantic_extra__[k] = v + else: + copied.__dict__.update(update) + copied.__pydantic_fields_set__.update(update.keys()) + return copied + + def model_dump( + self, + *, + mode: Literal['json', 'python'] | str = 'python', + include: IncEx | None = None, + exclude: IncEx | None = None, + context: Any | None = None, + by_alias: bool | None = None, + exclude_unset: bool = False, + exclude_defaults: bool = False, + exclude_none: bool = False, + exclude_computed_fields: bool = False, + round_trip: bool = False, + warnings: bool | Literal['none', 'warn', 'error'] = True, + fallback: Callable[[Any], Any] | None = None, + serialize_as_any: bool = False, + ) -> dict[str, Any]: + """!!! abstract "Usage Documentation" + [`model_dump`](../concepts/serialization.md#python-mode) + + Generate a dictionary representation of the model, optionally specifying which fields to include or exclude. + + Args: + mode: The mode in which `to_python` should run. + If mode is 'json', the output will only contain JSON serializable types. + If mode is 'python', the output may contain non-JSON-serializable Python objects. + include: A set of fields to include in the output. + exclude: A set of fields to exclude from the output. + context: Additional context to pass to the serializer. + by_alias: Whether to use the field's alias in the dictionary key if defined. + exclude_unset: Whether to exclude fields that have not been explicitly set. + exclude_defaults: Whether to exclude fields that are set to their default value. + exclude_none: Whether to exclude fields that have a value of `None`. + exclude_computed_fields: Whether to exclude computed fields. + While this can be useful for round-tripping, it is usually recommended to use the dedicated + `round_trip` parameter instead. + round_trip: If True, dumped values should be valid as input for non-idempotent types such as Json[T]. + warnings: How to handle serialization errors. False/"none" ignores them, True/"warn" logs errors, + "error" raises a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError]. + fallback: A function to call when an unknown value is encountered. If not provided, + a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError] error is raised. + serialize_as_any: Whether to serialize fields with duck-typing serialization behavior. + + Returns: + A dictionary representation of the model. + """ + return self.__pydantic_serializer__.to_python( + self, + mode=mode, + by_alias=by_alias, + include=include, + exclude=exclude, + context=context, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + exclude_computed_fields=exclude_computed_fields, + round_trip=round_trip, + warnings=warnings, + fallback=fallback, + serialize_as_any=serialize_as_any, + ) + + def model_dump_json( + self, + *, + indent: int | None = None, + ensure_ascii: bool = False, + include: IncEx | None = None, + exclude: IncEx | None = None, + context: Any | None = None, + by_alias: bool | None = None, + exclude_unset: bool = False, + exclude_defaults: bool = False, + exclude_none: bool = False, + exclude_computed_fields: bool = False, + round_trip: bool = False, + warnings: bool | Literal['none', 'warn', 'error'] = True, + fallback: Callable[[Any], Any] | None = None, + serialize_as_any: bool = False, + ) -> str: + """!!! abstract "Usage Documentation" + [`model_dump_json`](../concepts/serialization.md#json-mode) + + Generates a JSON representation of the model using Pydantic's `to_json` method. + + Args: + indent: Indentation to use in the JSON output. If None is passed, the output will be compact. + ensure_ascii: If `True`, the output is guaranteed to have all incoming non-ASCII characters escaped. + If `False` (the default), these characters will be output as-is. + include: Field(s) to include in the JSON output. + exclude: Field(s) to exclude from the JSON output. + context: Additional context to pass to the serializer. + by_alias: Whether to serialize using field aliases. + exclude_unset: Whether to exclude fields that have not been explicitly set. + exclude_defaults: Whether to exclude fields that are set to their default value. + exclude_none: Whether to exclude fields that have a value of `None`. + exclude_computed_fields: Whether to exclude computed fields. + While this can be useful for round-tripping, it is usually recommended to use the dedicated + `round_trip` parameter instead. + round_trip: If True, dumped values should be valid as input for non-idempotent types such as Json[T]. + warnings: How to handle serialization errors. False/"none" ignores them, True/"warn" logs errors, + "error" raises a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError]. + fallback: A function to call when an unknown value is encountered. If not provided, + a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError] error is raised. + serialize_as_any: Whether to serialize fields with duck-typing serialization behavior. + + Returns: + A JSON string representation of the model. + """ + return self.__pydantic_serializer__.to_json( + self, + indent=indent, + ensure_ascii=ensure_ascii, + include=include, + exclude=exclude, + context=context, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + exclude_computed_fields=exclude_computed_fields, + round_trip=round_trip, + warnings=warnings, + fallback=fallback, + serialize_as_any=serialize_as_any, + ).decode() + + @classmethod + def model_json_schema( + cls, + by_alias: bool = True, + ref_template: str = DEFAULT_REF_TEMPLATE, + schema_generator: type[GenerateJsonSchema] = GenerateJsonSchema, + mode: JsonSchemaMode = 'validation', + *, + union_format: Literal['any_of', 'primitive_type_array'] = 'any_of', + ) -> dict[str, Any]: + """Generates a JSON schema for a model class. + + Args: + by_alias: Whether to use attribute aliases or not. + ref_template: The reference template. + union_format: The format to use when combining schemas from unions together. Can be one of: + + - `'any_of'`: Use the [`anyOf`](https://json-schema.org/understanding-json-schema/reference/combining#anyOf) + keyword to combine schemas (the default). + - `'primitive_type_array'`: Use the [`type`](https://json-schema.org/understanding-json-schema/reference/type) + keyword as an array of strings, containing each type of the combination. If any of the schemas is not a primitive + type (`string`, `boolean`, `null`, `integer` or `number`) or contains constraints/metadata, falls back to + `any_of`. + schema_generator: To override the logic used to generate the JSON schema, as a subclass of + `GenerateJsonSchema` with your desired modifications + mode: The mode in which to generate the schema. + + Returns: + The JSON schema for the given model class. + """ + return model_json_schema( + cls, + by_alias=by_alias, + ref_template=ref_template, + union_format=union_format, + schema_generator=schema_generator, + mode=mode, + ) + + @classmethod + def model_parametrized_name(cls, params: tuple[type[Any], ...]) -> str: + """Compute the class name for parametrizations of generic classes. + + This method can be overridden to achieve a custom naming scheme for generic BaseModels. + + Args: + params: Tuple of types of the class. Given a generic class + `Model` with 2 type variables and a concrete model `Model[str, int]`, + the value `(str, int)` would be passed to `params`. + + Returns: + String representing the new class where `params` are passed to `cls` as type variables. + + Raises: + TypeError: Raised when trying to generate concrete names for non-generic models. + """ + if not issubclass(cls, Generic): + raise TypeError('Concrete names should only be generated for generic models.') + + # Any strings received should represent forward references, so we handle them specially below. + # If we eventually move toward wrapping them in a ForwardRef in __class_getitem__ in the future, + # we may be able to remove this special case. + param_names = [param if isinstance(param, str) else _repr.display_as_type(param) for param in params] + params_component = ', '.join(param_names) + return f'{cls.__name__}[{params_component}]' + + def model_post_init(self, context: Any, /) -> None: + """Override this method to perform additional initialization after `__init__` and `model_construct`. + This is useful if you want to do some validation that requires the entire model to be initialized. + """ + + @classmethod + def model_rebuild( + cls, + *, + force: bool = False, + raise_errors: bool = True, + _parent_namespace_depth: int = 2, + _types_namespace: MappingNamespace | None = None, + ) -> bool | None: + """Try to rebuild the pydantic-core schema for the model. + + This may be necessary when one of the annotations is a ForwardRef which could not be resolved during + the initial attempt to build the schema, and automatic rebuilding fails. + + Args: + force: Whether to force the rebuilding of the model schema, defaults to `False`. + raise_errors: Whether to raise errors, defaults to `True`. + _parent_namespace_depth: The depth level of the parent namespace, defaults to 2. + _types_namespace: The types namespace, defaults to `None`. + + Returns: + Returns `None` if the schema is already "complete" and rebuilding was not required. + If rebuilding _was_ required, returns `True` if rebuilding was successful, otherwise `False`. + """ + already_complete = cls.__pydantic_complete__ + if already_complete and not force: + return None + + cls.__pydantic_complete__ = False + + for attr in ('__pydantic_core_schema__', '__pydantic_validator__', '__pydantic_serializer__'): + if attr in cls.__dict__ and not isinstance(getattr(cls, attr), _mock_val_ser.MockValSer): + # Deleting the validator/serializer is necessary as otherwise they can get reused in + # pydantic-core. We do so only if they aren't mock instances, otherwise — as `model_rebuild()` + # isn't thread-safe — concurrent model instantiations can lead to the parent validator being used. + # Same applies for the core schema that can be reused in schema generation. + delattr(cls, attr) + + if _types_namespace is not None: + rebuild_ns = _types_namespace + elif _parent_namespace_depth > 0: + rebuild_ns = _typing_extra.parent_frame_namespace(parent_depth=_parent_namespace_depth, force=True) or {} + else: + rebuild_ns = {} + + parent_ns = _model_construction.unpack_lenient_weakvaluedict(cls.__pydantic_parent_namespace__) or {} + + ns_resolver = _namespace_utils.NsResolver( + parent_namespace={**rebuild_ns, **parent_ns}, + ) + + return _model_construction.complete_model_class( + cls, + _config.ConfigWrapper(cls.model_config, check=False), + ns_resolver, + raise_errors=raise_errors, + # If the model was already complete, we don't need to call the hook again. + call_on_complete_hook=not already_complete, + ) + + @classmethod + def model_validate( + cls, + obj: Any, + *, + strict: bool | None = None, + extra: ExtraValues | None = None, + from_attributes: bool | None = None, + context: Any | None = None, + by_alias: bool | None = None, + by_name: bool | None = None, + ) -> Self: + """Validate a pydantic model instance. + + Args: + obj: The object to validate. + strict: Whether to enforce types strictly. + extra: Whether to ignore, allow, or forbid extra data during model validation. + See the [`extra` configuration value][pydantic.ConfigDict.extra] for details. + from_attributes: Whether to extract data from object attributes. + context: Additional context to pass to the validator. + by_alias: Whether to use the field's alias when validating against the provided input data. + by_name: Whether to use the field's name when validating against the provided input data. + + Raises: + ValidationError: If the object could not be validated. + + Returns: + The validated model instance. + """ + # `__tracebackhide__` tells pytest and some other tools to omit this function from tracebacks + __tracebackhide__ = True + + if by_alias is False and by_name is not True: + raise PydanticUserError( + 'At least one of `by_alias` or `by_name` must be set to True.', + code='validate-by-alias-and-name-false', + ) + + return cls.__pydantic_validator__.validate_python( + obj, + strict=strict, + extra=extra, + from_attributes=from_attributes, + context=context, + by_alias=by_alias, + by_name=by_name, + ) + + @classmethod + def model_validate_json( + cls, + json_data: str | bytes | bytearray, + *, + strict: bool | None = None, + extra: ExtraValues | None = None, + context: Any | None = None, + by_alias: bool | None = None, + by_name: bool | None = None, + ) -> Self: + """!!! abstract "Usage Documentation" + [JSON Parsing](../concepts/json.md#json-parsing) + + Validate the given JSON data against the Pydantic model. + + Args: + json_data: The JSON data to validate. + strict: Whether to enforce types strictly. + extra: Whether to ignore, allow, or forbid extra data during model validation. + See the [`extra` configuration value][pydantic.ConfigDict.extra] for details. + context: Extra variables to pass to the validator. + by_alias: Whether to use the field's alias when validating against the provided input data. + by_name: Whether to use the field's name when validating against the provided input data. + + Returns: + The validated Pydantic model. + + Raises: + ValidationError: If `json_data` is not a JSON string or the object could not be validated. + """ + # `__tracebackhide__` tells pytest and some other tools to omit this function from tracebacks + __tracebackhide__ = True + + if by_alias is False and by_name is not True: + raise PydanticUserError( + 'At least one of `by_alias` or `by_name` must be set to True.', + code='validate-by-alias-and-name-false', + ) + + return cls.__pydantic_validator__.validate_json( + json_data, strict=strict, extra=extra, context=context, by_alias=by_alias, by_name=by_name + ) + + @classmethod + def model_validate_strings( + cls, + obj: Any, + *, + strict: bool | None = None, + extra: ExtraValues | None = None, + context: Any | None = None, + by_alias: bool | None = None, + by_name: bool | None = None, + ) -> Self: + """Validate the given object with string data against the Pydantic model. + + Args: + obj: The object containing string data to validate. + strict: Whether to enforce types strictly. + extra: Whether to ignore, allow, or forbid extra data during model validation. + See the [`extra` configuration value][pydantic.ConfigDict.extra] for details. + context: Extra variables to pass to the validator. + by_alias: Whether to use the field's alias when validating against the provided input data. + by_name: Whether to use the field's name when validating against the provided input data. + + Returns: + The validated Pydantic model. + """ + # `__tracebackhide__` tells pytest and some other tools to omit this function from tracebacks + __tracebackhide__ = True + + if by_alias is False and by_name is not True: + raise PydanticUserError( + 'At least one of `by_alias` or `by_name` must be set to True.', + code='validate-by-alias-and-name-false', + ) + + return cls.__pydantic_validator__.validate_strings( + obj, strict=strict, extra=extra, context=context, by_alias=by_alias, by_name=by_name + ) + + @classmethod + def __get_pydantic_core_schema__(cls, source: type[BaseModel], handler: GetCoreSchemaHandler, /) -> CoreSchema: + # This warning is only emitted when calling `super().__get_pydantic_core_schema__` from a model subclass. + # In the generate schema logic, this method (`BaseModel.__get_pydantic_core_schema__`) is special cased to + # *not* be called if not overridden. + warnings.warn( + 'The `__get_pydantic_core_schema__` method of the `BaseModel` class is deprecated. If you are calling ' + '`super().__get_pydantic_core_schema__` when overriding the method on a Pydantic model, consider using ' + '`handler(source)` instead. However, note that overriding this method on models can lead to unexpected ' + 'side effects.', + PydanticDeprecatedSince211, + stacklevel=2, + ) + # Logic copied over from `GenerateSchema._model_schema`: + schema = cls.__dict__.get('__pydantic_core_schema__') + if schema is not None and not isinstance(schema, _mock_val_ser.MockCoreSchema): + return cls.__pydantic_core_schema__ + + return handler(source) + + @classmethod + def __get_pydantic_json_schema__( + cls, + core_schema: CoreSchema, + handler: GetJsonSchemaHandler, + /, + ) -> JsonSchemaValue: + """Hook into generating the model's JSON schema. + + Args: + core_schema: A `pydantic-core` CoreSchema. + You can ignore this argument and call the handler with a new CoreSchema, + wrap this CoreSchema (`{'type': 'nullable', 'schema': current_schema}`), + or just call the handler with the original schema. + handler: Call into Pydantic's internal JSON schema generation. + This will raise a `pydantic.errors.PydanticInvalidForJsonSchema` if JSON schema + generation fails. + Since this gets called by `BaseModel.model_json_schema` you can override the + `schema_generator` argument to that function to change JSON schema generation globally + for a type. + + Returns: + A JSON schema, as a Python object. + """ + return handler(core_schema) + + @classmethod + def __pydantic_init_subclass__(cls, **kwargs: Any) -> None: + """This is intended to behave just like `__init_subclass__`, but is called by `ModelMetaclass` + only after basic class initialization is complete. In particular, attributes like `model_fields` will + be present when this is called, but forward annotations are not guaranteed to be resolved yet, + meaning that creating an instance of the class may fail. + + This is necessary because `__init_subclass__` will always be called by `type.__new__`, + and it would require a prohibitively large refactor to the `ModelMetaclass` to ensure that + `type.__new__` was called in such a manner that the class would already be sufficiently initialized. + + This will receive the same `kwargs` that would be passed to the standard `__init_subclass__`, namely, + any kwargs passed to the class definition that aren't used internally by Pydantic. + + Args: + **kwargs: Any keyword arguments passed to the class definition that aren't used internally + by Pydantic. + + Note: + You may want to override [`__pydantic_on_complete__()`][pydantic.main.BaseModel.__pydantic_on_complete__] + instead, which is called once the class and its fields are fully initialized and ready for validation. + """ + + @classmethod + def __pydantic_on_complete__(cls) -> None: + """This is called once the class and its fields are fully initialized and ready to be used. + + This typically happens when the class is created (just before + [`__pydantic_init_subclass__()`][pydantic.main.BaseModel.__pydantic_init_subclass__] is called on the superclass), + except when forward annotations are used that could not immediately be resolved. + In that case, it will be called later, when the model is rebuilt automatically or explicitly using + [`model_rebuild()`][pydantic.main.BaseModel.model_rebuild]. + """ + + def __class_getitem__( + cls, typevar_values: type[Any] | tuple[type[Any], ...] + ) -> type[BaseModel] | _forward_ref.PydanticRecursiveRef: + cached = _generics.get_cached_generic_type_early(cls, typevar_values) + if cached is not None: + return cached + + if cls is BaseModel: + raise TypeError('Type parameters should be placed on typing.Generic, not BaseModel') + if not hasattr(cls, '__parameters__'): + raise TypeError(f'{cls} cannot be parametrized because it does not inherit from typing.Generic') + if not cls.__pydantic_generic_metadata__['parameters'] and Generic not in cls.__bases__: + raise TypeError(f'{cls} is not a generic class') + + if not isinstance(typevar_values, tuple): + typevar_values = (typevar_values,) + + # For a model `class Model[T, U, V = int](BaseModel): ...` parametrized with `(str, bool)`, + # this gives us `{T: str, U: bool, V: int}`: + typevars_map = _generics.map_generic_model_arguments(cls, typevar_values) + # We also update the provided args to use defaults values (`(str, bool)` becomes `(str, bool, int)`): + typevar_values = tuple(v for v in typevars_map.values()) + + if _utils.all_identical(typevars_map.keys(), typevars_map.values()) and typevars_map: + submodel = cls # if arguments are equal to parameters it's the same object + _generics.set_cached_generic_type(cls, typevar_values, submodel) + else: + parent_args = cls.__pydantic_generic_metadata__['args'] + if not parent_args: + args = typevar_values + else: + args = tuple(_generics.replace_types(arg, typevars_map) for arg in parent_args) + + origin = cls.__pydantic_generic_metadata__['origin'] or cls + model_name = origin.model_parametrized_name(args) + params = tuple( + dict.fromkeys(_generics.iter_contained_typevars(typevars_map.values())) + ) # use dict as ordered set + + with _generics.generic_recursion_self_type(origin, args) as maybe_self_type: + cached = _generics.get_cached_generic_type_late(cls, typevar_values, origin, args) + if cached is not None: + return cached + + if maybe_self_type is not None: + return maybe_self_type + + # Attempt to rebuild the origin in case new types have been defined + try: + # depth 2 gets you above this __class_getitem__ call. + # Note that we explicitly provide the parent ns, otherwise + # `model_rebuild` will use the parent ns no matter if it is the ns of a module. + # We don't want this here, as this has unexpected effects when a model + # is being parametrized during a forward annotation evaluation. + parent_ns = _typing_extra.parent_frame_namespace(parent_depth=2) or {} + origin.model_rebuild(_types_namespace=parent_ns) + except PydanticUndefinedAnnotation: + # It's okay if it fails, it just means there are still undefined types + # that could be evaluated later. + pass + + submodel = _generics.create_generic_submodel(model_name, origin, args, params) + + _generics.set_cached_generic_type(cls, typevar_values, submodel, origin, args) + + return submodel + + def __copy__(self) -> Self: + """Returns a shallow copy of the model.""" + cls = type(self) + m = cls.__new__(cls) + _object_setattr(m, '__dict__', copy(self.__dict__)) + _object_setattr(m, '__pydantic_extra__', copy(self.__pydantic_extra__)) + _object_setattr(m, '__pydantic_fields_set__', copy(self.__pydantic_fields_set__)) + + if not hasattr(self, '__pydantic_private__') or self.__pydantic_private__ is None: + _object_setattr(m, '__pydantic_private__', None) + else: + _object_setattr( + m, + '__pydantic_private__', + {k: v for k, v in self.__pydantic_private__.items() if v is not PydanticUndefined}, + ) + + return m + + def __deepcopy__(self, memo: dict[int, Any] | None = None) -> Self: + """Returns a deep copy of the model.""" + cls = type(self) + m = cls.__new__(cls) + _object_setattr(m, '__dict__', deepcopy(self.__dict__, memo=memo)) + _object_setattr(m, '__pydantic_extra__', deepcopy(self.__pydantic_extra__, memo=memo)) + # This next line doesn't need a deepcopy because __pydantic_fields_set__ is a set[str], + # and attempting a deepcopy would be marginally slower. + _object_setattr(m, '__pydantic_fields_set__', copy(self.__pydantic_fields_set__)) + + if not hasattr(self, '__pydantic_private__') or self.__pydantic_private__ is None: + _object_setattr(m, '__pydantic_private__', None) + else: + _object_setattr( + m, + '__pydantic_private__', + deepcopy({k: v for k, v in self.__pydantic_private__.items() if v is not PydanticUndefined}, memo=memo), + ) + + return m + + if not TYPE_CHECKING: + # We put `__getattr__` in a non-TYPE_CHECKING block because otherwise, mypy allows arbitrary attribute access + # The same goes for __setattr__ and __delattr__, see: https://github.com/pydantic/pydantic/issues/8643 + + def __getattr__(self, item: str) -> Any: + private_attributes = object.__getattribute__(self, '__private_attributes__') + if item in private_attributes: + attribute = private_attributes[item] + if hasattr(attribute, '__get__'): + return attribute.__get__(self, type(self)) # type: ignore + + try: + # Note: self.__pydantic_private__ cannot be None if self.__private_attributes__ has items + return self.__pydantic_private__[item] # type: ignore + except KeyError as exc: + raise AttributeError(f'{type(self).__name__!r} object has no attribute {item!r}') from exc + else: + # `__pydantic_extra__` can fail to be set if the model is not yet fully initialized. + # See `BaseModel.__repr_args__` for more details + try: + pydantic_extra = object.__getattribute__(self, '__pydantic_extra__') + except AttributeError: + pydantic_extra = None + + if pydantic_extra and item in pydantic_extra: + return pydantic_extra[item] + else: + if hasattr(self.__class__, item): + return super().__getattribute__(item) # Raises AttributeError if appropriate + else: + # this is the current error + raise AttributeError(f'{type(self).__name__!r} object has no attribute {item!r}') + + def __setattr__(self, name: str, value: Any) -> None: + if (setattr_handler := self.__pydantic_setattr_handlers__.get(name)) is not None: + setattr_handler(self, name, value) + # if None is returned from _setattr_handler, the attribute was set directly + elif (setattr_handler := self._setattr_handler(name, value)) is not None: + setattr_handler(self, name, value) # call here to not memo on possibly unknown fields + self.__pydantic_setattr_handlers__[name] = setattr_handler # memoize the handler for faster access + + def _setattr_handler(self, name: str, value: Any) -> Callable[[BaseModel, str, Any], None] | None: + """Get a handler for setting an attribute on the model instance. + + Returns: + A handler for setting an attribute on the model instance. Used for memoization of the handler. + Memoizing the handlers leads to a dramatic performance improvement in `__setattr__` + Returns `None` when memoization is not safe, then the attribute is set directly. + """ + cls = self.__class__ + if name in cls.__class_vars__: + raise AttributeError( + f'{name!r} is a ClassVar of `{cls.__name__}` and cannot be set on an instance. ' + f'If you want to set a value on the class, use `{cls.__name__}.{name} = value`.' + ) + elif not _fields.is_valid_field_name(name): + if (attribute := cls.__private_attributes__.get(name)) is not None: + if hasattr(attribute, '__set__'): + return lambda model, _name, val: attribute.__set__(model, val) + else: + return _SIMPLE_SETATTR_HANDLERS['private'] + else: + _object_setattr(self, name, value) + return None # Can not return memoized handler with possibly freeform attr names + + attr = getattr(cls, name, None) + # NOTE: We currently special case properties and `cached_property`, but we might need + # to generalize this to all data/non-data descriptors at some point. For non-data descriptors + # (such as `cached_property`), it isn't obvious though. `cached_property` caches the value + # to the instance's `__dict__`, but other non-data descriptors might do things differently. + if isinstance(attr, cached_property): + return _SIMPLE_SETATTR_HANDLERS['cached_property'] + + _check_frozen(cls, name, value) + + # We allow properties to be set only on non frozen models for now (to match dataclasses). + # This can be changed if it ever gets requested. + if isinstance(attr, property): + return lambda model, _name, val: attr.__set__(model, val) + elif cls.model_config.get('validate_assignment'): + return _SIMPLE_SETATTR_HANDLERS['validate_assignment'] + elif name not in cls.__pydantic_fields__: + if cls.model_config.get('extra') != 'allow': + # TODO - matching error + raise ValueError(f'"{cls.__name__}" object has no field "{name}"') + elif attr is None: + # attribute does not exist, so put it in extra + self.__pydantic_extra__[name] = value + return None # Can not return memoized handler with possibly freeform attr names + else: + # attribute _does_ exist, and was not in extra, so update it + return _SIMPLE_SETATTR_HANDLERS['extra_known'] + else: + return _SIMPLE_SETATTR_HANDLERS['model_field'] + + def __delattr__(self, item: str) -> Any: + cls = self.__class__ + + if item in self.__private_attributes__: + attribute = self.__private_attributes__[item] + if hasattr(attribute, '__delete__'): + attribute.__delete__(self) # type: ignore + return + + try: + # Note: self.__pydantic_private__ cannot be None if self.__private_attributes__ has items + del self.__pydantic_private__[item] # type: ignore + return + except KeyError as exc: + raise AttributeError(f'{cls.__name__!r} object has no attribute {item!r}') from exc + + # Allow cached properties to be deleted (even if the class is frozen): + attr = getattr(cls, item, None) + if isinstance(attr, cached_property): + return object.__delattr__(self, item) + + _check_frozen(cls, name=item, value=None) + + if item in self.__pydantic_fields__: + object.__delattr__(self, item) + elif self.__pydantic_extra__ is not None and item in self.__pydantic_extra__: + del self.__pydantic_extra__[item] + else: + try: + object.__delattr__(self, item) + except AttributeError: + raise AttributeError(f'{type(self).__name__!r} object has no attribute {item!r}') + + # Because we make use of `@dataclass_transform()`, `__replace__` is already synthesized by + # type checkers, so we define the implementation in this `if not TYPE_CHECKING:` block: + def __replace__(self, **changes: Any) -> Self: + return self.model_copy(update=changes) + + def __getstate__(self) -> dict[Any, Any]: + private = self.__pydantic_private__ + if private: + private = {k: v for k, v in private.items() if v is not PydanticUndefined} + return { + '__dict__': self.__dict__, + '__pydantic_extra__': self.__pydantic_extra__, + '__pydantic_fields_set__': self.__pydantic_fields_set__, + '__pydantic_private__': private, + } + + def __setstate__(self, state: dict[Any, Any]) -> None: + _object_setattr(self, '__pydantic_fields_set__', state.get('__pydantic_fields_set__', {})) + _object_setattr(self, '__pydantic_extra__', state.get('__pydantic_extra__', {})) + _object_setattr(self, '__pydantic_private__', state.get('__pydantic_private__', {})) + _object_setattr(self, '__dict__', state.get('__dict__', {})) + + if not TYPE_CHECKING: + + def __eq__(self, other: Any) -> bool: + if isinstance(other, BaseModel): + # When comparing instances of generic types for equality, as long as all field values are equal, + # only require their generic origin types to be equal, rather than exact type equality. + # This prevents headaches like MyGeneric(x=1) != MyGeneric[Any](x=1). + self_type = self.__pydantic_generic_metadata__['origin'] or self.__class__ + other_type = other.__pydantic_generic_metadata__['origin'] or other.__class__ + + # Perform common checks first + if not ( + self_type == other_type + and getattr(self, '__pydantic_private__', None) == getattr(other, '__pydantic_private__', None) + and self.__pydantic_extra__ == other.__pydantic_extra__ + ): + return False + + # We only want to compare pydantic fields but ignoring fields is costly. + # We'll perform a fast check first, and fallback only when needed + # See GH-7444 and GH-7825 for rationale and a performance benchmark + + # First, do the fast (and sometimes faulty) __dict__ comparison + if self.__dict__ == other.__dict__: + # If the check above passes, then pydantic fields are equal, we can return early + return True + + # We don't want to trigger unnecessary costly filtering of __dict__ on all unequal objects, so we return + # early if there are no keys to ignore (we would just return False later on anyway) + model_fields = type(self).__pydantic_fields__.keys() + if self.__dict__.keys() <= model_fields and other.__dict__.keys() <= model_fields: + return False + + # If we reach here, there are non-pydantic-fields keys, mapped to unequal values, that we need to ignore + # Resort to costly filtering of the __dict__ objects + # We use operator.itemgetter because it is much faster than dict comprehensions + # NOTE: Contrary to standard python class and instances, when the Model class has a default value for an + # attribute and the model instance doesn't have a corresponding attribute, accessing the missing attribute + # raises an error in BaseModel.__getattr__ instead of returning the class attribute + # So we can use operator.itemgetter() instead of operator.attrgetter() + getter = operator.itemgetter(*model_fields) if model_fields else lambda _: _utils._SENTINEL + try: + return getter(self.__dict__) == getter(other.__dict__) + except KeyError: + # In rare cases (such as when using the deprecated BaseModel.copy() method), + # the __dict__ may not contain all model fields, which is how we can get here. + # getter(self.__dict__) is much faster than any 'safe' method that accounts + # for missing keys, and wrapping it in a `try` doesn't slow things down much + # in the common case. + self_fields_proxy = _utils.SafeGetItemProxy(self.__dict__) + other_fields_proxy = _utils.SafeGetItemProxy(other.__dict__) + return getter(self_fields_proxy) == getter(other_fields_proxy) + + # other instance is not a BaseModel + else: + return NotImplemented # delegate to the other item in the comparison + + if TYPE_CHECKING: + # We put `__init_subclass__` in a TYPE_CHECKING block because, even though we want the type-checking benefits + # described in the signature of `__init_subclass__` below, we don't want to modify the default behavior of + # subclass initialization. + + def __init_subclass__(cls, **kwargs: Unpack[ConfigDict]): + """This signature is included purely to help type-checkers check arguments to class declaration, which + provides a way to conveniently set model_config key/value pairs. + + ```python + from pydantic import BaseModel + + class MyModel(BaseModel, extra='allow'): ... + ``` + + However, this may be deceiving, since the _actual_ calls to `__init_subclass__` will not receive any + of the config arguments, and will only receive any keyword arguments passed during class initialization + that are _not_ expected keys in ConfigDict. (This is due to the way `ModelMetaclass.__new__` works.) + + Args: + **kwargs: Keyword arguments passed to the class definition, which set model_config + + Note: + You may want to override `__pydantic_init_subclass__` instead, which behaves similarly but is called + *after* the class is fully initialized. + """ + + def __iter__(self) -> TupleGenerator: + """So `dict(model)` works.""" + yield from [(k, v) for (k, v) in self.__dict__.items() if not k.startswith('_')] + extra = self.__pydantic_extra__ + if extra: + yield from extra.items() + + def __repr__(self) -> str: + return f'{self.__repr_name__()}({self.__repr_str__(", ")})' + + def __repr_args__(self) -> _repr.ReprArgs: + # Eagerly create the repr of computed fields, as this may trigger access of cached properties and as such + # modify the instance's `__dict__`. If we don't do it now, it could happen when iterating over the `__dict__` + # below if the instance happens to be referenced in a field, and would modify the `__dict__` size *during* iteration. + computed_fields_repr_args = [ + (k, getattr(self, k)) for k, v in self.__pydantic_computed_fields__.items() if v.repr + ] + + for k, v in self.__dict__.items(): + field = self.__pydantic_fields__.get(k) + if field and field.repr: + if v is not self: + yield k, v + else: + yield k, self.__repr_recursion__(v) + # `__pydantic_extra__` can fail to be set if the model is not yet fully initialized. + # This can happen if a `ValidationError` is raised during initialization and the instance's + # repr is generated as part of the exception handling. Therefore, we use `getattr` here + # with a fallback, even though the type hints indicate the attribute will always be present. + try: + pydantic_extra = object.__getattribute__(self, '__pydantic_extra__') + except AttributeError: + pydantic_extra = None + + if pydantic_extra is not None: + yield from ((k, v) for k, v in pydantic_extra.items()) + yield from computed_fields_repr_args + + # take logic from `_repr.Representation` without the side effects of inheritance, see #5740 + __repr_name__ = _repr.Representation.__repr_name__ + __repr_recursion__ = _repr.Representation.__repr_recursion__ + __repr_str__ = _repr.Representation.__repr_str__ + __pretty__ = _repr.Representation.__pretty__ + __rich_repr__ = _repr.Representation.__rich_repr__ + + def __str__(self) -> str: + return self.__repr_str__(' ') + + # ##### Deprecated methods from v1 ##### + @property + @typing_extensions.deprecated( + 'The `__fields__` attribute is deprecated, use the `model_fields` class property instead.', category=None + ) + def __fields__(self) -> dict[str, FieldInfo]: + warnings.warn( + 'The `__fields__` attribute is deprecated, use the `model_fields` class property instead.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + return getattr(type(self), '__pydantic_fields__', {}) + + @property + @typing_extensions.deprecated( + 'The `__fields_set__` attribute is deprecated, use `model_fields_set` instead.', + category=None, + ) + def __fields_set__(self) -> set[str]: + warnings.warn( + 'The `__fields_set__` attribute is deprecated, use `model_fields_set` instead.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + return self.__pydantic_fields_set__ + + @typing_extensions.deprecated('The `dict` method is deprecated; use `model_dump` instead.', category=None) + def dict( # noqa: D102 + self, + *, + include: IncEx | None = None, + exclude: IncEx | None = None, + by_alias: bool = False, + exclude_unset: bool = False, + exclude_defaults: bool = False, + exclude_none: bool = False, + ) -> Dict[str, Any]: # noqa UP006 + warnings.warn( + 'The `dict` method is deprecated; use `model_dump` instead.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + return self.model_dump( + include=include, + exclude=exclude, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + + @typing_extensions.deprecated('The `json` method is deprecated; use `model_dump_json` instead.', category=None) + def json( # noqa: D102 + self, + *, + include: IncEx | None = None, + exclude: IncEx | None = None, + by_alias: bool = False, + exclude_unset: bool = False, + exclude_defaults: bool = False, + exclude_none: bool = False, + encoder: Callable[[Any], Any] | None = PydanticUndefined, # type: ignore[assignment] + models_as_dict: bool = PydanticUndefined, # type: ignore[assignment] + **dumps_kwargs: Any, + ) -> str: + warnings.warn( + 'The `json` method is deprecated; use `model_dump_json` instead.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + if encoder is not PydanticUndefined: + raise TypeError('The `encoder` argument is no longer supported; use field serializers instead.') + if models_as_dict is not PydanticUndefined: + raise TypeError('The `models_as_dict` argument is no longer supported; use a model serializer instead.') + if dumps_kwargs: + raise TypeError('`dumps_kwargs` keyword arguments are no longer supported.') + return self.model_dump_json( + include=include, + exclude=exclude, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + + @classmethod + @typing_extensions.deprecated('The `parse_obj` method is deprecated; use `model_validate` instead.', category=None) + def parse_obj(cls, obj: Any) -> Self: # noqa: D102 + warnings.warn( + 'The `parse_obj` method is deprecated; use `model_validate` instead.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + return cls.model_validate(obj) + + @classmethod + @typing_extensions.deprecated( + 'The `parse_raw` method is deprecated; if your data is JSON use `model_validate_json`, ' + 'otherwise load the data then use `model_validate` instead.', + category=None, + ) + def parse_raw( # noqa: D102 + cls, + b: str | bytes, + *, + content_type: str | None = None, + encoding: str = 'utf8', + proto: DeprecatedParseProtocol | None = None, + allow_pickle: bool = False, + ) -> Self: # pragma: no cover + warnings.warn( + 'The `parse_raw` method is deprecated; if your data is JSON use `model_validate_json`, ' + 'otherwise load the data then use `model_validate` instead.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + from .deprecated import parse + + try: + obj = parse.load_str_bytes( + b, + proto=proto, + content_type=content_type, + encoding=encoding, + allow_pickle=allow_pickle, + ) + except (ValueError, TypeError) as exc: + import json + + # try to match V1 + if isinstance(exc, UnicodeDecodeError): + type_str = 'value_error.unicodedecode' + elif isinstance(exc, json.JSONDecodeError): + type_str = 'value_error.jsondecode' + elif isinstance(exc, ValueError): + type_str = 'value_error' + else: + type_str = 'type_error' + + # ctx is missing here, but since we've added `input` to the error, we're not pretending it's the same + error: pydantic_core.InitErrorDetails = { + # The type: ignore on the next line is to ignore the requirement of LiteralString + 'type': pydantic_core.PydanticCustomError(type_str, str(exc)), # type: ignore + 'loc': ('__root__',), + 'input': b, + } + raise pydantic_core.ValidationError.from_exception_data(cls.__name__, [error]) + return cls.model_validate(obj) + + @classmethod + @typing_extensions.deprecated( + 'The `parse_file` method is deprecated; load the data from file, then if your data is JSON ' + 'use `model_validate_json`, otherwise `model_validate` instead.', + category=None, + ) + def parse_file( # noqa: D102 + cls, + path: str | Path, + *, + content_type: str | None = None, + encoding: str = 'utf8', + proto: DeprecatedParseProtocol | None = None, + allow_pickle: bool = False, + ) -> Self: + warnings.warn( + 'The `parse_file` method is deprecated; load the data from file, then if your data is JSON ' + 'use `model_validate_json`, otherwise `model_validate` instead.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + from .deprecated import parse + + obj = parse.load_file( + path, + proto=proto, + content_type=content_type, + encoding=encoding, + allow_pickle=allow_pickle, + ) + return cls.parse_obj(obj) + + @classmethod + @typing_extensions.deprecated( + 'The `from_orm` method is deprecated; set ' + "`model_config['from_attributes']=True` and use `model_validate` instead.", + category=None, + ) + def from_orm(cls, obj: Any) -> Self: # noqa: D102 + warnings.warn( + 'The `from_orm` method is deprecated; set ' + "`model_config['from_attributes']=True` and use `model_validate` instead.", + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + if not cls.model_config.get('from_attributes', None): + raise PydanticUserError( + 'You must set the config attribute `from_attributes=True` to use from_orm', code=None + ) + return cls.model_validate(obj) + + @classmethod + @typing_extensions.deprecated('The `construct` method is deprecated; use `model_construct` instead.', category=None) + def construct(cls, _fields_set: set[str] | None = None, **values: Any) -> Self: # noqa: D102 + warnings.warn( + 'The `construct` method is deprecated; use `model_construct` instead.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + return cls.model_construct(_fields_set=_fields_set, **values) + + @typing_extensions.deprecated( + 'The `copy` method is deprecated; use `model_copy` instead. ' + 'See the docstring of `BaseModel.copy` for details about how to handle `include` and `exclude`.', + category=None, + ) + def copy( + self, + *, + include: AbstractSetIntStr | MappingIntStrAny | None = None, + exclude: AbstractSetIntStr | MappingIntStrAny | None = None, + update: Dict[str, Any] | None = None, # noqa UP006 + deep: bool = False, + ) -> Self: # pragma: no cover + """Returns a copy of the model. + + !!! warning "Deprecated" + This method is now deprecated; use `model_copy` instead. + + If you need `include` or `exclude`, use: + + ```python {test="skip" lint="skip"} + data = self.model_dump(include=include, exclude=exclude, round_trip=True) + data = {**data, **(update or {})} + copied = self.model_validate(data) + ``` + + Args: + include: Optional set or mapping specifying which fields to include in the copied model. + exclude: Optional set or mapping specifying which fields to exclude in the copied model. + update: Optional dictionary of field-value pairs to override field values in the copied model. + deep: If True, the values of fields that are Pydantic models will be deep-copied. + + Returns: + A copy of the model with included, excluded and updated fields as specified. + """ + warnings.warn( + 'The `copy` method is deprecated; use `model_copy` instead. ' + 'See the docstring of `BaseModel.copy` for details about how to handle `include` and `exclude`.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + from .deprecated import copy_internals + + values = dict( + copy_internals._iter( + self, to_dict=False, by_alias=False, include=include, exclude=exclude, exclude_unset=False + ), + **(update or {}), + ) + if self.__pydantic_private__ is None: + private = None + else: + private = {k: v for k, v in self.__pydantic_private__.items() if v is not PydanticUndefined} + + if self.__pydantic_extra__ is None: + extra: dict[str, Any] | None = None + else: + extra = self.__pydantic_extra__.copy() + for k in list(self.__pydantic_extra__): + if k not in values: # k was in the exclude + extra.pop(k) + for k in list(values): + if k in self.__pydantic_extra__: # k must have come from extra + extra[k] = values.pop(k) + + # new `__pydantic_fields_set__` can have unset optional fields with a set value in `update` kwarg + if update: + fields_set = self.__pydantic_fields_set__ | update.keys() + else: + fields_set = set(self.__pydantic_fields_set__) + + # removing excluded fields from `__pydantic_fields_set__` + if exclude: + fields_set -= set(exclude) + + return copy_internals._copy_and_set_values(self, values, fields_set, extra, private, deep=deep) + + @classmethod + @typing_extensions.deprecated('The `schema` method is deprecated; use `model_json_schema` instead.', category=None) + def schema( # noqa: D102 + cls, by_alias: bool = True, ref_template: str = DEFAULT_REF_TEMPLATE + ) -> Dict[str, Any]: # noqa UP006 + warnings.warn( + 'The `schema` method is deprecated; use `model_json_schema` instead.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + return cls.model_json_schema(by_alias=by_alias, ref_template=ref_template) + + @classmethod + @typing_extensions.deprecated( + 'The `schema_json` method is deprecated; use `model_json_schema` and json.dumps instead.', + category=None, + ) + def schema_json( # noqa: D102 + cls, *, by_alias: bool = True, ref_template: str = DEFAULT_REF_TEMPLATE, **dumps_kwargs: Any + ) -> str: # pragma: no cover + warnings.warn( + 'The `schema_json` method is deprecated; use `model_json_schema` and json.dumps instead.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + import json + + from .deprecated.json import pydantic_encoder + + return json.dumps( + cls.model_json_schema(by_alias=by_alias, ref_template=ref_template), + default=pydantic_encoder, + **dumps_kwargs, + ) + + @classmethod + @typing_extensions.deprecated('The `validate` method is deprecated; use `model_validate` instead.', category=None) + def validate(cls, value: Any) -> Self: # noqa: D102 + warnings.warn( + 'The `validate` method is deprecated; use `model_validate` instead.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + return cls.model_validate(value) + + @classmethod + @typing_extensions.deprecated( + 'The `update_forward_refs` method is deprecated; use `model_rebuild` instead.', + category=None, + ) + def update_forward_refs(cls, **localns: Any) -> None: # noqa: D102 + warnings.warn( + 'The `update_forward_refs` method is deprecated; use `model_rebuild` instead.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + if localns: # pragma: no cover + raise TypeError('`localns` arguments are not longer accepted.') + cls.model_rebuild(force=True) + + @typing_extensions.deprecated( + 'The private method `_iter` will be removed and should no longer be used.', category=None + ) + def _iter(self, *args: Any, **kwargs: Any) -> Any: + warnings.warn( + 'The private method `_iter` will be removed and should no longer be used.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + from .deprecated import copy_internals + + return copy_internals._iter(self, *args, **kwargs) + + @typing_extensions.deprecated( + 'The private method `_copy_and_set_values` will be removed and should no longer be used.', + category=None, + ) + def _copy_and_set_values(self, *args: Any, **kwargs: Any) -> Any: + warnings.warn( + 'The private method `_copy_and_set_values` will be removed and should no longer be used.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + from .deprecated import copy_internals + + return copy_internals._copy_and_set_values(self, *args, **kwargs) + + @classmethod + @typing_extensions.deprecated( + 'The private method `_get_value` will be removed and should no longer be used.', + category=None, + ) + def _get_value(cls, *args: Any, **kwargs: Any) -> Any: + warnings.warn( + 'The private method `_get_value` will be removed and should no longer be used.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + from .deprecated import copy_internals + + return copy_internals._get_value(cls, *args, **kwargs) + + @typing_extensions.deprecated( + 'The private method `_calculate_keys` will be removed and should no longer be used.', + category=None, + ) + def _calculate_keys(self, *args: Any, **kwargs: Any) -> Any: + warnings.warn( + 'The private method `_calculate_keys` will be removed and should no longer be used.', + category=PydanticDeprecatedSince20, + stacklevel=2, + ) + from .deprecated import copy_internals + + return copy_internals._calculate_keys(self, *args, **kwargs) + + +ModelT = TypeVar('ModelT', bound=BaseModel) + + +@overload +def create_model( + model_name: str, + /, + *, + __config__: ConfigDict | None = None, + __doc__: str | None = None, + __base__: None = None, + __module__: str = __name__, + __validators__: dict[str, Callable[..., Any]] | None = None, + __cls_kwargs__: dict[str, Any] | None = None, + __qualname__: str | None = None, + **field_definitions: Any | tuple[str, Any], +) -> type[BaseModel]: ... + + +@overload +def create_model( + model_name: str, + /, + *, + __config__: ConfigDict | None = None, + __doc__: str | None = None, + __base__: type[ModelT] | tuple[type[ModelT], ...], + __module__: str = __name__, + __validators__: dict[str, Callable[..., Any]] | None = None, + __cls_kwargs__: dict[str, Any] | None = None, + __qualname__: str | None = None, + **field_definitions: Any | tuple[str, Any], +) -> type[ModelT]: ... + + +def create_model( # noqa: C901 + model_name: str, + /, + *, + __config__: ConfigDict | None = None, + __doc__: str | None = None, + __base__: type[ModelT] | tuple[type[ModelT], ...] | None = None, + __module__: str | None = None, + __validators__: dict[str, Callable[..., Any]] | None = None, + __cls_kwargs__: dict[str, Any] | None = None, + __qualname__: str | None = None, + # TODO PEP 747: replace `Any` by the TypeForm: + **field_definitions: Any | tuple[str, Any], +) -> type[ModelT]: + """!!! abstract "Usage Documentation" + [Dynamic Model Creation](../concepts/models.md#dynamic-model-creation) + + Dynamically creates and returns a new Pydantic model, in other words, `create_model` dynamically creates a + subclass of [`BaseModel`][pydantic.BaseModel]. + + !!! warning + This function may execute arbitrary code contained in field annotations, if string references need to be evaluated. + + See [Security implications of introspecting annotations](https://docs.python.org/3/library/annotationlib.html#annotationlib-security) for more information. + + Args: + model_name: The name of the newly created model. + __config__: The configuration of the new model. + __doc__: The docstring of the new model. + __base__: The base class or classes for the new model. + __module__: The name of the module that the model belongs to; + if `None`, the value is taken from `sys._getframe(1)` + __validators__: A dictionary of methods that validate fields. The keys are the names of the validation methods to + be added to the model, and the values are the validation methods themselves. You can read more about functional + validators [here](https://docs.pydantic.dev/2.9/concepts/validators/#field-validators). + __cls_kwargs__: A dictionary of keyword arguments for class creation, such as `metaclass`. + __qualname__: The qualified name of the newly created model. + **field_definitions: Field definitions of the new model. Either: + + - a single element, representing the type annotation of the field. + - a two-tuple, the first element being the type and the second element the assigned value + (either a default or the [`Field()`][pydantic.Field] function). + + Returns: + The new [model][pydantic.BaseModel]. + + Raises: + PydanticUserError: If `__base__` and `__config__` are both passed. + """ + if __base__ is None: + __base__ = (cast('type[ModelT]', BaseModel),) + elif not isinstance(__base__, tuple): + __base__ = (__base__,) + + __cls_kwargs__ = __cls_kwargs__ or {} + + fields: dict[str, Any] = {} + annotations: dict[str, Any] = {} + + for f_name, f_def in field_definitions.items(): + if isinstance(f_def, tuple): + if len(f_def) != 2: + raise PydanticUserError( + f'Field definition for {f_name!r} should a single element representing the type or a two-tuple, the first element ' + 'being the type and the second element the assigned value (either a default or the `Field()` function).', + code='create-model-field-definitions', + ) + + annotations[f_name] = f_def[0] + fields[f_name] = f_def[1] + else: + annotations[f_name] = f_def + + if __module__ is None: + f = sys._getframe(1) + __module__ = f.f_globals['__name__'] + + namespace: dict[str, Any] = {'__annotations__': annotations, '__module__': __module__} + if __doc__: + namespace['__doc__'] = __doc__ + if __qualname__ is not None: + namespace['__qualname__'] = __qualname__ + if __validators__: + namespace.update(__validators__) + namespace.update(fields) + if __config__: + namespace['model_config'] = __config__ + resolved_bases = types.resolve_bases(__base__) + meta, ns, kwds = types.prepare_class(model_name, resolved_bases, kwds=__cls_kwargs__) + if resolved_bases is not __base__: + ns['__orig_bases__'] = __base__ + namespace.update(ns) + + return meta( + model_name, + resolved_bases, + namespace, + __pydantic_reset_parent_namespace__=False, + _create_model_module=__module__, + **kwds, + ) + + +__getattr__ = getattr_migration(__name__) diff --git a/backend/.venv/Lib/site-packages/pydantic/mypy.py b/backend/.venv/Lib/site-packages/pydantic/mypy.py new file mode 100644 index 0000000..6e8228e --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/mypy.py @@ -0,0 +1,1374 @@ +"""This module includes classes and functions designed specifically for use with the mypy plugin.""" + +from __future__ import annotations + +import sys +from collections.abc import Iterator +from configparser import ConfigParser +from typing import Any, Callable + +from mypy.errorcodes import ErrorCode +from mypy.expandtype import expand_type, expand_type_by_instance +from mypy.nodes import ( + ARG_NAMED, + ARG_NAMED_OPT, + ARG_OPT, + ARG_POS, + ARG_STAR2, + INVARIANT, + MDEF, + Argument, + AssignmentStmt, + Block, + CallExpr, + ClassDef, + Context, + Decorator, + DictExpr, + EllipsisExpr, + Expression, + FuncDef, + IfStmt, + JsonDict, + MemberExpr, + NameExpr, + PassStmt, + PlaceholderNode, + RefExpr, + Statement, + StrExpr, + SymbolTableNode, + TempNode, + TypeAlias, + TypeInfo, + Var, +) +from mypy.options import Options +from mypy.plugin import ( + CheckerPluginInterface, + ClassDefContext, + MethodContext, + Plugin, + ReportConfigContext, + SemanticAnalyzerPluginInterface, +) +from mypy.plugins.common import ( + deserialize_and_fixup_type, +) +from mypy.semanal import set_callable_name +from mypy.server.trigger import make_wildcard_trigger +from mypy.state import state +from mypy.type_visitor import TypeTranslator +from mypy.typeops import map_type_from_supertype +from mypy.types import ( + AnyType, + CallableType, + Instance, + NoneType, + Type, + TypeOfAny, + TypeType, + TypeVarType, + UnionType, + get_proper_type, +) +from mypy.typevars import fill_typevars +from mypy.util import get_unique_redefinition_name +from mypy.version import __version__ as mypy_version + +from pydantic._internal import _fields +from pydantic.version import parse_mypy_version + +CONFIGFILE_KEY = 'pydantic-mypy' +METADATA_KEY = 'pydantic-mypy-metadata' +BASEMODEL_FULLNAME = 'pydantic.main.BaseModel' +BASESETTINGS_FULLNAME = 'pydantic_settings.main.BaseSettings' +ROOT_MODEL_FULLNAME = 'pydantic.root_model.RootModel' +MODEL_METACLASS_FULLNAME = 'pydantic._internal._model_construction.ModelMetaclass' +FIELD_FULLNAME = 'pydantic.fields.Field' +DATACLASS_FULLNAME = 'pydantic.dataclasses.dataclass' +MODEL_VALIDATOR_FULLNAME = 'pydantic.functional_validators.model_validator' +DECORATOR_FULLNAMES = { + 'pydantic.functional_validators.field_validator', + 'pydantic.functional_validators.model_validator', + 'pydantic.functional_serializers.serializer', + 'pydantic.functional_serializers.model_serializer', + 'pydantic.deprecated.class_validators.validator', + 'pydantic.deprecated.class_validators.root_validator', +} +IMPLICIT_CLASSMETHOD_DECORATOR_FULLNAMES = DECORATOR_FULLNAMES - {'pydantic.functional_serializers.model_serializer'} + + +MYPY_VERSION_TUPLE = parse_mypy_version(mypy_version) +BUILTINS_NAME = 'builtins' + +# Increment version if plugin changes and mypy caches should be invalidated +__version__ = 2 + + +def plugin(version: str) -> type[Plugin]: + """`version` is the mypy version string. + + We might want to use this to print a warning if the mypy version being used is + newer, or especially older, than we expect (or need). + + Args: + version: The mypy version string. + + Return: + The Pydantic mypy plugin type. + """ + return PydanticPlugin + + +class PydanticPlugin(Plugin): + """The Pydantic mypy plugin.""" + + def __init__(self, options: Options) -> None: + self.plugin_config = PydanticPluginConfig(options) + self._plugin_data = self.plugin_config.to_data() + super().__init__(options) + + def get_base_class_hook(self, fullname: str) -> Callable[[ClassDefContext], None] | None: + """Update Pydantic model class.""" + sym = self.lookup_fully_qualified(fullname) + if sym and isinstance(sym.node, TypeInfo): # pragma: no branch + # No branching may occur if the mypy cache has not been cleared + if sym.node.has_base(BASEMODEL_FULLNAME): + return self._pydantic_model_class_maker_callback + return None + + def get_metaclass_hook(self, fullname: str) -> Callable[[ClassDefContext], None] | None: + """Update Pydantic `ModelMetaclass` definition.""" + if fullname == MODEL_METACLASS_FULLNAME: + return self._pydantic_model_metaclass_marker_callback + return None + + def get_method_hook(self, fullname: str) -> Callable[[MethodContext], Type] | None: + """Adjust return type of `from_orm` method call.""" + if fullname.endswith('.from_orm'): + return from_attributes_callback + return None + + def report_config_data(self, ctx: ReportConfigContext) -> dict[str, Any]: + """Return all plugin config data. + + Used by mypy to determine if cache needs to be discarded. + """ + return self._plugin_data + + def _pydantic_model_class_maker_callback(self, ctx: ClassDefContext) -> None: + transformer = PydanticModelTransformer(ctx.cls, ctx.reason, ctx.api, self.plugin_config) + transformer.transform() + + def _pydantic_model_metaclass_marker_callback(self, ctx: ClassDefContext) -> None: + """Reset dataclass_transform_spec attribute of ModelMetaclass. + + Let the plugin handle it. This behavior can be disabled + if 'debug_dataclass_transform' is set to True', for testing purposes. + """ + if self.plugin_config.debug_dataclass_transform: + return + info_metaclass = ctx.cls.info.declared_metaclass + assert info_metaclass, "callback not passed from 'get_metaclass_hook'" + if getattr(info_metaclass.type, 'dataclass_transform_spec', None): + info_metaclass.type.dataclass_transform_spec = None + + +class PydanticPluginConfig: + """A Pydantic mypy plugin config holder. + + Attributes: + init_forbid_extra: Whether to add a `**kwargs` at the end of the generated `__init__` signature. + init_typed: Whether to annotate fields in the generated `__init__`. + warn_required_dynamic_aliases: Whether to raise required dynamic aliases error. + debug_dataclass_transform: Whether to not reset `dataclass_transform_spec` attribute + of `ModelMetaclass` for testing purposes. + """ + + __slots__ = ( + 'init_forbid_extra', + 'init_typed', + 'warn_required_dynamic_aliases', + 'debug_dataclass_transform', + ) + init_forbid_extra: bool + init_typed: bool + warn_required_dynamic_aliases: bool + debug_dataclass_transform: bool # undocumented + + def __init__(self, options: Options) -> None: + if options.config_file is None: # pragma: no cover + return + + toml_config = parse_toml(options.config_file) + if toml_config is not None: + config = toml_config.get('tool', {}).get('pydantic-mypy', {}) + for key in self.__slots__: + setting = config.get(key, False) + if not isinstance(setting, bool): + raise ValueError(f'Configuration value must be a boolean for key: {key}') + setattr(self, key, setting) + else: + plugin_config = ConfigParser() + plugin_config.read(options.config_file) + for key in self.__slots__: + setting = plugin_config.getboolean(CONFIGFILE_KEY, key, fallback=False) + setattr(self, key, setting) + + def to_data(self) -> dict[str, Any]: + """Returns a dict of config names to their values.""" + return {key: getattr(self, key) for key in self.__slots__} + + +def from_attributes_callback(ctx: MethodContext) -> Type: + """Raise an error if from_attributes is not enabled.""" + model_type: Instance + ctx_type = ctx.type + if isinstance(ctx_type, TypeType): + ctx_type = ctx_type.item + if isinstance(ctx_type, CallableType) and isinstance(ctx_type.ret_type, Instance): + model_type = ctx_type.ret_type # called on the class + elif isinstance(ctx_type, Instance): + model_type = ctx_type # called on an instance (unusual, but still valid) + else: # pragma: no cover + detail = f'ctx.type: {ctx_type} (of type {ctx_type.__class__.__name__})' + error_unexpected_behavior(detail, ctx.api, ctx.context) + return ctx.default_return_type + pydantic_metadata = model_type.type.metadata.get(METADATA_KEY) + if pydantic_metadata is None: + return ctx.default_return_type + if not model_type.type.has_base(BASEMODEL_FULLNAME): + # not a Pydantic v2 model + return ctx.default_return_type + from_attributes = pydantic_metadata.get('config', {}).get('from_attributes') + if from_attributes is not True: + error_from_attributes(model_type.type.name, ctx.api, ctx.context) + return ctx.default_return_type + + +class PydanticModelField: + """Based on mypy.plugins.dataclasses.DataclassAttribute.""" + + def __init__( + self, + name: str, + alias: str | None, + is_frozen: bool, + has_dynamic_alias: bool, + has_default: bool, + strict: bool | None, + line: int, + column: int, + type: Type | None, + info: TypeInfo, + ): + self.name = name + self.alias = alias + self.is_frozen = is_frozen + self.has_dynamic_alias = has_dynamic_alias + self.has_default = has_default + self.strict = strict + self.line = line + self.column = column + self.type = type + self.info = info + + def to_argument( + self, + current_info: TypeInfo, + typed: bool, + model_strict: bool, + force_optional: bool, + use_alias: bool, + api: SemanticAnalyzerPluginInterface, + force_typevars_invariant: bool, + is_root_model_root: bool, + ) -> Argument: + """Based on mypy.plugins.dataclasses.DataclassAttribute.to_argument.""" + variable = self.to_var(current_info, api, use_alias, force_typevars_invariant) + + strict = model_strict if self.strict is None else self.strict + if typed or strict: + type_annotation = self.expand_type(current_info, api, include_root_type=True) + else: + type_annotation = AnyType(TypeOfAny.explicit) + + return Argument( + variable=variable, + type_annotation=type_annotation, + initializer=None, + kind=ARG_OPT + if is_root_model_root + else (ARG_NAMED_OPT if force_optional or self.has_default else ARG_NAMED), + ) + + def expand_type( + self, + current_info: TypeInfo, + api: SemanticAnalyzerPluginInterface, + force_typevars_invariant: bool = False, + include_root_type: bool = False, + ) -> Type | None: + """Based on mypy.plugins.dataclasses.DataclassAttribute.expand_type.""" + if force_typevars_invariant: + # In some cases, mypy will emit an error "Cannot use a covariant type variable as a parameter" + # To prevent that, we add an option to replace typevars with invariant ones while building certain + # method signatures (in particular, `__init__`). There may be a better way to do this, if this causes + # us problems in the future, we should look into why the dataclasses plugin doesn't have this issue. + if isinstance(self.type, TypeVarType): + modified_type = self.type.copy_modified() + modified_type.variance = INVARIANT + self.type = modified_type + + if self.type is not None and self.info.self_type is not None: + # In general, it is not safe to call `expand_type()` during semantic analysis, + # however this plugin is called very late, so all types should be fully ready. + # Also, it is tricky to avoid eager expansion of Self types here (e.g. because + # we serialize attributes). + with state.strict_optional_set(api.options.strict_optional): + filled_with_typevars = fill_typevars(current_info) + # Cannot be TupleType as current_info represents a Pydantic model: + assert isinstance(filled_with_typevars, Instance) + if force_typevars_invariant: + for arg in filled_with_typevars.args: + if isinstance(arg, TypeVarType): + arg.variance = INVARIANT + + expanded_type = expand_type(self.type, {self.info.self_type.id: filled_with_typevars}) + if include_root_type and isinstance(expanded_type, Instance) and is_root_model(expanded_type.type): + # When a root model is used as a field, Pydantic allows both an instance of the root model + # as well as instances of the `root` field type: + root_type = expanded_type.type['root'].type + if root_type is None: + # Happens if the hint for 'root' has unsolved forward references + return expanded_type + expanded_root_type = expand_type_by_instance(root_type, expanded_type) + expanded_type = UnionType([expanded_type, expanded_root_type]) + return expanded_type + return self.type + + def to_var( + self, + current_info: TypeInfo, + api: SemanticAnalyzerPluginInterface, + use_alias: bool, + force_typevars_invariant: bool = False, + ) -> Var: + """Based on mypy.plugins.dataclasses.DataclassAttribute.to_var.""" + if use_alias and self.alias is not None: + name = self.alias + else: + name = self.name + + return Var(name, self.expand_type(current_info, api, force_typevars_invariant)) + + def serialize(self) -> JsonDict: + """Based on mypy.plugins.dataclasses.DataclassAttribute.serialize.""" + assert self.type + return { + 'name': self.name, + 'alias': self.alias, + 'is_frozen': self.is_frozen, + 'has_dynamic_alias': self.has_dynamic_alias, + 'has_default': self.has_default, + 'strict': self.strict, + 'line': self.line, + 'column': self.column, + 'type': self.type.serialize(), + } + + @classmethod + def deserialize(cls, info: TypeInfo, data: JsonDict, api: SemanticAnalyzerPluginInterface) -> PydanticModelField: + """Based on mypy.plugins.dataclasses.DataclassAttribute.deserialize.""" + data = data.copy() + typ = deserialize_and_fixup_type(data.pop('type'), api) + return cls(type=typ, info=info, **data) + + def expand_typevar_from_subtype(self, sub_type: TypeInfo, api: SemanticAnalyzerPluginInterface) -> None: + """Expands type vars in the context of a subtype when an attribute is inherited + from a generic super type. + """ + if self.type is not None: + with state.strict_optional_set(api.options.strict_optional): + self.type = map_type_from_supertype(self.type, sub_type, self.info) + + +class PydanticModelClassVar: + """Based on mypy.plugins.dataclasses.DataclassAttribute. + + ClassVars are ignored by subclasses. + + Attributes: + name: the ClassVar name + """ + + def __init__(self, name): + self.name = name + + @classmethod + def deserialize(cls, data: JsonDict) -> PydanticModelClassVar: + """Based on mypy.plugins.dataclasses.DataclassAttribute.deserialize.""" + data = data.copy() + return cls(**data) + + def serialize(self) -> JsonDict: + """Based on mypy.plugins.dataclasses.DataclassAttribute.serialize.""" + return { + 'name': self.name, + } + + +class PydanticModelTransformer: + """Transform the BaseModel subclass according to the plugin settings. + + Attributes: + tracked_config_fields: A set of field configs that the plugin has to track their value. + """ + + tracked_config_fields: set[str] = { + 'extra', + 'frozen', + 'from_attributes', + 'populate_by_name', + 'validate_by_alias', + 'validate_by_name', + 'alias_generator', + 'strict', + } + + def __init__( + self, + cls: ClassDef, + reason: Expression | Statement, + api: SemanticAnalyzerPluginInterface, + plugin_config: PydanticPluginConfig, + ) -> None: + self._cls = cls + self._reason = reason + self._api = api + + self.plugin_config = plugin_config + + def transform(self) -> bool: + """Configures the BaseModel subclass according to the plugin settings. + + In particular: + + * determines the model config and fields, + * adds a fields-aware signature for the initializer and construct methods + * freezes the class if frozen = True + * stores the fields, config, and if the class is settings in the mypy metadata for access by subclasses + """ + info = self._cls.info + is_a_root_model = is_root_model(info) + config = self.collect_config() + fields, class_vars = self.collect_fields_and_class_vars(config, is_a_root_model) + if fields is None or class_vars is None: + # Some definitions are not ready. We need another pass. + return False + for field in fields: + if field.type is None: + return False + + is_settings = info.has_base(BASESETTINGS_FULLNAME) + self.add_initializer(fields, config, is_settings, is_a_root_model) + self.add_model_construct_method(fields, config, is_settings, is_a_root_model) + self.set_frozen(fields, self._api, frozen=config.frozen is True) + + self.adjust_decorator_signatures() + + info.metadata[METADATA_KEY] = { + 'fields': {field.name: field.serialize() for field in fields}, + 'class_vars': {class_var.name: class_var.serialize() for class_var in class_vars}, + 'config': config.get_values_dict(), + } + + return True + + def adjust_decorator_signatures(self) -> None: + """When we decorate a function `f` with `pydantic.validator(...)`, `pydantic.field_validator` + or `pydantic.serializer(...)`, mypy sees `f` as a regular method taking a `self` instance, + even though pydantic internally wraps `f` with `classmethod` if necessary. + + Teach mypy this by marking any function whose outermost decorator is a `validator()`, + `field_validator()` or `serializer()` call as a `classmethod`. + """ + for sym in self._cls.info.names.values(): + if isinstance(sym.node, Decorator): + first_dec = sym.node.original_decorators[0] + if ( + isinstance(first_dec, CallExpr) + and isinstance(first_dec.callee, NameExpr) + and first_dec.callee.fullname in IMPLICIT_CLASSMETHOD_DECORATOR_FULLNAMES + # @model_validator(mode="after") is an exception, it expects a regular method + and not ( + first_dec.callee.fullname == MODEL_VALIDATOR_FULLNAME + and any( + first_dec.arg_names[i] == 'mode' and isinstance(arg, StrExpr) and arg.value == 'after' + for i, arg in enumerate(first_dec.args) + ) + ) + ): + # TODO: Only do this if the first argument of the decorated function is `cls` + sym.node.func.is_class = True + + def collect_config(self) -> ModelConfigData: # noqa: C901 (ignore complexity) + """Collects the values of the config attributes that are used by the plugin, accounting for parent classes.""" + cls = self._cls + config = ModelConfigData() + + has_config_kwargs = False + has_config_from_namespace = False + + # Handle `class MyModel(BaseModel, =, ...):` + for name, expr in cls.keywords.items(): + config_data = self.get_config_update(name, expr) + if config_data: + has_config_kwargs = True + config.update(config_data) + + # Handle `model_config` + stmt: Statement | None = None + for stmt in cls.defs.body: + if not isinstance(stmt, (AssignmentStmt, ClassDef)): + continue + + if isinstance(stmt, AssignmentStmt): + lhs = stmt.lvalues[0] + if not isinstance(lhs, NameExpr) or lhs.name != 'model_config': + continue + + if isinstance(stmt.rvalue, CallExpr): # calls to `dict` or `ConfigDict` + for arg_name, arg in zip(stmt.rvalue.arg_names, stmt.rvalue.args): + if arg_name is None: + continue + config.update(self.get_config_update(arg_name, arg, lax_extra=True)) + elif isinstance(stmt.rvalue, DictExpr): # dict literals + for key_expr, value_expr in stmt.rvalue.items: + if not isinstance(key_expr, StrExpr): + continue + config.update(self.get_config_update(key_expr.value, value_expr)) + + elif isinstance(stmt, ClassDef): + if stmt.name != 'Config': # 'deprecated' Config-class + continue + for substmt in stmt.defs.body: + if not isinstance(substmt, AssignmentStmt): + continue + lhs = substmt.lvalues[0] + if not isinstance(lhs, NameExpr): + continue + config.update(self.get_config_update(lhs.name, substmt.rvalue)) + + if has_config_kwargs: + self._api.fail( + 'Specifying config in two places is ambiguous, use either Config attribute or class kwargs', + cls, + ) + break + + has_config_from_namespace = True + + if has_config_kwargs or has_config_from_namespace: + if ( + stmt + and config.has_alias_generator + and not (config.validate_by_name or config.populate_by_name) + and self.plugin_config.warn_required_dynamic_aliases + ): + error_required_dynamic_aliases(self._api, stmt) + + for info in cls.info.mro[1:]: # 0 is the current class + if METADATA_KEY not in info.metadata: + continue + + # Each class depends on the set of fields in its ancestors + self._api.add_plugin_dependency(make_wildcard_trigger(info.fullname)) + for name, value in info.metadata[METADATA_KEY]['config'].items(): + config.setdefault(name, value) + return config + + def collect_fields_and_class_vars( + self, model_config: ModelConfigData, is_root_model: bool + ) -> tuple[list[PydanticModelField] | None, list[PydanticModelClassVar] | None]: + """Collects the fields for the model, accounting for parent classes.""" + cls = self._cls + + # First, collect fields and ClassVars belonging to any class in the MRO, ignoring duplicates. + # + # We iterate through the MRO in reverse because attrs defined in the parent must appear + # earlier in the attributes list than attrs defined in the child. See: + # https://docs.python.org/3/library/dataclasses.html#inheritance + # + # However, we also want fields defined in the subtype to override ones defined + # in the parent. We can implement this via a dict without disrupting the attr order + # because dicts preserve insertion order in Python 3.7+. + found_fields: dict[str, PydanticModelField] = {} + found_class_vars: dict[str, PydanticModelClassVar] = {} + for info in reversed(cls.info.mro[1:-1]): # 0 is the current class, -2 is BaseModel, -1 is object + # if BASEMODEL_METADATA_TAG_KEY in info.metadata and BASEMODEL_METADATA_KEY not in info.metadata: + # # We haven't processed the base class yet. Need another pass. + # return None, None + if METADATA_KEY not in info.metadata: + continue + + # Each class depends on the set of attributes in its dataclass ancestors. + self._api.add_plugin_dependency(make_wildcard_trigger(info.fullname)) + + for name, data in info.metadata[METADATA_KEY]['fields'].items(): + field = PydanticModelField.deserialize(info, data, self._api) + # (The following comment comes directly from the dataclasses plugin) + # TODO: We shouldn't be performing type operations during the main + # semantic analysis pass, since some TypeInfo attributes might + # still be in flux. This should be performed in a later phase. + field.expand_typevar_from_subtype(cls.info, self._api) + found_fields[name] = field + + sym_node = cls.info.names.get(name) + if sym_node and sym_node.node and not isinstance(sym_node.node, Var): + self._api.fail( + 'BaseModel field may only be overridden by another field', + sym_node.node, + ) + # Collect ClassVars + for name, data in info.metadata[METADATA_KEY]['class_vars'].items(): + found_class_vars[name] = PydanticModelClassVar.deserialize(data) + + # Second, collect fields and ClassVars belonging to the current class. + current_field_names: set[str] = set() + current_class_vars_names: set[str] = set() + for stmt in self._get_assignment_statements_from_block(cls.defs): + maybe_field = self.collect_field_or_class_var_from_stmt(stmt, model_config, found_class_vars) + if maybe_field is None: + continue + + lhs = stmt.lvalues[0] + assert isinstance(lhs, NameExpr) # collect_field_or_class_var_from_stmt guarantees this + if isinstance(maybe_field, PydanticModelField): + if is_root_model and lhs.name != 'root': + error_extra_fields_on_root_model(self._api, stmt) + else: + current_field_names.add(lhs.name) + found_fields[lhs.name] = maybe_field + elif isinstance(maybe_field, PydanticModelClassVar): + current_class_vars_names.add(lhs.name) + found_class_vars[lhs.name] = maybe_field + + return list(found_fields.values()), list(found_class_vars.values()) + + def _get_assignment_statements_from_if_statement(self, stmt: IfStmt) -> Iterator[AssignmentStmt]: + for body in stmt.body: + if not body.is_unreachable: + yield from self._get_assignment_statements_from_block(body) + if stmt.else_body is not None and not stmt.else_body.is_unreachable: + yield from self._get_assignment_statements_from_block(stmt.else_body) + + def _get_assignment_statements_from_block(self, block: Block) -> Iterator[AssignmentStmt]: + for stmt in block.body: + if isinstance(stmt, AssignmentStmt): + yield stmt + elif isinstance(stmt, IfStmt): + yield from self._get_assignment_statements_from_if_statement(stmt) + + def collect_field_or_class_var_from_stmt( # noqa C901 + self, stmt: AssignmentStmt, model_config: ModelConfigData, class_vars: dict[str, PydanticModelClassVar] + ) -> PydanticModelField | PydanticModelClassVar | None: + """Get pydantic model field from statement. + + Args: + stmt: The statement. + model_config: Configuration settings for the model. + class_vars: ClassVars already known to be defined on the model. + + Returns: + A pydantic model field if it could find the field in statement. Otherwise, `None`. + """ + cls = self._cls + + lhs = stmt.lvalues[0] + if not isinstance(lhs, NameExpr) or not _fields.is_valid_field_name(lhs.name) or lhs.name == 'model_config': + return None + + if not stmt.new_syntax: + if ( + isinstance(stmt.rvalue, CallExpr) + and isinstance(stmt.rvalue.callee, CallExpr) + and isinstance(stmt.rvalue.callee.callee, NameExpr) + and stmt.rvalue.callee.callee.fullname in DECORATOR_FULLNAMES + ): + # This is a (possibly-reused) validator or serializer, not a field + # In particular, it looks something like: my_validator = validator('my_field')(f) + # Eventually, we may want to attempt to respect model_config['ignored_types'] + return None + + if lhs.name in class_vars: + # Class vars are not fields and are not required to be annotated + return None + + # The assignment does not have an annotation, and it's not anything else we recognize + error_untyped_fields(self._api, stmt) + return None + + lhs = stmt.lvalues[0] + if not isinstance(lhs, NameExpr): + return None + + if not _fields.is_valid_field_name(lhs.name) or lhs.name == 'model_config': + return None + + sym = cls.info.names.get(lhs.name) + if sym is None: # pragma: no cover + # This is likely due to a star import (see the dataclasses plugin for a more detailed explanation) + # This is the same logic used in the dataclasses plugin + return None + + node = sym.node + if isinstance(node, PlaceholderNode): # pragma: no cover + # See the PlaceholderNode docstring for more detail about how this can occur + # Basically, it is an edge case when dealing with complex import logic + + # The dataclasses plugin now asserts this cannot happen, but I'd rather not error if it does.. + return None + + if isinstance(node, TypeAlias): + self._api.fail( + 'Type aliases inside BaseModel definitions are not supported at runtime', + node, + ) + # Skip processing this node. This doesn't match the runtime behaviour, + # but the only alternative would be to modify the SymbolTable, + # and it's a little hairy to do that in a plugin. + return None + + if not isinstance(node, Var): # pragma: no cover + # Don't know if this edge case still happens with the `is_valid_field` check above + # but better safe than sorry + + # The dataclasses plugin now asserts this cannot happen, but I'd rather not error if it does.. + return None + + # x: ClassVar[int] is not a field + if node.is_classvar: + return PydanticModelClassVar(lhs.name) + + # x: InitVar[int] is not supported in BaseModel + node_type = get_proper_type(node.type) + if isinstance(node_type, Instance) and node_type.type.fullname == 'dataclasses.InitVar': + self._api.fail( + 'InitVar is not supported in BaseModel', + node, + ) + + has_default = self.get_has_default(stmt) + strict = self.get_strict(stmt) + + if sym.type is None and node.is_final and node.is_inferred: + # This follows the logic from the dataclasses plugin. The following comment is taken verbatim: + # + # This is a special case, assignment like x: Final = 42 is classified + # annotated above, but mypy strips the `Final` turning it into x = 42. + # We do not support inferred types in dataclasses, so we can try inferring + # type for simple literals, and otherwise require an explicit type + # argument for Final[...]. + typ = self._api.analyze_simple_literal_type(stmt.rvalue, is_final=True) + if typ: + node.type = typ + else: + self._api.fail( + 'Need type argument for Final[...] with non-literal default in BaseModel', + stmt, + ) + node.type = AnyType(TypeOfAny.from_error) + + if node.is_final and has_default: + # TODO this path should be removed (see https://github.com/pydantic/pydantic/issues/11119) + return PydanticModelClassVar(lhs.name) + + alias, has_dynamic_alias = self.get_alias_info(stmt) + if ( + has_dynamic_alias + and not (model_config.validate_by_name or model_config.populate_by_name) + and self.plugin_config.warn_required_dynamic_aliases + ): + error_required_dynamic_aliases(self._api, stmt) + is_frozen = self.is_field_frozen(stmt) + + init_type = self._infer_dataclass_attr_init_type(sym, lhs.name, stmt) + return PydanticModelField( + name=lhs.name, + has_dynamic_alias=has_dynamic_alias, + has_default=has_default, + strict=strict, + alias=alias, + is_frozen=is_frozen, + line=stmt.line, + column=stmt.column, + type=init_type, + info=cls.info, + ) + + def _infer_dataclass_attr_init_type(self, sym: SymbolTableNode, name: str, context: Context) -> Type | None: + """Infer __init__ argument type for an attribute. + + In particular, possibly use the signature of __set__. + """ + default = sym.type + if sym.implicit: + return default + t = get_proper_type(sym.type) + + # Perform a simple-minded inference from the signature of __set__, if present. + # We can't use mypy.checkmember here, since this plugin runs before type checking. + # We only support some basic scanerios here, which is hopefully sufficient for + # the vast majority of use cases. + if not isinstance(t, Instance): + return default + setter = t.type.get('__set__') + if setter: + if isinstance(setter.node, FuncDef): + super_info = t.type.get_containing_type_info('__set__') + assert super_info + if setter.type: + setter_type = get_proper_type(map_type_from_supertype(setter.type, t.type, super_info)) + else: + return AnyType(TypeOfAny.unannotated) + if isinstance(setter_type, CallableType) and setter_type.arg_kinds == [ + ARG_POS, + ARG_POS, + ARG_POS, + ]: + return expand_type_by_instance(setter_type.arg_types[2], t) + else: + self._api.fail(f'Unsupported signature for "__set__" in "{t.type.name}"', context) + else: + self._api.fail(f'Unsupported "__set__" in "{t.type.name}"', context) + + return default + + def add_initializer( + self, fields: list[PydanticModelField], config: ModelConfigData, is_settings: bool, is_root_model: bool + ) -> None: + """Adds a fields-aware `__init__` method to the class. + + The added `__init__` will be annotated with types vs. all `Any` depending on the plugin settings. + """ + if '__init__' in self._cls.info.names and not self._cls.info.names['__init__'].plugin_generated: + return # Don't generate an __init__ if one already exists + + typed = self.plugin_config.init_typed + model_strict = bool(config.strict) + use_alias = not (config.validate_by_name or config.populate_by_name) and config.validate_by_alias is not False + requires_dynamic_aliases = bool(config.has_alias_generator and not config.validate_by_name) + args = self.get_field_arguments( + fields, + typed=typed, + model_strict=model_strict, + requires_dynamic_aliases=requires_dynamic_aliases, + use_alias=use_alias, + is_settings=is_settings, + is_root_model=is_root_model, + force_typevars_invariant=True, + ) + + if is_settings: + base_settings_node = self._api.lookup_fully_qualified(BASESETTINGS_FULLNAME).node + assert isinstance(base_settings_node, TypeInfo) + if '__init__' in base_settings_node.names: + base_settings_init_node = base_settings_node.names['__init__'].node + assert isinstance(base_settings_init_node, FuncDef) + if base_settings_init_node is not None and base_settings_init_node.type is not None: + func_type = base_settings_init_node.type + assert isinstance(func_type, CallableType) + for arg_idx, arg_name in enumerate(func_type.arg_names): + if arg_name is None or arg_name.startswith('__') or not arg_name.startswith('_'): + continue + analyzed_variable_type = self._api.anal_type(func_type.arg_types[arg_idx]) + if analyzed_variable_type is not None and arg_name == '_cli_settings_source': + # _cli_settings_source is defined as CliSettingsSource[Any], and as such + # the Any causes issues with --disallow-any-explicit. As a workaround, change + # the Any type (as if CliSettingsSource was left unparameterized): + analyzed_variable_type = analyzed_variable_type.accept( + ChangeExplicitTypeOfAny(TypeOfAny.from_omitted_generics) + ) + variable = Var(arg_name, analyzed_variable_type) + args.append(Argument(variable, analyzed_variable_type, None, ARG_OPT)) + + if not self.should_init_forbid_extra(fields, config): + var = Var('kwargs') + args.append(Argument(var, AnyType(TypeOfAny.explicit), None, ARG_STAR2)) + + add_method(self._api, self._cls, '__init__', args=args, return_type=NoneType()) + + def add_model_construct_method( + self, + fields: list[PydanticModelField], + config: ModelConfigData, + is_settings: bool, + is_root_model: bool, + ) -> None: + """Adds a fully typed `model_construct` classmethod to the class. + + Similar to the fields-aware __init__ method, but always uses the field names (not aliases), + and does not treat settings fields as optional. + """ + set_str = self._api.named_type(f'{BUILTINS_NAME}.set', [self._api.named_type(f'{BUILTINS_NAME}.str')]) + optional_set_str = UnionType([set_str, NoneType()]) + fields_set_argument = Argument(Var('_fields_set', optional_set_str), optional_set_str, None, ARG_OPT) + with state.strict_optional_set(self._api.options.strict_optional): + args = self.get_field_arguments( + fields, + typed=True, + model_strict=bool(config.strict), + requires_dynamic_aliases=False, + use_alias=False, + is_settings=is_settings, + is_root_model=is_root_model, + ) + if not self.should_init_forbid_extra(fields, config): + var = Var('kwargs') + args.append(Argument(var, AnyType(TypeOfAny.explicit), None, ARG_STAR2)) + + args = args + [fields_set_argument] if is_root_model else [fields_set_argument] + args + + add_method( + self._api, + self._cls, + 'model_construct', + args=args, + return_type=fill_typevars(self._cls.info), + is_classmethod=True, + ) + + def set_frozen(self, fields: list[PydanticModelField], api: SemanticAnalyzerPluginInterface, frozen: bool) -> None: + """Marks all fields as properties so that attempts to set them trigger mypy errors. + + This is the same approach used by the attrs and dataclasses plugins. + """ + info = self._cls.info + for field in fields: + sym_node = info.names.get(field.name) + if sym_node is not None: + var = sym_node.node + if isinstance(var, Var): + var.is_property = frozen or field.is_frozen + elif isinstance(var, PlaceholderNode) and not self._api.final_iteration: + # See https://github.com/pydantic/pydantic/issues/5191 to hit this branch for test coverage + self._api.defer() + # `var` can also be a FuncDef or Decorator node (e.g. when overriding a field with a function or property). + # In that case, we don't want to do anything. Mypy will already raise an error that a field was not properly + # overridden. + else: + var = field.to_var(info, api, use_alias=False) + var.info = info + var.is_property = frozen + var._fullname = info.fullname + '.' + var.name + info.names[var.name] = SymbolTableNode(MDEF, var) + + def get_config_update(self, name: str, arg: Expression, lax_extra: bool = False) -> ModelConfigData | None: + """Determines the config update due to a single kwarg in the ConfigDict definition. + + Warns if a tracked config attribute is set to a value the plugin doesn't know how to interpret (e.g., an int) + """ + if name not in self.tracked_config_fields: + return None + if name == 'extra': + if isinstance(arg, StrExpr): + forbid_extra = arg.value == 'forbid' + elif isinstance(arg, MemberExpr): + forbid_extra = arg.name == 'forbid' + else: + if not lax_extra: + # Only emit an error for other types of `arg` (e.g., `NameExpr`, `ConditionalExpr`, etc.) when + # reading from a config class, etc. If a ConfigDict is used, then we don't want to emit an error + # because you'll get type checking from the ConfigDict itself. + # + # It would be nice if we could introspect the types better otherwise, but I don't know what the API + # is to evaluate an expr into its type and then check if that type is compatible with the expected + # type. Note that you can still get proper type checking via: `model_config = ConfigDict(...)`, just + # if you don't use an explicit string, the plugin won't be able to infer whether extra is forbidden. + error_invalid_config_value(name, self._api, arg) + return None + return ModelConfigData(forbid_extra=forbid_extra) + if name == 'alias_generator': + has_alias_generator = True + if isinstance(arg, NameExpr) and arg.fullname == 'builtins.None': + has_alias_generator = False + return ModelConfigData(has_alias_generator=has_alias_generator) + if isinstance(arg, NameExpr) and arg.fullname in ('builtins.True', 'builtins.False'): + return ModelConfigData(**{name: arg.fullname == 'builtins.True'}) + error_invalid_config_value(name, self._api, arg) + return None + + @staticmethod + def get_has_default(stmt: AssignmentStmt) -> bool: + """Returns a boolean indicating whether the field defined in `stmt` is a required field.""" + expr = stmt.rvalue + if isinstance(expr, TempNode): + # TempNode means annotation-only, so has no default + return False + if isinstance(expr, CallExpr) and isinstance(expr.callee, RefExpr) and expr.callee.fullname == FIELD_FULLNAME: + # The "default value" is a call to `Field`; at this point, the field has a default if and only if: + # * there is a positional argument that is not `...` + # * there is a keyword argument named "default" that is not `...` + # * there is a "default_factory" that is not `None` + for arg, name in zip(expr.args, expr.arg_names): + # If name is None, then this arg is the default because it is the only positional argument. + if name is None or name == 'default': + return arg.__class__ is not EllipsisExpr + if name == 'default_factory': + return not (isinstance(arg, NameExpr) and arg.fullname == 'builtins.None') + return False + # Has no default if the "default value" is Ellipsis (i.e., `field_name: Annotation = ...`) + return not isinstance(expr, EllipsisExpr) + + @staticmethod + def get_strict(stmt: AssignmentStmt) -> bool | None: + """Returns a the `strict` value of a field if defined, otherwise `None`.""" + expr = stmt.rvalue + if isinstance(expr, CallExpr) and isinstance(expr.callee, RefExpr) and expr.callee.fullname == FIELD_FULLNAME: + for arg, name in zip(expr.args, expr.arg_names): + if name != 'strict': + continue + if isinstance(arg, NameExpr): + if arg.fullname == 'builtins.True': + return True + elif arg.fullname == 'builtins.False': + return False + return None + return None + + @staticmethod + def get_alias_info(stmt: AssignmentStmt) -> tuple[str | None, bool]: + """Returns a pair (alias, has_dynamic_alias), extracted from the declaration of the field defined in `stmt`. + + `has_dynamic_alias` is True if and only if an alias is provided, but not as a string literal. + If `has_dynamic_alias` is True, `alias` will be None. + """ + expr = stmt.rvalue + if isinstance(expr, TempNode): + # TempNode means annotation-only + return None, False + + if not ( + isinstance(expr, CallExpr) and isinstance(expr.callee, RefExpr) and expr.callee.fullname == FIELD_FULLNAME + ): + # Assigned value is not a call to pydantic.fields.Field + return None, False + + if 'validation_alias' in expr.arg_names: + arg = expr.args[expr.arg_names.index('validation_alias')] + elif 'alias' in expr.arg_names: + arg = expr.args[expr.arg_names.index('alias')] + else: + return None, False + + if isinstance(arg, StrExpr): + return arg.value, False + else: + return None, True + + @staticmethod + def is_field_frozen(stmt: AssignmentStmt) -> bool: + """Returns whether the field is frozen, extracted from the declaration of the field defined in `stmt`. + + Note that this is only whether the field was declared to be frozen in a ` = Field(frozen=True)` + sense; this does not determine whether the field is frozen because the entire model is frozen; that is + handled separately. + """ + expr = stmt.rvalue + if isinstance(expr, TempNode): + # TempNode means annotation-only + return False + + if not ( + isinstance(expr, CallExpr) and isinstance(expr.callee, RefExpr) and expr.callee.fullname == FIELD_FULLNAME + ): + # Assigned value is not a call to pydantic.fields.Field + return False + + for i, arg_name in enumerate(expr.arg_names): + if arg_name == 'frozen': + arg = expr.args[i] + return isinstance(arg, NameExpr) and arg.fullname == 'builtins.True' + return False + + def get_field_arguments( + self, + fields: list[PydanticModelField], + typed: bool, + model_strict: bool, + use_alias: bool, + requires_dynamic_aliases: bool, + is_settings: bool, + is_root_model: bool, + force_typevars_invariant: bool = False, + ) -> list[Argument]: + """Helper function used during the construction of the `__init__` and `model_construct` method signatures. + + Returns a list of mypy Argument instances for use in the generated signatures. + """ + info = self._cls.info + arguments = [ + field.to_argument( + info, + typed=typed, + model_strict=model_strict, + force_optional=requires_dynamic_aliases or is_settings, + use_alias=use_alias, + api=self._api, + force_typevars_invariant=force_typevars_invariant, + is_root_model_root=is_root_model and field.name == 'root', + ) + for field in fields + if not (use_alias and field.has_dynamic_alias) + ] + return arguments + + def should_init_forbid_extra(self, fields: list[PydanticModelField], config: ModelConfigData) -> bool: + """Indicates whether the generated `__init__` should get a `**kwargs` at the end of its signature. + + We disallow arbitrary kwargs if the extra config setting is "forbid", or if the plugin config says to, + *unless* a required dynamic alias is present (since then we can't determine a valid signature). + """ + if not (config.validate_by_name or config.populate_by_name): + if self.is_dynamic_alias_present(fields, bool(config.has_alias_generator)): + return False + if config.forbid_extra: + return True + return self.plugin_config.init_forbid_extra + + @staticmethod + def is_dynamic_alias_present(fields: list[PydanticModelField], has_alias_generator: bool) -> bool: + """Returns whether any fields on the model have a "dynamic alias", i.e., an alias that cannot be + determined during static analysis. + """ + for field in fields: + if field.has_dynamic_alias: + return True + if has_alias_generator: + for field in fields: + if field.alias is None: + return True + return False + + +class ChangeExplicitTypeOfAny(TypeTranslator): + """A type translator used to change type of Any's, if explicit.""" + + def __init__(self, type_of_any: int) -> None: + self._type_of_any = type_of_any + super().__init__() + + def visit_any(self, t: AnyType) -> Type: # noqa: D102 + if t.type_of_any == TypeOfAny.explicit: + return t.copy_modified(type_of_any=self._type_of_any) + else: + return t + + +class ModelConfigData: + """Pydantic mypy plugin model config class.""" + + def __init__( + self, + forbid_extra: bool | None = None, + frozen: bool | None = None, + from_attributes: bool | None = None, + populate_by_name: bool | None = None, + validate_by_alias: bool | None = None, + validate_by_name: bool | None = None, + has_alias_generator: bool | None = None, + strict: bool | None = None, + ): + self.forbid_extra = forbid_extra + self.frozen = frozen + self.from_attributes = from_attributes + self.populate_by_name = populate_by_name + self.validate_by_alias = validate_by_alias + self.validate_by_name = validate_by_name + self.has_alias_generator = has_alias_generator + self.strict = strict + + def get_values_dict(self) -> dict[str, Any]: + """Returns a dict of Pydantic model config names to their values. + + It includes the config if config value is not `None`. + """ + return {k: v for k, v in self.__dict__.items() if v is not None} + + def update(self, config: ModelConfigData | None) -> None: + """Update Pydantic model config values.""" + if config is None: + return + for k, v in config.get_values_dict().items(): + setattr(self, k, v) + + def setdefault(self, key: str, value: Any) -> None: + """Set default value for Pydantic model config if config value is `None`.""" + if getattr(self, key) is None: + setattr(self, key, value) + + +def is_root_model(info: TypeInfo) -> bool: + """Return whether the type info is a root model subclass (or the `RootModel` class itself).""" + return info.has_base(ROOT_MODEL_FULLNAME) + + +ERROR_ORM = ErrorCode('pydantic-orm', 'Invalid from_attributes call', 'Pydantic') +ERROR_CONFIG = ErrorCode('pydantic-config', 'Invalid config value', 'Pydantic') +ERROR_ALIAS = ErrorCode('pydantic-alias', 'Dynamic alias disallowed', 'Pydantic') +ERROR_UNEXPECTED = ErrorCode('pydantic-unexpected', 'Unexpected behavior', 'Pydantic') +ERROR_UNTYPED = ErrorCode('pydantic-field', 'Untyped field disallowed', 'Pydantic') +ERROR_FIELD_DEFAULTS = ErrorCode('pydantic-field', 'Invalid Field defaults', 'Pydantic') +ERROR_EXTRA_FIELD_ROOT_MODEL = ErrorCode('pydantic-field', 'Extra field on RootModel subclass', 'Pydantic') + + +def error_from_attributes(model_name: str, api: CheckerPluginInterface, context: Context) -> None: + """Emits an error when the model does not have `from_attributes=True`.""" + api.fail(f'"{model_name}" does not have from_attributes=True', context, code=ERROR_ORM) + + +def error_invalid_config_value(name: str, api: SemanticAnalyzerPluginInterface, context: Context) -> None: + """Emits an error when the config value is invalid.""" + api.fail(f'Invalid value for "Config.{name}"', context, code=ERROR_CONFIG) + + +def error_required_dynamic_aliases(api: SemanticAnalyzerPluginInterface, context: Context) -> None: + """Emits required dynamic aliases error. + + This will be called when `warn_required_dynamic_aliases=True`. + """ + api.fail('Required dynamic aliases disallowed', context, code=ERROR_ALIAS) + + +def error_unexpected_behavior( + detail: str, api: CheckerPluginInterface | SemanticAnalyzerPluginInterface, context: Context +) -> None: # pragma: no cover + """Emits unexpected behavior error.""" + # Can't think of a good way to test this, but I confirmed it renders as desired by adding to a non-error path + link = 'https://github.com/pydantic/pydantic/issues/new/choose' + full_message = f'The pydantic mypy plugin ran into unexpected behavior: {detail}\n' + full_message += f'Please consider reporting this bug at {link} so we can try to fix it!' + api.fail(full_message, context, code=ERROR_UNEXPECTED) + + +def error_untyped_fields(api: SemanticAnalyzerPluginInterface, context: Context) -> None: + """Emits an error when there is an untyped field in the model.""" + api.fail('Untyped fields disallowed', context, code=ERROR_UNTYPED) + + +def error_extra_fields_on_root_model(api: CheckerPluginInterface, context: Context) -> None: + """Emits an error when there is more than just a root field defined for a subclass of RootModel.""" + api.fail('Only `root` is allowed as a field of a `RootModel`', context, code=ERROR_EXTRA_FIELD_ROOT_MODEL) + + +def add_method( + api: SemanticAnalyzerPluginInterface | CheckerPluginInterface, + cls: ClassDef, + name: str, + args: list[Argument], + return_type: Type, + self_type: Type | None = None, + tvar_def: TypeVarType | None = None, + is_classmethod: bool = False, +) -> None: + """Very closely related to `mypy.plugins.common.add_method_to_class`, with a few pydantic-specific changes.""" + info = cls.info + + # First remove any previously generated methods with the same name + # to avoid clashes and problems in the semantic analyzer. + if name in info.names: + sym = info.names[name] + if sym.plugin_generated and isinstance(sym.node, FuncDef): + cls.defs.body.remove(sym.node) # pragma: no cover + + if isinstance(api, SemanticAnalyzerPluginInterface): + function_type = api.named_type('builtins.function') + else: + function_type = api.named_generic_type('builtins.function', []) + + if is_classmethod: + self_type = self_type or TypeType(fill_typevars(info)) + first = [Argument(Var('_cls'), self_type, None, ARG_POS, True)] + else: + self_type = self_type or fill_typevars(info) + # `self` is positional *ONLY* here, but this can't be expressed + # fully in the mypy internal API. ARG_POS is the closest we can get. + # Using ARG_POS will, however, give mypy errors if a `self` field + # is present on a model: + # + # Name "self" already defined (possibly by an import) [no-redef] + # + # As a workaround, we give this argument a name that will + # never conflict. By its positional nature, this name will not + # be used or exposed to users. + first = [Argument(Var('__pydantic_self__'), self_type, None, ARG_POS)] + args = first + args + + arg_types, arg_names, arg_kinds = [], [], [] + for arg in args: + assert arg.type_annotation, 'All arguments must be fully typed.' + arg_types.append(arg.type_annotation) + arg_names.append(arg.variable.name) + arg_kinds.append(arg.kind) + + signature = CallableType( + arg_types, arg_kinds, arg_names, return_type, function_type, variables=[tvar_def] if tvar_def else None + ) + + func = FuncDef(name, args, Block([PassStmt()])) + func.info = info + func.type = set_callable_name(signature, func) + func.is_class = is_classmethod + func._fullname = info.fullname + '.' + name + func.line = info.line + + # NOTE: we would like the plugin generated node to dominate, but we still + # need to keep any existing definitions so they get semantically analyzed. + if name in info.names: + # Get a nice unique name instead. + r_name = get_unique_redefinition_name(name, info.names) + info.names[r_name] = info.names[name] + + # Add decorator for is_classmethod + # The dataclasses plugin claims this is unnecessary for classmethods, but not including it results in a + # signature incompatible with the superclass, which causes mypy errors to occur for every subclass of BaseModel. + if is_classmethod: + func.is_decorated = True + v = Var(name, func.type) + v.info = info + v._fullname = func._fullname + v.is_classmethod = True + dec = Decorator(func, [NameExpr('classmethod')], v) + dec.line = info.line + sym = SymbolTableNode(MDEF, dec) + else: + sym = SymbolTableNode(MDEF, func) + sym.plugin_generated = True + info.names[name] = sym + + info.defn.defs.body.append(func) + + +def parse_toml(config_file: str) -> dict[str, Any] | None: + """Returns a dict of config keys to values. + + It reads configs from toml file and returns `None` if the file is not a toml file. + """ + if not config_file.endswith('.toml'): + return None + + if sys.version_info >= (3, 11): + import tomllib as toml_ + else: + try: + import tomli as toml_ + except ImportError: # pragma: no cover + import warnings + + warnings.warn('No TOML parser installed, cannot read configuration from `pyproject.toml`.', stacklevel=2) + return None + + with open(config_file, 'rb') as rf: + return toml_.load(rf) diff --git a/backend/.venv/Lib/site-packages/pydantic/networks.py b/backend/.venv/Lib/site-packages/pydantic/networks.py new file mode 100644 index 0000000..04a7cac --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/networks.py @@ -0,0 +1,1331 @@ +"""The networks module contains types for common network-related fields.""" + +from __future__ import annotations as _annotations + +import dataclasses as _dataclasses +import re +from dataclasses import fields +from functools import lru_cache +from importlib.metadata import version +from ipaddress import IPv4Address, IPv4Interface, IPv4Network, IPv6Address, IPv6Interface, IPv6Network +from typing import TYPE_CHECKING, Annotated, Any, ClassVar + +from pydantic_core import ( + MultiHostHost, + PydanticCustomError, + PydanticSerializationUnexpectedValue, + SchemaSerializer, + core_schema, +) +from pydantic_core import MultiHostUrl as _CoreMultiHostUrl +from pydantic_core import Url as _CoreUrl +from typing_extensions import Self, TypeAlias + +from pydantic.errors import PydanticUserError + +from ._internal import _repr, _schema_generation_shared +from ._migration import getattr_migration +from .annotated_handlers import GetCoreSchemaHandler +from .json_schema import JsonSchemaValue +from .type_adapter import TypeAdapter + +if TYPE_CHECKING: + import email_validator + + NetworkType: TypeAlias = 'str | bytes | int | tuple[str | bytes | int, str | int]' + +else: + email_validator = None + + +__all__ = [ + 'AnyUrl', + 'AnyHttpUrl', + 'FileUrl', + 'FtpUrl', + 'HttpUrl', + 'WebsocketUrl', + 'AnyWebsocketUrl', + 'UrlConstraints', + 'EmailStr', + 'NameEmail', + 'IPvAnyAddress', + 'IPvAnyInterface', + 'IPvAnyNetwork', + 'PostgresDsn', + 'CockroachDsn', + 'AmqpDsn', + 'RedisDsn', + 'MongoDsn', + 'KafkaDsn', + 'NatsDsn', + 'validate_email', + 'MySQLDsn', + 'MariaDBDsn', + 'ClickHouseDsn', + 'SnowflakeDsn', +] + + +@_dataclasses.dataclass +class UrlConstraints: + """Url constraints. + + Attributes: + max_length: The maximum length of the url. Defaults to `None`. + allowed_schemes: The allowed schemes. Defaults to `None`. + host_required: Whether the host is required. Defaults to `None`. + default_host: The default host. Defaults to `None`. + default_port: The default port. Defaults to `None`. + default_path: The default path. Defaults to `None`. + preserve_empty_path: Whether to preserve empty URL paths. Defaults to `None`. + """ + + max_length: int | None = None + allowed_schemes: list[str] | None = None + host_required: bool | None = None + default_host: str | None = None + default_port: int | None = None + default_path: str | None = None + preserve_empty_path: bool | None = None + + def __hash__(self) -> int: + return hash( + ( + self.max_length, + tuple(self.allowed_schemes) if self.allowed_schemes is not None else None, + self.host_required, + self.default_host, + self.default_port, + self.default_path, + self.preserve_empty_path, + ) + ) + + @property + def defined_constraints(self) -> dict[str, Any]: + """Fetch a key / value mapping of constraints to values that are not None. Used for core schema updates.""" + return {field.name: value for field in fields(self) if (value := getattr(self, field.name)) is not None} + + def __get_pydantic_core_schema__(self, source: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: + schema = handler(source) + + # for function-wrap schemas, url constraints is applied to the inner schema + # because when we generate schemas for urls, we wrap a core_schema.url_schema() with a function-wrap schema + # that helps with validation on initialization, see _BaseUrl and _BaseMultiHostUrl below. + schema_to_mutate = schema['schema'] if schema['type'] == 'function-wrap' else schema + if annotated_type := schema_to_mutate['type'] not in ('url', 'multi-host-url'): + raise PydanticUserError( + f"'UrlConstraints' cannot annotate '{annotated_type}'.", code='invalid-annotated-type' + ) + for constraint_key, constraint_value in self.defined_constraints.items(): + schema_to_mutate[constraint_key] = constraint_value + return schema + + +class _BaseUrl: + _constraints: ClassVar[UrlConstraints] = UrlConstraints() + _url: _CoreUrl + + def __init__(self, url: str | _CoreUrl | _BaseUrl) -> None: + self._url = _build_type_adapter(self.__class__).validate_python(url)._url + + @property + def scheme(self) -> str: + """The scheme part of the URL. + + e.g. `https` in `https://user:pass@host:port/path?query#fragment` + """ + return self._url.scheme + + @property + def username(self) -> str | None: + """The username part of the URL, or `None`. + + e.g. `user` in `https://user:pass@host:port/path?query#fragment` + """ + return self._url.username + + @property + def password(self) -> str | None: + """The password part of the URL, or `None`. + + e.g. `pass` in `https://user:pass@host:port/path?query#fragment` + """ + return self._url.password + + @property + def host(self) -> str | None: + """The host part of the URL, or `None`. + + If the URL must be punycode encoded, this is the encoded host, e.g if the input URL is `https://£££.com`, + `host` will be `xn--9aaa.com` + """ + return self._url.host + + def unicode_host(self) -> str | None: + """The host part of the URL as a unicode string, or `None`. + + e.g. `host` in `https://user:pass@host:port/path?query#fragment` + + If the URL must be punycode encoded, this is the decoded host, e.g if the input URL is `https://£££.com`, + `unicode_host()` will be `£££.com` + """ + return self._url.unicode_host() + + @property + def port(self) -> int | None: + """The port part of the URL, or `None`. + + e.g. `port` in `https://user:pass@host:port/path?query#fragment` + """ + return self._url.port + + @property + def path(self) -> str | None: + """The path part of the URL, or `None`. + + e.g. `/path` in `https://user:pass@host:port/path?query#fragment` + """ + return self._url.path + + @property + def query(self) -> str | None: + """The query part of the URL, or `None`. + + e.g. `query` in `https://user:pass@host:port/path?query#fragment` + """ + return self._url.query + + def query_params(self) -> list[tuple[str, str]]: + """The query part of the URL as a list of key-value pairs. + + e.g. `[('foo', 'bar')]` in `https://user:pass@host:port/path?foo=bar#fragment` + """ + return self._url.query_params() + + @property + def fragment(self) -> str | None: + """The fragment part of the URL, or `None`. + + e.g. `fragment` in `https://user:pass@host:port/path?query#fragment` + """ + return self._url.fragment + + def unicode_string(self) -> str: + """The URL as a unicode string, unlike `__str__()` this will not punycode encode the host. + + If the URL must be punycode encoded, this is the decoded string, e.g if the input URL is `https://£££.com`, + `unicode_string()` will be `https://£££.com` + """ + return self._url.unicode_string() + + def encoded_string(self) -> str: + """The URL's encoded string representation via __str__(). + + This returns the punycode-encoded host version of the URL as a string. + """ + return str(self) + + def __str__(self) -> str: + """The URL as a string, this will punycode encode the host if required.""" + return str(self._url) + + def __repr__(self) -> str: + return f'{self.__class__.__name__}({str(self._url)!r})' + + def __deepcopy__(self, memo: dict) -> Self: + return self.__class__(self._url) + + def __eq__(self, other: Any) -> bool: + return self.__class__ is other.__class__ and self._url == other._url + + def __lt__(self, other: Any) -> bool: + return self.__class__ is other.__class__ and self._url < other._url + + def __gt__(self, other: Any) -> bool: + return self.__class__ is other.__class__ and self._url > other._url + + def __le__(self, other: Any) -> bool: + return self.__class__ is other.__class__ and self._url <= other._url + + def __ge__(self, other: Any) -> bool: + return self.__class__ is other.__class__ and self._url >= other._url + + def __hash__(self) -> int: + return hash(self._url) + + def __len__(self) -> int: + return len(str(self._url)) + + @classmethod + def build( + cls, + *, + scheme: str, + username: str | None = None, + password: str | None = None, + host: str, + port: int | None = None, + path: str | None = None, + query: str | None = None, + fragment: str | None = None, + ) -> Self: + """Build a new `Url` instance from its component parts. + + Args: + scheme: The scheme part of the URL. + username: The username part of the URL, or omit for no username. + password: The password part of the URL, or omit for no password. + host: The host part of the URL. + port: The port part of the URL, or omit for no port. + path: The path part of the URL, or omit for no path. + query: The query part of the URL, or omit for no query. + fragment: The fragment part of the URL, or omit for no fragment. + + Returns: + An instance of URL + """ + return cls( + _CoreUrl.build( + scheme=scheme, + username=username, + password=password, + host=host, + port=port, + path=path, + query=query, + fragment=fragment, + ) + ) + + @classmethod + def serialize_url(cls, url: Any, info: core_schema.SerializationInfo) -> str | Self: + if not isinstance(url, cls): + raise PydanticSerializationUnexpectedValue( + f"Expected `{cls}` but got `{type(url)}` with value `'{url}'` - serialized value may not be as expected." + ) + if info.mode == 'json': + return str(url) + return url + + @classmethod + def __get_pydantic_core_schema__( + cls, source: type[_BaseUrl], handler: GetCoreSchemaHandler + ) -> core_schema.CoreSchema: + def wrap_val(v, h): + if isinstance(v, source): + return v + if isinstance(v, _BaseUrl): + v = str(v) + core_url = h(v) + instance = source.__new__(source) + instance._url = core_url + return instance + + return core_schema.no_info_wrap_validator_function( + wrap_val, + schema=core_schema.url_schema(**cls._constraints.defined_constraints), + serialization=core_schema.plain_serializer_function_ser_schema( + cls.serialize_url, info_arg=True, when_used='always' + ), + ) + + @classmethod + def __get_pydantic_json_schema__( + cls, core_schema: core_schema.CoreSchema, handler: _schema_generation_shared.GetJsonSchemaHandler + ) -> JsonSchemaValue: + # we use the url schema for json schema generation, but we might have to extract it from + # the function-wrap schema we use as a tool for validation on initialization + inner_schema = core_schema['schema'] if core_schema['type'] == 'function-wrap' else core_schema + return handler(inner_schema) + + __pydantic_serializer__ = SchemaSerializer(core_schema.any_schema(serialization=core_schema.to_string_ser_schema())) + + +class _BaseMultiHostUrl: + _constraints: ClassVar[UrlConstraints] = UrlConstraints() + _url: _CoreMultiHostUrl + + def __init__(self, url: str | _CoreMultiHostUrl | _BaseMultiHostUrl) -> None: + self._url = _build_type_adapter(self.__class__).validate_python(url)._url + + @property + def scheme(self) -> str: + """The scheme part of the URL. + + e.g. `https` in `https://foo.com,bar.com/path?query#fragment` + """ + return self._url.scheme + + @property + def path(self) -> str | None: + """The path part of the URL, or `None`. + + e.g. `/path` in `https://foo.com,bar.com/path?query#fragment` + """ + return self._url.path + + @property + def query(self) -> str | None: + """The query part of the URL, or `None`. + + e.g. `query` in `https://foo.com,bar.com/path?query#fragment` + """ + return self._url.query + + def query_params(self) -> list[tuple[str, str]]: + """The query part of the URL as a list of key-value pairs. + + e.g. `[('foo', 'bar')]` in `https://foo.com,bar.com/path?foo=bar#fragment` + """ + return self._url.query_params() + + @property + def fragment(self) -> str | None: + """The fragment part of the URL, or `None`. + + e.g. `fragment` in `https://foo.com,bar.com/path?query#fragment` + """ + return self._url.fragment + + def hosts(self) -> list[MultiHostHost]: + '''The hosts of the `MultiHostUrl` as [`MultiHostHost`][pydantic_core.MultiHostHost] typed dicts. + + ```python + from pydantic_core import MultiHostUrl + + mhu = MultiHostUrl('https://foo.com:123,foo:bar@bar.com/path') + print(mhu.hosts()) + """ + [ + {'username': None, 'password': None, 'host': 'foo.com', 'port': 123}, + {'username': 'foo', 'password': 'bar', 'host': 'bar.com', 'port': 443} + ] + ``` + Returns: + A list of dicts, each representing a host. + ''' + return self._url.hosts() + + def encoded_string(self) -> str: + """The URL's encoded string representation via __str__(). + + This returns the punycode-encoded host version of the URL as a string. + """ + return str(self) + + def unicode_string(self) -> str: + """The URL as a unicode string, unlike `__str__()` this will not punycode encode the hosts.""" + return self._url.unicode_string() + + def __str__(self) -> str: + """The URL as a string, this will punycode encode the host if required.""" + return str(self._url) + + def __repr__(self) -> str: + return f'{self.__class__.__name__}({str(self._url)!r})' + + def __deepcopy__(self, memo: dict) -> Self: + return self.__class__(self._url) + + def __eq__(self, other: Any) -> bool: + return self.__class__ is other.__class__ and self._url == other._url + + def __hash__(self) -> int: + return hash(self._url) + + def __len__(self) -> int: + return len(str(self._url)) + + @classmethod + def build( + cls, + *, + scheme: str, + hosts: list[MultiHostHost] | None = None, + username: str | None = None, + password: str | None = None, + host: str | None = None, + port: int | None = None, + path: str | None = None, + query: str | None = None, + fragment: str | None = None, + ) -> Self: + """Build a new `MultiHostUrl` instance from its component parts. + + This method takes either `hosts` - a list of `MultiHostHost` typed dicts, or the individual components + `username`, `password`, `host` and `port`. + + Args: + scheme: The scheme part of the URL. + hosts: Multiple hosts to build the URL from. + username: The username part of the URL. + password: The password part of the URL. + host: The host part of the URL. + port: The port part of the URL. + path: The path part of the URL. + query: The query part of the URL, or omit for no query. + fragment: The fragment part of the URL, or omit for no fragment. + + Returns: + An instance of `MultiHostUrl` + """ + return cls( + _CoreMultiHostUrl.build( + scheme=scheme, + hosts=hosts, + username=username, + password=password, + host=host, + port=port, + path=path, + query=query, + fragment=fragment, + ) + ) + + @classmethod + def serialize_url(cls, url: Any, info: core_schema.SerializationInfo) -> str | Self: + if not isinstance(url, cls): + raise PydanticSerializationUnexpectedValue( + f"Expected `{cls}` but got `{type(url)}` with value `'{url}'` - serialized value may not be as expected." + ) + if info.mode == 'json': + return str(url) + return url + + @classmethod + def __get_pydantic_core_schema__( + cls, source: type[_BaseMultiHostUrl], handler: GetCoreSchemaHandler + ) -> core_schema.CoreSchema: + def wrap_val(v, h): + if isinstance(v, source): + return v + if isinstance(v, _BaseMultiHostUrl): + v = str(v) + core_url = h(v) + instance = source.__new__(source) + instance._url = core_url + return instance + + return core_schema.no_info_wrap_validator_function( + wrap_val, + schema=core_schema.multi_host_url_schema(**cls._constraints.defined_constraints), + serialization=core_schema.plain_serializer_function_ser_schema( + cls.serialize_url, info_arg=True, when_used='always' + ), + ) + + @classmethod + def __get_pydantic_json_schema__( + cls, core_schema: core_schema.CoreSchema, handler: _schema_generation_shared.GetJsonSchemaHandler + ) -> JsonSchemaValue: + # we use the url schema for json schema generation, but we might have to extract it from + # the function-wrap schema we use as a tool for validation on initialization + inner_schema = core_schema['schema'] if core_schema['type'] == 'function-wrap' else core_schema + return handler(inner_schema) + + __pydantic_serializer__ = SchemaSerializer(core_schema.any_schema(serialization=core_schema.to_string_ser_schema())) + + +@lru_cache +def _build_type_adapter(cls: type[_BaseUrl | _BaseMultiHostUrl]) -> TypeAdapter: + return TypeAdapter(cls) + + +class AnyUrl(_BaseUrl): + """Base type for all URLs. + + * Any scheme allowed + * Top-level domain (TLD) not required + * Host not required + + Assuming an input URL of `http://samuel:pass@example.com:8000/the/path/?query=here#fragment=is;this=bit`, + the types export the following properties: + + - `scheme`: the URL scheme (`http`), always set. + - `host`: the URL host (`example.com`). + - `username`: optional username if included (`samuel`). + - `password`: optional password if included (`pass`). + - `port`: optional port (`8000`). + - `path`: optional path (`/the/path/`). + - `query`: optional URL query (for example, `GET` arguments or "search string", such as `query=here`). + - `fragment`: optional fragment (`fragment=is;this=bit`). + """ + + +# Note: all single host urls inherit from `AnyUrl` to preserve compatibility with pre-v2.10 code +# Where urls were annotated variants of `AnyUrl`, which was an alias to `pydantic_core.Url` + + +class AnyHttpUrl(AnyUrl): + """A type that will accept any http or https URL. + + * TLD not required + * Host not required + """ + + _constraints = UrlConstraints(allowed_schemes=['http', 'https']) + + +class HttpUrl(AnyUrl): + """A type that will accept any http or https URL. + + * TLD not required + * Host not required + * Max length 2083 + + ```python + from pydantic import BaseModel, HttpUrl, ValidationError + + class MyModel(BaseModel): + url: HttpUrl + + m = MyModel(url='http://www.example.com') # (1)! + print(m.url) + #> http://www.example.com/ + + try: + MyModel(url='ftp://invalid.url') + except ValidationError as e: + print(e) + ''' + 1 validation error for MyModel + url + URL scheme should be 'http' or 'https' [type=url_scheme, input_value='ftp://invalid.url', input_type=str] + ''' + + try: + MyModel(url='not a url') + except ValidationError as e: + print(e) + ''' + 1 validation error for MyModel + url + Input should be a valid URL, relative URL without a base [type=url_parsing, input_value='not a url', input_type=str] + ''' + ``` + + 1. Note: mypy would prefer `m = MyModel(url=HttpUrl('http://www.example.com'))`, but Pydantic will convert the string to an HttpUrl instance anyway. + + "International domains" (e.g. a URL where the host or TLD includes non-ascii characters) will be encoded via + [punycode](https://en.wikipedia.org/wiki/Punycode) (see + [this article](https://www.xudongz.com/blog/2017/idn-phishing/) for a good description of why this is important): + + ```python + from pydantic import BaseModel, HttpUrl + + class MyModel(BaseModel): + url: HttpUrl + + m1 = MyModel(url='http://puny£code.com') + print(m1.url) + #> http://xn--punycode-eja.com/ + m2 = MyModel(url='https://www.аррӏе.com/') + print(m2.url) + #> https://www.xn--80ak6aa92e.com/ + m3 = MyModel(url='https://www.example.珠宝/') + print(m3.url) + #> https://www.example.xn--pbt977c/ + ``` + + + !!! warning "Underscores in Hostnames" + In Pydantic, underscores are allowed in all parts of a domain except the TLD. + Technically this might be wrong - in theory the hostname cannot have underscores, but subdomains can. + + To explain this; consider the following two cases: + + - `exam_ple.co.uk`: the hostname is `exam_ple`, which should not be allowed since it contains an underscore. + - `foo_bar.example.com` the hostname is `example`, which should be allowed since the underscore is in the subdomain. + + Without having an exhaustive list of TLDs, it would be impossible to differentiate between these two. Therefore + underscores are allowed, but you can always do further validation in a validator if desired. + + Also, Chrome, Firefox, and Safari all currently accept `http://exam_ple.com` as a URL, so we're in good + (or at least big) company. + """ + + _constraints = UrlConstraints(max_length=2083, allowed_schemes=['http', 'https']) + + +class AnyWebsocketUrl(AnyUrl): + """A type that will accept any ws or wss URL. + + * TLD not required + * Host not required + """ + + _constraints = UrlConstraints(allowed_schemes=['ws', 'wss']) + + +class WebsocketUrl(AnyUrl): + """A type that will accept any ws or wss URL. + + * TLD not required + * Host not required + * Max length 2083 + """ + + _constraints = UrlConstraints(max_length=2083, allowed_schemes=['ws', 'wss']) + + +class FileUrl(AnyUrl): + """A type that will accept any file URL. + + * Host not required + """ + + _constraints = UrlConstraints(allowed_schemes=['file']) + + +class FtpUrl(AnyUrl): + """A type that will accept ftp URL. + + * TLD not required + * Host not required + """ + + _constraints = UrlConstraints(allowed_schemes=['ftp']) + + +class PostgresDsn(_BaseMultiHostUrl): + """A type that will accept any Postgres DSN. + + * User info required + * TLD not required + * Host required + * Supports multiple hosts + + If further validation is required, these properties can be used by validators to enforce specific behaviour: + + ```python + from pydantic import ( + BaseModel, + HttpUrl, + PostgresDsn, + ValidationError, + field_validator, + ) + + class MyModel(BaseModel): + url: HttpUrl + + m = MyModel(url='http://www.example.com') + + # the repr() method for a url will display all properties of the url + print(repr(m.url)) + #> HttpUrl('http://www.example.com/') + print(m.url.scheme) + #> http + print(m.url.host) + #> www.example.com + print(m.url.port) + #> 80 + + class MyDatabaseModel(BaseModel): + db: PostgresDsn + + @field_validator('db') + def check_db_name(cls, v): + assert v.path and len(v.path) > 1, 'database must be provided' + return v + + m = MyDatabaseModel(db='postgres://user:pass@localhost:5432/foobar') + print(m.db) + #> postgres://user:pass@localhost:5432/foobar + + try: + MyDatabaseModel(db='postgres://user:pass@localhost:5432') + except ValidationError as e: + print(e) + ''' + 1 validation error for MyDatabaseModel + db + Assertion failed, database must be provided + assert (None) + + where None = PostgresDsn('postgres://user:pass@localhost:5432').path [type=assertion_error, input_value='postgres://user:pass@localhost:5432', input_type=str] + ''' + ``` + """ + + _constraints = UrlConstraints( + host_required=True, + allowed_schemes=[ + 'postgres', + 'postgresql', + 'postgresql+asyncpg', + 'postgresql+pg8000', + 'postgresql+psycopg', + 'postgresql+psycopg2', + 'postgresql+psycopg2cffi', + 'postgresql+py-postgresql', + 'postgresql+pygresql', + ], + ) + + @property + def host(self) -> str: + """The required URL host.""" + return self._url.host # pyright: ignore[reportAttributeAccessIssue] + + +class CockroachDsn(AnyUrl): + """A type that will accept any Cockroach DSN. + + * User info required + * TLD not required + * Host required + """ + + _constraints = UrlConstraints( + host_required=True, + allowed_schemes=[ + 'cockroachdb', + 'cockroachdb+psycopg2', + 'cockroachdb+asyncpg', + ], + ) + + @property + def host(self) -> str: + """The required URL host.""" + return self._url.host # pyright: ignore[reportReturnType] + + +class AmqpDsn(AnyUrl): + """A type that will accept any AMQP DSN. + + * User info required + * TLD not required + * Host not required + """ + + _constraints = UrlConstraints(allowed_schemes=['amqp', 'amqps']) + + +class RedisDsn(AnyUrl): + """A type that will accept any Redis DSN. + + * User info required + * TLD not required + * Host required (e.g., `rediss://:pass@localhost`) + """ + + _constraints = UrlConstraints( + allowed_schemes=['redis', 'rediss'], + default_host='localhost', + default_port=6379, + default_path='/0', + host_required=True, + ) + + @property + def host(self) -> str: + """The required URL host.""" + return self._url.host # pyright: ignore[reportReturnType] + + +class MongoDsn(_BaseMultiHostUrl): + """A type that will accept any MongoDB DSN. + + * User info not required + * Database name not required + * Port not required + * User info may be passed without user part (e.g., `mongodb://mongodb0.example.com:27017`). + + !!! warning + If a port isn't specified, the default MongoDB port `27017` will be used. If this behavior is + undesirable, you can use the following: + + ```python + from typing import Annotated + + from pydantic import UrlConstraints + from pydantic_core import MultiHostUrl + + MongoDsnNoDefaultPort = Annotated[ + MultiHostUrl, + UrlConstraints(allowed_schemes=['mongodb', 'mongodb+srv']), + ] + ``` + """ + + _constraints = UrlConstraints(allowed_schemes=['mongodb', 'mongodb+srv'], default_port=27017) + + +class KafkaDsn(AnyUrl): + """A type that will accept any Kafka DSN. + + * User info required + * TLD not required + * Host not required + """ + + _constraints = UrlConstraints(allowed_schemes=['kafka'], default_host='localhost', default_port=9092) + + +class NatsDsn(_BaseMultiHostUrl): + """A type that will accept any NATS DSN. + + NATS is a connective technology built for the ever increasingly hyper-connected world. + It is a single technology that enables applications to securely communicate across + any combination of cloud vendors, on-premise, edge, web and mobile, and devices. + More: https://nats.io + """ + + _constraints = UrlConstraints( + allowed_schemes=['nats', 'tls', 'ws', 'wss'], default_host='localhost', default_port=4222 + ) + + +class MySQLDsn(AnyUrl): + """A type that will accept any MySQL DSN. + + * User info required + * TLD not required + * Host not required + """ + + _constraints = UrlConstraints( + allowed_schemes=[ + 'mysql', + 'mysql+mysqlconnector', + 'mysql+aiomysql', + 'mysql+asyncmy', + 'mysql+mysqldb', + 'mysql+pymysql', + 'mysql+cymysql', + 'mysql+pyodbc', + ], + default_port=3306, + host_required=True, + ) + + +class MariaDBDsn(AnyUrl): + """A type that will accept any MariaDB DSN. + + * User info required + * TLD not required + * Host not required + """ + + _constraints = UrlConstraints( + allowed_schemes=['mariadb', 'mariadb+mariadbconnector', 'mariadb+pymysql'], + default_port=3306, + ) + + +class ClickHouseDsn(AnyUrl): + """A type that will accept any ClickHouse DSN. + + * User info required + * TLD not required + * Host not required + """ + + _constraints = UrlConstraints( + allowed_schemes=[ + 'clickhouse+native', + 'clickhouse+asynch', + 'clickhouse+http', + 'clickhouse', + 'clickhouses', + 'clickhousedb', + ], + default_host='localhost', + default_port=9000, + ) + + +class SnowflakeDsn(AnyUrl): + """A type that will accept any Snowflake DSN. + + * User info required + * TLD not required + * Host required + """ + + _constraints = UrlConstraints( + allowed_schemes=['snowflake'], + host_required=True, + ) + + @property + def host(self) -> str: + """The required URL host.""" + return self._url.host # pyright: ignore[reportReturnType] + + +def import_email_validator() -> None: + global email_validator + try: + import email_validator + except ImportError as e: + raise ImportError("email-validator is not installed, run `pip install 'pydantic[email]'`") from e + if not version('email-validator').partition('.')[0] == '2': + raise ImportError('email-validator version >= 2.0 required, run pip install -U email-validator') + + +if TYPE_CHECKING: + EmailStr = Annotated[str, ...] +else: + + class EmailStr: + """ + Info: + To use this type, you need to install the optional + [`email-validator`](https://github.com/JoshData/python-email-validator) package: + + ```bash + pip install email-validator + ``` + + Validate email addresses. + + ```python + from pydantic import BaseModel, EmailStr + + class Model(BaseModel): + email: EmailStr + + print(Model(email='contact@mail.com')) + #> email='contact@mail.com' + ``` + """ # noqa: D212 + + @classmethod + def __get_pydantic_core_schema__( + cls, + _source: type[Any], + _handler: GetCoreSchemaHandler, + ) -> core_schema.CoreSchema: + import_email_validator() + return core_schema.no_info_after_validator_function(cls._validate, core_schema.str_schema()) + + @classmethod + def __get_pydantic_json_schema__( + cls, core_schema: core_schema.CoreSchema, handler: _schema_generation_shared.GetJsonSchemaHandler + ) -> JsonSchemaValue: + field_schema = handler(core_schema) + field_schema.update(type='string', format='email') + return field_schema + + @classmethod + def _validate(cls, input_value: str, /) -> str: + return validate_email(input_value)[1] + + +class NameEmail(_repr.Representation): + """ + Info: + To use this type, you need to install the optional + [`email-validator`](https://github.com/JoshData/python-email-validator) package: + + ```bash + pip install email-validator + ``` + + Validate a name and email address combination, as specified by + [RFC 5322](https://datatracker.ietf.org/doc/html/rfc5322#section-3.4). + + The `NameEmail` has two properties: `name` and `email`. + In case the `name` is not provided, it's inferred from the email address. + + ```python + from pydantic import BaseModel, NameEmail + + class User(BaseModel): + email: NameEmail + + user = User(email='Fred Bloggs ') + print(user.email) + #> Fred Bloggs + print(user.email.name) + #> Fred Bloggs + + user = User(email='fred.bloggs@example.com') + print(user.email) + #> fred.bloggs + print(user.email.name) + #> fred.bloggs + ``` + """ # noqa: D212 + + __slots__ = 'name', 'email' + + def __init__(self, name: str, email: str): + self.name = name + self.email = email + + def __eq__(self, other: Any) -> bool: + return isinstance(other, NameEmail) and (self.name, self.email) == (other.name, other.email) + + @classmethod + def __get_pydantic_json_schema__( + cls, core_schema: core_schema.CoreSchema, handler: _schema_generation_shared.GetJsonSchemaHandler + ) -> JsonSchemaValue: + field_schema = handler(core_schema) + field_schema.update(type='string', format='name-email') + return field_schema + + @classmethod + def __get_pydantic_core_schema__( + cls, + _source: type[Any], + _handler: GetCoreSchemaHandler, + ) -> core_schema.CoreSchema: + import_email_validator() + + return core_schema.no_info_after_validator_function( + cls._validate, + core_schema.json_or_python_schema( + json_schema=core_schema.str_schema(), + python_schema=core_schema.union_schema( + [core_schema.is_instance_schema(cls), core_schema.str_schema()], + custom_error_type='name_email_type', + custom_error_message='Input is not a valid NameEmail', + ), + serialization=core_schema.to_string_ser_schema(), + ), + ) + + @classmethod + def _validate(cls, input_value: Self | str, /) -> Self: + if isinstance(input_value, str): + name, email = validate_email(input_value) + return cls(name, email) + else: + return input_value + + def __str__(self) -> str: + if '@' in self.name: + return f'"{self.name}" <{self.email}>' + + return f'{self.name} <{self.email}>' + + +IPvAnyAddressType: TypeAlias = 'IPv4Address | IPv6Address' +IPvAnyInterfaceType: TypeAlias = 'IPv4Interface | IPv6Interface' +IPvAnyNetworkType: TypeAlias = 'IPv4Network | IPv6Network' + +if TYPE_CHECKING: + IPvAnyAddress = IPvAnyAddressType + IPvAnyInterface = IPvAnyInterfaceType + IPvAnyNetwork = IPvAnyNetworkType +else: + + class IPvAnyAddress: + """Validate an IPv4 or IPv6 address. + + ```python + from pydantic import BaseModel + from pydantic.networks import IPvAnyAddress + + class IpModel(BaseModel): + ip: IPvAnyAddress + + print(IpModel(ip='127.0.0.1')) + #> ip=IPv4Address('127.0.0.1') + + try: + IpModel(ip='http://www.example.com') + except ValueError as e: + print(e.errors()) + ''' + [ + { + 'type': 'ip_any_address', + 'loc': ('ip',), + 'msg': 'value is not a valid IPv4 or IPv6 address', + 'input': 'http://www.example.com', + } + ] + ''' + ``` + """ + + __slots__ = () + + def __new__(cls, value: Any) -> IPvAnyAddressType: + """Validate an IPv4 or IPv6 address.""" + try: + return IPv4Address(value) + except ValueError: + pass + + try: + return IPv6Address(value) + except ValueError: + raise PydanticCustomError('ip_any_address', 'value is not a valid IPv4 or IPv6 address') + + @classmethod + def __get_pydantic_json_schema__( + cls, core_schema: core_schema.CoreSchema, handler: _schema_generation_shared.GetJsonSchemaHandler + ) -> JsonSchemaValue: + field_schema = {} + field_schema.update(type='string', format='ipvanyaddress') + return field_schema + + @classmethod + def __get_pydantic_core_schema__( + cls, + _source: type[Any], + _handler: GetCoreSchemaHandler, + ) -> core_schema.CoreSchema: + return core_schema.no_info_plain_validator_function( + cls._validate, serialization=core_schema.to_string_ser_schema() + ) + + @classmethod + def _validate(cls, input_value: Any, /) -> IPvAnyAddressType: + return cls(input_value) # type: ignore[return-value] + + class IPvAnyInterface: + """Validate an IPv4 or IPv6 interface.""" + + __slots__ = () + + def __new__(cls, value: NetworkType) -> IPvAnyInterfaceType: + """Validate an IPv4 or IPv6 interface.""" + try: + return IPv4Interface(value) + except ValueError: + pass + + try: + return IPv6Interface(value) + except ValueError: + raise PydanticCustomError('ip_any_interface', 'value is not a valid IPv4 or IPv6 interface') + + @classmethod + def __get_pydantic_json_schema__( + cls, core_schema: core_schema.CoreSchema, handler: _schema_generation_shared.GetJsonSchemaHandler + ) -> JsonSchemaValue: + field_schema = {} + field_schema.update(type='string', format='ipvanyinterface') + return field_schema + + @classmethod + def __get_pydantic_core_schema__( + cls, + _source: type[Any], + _handler: GetCoreSchemaHandler, + ) -> core_schema.CoreSchema: + return core_schema.no_info_plain_validator_function( + cls._validate, serialization=core_schema.to_string_ser_schema() + ) + + @classmethod + def _validate(cls, input_value: NetworkType, /) -> IPvAnyInterfaceType: + return cls(input_value) # type: ignore[return-value] + + class IPvAnyNetwork: + """Validate an IPv4 or IPv6 network.""" + + __slots__ = () + + def __new__(cls, value: NetworkType) -> IPvAnyNetworkType: + """Validate an IPv4 or IPv6 network.""" + # Assume IP Network is defined with a default value for `strict` argument. + # Define your own class if you want to specify network address check strictness. + try: + return IPv4Network(value) + except ValueError: + pass + + try: + return IPv6Network(value) + except ValueError: + raise PydanticCustomError('ip_any_network', 'value is not a valid IPv4 or IPv6 network') + + @classmethod + def __get_pydantic_json_schema__( + cls, core_schema: core_schema.CoreSchema, handler: _schema_generation_shared.GetJsonSchemaHandler + ) -> JsonSchemaValue: + field_schema = {} + field_schema.update(type='string', format='ipvanynetwork') + return field_schema + + @classmethod + def __get_pydantic_core_schema__( + cls, + _source: type[Any], + _handler: GetCoreSchemaHandler, + ) -> core_schema.CoreSchema: + return core_schema.no_info_plain_validator_function( + cls._validate, serialization=core_schema.to_string_ser_schema() + ) + + @classmethod + def _validate(cls, input_value: NetworkType, /) -> IPvAnyNetworkType: + return cls(input_value) # type: ignore[return-value] + + +def _build_pretty_email_regex() -> re.Pattern[str]: + name_chars = r'[\w!#$%&\'*+\-/=?^_`{|}~]' + unquoted_name_group = rf'((?:{name_chars}+\s+)*{name_chars}+)' + quoted_name_group = r'"((?:[^"]|\")+)"' + email_group = r'<(.+)>' + return re.compile(rf'\s*(?:{unquoted_name_group}|{quoted_name_group})?\s*{email_group}\s*') + + +pretty_email_regex = _build_pretty_email_regex() + +MAX_EMAIL_LENGTH = 2048 +"""Maximum length for an email. +A somewhat arbitrary but very generous number compared to what is allowed by most implementations. +""" + + +def validate_email(value: str) -> tuple[str, str]: + """Email address validation using [email-validator](https://pypi.org/project/email-validator/). + + Returns: + A tuple containing the local part of the email (or the name for "pretty" email addresses) + and the normalized email. + + Raises: + PydanticCustomError: If the email is invalid. + + Note: + Note that: + + * Raw IP address (literal) domain parts are not allowed. + * `"John Doe "` style "pretty" email addresses are processed. + * Spaces are striped from the beginning and end of addresses, but no error is raised. + """ + if email_validator is None: + import_email_validator() + + if len(value) > MAX_EMAIL_LENGTH: + raise PydanticCustomError( + 'value_error', + 'value is not a valid email address: {reason}', + {'reason': f'Length must not exceed {MAX_EMAIL_LENGTH} characters'}, + ) + + m = pretty_email_regex.fullmatch(value) + name: str | None = None + if m: + unquoted_name, quoted_name, value = m.groups() + name = unquoted_name or quoted_name + + email = value.strip() + + try: + parts = email_validator.validate_email(email, check_deliverability=False) + except email_validator.EmailNotValidError as e: + raise PydanticCustomError( + 'value_error', 'value is not a valid email address: {reason}', {'reason': str(e.args[0])} + ) from e + + email = parts.normalized + assert email is not None + name = name or parts.local_part + return name, email + + +__getattr__ = getattr_migration(__name__) diff --git a/backend/.venv/Lib/site-packages/pydantic/parse.py b/backend/.venv/Lib/site-packages/pydantic/parse.py new file mode 100644 index 0000000..68b7f04 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/parse.py @@ -0,0 +1,5 @@ +"""The `parse` module is a backport module from V1.""" + +from ._migration import getattr_migration + +__getattr__ = getattr_migration(__name__) diff --git a/backend/.venv/Lib/site-packages/pydantic/plugin/__init__.py b/backend/.venv/Lib/site-packages/pydantic/plugin/__init__.py new file mode 100644 index 0000000..840d20a --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/plugin/__init__.py @@ -0,0 +1,193 @@ +"""!!! abstract "Usage Documentation" + [Build a Plugin](../concepts/plugins.md#build-a-plugin) + +Plugin interface for Pydantic plugins, and related types. +""" + +from __future__ import annotations + +from typing import Any, Callable, Literal, NamedTuple + +from pydantic_core import CoreConfig, CoreSchema, ValidationError +from typing_extensions import Protocol, TypeAlias + +from pydantic.config import ExtraValues + +__all__ = ( + 'PydanticPluginProtocol', + 'BaseValidateHandlerProtocol', + 'ValidatePythonHandlerProtocol', + 'ValidateJsonHandlerProtocol', + 'ValidateStringsHandlerProtocol', + 'NewSchemaReturns', + 'SchemaTypePath', + 'SchemaKind', +) + +NewSchemaReturns: TypeAlias = 'tuple[ValidatePythonHandlerProtocol | None, ValidateJsonHandlerProtocol | None, ValidateStringsHandlerProtocol | None]' + + +class SchemaTypePath(NamedTuple): + """Path defining where `schema_type` was defined, or where `TypeAdapter` was called.""" + + module: str + name: str + + +SchemaKind: TypeAlias = Literal['BaseModel', 'TypeAdapter', 'dataclass', 'create_model', 'validate_call'] + + +class PydanticPluginProtocol(Protocol): + """Protocol defining the interface for Pydantic plugins.""" + + def new_schema_validator( + self, + schema: CoreSchema, + schema_type: Any, + schema_type_path: SchemaTypePath, + schema_kind: SchemaKind, + config: CoreConfig | None, + plugin_settings: dict[str, object], + ) -> tuple[ + ValidatePythonHandlerProtocol | None, ValidateJsonHandlerProtocol | None, ValidateStringsHandlerProtocol | None + ]: + """This method is called for each plugin every time a new [`SchemaValidator`][pydantic_core.SchemaValidator] + is created. + + It should return an event handler for each of the three validation methods, or `None` if the plugin does not + implement that method. + + Args: + schema: The schema to validate against. + schema_type: The original type which the schema was created from, e.g. the model class. + schema_type_path: Path defining where `schema_type` was defined, or where `TypeAdapter` was called. + schema_kind: The kind of schema to validate against. + config: The config to use for validation. + plugin_settings: Any plugin settings. + + Returns: + A tuple of optional event handlers for each of the three validation methods - + `validate_python`, `validate_json`, `validate_strings`. + """ + raise NotImplementedError('Pydantic plugins should implement `new_schema_validator`.') + + +class BaseValidateHandlerProtocol(Protocol): + """Base class for plugin callbacks protocols. + + You shouldn't implement this protocol directly, instead use one of the subclasses with adds the correctly + typed `on_error` method. + """ + + on_enter: Callable[..., None] + """`on_enter` is changed to be more specific on all subclasses""" + + def on_success(self, result: Any) -> None: + """Callback to be notified of successful validation. + + Args: + result: The result of the validation. + """ + return + + def on_error(self, error: ValidationError) -> None: + """Callback to be notified of validation errors. + + Args: + error: The validation error. + """ + return + + def on_exception(self, exception: Exception) -> None: + """Callback to be notified of validation exceptions. + + Args: + exception: The exception raised during validation. + """ + return + + +class ValidatePythonHandlerProtocol(BaseValidateHandlerProtocol, Protocol): + """Event handler for `SchemaValidator.validate_python`.""" + + def on_enter( + self, + input: Any, + *, + strict: bool | None = None, + extra: ExtraValues | None = None, + from_attributes: bool | None = None, + context: Any | None = None, + self_instance: Any | None = None, + by_alias: bool | None = None, + by_name: bool | None = None, + ) -> None: + """Callback to be notified of validation start, and create an instance of the event handler. + + Args: + input: The input to be validated. + strict: Whether to validate the object in strict mode. + extra: Whether to ignore, allow, or forbid extra data during model validation. + from_attributes: Whether to validate objects as inputs by extracting attributes. + context: The context to use for validation, this is passed to functional validators. + self_instance: An instance of a model to set attributes on from validation, this is used when running + validation from the `__init__` method of a model. + by_alias: Whether to use the field's alias to match the input data to an attribute. + by_name: Whether to use the field's name to match the input data to an attribute. + """ + + +class ValidateJsonHandlerProtocol(BaseValidateHandlerProtocol, Protocol): + """Event handler for `SchemaValidator.validate_json`.""" + + def on_enter( + self, + input: str | bytes | bytearray, + *, + strict: bool | None = None, + extra: ExtraValues | None = None, + context: Any | None = None, + self_instance: Any | None = None, + by_alias: bool | None = None, + by_name: bool | None = None, + ) -> None: + """Callback to be notified of validation start, and create an instance of the event handler. + + Args: + input: The JSON data to be validated. + strict: Whether to validate the object in strict mode. + extra: Whether to ignore, allow, or forbid extra data during model validation. + context: The context to use for validation, this is passed to functional validators. + self_instance: An instance of a model to set attributes on from validation, this is used when running + validation from the `__init__` method of a model. + by_alias: Whether to use the field's alias to match the input data to an attribute. + by_name: Whether to use the field's name to match the input data to an attribute. + """ + + +StringInput: TypeAlias = 'dict[str, StringInput]' + + +class ValidateStringsHandlerProtocol(BaseValidateHandlerProtocol, Protocol): + """Event handler for `SchemaValidator.validate_strings`.""" + + def on_enter( + self, + input: StringInput, + *, + strict: bool | None = None, + extra: ExtraValues | None = None, + context: Any | None = None, + by_alias: bool | None = None, + by_name: bool | None = None, + ) -> None: + """Callback to be notified of validation start, and create an instance of the event handler. + + Args: + input: The string data to be validated. + strict: Whether to validate the object in strict mode. + extra: Whether to ignore, allow, or forbid extra data during model validation. + context: The context to use for validation, this is passed to functional validators. + by_alias: Whether to use the field's alias to match the input data to an attribute. + by_name: Whether to use the field's name to match the input data to an attribute. + """ diff --git a/backend/.venv/Lib/site-packages/pydantic/plugin/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/plugin/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1a9e47a287bc1ed873d98ccf5e61998ef5d622f9 GIT binary patch literal 8936 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 Iterable[PydanticPluginProtocol]: + """Load plugins for Pydantic. + + Inspired by: https://github.com/pytest-dev/pluggy/blob/1.3.0/src/pluggy/_manager.py#L376-L402 + """ + disabled_plugins = os.getenv('PYDANTIC_DISABLE_PLUGINS') + global _plugins, _loading_plugins + if _loading_plugins: + # this happens when plugins themselves use pydantic, we return no plugins + return () + elif disabled_plugins in ('__all__', '1', 'true'): + return () + elif _plugins is None: + _plugins = {} + # set _loading_plugins so any plugins that use pydantic don't themselves use plugins + _loading_plugins = True + try: + for dist in importlib_metadata.distributions(): + for entry_point in dist.entry_points: + if entry_point.group != PYDANTIC_ENTRY_POINT_GROUP: + continue + if entry_point.value in _plugins: + continue + if disabled_plugins is not None and entry_point.name in disabled_plugins.split(','): + continue + try: + _plugins[entry_point.value] = entry_point.load() + except (ImportError, AttributeError) as e: + warnings.warn( + f'{e.__class__.__name__} while loading the `{entry_point.name}` Pydantic plugin, ' + f'this plugin will not be installed.\n\n{e!r}', + stacklevel=2, + ) + finally: + _loading_plugins = False + + return _plugins.values() diff --git a/backend/.venv/Lib/site-packages/pydantic/plugin/_schema_validator.py b/backend/.venv/Lib/site-packages/pydantic/plugin/_schema_validator.py new file mode 100644 index 0000000..83f2562 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/plugin/_schema_validator.py @@ -0,0 +1,140 @@ +"""Pluggable schema validator for pydantic.""" + +from __future__ import annotations + +import functools +from collections.abc import Iterable +from typing import TYPE_CHECKING, Any, Callable, Literal, TypeVar + +from pydantic_core import CoreConfig, CoreSchema, SchemaValidator, ValidationError +from typing_extensions import ParamSpec + +if TYPE_CHECKING: + from . import BaseValidateHandlerProtocol, PydanticPluginProtocol, SchemaKind, SchemaTypePath + + +P = ParamSpec('P') +R = TypeVar('R') +Event = Literal['on_validate_python', 'on_validate_json', 'on_validate_strings'] +events: list[Event] = list(Event.__args__) # type: ignore + + +def create_schema_validator( + schema: CoreSchema, + schema_type: Any, + schema_type_module: str, + schema_type_name: str, + schema_kind: SchemaKind, + config: CoreConfig | None = None, + plugin_settings: dict[str, Any] | None = None, +) -> SchemaValidator | PluggableSchemaValidator: + """Create a `SchemaValidator` or `PluggableSchemaValidator` if plugins are installed. + + Returns: + If plugins are installed then return `PluggableSchemaValidator`, otherwise return `SchemaValidator`. + """ + from . import SchemaTypePath + from ._loader import get_plugins + + plugins = get_plugins() + if plugins: + return PluggableSchemaValidator( + schema, + schema_type, + SchemaTypePath(schema_type_module, schema_type_name), + schema_kind, + config, + plugins, + plugin_settings or {}, + ) + else: + return SchemaValidator(schema, config) + + +class PluggableSchemaValidator: + """Pluggable schema validator.""" + + __slots__ = '_schema_validator', 'validate_json', 'validate_python', 'validate_strings' + + def __init__( + self, + schema: CoreSchema, + schema_type: Any, + schema_type_path: SchemaTypePath, + schema_kind: SchemaKind, + config: CoreConfig | None, + plugins: Iterable[PydanticPluginProtocol], + plugin_settings: dict[str, Any], + ) -> None: + self._schema_validator = SchemaValidator(schema, config) + + python_event_handlers: list[BaseValidateHandlerProtocol] = [] + json_event_handlers: list[BaseValidateHandlerProtocol] = [] + strings_event_handlers: list[BaseValidateHandlerProtocol] = [] + for plugin in plugins: + try: + p, j, s = plugin.new_schema_validator( + schema, schema_type, schema_type_path, schema_kind, config, plugin_settings + ) + except TypeError as e: # pragma: no cover + raise TypeError(f'Error using plugin `{plugin.__module__}:{plugin.__class__.__name__}`: {e}') from e + if p is not None: + python_event_handlers.append(p) + if j is not None: + json_event_handlers.append(j) + if s is not None: + strings_event_handlers.append(s) + + self.validate_python = build_wrapper(self._schema_validator.validate_python, python_event_handlers) + self.validate_json = build_wrapper(self._schema_validator.validate_json, json_event_handlers) + self.validate_strings = build_wrapper(self._schema_validator.validate_strings, strings_event_handlers) + + def __getattr__(self, name: str) -> Any: + return getattr(self._schema_validator, name) + + +def build_wrapper(func: Callable[P, R], event_handlers: list[BaseValidateHandlerProtocol]) -> Callable[P, R]: + if not event_handlers: + return func + else: + on_enters = tuple(h.on_enter for h in event_handlers if filter_handlers(h, 'on_enter')) + on_successes = tuple(h.on_success for h in event_handlers if filter_handlers(h, 'on_success')) + on_errors = tuple(h.on_error for h in event_handlers if filter_handlers(h, 'on_error')) + on_exceptions = tuple(h.on_exception for h in event_handlers if filter_handlers(h, 'on_exception')) + + @functools.wraps(func) + def wrapper(*args: P.args, **kwargs: P.kwargs) -> R: + for on_enter_handler in on_enters: + on_enter_handler(*args, **kwargs) + + try: + result = func(*args, **kwargs) + except ValidationError as error: + for on_error_handler in on_errors: + on_error_handler(error) + raise + except Exception as exception: + for on_exception_handler in on_exceptions: + on_exception_handler(exception) + raise + else: + for on_success_handler in on_successes: + on_success_handler(result) + return result + + return wrapper + + +def filter_handlers(handler_cls: BaseValidateHandlerProtocol, method_name: str) -> bool: + """Filter out handler methods which are not implemented by the plugin directly - e.g. are missing + or are inherited from the protocol. + """ + handler = getattr(handler_cls, method_name, None) + if handler is None: + return False + elif handler.__module__ == 'pydantic.plugin': + # this is the original handler, from the protocol due to runtime inheritance + # we don't want to call it + return False + else: + return True diff --git a/backend/.venv/Lib/site-packages/pydantic/py.typed b/backend/.venv/Lib/site-packages/pydantic/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/pydantic/root_model.py b/backend/.venv/Lib/site-packages/pydantic/root_model.py new file mode 100644 index 0000000..80a5420 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/root_model.py @@ -0,0 +1,155 @@ +"""RootModel class and type definitions.""" + +from __future__ import annotations as _annotations + +from copy import copy, deepcopy +from typing import TYPE_CHECKING, Any, Generic, Literal, TypeVar + +from pydantic_core import PydanticUndefined +from typing_extensions import Self, dataclass_transform + +from . import PydanticUserError +from ._internal import _model_construction, _repr +from .main import BaseModel, _object_setattr + +if TYPE_CHECKING: + from .fields import Field as PydanticModelField + from .fields import PrivateAttr as PydanticModelPrivateAttr + + # dataclass_transform could be applied to RootModel directly, but `ModelMetaclass`'s dataclass_transform + # takes priority (at least with pyright). We trick type checkers into thinking we apply dataclass_transform + # on a new metaclass. + @dataclass_transform(kw_only_default=False, field_specifiers=(PydanticModelField, PydanticModelPrivateAttr)) + class _RootModelMetaclass(_model_construction.ModelMetaclass): ... +else: + _RootModelMetaclass = _model_construction.ModelMetaclass + +__all__ = ('RootModel',) + +RootModelRootType = TypeVar('RootModelRootType') + + +class RootModel(BaseModel, Generic[RootModelRootType], metaclass=_RootModelMetaclass): + """!!! abstract "Usage Documentation" + [`RootModel` and Custom Root Types](../concepts/models.md#rootmodel-and-custom-root-types) + + A Pydantic `BaseModel` for the root object of the model. + + Attributes: + root: The root object of the model. + __pydantic_root_model__: Whether the model is a RootModel. + __pydantic_private__: Private fields in the model. + __pydantic_extra__: Extra fields in the model. + + """ + + __pydantic_root_model__ = True + __pydantic_private__ = None + __pydantic_extra__ = None + + root: RootModelRootType + + def __init_subclass__(cls, **kwargs): + extra = cls.model_config.get('extra') + if extra is not None: + raise PydanticUserError( + "`RootModel` does not support setting `model_config['extra']`", code='root-model-extra' + ) + super().__init_subclass__(**kwargs) + + def __init__(self, /, root: RootModelRootType = PydanticUndefined, **data) -> None: # type: ignore + __tracebackhide__ = True + if data: + if root is not PydanticUndefined: + raise ValueError( + '"RootModel.__init__" accepts either a single positional argument or arbitrary keyword arguments' + ) + root = data # type: ignore + self.__pydantic_validator__.validate_python(root, self_instance=self) + + __init__.__pydantic_base_init__ = True # pyright: ignore[reportFunctionMemberAccess] + + @classmethod + def model_construct(cls, root: RootModelRootType, _fields_set: set[str] | None = None) -> Self: # type: ignore + """Create a new model using the provided root object and update fields set. + + Args: + root: The root object of the model. + _fields_set: The set of fields to be updated. + + Returns: + The new model. + + Raises: + NotImplemented: If the model is not a subclass of `RootModel`. + """ + return super().model_construct(root=root, _fields_set=_fields_set) + + def __getstate__(self) -> dict[Any, Any]: + return { + '__dict__': self.__dict__, + '__pydantic_fields_set__': self.__pydantic_fields_set__, + } + + def __setstate__(self, state: dict[Any, Any]) -> None: + _object_setattr(self, '__pydantic_fields_set__', state['__pydantic_fields_set__']) + _object_setattr(self, '__dict__', state['__dict__']) + + def __copy__(self) -> Self: + """Returns a shallow copy of the model.""" + cls = type(self) + m = cls.__new__(cls) + _object_setattr(m, '__dict__', copy(self.__dict__)) + _object_setattr(m, '__pydantic_fields_set__', copy(self.__pydantic_fields_set__)) + return m + + def __deepcopy__(self, memo: dict[int, Any] | None = None) -> Self: + """Returns a deep copy of the model.""" + cls = type(self) + m = cls.__new__(cls) + _object_setattr(m, '__dict__', deepcopy(self.__dict__, memo=memo)) + # This next line doesn't need a deepcopy because __pydantic_fields_set__ is a set[str], + # and attempting a deepcopy would be marginally slower. + _object_setattr(m, '__pydantic_fields_set__', copy(self.__pydantic_fields_set__)) + return m + + if TYPE_CHECKING: + + def model_dump( # type: ignore + self, + *, + mode: Literal['json', 'python'] | str = 'python', + include: Any = None, + exclude: Any = None, + context: dict[str, Any] | None = None, + by_alias: bool | None = None, + exclude_unset: bool = False, + exclude_defaults: bool = False, + exclude_none: bool = False, + exclude_computed_fields: bool = False, + round_trip: bool = False, + warnings: bool | Literal['none', 'warn', 'error'] = True, + serialize_as_any: bool = False, + ) -> Any: + """This method is included just to get a more accurate return type for type checkers. + It is included in this `if TYPE_CHECKING:` block since no override is actually necessary. + + See the documentation of `BaseModel.model_dump` for more details about the arguments. + + Generally, this method will have a return type of `RootModelRootType`, assuming that `RootModelRootType` is + not a `BaseModel` subclass. If `RootModelRootType` is a `BaseModel` subclass, then the return + type will likely be `dict[str, Any]`, as `model_dump` calls are recursive. The return type could + even be something different, in the case of a custom serializer. + Thus, `Any` is used here to catch all of these cases. + """ + ... + + def __eq__(self, other: Any) -> bool: + if not isinstance(other, RootModel): + return NotImplemented + return self.__pydantic_fields__['root'].annotation == other.__pydantic_fields__[ + 'root' + ].annotation and super().__eq__(other) + + def __repr_args__(self) -> _repr.ReprArgs: + yield 'root', self.root diff --git a/backend/.venv/Lib/site-packages/pydantic/schema.py b/backend/.venv/Lib/site-packages/pydantic/schema.py new file mode 100644 index 0000000..a3245a6 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/schema.py @@ -0,0 +1,5 @@ +"""The `schema` module is a backport module from V1.""" + +from ._migration import getattr_migration + +__getattr__ = getattr_migration(__name__) diff --git a/backend/.venv/Lib/site-packages/pydantic/tools.py b/backend/.venv/Lib/site-packages/pydantic/tools.py new file mode 100644 index 0000000..fdc68c4 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/tools.py @@ -0,0 +1,5 @@ +"""The `tools` module is a backport module from V1.""" + +from ._migration import getattr_migration + +__getattr__ = getattr_migration(__name__) diff --git a/backend/.venv/Lib/site-packages/pydantic/type_adapter.py b/backend/.venv/Lib/site-packages/pydantic/type_adapter.py new file mode 100644 index 0000000..6f1a082 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/type_adapter.py @@ -0,0 +1,795 @@ +"""Type adapter specification.""" + +from __future__ import annotations as _annotations + +import sys +import types +from collections.abc import Callable, Iterable +from dataclasses import is_dataclass +from types import FrameType +from typing import ( + Any, + Generic, + Literal, + TypeVar, + cast, + final, + overload, +) + +from pydantic_core import CoreSchema, SchemaSerializer, SchemaValidator, Some +from typing_extensions import ParamSpec, is_typeddict + +from pydantic.errors import PydanticUserError +from pydantic.main import BaseModel, IncEx + +from ._internal import _config, _generate_schema, _mock_val_ser, _namespace_utils, _repr, _typing_extra, _utils +from .config import ConfigDict, ExtraValues +from .errors import PydanticUndefinedAnnotation +from .json_schema import ( + DEFAULT_REF_TEMPLATE, + GenerateJsonSchema, + JsonSchemaKeyT, + JsonSchemaMode, + JsonSchemaValue, +) +from .plugin._schema_validator import PluggableSchemaValidator, create_schema_validator + +T = TypeVar('T') +R = TypeVar('R') +P = ParamSpec('P') +TypeAdapterT = TypeVar('TypeAdapterT', bound='TypeAdapter') + + +def _getattr_no_parents(obj: Any, attribute: str) -> Any: + """Returns the attribute value without attempting to look up attributes from parent types.""" + if hasattr(obj, '__dict__'): + try: + return obj.__dict__[attribute] + except KeyError: + pass + + slots = getattr(obj, '__slots__', None) + if slots is not None and attribute in slots: + return getattr(obj, attribute) + else: + raise AttributeError(attribute) + + +def _type_has_config(type_: Any) -> bool: + """Returns whether the type has config.""" + type_ = _typing_extra.annotated_type(type_) or type_ + try: + return issubclass(type_, BaseModel) or is_dataclass(type_) or is_typeddict(type_) + except TypeError: + # type is not a class + return False + + +@final +class TypeAdapter(Generic[T]): + """!!! abstract "Usage Documentation" + [`TypeAdapter`](../concepts/type_adapter.md) + + Type adapters provide a flexible way to perform validation and serialization based on a Python type. + + A `TypeAdapter` instance exposes some of the functionality from `BaseModel` instance methods + for types that do not have such methods (such as dataclasses, primitive types, and more). + + **Note:** `TypeAdapter` instances are not types, and cannot be used as type annotations for fields. + + Args: + type: The type associated with the `TypeAdapter`. + config: Configuration for the `TypeAdapter`, should be a dictionary conforming to + [`ConfigDict`][pydantic.config.ConfigDict]. + + !!! note + You cannot provide a configuration when instantiating a `TypeAdapter` if the type you're using + has its own config that cannot be overridden (ex: `BaseModel`, `TypedDict`, and `dataclass`). A + [`type-adapter-config-unused`](../errors/usage_errors.md#type-adapter-config-unused) error will + be raised in this case. + _parent_depth: Depth at which to search for the [parent frame][frame-objects]. This frame is used when + resolving forward annotations during schema building, by looking for the globals and locals of this + frame. Defaults to 2, which will result in the frame where the `TypeAdapter` was instantiated. + + !!! note + This parameter is named with an underscore to suggest its private nature and discourage use. + It may be deprecated in a minor version, so we only recommend using it if you're comfortable + with potential change in behavior/support. It's default value is 2 because internally, + the `TypeAdapter` class makes another call to fetch the frame. + module: The module that passes to plugin if provided. + + Attributes: + core_schema: The core schema for the type. + validator: The schema validator for the type. + serializer: The schema serializer for the type. + pydantic_complete: Whether the core schema for the type is successfully built. + + ??? tip "Compatibility with `mypy`" + Depending on the type used, `mypy` might raise an error when instantiating a `TypeAdapter`. As a workaround, you can explicitly + annotate your variable: + + ```py + from typing import Union + + from pydantic import TypeAdapter + + ta: TypeAdapter[Union[str, int]] = TypeAdapter(Union[str, int]) # type: ignore[arg-type] + ``` + + ??? info "Namespace management nuances and implementation details" + + Here, we collect some notes on namespace management, and subtle differences from `BaseModel`: + + `BaseModel` uses its own `__module__` to find out where it was defined + and then looks for symbols to resolve forward references in those globals. + On the other hand, `TypeAdapter` can be initialized with arbitrary objects, + which may not be types and thus do not have a `__module__` available. + So instead we look at the globals in our parent stack frame. + + It is expected that the `ns_resolver` passed to this function will have the correct + namespace for the type we're adapting. See the source code for `TypeAdapter.__init__` + and `TypeAdapter.rebuild` for various ways to construct this namespace. + + This works for the case where this function is called in a module that + has the target of forward references in its scope, but + does not always work for more complex cases. + + For example, take the following: + + ```python {title="a.py"} + IntList = list[int] + OuterDict = dict[str, 'IntList'] + ``` + + ```python {test="skip" title="b.py"} + from a import OuterDict + + from pydantic import TypeAdapter + + IntList = int # replaces the symbol the forward reference is looking for + v = TypeAdapter(OuterDict) + v({'x': 1}) # should fail but doesn't + ``` + + If `OuterDict` were a `BaseModel`, this would work because it would resolve + the forward reference within the `a.py` namespace. + But `TypeAdapter(OuterDict)` can't determine what module `OuterDict` came from. + + In other words, the assumption that _all_ forward references exist in the + module we are being called from is not technically always true. + Although most of the time it is and it works fine for recursive models and such, + `BaseModel`'s behavior isn't perfect either and _can_ break in similar ways, + so there is no right or wrong between the two. + + But at the very least this behavior is _subtly_ different from `BaseModel`'s. + """ + + core_schema: CoreSchema + validator: SchemaValidator | PluggableSchemaValidator + serializer: SchemaSerializer + pydantic_complete: bool + + @overload + def __init__( + self, + type: type[T], + *, + config: ConfigDict | None = ..., + _parent_depth: int = ..., + module: str | None = ..., + ) -> None: ... + + # This second overload is for unsupported special forms (such as Annotated, Union, etc.) + # Currently there is no way to type this correctly + # See https://github.com/python/typing/pull/1618 + @overload + def __init__( + self, + type: Any, + *, + config: ConfigDict | None = ..., + _parent_depth: int = ..., + module: str | None = ..., + ) -> None: ... + + def __init__( + self, + type: Any, + *, + config: ConfigDict | None = None, + _parent_depth: int = 2, + module: str | None = None, + ) -> None: + if _type_has_config(type) and config is not None: + raise PydanticUserError( + 'Cannot use `config` when the type is a BaseModel, dataclass or TypedDict.' + ' These types can have their own config and setting the config via the `config`' + ' parameter to TypeAdapter will not override it, thus the `config` you passed to' + ' TypeAdapter becomes meaningless, which is probably not what you want.', + code='type-adapter-config-unused', + ) + + self._type = type + self._config = config + self._parent_depth = _parent_depth + self.pydantic_complete = False + + parent_frame = self._fetch_parent_frame() + if isinstance(type, types.FunctionType): + # Special case functions, which are *not* pushed to the `NsResolver` stack and without this special case + # would only have access to the parent namespace where the `TypeAdapter` was instantiated (if the function is defined + # in another module, we need to look at that module's globals). + if parent_frame is not None: + # `f_locals` is the namespace where the type adapter was instantiated (~ to `f_globals` if at the module level): + parent_ns = parent_frame.f_locals + else: # pragma: no cover + parent_ns = None + globalns, localns = _namespace_utils.ns_for_function( + type, + parent_namespace=parent_ns, + ) + parent_namespace = None + else: + if parent_frame is not None: + globalns = parent_frame.f_globals + # Do not provide a local ns if the type adapter happens to be instantiated at the module level: + localns = parent_frame.f_locals if parent_frame.f_locals is not globalns else {} + else: # pragma: no cover + globalns = {} + localns = {} + parent_namespace = localns + + self._module_name = module or cast(str, globalns.get('__name__', '')) + self._init_core_attrs( + ns_resolver=_namespace_utils.NsResolver( + namespaces_tuple=_namespace_utils.NamespacesTuple(locals=localns, globals=globalns), + parent_namespace=parent_namespace, + ), + force=False, + ) + + def _fetch_parent_frame(self) -> FrameType | None: + frame = sys._getframe(self._parent_depth) + if frame.f_globals.get('__name__') == 'typing': + # Because `TypeAdapter` is generic, explicitly parametrizing the class results + # in a `typing._GenericAlias` instance, which proxies instantiation calls to the + # "real" `TypeAdapter` class and thus adding an extra frame to the call. To avoid + # pulling anything from the `typing` module, use the correct frame (the one before): + return frame.f_back + + return frame + + def _init_core_attrs( + self, ns_resolver: _namespace_utils.NsResolver, force: bool, raise_errors: bool = False + ) -> bool: + """Initialize the core schema, validator, and serializer for the type. + + Args: + ns_resolver: The namespace resolver to use when building the core schema for the adapted type. + force: Whether to force the construction of the core schema, validator, and serializer. + If `force` is set to `False` and `_defer_build` is `True`, the core schema, validator, and serializer will be set to mocks. + raise_errors: Whether to raise errors if initializing any of the core attrs fails. + + Returns: + `True` if the core schema, validator, and serializer were successfully initialized, otherwise `False`. + + Raises: + PydanticUndefinedAnnotation: If `PydanticUndefinedAnnotation` occurs in`__get_pydantic_core_schema__` + and `raise_errors=True`. + """ + if not force and self._defer_build: + _mock_val_ser.set_type_adapter_mocks(self) + self.pydantic_complete = False + return False + + try: + self.core_schema = _getattr_no_parents(self._type, '__pydantic_core_schema__') + self.validator = _getattr_no_parents(self._type, '__pydantic_validator__') + self.serializer = _getattr_no_parents(self._type, '__pydantic_serializer__') + + # TODO: we don't go through the rebuild logic here directly because we don't want + # to repeat all of the namespace fetching logic that we've already done + # so we simply skip to the block below that does the actual schema generation + if ( + isinstance(self.core_schema, _mock_val_ser.MockCoreSchema) + or isinstance(self.validator, _mock_val_ser.MockValSer) + or isinstance(self.serializer, _mock_val_ser.MockValSer) + ): + raise AttributeError() + except AttributeError: + config_wrapper = _config.ConfigWrapper(self._config) + + schema_generator = _generate_schema.GenerateSchema(config_wrapper, ns_resolver=ns_resolver) + + try: + core_schema = schema_generator.generate_schema(self._type) + except PydanticUndefinedAnnotation: + if raise_errors: + raise + _mock_val_ser.set_type_adapter_mocks(self) + return False + + try: + self.core_schema = schema_generator.clean_schema(core_schema) + except _generate_schema.InvalidSchemaError: + _mock_val_ser.set_type_adapter_mocks(self) + return False + + core_config = config_wrapper.core_config(None) + + self.validator = create_schema_validator( + schema=self.core_schema, + schema_type=self._type, + schema_type_module=self._module_name, + schema_type_name=str(self._type), + schema_kind='TypeAdapter', + config=core_config, + plugin_settings=config_wrapper.plugin_settings, + ) + self.serializer = SchemaSerializer(self.core_schema, core_config) + + self.pydantic_complete = True + return True + + @property + def _defer_build(self) -> bool: + config = self._config if self._config is not None else self._model_config + if config: + return config.get('defer_build') is True + return False + + @property + def _model_config(self) -> ConfigDict | None: + type_: Any = _typing_extra.annotated_type(self._type) or self._type # Eg FastAPI heavily uses Annotated + if _utils.lenient_issubclass(type_, BaseModel): + return type_.model_config + return getattr(type_, '__pydantic_config__', None) + + def __repr__(self) -> str: + return f'TypeAdapter({_repr.display_as_type(self._type)})' + + def rebuild( + self, + *, + force: bool = False, + raise_errors: bool = True, + _parent_namespace_depth: int = 2, + _types_namespace: _namespace_utils.MappingNamespace | None = None, + ) -> bool | None: + """Try to rebuild the pydantic-core schema for the adapter's type. + + This may be necessary when one of the annotations is a ForwardRef which could not be resolved during + the initial attempt to build the schema, and automatic rebuilding fails. + + Args: + force: Whether to force the rebuilding of the type adapter's schema, defaults to `False`. + raise_errors: Whether to raise errors, defaults to `True`. + _parent_namespace_depth: Depth at which to search for the [parent frame][frame-objects]. This + frame is used when resolving forward annotations during schema rebuilding, by looking for + the locals of this frame. Defaults to 2, which will result in the frame where the method + was called. + _types_namespace: An explicit types namespace to use, instead of using the local namespace + from the parent frame. Defaults to `None`. + + Returns: + Returns `None` if the schema is already "complete" and rebuilding was not required. + If rebuilding _was_ required, returns `True` if rebuilding was successful, otherwise `False`. + """ + if not force and self.pydantic_complete: + return None + + if _types_namespace is not None: + rebuild_ns = _types_namespace + elif _parent_namespace_depth > 0: + rebuild_ns = _typing_extra.parent_frame_namespace(parent_depth=_parent_namespace_depth, force=True) or {} + else: + rebuild_ns = {} + + # we have to manually fetch globals here because there's no type on the stack of the NsResolver + # and so we skip the globalns = get_module_ns_of(typ) call that would normally happen + globalns = sys._getframe(max(_parent_namespace_depth - 1, 1)).f_globals + ns_resolver = _namespace_utils.NsResolver( + namespaces_tuple=_namespace_utils.NamespacesTuple(locals=rebuild_ns, globals=globalns), + parent_namespace=rebuild_ns, + ) + return self._init_core_attrs(ns_resolver=ns_resolver, force=True, raise_errors=raise_errors) + + def validate_python( + self, + object: Any, + /, + *, + strict: bool | None = None, + extra: ExtraValues | None = None, + from_attributes: bool | None = None, + context: Any | None = None, + experimental_allow_partial: bool | Literal['off', 'on', 'trailing-strings'] = False, + by_alias: bool | None = None, + by_name: bool | None = None, + ) -> T: + """Validate a Python object against the model. + + Args: + object: The Python object to validate against the model. + strict: Whether to strictly check types. + extra: Whether to ignore, allow, or forbid extra data during model validation. + See the [`extra` configuration value][pydantic.ConfigDict.extra] for details. + from_attributes: Whether to extract data from object attributes. + context: Additional context to pass to the validator. + experimental_allow_partial: **Experimental** whether to enable + [partial validation](../concepts/experimental.md#partial-validation), e.g. to process streams. + * False / 'off': Default behavior, no partial validation. + * True / 'on': Enable partial validation. + * 'trailing-strings': Enable partial validation and allow trailing strings in the input. + by_alias: Whether to use the field's alias when validating against the provided input data. + by_name: Whether to use the field's name when validating against the provided input data. + + !!! note + When using `TypeAdapter` with a Pydantic `dataclass`, the use of the `from_attributes` + argument is not supported. + + Returns: + The validated object. + """ + if by_alias is False and by_name is not True: + raise PydanticUserError( + 'At least one of `by_alias` or `by_name` must be set to True.', + code='validate-by-alias-and-name-false', + ) + + return self.validator.validate_python( + object, + strict=strict, + extra=extra, + from_attributes=from_attributes, + context=context, + allow_partial=experimental_allow_partial, + by_alias=by_alias, + by_name=by_name, + ) + + def validate_json( + self, + data: str | bytes | bytearray, + /, + *, + strict: bool | None = None, + extra: ExtraValues | None = None, + context: Any | None = None, + experimental_allow_partial: bool | Literal['off', 'on', 'trailing-strings'] = False, + by_alias: bool | None = None, + by_name: bool | None = None, + ) -> T: + """!!! abstract "Usage Documentation" + [JSON Parsing](../concepts/json.md#json-parsing) + + Validate a JSON string or bytes against the model. + + Args: + data: The JSON data to validate against the model. + strict: Whether to strictly check types. + extra: Whether to ignore, allow, or forbid extra data during model validation. + See the [`extra` configuration value][pydantic.ConfigDict.extra] for details. + context: Additional context to use during validation. + experimental_allow_partial: **Experimental** whether to enable + [partial validation](../concepts/experimental.md#partial-validation), e.g. to process streams. + * False / 'off': Default behavior, no partial validation. + * True / 'on': Enable partial validation. + * 'trailing-strings': Enable partial validation and allow trailing strings in the input. + by_alias: Whether to use the field's alias when validating against the provided input data. + by_name: Whether to use the field's name when validating against the provided input data. + + Returns: + The validated object. + """ + if by_alias is False and by_name is not True: + raise PydanticUserError( + 'At least one of `by_alias` or `by_name` must be set to True.', + code='validate-by-alias-and-name-false', + ) + + return self.validator.validate_json( + data, + strict=strict, + extra=extra, + context=context, + allow_partial=experimental_allow_partial, + by_alias=by_alias, + by_name=by_name, + ) + + def validate_strings( + self, + obj: Any, + /, + *, + strict: bool | None = None, + extra: ExtraValues | None = None, + context: Any | None = None, + experimental_allow_partial: bool | Literal['off', 'on', 'trailing-strings'] = False, + by_alias: bool | None = None, + by_name: bool | None = None, + ) -> T: + """Validate object contains string data against the model. + + Args: + obj: The object contains string data to validate. + strict: Whether to strictly check types. + extra: Whether to ignore, allow, or forbid extra data during model validation. + See the [`extra` configuration value][pydantic.ConfigDict.extra] for details. + context: Additional context to use during validation. + experimental_allow_partial: **Experimental** whether to enable + [partial validation](../concepts/experimental.md#partial-validation), e.g. to process streams. + * False / 'off': Default behavior, no partial validation. + * True / 'on': Enable partial validation. + * 'trailing-strings': Enable partial validation and allow trailing strings in the input. + by_alias: Whether to use the field's alias when validating against the provided input data. + by_name: Whether to use the field's name when validating against the provided input data. + + Returns: + The validated object. + """ + if by_alias is False and by_name is not True: + raise PydanticUserError( + 'At least one of `by_alias` or `by_name` must be set to True.', + code='validate-by-alias-and-name-false', + ) + + return self.validator.validate_strings( + obj, + strict=strict, + extra=extra, + context=context, + allow_partial=experimental_allow_partial, + by_alias=by_alias, + by_name=by_name, + ) + + def get_default_value(self, *, strict: bool | None = None, context: Any | None = None) -> Some[T] | None: + """Get the default value for the wrapped type. + + Args: + strict: Whether to strictly check types. + context: Additional context to pass to the validator. + + Returns: + The default value wrapped in a `Some` if there is one or None if not. + """ + return self.validator.get_default_value(strict=strict, context=context) + + def dump_python( + self, + instance: T, + /, + *, + mode: Literal['json', 'python'] = 'python', + include: IncEx | None = None, + exclude: IncEx | None = None, + by_alias: bool | None = None, + exclude_unset: bool = False, + exclude_defaults: bool = False, + exclude_none: bool = False, + exclude_computed_fields: bool = False, + round_trip: bool = False, + warnings: bool | Literal['none', 'warn', 'error'] = True, + fallback: Callable[[Any], Any] | None = None, + serialize_as_any: bool = False, + context: Any | None = None, + ) -> Any: + """Dump an instance of the adapted type to a Python object. + + Args: + instance: The Python object to serialize. + mode: The output format. + include: Fields to include in the output. + exclude: Fields to exclude from the output. + by_alias: Whether to use alias names for field names. + exclude_unset: Whether to exclude unset fields. + exclude_defaults: Whether to exclude fields with default values. + exclude_none: Whether to exclude fields with None values. + exclude_computed_fields: Whether to exclude computed fields. + While this can be useful for round-tripping, it is usually recommended to use the dedicated + `round_trip` parameter instead. + round_trip: Whether to output the serialized data in a way that is compatible with deserialization. + warnings: How to handle serialization errors. False/"none" ignores them, True/"warn" logs errors, + "error" raises a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError]. + fallback: A function to call when an unknown value is encountered. If not provided, + a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError] error is raised. + serialize_as_any: Whether to serialize fields with duck-typing serialization behavior. + context: Additional context to pass to the serializer. + + Returns: + The serialized object. + """ + return self.serializer.to_python( + instance, + mode=mode, + by_alias=by_alias, + include=include, + exclude=exclude, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + exclude_computed_fields=exclude_computed_fields, + round_trip=round_trip, + warnings=warnings, + fallback=fallback, + serialize_as_any=serialize_as_any, + context=context, + ) + + def dump_json( + self, + instance: T, + /, + *, + indent: int | None = None, + ensure_ascii: bool = False, + include: IncEx | None = None, + exclude: IncEx | None = None, + by_alias: bool | None = None, + exclude_unset: bool = False, + exclude_defaults: bool = False, + exclude_none: bool = False, + exclude_computed_fields: bool = False, + round_trip: bool = False, + warnings: bool | Literal['none', 'warn', 'error'] = True, + fallback: Callable[[Any], Any] | None = None, + serialize_as_any: bool = False, + context: Any | None = None, + ) -> bytes: + """!!! abstract "Usage Documentation" + [JSON Serialization](../concepts/json.md#json-serialization) + + Serialize an instance of the adapted type to JSON. + + Args: + instance: The instance to be serialized. + indent: Number of spaces for JSON indentation. + ensure_ascii: If `True`, the output is guaranteed to have all incoming non-ASCII characters escaped. + If `False` (the default), these characters will be output as-is. + include: Fields to include. + exclude: Fields to exclude. + by_alias: Whether to use alias names for field names. + exclude_unset: Whether to exclude unset fields. + exclude_defaults: Whether to exclude fields with default values. + exclude_none: Whether to exclude fields with a value of `None`. + exclude_computed_fields: Whether to exclude computed fields. + While this can be useful for round-tripping, it is usually recommended to use the dedicated + `round_trip` parameter instead. + round_trip: Whether to serialize and deserialize the instance to ensure round-tripping. + warnings: How to handle serialization errors. False/"none" ignores them, True/"warn" logs errors, + "error" raises a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError]. + fallback: A function to call when an unknown value is encountered. If not provided, + a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError] error is raised. + serialize_as_any: Whether to serialize fields with duck-typing serialization behavior. + context: Additional context to pass to the serializer. + + Returns: + The JSON representation of the given instance as bytes. + """ + return self.serializer.to_json( + instance, + indent=indent, + ensure_ascii=ensure_ascii, + include=include, + exclude=exclude, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + exclude_computed_fields=exclude_computed_fields, + round_trip=round_trip, + warnings=warnings, + fallback=fallback, + serialize_as_any=serialize_as_any, + context=context, + ) + + def json_schema( + self, + *, + by_alias: bool = True, + ref_template: str = DEFAULT_REF_TEMPLATE, + union_format: Literal['any_of', 'primitive_type_array'] = 'any_of', + schema_generator: type[GenerateJsonSchema] = GenerateJsonSchema, + mode: JsonSchemaMode = 'validation', + ) -> dict[str, Any]: + """Generate a JSON schema for the adapted type. + + Args: + by_alias: Whether to use alias names for field names. + ref_template: The format string used for generating $ref strings. + union_format: The format to use when combining schemas from unions together. Can be one of: + + - `'any_of'`: Use the [`anyOf`](https://json-schema.org/understanding-json-schema/reference/combining#anyOf) + keyword to combine schemas (the default). + - `'primitive_type_array'`: Use the [`type`](https://json-schema.org/understanding-json-schema/reference/type) + keyword as an array of strings, containing each type of the combination. If any of the schemas is not a primitive + type (`string`, `boolean`, `null`, `integer` or `number`) or contains constraints/metadata, falls back to + `any_of`. + schema_generator: To override the logic used to generate the JSON schema, as a subclass of + `GenerateJsonSchema` with your desired modifications + mode: The mode in which to generate the schema. + schema_generator: The generator class used for creating the schema. + mode: The mode to use for schema generation. + + Returns: + The JSON schema for the model as a dictionary. + """ + schema_generator_instance = schema_generator( + by_alias=by_alias, ref_template=ref_template, union_format=union_format + ) + if isinstance(self.core_schema, _mock_val_ser.MockCoreSchema): + self.core_schema.rebuild() + assert not isinstance(self.core_schema, _mock_val_ser.MockCoreSchema), 'this is a bug! please report it' + return schema_generator_instance.generate(self.core_schema, mode=mode) + + @staticmethod + def json_schemas( + inputs: Iterable[tuple[JsonSchemaKeyT, JsonSchemaMode, TypeAdapter[Any]]], + /, + *, + by_alias: bool = True, + title: str | None = None, + description: str | None = None, + ref_template: str = DEFAULT_REF_TEMPLATE, + union_format: Literal['any_of', 'primitive_type_array'] = 'any_of', + schema_generator: type[GenerateJsonSchema] = GenerateJsonSchema, + ) -> tuple[dict[tuple[JsonSchemaKeyT, JsonSchemaMode], JsonSchemaValue], JsonSchemaValue]: + """Generate a JSON schema including definitions from multiple type adapters. + + Args: + inputs: Inputs to schema generation. The first two items will form the keys of the (first) + output mapping; the type adapters will provide the core schemas that get converted into + definitions in the output JSON schema. + by_alias: Whether to use alias names. + title: The title for the schema. + description: The description for the schema. + ref_template: The format string used for generating $ref strings. + union_format: The format to use when combining schemas from unions together. Can be one of: + + - `'any_of'`: Use the [`anyOf`](https://json-schema.org/understanding-json-schema/reference/combining#anyOf) + keyword to combine schemas (the default). + - `'primitive_type_array'`: Use the [`type`](https://json-schema.org/understanding-json-schema/reference/type) + keyword as an array of strings, containing each type of the combination. If any of the schemas is not a primitive + type (`string`, `boolean`, `null`, `integer` or `number`) or contains constraints/metadata, falls back to + `any_of`. + schema_generator: The generator class used for creating the schema. + + Returns: + A tuple where: + + - The first element is a dictionary whose keys are tuples of JSON schema key type and JSON mode, and + whose values are the JSON schema corresponding to that pair of inputs. (These schemas may have + JsonRef references to definitions that are defined in the second returned element.) + - The second element is a JSON schema containing all definitions referenced in the first returned + element, along with the optional title and description keys. + + """ + schema_generator_instance = schema_generator( + by_alias=by_alias, ref_template=ref_template, union_format=union_format + ) + + inputs_ = [] + for key, mode, adapter in inputs: + # This is the same pattern we follow for model json schemas - we attempt a core schema rebuild if we detect a mock + if isinstance(adapter.core_schema, _mock_val_ser.MockCoreSchema): + adapter.core_schema.rebuild() + assert not isinstance(adapter.core_schema, _mock_val_ser.MockCoreSchema), ( + 'this is a bug! please report it' + ) + inputs_.append((key, mode, adapter.core_schema)) + + json_schemas_map, definitions = schema_generator_instance.generate_definitions(inputs_) + + json_schema: dict[str, Any] = {} + if definitions: + json_schema['$defs'] = definitions + if title: + json_schema['title'] = title + if description: + json_schema['description'] = description + + return json_schemas_map, json_schema diff --git a/backend/.venv/Lib/site-packages/pydantic/types.py b/backend/.venv/Lib/site-packages/pydantic/types.py new file mode 100644 index 0000000..59160ab --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/types.py @@ -0,0 +1,3295 @@ +"""The types module contains custom types used by pydantic.""" + +from __future__ import annotations as _annotations + +import base64 +import dataclasses as _dataclasses +import re +from collections.abc import Hashable, Iterator +from datetime import date, datetime +from decimal import Decimal +from enum import Enum +from pathlib import Path +from re import Pattern +from types import ModuleType +from typing import ( + TYPE_CHECKING, + Annotated, + Any, + Callable, + ClassVar, + Generic, + Literal, + TypeVar, + Union, + cast, +) +from uuid import UUID + +import annotated_types +from annotated_types import BaseMetadata, MaxLen, MinLen +from pydantic_core import CoreSchema, PydanticCustomError, SchemaSerializer, core_schema +from typing_extensions import Protocol, TypeAlias, TypeAliasType, deprecated, get_args, get_origin +from typing_inspection.introspection import is_union_origin + +from ._internal import _fields, _internal_dataclass, _utils, _validators +from ._migration import getattr_migration +from .annotated_handlers import GetCoreSchemaHandler, GetJsonSchemaHandler +from .errors import PydanticUserError +from .json_schema import JsonSchemaValue +from .warnings import PydanticDeprecatedSince20 + +if TYPE_CHECKING: + from ._internal._core_metadata import CoreMetadata + +__all__ = ( + 'Strict', + 'StrictStr', + 'SocketPath', + 'conbytes', + 'conlist', + 'conset', + 'confrozenset', + 'constr', + 'ImportString', + 'conint', + 'PositiveInt', + 'NegativeInt', + 'NonNegativeInt', + 'NonPositiveInt', + 'confloat', + 'PositiveFloat', + 'NegativeFloat', + 'NonNegativeFloat', + 'NonPositiveFloat', + 'FiniteFloat', + 'condecimal', + 'UUID1', + 'UUID3', + 'UUID4', + 'UUID5', + 'UUID6', + 'UUID7', + 'UUID8', + 'FilePath', + 'DirectoryPath', + 'NewPath', + 'Json', + 'Secret', + 'SecretStr', + 'SecretBytes', + 'StrictBool', + 'StrictBytes', + 'StrictInt', + 'StrictFloat', + 'PaymentCardNumber', + 'ByteSize', + 'PastDate', + 'FutureDate', + 'PastDatetime', + 'FutureDatetime', + 'condate', + 'AwareDatetime', + 'NaiveDatetime', + 'AllowInfNan', + 'EncoderProtocol', + 'EncodedBytes', + 'EncodedStr', + 'Base64Encoder', + 'Base64Bytes', + 'Base64Str', + 'Base64UrlBytes', + 'Base64UrlStr', + 'GetPydanticSchema', + 'StringConstraints', + 'Tag', + 'Discriminator', + 'JsonValue', + 'OnErrorOmit', + 'FailFast', +) + + +T = TypeVar('T') + + +@_dataclasses.dataclass +class Strict(_fields.PydanticMetadata, BaseMetadata): + """!!! abstract "Usage Documentation" + [Strict Mode with `Annotated` `Strict`](../concepts/strict_mode.md#strict-mode-with-annotated-strict) + + A field metadata class to indicate that a field should be validated in strict mode. + Use this class as an annotation via [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated), as seen below. + + Attributes: + strict: Whether to validate the field in strict mode. + + Example: + ```python + from typing import Annotated + + from pydantic.types import Strict + + StrictBool = Annotated[bool, Strict()] + ``` + """ + + strict: bool = True + + def __hash__(self) -> int: + return hash(self.strict) + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ BOOLEAN TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +StrictBool = Annotated[bool, Strict()] +"""A boolean that must be either ``True`` or ``False``.""" + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTEGER TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +def conint( + *, + strict: bool | None = None, + gt: int | None = None, + ge: int | None = None, + lt: int | None = None, + le: int | None = None, + multiple_of: int | None = None, +) -> type[int]: + """ + !!! warning "Discouraged" + This function is **discouraged** in favor of using + [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) with + [`Field`][pydantic.fields.Field] instead. + + This function will be **deprecated** in Pydantic 3.0. + + The reason is that `conint` returns a type, which doesn't play well with static analysis tools. + + === ":x: Don't do this" + ```python + from pydantic import BaseModel, conint + + class Foo(BaseModel): + bar: conint(strict=True, gt=0) + ``` + + === ":white_check_mark: Do this" + ```python + from typing import Annotated + + from pydantic import BaseModel, Field + + class Foo(BaseModel): + bar: Annotated[int, Field(strict=True, gt=0)] + ``` + + A wrapper around `int` that allows for additional constraints. + + Args: + strict: Whether to validate the integer in strict mode. Defaults to `None`. + gt: The value must be greater than this. + ge: The value must be greater than or equal to this. + lt: The value must be less than this. + le: The value must be less than or equal to this. + multiple_of: The value must be a multiple of this. + + Returns: + The wrapped integer type. + + ```python + from pydantic import BaseModel, ValidationError, conint + + class ConstrainedExample(BaseModel): + constrained_int: conint(gt=1) + + m = ConstrainedExample(constrained_int=2) + print(repr(m)) + #> ConstrainedExample(constrained_int=2) + + try: + ConstrainedExample(constrained_int=0) + except ValidationError as e: + print(e.errors()) + ''' + [ + { + 'type': 'greater_than', + 'loc': ('constrained_int',), + 'msg': 'Input should be greater than 1', + 'input': 0, + 'ctx': {'gt': 1}, + 'url': 'https://errors.pydantic.dev/2/v/greater_than', + } + ] + ''' + ``` + + """ # noqa: D212 + return Annotated[ # pyright: ignore[reportReturnType] + int, + Strict(strict) if strict is not None else None, + annotated_types.Interval(gt=gt, ge=ge, lt=lt, le=le), + annotated_types.MultipleOf(multiple_of) if multiple_of is not None else None, + ] + + +PositiveInt = Annotated[int, annotated_types.Gt(0)] +"""An integer that must be greater than zero. + +```python +from pydantic import BaseModel, PositiveInt, ValidationError + +class Model(BaseModel): + positive_int: PositiveInt + +m = Model(positive_int=1) +print(repr(m)) +#> Model(positive_int=1) + +try: + Model(positive_int=-1) +except ValidationError as e: + print(e.errors()) + ''' + [ + { + 'type': 'greater_than', + 'loc': ('positive_int',), + 'msg': 'Input should be greater than 0', + 'input': -1, + 'ctx': {'gt': 0}, + 'url': 'https://errors.pydantic.dev/2/v/greater_than', + } + ] + ''' +``` +""" +NegativeInt = Annotated[int, annotated_types.Lt(0)] +"""An integer that must be less than zero. + +```python +from pydantic import BaseModel, NegativeInt, ValidationError + +class Model(BaseModel): + negative_int: NegativeInt + +m = Model(negative_int=-1) +print(repr(m)) +#> Model(negative_int=-1) + +try: + Model(negative_int=1) +except ValidationError as e: + print(e.errors()) + ''' + [ + { + 'type': 'less_than', + 'loc': ('negative_int',), + 'msg': 'Input should be less than 0', + 'input': 1, + 'ctx': {'lt': 0}, + 'url': 'https://errors.pydantic.dev/2/v/less_than', + } + ] + ''' +``` +""" +NonPositiveInt = Annotated[int, annotated_types.Le(0)] +"""An integer that must be less than or equal to zero. + +```python +from pydantic import BaseModel, NonPositiveInt, ValidationError + +class Model(BaseModel): + non_positive_int: NonPositiveInt + +m = Model(non_positive_int=0) +print(repr(m)) +#> Model(non_positive_int=0) + +try: + Model(non_positive_int=1) +except ValidationError as e: + print(e.errors()) + ''' + [ + { + 'type': 'less_than_equal', + 'loc': ('non_positive_int',), + 'msg': 'Input should be less than or equal to 0', + 'input': 1, + 'ctx': {'le': 0}, + 'url': 'https://errors.pydantic.dev/2/v/less_than_equal', + } + ] + ''' +``` +""" +NonNegativeInt = Annotated[int, annotated_types.Ge(0)] +"""An integer that must be greater than or equal to zero. + +```python +from pydantic import BaseModel, NonNegativeInt, ValidationError + +class Model(BaseModel): + non_negative_int: NonNegativeInt + +m = Model(non_negative_int=0) +print(repr(m)) +#> Model(non_negative_int=0) + +try: + Model(non_negative_int=-1) +except ValidationError as e: + print(e.errors()) + ''' + [ + { + 'type': 'greater_than_equal', + 'loc': ('non_negative_int',), + 'msg': 'Input should be greater than or equal to 0', + 'input': -1, + 'ctx': {'ge': 0}, + 'url': 'https://errors.pydantic.dev/2/v/greater_than_equal', + } + ] + ''' +``` +""" +StrictInt = Annotated[int, Strict()] +"""An integer that must be validated in strict mode. + +```python +from pydantic import BaseModel, StrictInt, ValidationError + +class StrictIntModel(BaseModel): + strict_int: StrictInt + +try: + StrictIntModel(strict_int=3.14159) +except ValidationError as e: + print(e) + ''' + 1 validation error for StrictIntModel + strict_int + Input should be a valid integer [type=int_type, input_value=3.14159, input_type=float] + ''' +``` +""" + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FLOAT TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +@_dataclasses.dataclass +class AllowInfNan(_fields.PydanticMetadata): + """A field metadata class to indicate that a field should allow `-inf`, `inf`, and `nan`. + + Use this class as an annotation via [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated), as seen below. + + Attributes: + allow_inf_nan: Whether to allow `-inf`, `inf`, and `nan`. Defaults to `True`. + + Example: + ```python + from typing import Annotated + + from pydantic.types import AllowInfNan + + LaxFloat = Annotated[float, AllowInfNan()] + ``` + """ + + allow_inf_nan: bool = True + + def __hash__(self) -> int: + return hash(self.allow_inf_nan) + + +def confloat( + *, + strict: bool | None = None, + gt: float | None = None, + ge: float | None = None, + lt: float | None = None, + le: float | None = None, + multiple_of: float | None = None, + allow_inf_nan: bool | None = None, +) -> type[float]: + """ + !!! warning "Discouraged" + This function is **discouraged** in favor of using + [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) with + [`Field`][pydantic.fields.Field] instead. + + This function will be **deprecated** in Pydantic 3.0. + + The reason is that `confloat` returns a type, which doesn't play well with static analysis tools. + + === ":x: Don't do this" + ```python + from pydantic import BaseModel, confloat + + class Foo(BaseModel): + bar: confloat(strict=True, gt=0) + ``` + + === ":white_check_mark: Do this" + ```python + from typing import Annotated + + from pydantic import BaseModel, Field + + class Foo(BaseModel): + bar: Annotated[float, Field(strict=True, gt=0)] + ``` + + A wrapper around `float` that allows for additional constraints. + + Args: + strict: Whether to validate the float in strict mode. + gt: The value must be greater than this. + ge: The value must be greater than or equal to this. + lt: The value must be less than this. + le: The value must be less than or equal to this. + multiple_of: The value must be a multiple of this. + allow_inf_nan: Whether to allow `-inf`, `inf`, and `nan`. + + Returns: + The wrapped float type. + + ```python + from pydantic import BaseModel, ValidationError, confloat + + class ConstrainedExample(BaseModel): + constrained_float: confloat(gt=1.0) + + m = ConstrainedExample(constrained_float=1.1) + print(repr(m)) + #> ConstrainedExample(constrained_float=1.1) + + try: + ConstrainedExample(constrained_float=0.9) + except ValidationError as e: + print(e.errors()) + ''' + [ + { + 'type': 'greater_than', + 'loc': ('constrained_float',), + 'msg': 'Input should be greater than 1', + 'input': 0.9, + 'ctx': {'gt': 1.0}, + 'url': 'https://errors.pydantic.dev/2/v/greater_than', + } + ] + ''' + ``` + """ # noqa: D212 + return Annotated[ # pyright: ignore[reportReturnType] + float, + Strict(strict) if strict is not None else None, + annotated_types.Interval(gt=gt, ge=ge, lt=lt, le=le), + annotated_types.MultipleOf(multiple_of) if multiple_of is not None else None, + AllowInfNan(allow_inf_nan) if allow_inf_nan is not None else None, + ] + + +PositiveFloat = Annotated[float, annotated_types.Gt(0)] +"""A float that must be greater than zero. + +```python +from pydantic import BaseModel, PositiveFloat, ValidationError + +class Model(BaseModel): + positive_float: PositiveFloat + +m = Model(positive_float=1.0) +print(repr(m)) +#> Model(positive_float=1.0) + +try: + Model(positive_float=-1.0) +except ValidationError as e: + print(e.errors()) + ''' + [ + { + 'type': 'greater_than', + 'loc': ('positive_float',), + 'msg': 'Input should be greater than 0', + 'input': -1.0, + 'ctx': {'gt': 0.0}, + 'url': 'https://errors.pydantic.dev/2/v/greater_than', + } + ] + ''' +``` +""" +NegativeFloat = Annotated[float, annotated_types.Lt(0)] +"""A float that must be less than zero. + +```python +from pydantic import BaseModel, NegativeFloat, ValidationError + +class Model(BaseModel): + negative_float: NegativeFloat + +m = Model(negative_float=-1.0) +print(repr(m)) +#> Model(negative_float=-1.0) + +try: + Model(negative_float=1.0) +except ValidationError as e: + print(e.errors()) + ''' + [ + { + 'type': 'less_than', + 'loc': ('negative_float',), + 'msg': 'Input should be less than 0', + 'input': 1.0, + 'ctx': {'lt': 0.0}, + 'url': 'https://errors.pydantic.dev/2/v/less_than', + } + ] + ''' +``` +""" +NonPositiveFloat = Annotated[float, annotated_types.Le(0)] +"""A float that must be less than or equal to zero. + +```python +from pydantic import BaseModel, NonPositiveFloat, ValidationError + +class Model(BaseModel): + non_positive_float: NonPositiveFloat + +m = Model(non_positive_float=0.0) +print(repr(m)) +#> Model(non_positive_float=0.0) + +try: + Model(non_positive_float=1.0) +except ValidationError as e: + print(e.errors()) + ''' + [ + { + 'type': 'less_than_equal', + 'loc': ('non_positive_float',), + 'msg': 'Input should be less than or equal to 0', + 'input': 1.0, + 'ctx': {'le': 0.0}, + 'url': 'https://errors.pydantic.dev/2/v/less_than_equal', + } + ] + ''' +``` +""" +NonNegativeFloat = Annotated[float, annotated_types.Ge(0)] +"""A float that must be greater than or equal to zero. + +```python +from pydantic import BaseModel, NonNegativeFloat, ValidationError + +class Model(BaseModel): + non_negative_float: NonNegativeFloat + +m = Model(non_negative_float=0.0) +print(repr(m)) +#> Model(non_negative_float=0.0) + +try: + Model(non_negative_float=-1.0) +except ValidationError as e: + print(e.errors()) + ''' + [ + { + 'type': 'greater_than_equal', + 'loc': ('non_negative_float',), + 'msg': 'Input should be greater than or equal to 0', + 'input': -1.0, + 'ctx': {'ge': 0.0}, + 'url': 'https://errors.pydantic.dev/2/v/greater_than_equal', + } + ] + ''' +``` +""" +StrictFloat = Annotated[float, Strict(True)] +"""A float that must be validated in strict mode. + +```python +from pydantic import BaseModel, StrictFloat, ValidationError + +class StrictFloatModel(BaseModel): + strict_float: StrictFloat + +try: + StrictFloatModel(strict_float='1.0') +except ValidationError as e: + print(e) + ''' + 1 validation error for StrictFloatModel + strict_float + Input should be a valid number [type=float_type, input_value='1.0', input_type=str] + ''' +``` +""" +FiniteFloat = Annotated[float, AllowInfNan(False)] +"""A float that must be finite (not ``-inf``, ``inf``, or ``nan``). + +```python +from pydantic import BaseModel, FiniteFloat + +class Model(BaseModel): + finite: FiniteFloat + +m = Model(finite=1.0) +print(m) +#> finite=1.0 +``` +""" + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ BYTES TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +def conbytes( + *, + min_length: int | None = None, + max_length: int | None = None, + strict: bool | None = None, +) -> type[bytes]: + """A wrapper around `bytes` that allows for additional constraints. + + Args: + min_length: The minimum length of the bytes. + max_length: The maximum length of the bytes. + strict: Whether to validate the bytes in strict mode. + + Returns: + The wrapped bytes type. + """ + return Annotated[ # pyright: ignore[reportReturnType] + bytes, + Strict(strict) if strict is not None else None, + annotated_types.Len(min_length or 0, max_length), + ] + + +StrictBytes = Annotated[bytes, Strict()] +"""A bytes that must be validated in strict mode.""" + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ STRING TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +@_dataclasses.dataclass(frozen=True) +class StringConstraints(annotated_types.GroupedMetadata): + """!!! abstract "Usage Documentation" + [String types](./standard_library_types.md#strings) + + A field metadata class to apply constraints to `str` types. + Use this class as an annotation via [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated), as seen below. + + Attributes: + strip_whitespace: Whether to remove leading and trailing whitespace. + to_upper: Whether to convert the string to uppercase. + to_lower: Whether to convert the string to lowercase. + strict: Whether to validate the string in strict mode. + min_length: The minimum length of the string. + max_length: The maximum length of the string. + pattern: A regex pattern that the string must match. + + Example: + ```python + from typing import Annotated + + from pydantic.types import StringConstraints + + ConstrainedStr = Annotated[str, StringConstraints(min_length=1, max_length=10)] + ``` + """ + + strip_whitespace: bool | None = None + to_upper: bool | None = None + to_lower: bool | None = None + strict: bool | None = None + min_length: int | None = None + max_length: int | None = None + pattern: str | Pattern[str] | None = None + + def __iter__(self) -> Iterator[BaseMetadata]: + if self.min_length is not None: + yield MinLen(self.min_length) + if self.max_length is not None: + yield MaxLen(self.max_length) + if self.strict is not None: + yield Strict(self.strict) + if ( + self.strip_whitespace is not None + or self.pattern is not None + or self.to_lower is not None + or self.to_upper is not None + ): + yield _fields.pydantic_general_metadata( + strip_whitespace=self.strip_whitespace, + to_upper=self.to_upper, + to_lower=self.to_lower, + pattern=self.pattern, + ) + + +def constr( + *, + strip_whitespace: bool | None = None, + to_upper: bool | None = None, + to_lower: bool | None = None, + strict: bool | None = None, + min_length: int | None = None, + max_length: int | None = None, + pattern: str | Pattern[str] | None = None, +) -> type[str]: + """ + !!! warning "Discouraged" + This function is **discouraged** in favor of using + [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) with + [`StringConstraints`][pydantic.types.StringConstraints] instead. + + This function will be **deprecated** in Pydantic 3.0. + + The reason is that `constr` returns a type, which doesn't play well with static analysis tools. + + === ":x: Don't do this" + ```python + from pydantic import BaseModel, constr + + class Foo(BaseModel): + bar: constr(strip_whitespace=True, to_upper=True, pattern=r'^[A-Z]+$') + ``` + + === ":white_check_mark: Do this" + ```python + from typing import Annotated + + from pydantic import BaseModel, StringConstraints + + class Foo(BaseModel): + bar: Annotated[ + str, + StringConstraints( + strip_whitespace=True, to_upper=True, pattern=r'^[A-Z]+$' + ), + ] + ``` + + A wrapper around `str` that allows for additional constraints. + + ```python + from pydantic import BaseModel, constr + + class Foo(BaseModel): + bar: constr(strip_whitespace=True, to_upper=True) + + foo = Foo(bar=' hello ') + print(foo) + #> bar='HELLO' + ``` + + Args: + strip_whitespace: Whether to remove leading and trailing whitespace. + to_upper: Whether to turn all characters to uppercase. + to_lower: Whether to turn all characters to lowercase. + strict: Whether to validate the string in strict mode. + min_length: The minimum length of the string. + max_length: The maximum length of the string. + pattern: A regex pattern to validate the string against. + + Returns: + The wrapped string type. + """ # noqa: D212 + return Annotated[ # pyright: ignore[reportReturnType] + str, + StringConstraints( + strip_whitespace=strip_whitespace, + to_upper=to_upper, + to_lower=to_lower, + strict=strict, + min_length=min_length, + max_length=max_length, + pattern=pattern, + ), + ] + + +StrictStr = Annotated[str, Strict()] +"""A string that must be validated in strict mode.""" + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ COLLECTION TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +HashableItemType = TypeVar('HashableItemType', bound=Hashable) + + +def conset( + item_type: type[HashableItemType], *, min_length: int | None = None, max_length: int | None = None +) -> type[set[HashableItemType]]: + """A wrapper around `typing.Set` that allows for additional constraints. + + Args: + item_type: The type of the items in the set. + min_length: The minimum length of the set. + max_length: The maximum length of the set. + + Returns: + The wrapped set type. + """ + return Annotated[set[item_type], annotated_types.Len(min_length or 0, max_length)] # pyright: ignore[reportReturnType] + + +def confrozenset( + item_type: type[HashableItemType], *, min_length: int | None = None, max_length: int | None = None +) -> type[frozenset[HashableItemType]]: + """A wrapper around `typing.FrozenSet` that allows for additional constraints. + + Args: + item_type: The type of the items in the frozenset. + min_length: The minimum length of the frozenset. + max_length: The maximum length of the frozenset. + + Returns: + The wrapped frozenset type. + """ + return Annotated[frozenset[item_type], annotated_types.Len(min_length or 0, max_length)] # pyright: ignore[reportReturnType] + + +AnyItemType = TypeVar('AnyItemType') + + +def conlist( + item_type: type[AnyItemType], + *, + min_length: int | None = None, + max_length: int | None = None, + unique_items: bool | None = None, +) -> type[list[AnyItemType]]: + """A wrapper around [`list`][] that adds validation. + + Args: + item_type: The type of the items in the list. + min_length: The minimum length of the list. Defaults to None. + max_length: The maximum length of the list. Defaults to None. + unique_items: Whether the items in the list must be unique. Defaults to None. + !!! warning Deprecated + The `unique_items` parameter is deprecated, use `Set` instead. + See [this issue](https://github.com/pydantic/pydantic-core/issues/296) for more details. + + Returns: + The wrapped list type. + """ + if unique_items is not None: + raise PydanticUserError( + ( + '`unique_items` is removed, use `Set` instead' + '(this feature is discussed in https://github.com/pydantic/pydantic-core/issues/296)' + ), + code='removed-kwargs', + ) + return Annotated[list[item_type], annotated_types.Len(min_length or 0, max_length)] # pyright: ignore[reportReturnType] + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~ IMPORT STRING TYPE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +AnyType = TypeVar('AnyType') +if TYPE_CHECKING: + ImportString = Annotated[AnyType, ...] +else: + + class ImportString: + """A type that can be used to import a Python object from a string. + + `ImportString` expects a string and loads the Python object importable at that dotted path. + Attributes of modules may be separated from the module by `:` or `.`, e.g. if `'math:cos'` is provided, + the resulting field value would be the function `cos`. If a `.` is used and both an attribute and submodule + are present at the same path, the module will be preferred. + + On model instantiation, pointers will be evaluated and imported. There is + some nuance to this behavior, demonstrated in the examples below. + + ```python + import math + + from pydantic import BaseModel, Field, ImportString, ValidationError + + class ImportThings(BaseModel): + obj: ImportString + + # A string value will cause an automatic import + my_cos = ImportThings(obj='math.cos') + + # You can use the imported function as you would expect + cos_of_0 = my_cos.obj(0) + assert cos_of_0 == 1 + + # A string whose value cannot be imported will raise an error + try: + ImportThings(obj='foo.bar') + except ValidationError as e: + print(e) + ''' + 1 validation error for ImportThings + obj + Invalid python path: No module named 'foo.bar' [type=import_error, input_value='foo.bar', input_type=str] + ''' + + # Actual python objects can be assigned as well + my_cos = ImportThings(obj=math.cos) + my_cos_2 = ImportThings(obj='math.cos') + my_cos_3 = ImportThings(obj='math:cos') + assert my_cos == my_cos_2 == my_cos_3 + + # You can set default field value either as Python object: + class ImportThingsDefaultPyObj(BaseModel): + obj: ImportString = math.cos + + # or as a string value (but only if used with `validate_default=True`) + class ImportThingsDefaultString(BaseModel): + obj: ImportString = Field(default='math.cos', validate_default=True) + + my_cos_default1 = ImportThingsDefaultPyObj() + my_cos_default2 = ImportThingsDefaultString() + assert my_cos_default1.obj == my_cos_default2.obj == math.cos + + # note: this will not work! + class ImportThingsMissingValidateDefault(BaseModel): + obj: ImportString = 'math.cos' + + my_cos_default3 = ImportThingsMissingValidateDefault() + assert my_cos_default3.obj == 'math.cos' # just string, not evaluated + ``` + + Serializing an `ImportString` type to json is also possible. + + ```python + from pydantic import BaseModel, ImportString + + class ImportThings(BaseModel): + obj: ImportString + + # Create an instance + m = ImportThings(obj='math.cos') + print(m) + #> obj= + print(m.model_dump_json()) + #> {"obj":"math.cos"} + ``` + """ + + @classmethod + def __class_getitem__(cls, item: AnyType) -> AnyType: + return Annotated[item, cls()] + + @classmethod + def __get_pydantic_core_schema__( + cls, source: type[Any], handler: GetCoreSchemaHandler + ) -> core_schema.CoreSchema: + serializer = core_schema.plain_serializer_function_ser_schema(cls._serialize, when_used='json') + if cls is source: + # Treat bare usage of ImportString (`schema is None`) as the same as ImportString[Any] + return core_schema.no_info_plain_validator_function( + function=_validators.import_string, serialization=serializer + ) + else: + return core_schema.no_info_before_validator_function( + function=_validators.import_string, schema=handler(source), serialization=serializer + ) + + @classmethod + def __get_pydantic_json_schema__(cls, cs: CoreSchema, handler: GetJsonSchemaHandler) -> JsonSchemaValue: + return handler(core_schema.str_schema()) + + @staticmethod + def _serialize(v: Any) -> str: + if isinstance(v, ModuleType): + return v.__name__ + elif hasattr(v, '__module__') and hasattr(v, '__name__'): + return f'{v.__module__}.{v.__name__}' + # Handle special cases for sys.XXX streams + # if we see more of these, we should consider a more general solution + elif hasattr(v, 'name'): + if v.name == '': + return 'sys.stdout' + elif v.name == '': + return 'sys.stdin' + elif v.name == '': + return 'sys.stderr' + return v + + def __repr__(self) -> str: + return 'ImportString' + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DECIMAL TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +def condecimal( + *, + strict: bool | None = None, + gt: int | Decimal | None = None, + ge: int | Decimal | None = None, + lt: int | Decimal | None = None, + le: int | Decimal | None = None, + multiple_of: int | Decimal | None = None, + max_digits: int | None = None, + decimal_places: int | None = None, + allow_inf_nan: bool | None = None, +) -> type[Decimal]: + """ + !!! warning "Discouraged" + This function is **discouraged** in favor of using + [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) with + [`Field`][pydantic.fields.Field] instead. + + This function will be **deprecated** in Pydantic 3.0. + + The reason is that `condecimal` returns a type, which doesn't play well with static analysis tools. + + === ":x: Don't do this" + ```python + from pydantic import BaseModel, condecimal + + class Foo(BaseModel): + bar: condecimal(strict=True, allow_inf_nan=True) + ``` + + === ":white_check_mark: Do this" + ```python + from decimal import Decimal + from typing import Annotated + + from pydantic import BaseModel, Field + + class Foo(BaseModel): + bar: Annotated[Decimal, Field(strict=True, allow_inf_nan=True)] + ``` + + A wrapper around Decimal that adds validation. + + Args: + strict: Whether to validate the value in strict mode. Defaults to `None`. + gt: The value must be greater than this. Defaults to `None`. + ge: The value must be greater than or equal to this. Defaults to `None`. + lt: The value must be less than this. Defaults to `None`. + le: The value must be less than or equal to this. Defaults to `None`. + multiple_of: The value must be a multiple of this. Defaults to `None`. + max_digits: The maximum number of digits. Defaults to `None`. + decimal_places: The number of decimal places. Defaults to `None`. + allow_inf_nan: Whether to allow infinity and NaN. Defaults to `None`. + + ```python + from decimal import Decimal + + from pydantic import BaseModel, ValidationError, condecimal + + class ConstrainedExample(BaseModel): + constrained_decimal: condecimal(gt=Decimal('1.0')) + + m = ConstrainedExample(constrained_decimal=Decimal('1.1')) + print(repr(m)) + #> ConstrainedExample(constrained_decimal=Decimal('1.1')) + + try: + ConstrainedExample(constrained_decimal=Decimal('0.9')) + except ValidationError as e: + print(e.errors()) + ''' + [ + { + 'type': 'greater_than', + 'loc': ('constrained_decimal',), + 'msg': 'Input should be greater than 1.0', + 'input': Decimal('0.9'), + 'ctx': {'gt': Decimal('1.0')}, + 'url': 'https://errors.pydantic.dev/2/v/greater_than', + } + ] + ''' + ``` + """ # noqa: D212 + return Annotated[ # pyright: ignore[reportReturnType] + Decimal, + Strict(strict) if strict is not None else None, + annotated_types.Interval(gt=gt, ge=ge, lt=lt, le=le), + annotated_types.MultipleOf(multiple_of) if multiple_of is not None else None, + _fields.pydantic_general_metadata(max_digits=max_digits, decimal_places=decimal_places), + AllowInfNan(allow_inf_nan) if allow_inf_nan is not None else None, + ] + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UUID TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +@_dataclasses.dataclass(**_internal_dataclass.slots_true) +class UuidVersion: + """A field metadata class to indicate a [UUID](https://docs.python.org/3/library/uuid.html) version. + + Use this class as an annotation via [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated), as seen below. + + Attributes: + uuid_version: The version of the UUID. Must be one of 1, 3, 4, 5, 6, 7 or 8. + + Example: + ```python + from typing import Annotated + from uuid import UUID + + from pydantic.types import UuidVersion + + UUID1 = Annotated[UUID, UuidVersion(1)] + ``` + """ + + uuid_version: Literal[1, 3, 4, 5, 6, 7, 8] + + def __get_pydantic_json_schema__( + self, core_schema: core_schema.CoreSchema, handler: GetJsonSchemaHandler + ) -> JsonSchemaValue: + field_schema = handler(core_schema) + field_schema.pop('anyOf', None) # remove the bytes/str union + field_schema.update(type='string', format=f'uuid{self.uuid_version}') + return field_schema + + def __get_pydantic_core_schema__(self, source: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: + schema = handler(source) + _check_annotated_type(schema['type'], 'uuid', self.__class__.__name__) + schema['version'] = self.uuid_version # type: ignore + return schema + + def __hash__(self) -> int: + return hash(type(self.uuid_version)) + + +UUID1 = Annotated[UUID, UuidVersion(1)] +"""A [UUID](https://docs.python.org/3/library/uuid.html) that must be version 1. + +```python +import uuid + +from pydantic import UUID1, BaseModel + +class Model(BaseModel): + uuid1: UUID1 + +Model(uuid1=uuid.uuid1()) +``` +""" +UUID3 = Annotated[UUID, UuidVersion(3)] +"""A [UUID](https://docs.python.org/3/library/uuid.html) that must be version 3. + +```python +import uuid + +from pydantic import UUID3, BaseModel + +class Model(BaseModel): + uuid3: UUID3 + +Model(uuid3=uuid.uuid3(uuid.NAMESPACE_DNS, 'pydantic.org')) +``` +""" +UUID4 = Annotated[UUID, UuidVersion(4)] +"""A [UUID](https://docs.python.org/3/library/uuid.html) that must be version 4. + +```python +import uuid + +from pydantic import UUID4, BaseModel + +class Model(BaseModel): + uuid4: UUID4 + +Model(uuid4=uuid.uuid4()) +``` +""" +UUID5 = Annotated[UUID, UuidVersion(5)] +"""A [UUID](https://docs.python.org/3/library/uuid.html) that must be version 5. + +```python +import uuid + +from pydantic import UUID5, BaseModel + +class Model(BaseModel): + uuid5: UUID5 + +Model(uuid5=uuid.uuid5(uuid.NAMESPACE_DNS, 'pydantic.org')) +``` +""" +UUID6 = Annotated[UUID, UuidVersion(6)] +"""A [UUID](https://docs.python.org/3/library/uuid.html) that must be version 6. + +```python +import uuid + +from pydantic import UUID6, BaseModel + +class Model(BaseModel): + uuid6: UUID6 + +Model(uuid6=uuid.UUID('1efea953-c2d6-6790-aa0a-69db8c87df97')) +``` +""" +UUID7 = Annotated[UUID, UuidVersion(7)] +"""A [UUID](https://docs.python.org/3/library/uuid.html) that must be version 7. + +```python +import uuid + +from pydantic import UUID7, BaseModel + +class Model(BaseModel): + uuid7: UUID7 + +Model(uuid7=uuid.UUID('0194fdcb-1c47-7a09-b52c-561154de0b4a')) +``` +""" +UUID8 = Annotated[UUID, UuidVersion(8)] +"""A [UUID](https://docs.python.org/3/library/uuid.html) that must be version 8. + +```python +import uuid + +from pydantic import UUID8, BaseModel + +class Model(BaseModel): + uuid8: UUID8 + +Model(uuid8=uuid.UUID('81a0b92e-6078-8551-9c81-8ccb666bdab8')) +``` +""" + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PATH TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +@_dataclasses.dataclass +class PathType: + path_type: Literal['file', 'dir', 'new', 'socket'] + + def __get_pydantic_json_schema__( + self, core_schema: core_schema.CoreSchema, handler: GetJsonSchemaHandler + ) -> JsonSchemaValue: + field_schema = handler(core_schema) + format_conversion = {'file': 'file-path', 'dir': 'directory-path'} + field_schema.update(format=format_conversion.get(self.path_type, 'path'), type='string') + return field_schema + + def __get_pydantic_core_schema__(self, source: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: + function_lookup = { + 'file': cast(core_schema.WithInfoValidatorFunction, self.validate_file), + 'dir': cast(core_schema.WithInfoValidatorFunction, self.validate_directory), + 'new': cast(core_schema.WithInfoValidatorFunction, self.validate_new), + 'socket': cast(core_schema.WithInfoValidatorFunction, self.validate_socket), + } + + return core_schema.with_info_after_validator_function( + function_lookup[self.path_type], + handler(source), + ) + + @staticmethod + def validate_file(path: Path, _: core_schema.ValidationInfo) -> Path: + if path.is_file(): + return path + else: + raise PydanticCustomError('path_not_file', 'Path does not point to a file') + + @staticmethod + def validate_socket(path: Path, _: core_schema.ValidationInfo) -> Path: + if path.is_socket(): + return path + else: + raise PydanticCustomError('path_not_socket', 'Path does not point to a socket') + + @staticmethod + def validate_directory(path: Path, _: core_schema.ValidationInfo) -> Path: + if path.is_dir(): + return path + else: + raise PydanticCustomError('path_not_directory', 'Path does not point to a directory') + + @staticmethod + def validate_new(path: Path, _: core_schema.ValidationInfo) -> Path: + if path.exists(): + raise PydanticCustomError('path_exists', 'Path already exists') + elif not path.parent.exists(): + raise PydanticCustomError('parent_does_not_exist', 'Parent directory does not exist') + else: + return path + + def __hash__(self) -> int: + return hash(type(self.path_type)) + + +FilePath = Annotated[Path, PathType('file')] +"""A path that must point to a file. + +```python +from pathlib import Path + +from pydantic import BaseModel, FilePath, ValidationError + +class Model(BaseModel): + f: FilePath + +path = Path('text.txt') +path.touch() +m = Model(f='text.txt') +print(m.model_dump()) +#> {'f': PosixPath('text.txt')} +path.unlink() + +path = Path('directory') +path.mkdir(exist_ok=True) +try: + Model(f='directory') # directory +except ValidationError as e: + print(e) + ''' + 1 validation error for Model + f + Path does not point to a file [type=path_not_file, input_value='directory', input_type=str] + ''' +path.rmdir() + +try: + Model(f='not-exists-file') +except ValidationError as e: + print(e) + ''' + 1 validation error for Model + f + Path does not point to a file [type=path_not_file, input_value='not-exists-file', input_type=str] + ''' +``` +""" +DirectoryPath = Annotated[Path, PathType('dir')] +"""A path that must point to a directory. + +```python +from pathlib import Path + +from pydantic import BaseModel, DirectoryPath, ValidationError + +class Model(BaseModel): + f: DirectoryPath + +path = Path('directory/') +path.mkdir() +m = Model(f='directory/') +print(m.model_dump()) +#> {'f': PosixPath('directory')} +path.rmdir() + +path = Path('file.txt') +path.touch() +try: + Model(f='file.txt') # file +except ValidationError as e: + print(e) + ''' + 1 validation error for Model + f + Path does not point to a directory [type=path_not_directory, input_value='file.txt', input_type=str] + ''' +path.unlink() + +try: + Model(f='not-exists-directory') +except ValidationError as e: + print(e) + ''' + 1 validation error for Model + f + Path does not point to a directory [type=path_not_directory, input_value='not-exists-directory', input_type=str] + ''' +``` +""" +NewPath = Annotated[Path, PathType('new')] +"""A path for a new file or directory that must not already exist. The parent directory must already exist.""" + +SocketPath = Annotated[Path, PathType('socket')] +"""A path to an existing socket file""" + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON TYPE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +if TYPE_CHECKING: + # Json[list[str]] will be recognized by type checkers as list[str] + Json = Annotated[AnyType, ...] + +else: + + class Json: + """A special type wrapper which loads JSON before parsing. + + You can use the `Json` data type to make Pydantic first load a raw JSON string before + validating the loaded data into the parametrized type: + + ```python + from typing import Any + + from pydantic import BaseModel, Json, ValidationError + + class AnyJsonModel(BaseModel): + json_obj: Json[Any] + + class ConstrainedJsonModel(BaseModel): + json_obj: Json[list[int]] + + print(AnyJsonModel(json_obj='{"b": 1}')) + #> json_obj={'b': 1} + print(ConstrainedJsonModel(json_obj='[1, 2, 3]')) + #> json_obj=[1, 2, 3] + + try: + ConstrainedJsonModel(json_obj=12) + except ValidationError as e: + print(e) + ''' + 1 validation error for ConstrainedJsonModel + json_obj + JSON input should be string, bytes or bytearray [type=json_type, input_value=12, input_type=int] + ''' + + try: + ConstrainedJsonModel(json_obj='[a, b]') + except ValidationError as e: + print(e) + ''' + 1 validation error for ConstrainedJsonModel + json_obj + Invalid JSON: expected value at line 1 column 2 [type=json_invalid, input_value='[a, b]', input_type=str] + ''' + + try: + ConstrainedJsonModel(json_obj='["a", "b"]') + except ValidationError as e: + print(e) + ''' + 2 validation errors for ConstrainedJsonModel + json_obj.0 + Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='a', input_type=str] + json_obj.1 + Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='b', input_type=str] + ''' + ``` + + When you dump the model using `model_dump` or `model_dump_json`, the dumped value will be the result of validation, + not the original JSON string. However, you can use the argument `round_trip=True` to get the original JSON string back: + + ```python + from pydantic import BaseModel, Json + + class ConstrainedJsonModel(BaseModel): + json_obj: Json[list[int]] + + print(ConstrainedJsonModel(json_obj='[1, 2, 3]').model_dump_json()) + #> {"json_obj":[1,2,3]} + print( + ConstrainedJsonModel(json_obj='[1, 2, 3]').model_dump_json(round_trip=True) + ) + #> {"json_obj":"[1,2,3]"} + ``` + """ + + @classmethod + def __class_getitem__(cls, item: AnyType) -> AnyType: + return Annotated[item, cls()] + + @classmethod + def __get_pydantic_core_schema__(cls, source: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: + if cls is source: + return core_schema.json_schema(None) + else: + return core_schema.json_schema(handler(source)) + + def __repr__(self) -> str: + return 'Json' + + def __hash__(self) -> int: + return hash(type(self)) + + def __eq__(self, other: Any) -> bool: + return type(other) is type(self) + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SECRET TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# The `Secret` class being conceptually immutable, make the type variable covariant: +SecretType = TypeVar('SecretType', covariant=True) + + +class _SecretBase(Generic[SecretType]): + def __init__(self, secret_value: SecretType) -> None: + self._secret_value: SecretType = secret_value + + def get_secret_value(self) -> SecretType: + """Get the secret value. + + Returns: + The secret value. + """ + return self._secret_value + + def __eq__(self, other: Any) -> bool: + return isinstance(other, self.__class__) and self.get_secret_value() == other.get_secret_value() + + def __hash__(self) -> int: + return hash(self.get_secret_value()) + + def __str__(self) -> str: + return str(self._display()) + + def __repr__(self) -> str: + return f'{self.__class__.__name__}({self._display()!r})' + + def _display(self) -> str | bytes: + raise NotImplementedError + + +def _serialize_secret(value: Secret[SecretType], info: core_schema.SerializationInfo) -> str | Secret[SecretType]: + if info.mode == 'json': + return str(value) + else: + return value + + +class Secret(_SecretBase[SecretType]): + """A generic base class used for defining a field with sensitive information that you do not want to be visible in logging or tracebacks. + + You may either directly parametrize `Secret` with a type, or subclass from `Secret` with a parametrized type. The benefit of subclassing + is that you can define a custom `_display` method, which will be used for `repr()` and `str()` methods. The examples below demonstrate both + ways of using `Secret` to create a new secret type. + + 1. Directly parametrizing `Secret` with a type: + + ```python + from pydantic import BaseModel, Secret + + SecretBool = Secret[bool] + + class Model(BaseModel): + secret_bool: SecretBool + + m = Model(secret_bool=True) + print(m.model_dump()) + #> {'secret_bool': Secret('**********')} + + print(m.model_dump_json()) + #> {"secret_bool":"**********"} + + print(m.secret_bool.get_secret_value()) + #> True + ``` + + 2. Subclassing from parametrized `Secret`: + + ```python + from datetime import date + + from pydantic import BaseModel, Secret + + class SecretDate(Secret[date]): + def _display(self) -> str: + return '****/**/**' + + class Model(BaseModel): + secret_date: SecretDate + + m = Model(secret_date=date(2022, 1, 1)) + print(m.model_dump()) + #> {'secret_date': SecretDate('****/**/**')} + + print(m.model_dump_json()) + #> {"secret_date":"****/**/**"} + + print(m.secret_date.get_secret_value()) + #> 2022-01-01 + ``` + + The value returned by the `_display` method will be used for `repr()` and `str()`. + + You can enforce constraints on the underlying type through annotations: + For example: + + ```python + from typing import Annotated + + from pydantic import BaseModel, Field, Secret, ValidationError + + SecretPosInt = Secret[Annotated[int, Field(gt=0, strict=True)]] + + class Model(BaseModel): + sensitive_int: SecretPosInt + + m = Model(sensitive_int=42) + print(m.model_dump()) + #> {'sensitive_int': Secret('**********')} + + try: + m = Model(sensitive_int=-42) # (1)! + except ValidationError as exc_info: + print(exc_info.errors(include_url=False, include_input=False)) + ''' + [ + { + 'type': 'greater_than', + 'loc': ('sensitive_int',), + 'msg': 'Input should be greater than 0', + 'ctx': {'gt': 0}, + } + ] + ''' + + try: + m = Model(sensitive_int='42') # (2)! + except ValidationError as exc_info: + print(exc_info.errors(include_url=False, include_input=False)) + ''' + [ + { + 'type': 'int_type', + 'loc': ('sensitive_int',), + 'msg': 'Input should be a valid integer', + } + ] + ''' + ``` + + 1. The input value is not greater than 0, so it raises a validation error. + 2. The input value is not an integer, so it raises a validation error because the `SecretPosInt` type has strict mode enabled. + """ + + def _display(self) -> str | bytes: + return '**********' if self.get_secret_value() else '' + + @classmethod + def __get_pydantic_core_schema__(cls, source: type[Any], handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: + inner_type = None + # if origin_type is Secret, then cls is a GenericAlias, and we can extract the inner type directly + origin_type = get_origin(source) + if origin_type is not None: + inner_type = get_args(source)[0] + # otherwise, we need to get the inner type from the base class + else: + bases = getattr(cls, '__orig_bases__', getattr(cls, '__bases__', [])) + for base in bases: + if get_origin(base) is Secret: + inner_type = get_args(base)[0] + if bases == [] or inner_type is None: + raise TypeError( + f"Can't get secret type from {cls.__name__}. " + 'Please use Secret[], or subclass from Secret[] instead.' + ) + + inner_schema = handler.generate_schema(inner_type) # type: ignore + + def validate_secret_value(value, handler) -> Secret[SecretType]: + if isinstance(value, Secret): + value = value.get_secret_value() + validated_inner = handler(value) + return cls(validated_inner) + + return core_schema.json_or_python_schema( + python_schema=core_schema.no_info_wrap_validator_function( + validate_secret_value, + inner_schema, + ), + json_schema=core_schema.no_info_after_validator_function(lambda x: cls(x), inner_schema), + serialization=core_schema.plain_serializer_function_ser_schema( + _serialize_secret, + info_arg=True, + when_used='always', + ), + ) + + __pydantic_serializer__ = SchemaSerializer( + core_schema.any_schema( + serialization=core_schema.plain_serializer_function_ser_schema( + _serialize_secret, + info_arg=True, + when_used='always', + ) + ) + ) + + +def _secret_display(value: SecretType) -> str: # type: ignore + return '**********' if value else '' + + +def _serialize_secret_field( + value: _SecretField[SecretType], info: core_schema.SerializationInfo +) -> str | _SecretField[SecretType]: + if info.mode == 'json': + # we want the output to always be string without the `b'` prefix for bytes, + # hence we just use `secret_display` + return _secret_display(value.get_secret_value()) + else: + return value + + +class _SecretField(_SecretBase[SecretType]): + _inner_schema: ClassVar[CoreSchema] + _error_kind: ClassVar[str] + + @classmethod + def __get_pydantic_core_schema__(cls, source: type[Any], handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: + def get_json_schema(_core_schema: core_schema.CoreSchema, handler: GetJsonSchemaHandler) -> JsonSchemaValue: + json_schema = handler(cls._inner_schema) + _utils.update_not_none( + json_schema, + type='string', + writeOnly=True, + format='password', + ) + return json_schema + + def get_secret_schema(strict: bool) -> CoreSchema: + inner_schema = {**cls._inner_schema, 'strict': strict} + json_schema = core_schema.no_info_after_validator_function( + source, # construct the type + inner_schema, # pyright: ignore[reportArgumentType] + ) + return core_schema.json_or_python_schema( + python_schema=core_schema.union_schema( + [ + core_schema.is_instance_schema(source), + json_schema, + ], + custom_error_type=cls._error_kind, + ), + json_schema=json_schema, + serialization=core_schema.plain_serializer_function_ser_schema( + _serialize_secret_field, + info_arg=True, + when_used='always', + ), + ) + + return core_schema.lax_or_strict_schema( + lax_schema=get_secret_schema(strict=False), + strict_schema=get_secret_schema(strict=True), + metadata={'pydantic_js_functions': [get_json_schema]}, + ) + + __pydantic_serializer__ = SchemaSerializer( + core_schema.any_schema( + serialization=core_schema.plain_serializer_function_ser_schema( + _serialize_secret_field, + info_arg=True, + when_used='always', + ) + ) + ) + + +class SecretStr(_SecretField[str]): + """A string used for storing sensitive information that you do not want to be visible in logging or tracebacks. + + When the secret value is nonempty, it is displayed as `'**********'` instead of the underlying value in + calls to `repr()` and `str()`. If the value _is_ empty, it is displayed as `''`. + + ```python + from pydantic import BaseModel, SecretStr + + class User(BaseModel): + username: str + password: SecretStr + + user = User(username='scolvin', password='password1') + + print(user) + #> username='scolvin' password=SecretStr('**********') + print(user.password.get_secret_value()) + #> password1 + print((SecretStr('password'), SecretStr(''))) + #> (SecretStr('**********'), SecretStr('')) + ``` + + As seen above, by default, [`SecretStr`][pydantic.types.SecretStr] (and [`SecretBytes`][pydantic.types.SecretBytes]) + will be serialized as `**********` when serializing to json. + + You can use the [`field_serializer`][pydantic.functional_serializers.field_serializer] to dump the + secret as plain-text when serializing to json. + + ```python + from pydantic import BaseModel, SecretBytes, SecretStr, field_serializer + + class Model(BaseModel): + password: SecretStr + password_bytes: SecretBytes + + @field_serializer('password', 'password_bytes', when_used='json') + def dump_secret(self, v): + return v.get_secret_value() + + model = Model(password='IAmSensitive', password_bytes=b'IAmSensitiveBytes') + print(model) + #> password=SecretStr('**********') password_bytes=SecretBytes(b'**********') + print(model.password) + #> ********** + print(model.model_dump()) + ''' + { + 'password': SecretStr('**********'), + 'password_bytes': SecretBytes(b'**********'), + } + ''' + print(model.model_dump_json()) + #> {"password":"IAmSensitive","password_bytes":"IAmSensitiveBytes"} + ``` + """ + + _inner_schema: ClassVar[CoreSchema] = core_schema.str_schema() + _error_kind: ClassVar[str] = 'string_type' + + def __len__(self) -> int: + return len(self._secret_value) + + def _display(self) -> str: + return _secret_display(self._secret_value) + + +class SecretBytes(_SecretField[bytes]): + """A bytes used for storing sensitive information that you do not want to be visible in logging or tracebacks. + + It displays `b'**********'` instead of the string value on `repr()` and `str()` calls. + When the secret value is nonempty, it is displayed as `b'**********'` instead of the underlying value in + calls to `repr()` and `str()`. If the value _is_ empty, it is displayed as `b''`. + + ```python + from pydantic import BaseModel, SecretBytes + + class User(BaseModel): + username: str + password: SecretBytes + + user = User(username='scolvin', password=b'password1') + #> username='scolvin' password=SecretBytes(b'**********') + print(user.password.get_secret_value()) + #> b'password1' + print((SecretBytes(b'password'), SecretBytes(b''))) + #> (SecretBytes(b'**********'), SecretBytes(b'')) + ``` + """ + + _inner_schema: ClassVar[CoreSchema] = core_schema.bytes_schema() + _error_kind: ClassVar[str] = 'bytes_type' + + def __len__(self) -> int: + return len(self._secret_value) + + def _display(self) -> bytes: + return _secret_display(self._secret_value).encode() + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PAYMENT CARD TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +class PaymentCardBrand(str, Enum): + amex = 'American Express' + mastercard = 'Mastercard' + visa = 'Visa' + other = 'other' + + def __str__(self) -> str: + return self.value + + +@deprecated( + 'The `PaymentCardNumber` class is deprecated, use `pydantic_extra_types` instead. ' + 'See https://docs.pydantic.dev/latest/api/pydantic_extra_types_payment/#pydantic_extra_types.payment.PaymentCardNumber.', + category=PydanticDeprecatedSince20, +) +class PaymentCardNumber(str): + """Based on: https://en.wikipedia.org/wiki/Payment_card_number.""" + + strip_whitespace: ClassVar[bool] = True + min_length: ClassVar[int] = 12 + max_length: ClassVar[int] = 19 + bin: str + last4: str + brand: PaymentCardBrand + + def __init__(self, card_number: str): + self.validate_digits(card_number) + + card_number = self.validate_luhn_check_digit(card_number) + + self.bin = card_number[:6] + self.last4 = card_number[-4:] + self.brand = self.validate_brand(card_number) + + @classmethod + def __get_pydantic_core_schema__(cls, source: type[Any], handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: + return core_schema.with_info_after_validator_function( + cls.validate, + core_schema.str_schema( + min_length=cls.min_length, max_length=cls.max_length, strip_whitespace=cls.strip_whitespace + ), + ) + + @classmethod + def validate(cls, input_value: str, /, _: core_schema.ValidationInfo) -> PaymentCardNumber: + """Validate the card number and return a `PaymentCardNumber` instance.""" + return cls(input_value) + + @property + def masked(self) -> str: + """Mask all but the last 4 digits of the card number. + + Returns: + A masked card number string. + """ + num_masked = len(self) - 10 # len(bin) + len(last4) == 10 + return f'{self.bin}{"*" * num_masked}{self.last4}' + + @classmethod + def validate_digits(cls, card_number: str) -> None: + """Validate that the card number is all digits.""" + if not card_number.isdigit(): + raise PydanticCustomError('payment_card_number_digits', 'Card number is not all digits') + + @classmethod + def validate_luhn_check_digit(cls, card_number: str) -> str: + """Based on: https://en.wikipedia.org/wiki/Luhn_algorithm.""" + sum_ = int(card_number[-1]) + length = len(card_number) + parity = length % 2 + for i in range(length - 1): + digit = int(card_number[i]) + if i % 2 == parity: + digit *= 2 + if digit > 9: + digit -= 9 + sum_ += digit + valid = sum_ % 10 == 0 + if not valid: + raise PydanticCustomError('payment_card_number_luhn', 'Card number is not luhn valid') + return card_number + + @staticmethod + def validate_brand(card_number: str) -> PaymentCardBrand: + """Validate length based on BIN for major brands: + https://en.wikipedia.org/wiki/Payment_card_number#Issuer_identification_number_(IIN). + """ + if card_number[0] == '4': + brand = PaymentCardBrand.visa + elif 51 <= int(card_number[:2]) <= 55: + brand = PaymentCardBrand.mastercard + elif card_number[:2] in {'34', '37'}: + brand = PaymentCardBrand.amex + else: + brand = PaymentCardBrand.other + + required_length: None | int | str = None + if brand in PaymentCardBrand.mastercard: + required_length = 16 + valid = len(card_number) == required_length + elif brand == PaymentCardBrand.visa: + required_length = '13, 16 or 19' + valid = len(card_number) in {13, 16, 19} + elif brand == PaymentCardBrand.amex: + required_length = 15 + valid = len(card_number) == required_length + else: + valid = True + + if not valid: + raise PydanticCustomError( + 'payment_card_number_brand', + 'Length for a {brand} card must be {required_length}', + {'brand': brand, 'required_length': required_length}, + ) + return brand + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ BYTE SIZE TYPE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +class ByteSize(int): + """Converts a string representing a number of bytes with units (such as `'1KB'` or `'11.5MiB'`) into an integer. + + You can use the `ByteSize` data type to (case-insensitively) convert a string representation of a number of bytes into + an integer, and also to print out human-readable strings representing a number of bytes. + + In conformance with [IEC 80000-13 Standard](https://en.wikipedia.org/wiki/ISO/IEC_80000) we interpret `'1KB'` to mean 1000 bytes, + and `'1KiB'` to mean 1024 bytes. In general, including a middle `'i'` will cause the unit to be interpreted as a power of 2, + rather than a power of 10 (so, for example, `'1 MB'` is treated as `1_000_000` bytes, whereas `'1 MiB'` is treated as `1_048_576` bytes). + + !!! info + Note that `1b` will be parsed as "1 byte" and not "1 bit". + + ```python + from pydantic import BaseModel, ByteSize + + class MyModel(BaseModel): + size: ByteSize + + print(MyModel(size=52000).size) + #> 52000 + print(MyModel(size='3000 KiB').size) + #> 3072000 + + m = MyModel(size='50 PB') + print(m.size.human_readable()) + #> 44.4PiB + print(m.size.human_readable(decimal=True)) + #> 50.0PB + print(m.size.human_readable(separator=' ')) + #> 44.4 PiB + + print(m.size.to('TiB')) + #> 45474.73508864641 + ``` + """ + + byte_sizes = { + 'b': 1, + 'kb': 10**3, + 'mb': 10**6, + 'gb': 10**9, + 'tb': 10**12, + 'pb': 10**15, + 'eb': 10**18, + 'kib': 2**10, + 'mib': 2**20, + 'gib': 2**30, + 'tib': 2**40, + 'pib': 2**50, + 'eib': 2**60, + 'bit': 1 / 8, + 'kbit': 10**3 / 8, + 'mbit': 10**6 / 8, + 'gbit': 10**9 / 8, + 'tbit': 10**12 / 8, + 'pbit': 10**15 / 8, + 'ebit': 10**18 / 8, + 'kibit': 2**10 / 8, + 'mibit': 2**20 / 8, + 'gibit': 2**30 / 8, + 'tibit': 2**40 / 8, + 'pibit': 2**50 / 8, + 'eibit': 2**60 / 8, + } + byte_sizes.update({k.lower()[0]: v for k, v in byte_sizes.items() if 'i' not in k}) + + byte_string_pattern = r'^\s*(\d*\.?\d+)\s*(\w+)?' + byte_string_re = re.compile(byte_string_pattern, re.IGNORECASE) + + @classmethod + def __get_pydantic_core_schema__(cls, source: type[Any], handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: + return core_schema.with_info_after_validator_function( + function=cls._validate, + schema=core_schema.union_schema( + [ + core_schema.str_schema(pattern=cls.byte_string_pattern), + core_schema.int_schema(ge=0), + ], + custom_error_type='byte_size', + custom_error_message='could not parse value and unit from byte string', + ), + serialization=core_schema.plain_serializer_function_ser_schema( + int, return_schema=core_schema.int_schema(ge=0) + ), + ) + + @classmethod + def _validate(cls, input_value: Any, /, _: core_schema.ValidationInfo) -> ByteSize: + try: + return cls(int(input_value)) + except ValueError: + pass + + str_match = cls.byte_string_re.match(str(input_value)) + if str_match is None: + raise PydanticCustomError('byte_size', 'could not parse value and unit from byte string') + + scalar, unit = str_match.groups() + if unit is None: + unit = 'b' + + try: + unit_mult = cls.byte_sizes[unit.lower()] + except KeyError: + raise PydanticCustomError('byte_size_unit', 'could not interpret byte unit: {unit}', {'unit': unit}) + + return cls(int(float(scalar) * unit_mult)) + + def human_readable(self, decimal: bool = False, separator: str = '') -> str: + """Converts a byte size to a human readable string. + + Args: + decimal: If True, use decimal units (e.g. 1000 bytes per KB). If False, use binary units + (e.g. 1024 bytes per KiB). + separator: A string used to split the value and unit. Defaults to an empty string (''). + + Returns: + A human readable string representation of the byte size. + """ + if decimal: + divisor = 1000 + units = 'B', 'KB', 'MB', 'GB', 'TB', 'PB' + final_unit = 'EB' + else: + divisor = 1024 + units = 'B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB' + final_unit = 'EiB' + + num = float(self) + for unit in units: + if abs(num) < divisor: + if unit == 'B': + return f'{num:0.0f}{separator}{unit}' + else: + return f'{num:0.1f}{separator}{unit}' + num /= divisor + + return f'{num:0.1f}{separator}{final_unit}' + + def to(self, unit: str) -> float: + """Converts a byte size to another unit, including both byte and bit units. + + Args: + unit: The unit to convert to. Must be one of the following: B, KB, MB, GB, TB, PB, EB, + KiB, MiB, GiB, TiB, PiB, EiB (byte units) and + bit, kbit, mbit, gbit, tbit, pbit, ebit, + kibit, mibit, gibit, tibit, pibit, eibit (bit units). + + Returns: + The byte size in the new unit. + """ + try: + unit_div = self.byte_sizes[unit.lower()] + except KeyError: + raise PydanticCustomError('byte_size_unit', 'Could not interpret byte unit: {unit}', {'unit': unit}) + + return self / unit_div + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DATE TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +def _check_annotated_type(annotated_type: str, expected_type: str, annotation: str) -> None: + if annotated_type != expected_type: + raise PydanticUserError(f"'{annotation}' cannot annotate '{annotated_type}'.", code='invalid-annotated-type') + + +if TYPE_CHECKING: + PastDate = Annotated[date, ...] + FutureDate = Annotated[date, ...] +else: + + class PastDate: + """A date in the past.""" + + @classmethod + def __get_pydantic_core_schema__( + cls, source: type[Any], handler: GetCoreSchemaHandler + ) -> core_schema.CoreSchema: + if cls is source: + # used directly as a type + return core_schema.date_schema(now_op='past') + else: + schema = handler(source) + _check_annotated_type(schema['type'], 'date', cls.__name__) + schema['now_op'] = 'past' + return schema + + def __repr__(self) -> str: + return 'PastDate' + + class FutureDate: + """A date in the future.""" + + @classmethod + def __get_pydantic_core_schema__( + cls, source: type[Any], handler: GetCoreSchemaHandler + ) -> core_schema.CoreSchema: + if cls is source: + # used directly as a type + return core_schema.date_schema(now_op='future') + else: + schema = handler(source) + _check_annotated_type(schema['type'], 'date', cls.__name__) + schema['now_op'] = 'future' + return schema + + def __repr__(self) -> str: + return 'FutureDate' + + +def condate( + *, + strict: bool | None = None, + gt: date | None = None, + ge: date | None = None, + lt: date | None = None, + le: date | None = None, +) -> type[date]: + """A wrapper for date that adds constraints. + + Args: + strict: Whether to validate the date value in strict mode. Defaults to `None`. + gt: The value must be greater than this. Defaults to `None`. + ge: The value must be greater than or equal to this. Defaults to `None`. + lt: The value must be less than this. Defaults to `None`. + le: The value must be less than or equal to this. Defaults to `None`. + + Returns: + A date type with the specified constraints. + """ + return Annotated[ # pyright: ignore[reportReturnType] + date, + Strict(strict) if strict is not None else None, + annotated_types.Interval(gt=gt, ge=ge, lt=lt, le=le), + ] + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DATETIME TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +if TYPE_CHECKING: + AwareDatetime = Annotated[datetime, ...] + NaiveDatetime = Annotated[datetime, ...] + PastDatetime = Annotated[datetime, ...] + FutureDatetime = Annotated[datetime, ...] + +else: + + class AwareDatetime: + """A datetime that requires timezone info.""" + + @classmethod + def __get_pydantic_core_schema__( + cls, source: type[Any], handler: GetCoreSchemaHandler + ) -> core_schema.CoreSchema: + if cls is source: + # used directly as a type + return core_schema.datetime_schema(tz_constraint='aware') + else: + schema = handler(source) + _check_annotated_type(schema['type'], 'datetime', cls.__name__) + schema['tz_constraint'] = 'aware' + return schema + + def __repr__(self) -> str: + return 'AwareDatetime' + + class NaiveDatetime: + """A datetime that doesn't require timezone info.""" + + @classmethod + def __get_pydantic_core_schema__( + cls, source: type[Any], handler: GetCoreSchemaHandler + ) -> core_schema.CoreSchema: + if cls is source: + # used directly as a type + return core_schema.datetime_schema(tz_constraint='naive') + else: + schema = handler(source) + _check_annotated_type(schema['type'], 'datetime', cls.__name__) + schema['tz_constraint'] = 'naive' + return schema + + def __repr__(self) -> str: + return 'NaiveDatetime' + + class PastDatetime: + """A datetime that must be in the past.""" + + @classmethod + def __get_pydantic_core_schema__( + cls, source: type[Any], handler: GetCoreSchemaHandler + ) -> core_schema.CoreSchema: + if cls is source: + # used directly as a type + return core_schema.datetime_schema(now_op='past') + else: + schema = handler(source) + _check_annotated_type(schema['type'], 'datetime', cls.__name__) + schema['now_op'] = 'past' + return schema + + def __repr__(self) -> str: + return 'PastDatetime' + + class FutureDatetime: + """A datetime that must be in the future.""" + + @classmethod + def __get_pydantic_core_schema__( + cls, source: type[Any], handler: GetCoreSchemaHandler + ) -> core_schema.CoreSchema: + if cls is source: + # used directly as a type + return core_schema.datetime_schema(now_op='future') + else: + schema = handler(source) + _check_annotated_type(schema['type'], 'datetime', cls.__name__) + schema['now_op'] = 'future' + return schema + + def __repr__(self) -> str: + return 'FutureDatetime' + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Encoded TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +class EncoderProtocol(Protocol): + """Protocol for encoding and decoding data to and from bytes.""" + + @classmethod + def decode(cls, data: bytes) -> bytes: + """Decode the data using the encoder. + + Args: + data: The data to decode. + + Returns: + The decoded data. + """ + ... + + @classmethod + def encode(cls, value: bytes) -> bytes: + """Encode the data using the encoder. + + Args: + value: The data to encode. + + Returns: + The encoded data. + """ + ... + + @classmethod + def get_json_format(cls) -> str: + """Get the JSON format for the encoded data. + + Returns: + The JSON format for the encoded data. + """ + ... + + +class Base64Encoder(EncoderProtocol): + """Standard (non-URL-safe) Base64 encoder.""" + + @classmethod + def decode(cls, data: bytes) -> bytes: + """Decode the data from base64 encoded bytes to original bytes data. + + Args: + data: The data to decode. + + Returns: + The decoded data. + """ + try: + return base64.b64decode(data) + except ValueError as e: + raise PydanticCustomError('base64_decode', "Base64 decoding error: '{error}'", {'error': str(e)}) + + @classmethod + def encode(cls, value: bytes) -> bytes: + """Encode the data from bytes to a base64 encoded bytes. + + Args: + value: The data to encode. + + Returns: + The encoded data. + """ + return base64.b64encode(value) + + @classmethod + def get_json_format(cls) -> Literal['base64']: + """Get the JSON format for the encoded data. + + Returns: + The JSON format for the encoded data. + """ + return 'base64' + + +class Base64UrlEncoder(EncoderProtocol): + """URL-safe Base64 encoder.""" + + @classmethod + def decode(cls, data: bytes) -> bytes: + """Decode the data from base64 encoded bytes to original bytes data. + + Args: + data: The data to decode. + + Returns: + The decoded data. + """ + try: + return base64.urlsafe_b64decode(data) + except ValueError as e: + raise PydanticCustomError('base64_decode', "Base64 decoding error: '{error}'", {'error': str(e)}) + + @classmethod + def encode(cls, value: bytes) -> bytes: + """Encode the data from bytes to a base64 encoded bytes. + + Args: + value: The data to encode. + + Returns: + The encoded data. + """ + return base64.urlsafe_b64encode(value) + + @classmethod + def get_json_format(cls) -> Literal['base64url']: + """Get the JSON format for the encoded data. + + Returns: + The JSON format for the encoded data. + """ + return 'base64url' + + +@_dataclasses.dataclass(**_internal_dataclass.slots_true) +class EncodedBytes: + """A bytes type that is encoded and decoded using the specified encoder. + + `EncodedBytes` needs an encoder that implements `EncoderProtocol` to operate. + + ```python + from typing import Annotated + + from pydantic import BaseModel, EncodedBytes, EncoderProtocol, ValidationError + + class MyEncoder(EncoderProtocol): + @classmethod + def decode(cls, data: bytes) -> bytes: + if data == b'**undecodable**': + raise ValueError('Cannot decode data') + return data[13:] + + @classmethod + def encode(cls, value: bytes) -> bytes: + return b'**encoded**: ' + value + + @classmethod + def get_json_format(cls) -> str: + return 'my-encoder' + + MyEncodedBytes = Annotated[bytes, EncodedBytes(encoder=MyEncoder)] + + class Model(BaseModel): + my_encoded_bytes: MyEncodedBytes + + # Initialize the model with encoded data + m = Model(my_encoded_bytes=b'**encoded**: some bytes') + + # Access decoded value + print(m.my_encoded_bytes) + #> b'some bytes' + + # Serialize into the encoded form + print(m.model_dump()) + #> {'my_encoded_bytes': b'**encoded**: some bytes'} + + # Validate encoded data + try: + Model(my_encoded_bytes=b'**undecodable**') + except ValidationError as e: + print(e) + ''' + 1 validation error for Model + my_encoded_bytes + Value error, Cannot decode data [type=value_error, input_value=b'**undecodable**', input_type=bytes] + ''' + ``` + """ + + encoder: type[EncoderProtocol] + + def __get_pydantic_json_schema__( + self, core_schema: core_schema.CoreSchema, handler: GetJsonSchemaHandler + ) -> JsonSchemaValue: + field_schema = handler(core_schema) + field_schema.update(type='string', format=self.encoder.get_json_format()) + return field_schema + + def __get_pydantic_core_schema__(self, source: type[Any], handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: + schema = handler(source) + _check_annotated_type(schema['type'], 'bytes', self.__class__.__name__) + return core_schema.with_info_after_validator_function( + function=self.decode, + schema=schema, + serialization=core_schema.plain_serializer_function_ser_schema(function=self.encode), + ) + + def decode(self, data: bytes, _: core_schema.ValidationInfo) -> bytes: + """Decode the data using the specified encoder. + + Args: + data: The data to decode. + + Returns: + The decoded data. + """ + return self.encoder.decode(data) + + def encode(self, value: bytes) -> bytes: + """Encode the data using the specified encoder. + + Args: + value: The data to encode. + + Returns: + The encoded data. + """ + return self.encoder.encode(value) + + def __hash__(self) -> int: + return hash(self.encoder) + + +@_dataclasses.dataclass(**_internal_dataclass.slots_true) +class EncodedStr: + """A str type that is encoded and decoded using the specified encoder. + + `EncodedStr` needs an encoder that implements `EncoderProtocol` to operate. + + ```python + from typing import Annotated + + from pydantic import BaseModel, EncodedStr, EncoderProtocol, ValidationError + + class MyEncoder(EncoderProtocol): + @classmethod + def decode(cls, data: bytes) -> bytes: + if data == b'**undecodable**': + raise ValueError('Cannot decode data') + return data[13:] + + @classmethod + def encode(cls, value: bytes) -> bytes: + return b'**encoded**: ' + value + + @classmethod + def get_json_format(cls) -> str: + return 'my-encoder' + + MyEncodedStr = Annotated[str, EncodedStr(encoder=MyEncoder)] + + class Model(BaseModel): + my_encoded_str: MyEncodedStr + + # Initialize the model with encoded data + m = Model(my_encoded_str='**encoded**: some str') + + # Access decoded value + print(m.my_encoded_str) + #> some str + + # Serialize into the encoded form + print(m.model_dump()) + #> {'my_encoded_str': '**encoded**: some str'} + + # Validate encoded data + try: + Model(my_encoded_str='**undecodable**') + except ValidationError as e: + print(e) + ''' + 1 validation error for Model + my_encoded_str + Value error, Cannot decode data [type=value_error, input_value='**undecodable**', input_type=str] + ''' + ``` + """ + + encoder: type[EncoderProtocol] + + def __get_pydantic_json_schema__( + self, core_schema: core_schema.CoreSchema, handler: GetJsonSchemaHandler + ) -> JsonSchemaValue: + field_schema = handler(core_schema) + field_schema.update(type='string', format=self.encoder.get_json_format()) + return field_schema + + def __get_pydantic_core_schema__(self, source: type[Any], handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: + schema = handler(source) + _check_annotated_type(schema['type'], 'str', self.__class__.__name__) + return core_schema.with_info_after_validator_function( + function=self.decode_str, + schema=schema, + serialization=core_schema.plain_serializer_function_ser_schema(function=self.encode_str), + ) + + def decode_str(self, data: str, _: core_schema.ValidationInfo) -> str: + """Decode the data using the specified encoder. + + Args: + data: The data to decode. + + Returns: + The decoded data. + """ + return self.encoder.decode(data.encode()).decode() + + def encode_str(self, value: str) -> str: + """Encode the data using the specified encoder. + + Args: + value: The data to encode. + + Returns: + The encoded data. + """ + return self.encoder.encode(value.encode()).decode() # noqa: UP008 + + def __hash__(self) -> int: + return hash(self.encoder) + + +Base64Bytes = Annotated[bytes, EncodedBytes(encoder=Base64Encoder)] +"""A bytes type that is encoded and decoded using the standard (non-URL-safe) base64 encoder. + +Note: + Under the hood, `Base64Bytes` uses the standard library `base64.b64encode` and `base64.b64decode` functions. + + As a result, attempting to decode url-safe base64 data using the `Base64Bytes` type may fail or produce an incorrect + decoding. + +Warning: + In versions of Pydantic prior to v2.10, `Base64Bytes` used [`base64.encodebytes`][base64.encodebytes] + and [`base64.decodebytes`][base64.decodebytes] functions. According to the [base64 documentation](https://docs.python.org/3/library/base64.html), + these methods are considered legacy implementation, and thus, Pydantic v2.10+ now uses the modern + [`base64.b64encode`][base64.b64encode] and [`base64.b64decode`][base64.b64decode] functions. + + If you'd still like to use these legacy encoders / decoders, you can achieve this by creating a custom annotated type, + like follows: + + ```python + import base64 + from typing import Annotated, Literal + + from pydantic_core import PydanticCustomError + + from pydantic import EncodedBytes, EncoderProtocol + + class LegacyBase64Encoder(EncoderProtocol): + @classmethod + def decode(cls, data: bytes) -> bytes: + try: + return base64.decodebytes(data) + except ValueError as e: + raise PydanticCustomError( + 'base64_decode', + "Base64 decoding error: '{error}'", + {'error': str(e)}, + ) + + @classmethod + def encode(cls, value: bytes) -> bytes: + return base64.encodebytes(value) + + @classmethod + def get_json_format(cls) -> Literal['base64']: + return 'base64' + + LegacyBase64Bytes = Annotated[bytes, EncodedBytes(encoder=LegacyBase64Encoder)] + ``` + +```python +from pydantic import Base64Bytes, BaseModel, ValidationError + +class Model(BaseModel): + base64_bytes: Base64Bytes + +# Initialize the model with base64 data +m = Model(base64_bytes=b'VGhpcyBpcyB0aGUgd2F5') + +# Access decoded value +print(m.base64_bytes) +#> b'This is the way' + +# Serialize into the base64 form +print(m.model_dump()) +#> {'base64_bytes': b'VGhpcyBpcyB0aGUgd2F5'} + +# Validate base64 data +try: + print(Model(base64_bytes=b'undecodable').base64_bytes) +except ValidationError as e: + print(e) + ''' + 1 validation error for Model + base64_bytes + Base64 decoding error: 'Incorrect padding' [type=base64_decode, input_value=b'undecodable', input_type=bytes] + ''' +``` +""" +Base64Str = Annotated[str, EncodedStr(encoder=Base64Encoder)] +"""A str type that is encoded and decoded using the standard (non-URL-safe) base64 encoder. + +Note: + Under the hood, `Base64Str` uses the standard library `base64.b64encode` and `base64.b64decode` functions. + + As a result, attempting to decode url-safe base64 data using the `Base64Str` type may fail or produce an incorrect + decoding. + +Warning: + In versions of Pydantic prior to v2.10, `Base64Str` used [`base64.encodebytes`][base64.encodebytes] + and [`base64.decodebytes`][base64.decodebytes] functions. According to the [base64 documentation](https://docs.python.org/3/library/base64.html), + these methods are considered legacy implementation, and thus, Pydantic v2.10+ now uses the modern + [`base64.b64encode`][base64.b64encode] and [`base64.b64decode`][base64.b64decode] functions. + + See the [`Base64Bytes`][pydantic.types.Base64Bytes] type for more information on how to + replicate the old behavior with the legacy encoders / decoders. + +```python +from pydantic import Base64Str, BaseModel, ValidationError + +class Model(BaseModel): + base64_str: Base64Str + +# Initialize the model with base64 data +m = Model(base64_str='VGhlc2UgYXJlbid0IHRoZSBkcm9pZHMgeW91J3JlIGxvb2tpbmcgZm9y') + +# Access decoded value +print(m.base64_str) +#> These aren't the droids you're looking for + +# Serialize into the base64 form +print(m.model_dump()) +#> {'base64_str': 'VGhlc2UgYXJlbid0IHRoZSBkcm9pZHMgeW91J3JlIGxvb2tpbmcgZm9y'} + +# Validate base64 data +try: + print(Model(base64_str='undecodable').base64_str) +except ValidationError as e: + print(e) + ''' + 1 validation error for Model + base64_str + Base64 decoding error: 'Incorrect padding' [type=base64_decode, input_value='undecodable', input_type=str] + ''' +``` +""" +Base64UrlBytes = Annotated[bytes, EncodedBytes(encoder=Base64UrlEncoder)] +"""A bytes type that is encoded and decoded using the URL-safe base64 encoder. + +Note: + Under the hood, `Base64UrlBytes` use standard library `base64.urlsafe_b64encode` and `base64.urlsafe_b64decode` + functions. + + As a result, the `Base64UrlBytes` type can be used to faithfully decode "vanilla" base64 data + (using `'+'` and `'/'`). + +```python +from pydantic import Base64UrlBytes, BaseModel + +class Model(BaseModel): + base64url_bytes: Base64UrlBytes + +# Initialize the model with base64 data +m = Model(base64url_bytes=b'SHc_dHc-TXc==') +print(m) +#> base64url_bytes=b'Hw?tw>Mw' +``` +""" +Base64UrlStr = Annotated[str, EncodedStr(encoder=Base64UrlEncoder)] +"""A str type that is encoded and decoded using the URL-safe base64 encoder. + +Note: + Under the hood, `Base64UrlStr` use standard library `base64.urlsafe_b64encode` and `base64.urlsafe_b64decode` + functions. + + As a result, the `Base64UrlStr` type can be used to faithfully decode "vanilla" base64 data (using `'+'` and `'/'`). + +```python +from pydantic import Base64UrlStr, BaseModel + +class Model(BaseModel): + base64url_str: Base64UrlStr + +# Initialize the model with base64 data +m = Model(base64url_str='SHc_dHc-TXc==') +print(m) +#> base64url_str='Hw?tw>Mw' +``` +""" + + +__getattr__ = getattr_migration(__name__) + + +@_dataclasses.dataclass(**_internal_dataclass.slots_true) +class GetPydanticSchema: + """!!! abstract "Usage Documentation" + [Using `GetPydanticSchema` to Reduce Boilerplate](../concepts/types.md#using-getpydanticschema-to-reduce-boilerplate) + + A convenience class for creating an annotation that provides pydantic custom type hooks. + + This class is intended to eliminate the need to create a custom "marker" which defines the + `__get_pydantic_core_schema__` and `__get_pydantic_json_schema__` custom hook methods. + + For example, to have a field treated by type checkers as `int`, but by pydantic as `Any`, you can do: + ```python + from typing import Annotated, Any + + from pydantic import BaseModel, GetPydanticSchema + + HandleAsAny = GetPydanticSchema(lambda _s, h: h(Any)) + + class Model(BaseModel): + x: Annotated[int, HandleAsAny] # pydantic sees `x: Any` + + print(repr(Model(x='abc').x)) + #> 'abc' + ``` + """ + + get_pydantic_core_schema: Callable[[Any, GetCoreSchemaHandler], CoreSchema] | None = None + get_pydantic_json_schema: Callable[[Any, GetJsonSchemaHandler], JsonSchemaValue] | None = None + + # Note: we may want to consider adding a convenience staticmethod `def for_type(type_: Any) -> GetPydanticSchema:` + # which returns `GetPydanticSchema(lambda _s, h: h(type_))` + + if not TYPE_CHECKING: + # We put `__getattr__` in a non-TYPE_CHECKING block because otherwise, mypy allows arbitrary attribute access + + def __getattr__(self, item: str) -> Any: + """Use this rather than defining `__get_pydantic_core_schema__` etc. to reduce the number of nested calls.""" + if item == '__get_pydantic_core_schema__' and self.get_pydantic_core_schema: + return self.get_pydantic_core_schema + elif item == '__get_pydantic_json_schema__' and self.get_pydantic_json_schema: + return self.get_pydantic_json_schema + else: + return object.__getattribute__(self, item) + + __hash__ = object.__hash__ + + +@_dataclasses.dataclass(**_internal_dataclass.slots_true, frozen=True) +class Tag: + """Provides a way to specify the expected tag to use for a case of a (callable) discriminated union. + + Also provides a way to label a union case in error messages. + + When using a callable `Discriminator`, attach a `Tag` to each case in the `Union` to specify the tag that + should be used to identify that case. For example, in the below example, the `Tag` is used to specify that + if `get_discriminator_value` returns `'apple'`, the input should be validated as an `ApplePie`, and if it + returns `'pumpkin'`, the input should be validated as a `PumpkinPie`. + + The primary role of the `Tag` here is to map the return value from the callable `Discriminator` function to + the appropriate member of the `Union` in question. + + ```python + from typing import Annotated, Any, Literal, Union + + from pydantic import BaseModel, Discriminator, Tag + + class Pie(BaseModel): + time_to_cook: int + num_ingredients: int + + class ApplePie(Pie): + fruit: Literal['apple'] = 'apple' + + class PumpkinPie(Pie): + filling: Literal['pumpkin'] = 'pumpkin' + + def get_discriminator_value(v: Any) -> str: + if isinstance(v, dict): + return v.get('fruit', v.get('filling')) + return getattr(v, 'fruit', getattr(v, 'filling', None)) + + class ThanksgivingDinner(BaseModel): + dessert: Annotated[ + Union[ + Annotated[ApplePie, Tag('apple')], + Annotated[PumpkinPie, Tag('pumpkin')], + ], + Discriminator(get_discriminator_value), + ] + + apple_variation = ThanksgivingDinner.model_validate( + {'dessert': {'fruit': 'apple', 'time_to_cook': 60, 'num_ingredients': 8}} + ) + print(repr(apple_variation)) + ''' + ThanksgivingDinner(dessert=ApplePie(time_to_cook=60, num_ingredients=8, fruit='apple')) + ''' + + pumpkin_variation = ThanksgivingDinner.model_validate( + { + 'dessert': { + 'filling': 'pumpkin', + 'time_to_cook': 40, + 'num_ingredients': 6, + } + } + ) + print(repr(pumpkin_variation)) + ''' + ThanksgivingDinner(dessert=PumpkinPie(time_to_cook=40, num_ingredients=6, filling='pumpkin')) + ''' + ``` + + !!! note + You must specify a `Tag` for every case in a `Tag` that is associated with a + callable `Discriminator`. Failing to do so will result in a `PydanticUserError` with code + [`callable-discriminator-no-tag`](../errors/usage_errors.md#callable-discriminator-no-tag). + + See the [Discriminated Unions] concepts docs for more details on how to use `Tag`s. + + [Discriminated Unions]: ../concepts/unions.md#discriminated-unions + """ + + tag: str + + def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> CoreSchema: + schema = handler(source_type) + metadata = cast('CoreMetadata', schema.setdefault('metadata', {})) + metadata['pydantic_internal_union_tag_key'] = self.tag + return schema + + +@_dataclasses.dataclass(**_internal_dataclass.slots_true, frozen=True) +class Discriminator: + """!!! abstract "Usage Documentation" + [Discriminated Unions with `Callable` `Discriminator`](../concepts/unions.md#discriminated-unions-with-callable-discriminator) + + Provides a way to use a custom callable as the way to extract the value of a union discriminator. + + This allows you to get validation behavior like you'd get from `Field(discriminator=)`, + but without needing to have a single shared field across all the union choices. This also makes it + possible to handle unions of models and primitive types with discriminated-union-style validation errors. + Finally, this allows you to use a custom callable as the way to identify which member of a union a value + belongs to, while still seeing all the performance benefits of a discriminated union. + + Consider this example, which is much more performant with the use of `Discriminator` and thus a `TaggedUnion` + than it would be as a normal `Union`. + + ```python + from typing import Annotated, Any, Literal, Union + + from pydantic import BaseModel, Discriminator, Tag + + class Pie(BaseModel): + time_to_cook: int + num_ingredients: int + + class ApplePie(Pie): + fruit: Literal['apple'] = 'apple' + + class PumpkinPie(Pie): + filling: Literal['pumpkin'] = 'pumpkin' + + def get_discriminator_value(v: Any) -> str: + if isinstance(v, dict): + return v.get('fruit', v.get('filling')) + return getattr(v, 'fruit', getattr(v, 'filling', None)) + + class ThanksgivingDinner(BaseModel): + dessert: Annotated[ + Union[ + Annotated[ApplePie, Tag('apple')], + Annotated[PumpkinPie, Tag('pumpkin')], + ], + Discriminator(get_discriminator_value), + ] + + apple_variation = ThanksgivingDinner.model_validate( + {'dessert': {'fruit': 'apple', 'time_to_cook': 60, 'num_ingredients': 8}} + ) + print(repr(apple_variation)) + ''' + ThanksgivingDinner(dessert=ApplePie(time_to_cook=60, num_ingredients=8, fruit='apple')) + ''' + + pumpkin_variation = ThanksgivingDinner.model_validate( + { + 'dessert': { + 'filling': 'pumpkin', + 'time_to_cook': 40, + 'num_ingredients': 6, + } + } + ) + print(repr(pumpkin_variation)) + ''' + ThanksgivingDinner(dessert=PumpkinPie(time_to_cook=40, num_ingredients=6, filling='pumpkin')) + ''' + ``` + + See the [Discriminated Unions] concepts docs for more details on how to use `Discriminator`s. + + [Discriminated Unions]: ../concepts/unions.md#discriminated-unions + """ + + discriminator: str | Callable[[Any], Hashable] + """The callable or field name for discriminating the type in a tagged union. + + A `Callable` discriminator must extract the value of the discriminator from the input. + A `str` discriminator must be the name of a field to discriminate against. + """ + custom_error_type: str | None = None + """Type to use in [custom errors](../errors/errors.md) replacing the standard discriminated union + validation errors. + """ + custom_error_message: str | None = None + """Message to use in custom errors.""" + custom_error_context: dict[str, int | str | float] | None = None + """Context to use in custom errors.""" + + def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> CoreSchema: + if not is_union_origin(get_origin(source_type)): + raise TypeError(f'{type(self).__name__} must be used with a Union type, not {source_type}') + + if isinstance(self.discriminator, str): + from pydantic import Field + + return handler(Annotated[source_type, Field(discriminator=self.discriminator)]) + else: + original_schema = handler(source_type) + return self._convert_schema(original_schema, handler) + + def _convert_schema( + self, original_schema: core_schema.CoreSchema, handler: GetCoreSchemaHandler | None = None + ) -> core_schema.TaggedUnionSchema: + if original_schema['type'] != 'union': + # This likely indicates that the schema was a single-item union that was simplified. + # In this case, we do the same thing we do in + # `pydantic._internal._discriminated_union._ApplyInferredDiscriminator._apply_to_root`, namely, + # package the generated schema back into a single-item union. + original_schema = core_schema.union_schema([original_schema]) + + tagged_union_choices = {} + for choice in original_schema['choices']: + tag = None + if isinstance(choice, tuple): + choice, tag = choice + metadata = cast('CoreMetadata | None', choice.get('metadata')) + if metadata is not None: + tag = metadata.get('pydantic_internal_union_tag_key') or tag + if tag is None: + # `handler` is None when this method is called from `apply_discriminator()` (deferred discriminators) + if handler is not None and choice['type'] == 'definition-ref': + # If choice was built from a PEP 695 type alias, try to resolve the def: + try: + choice = handler.resolve_ref_schema(choice) + except LookupError: + pass + else: + metadata = cast('CoreMetadata | None', choice.get('metadata')) + if metadata is not None: + tag = metadata.get('pydantic_internal_union_tag_key') + + if tag is None: + raise PydanticUserError( + f'`Tag` not provided for choice {choice} used with `Discriminator`', + code='callable-discriminator-no-tag', + ) + tagged_union_choices[tag] = choice + + # Have to do these verbose checks to ensure falsy values ('' and {}) don't get ignored + custom_error_type = self.custom_error_type + if custom_error_type is None: + custom_error_type = original_schema.get('custom_error_type') + + custom_error_message = self.custom_error_message + if custom_error_message is None: + custom_error_message = original_schema.get('custom_error_message') + + custom_error_context = self.custom_error_context + if custom_error_context is None: + custom_error_context = original_schema.get('custom_error_context') + + custom_error_type = original_schema.get('custom_error_type') if custom_error_type is None else custom_error_type + return core_schema.tagged_union_schema( + tagged_union_choices, + self.discriminator, + custom_error_type=custom_error_type, + custom_error_message=custom_error_message, + custom_error_context=custom_error_context, + strict=original_schema.get('strict'), + ref=original_schema.get('ref'), + metadata=original_schema.get('metadata'), + serialization=original_schema.get('serialization'), + ) + + +_JSON_TYPES = {int, float, str, bool, list, dict, type(None)} + + +def _get_type_name(x: Any) -> str: + type_ = type(x) + if type_ in _JSON_TYPES: + return type_.__name__ + + # Handle proper subclasses; note we don't need to handle None or bool here + if isinstance(x, int): + return 'int' + if isinstance(x, float): + return 'float' + if isinstance(x, str): + return 'str' + if isinstance(x, list): + return 'list' + if isinstance(x, dict): + return 'dict' + + # Fail by returning the type's actual name + return getattr(type_, '__name__', '') + + +class _AllowAnyJson: + @classmethod + def __get_pydantic_core_schema__(cls, source_type: Any, handler: GetCoreSchemaHandler) -> CoreSchema: + python_schema = handler(source_type) + return core_schema.json_or_python_schema(json_schema=core_schema.any_schema(), python_schema=python_schema) + + +if TYPE_CHECKING: + # This seems to only be necessary for mypy + JsonValue: TypeAlias = Union[ + list['JsonValue'], + dict[str, 'JsonValue'], + str, + bool, + int, + float, + None, + ] + """A `JsonValue` is used to represent a value that can be serialized to JSON. + + It may be one of: + + * `list['JsonValue']` + * `dict[str, 'JsonValue']` + * `str` + * `bool` + * `int` + * `float` + * `None` + + The following example demonstrates how to use `JsonValue` to validate JSON data, + and what kind of errors to expect when input data is not json serializable. + + ```python + import json + + from pydantic import BaseModel, JsonValue, ValidationError + + class Model(BaseModel): + j: JsonValue + + valid_json_data = {'j': {'a': {'b': {'c': 1, 'd': [2, None]}}}} + invalid_json_data = {'j': {'a': {'b': ...}}} + + print(repr(Model.model_validate(valid_json_data))) + #> Model(j={'a': {'b': {'c': 1, 'd': [2, None]}}}) + print(repr(Model.model_validate_json(json.dumps(valid_json_data)))) + #> Model(j={'a': {'b': {'c': 1, 'd': [2, None]}}}) + + try: + Model.model_validate(invalid_json_data) + except ValidationError as e: + print(e) + ''' + 1 validation error for Model + j.dict.a.dict.b + input was not a valid JSON value [type=invalid-json-value, input_value=Ellipsis, input_type=ellipsis] + ''' + ``` + """ + +else: + JsonValue = TypeAliasType( + 'JsonValue', + Annotated[ + Union[ + Annotated[list['JsonValue'], Tag('list')], + Annotated[dict[str, 'JsonValue'], Tag('dict')], + Annotated[str, Tag('str')], + Annotated[bool, Tag('bool')], + Annotated[int, Tag('int')], + Annotated[float, Tag('float')], + Annotated[None, Tag('NoneType')], + ], + Discriminator( + _get_type_name, + custom_error_type='invalid-json-value', + custom_error_message='input was not a valid JSON value', + ), + _AllowAnyJson, + ], + ) + + +class _OnErrorOmit: + @classmethod + def __get_pydantic_core_schema__(cls, source_type: Any, handler: GetCoreSchemaHandler) -> CoreSchema: + # there is no actual default value here but we use with_default_schema since it already has the on_error + # behavior implemented and it would be no more efficient to implement it on every other validator + # or as a standalone validator + return core_schema.with_default_schema(schema=handler(source_type), on_error='omit') + + +OnErrorOmit = Annotated[T, _OnErrorOmit] +""" +When used as an item in a list, the key type in a dict, optional values of a TypedDict, etc. +this annotation omits the item from the iteration if there is any error validating it. +That is, instead of a [`ValidationError`][pydantic_core.ValidationError] being propagated up and the entire iterable being discarded +any invalid items are discarded and the valid ones are returned. +""" + + +@_dataclasses.dataclass +class FailFast(_fields.PydanticMetadata, BaseMetadata): + """A `FailFast` annotation can be used to specify that validation should stop at the first error. + + This can be useful when you want to validate a large amount of data and you only need to know if it's valid or not. + + You might want to enable this setting if you want to validate your data faster (basically, if you use this, + validation will be more performant with the caveat that you get less information). + + ```python + from typing import Annotated + + from pydantic import BaseModel, FailFast, ValidationError + + class Model(BaseModel): + x: Annotated[list[int], FailFast()] + + # This will raise a single error for the first invalid value and stop validation + try: + obj = Model(x=[1, 2, 'a', 4, 5, 'b', 7, 8, 9, 'c']) + except ValidationError as e: + print(e) + ''' + 1 validation error for Model + x.2 + Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='a', input_type=str] + ''' + ``` + """ + + fail_fast: bool = True diff --git a/backend/.venv/Lib/site-packages/pydantic/typing.py b/backend/.venv/Lib/site-packages/pydantic/typing.py new file mode 100644 index 0000000..0bda22d --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/typing.py @@ -0,0 +1,5 @@ +"""`typing` module is a backport module from V1.""" + +from ._migration import getattr_migration + +__getattr__ = getattr_migration(__name__) diff --git a/backend/.venv/Lib/site-packages/pydantic/utils.py b/backend/.venv/Lib/site-packages/pydantic/utils.py new file mode 100644 index 0000000..8d1e2a8 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/utils.py @@ -0,0 +1,5 @@ +"""The `utils` module is a backport module from V1.""" + +from ._migration import getattr_migration + +__getattr__ = getattr_migration(__name__) diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/__init__.py b/backend/.venv/Lib/site-packages/pydantic/v1/__init__.py new file mode 100644 index 0000000..4807865 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/__init__.py @@ -0,0 +1,142 @@ +# flake8: noqa +import sys +import warnings + +from pydantic.v1 import dataclasses +from pydantic.v1.annotated_types import create_model_from_namedtuple, create_model_from_typeddict +from pydantic.v1.class_validators import root_validator, validator +from pydantic.v1.config import BaseConfig, ConfigDict, Extra +from pydantic.v1.decorator import validate_arguments +from pydantic.v1.env_settings import BaseSettings +from pydantic.v1.error_wrappers import ValidationError +from pydantic.v1.errors import * +from pydantic.v1.fields import Field, PrivateAttr, Required +from pydantic.v1.main import * +from pydantic.v1.networks import * +from pydantic.v1.parse import Protocol +from pydantic.v1.tools import * +from pydantic.v1.types import * +from pydantic.v1.version import VERSION, compiled + +__version__ = VERSION + +# WARNING __all__ from pydantic.errors is not included here, it will be removed as an export here in v2 +# please use "from pydantic.v1.errors import ..." instead +__all__ = [ + # annotated types utils + 'create_model_from_namedtuple', + 'create_model_from_typeddict', + # dataclasses + 'dataclasses', + # class_validators + 'root_validator', + 'validator', + # config + 'BaseConfig', + 'ConfigDict', + 'Extra', + # decorator + 'validate_arguments', + # env_settings + 'BaseSettings', + # error_wrappers + 'ValidationError', + # fields + 'Field', + 'Required', + # main + 'BaseModel', + 'create_model', + 'validate_model', + # network + 'AnyUrl', + 'AnyHttpUrl', + 'FileUrl', + 'HttpUrl', + 'stricturl', + 'EmailStr', + 'NameEmail', + 'IPvAnyAddress', + 'IPvAnyInterface', + 'IPvAnyNetwork', + 'PostgresDsn', + 'CockroachDsn', + 'AmqpDsn', + 'RedisDsn', + 'MongoDsn', + 'KafkaDsn', + 'validate_email', + # parse + 'Protocol', + # tools + 'parse_file_as', + 'parse_obj_as', + 'parse_raw_as', + 'schema_of', + 'schema_json_of', + # types + 'NoneStr', + 'NoneBytes', + 'StrBytes', + 'NoneStrBytes', + 'StrictStr', + 'ConstrainedBytes', + 'conbytes', + 'ConstrainedList', + 'conlist', + 'ConstrainedSet', + 'conset', + 'ConstrainedFrozenSet', + 'confrozenset', + 'ConstrainedStr', + 'constr', + 'PyObject', + 'ConstrainedInt', + 'conint', + 'PositiveInt', + 'NegativeInt', + 'NonNegativeInt', + 'NonPositiveInt', + 'ConstrainedFloat', + 'confloat', + 'PositiveFloat', + 'NegativeFloat', + 'NonNegativeFloat', + 'NonPositiveFloat', + 'FiniteFloat', + 'ConstrainedDecimal', + 'condecimal', + 'ConstrainedDate', + 'condate', + 'UUID1', + 'UUID3', + 'UUID4', + 'UUID5', + 'FilePath', + 'DirectoryPath', + 'Json', + 'JsonWrapper', + 'SecretField', + 'SecretStr', + 'SecretBytes', + 'StrictBool', + 'StrictBytes', + 'StrictInt', + 'StrictFloat', + 'PaymentCardNumber', + 'PrivateAttr', + 'ByteSize', + 'PastDate', + 'FutureDate', + # version + 'compiled', + 'VERSION', +] + + +if sys.version_info >= (3, 14): + warnings.warn( + "Core Pydantic V1 functionality isn't compatible with Python 3.14 or greater.", + UserWarning, + stacklevel=2, + ) diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6a5db6c3c95a8d0ade70d3522387cc4ee7aa36c9 GIT binary patch literal 2515 zcmZWr%WoS+7@zecUcZw#eb9#1ZKYO0YKqmuffl4Z)j*R*jgpF$#WL9)JDbezxHDs? zu7oHjuH3kDL%?6csa%MLL_w-Jm&3YK53e{^EJW(g)i(0WKUmH+f_Co@ zlRrKE%3c#8el~@OwfpI*e#rS%a@`;QdE%#Ztg%qv>RU6DCt6&au~gB=5_=R2LBvc- zO?#YRN!*b6gt{%xLN~%8@nyF|iMsfItL%4(?+2cQ;0k9yBm^73ec8x*and@h}v4NZpGIJEL!56aZp+B z!S&hYfKXo**Ll!`1m>jV%6>$ibOTO&aI)7qlgwij-kIB4dbF|fa821B3p)V?hc9>r z3c~eNaa}4trb$i{Ta&yddK!6A6PQNC%bHX*nE;~l`lYM7ZmN{5ld8N)%v4p4%|-o9 zPE`TU`%-o^pIe4!7-p!+3(28AT`<~9Ar9yUWRzcnW*AA8SJr!Q!JO}NB7~~O;z}e5 zZ()xN?Q2BtGrk9fVM4aSbx}mBw7|SQ&ak(mrQBTjq@x+Amme4hdzD3PW^|w7)*jZ} zX&OX7hfnIH%N@)Gaa-_u7YkL2MYg@0kT~AgQeJpF5b3g(stnj&!6Gf^)>uU1{D7J7 zOCppFa?F(m)>z7e9_pgK$6<^F3{Made-PxcXxoHW6SfC|kSYfzs+mf{0)wT-z#!n9 zO6Zq4dqyH{ErAu*03_`*5(_Udv3k=m9kJjhOiq`mc(bKIXX7 zAzT$V2<(oGmpLB`y43@H+~q<%0`rVfFqm-|nGI9oSRdy#v5xy1P!=%v*Sg_0;e1?A zudTy2f@cI8h=nvM6_&fObVT!fN-uW}$V}=)qryoA$g>9vjFb9$-^Y;*y!uw7-s(o4 z1VjR8lKpxhq8qZVp#^%pO-X$}kUQWncUV-vJ=?fbXS@!psJ}3KlG4{(svrP{_bBNR zI&(v%MISa`AM;4Vo+@?*ADitp3_Pie3C%2yA|~NB-_>X=PN7UqC*2InpTe^^#W*!N z;%7kmE!o2nDJ0W z*BvNbSLIw6QwmIJs0*SNQyJY!RooPWKaP9)BYF*KpnpGK_^7GzS#$uio6)WmH?ilj zE=*R`z6nJp&25+q68X*99#ppZAlPmKkdT`Yu!q}3G>6Z-)oa{xUA@h&JKO0i`yTwc z=~D6u{~Epo|0N;u6v(TzWmzv#;SW^(3tc-#_!!L}qkAvVy(4tz2sMt-hli+sjPAZb zcMs8}Lv-~BT|Y#Z;rAFd{;ZsNUi{k*tzznV?$wuRl*#>`uDwXtzT5vTed!=G@%;X` dtKY01*jop7?VvXGPcD-kdj)Qn`B(7q{{YF{P}l$f literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/_hypothesis_plugin.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/_hypothesis_plugin.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9339affe35119a22dd8ca906c19b5b668f58f24b GIT binary patch literal 20502 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 LRQu}^8p8h%tzoWe literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/annotated_types.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/annotated_types.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7e92d83f1235904b13054991a1fc9c1cda8ec05d GIT binary patch literal 3881 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/color.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/color.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..46e48a124c6ae0002d5240c7a7e29ea550b5d1e7 GIT binary patch literal 25847 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 AtpET3 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/config.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/config.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..379bdcd792bbd3c308abe7014309cd1c91dfc7d5 GIT binary patch literal 8396 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/dataclasses.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/dataclasses.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2cb386e0cf5ef26af2d8bffe403a97271610c673 GIT binary patch literal 22741 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 ROl2b$ZoM<{7$0PX{|{7tP`>~G literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/decorator.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/decorator.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..84ebed73b8de9616db2ffc5d0729c7575535d996 GIT binary patch literal 13914 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 R{!%}vrDL$o$%io7e*twOl@I^` literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/env_settings.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/env_settings.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ee2f581d2396bd785dd07bf7c20395dd3da01680 GIT binary patch literal 17716 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 L!TVIgR_^}+w5l5l literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/error_wrappers.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/error_wrappers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a924ef533b183631ad4dba98db855d532261033b GIT binary patch literal 8924 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 PkS0)FI=G1sMy3A;E^~xA literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/errors.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/errors.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..403b44c7d9c34389b2257a3ff8f7e19e47588483 GIT binary patch literal 29599 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/main.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/main.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..de42ed8bc4081858e9ee2d59c3858f408911da5c GIT binary patch literal 48213 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≻zO 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 P8vLrgD=Ny!hKc_G)+H8( literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/mypy.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/mypy.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..75e7dce972040db06714d7654e0f064d48439b2e GIT binary patch literal 46355 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
    3GuJ-**>cqi+r6spF1%NaCbb=a?kL0G$ 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 Tazhg7t&n7rgj|ne$;r~cBfDAf literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/schema.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/schema.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e0206cfa16860c705e73a7f61212717cdf587dfb GIT binary patch literal 48472 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 HbmjjGB1QqQ literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/tools.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/tools.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8da5263c83eae1c75bea8132ec44da3a5354d04b GIT binary patch literal 3877 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 literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/utils.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9a05b1ef523779e274b2948a50072c6301102682 GIT binary patch literal 35234 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 W4qky&w?XnPO52<6*;yhc(fvP&k12fs literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/version.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic/v1/__pycache__/version.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e3094e959007bfc9f4d364d2dac401b5535c2de2 GIT binary patch literal 1955 zcmZt`TWlLeaQEJJ?L3GR*-6^Cv?a3II0+T1lBTI3Euyr9mKGF(E9>Ihr01OPPInil zacvZ#N)!}{@1IEVoHQ^)j10ij>n!3Q{3VY3Km5xt2tG>$Ypjsr;JG~VFGxd0+uR;ugmK;yh7 z5oMCo-{kbz1yj7u2KoWbSz5(hqEh*QXkB_5+GR1!4d1iE+#p^_Lt94c}} zF&p;HZevZtwclo99zSobB}KZCpgzx`*35@Vb5|3YvUNDoL7>?b<1?(OTdtDoWYC|CRXnPi$H8 zy*`ijA+N!|0hNc$Lamp#Y8@PPL=Y!14eL4Ea=diT(q;?-4B@QmT}lX4(MaC2EW@Re zW_iTS7aB=U)s3FKYUrBkSx%wZo3nLus)t+#IqMOZ;vS0A38~Oz&uOaZ>6v)FeG1K6 z9KXj3A>DL6)iB~VJXvV4=e$dn>0h9VZK&R)<>U%c%l5#!YQ!~SyUBR{8gwZRW_Bi4 zftU`%+I$zb)6fo!sE97UfKUn=rG!hI_P>QFLOT}VhQ}JV3PsLOWtQdXU%)=*R_oPU z@DsdpJWX-lWsbz-@uy=WgQ;1|nRac^NSRsB?NKusYX&k4dCyo5NlmDkX<}-rWFBgi zI-^gdT-_r*aA8`VB5ul0dvCtKw_b~+Jx2pWQ^X{fZD+X9weyE3hYTyD8t!m%OW`?i z#vO$1H}qs4twcz9Oe>$guyXd?%J~b|-&t$zF1L0s;iZu~^0zHto%^Qk`#oRpxhvew ztoFaU)_NMW|8m)wd++EmoM?7fUqa|}E)CRr&(J3vRyiuOK47N+oSat1+I6bho+lm0 za;T)*HiYW1?9?WYl1@*;xJsv48ePlC6DrxNLrjm#^{A+jwRDq;kd&O8kgLx-9n1oI zv-%Vb`wf<64Mwp|1vc$mHpHL|3>-EH92Q1(YXZXk4z_u;A+&4=4G)FxheGG0NZb5t z8{yN}aE0Rotq(%68+&gjZYDk-S!!8r@3|LBRwNW?TT?pAO6QGp_m!^7F4S-aKW;+1 z_y4l{z=LS#t+7uV)}qOBG`Sk>TZZl+5mEd}z_2HRR8FViL#ET!98)P%{gSm@H@xV1jy^Htk!m%ZJz#TLfs?|K*L7PCLYWAoyRGTuxP9N~t$8{%R1D7yfN4+b--g)^^uw`DZ z2nvpE2+b9R7h~%!vBl#bAHSwlf^B#bU(Y;73_qy^P^cZkVj9s86|f@4{)TiaEx^Pb s>#gncuUyma3+>E)$5S^7PrWZ3LJOfTbX!jFOE|%Q5jx8MfRFP30G&M7cK`qY literal 0 HcmV?d00001 diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/_hypothesis_plugin.py b/backend/.venv/Lib/site-packages/pydantic/v1/_hypothesis_plugin.py new file mode 100644 index 0000000..b62234d --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/_hypothesis_plugin.py @@ -0,0 +1,391 @@ +""" +Register Hypothesis strategies for Pydantic custom types. + +This enables fully-automatic generation of test data for most Pydantic classes. + +Note that this module has *no* runtime impact on Pydantic itself; instead it +is registered as a setuptools entry point and Hypothesis will import it if +Pydantic is installed. See also: + +https://hypothesis.readthedocs.io/en/latest/strategies.html#registering-strategies-via-setuptools-entry-points +https://hypothesis.readthedocs.io/en/latest/data.html#hypothesis.strategies.register_type_strategy +https://hypothesis.readthedocs.io/en/latest/strategies.html#interaction-with-pytest-cov +https://docs.pydantic.dev/usage/types/#pydantic-types + +Note that because our motivation is to *improve user experience*, the strategies +are always sound (never generate invalid data) but sacrifice completeness for +maintainability (ie may be unable to generate some tricky but valid data). + +Finally, this module makes liberal use of `# type: ignore[]` pragmas. +This is because Hypothesis annotates `register_type_strategy()` with +`(T, SearchStrategy[T])`, but in most cases we register e.g. `ConstrainedInt` +to generate instances of the builtin `int` type which match the constraints. +""" + +import contextlib +import datetime +import ipaddress +import json +import math +from fractions import Fraction +from typing import Callable, Dict, Type, Union, cast, overload + +import hypothesis.strategies as st + +import pydantic +import pydantic.color +import pydantic.types +from pydantic.v1.utils import lenient_issubclass + +# FilePath and DirectoryPath are explicitly unsupported, as we'd have to create +# them on-disk, and that's unsafe in general without being told *where* to do so. +# +# URLs are unsupported because it's easy for users to define their own strategy for +# "normal" URLs, and hard for us to define a general strategy which includes "weird" +# URLs but doesn't also have unpredictable performance problems. +# +# conlist() and conset() are unsupported for now, because the workarounds for +# Cython and Hypothesis to handle parametrized generic types are incompatible. +# We are rethinking Hypothesis compatibility in Pydantic v2. + +# Emails +try: + import email_validator +except ImportError: # pragma: no cover + pass +else: + + def is_valid_email(s: str) -> bool: + # Hypothesis' st.emails() occasionally generates emails like 0@A0--0.ac + # that are invalid according to email-validator, so we filter those out. + try: + email_validator.validate_email(s, check_deliverability=False) + return True + except email_validator.EmailNotValidError: # pragma: no cover + return False + + # Note that these strategies deliberately stay away from any tricky Unicode + # or other encoding issues; we're just trying to generate *something* valid. + st.register_type_strategy(pydantic.EmailStr, st.emails().filter(is_valid_email)) # type: ignore[arg-type] + st.register_type_strategy( + pydantic.NameEmail, + st.builds( + '{} <{}>'.format, # type: ignore[arg-type] + st.from_regex('[A-Za-z0-9_]+( [A-Za-z0-9_]+){0,5}', fullmatch=True), + st.emails().filter(is_valid_email), + ), + ) + +# PyObject - dotted names, in this case taken from the math module. +st.register_type_strategy( + pydantic.PyObject, # type: ignore[arg-type] + st.sampled_from( + [cast(pydantic.PyObject, f'math.{name}') for name in sorted(vars(math)) if not name.startswith('_')] + ), +) + +# CSS3 Colors; as name, hex, rgb(a) tuples or strings, or hsl strings +_color_regexes = ( + '|'.join( + ( + pydantic.color.r_hex_short, + pydantic.color.r_hex_long, + pydantic.color.r_rgb, + pydantic.color.r_rgba, + pydantic.color.r_hsl, + pydantic.color.r_hsla, + ) + ) + # Use more precise regex patterns to avoid value-out-of-range errors + .replace(pydantic.color._r_sl, r'(?:(\d\d?(?:\.\d+)?|100(?:\.0+)?)%)') + .replace(pydantic.color._r_alpha, r'(?:(0(?:\.\d+)?|1(?:\.0+)?|\.\d+|\d{1,2}%))') + .replace(pydantic.color._r_255, r'(?:((?:\d|\d\d|[01]\d\d|2[0-4]\d|25[0-4])(?:\.\d+)?|255(?:\.0+)?))') +) +st.register_type_strategy( + pydantic.color.Color, + st.one_of( + st.sampled_from(sorted(pydantic.color.COLORS_BY_NAME)), + st.tuples( + st.integers(0, 255), + st.integers(0, 255), + st.integers(0, 255), + st.none() | st.floats(0, 1) | st.floats(0, 100).map('{}%'.format), + ), + st.from_regex(_color_regexes, fullmatch=True), + ), +) + + +# Card numbers, valid according to the Luhn algorithm + + +def add_luhn_digit(card_number: str) -> str: + # See https://en.wikipedia.org/wiki/Luhn_algorithm + for digit in '0123456789': + with contextlib.suppress(Exception): + pydantic.PaymentCardNumber.validate_luhn_check_digit(card_number + digit) + return card_number + digit + raise AssertionError('Unreachable') # pragma: no cover + + +card_patterns = ( + # Note that these patterns omit the Luhn check digit; that's added by the function above + '4[0-9]{14}', # Visa + '5[12345][0-9]{13}', # Mastercard + '3[47][0-9]{12}', # American Express + '[0-26-9][0-9]{10,17}', # other (incomplete to avoid overlap) +) +st.register_type_strategy( + pydantic.PaymentCardNumber, + st.from_regex('|'.join(card_patterns), fullmatch=True).map(add_luhn_digit), # type: ignore[arg-type] +) + +# UUIDs +st.register_type_strategy(pydantic.UUID1, st.uuids(version=1)) +st.register_type_strategy(pydantic.UUID3, st.uuids(version=3)) +st.register_type_strategy(pydantic.UUID4, st.uuids(version=4)) +st.register_type_strategy(pydantic.UUID5, st.uuids(version=5)) + +# Secrets +st.register_type_strategy(pydantic.SecretBytes, st.binary().map(pydantic.SecretBytes)) +st.register_type_strategy(pydantic.SecretStr, st.text().map(pydantic.SecretStr)) + +# IP addresses, networks, and interfaces +st.register_type_strategy(pydantic.IPvAnyAddress, st.ip_addresses()) # type: ignore[arg-type] +st.register_type_strategy( + pydantic.IPvAnyInterface, + st.from_type(ipaddress.IPv4Interface) | st.from_type(ipaddress.IPv6Interface), # type: ignore[arg-type] +) +st.register_type_strategy( + pydantic.IPvAnyNetwork, + st.from_type(ipaddress.IPv4Network) | st.from_type(ipaddress.IPv6Network), # type: ignore[arg-type] +) + +# We hook into the con***() functions and the ConstrainedNumberMeta metaclass, +# so here we only have to register subclasses for other constrained types which +# don't go via those mechanisms. Then there are the registration hooks below. +st.register_type_strategy(pydantic.StrictBool, st.booleans()) +st.register_type_strategy(pydantic.StrictStr, st.text()) + + +# FutureDate, PastDate +st.register_type_strategy(pydantic.FutureDate, st.dates(min_value=datetime.date.today() + datetime.timedelta(days=1))) +st.register_type_strategy(pydantic.PastDate, st.dates(max_value=datetime.date.today() - datetime.timedelta(days=1))) + + +# Constrained-type resolver functions +# +# For these ones, we actually want to inspect the type in order to work out a +# satisfying strategy. First up, the machinery for tracking resolver functions: + +RESOLVERS: Dict[type, Callable[[type], st.SearchStrategy]] = {} # type: ignore[type-arg] + + +@overload +def _registered(typ: Type[pydantic.types.T]) -> Type[pydantic.types.T]: + pass + + +@overload +def _registered(typ: pydantic.types.ConstrainedNumberMeta) -> pydantic.types.ConstrainedNumberMeta: + pass + + +def _registered( + typ: Union[Type[pydantic.types.T], pydantic.types.ConstrainedNumberMeta] +) -> Union[Type[pydantic.types.T], pydantic.types.ConstrainedNumberMeta]: + # This function replaces the version in `pydantic.types`, in order to + # effect the registration of new constrained types so that Hypothesis + # can generate valid examples. + pydantic.types._DEFINED_TYPES.add(typ) + for supertype, resolver in RESOLVERS.items(): + if issubclass(typ, supertype): + st.register_type_strategy(typ, resolver(typ)) # type: ignore + return typ + raise NotImplementedError(f'Unknown type {typ!r} has no resolver to register') # pragma: no cover + + +def resolves( + typ: Union[type, pydantic.types.ConstrainedNumberMeta] +) -> Callable[[Callable[..., st.SearchStrategy]], Callable[..., st.SearchStrategy]]: # type: ignore[type-arg] + def inner(f): # type: ignore + assert f not in RESOLVERS + RESOLVERS[typ] = f + return f + + return inner + + +# Type-to-strategy resolver functions + + +@resolves(pydantic.JsonWrapper) +def resolve_json(cls): # type: ignore[no-untyped-def] + try: + inner = st.none() if cls.inner_type is None else st.from_type(cls.inner_type) + except Exception: # pragma: no cover + finite = st.floats(allow_infinity=False, allow_nan=False) + inner = st.recursive( + base=st.one_of(st.none(), st.booleans(), st.integers(), finite, st.text()), + extend=lambda x: st.lists(x) | st.dictionaries(st.text(), x), # type: ignore + ) + inner_type = getattr(cls, 'inner_type', None) + return st.builds( + cls.inner_type.json if lenient_issubclass(inner_type, pydantic.BaseModel) else json.dumps, + inner, + ensure_ascii=st.booleans(), + indent=st.none() | st.integers(0, 16), + sort_keys=st.booleans(), + ) + + +@resolves(pydantic.ConstrainedBytes) +def resolve_conbytes(cls): # type: ignore[no-untyped-def] # pragma: no cover + min_size = cls.min_length or 0 + max_size = cls.max_length + if not cls.strip_whitespace: + return st.binary(min_size=min_size, max_size=max_size) + # Fun with regex to ensure we neither start nor end with whitespace + repeats = '{{{},{}}}'.format( + min_size - 2 if min_size > 2 else 0, + max_size - 2 if (max_size or 0) > 2 else '', + ) + if min_size >= 2: + pattern = rf'\W.{repeats}\W' + elif min_size == 1: + pattern = rf'\W(.{repeats}\W)?' + else: + assert min_size == 0 + pattern = rf'(\W(.{repeats}\W)?)?' + return st.from_regex(pattern.encode(), fullmatch=True) + + +@resolves(pydantic.ConstrainedDecimal) +def resolve_condecimal(cls): # type: ignore[no-untyped-def] + min_value = cls.ge + max_value = cls.le + if cls.gt is not None: + assert min_value is None, 'Set `gt` or `ge`, but not both' + min_value = cls.gt + if cls.lt is not None: + assert max_value is None, 'Set `lt` or `le`, but not both' + max_value = cls.lt + s = st.decimals(min_value, max_value, allow_nan=False, places=cls.decimal_places) + if cls.lt is not None: + s = s.filter(lambda d: d < cls.lt) + if cls.gt is not None: + s = s.filter(lambda d: cls.gt < d) + return s + + +@resolves(pydantic.ConstrainedFloat) +def resolve_confloat(cls): # type: ignore[no-untyped-def] + min_value = cls.ge + max_value = cls.le + exclude_min = False + exclude_max = False + + if cls.gt is not None: + assert min_value is None, 'Set `gt` or `ge`, but not both' + min_value = cls.gt + exclude_min = True + if cls.lt is not None: + assert max_value is None, 'Set `lt` or `le`, but not both' + max_value = cls.lt + exclude_max = True + + if cls.multiple_of is None: + return st.floats(min_value, max_value, exclude_min=exclude_min, exclude_max=exclude_max, allow_nan=False) + + if min_value is not None: + min_value = math.ceil(min_value / cls.multiple_of) + if exclude_min: + min_value = min_value + 1 + if max_value is not None: + assert max_value >= cls.multiple_of, 'Cannot build model with max value smaller than multiple of' + max_value = math.floor(max_value / cls.multiple_of) + if exclude_max: + max_value = max_value - 1 + + return st.integers(min_value, max_value).map(lambda x: x * cls.multiple_of) + + +@resolves(pydantic.ConstrainedInt) +def resolve_conint(cls): # type: ignore[no-untyped-def] + min_value = cls.ge + max_value = cls.le + if cls.gt is not None: + assert min_value is None, 'Set `gt` or `ge`, but not both' + min_value = cls.gt + 1 + if cls.lt is not None: + assert max_value is None, 'Set `lt` or `le`, but not both' + max_value = cls.lt - 1 + + if cls.multiple_of is None or cls.multiple_of == 1: + return st.integers(min_value, max_value) + + # These adjustments and the .map handle integer-valued multiples, while the + # .filter handles trickier cases as for confloat. + if min_value is not None: + min_value = math.ceil(Fraction(min_value) / Fraction(cls.multiple_of)) + if max_value is not None: + max_value = math.floor(Fraction(max_value) / Fraction(cls.multiple_of)) + return st.integers(min_value, max_value).map(lambda x: x * cls.multiple_of) + + +@resolves(pydantic.ConstrainedDate) +def resolve_condate(cls): # type: ignore[no-untyped-def] + if cls.ge is not None: + assert cls.gt is None, 'Set `gt` or `ge`, but not both' + min_value = cls.ge + elif cls.gt is not None: + min_value = cls.gt + datetime.timedelta(days=1) + else: + min_value = datetime.date.min + if cls.le is not None: + assert cls.lt is None, 'Set `lt` or `le`, but not both' + max_value = cls.le + elif cls.lt is not None: + max_value = cls.lt - datetime.timedelta(days=1) + else: + max_value = datetime.date.max + return st.dates(min_value, max_value) + + +@resolves(pydantic.ConstrainedStr) +def resolve_constr(cls): # type: ignore[no-untyped-def] # pragma: no cover + min_size = cls.min_length or 0 + max_size = cls.max_length + + if cls.regex is None and not cls.strip_whitespace: + return st.text(min_size=min_size, max_size=max_size) + + if cls.regex is not None: + strategy = st.from_regex(cls.regex) + if cls.strip_whitespace: + strategy = strategy.filter(lambda s: s == s.strip()) + elif cls.strip_whitespace: + repeats = '{{{},{}}}'.format( + min_size - 2 if min_size > 2 else 0, + max_size - 2 if (max_size or 0) > 2 else '', + ) + if min_size >= 2: + strategy = st.from_regex(rf'\W.{repeats}\W') + elif min_size == 1: + strategy = st.from_regex(rf'\W(.{repeats}\W)?') + else: + assert min_size == 0 + strategy = st.from_regex(rf'(\W(.{repeats}\W)?)?') + + if min_size == 0 and max_size is None: + return strategy + elif max_size is None: + return strategy.filter(lambda s: min_size <= len(s)) + return strategy.filter(lambda s: min_size <= len(s) <= max_size) + + +# Finally, register all previously-defined types, and patch in our new function +for typ in list(pydantic.types._DEFINED_TYPES): + _registered(typ) +pydantic.types._registered = _registered +st.register_type_strategy(pydantic.Json, resolve_json) diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/annotated_types.py b/backend/.venv/Lib/site-packages/pydantic/v1/annotated_types.py new file mode 100644 index 0000000..d9eaaaf --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/annotated_types.py @@ -0,0 +1,72 @@ +import sys +from typing import TYPE_CHECKING, Any, Dict, FrozenSet, NamedTuple, Type + +from pydantic.v1.fields import Required +from pydantic.v1.main import BaseModel, create_model +from pydantic.v1.typing import is_typeddict, is_typeddict_special + +if TYPE_CHECKING: + from typing_extensions import TypedDict + +if sys.version_info < (3, 11): + + def is_legacy_typeddict(typeddict_cls: Type['TypedDict']) -> bool: # type: ignore[valid-type] + return is_typeddict(typeddict_cls) and type(typeddict_cls).__module__ == 'typing' + +else: + + def is_legacy_typeddict(_: Any) -> Any: + return False + + +def create_model_from_typeddict( + # Mypy bug: `Type[TypedDict]` is resolved as `Any` https://github.com/python/mypy/issues/11030 + typeddict_cls: Type['TypedDict'], # type: ignore[valid-type] + **kwargs: Any, +) -> Type['BaseModel']: + """ + Create a `BaseModel` based on the fields of a `TypedDict`. + Since `typing.TypedDict` in Python 3.8 does not store runtime information about optional keys, + we raise an error if this happens (see https://bugs.python.org/issue38834). + """ + field_definitions: Dict[str, Any] + + # Best case scenario: with python 3.9+ or when `TypedDict` is imported from `typing_extensions` + if not hasattr(typeddict_cls, '__required_keys__'): + raise TypeError( + 'You should use `typing_extensions.TypedDict` instead of `typing.TypedDict` with Python < 3.9.2. ' + 'Without it, there is no way to differentiate required and optional fields when subclassed.' + ) + + if is_legacy_typeddict(typeddict_cls) and any( + is_typeddict_special(t) for t in typeddict_cls.__annotations__.values() + ): + raise TypeError( + 'You should use `typing_extensions.TypedDict` instead of `typing.TypedDict` with Python < 3.11. ' + 'Without it, there is no way to reflect Required/NotRequired keys.' + ) + + required_keys: FrozenSet[str] = typeddict_cls.__required_keys__ # type: ignore[attr-defined] + field_definitions = { + field_name: (field_type, Required if field_name in required_keys else None) + for field_name, field_type in typeddict_cls.__annotations__.items() + } + + return create_model(typeddict_cls.__name__, **kwargs, **field_definitions) + + +def create_model_from_namedtuple(namedtuple_cls: Type['NamedTuple'], **kwargs: Any) -> Type['BaseModel']: + """ + Create a `BaseModel` based on the fields of a named tuple. + A named tuple can be created with `typing.NamedTuple` and declared annotations + but also with `collections.namedtuple`, in this case we consider all fields + to have type `Any`. + """ + # With python 3.10+, `__annotations__` always exists but can be empty hence the `getattr... or...` logic + namedtuple_annotations: Dict[str, Type[Any]] = getattr(namedtuple_cls, '__annotations__', None) or { + k: Any for k in namedtuple_cls._fields + } + field_definitions: Dict[str, Any] = { + field_name: (field_type, Required) for field_name, field_type in namedtuple_annotations.items() + } + return create_model(namedtuple_cls.__name__, **kwargs, **field_definitions) diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/class_validators.py b/backend/.venv/Lib/site-packages/pydantic/v1/class_validators.py new file mode 100644 index 0000000..2f68fc8 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/class_validators.py @@ -0,0 +1,361 @@ +import warnings +from collections import ChainMap +from functools import partial, partialmethod, wraps +from itertools import chain +from types import FunctionType +from typing import TYPE_CHECKING, Any, Callable, Dict, Iterable, List, Optional, Set, Tuple, Type, Union, overload + +from pydantic.v1.errors import ConfigError +from pydantic.v1.typing import AnyCallable +from pydantic.v1.utils import ROOT_KEY, in_ipython + +if TYPE_CHECKING: + from pydantic.v1.typing import AnyClassMethod + + +class Validator: + __slots__ = 'func', 'pre', 'each_item', 'always', 'check_fields', 'skip_on_failure' + + def __init__( + self, + func: AnyCallable, + pre: bool = False, + each_item: bool = False, + always: bool = False, + check_fields: bool = False, + skip_on_failure: bool = False, + ): + self.func = func + self.pre = pre + self.each_item = each_item + self.always = always + self.check_fields = check_fields + self.skip_on_failure = skip_on_failure + + +if TYPE_CHECKING: + from inspect import Signature + + from pydantic.v1.config import BaseConfig + from pydantic.v1.fields import ModelField + from pydantic.v1.types import ModelOrDc + + ValidatorCallable = Callable[[Optional[ModelOrDc], Any, Dict[str, Any], ModelField, Type[BaseConfig]], Any] + ValidatorsList = List[ValidatorCallable] + ValidatorListDict = Dict[str, List[Validator]] + +_FUNCS: Set[str] = set() +VALIDATOR_CONFIG_KEY = '__validator_config__' +ROOT_VALIDATOR_CONFIG_KEY = '__root_validator_config__' + + +def validator( + *fields: str, + pre: bool = False, + each_item: bool = False, + always: bool = False, + check_fields: bool = True, + whole: Optional[bool] = None, + allow_reuse: bool = False, +) -> Callable[[AnyCallable], 'AnyClassMethod']: + """ + Decorate methods on the class indicating that they should be used to validate fields + :param fields: which field(s) the method should be called on + :param pre: whether or not this validator should be called before the standard validators (else after) + :param each_item: for complex objects (sets, lists etc.) whether to validate individual elements rather than the + whole object + :param always: whether this method and other validators should be called even if the value is missing + :param check_fields: whether to check that the fields actually exist on the model + :param allow_reuse: whether to track and raise an error if another validator refers to the decorated function + """ + if not fields: + raise ConfigError('validator with no fields specified') + elif isinstance(fields[0], FunctionType): + raise ConfigError( + "validators should be used with fields and keyword arguments, not bare. " # noqa: Q000 + "E.g. usage should be `@validator('', ...)`" + ) + elif not all(isinstance(field, str) for field in fields): + raise ConfigError( + "validator fields should be passed as separate string args. " # noqa: Q000 + "E.g. usage should be `@validator('', '', ...)`" + ) + + if whole is not None: + warnings.warn( + 'The "whole" keyword argument is deprecated, use "each_item" (inverse meaning, default False) instead', + DeprecationWarning, + ) + assert each_item is False, '"each_item" and "whole" conflict, remove "whole"' + each_item = not whole + + def dec(f: AnyCallable) -> 'AnyClassMethod': + f_cls = _prepare_validator(f, allow_reuse) + setattr( + f_cls, + VALIDATOR_CONFIG_KEY, + ( + fields, + Validator(func=f_cls.__func__, pre=pre, each_item=each_item, always=always, check_fields=check_fields), + ), + ) + return f_cls + + return dec + + +@overload +def root_validator(_func: AnyCallable) -> 'AnyClassMethod': + ... + + +@overload +def root_validator( + *, pre: bool = False, allow_reuse: bool = False, skip_on_failure: bool = False +) -> Callable[[AnyCallable], 'AnyClassMethod']: + ... + + +def root_validator( + _func: Optional[AnyCallable] = None, *, pre: bool = False, allow_reuse: bool = False, skip_on_failure: bool = False +) -> Union['AnyClassMethod', Callable[[AnyCallable], 'AnyClassMethod']]: + """ + Decorate methods on a model indicating that they should be used to validate (and perhaps modify) data either + before or after standard model parsing/validation is performed. + """ + if _func: + f_cls = _prepare_validator(_func, allow_reuse) + setattr( + f_cls, ROOT_VALIDATOR_CONFIG_KEY, Validator(func=f_cls.__func__, pre=pre, skip_on_failure=skip_on_failure) + ) + return f_cls + + def dec(f: AnyCallable) -> 'AnyClassMethod': + f_cls = _prepare_validator(f, allow_reuse) + setattr( + f_cls, ROOT_VALIDATOR_CONFIG_KEY, Validator(func=f_cls.__func__, pre=pre, skip_on_failure=skip_on_failure) + ) + return f_cls + + return dec + + +def _prepare_validator(function: AnyCallable, allow_reuse: bool) -> 'AnyClassMethod': + """ + Avoid validators with duplicated names since without this, validators can be overwritten silently + which generally isn't the intended behaviour, don't run in ipython (see #312) or if allow_reuse is False. + """ + f_cls = function if isinstance(function, classmethod) else classmethod(function) + if not in_ipython() and not allow_reuse: + ref = ( + getattr(f_cls.__func__, '__module__', '') + + '.' + + getattr(f_cls.__func__, '__qualname__', f'') + ) + if ref in _FUNCS: + raise ConfigError(f'duplicate validator function "{ref}"; if this is intended, set `allow_reuse=True`') + _FUNCS.add(ref) + return f_cls + + +class ValidatorGroup: + def __init__(self, validators: 'ValidatorListDict') -> None: + self.validators = validators + self.used_validators = {'*'} + + def get_validators(self, name: str) -> Optional[Dict[str, Validator]]: + self.used_validators.add(name) + validators = self.validators.get(name, []) + if name != ROOT_KEY: + validators += self.validators.get('*', []) + if validators: + return {getattr(v.func, '__name__', f''): v for v in validators} + else: + return None + + def check_for_unused(self) -> None: + unused_validators = set( + chain.from_iterable( + ( + getattr(v.func, '__name__', f'') + for v in self.validators[f] + if v.check_fields + ) + for f in (self.validators.keys() - self.used_validators) + ) + ) + if unused_validators: + fn = ', '.join(unused_validators) + raise ConfigError( + f"Validators defined with incorrect fields: {fn} " # noqa: Q000 + f"(use check_fields=False if you're inheriting from the model and intended this)" + ) + + +def extract_validators(namespace: Dict[str, Any]) -> Dict[str, List[Validator]]: + validators: Dict[str, List[Validator]] = {} + for var_name, value in namespace.items(): + validator_config = getattr(value, VALIDATOR_CONFIG_KEY, None) + if validator_config: + fields, v = validator_config + for field in fields: + if field in validators: + validators[field].append(v) + else: + validators[field] = [v] + return validators + + +def extract_root_validators(namespace: Dict[str, Any]) -> Tuple[List[AnyCallable], List[Tuple[bool, AnyCallable]]]: + from inspect import signature + + pre_validators: List[AnyCallable] = [] + post_validators: List[Tuple[bool, AnyCallable]] = [] + for name, value in namespace.items(): + validator_config: Optional[Validator] = getattr(value, ROOT_VALIDATOR_CONFIG_KEY, None) + if validator_config: + sig = signature(validator_config.func) + args = list(sig.parameters.keys()) + if args[0] == 'self': + raise ConfigError( + f'Invalid signature for root validator {name}: {sig}, "self" not permitted as first argument, ' + f'should be: (cls, values).' + ) + if len(args) != 2: + raise ConfigError(f'Invalid signature for root validator {name}: {sig}, should be: (cls, values).') + # check function signature + if validator_config.pre: + pre_validators.append(validator_config.func) + else: + post_validators.append((validator_config.skip_on_failure, validator_config.func)) + return pre_validators, post_validators + + +def inherit_validators(base_validators: 'ValidatorListDict', validators: 'ValidatorListDict') -> 'ValidatorListDict': + for field, field_validators in base_validators.items(): + if field not in validators: + validators[field] = [] + validators[field] += field_validators + return validators + + +def make_generic_validator(validator: AnyCallable) -> 'ValidatorCallable': + """ + Make a generic function which calls a validator with the right arguments. + + Unfortunately other approaches (eg. return a partial of a function that builds the arguments) is slow, + hence this laborious way of doing things. + + It's done like this so validators don't all need **kwargs in their signature, eg. any combination of + the arguments "values", "fields" and/or "config" are permitted. + """ + from inspect import signature + + if not isinstance(validator, (partial, partialmethod)): + # This should be the default case, so overhead is reduced + sig = signature(validator) + args = list(sig.parameters.keys()) + else: + # Fix the generated argument lists of partial methods + sig = signature(validator.func) + args = [ + k + for k in signature(validator.func).parameters.keys() + if k not in validator.args | validator.keywords.keys() + ] + + first_arg = args.pop(0) + if first_arg == 'self': + raise ConfigError( + f'Invalid signature for validator {validator}: {sig}, "self" not permitted as first argument, ' + f'should be: (cls, value, values, config, field), "values", "config" and "field" are all optional.' + ) + elif first_arg == 'cls': + # assume the second argument is value + return wraps(validator)(_generic_validator_cls(validator, sig, set(args[1:]))) + else: + # assume the first argument was value which has already been removed + return wraps(validator)(_generic_validator_basic(validator, sig, set(args))) + + +def prep_validators(v_funcs: Iterable[AnyCallable]) -> 'ValidatorsList': + return [make_generic_validator(f) for f in v_funcs if f] + + +all_kwargs = {'values', 'field', 'config'} + + +def _generic_validator_cls(validator: AnyCallable, sig: 'Signature', args: Set[str]) -> 'ValidatorCallable': + # assume the first argument is value + has_kwargs = False + if 'kwargs' in args: + has_kwargs = True + args -= {'kwargs'} + + if not args.issubset(all_kwargs): + raise ConfigError( + f'Invalid signature for validator {validator}: {sig}, should be: ' + f'(cls, value, values, config, field), "values", "config" and "field" are all optional.' + ) + + if has_kwargs: + return lambda cls, v, values, field, config: validator(cls, v, values=values, field=field, config=config) + elif args == set(): + return lambda cls, v, values, field, config: validator(cls, v) + elif args == {'values'}: + return lambda cls, v, values, field, config: validator(cls, v, values=values) + elif args == {'field'}: + return lambda cls, v, values, field, config: validator(cls, v, field=field) + elif args == {'config'}: + return lambda cls, v, values, field, config: validator(cls, v, config=config) + elif args == {'values', 'field'}: + return lambda cls, v, values, field, config: validator(cls, v, values=values, field=field) + elif args == {'values', 'config'}: + return lambda cls, v, values, field, config: validator(cls, v, values=values, config=config) + elif args == {'field', 'config'}: + return lambda cls, v, values, field, config: validator(cls, v, field=field, config=config) + else: + # args == {'values', 'field', 'config'} + return lambda cls, v, values, field, config: validator(cls, v, values=values, field=field, config=config) + + +def _generic_validator_basic(validator: AnyCallable, sig: 'Signature', args: Set[str]) -> 'ValidatorCallable': + has_kwargs = False + if 'kwargs' in args: + has_kwargs = True + args -= {'kwargs'} + + if not args.issubset(all_kwargs): + raise ConfigError( + f'Invalid signature for validator {validator}: {sig}, should be: ' + f'(value, values, config, field), "values", "config" and "field" are all optional.' + ) + + if has_kwargs: + return lambda cls, v, values, field, config: validator(v, values=values, field=field, config=config) + elif args == set(): + return lambda cls, v, values, field, config: validator(v) + elif args == {'values'}: + return lambda cls, v, values, field, config: validator(v, values=values) + elif args == {'field'}: + return lambda cls, v, values, field, config: validator(v, field=field) + elif args == {'config'}: + return lambda cls, v, values, field, config: validator(v, config=config) + elif args == {'values', 'field'}: + return lambda cls, v, values, field, config: validator(v, values=values, field=field) + elif args == {'values', 'config'}: + return lambda cls, v, values, field, config: validator(v, values=values, config=config) + elif args == {'field', 'config'}: + return lambda cls, v, values, field, config: validator(v, field=field, config=config) + else: + # args == {'values', 'field', 'config'} + return lambda cls, v, values, field, config: validator(v, values=values, field=field, config=config) + + +def gather_all_validators(type_: 'ModelOrDc') -> Dict[str, 'AnyClassMethod']: + all_attributes = ChainMap(*[cls.__dict__ for cls in type_.__mro__]) # type: ignore[arg-type,var-annotated] + return { + k: v + for k, v in all_attributes.items() + if hasattr(v, VALIDATOR_CONFIG_KEY) or hasattr(v, ROOT_VALIDATOR_CONFIG_KEY) + } diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/color.py b/backend/.venv/Lib/site-packages/pydantic/v1/color.py new file mode 100644 index 0000000..b0bbf78 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/color.py @@ -0,0 +1,494 @@ +""" +Color definitions are used as per CSS3 specification: +http://www.w3.org/TR/css3-color/#svg-color + +A few colors have multiple names referring to the sames colors, eg. `grey` and `gray` or `aqua` and `cyan`. + +In these cases the LAST color when sorted alphabetically takes preferences, +eg. Color((0, 255, 255)).as_named() == 'cyan' because "cyan" comes after "aqua". +""" +import math +import re +from colorsys import hls_to_rgb, rgb_to_hls +from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, Union, cast + +from pydantic.v1.errors import ColorError +from pydantic.v1.utils import Representation, almost_equal_floats + +if TYPE_CHECKING: + from pydantic.v1.typing import CallableGenerator, ReprArgs + +ColorTuple = Union[Tuple[int, int, int], Tuple[int, int, int, float]] +ColorType = Union[ColorTuple, str] +HslColorTuple = Union[Tuple[float, float, float], Tuple[float, float, float, float]] + + +class RGBA: + """ + Internal use only as a representation of a color. + """ + + __slots__ = 'r', 'g', 'b', 'alpha', '_tuple' + + def __init__(self, r: float, g: float, b: float, alpha: Optional[float]): + self.r = r + self.g = g + self.b = b + self.alpha = alpha + + self._tuple: Tuple[float, float, float, Optional[float]] = (r, g, b, alpha) + + def __getitem__(self, item: Any) -> Any: + return self._tuple[item] + + +# these are not compiled here to avoid import slowdown, they'll be compiled the first time they're used, then cached +r_hex_short = r'\s*(?:#|0x)?([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])?\s*' +r_hex_long = r'\s*(?:#|0x)?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})?\s*' +_r_255 = r'(\d{1,3}(?:\.\d+)?)' +_r_comma = r'\s*,\s*' +r_rgb = fr'\s*rgb\(\s*{_r_255}{_r_comma}{_r_255}{_r_comma}{_r_255}\)\s*' +_r_alpha = r'(\d(?:\.\d+)?|\.\d+|\d{1,2}%)' +r_rgba = fr'\s*rgba\(\s*{_r_255}{_r_comma}{_r_255}{_r_comma}{_r_255}{_r_comma}{_r_alpha}\s*\)\s*' +_r_h = r'(-?\d+(?:\.\d+)?|-?\.\d+)(deg|rad|turn)?' +_r_sl = r'(\d{1,3}(?:\.\d+)?)%' +r_hsl = fr'\s*hsl\(\s*{_r_h}{_r_comma}{_r_sl}{_r_comma}{_r_sl}\s*\)\s*' +r_hsla = fr'\s*hsl\(\s*{_r_h}{_r_comma}{_r_sl}{_r_comma}{_r_sl}{_r_comma}{_r_alpha}\s*\)\s*' + +# colors where the two hex characters are the same, if all colors match this the short version of hex colors can be used +repeat_colors = {int(c * 2, 16) for c in '0123456789abcdef'} +rads = 2 * math.pi + + +class Color(Representation): + __slots__ = '_original', '_rgba' + + def __init__(self, value: ColorType) -> None: + self._rgba: RGBA + self._original: ColorType + if isinstance(value, (tuple, list)): + self._rgba = parse_tuple(value) + elif isinstance(value, str): + self._rgba = parse_str(value) + elif isinstance(value, Color): + self._rgba = value._rgba + value = value._original + else: + raise ColorError(reason='value must be a tuple, list or string') + + # if we've got here value must be a valid color + self._original = value + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update(type='string', format='color') + + def original(self) -> ColorType: + """ + Original value passed to Color + """ + return self._original + + def as_named(self, *, fallback: bool = False) -> str: + if self._rgba.alpha is None: + rgb = cast(Tuple[int, int, int], self.as_rgb_tuple()) + try: + return COLORS_BY_VALUE[rgb] + except KeyError as e: + if fallback: + return self.as_hex() + else: + raise ValueError('no named color found, use fallback=True, as_hex() or as_rgb()') from e + else: + return self.as_hex() + + def as_hex(self) -> str: + """ + Hex string representing the color can be 3, 4, 6 or 8 characters depending on whether the string + a "short" representation of the color is possible and whether there's an alpha channel. + """ + values = [float_to_255(c) for c in self._rgba[:3]] + if self._rgba.alpha is not None: + values.append(float_to_255(self._rgba.alpha)) + + as_hex = ''.join(f'{v:02x}' for v in values) + if all(c in repeat_colors for c in values): + as_hex = ''.join(as_hex[c] for c in range(0, len(as_hex), 2)) + return '#' + as_hex + + def as_rgb(self) -> str: + """ + Color as an rgb(, , ) or rgba(, , , ) string. + """ + if self._rgba.alpha is None: + return f'rgb({float_to_255(self._rgba.r)}, {float_to_255(self._rgba.g)}, {float_to_255(self._rgba.b)})' + else: + return ( + f'rgba({float_to_255(self._rgba.r)}, {float_to_255(self._rgba.g)}, {float_to_255(self._rgba.b)}, ' + f'{round(self._alpha_float(), 2)})' + ) + + def as_rgb_tuple(self, *, alpha: Optional[bool] = None) -> ColorTuple: + """ + Color as an RGB or RGBA tuple; red, green and blue are in the range 0 to 255, alpha if included is + in the range 0 to 1. + + :param alpha: whether to include the alpha channel, options are + None - (default) include alpha only if it's set (e.g. not None) + True - always include alpha, + False - always omit alpha, + """ + r, g, b = (float_to_255(c) for c in self._rgba[:3]) + if alpha is None: + if self._rgba.alpha is None: + return r, g, b + else: + return r, g, b, self._alpha_float() + elif alpha: + return r, g, b, self._alpha_float() + else: + # alpha is False + return r, g, b + + def as_hsl(self) -> str: + """ + Color as an hsl(, , ) or hsl(, , , ) string. + """ + if self._rgba.alpha is None: + h, s, li = self.as_hsl_tuple(alpha=False) # type: ignore + return f'hsl({h * 360:0.0f}, {s:0.0%}, {li:0.0%})' + else: + h, s, li, a = self.as_hsl_tuple(alpha=True) # type: ignore + return f'hsl({h * 360:0.0f}, {s:0.0%}, {li:0.0%}, {round(a, 2)})' + + def as_hsl_tuple(self, *, alpha: Optional[bool] = None) -> HslColorTuple: + """ + Color as an HSL or HSLA tuple, e.g. hue, saturation, lightness and optionally alpha; all elements are in + the range 0 to 1. + + NOTE: this is HSL as used in HTML and most other places, not HLS as used in python's colorsys. + + :param alpha: whether to include the alpha channel, options are + None - (default) include alpha only if it's set (e.g. not None) + True - always include alpha, + False - always omit alpha, + """ + h, l, s = rgb_to_hls(self._rgba.r, self._rgba.g, self._rgba.b) + if alpha is None: + if self._rgba.alpha is None: + return h, s, l + else: + return h, s, l, self._alpha_float() + if alpha: + return h, s, l, self._alpha_float() + else: + # alpha is False + return h, s, l + + def _alpha_float(self) -> float: + return 1 if self._rgba.alpha is None else self._rgba.alpha + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls + + def __str__(self) -> str: + return self.as_named(fallback=True) + + def __repr_args__(self) -> 'ReprArgs': + return [(None, self.as_named(fallback=True))] + [('rgb', self.as_rgb_tuple())] # type: ignore + + def __eq__(self, other: Any) -> bool: + return isinstance(other, Color) and self.as_rgb_tuple() == other.as_rgb_tuple() + + def __hash__(self) -> int: + return hash(self.as_rgb_tuple()) + + +def parse_tuple(value: Tuple[Any, ...]) -> RGBA: + """ + Parse a tuple or list as a color. + """ + if len(value) == 3: + r, g, b = (parse_color_value(v) for v in value) + return RGBA(r, g, b, None) + elif len(value) == 4: + r, g, b = (parse_color_value(v) for v in value[:3]) + return RGBA(r, g, b, parse_float_alpha(value[3])) + else: + raise ColorError(reason='tuples must have length 3 or 4') + + +def parse_str(value: str) -> RGBA: + """ + Parse a string to an RGBA tuple, trying the following formats (in this order): + * named color, see COLORS_BY_NAME below + * hex short eg. `fff` (prefix can be `#`, `0x` or nothing) + * hex long eg. `ffffff` (prefix can be `#`, `0x` or nothing) + * `rgb(, , ) ` + * `rgba(, , , )` + """ + value_lower = value.lower() + try: + r, g, b = COLORS_BY_NAME[value_lower] + except KeyError: + pass + else: + return ints_to_rgba(r, g, b, None) + + m = re.fullmatch(r_hex_short, value_lower) + if m: + *rgb, a = m.groups() + r, g, b = (int(v * 2, 16) for v in rgb) + if a: + alpha: Optional[float] = int(a * 2, 16) / 255 + else: + alpha = None + return ints_to_rgba(r, g, b, alpha) + + m = re.fullmatch(r_hex_long, value_lower) + if m: + *rgb, a = m.groups() + r, g, b = (int(v, 16) for v in rgb) + if a: + alpha = int(a, 16) / 255 + else: + alpha = None + return ints_to_rgba(r, g, b, alpha) + + m = re.fullmatch(r_rgb, value_lower) + if m: + return ints_to_rgba(*m.groups(), None) # type: ignore + + m = re.fullmatch(r_rgba, value_lower) + if m: + return ints_to_rgba(*m.groups()) # type: ignore + + m = re.fullmatch(r_hsl, value_lower) + if m: + h, h_units, s, l_ = m.groups() + return parse_hsl(h, h_units, s, l_) + + m = re.fullmatch(r_hsla, value_lower) + if m: + h, h_units, s, l_, a = m.groups() + return parse_hsl(h, h_units, s, l_, parse_float_alpha(a)) + + raise ColorError(reason='string not recognised as a valid color') + + +def ints_to_rgba(r: Union[int, str], g: Union[int, str], b: Union[int, str], alpha: Optional[float]) -> RGBA: + return RGBA(parse_color_value(r), parse_color_value(g), parse_color_value(b), parse_float_alpha(alpha)) + + +def parse_color_value(value: Union[int, str], max_val: int = 255) -> float: + """ + Parse a value checking it's a valid int in the range 0 to max_val and divide by max_val to give a number + in the range 0 to 1 + """ + try: + color = float(value) + except ValueError: + raise ColorError(reason='color values must be a valid number') + if 0 <= color <= max_val: + return color / max_val + else: + raise ColorError(reason=f'color values must be in the range 0 to {max_val}') + + +def parse_float_alpha(value: Union[None, str, float, int]) -> Optional[float]: + """ + Parse a value checking it's a valid float in the range 0 to 1 + """ + if value is None: + return None + try: + if isinstance(value, str) and value.endswith('%'): + alpha = float(value[:-1]) / 100 + else: + alpha = float(value) + except ValueError: + raise ColorError(reason='alpha values must be a valid float') + + if almost_equal_floats(alpha, 1): + return None + elif 0 <= alpha <= 1: + return alpha + else: + raise ColorError(reason='alpha values must be in the range 0 to 1') + + +def parse_hsl(h: str, h_units: str, sat: str, light: str, alpha: Optional[float] = None) -> RGBA: + """ + Parse raw hue, saturation, lightness and alpha values and convert to RGBA. + """ + s_value, l_value = parse_color_value(sat, 100), parse_color_value(light, 100) + + h_value = float(h) + if h_units in {None, 'deg'}: + h_value = h_value % 360 / 360 + elif h_units == 'rad': + h_value = h_value % rads / rads + else: + # turns + h_value = h_value % 1 + + r, g, b = hls_to_rgb(h_value, l_value, s_value) + return RGBA(r, g, b, alpha) + + +def float_to_255(c: float) -> int: + return int(round(c * 255)) + + +COLORS_BY_NAME = { + 'aliceblue': (240, 248, 255), + 'antiquewhite': (250, 235, 215), + 'aqua': (0, 255, 255), + 'aquamarine': (127, 255, 212), + 'azure': (240, 255, 255), + 'beige': (245, 245, 220), + 'bisque': (255, 228, 196), + 'black': (0, 0, 0), + 'blanchedalmond': (255, 235, 205), + 'blue': (0, 0, 255), + 'blueviolet': (138, 43, 226), + 'brown': (165, 42, 42), + 'burlywood': (222, 184, 135), + 'cadetblue': (95, 158, 160), + 'chartreuse': (127, 255, 0), + 'chocolate': (210, 105, 30), + 'coral': (255, 127, 80), + 'cornflowerblue': (100, 149, 237), + 'cornsilk': (255, 248, 220), + 'crimson': (220, 20, 60), + 'cyan': (0, 255, 255), + 'darkblue': (0, 0, 139), + 'darkcyan': (0, 139, 139), + 'darkgoldenrod': (184, 134, 11), + 'darkgray': (169, 169, 169), + 'darkgreen': (0, 100, 0), + 'darkgrey': (169, 169, 169), + 'darkkhaki': (189, 183, 107), + 'darkmagenta': (139, 0, 139), + 'darkolivegreen': (85, 107, 47), + 'darkorange': (255, 140, 0), + 'darkorchid': (153, 50, 204), + 'darkred': (139, 0, 0), + 'darksalmon': (233, 150, 122), + 'darkseagreen': (143, 188, 143), + 'darkslateblue': (72, 61, 139), + 'darkslategray': (47, 79, 79), + 'darkslategrey': (47, 79, 79), + 'darkturquoise': (0, 206, 209), + 'darkviolet': (148, 0, 211), + 'deeppink': (255, 20, 147), + 'deepskyblue': (0, 191, 255), + 'dimgray': (105, 105, 105), + 'dimgrey': (105, 105, 105), + 'dodgerblue': (30, 144, 255), + 'firebrick': (178, 34, 34), + 'floralwhite': (255, 250, 240), + 'forestgreen': (34, 139, 34), + 'fuchsia': (255, 0, 255), + 'gainsboro': (220, 220, 220), + 'ghostwhite': (248, 248, 255), + 'gold': (255, 215, 0), + 'goldenrod': (218, 165, 32), + 'gray': (128, 128, 128), + 'green': (0, 128, 0), + 'greenyellow': (173, 255, 47), + 'grey': (128, 128, 128), + 'honeydew': (240, 255, 240), + 'hotpink': (255, 105, 180), + 'indianred': (205, 92, 92), + 'indigo': (75, 0, 130), + 'ivory': (255, 255, 240), + 'khaki': (240, 230, 140), + 'lavender': (230, 230, 250), + 'lavenderblush': (255, 240, 245), + 'lawngreen': (124, 252, 0), + 'lemonchiffon': (255, 250, 205), + 'lightblue': (173, 216, 230), + 'lightcoral': (240, 128, 128), + 'lightcyan': (224, 255, 255), + 'lightgoldenrodyellow': (250, 250, 210), + 'lightgray': (211, 211, 211), + 'lightgreen': (144, 238, 144), + 'lightgrey': (211, 211, 211), + 'lightpink': (255, 182, 193), + 'lightsalmon': (255, 160, 122), + 'lightseagreen': (32, 178, 170), + 'lightskyblue': (135, 206, 250), + 'lightslategray': (119, 136, 153), + 'lightslategrey': (119, 136, 153), + 'lightsteelblue': (176, 196, 222), + 'lightyellow': (255, 255, 224), + 'lime': (0, 255, 0), + 'limegreen': (50, 205, 50), + 'linen': (250, 240, 230), + 'magenta': (255, 0, 255), + 'maroon': (128, 0, 0), + 'mediumaquamarine': (102, 205, 170), + 'mediumblue': (0, 0, 205), + 'mediumorchid': (186, 85, 211), + 'mediumpurple': (147, 112, 219), + 'mediumseagreen': (60, 179, 113), + 'mediumslateblue': (123, 104, 238), + 'mediumspringgreen': (0, 250, 154), + 'mediumturquoise': (72, 209, 204), + 'mediumvioletred': (199, 21, 133), + 'midnightblue': (25, 25, 112), + 'mintcream': (245, 255, 250), + 'mistyrose': (255, 228, 225), + 'moccasin': (255, 228, 181), + 'navajowhite': (255, 222, 173), + 'navy': (0, 0, 128), + 'oldlace': (253, 245, 230), + 'olive': (128, 128, 0), + 'olivedrab': (107, 142, 35), + 'orange': (255, 165, 0), + 'orangered': (255, 69, 0), + 'orchid': (218, 112, 214), + 'palegoldenrod': (238, 232, 170), + 'palegreen': (152, 251, 152), + 'paleturquoise': (175, 238, 238), + 'palevioletred': (219, 112, 147), + 'papayawhip': (255, 239, 213), + 'peachpuff': (255, 218, 185), + 'peru': (205, 133, 63), + 'pink': (255, 192, 203), + 'plum': (221, 160, 221), + 'powderblue': (176, 224, 230), + 'purple': (128, 0, 128), + 'red': (255, 0, 0), + 'rosybrown': (188, 143, 143), + 'royalblue': (65, 105, 225), + 'saddlebrown': (139, 69, 19), + 'salmon': (250, 128, 114), + 'sandybrown': (244, 164, 96), + 'seagreen': (46, 139, 87), + 'seashell': (255, 245, 238), + 'sienna': (160, 82, 45), + 'silver': (192, 192, 192), + 'skyblue': (135, 206, 235), + 'slateblue': (106, 90, 205), + 'slategray': (112, 128, 144), + 'slategrey': (112, 128, 144), + 'snow': (255, 250, 250), + 'springgreen': (0, 255, 127), + 'steelblue': (70, 130, 180), + 'tan': (210, 180, 140), + 'teal': (0, 128, 128), + 'thistle': (216, 191, 216), + 'tomato': (255, 99, 71), + 'turquoise': (64, 224, 208), + 'violet': (238, 130, 238), + 'wheat': (245, 222, 179), + 'white': (255, 255, 255), + 'whitesmoke': (245, 245, 245), + 'yellow': (255, 255, 0), + 'yellowgreen': (154, 205, 50), +} + +COLORS_BY_VALUE = {v: k for k, v in COLORS_BY_NAME.items()} diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/config.py b/backend/.venv/Lib/site-packages/pydantic/v1/config.py new file mode 100644 index 0000000..18f7c99 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/config.py @@ -0,0 +1,191 @@ +import json +from enum import Enum +from typing import TYPE_CHECKING, Any, Callable, Dict, ForwardRef, Optional, Tuple, Type, Union + +from typing_extensions import Literal, Protocol + +from pydantic.v1.typing import AnyArgTCallable, AnyCallable +from pydantic.v1.utils import GetterDict +from pydantic.v1.version import compiled + +if TYPE_CHECKING: + from typing import overload + + from pydantic.v1.fields import ModelField + from pydantic.v1.main import BaseModel + + ConfigType = Type['BaseConfig'] + + class SchemaExtraCallable(Protocol): + @overload + def __call__(self, schema: Dict[str, Any]) -> None: + pass + + @overload + def __call__(self, schema: Dict[str, Any], model_class: Type[BaseModel]) -> None: + pass + +else: + SchemaExtraCallable = Callable[..., None] + +__all__ = 'BaseConfig', 'ConfigDict', 'get_config', 'Extra', 'inherit_config', 'prepare_config' + + +class Extra(str, Enum): + allow = 'allow' + ignore = 'ignore' + forbid = 'forbid' + + +# https://github.com/cython/cython/issues/4003 +# Fixed in Cython 3 and Pydantic v1 won't support Cython 3. +# Pydantic v2 doesn't depend on Cython at all. +if not compiled: + from typing_extensions import TypedDict + + class ConfigDict(TypedDict, total=False): + title: Optional[str] + anystr_lower: bool + anystr_strip_whitespace: bool + min_anystr_length: int + max_anystr_length: Optional[int] + validate_all: bool + extra: Extra + allow_mutation: bool + frozen: bool + allow_population_by_field_name: bool + use_enum_values: bool + fields: Dict[str, Union[str, Dict[str, str]]] + validate_assignment: bool + error_msg_templates: Dict[str, str] + arbitrary_types_allowed: bool + orm_mode: bool + getter_dict: Type[GetterDict] + alias_generator: Optional[Callable[[str], str]] + keep_untouched: Tuple[type, ...] + schema_extra: Union[Dict[str, object], 'SchemaExtraCallable'] + json_loads: Callable[[str], object] + json_dumps: AnyArgTCallable[str] + json_encoders: Dict[Type[object], AnyCallable] + underscore_attrs_are_private: bool + allow_inf_nan: bool + copy_on_model_validation: Literal['none', 'deep', 'shallow'] + # whether dataclass `__post_init__` should be run after validation + post_init_call: Literal['before_validation', 'after_validation'] + +else: + ConfigDict = dict # type: ignore + + +class BaseConfig: + title: Optional[str] = None + anystr_lower: bool = False + anystr_upper: bool = False + anystr_strip_whitespace: bool = False + min_anystr_length: int = 0 + max_anystr_length: Optional[int] = None + validate_all: bool = False + extra: Extra = Extra.ignore + allow_mutation: bool = True + frozen: bool = False + allow_population_by_field_name: bool = False + use_enum_values: bool = False + fields: Dict[str, Union[str, Dict[str, str]]] = {} + validate_assignment: bool = False + error_msg_templates: Dict[str, str] = {} + arbitrary_types_allowed: bool = False + orm_mode: bool = False + getter_dict: Type[GetterDict] = GetterDict + alias_generator: Optional[Callable[[str], str]] = None + keep_untouched: Tuple[type, ...] = () + schema_extra: Union[Dict[str, Any], 'SchemaExtraCallable'] = {} + json_loads: Callable[[str], Any] = json.loads + json_dumps: Callable[..., str] = json.dumps + json_encoders: Dict[Union[Type[Any], str, ForwardRef], AnyCallable] = {} + underscore_attrs_are_private: bool = False + allow_inf_nan: bool = True + + # whether inherited models as fields should be reconstructed as base model, + # and whether such a copy should be shallow or deep + copy_on_model_validation: Literal['none', 'deep', 'shallow'] = 'shallow' + + # whether `Union` should check all allowed types before even trying to coerce + smart_union: bool = False + # whether dataclass `__post_init__` should be run before or after validation + post_init_call: Literal['before_validation', 'after_validation'] = 'before_validation' + + @classmethod + def get_field_info(cls, name: str) -> Dict[str, Any]: + """ + Get properties of FieldInfo from the `fields` property of the config class. + """ + + fields_value = cls.fields.get(name) + + if isinstance(fields_value, str): + field_info: Dict[str, Any] = {'alias': fields_value} + elif isinstance(fields_value, dict): + field_info = fields_value + else: + field_info = {} + + if 'alias' in field_info: + field_info.setdefault('alias_priority', 2) + + if field_info.get('alias_priority', 0) <= 1 and cls.alias_generator: + alias = cls.alias_generator(name) + if not isinstance(alias, str): + raise TypeError(f'Config.alias_generator must return str, not {alias.__class__}') + field_info.update(alias=alias, alias_priority=1) + return field_info + + @classmethod + def prepare_field(cls, field: 'ModelField') -> None: + """ + Optional hook to check or modify fields during model creation. + """ + pass + + +def get_config(config: Union[ConfigDict, Type[object], None]) -> Type[BaseConfig]: + if config is None: + return BaseConfig + + else: + config_dict = ( + config + if isinstance(config, dict) + else {k: getattr(config, k) for k in dir(config) if not k.startswith('__')} + ) + + class Config(BaseConfig): + ... + + for k, v in config_dict.items(): + setattr(Config, k, v) + return Config + + +def inherit_config(self_config: 'ConfigType', parent_config: 'ConfigType', **namespace: Any) -> 'ConfigType': + if not self_config: + base_classes: Tuple['ConfigType', ...] = (parent_config,) + elif self_config == parent_config: + base_classes = (self_config,) + else: + base_classes = self_config, parent_config + + namespace['json_encoders'] = { + **getattr(parent_config, 'json_encoders', {}), + **getattr(self_config, 'json_encoders', {}), + **namespace.get('json_encoders', {}), + } + + return type('Config', base_classes, namespace) + + +def prepare_config(config: Type[BaseConfig], cls_name: str) -> None: + if not isinstance(config.extra, Extra): + try: + config.extra = Extra(config.extra) + except ValueError: + raise ValueError(f'"{cls_name}": {config.extra} is not a valid value for "extra"') diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/dataclasses.py b/backend/.venv/Lib/site-packages/pydantic/v1/dataclasses.py new file mode 100644 index 0000000..bd16702 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/dataclasses.py @@ -0,0 +1,500 @@ +""" +The main purpose is to enhance stdlib dataclasses by adding validation +A pydantic dataclass can be generated from scratch or from a stdlib one. + +Behind the scene, a pydantic dataclass is just like a regular one on which we attach +a `BaseModel` and magic methods to trigger the validation of the data. +`__init__` and `__post_init__` are hence overridden and have extra logic to be +able to validate input data. + +When a pydantic dataclass is generated from scratch, it's just a plain dataclass +with validation triggered at initialization + +The tricky part if for stdlib dataclasses that are converted after into pydantic ones e.g. + +```py +@dataclasses.dataclass +class M: + x: int + +ValidatedM = pydantic.dataclasses.dataclass(M) +``` + +We indeed still want to support equality, hashing, repr, ... as if it was the stdlib one! + +```py +assert isinstance(ValidatedM(x=1), M) +assert ValidatedM(x=1) == M(x=1) +``` + +This means we **don't want to create a new dataclass that inherits from it** +The trick is to create a wrapper around `M` that will act as a proxy to trigger +validation without altering default `M` behaviour. +""" +import copy +import dataclasses +import sys +from contextlib import contextmanager +from functools import wraps + +try: + from functools import cached_property +except ImportError: + # cached_property available only for python3.8+ + pass + +from typing import TYPE_CHECKING, Any, Callable, ClassVar, Dict, Generator, Optional, Type, TypeVar, Union, overload + +from typing_extensions import dataclass_transform + +from pydantic.v1.class_validators import gather_all_validators +from pydantic.v1.config import BaseConfig, ConfigDict, Extra, get_config +from pydantic.v1.error_wrappers import ValidationError +from pydantic.v1.errors import DataclassTypeError +from pydantic.v1.fields import Field, FieldInfo, Required, Undefined +from pydantic.v1.main import create_model, validate_model +from pydantic.v1.utils import ClassAttribute + +if TYPE_CHECKING: + from pydantic.v1.main import BaseModel + from pydantic.v1.typing import CallableGenerator, NoArgAnyCallable + + DataclassT = TypeVar('DataclassT', bound='Dataclass') + + DataclassClassOrWrapper = Union[Type['Dataclass'], 'DataclassProxy'] + + class Dataclass: + # stdlib attributes + __dataclass_fields__: ClassVar[Dict[str, Any]] + __dataclass_params__: ClassVar[Any] # in reality `dataclasses._DataclassParams` + __post_init__: ClassVar[Callable[..., None]] + + # Added by pydantic + __pydantic_run_validation__: ClassVar[bool] + __post_init_post_parse__: ClassVar[Callable[..., None]] + __pydantic_initialised__: ClassVar[bool] + __pydantic_model__: ClassVar[Type[BaseModel]] + __pydantic_validate_values__: ClassVar[Callable[['Dataclass'], None]] + __pydantic_has_field_info_default__: ClassVar[bool] # whether a `pydantic.Field` is used as default value + + def __init__(self, *args: object, **kwargs: object) -> None: + pass + + @classmethod + def __get_validators__(cls: Type['Dataclass']) -> 'CallableGenerator': + pass + + @classmethod + def __validate__(cls: Type['DataclassT'], v: Any) -> 'DataclassT': + pass + + +__all__ = [ + 'dataclass', + 'set_validation', + 'create_pydantic_model_from_dataclass', + 'is_builtin_dataclass', + 'make_dataclass_validator', +] + +_T = TypeVar('_T') + +if sys.version_info >= (3, 10): + + @dataclass_transform(field_specifiers=(dataclasses.field, Field)) + @overload + def dataclass( + *, + init: bool = True, + repr: bool = True, + eq: bool = True, + order: bool = False, + unsafe_hash: bool = False, + frozen: bool = False, + config: Union[ConfigDict, Type[object], None] = None, + validate_on_init: Optional[bool] = None, + use_proxy: Optional[bool] = None, + kw_only: bool = ..., + ) -> Callable[[Type[_T]], 'DataclassClassOrWrapper']: + ... + + @dataclass_transform(field_specifiers=(dataclasses.field, Field)) + @overload + def dataclass( + _cls: Type[_T], + *, + init: bool = True, + repr: bool = True, + eq: bool = True, + order: bool = False, + unsafe_hash: bool = False, + frozen: bool = False, + config: Union[ConfigDict, Type[object], None] = None, + validate_on_init: Optional[bool] = None, + use_proxy: Optional[bool] = None, + kw_only: bool = ..., + ) -> 'DataclassClassOrWrapper': + ... + +else: + + @dataclass_transform(field_specifiers=(dataclasses.field, Field)) + @overload + def dataclass( + *, + init: bool = True, + repr: bool = True, + eq: bool = True, + order: bool = False, + unsafe_hash: bool = False, + frozen: bool = False, + config: Union[ConfigDict, Type[object], None] = None, + validate_on_init: Optional[bool] = None, + use_proxy: Optional[bool] = None, + ) -> Callable[[Type[_T]], 'DataclassClassOrWrapper']: + ... + + @dataclass_transform(field_specifiers=(dataclasses.field, Field)) + @overload + def dataclass( + _cls: Type[_T], + *, + init: bool = True, + repr: bool = True, + eq: bool = True, + order: bool = False, + unsafe_hash: bool = False, + frozen: bool = False, + config: Union[ConfigDict, Type[object], None] = None, + validate_on_init: Optional[bool] = None, + use_proxy: Optional[bool] = None, + ) -> 'DataclassClassOrWrapper': + ... + + +@dataclass_transform(field_specifiers=(dataclasses.field, Field)) +def dataclass( + _cls: Optional[Type[_T]] = None, + *, + init: bool = True, + repr: bool = True, + eq: bool = True, + order: bool = False, + unsafe_hash: bool = False, + frozen: bool = False, + config: Union[ConfigDict, Type[object], None] = None, + validate_on_init: Optional[bool] = None, + use_proxy: Optional[bool] = None, + kw_only: bool = False, +) -> Union[Callable[[Type[_T]], 'DataclassClassOrWrapper'], 'DataclassClassOrWrapper']: + """ + Like the python standard lib dataclasses but with type validation. + The result is either a pydantic dataclass that will validate input data + or a wrapper that will trigger validation around a stdlib dataclass + to avoid modifying it directly + """ + the_config = get_config(config) + + def wrap(cls: Type[Any]) -> 'DataclassClassOrWrapper': + should_use_proxy = ( + use_proxy + if use_proxy is not None + else ( + is_builtin_dataclass(cls) + and (cls.__bases__[0] is object or set(dir(cls)) == set(dir(cls.__bases__[0]))) + ) + ) + if should_use_proxy: + dc_cls_doc = '' + dc_cls = DataclassProxy(cls) + default_validate_on_init = False + else: + dc_cls_doc = cls.__doc__ or '' # needs to be done before generating dataclass + if sys.version_info >= (3, 10): + dc_cls = dataclasses.dataclass( + cls, + init=init, + repr=repr, + eq=eq, + order=order, + unsafe_hash=unsafe_hash, + frozen=frozen, + kw_only=kw_only, + ) + else: + dc_cls = dataclasses.dataclass( # type: ignore + cls, init=init, repr=repr, eq=eq, order=order, unsafe_hash=unsafe_hash, frozen=frozen + ) + default_validate_on_init = True + + should_validate_on_init = default_validate_on_init if validate_on_init is None else validate_on_init + _add_pydantic_validation_attributes(cls, the_config, should_validate_on_init, dc_cls_doc) + dc_cls.__pydantic_model__.__try_update_forward_refs__(**{cls.__name__: cls}) + return dc_cls + + if _cls is None: + return wrap + + return wrap(_cls) + + +@contextmanager +def set_validation(cls: Type['DataclassT'], value: bool) -> Generator[Type['DataclassT'], None, None]: + original_run_validation = cls.__pydantic_run_validation__ + try: + cls.__pydantic_run_validation__ = value + yield cls + finally: + cls.__pydantic_run_validation__ = original_run_validation + + +class DataclassProxy: + __slots__ = '__dataclass__' + + def __init__(self, dc_cls: Type['Dataclass']) -> None: + object.__setattr__(self, '__dataclass__', dc_cls) + + def __call__(self, *args: Any, **kwargs: Any) -> Any: + with set_validation(self.__dataclass__, True): + return self.__dataclass__(*args, **kwargs) + + def __getattr__(self, name: str) -> Any: + return getattr(self.__dataclass__, name) + + def __setattr__(self, __name: str, __value: Any) -> None: + return setattr(self.__dataclass__, __name, __value) + + def __instancecheck__(self, instance: Any) -> bool: + return isinstance(instance, self.__dataclass__) + + def __copy__(self) -> 'DataclassProxy': + return DataclassProxy(copy.copy(self.__dataclass__)) + + def __deepcopy__(self, memo: Any) -> 'DataclassProxy': + return DataclassProxy(copy.deepcopy(self.__dataclass__, memo)) + + +def _add_pydantic_validation_attributes( # noqa: C901 (ignore complexity) + dc_cls: Type['Dataclass'], + config: Type[BaseConfig], + validate_on_init: bool, + dc_cls_doc: str, +) -> None: + """ + We need to replace the right method. If no `__post_init__` has been set in the stdlib dataclass + it won't even exist (code is generated on the fly by `dataclasses`) + By default, we run validation after `__init__` or `__post_init__` if defined + """ + init = dc_cls.__init__ + + @wraps(init) + def handle_extra_init(self: 'Dataclass', *args: Any, **kwargs: Any) -> None: + if config.extra == Extra.ignore: + init(self, *args, **{k: v for k, v in kwargs.items() if k in self.__dataclass_fields__}) + + elif config.extra == Extra.allow: + for k, v in kwargs.items(): + self.__dict__.setdefault(k, v) + init(self, *args, **{k: v for k, v in kwargs.items() if k in self.__dataclass_fields__}) + + else: + init(self, *args, **kwargs) + + if hasattr(dc_cls, '__post_init__'): + try: + post_init = dc_cls.__post_init__.__wrapped__ # type: ignore[attr-defined] + except AttributeError: + post_init = dc_cls.__post_init__ + + @wraps(post_init) + def new_post_init(self: 'Dataclass', *args: Any, **kwargs: Any) -> None: + if config.post_init_call == 'before_validation': + post_init(self, *args, **kwargs) + + if self.__class__.__pydantic_run_validation__: + self.__pydantic_validate_values__() + if hasattr(self, '__post_init_post_parse__'): + self.__post_init_post_parse__(*args, **kwargs) + + if config.post_init_call == 'after_validation': + post_init(self, *args, **kwargs) + + setattr(dc_cls, '__init__', handle_extra_init) + setattr(dc_cls, '__post_init__', new_post_init) + + else: + + @wraps(init) + def new_init(self: 'Dataclass', *args: Any, **kwargs: Any) -> None: + handle_extra_init(self, *args, **kwargs) + + if self.__class__.__pydantic_run_validation__: + self.__pydantic_validate_values__() + + if hasattr(self, '__post_init_post_parse__'): + # We need to find again the initvars. To do that we use `__dataclass_fields__` instead of + # public method `dataclasses.fields` + + # get all initvars and their default values + initvars_and_values: Dict[str, Any] = {} + for i, f in enumerate(self.__class__.__dataclass_fields__.values()): + if f._field_type is dataclasses._FIELD_INITVAR: # type: ignore[attr-defined] + try: + # set arg value by default + initvars_and_values[f.name] = args[i] + except IndexError: + initvars_and_values[f.name] = kwargs.get(f.name, f.default) + + self.__post_init_post_parse__(**initvars_and_values) + + setattr(dc_cls, '__init__', new_init) + + setattr(dc_cls, '__pydantic_run_validation__', ClassAttribute('__pydantic_run_validation__', validate_on_init)) + setattr(dc_cls, '__pydantic_initialised__', False) + setattr(dc_cls, '__pydantic_model__', create_pydantic_model_from_dataclass(dc_cls, config, dc_cls_doc)) + setattr(dc_cls, '__pydantic_validate_values__', _dataclass_validate_values) + setattr(dc_cls, '__validate__', classmethod(_validate_dataclass)) + setattr(dc_cls, '__get_validators__', classmethod(_get_validators)) + + if dc_cls.__pydantic_model__.__config__.validate_assignment and not dc_cls.__dataclass_params__.frozen: + setattr(dc_cls, '__setattr__', _dataclass_validate_assignment_setattr) + + +def _get_validators(cls: 'DataclassClassOrWrapper') -> 'CallableGenerator': + yield cls.__validate__ + + +def _validate_dataclass(cls: Type['DataclassT'], v: Any) -> 'DataclassT': + with set_validation(cls, True): + if isinstance(v, cls): + v.__pydantic_validate_values__() + return v + elif isinstance(v, (list, tuple)): + return cls(*v) + elif isinstance(v, dict): + return cls(**v) + else: + raise DataclassTypeError(class_name=cls.__name__) + + +def create_pydantic_model_from_dataclass( + dc_cls: Type['Dataclass'], + config: Type[Any] = BaseConfig, + dc_cls_doc: Optional[str] = None, +) -> Type['BaseModel']: + field_definitions: Dict[str, Any] = {} + for field in dataclasses.fields(dc_cls): + default: Any = Undefined + default_factory: Optional['NoArgAnyCallable'] = None + field_info: FieldInfo + + if field.default is not dataclasses.MISSING: + default = field.default + elif field.default_factory is not dataclasses.MISSING: + default_factory = field.default_factory + else: + default = Required + + if isinstance(default, FieldInfo): + field_info = default + dc_cls.__pydantic_has_field_info_default__ = True + else: + field_info = Field(default=default, default_factory=default_factory, **field.metadata) + + field_definitions[field.name] = (field.type, field_info) + + validators = gather_all_validators(dc_cls) + model: Type['BaseModel'] = create_model( + dc_cls.__name__, + __config__=config, + __module__=dc_cls.__module__, + __validators__=validators, + __cls_kwargs__={'__resolve_forward_refs__': False}, + **field_definitions, + ) + model.__doc__ = dc_cls_doc if dc_cls_doc is not None else dc_cls.__doc__ or '' + return model + + +if sys.version_info >= (3, 8): + + def _is_field_cached_property(obj: 'Dataclass', k: str) -> bool: + return isinstance(getattr(type(obj), k, None), cached_property) + +else: + + def _is_field_cached_property(obj: 'Dataclass', k: str) -> bool: + return False + + +def _dataclass_validate_values(self: 'Dataclass') -> None: + # validation errors can occur if this function is called twice on an already initialised dataclass. + # for example if Extra.forbid is enabled, it would consider __pydantic_initialised__ an invalid extra property + if getattr(self, '__pydantic_initialised__'): + return + if getattr(self, '__pydantic_has_field_info_default__', False): + # We need to remove `FieldInfo` values since they are not valid as input + # It's ok to do that because they are obviously the default values! + input_data = { + k: v + for k, v in self.__dict__.items() + if not (isinstance(v, FieldInfo) or _is_field_cached_property(self, k)) + } + else: + input_data = {k: v for k, v in self.__dict__.items() if not _is_field_cached_property(self, k)} + d, _, validation_error = validate_model(self.__pydantic_model__, input_data, cls=self.__class__) + if validation_error: + raise validation_error + self.__dict__.update(d) + object.__setattr__(self, '__pydantic_initialised__', True) + + +def _dataclass_validate_assignment_setattr(self: 'Dataclass', name: str, value: Any) -> None: + if self.__pydantic_initialised__: + d = dict(self.__dict__) + d.pop(name, None) + known_field = self.__pydantic_model__.__fields__.get(name, None) + if known_field: + value, error_ = known_field.validate(value, d, loc=name, cls=self.__class__) + if error_: + raise ValidationError([error_], self.__class__) + + object.__setattr__(self, name, value) + + +def is_builtin_dataclass(_cls: Type[Any]) -> bool: + """ + Whether a class is a stdlib dataclass + (useful to discriminated a pydantic dataclass that is actually a wrapper around a stdlib dataclass) + + we check that + - `_cls` is a dataclass + - `_cls` is not a processed pydantic dataclass (with a basemodel attached) + - `_cls` is not a pydantic dataclass inheriting directly from a stdlib dataclass + e.g. + ``` + @dataclasses.dataclass + class A: + x: int + + @pydantic.dataclasses.dataclass + class B(A): + y: int + ``` + In this case, when we first check `B`, we make an extra check and look at the annotations ('y'), + which won't be a superset of all the dataclass fields (only the stdlib fields i.e. 'x') + """ + return ( + dataclasses.is_dataclass(_cls) + and not hasattr(_cls, '__pydantic_model__') + and set(_cls.__dataclass_fields__).issuperset(set(getattr(_cls, '__annotations__', {}))) + ) + + +def make_dataclass_validator(dc_cls: Type['Dataclass'], config: Type[BaseConfig]) -> 'CallableGenerator': + """ + Create a pydantic.dataclass from a builtin dataclass to add type validation + and yield the validators + It retrieves the parameters of the dataclass and forwards them to the newly created dataclass + """ + yield from _get_validators(dataclass(dc_cls, config=config, use_proxy=True)) diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/datetime_parse.py b/backend/.venv/Lib/site-packages/pydantic/v1/datetime_parse.py new file mode 100644 index 0000000..a7598fc --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/datetime_parse.py @@ -0,0 +1,248 @@ +""" +Functions to parse datetime objects. + +We're using regular expressions rather than time.strptime because: +- They provide both validation and parsing. +- They're more flexible for datetimes. +- The date/datetime/time constructors produce friendlier error messages. + +Stolen from https://raw.githubusercontent.com/django/django/main/django/utils/dateparse.py at +9718fa2e8abe430c3526a9278dd976443d4ae3c6 + +Changed to: +* use standard python datetime types not django.utils.timezone +* raise ValueError when regex doesn't match rather than returning None +* support parsing unix timestamps for dates and datetimes +""" +import re +from datetime import date, datetime, time, timedelta, timezone +from typing import Dict, Optional, Type, Union + +from pydantic.v1 import errors + +date_expr = r'(?P\d{4})-(?P\d{1,2})-(?P\d{1,2})' +time_expr = ( + r'(?P\d{1,2}):(?P\d{1,2})' + r'(?::(?P\d{1,2})(?:\.(?P\d{1,6})\d{0,6})?)?' + r'(?PZ|[+-]\d{2}(?::?\d{2})?)?$' +) + +date_re = re.compile(f'{date_expr}$') +time_re = re.compile(time_expr) +datetime_re = re.compile(f'{date_expr}[T ]{time_expr}') + +standard_duration_re = re.compile( + r'^' + r'(?:(?P-?\d+) (days?, )?)?' + r'((?:(?P-?\d+):)(?=\d+:\d+))?' + r'(?:(?P-?\d+):)?' + r'(?P-?\d+)' + r'(?:\.(?P\d{1,6})\d{0,6})?' + r'$' +) + +# Support the sections of ISO 8601 date representation that are accepted by timedelta +iso8601_duration_re = re.compile( + r'^(?P[-+]?)' + r'P' + r'(?:(?P\d+(.\d+)?)D)?' + r'(?:T' + r'(?:(?P\d+(.\d+)?)H)?' + r'(?:(?P\d+(.\d+)?)M)?' + r'(?:(?P\d+(.\d+)?)S)?' + r')?' + r'$' +) + +EPOCH = datetime(1970, 1, 1) +# if greater than this, the number is in ms, if less than or equal it's in seconds +# (in seconds this is 11th October 2603, in ms it's 20th August 1970) +MS_WATERSHED = int(2e10) +# slightly more than datetime.max in ns - (datetime.max - EPOCH).total_seconds() * 1e9 +MAX_NUMBER = int(3e20) +StrBytesIntFloat = Union[str, bytes, int, float] + + +def get_numeric(value: StrBytesIntFloat, native_expected_type: str) -> Union[None, int, float]: + if isinstance(value, (int, float)): + return value + try: + return float(value) + except ValueError: + return None + except TypeError: + raise TypeError(f'invalid type; expected {native_expected_type}, string, bytes, int or float') + + +def from_unix_seconds(seconds: Union[int, float]) -> datetime: + if seconds > MAX_NUMBER: + return datetime.max + elif seconds < -MAX_NUMBER: + return datetime.min + + while abs(seconds) > MS_WATERSHED: + seconds /= 1000 + dt = EPOCH + timedelta(seconds=seconds) + return dt.replace(tzinfo=timezone.utc) + + +def _parse_timezone(value: Optional[str], error: Type[Exception]) -> Union[None, int, timezone]: + if value == 'Z': + return timezone.utc + elif value is not None: + offset_mins = int(value[-2:]) if len(value) > 3 else 0 + offset = 60 * int(value[1:3]) + offset_mins + if value[0] == '-': + offset = -offset + try: + return timezone(timedelta(minutes=offset)) + except ValueError: + raise error() + else: + return None + + +def parse_date(value: Union[date, StrBytesIntFloat]) -> date: + """ + Parse a date/int/float/string and return a datetime.date. + + Raise ValueError if the input is well formatted but not a valid date. + Raise ValueError if the input isn't well formatted. + """ + if isinstance(value, date): + if isinstance(value, datetime): + return value.date() + else: + return value + + number = get_numeric(value, 'date') + if number is not None: + return from_unix_seconds(number).date() + + if isinstance(value, bytes): + value = value.decode() + + match = date_re.match(value) # type: ignore + if match is None: + raise errors.DateError() + + kw = {k: int(v) for k, v in match.groupdict().items()} + + try: + return date(**kw) + except ValueError: + raise errors.DateError() + + +def parse_time(value: Union[time, StrBytesIntFloat]) -> time: + """ + Parse a time/string and return a datetime.time. + + Raise ValueError if the input is well formatted but not a valid time. + Raise ValueError if the input isn't well formatted, in particular if it contains an offset. + """ + if isinstance(value, time): + return value + + number = get_numeric(value, 'time') + if number is not None: + if number >= 86400: + # doesn't make sense since the time time loop back around to 0 + raise errors.TimeError() + return (datetime.min + timedelta(seconds=number)).time() + + if isinstance(value, bytes): + value = value.decode() + + match = time_re.match(value) # type: ignore + if match is None: + raise errors.TimeError() + + kw = match.groupdict() + if kw['microsecond']: + kw['microsecond'] = kw['microsecond'].ljust(6, '0') + + tzinfo = _parse_timezone(kw.pop('tzinfo'), errors.TimeError) + kw_: Dict[str, Union[None, int, timezone]] = {k: int(v) for k, v in kw.items() if v is not None} + kw_['tzinfo'] = tzinfo + + try: + return time(**kw_) # type: ignore + except ValueError: + raise errors.TimeError() + + +def parse_datetime(value: Union[datetime, StrBytesIntFloat]) -> datetime: + """ + Parse a datetime/int/float/string and return a datetime.datetime. + + This function supports time zone offsets. When the input contains one, + the output uses a timezone with a fixed offset from UTC. + + Raise ValueError if the input is well formatted but not a valid datetime. + Raise ValueError if the input isn't well formatted. + """ + if isinstance(value, datetime): + return value + + number = get_numeric(value, 'datetime') + if number is not None: + return from_unix_seconds(number) + + if isinstance(value, bytes): + value = value.decode() + + match = datetime_re.match(value) # type: ignore + if match is None: + raise errors.DateTimeError() + + kw = match.groupdict() + if kw['microsecond']: + kw['microsecond'] = kw['microsecond'].ljust(6, '0') + + tzinfo = _parse_timezone(kw.pop('tzinfo'), errors.DateTimeError) + kw_: Dict[str, Union[None, int, timezone]] = {k: int(v) for k, v in kw.items() if v is not None} + kw_['tzinfo'] = tzinfo + + try: + return datetime(**kw_) # type: ignore + except ValueError: + raise errors.DateTimeError() + + +def parse_duration(value: StrBytesIntFloat) -> timedelta: + """ + Parse a duration int/float/string and return a datetime.timedelta. + + The preferred format for durations in Django is '%d %H:%M:%S.%f'. + + Also supports ISO 8601 representation. + """ + if isinstance(value, timedelta): + return value + + if isinstance(value, (int, float)): + # below code requires a string + value = f'{value:f}' + elif isinstance(value, bytes): + value = value.decode() + + try: + match = standard_duration_re.match(value) or iso8601_duration_re.match(value) + except TypeError: + raise TypeError('invalid type; expected timedelta, string, bytes, int or float') + + if not match: + raise errors.DurationError() + + kw = match.groupdict() + sign = -1 if kw.pop('sign', '+') == '-' else 1 + if kw.get('microseconds'): + kw['microseconds'] = kw['microseconds'].ljust(6, '0') + + if kw.get('seconds') and kw.get('microseconds') and kw['seconds'].startswith('-'): + kw['microseconds'] = '-' + kw['microseconds'] + + kw_ = {k: float(v) for k, v in kw.items() if v is not None} + + return sign * timedelta(**kw_) diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/decorator.py b/backend/.venv/Lib/site-packages/pydantic/v1/decorator.py new file mode 100644 index 0000000..2c7c2c2 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/decorator.py @@ -0,0 +1,264 @@ +from functools import wraps +from typing import TYPE_CHECKING, Any, Callable, Dict, List, Mapping, Optional, Tuple, Type, TypeVar, Union, overload + +from pydantic.v1 import validator +from pydantic.v1.config import Extra +from pydantic.v1.errors import ConfigError +from pydantic.v1.main import BaseModel, create_model +from pydantic.v1.typing import get_all_type_hints +from pydantic.v1.utils import to_camel + +__all__ = ('validate_arguments',) + +if TYPE_CHECKING: + from pydantic.v1.typing import AnyCallable + + AnyCallableT = TypeVar('AnyCallableT', bound=AnyCallable) + ConfigType = Union[None, Type[Any], Dict[str, Any]] + + +@overload +def validate_arguments(func: None = None, *, config: 'ConfigType' = None) -> Callable[['AnyCallableT'], 'AnyCallableT']: + ... + + +@overload +def validate_arguments(func: 'AnyCallableT') -> 'AnyCallableT': + ... + + +def validate_arguments(func: Optional['AnyCallableT'] = None, *, config: 'ConfigType' = None) -> Any: + """ + Decorator to validate the arguments passed to a function. + """ + + def validate(_func: 'AnyCallable') -> 'AnyCallable': + vd = ValidatedFunction(_func, config) + + @wraps(_func) + def wrapper_function(*args: Any, **kwargs: Any) -> Any: + return vd.call(*args, **kwargs) + + wrapper_function.vd = vd # type: ignore + wrapper_function.validate = vd.init_model_instance # type: ignore + wrapper_function.raw_function = vd.raw_function # type: ignore + wrapper_function.model = vd.model # type: ignore + return wrapper_function + + if func: + return validate(func) + else: + return validate + + +ALT_V_ARGS = 'v__args' +ALT_V_KWARGS = 'v__kwargs' +V_POSITIONAL_ONLY_NAME = 'v__positional_only' +V_DUPLICATE_KWARGS = 'v__duplicate_kwargs' + + +class ValidatedFunction: + def __init__(self, function: 'AnyCallableT', config: 'ConfigType'): # noqa C901 + from inspect import Parameter, signature + + parameters: Mapping[str, Parameter] = signature(function).parameters + + if parameters.keys() & {ALT_V_ARGS, ALT_V_KWARGS, V_POSITIONAL_ONLY_NAME, V_DUPLICATE_KWARGS}: + raise ConfigError( + f'"{ALT_V_ARGS}", "{ALT_V_KWARGS}", "{V_POSITIONAL_ONLY_NAME}" and "{V_DUPLICATE_KWARGS}" ' + f'are not permitted as argument names when using the "{validate_arguments.__name__}" decorator' + ) + + self.raw_function = function + self.arg_mapping: Dict[int, str] = {} + self.positional_only_args = set() + self.v_args_name = 'args' + self.v_kwargs_name = 'kwargs' + + type_hints = get_all_type_hints(function) + takes_args = False + takes_kwargs = False + fields: Dict[str, Tuple[Any, Any]] = {} + for i, (name, p) in enumerate(parameters.items()): + if p.annotation is p.empty: + annotation = Any + else: + annotation = type_hints[name] + + default = ... if p.default is p.empty else p.default + if p.kind == Parameter.POSITIONAL_ONLY: + self.arg_mapping[i] = name + fields[name] = annotation, default + fields[V_POSITIONAL_ONLY_NAME] = List[str], None + self.positional_only_args.add(name) + elif p.kind == Parameter.POSITIONAL_OR_KEYWORD: + self.arg_mapping[i] = name + fields[name] = annotation, default + fields[V_DUPLICATE_KWARGS] = List[str], None + elif p.kind == Parameter.KEYWORD_ONLY: + fields[name] = annotation, default + elif p.kind == Parameter.VAR_POSITIONAL: + self.v_args_name = name + fields[name] = Tuple[annotation, ...], None + takes_args = True + else: + assert p.kind == Parameter.VAR_KEYWORD, p.kind + self.v_kwargs_name = name + fields[name] = Dict[str, annotation], None # type: ignore + takes_kwargs = True + + # these checks avoid a clash between "args" and a field with that name + if not takes_args and self.v_args_name in fields: + self.v_args_name = ALT_V_ARGS + + # same with "kwargs" + if not takes_kwargs and self.v_kwargs_name in fields: + self.v_kwargs_name = ALT_V_KWARGS + + if not takes_args: + # we add the field so validation below can raise the correct exception + fields[self.v_args_name] = List[Any], None + + if not takes_kwargs: + # same with kwargs + fields[self.v_kwargs_name] = Dict[Any, Any], None + + self.create_model(fields, takes_args, takes_kwargs, config) + + def init_model_instance(self, *args: Any, **kwargs: Any) -> BaseModel: + values = self.build_values(args, kwargs) + return self.model(**values) + + def call(self, *args: Any, **kwargs: Any) -> Any: + m = self.init_model_instance(*args, **kwargs) + return self.execute(m) + + def build_values(self, args: Tuple[Any, ...], kwargs: Dict[str, Any]) -> Dict[str, Any]: + values: Dict[str, Any] = {} + if args: + arg_iter = enumerate(args) + while True: + try: + i, a = next(arg_iter) + except StopIteration: + break + arg_name = self.arg_mapping.get(i) + if arg_name is not None: + values[arg_name] = a + else: + values[self.v_args_name] = [a] + [a for _, a in arg_iter] + break + + var_kwargs: Dict[str, Any] = {} + wrong_positional_args = [] + duplicate_kwargs = [] + fields_alias = [ + field.alias + for name, field in self.model.__fields__.items() + if name not in (self.v_args_name, self.v_kwargs_name) + ] + non_var_fields = set(self.model.__fields__) - {self.v_args_name, self.v_kwargs_name} + for k, v in kwargs.items(): + if k in non_var_fields or k in fields_alias: + if k in self.positional_only_args: + wrong_positional_args.append(k) + if k in values: + duplicate_kwargs.append(k) + values[k] = v + else: + var_kwargs[k] = v + + if var_kwargs: + values[self.v_kwargs_name] = var_kwargs + if wrong_positional_args: + values[V_POSITIONAL_ONLY_NAME] = wrong_positional_args + if duplicate_kwargs: + values[V_DUPLICATE_KWARGS] = duplicate_kwargs + return values + + def execute(self, m: BaseModel) -> Any: + d = {k: v for k, v in m._iter() if k in m.__fields_set__ or m.__fields__[k].default_factory} + var_kwargs = d.pop(self.v_kwargs_name, {}) + + if self.v_args_name in d: + args_: List[Any] = [] + in_kwargs = False + kwargs = {} + for name, value in d.items(): + if in_kwargs: + kwargs[name] = value + elif name == self.v_args_name: + args_ += value + in_kwargs = True + else: + args_.append(value) + return self.raw_function(*args_, **kwargs, **var_kwargs) + elif self.positional_only_args: + args_ = [] + kwargs = {} + for name, value in d.items(): + if name in self.positional_only_args: + args_.append(value) + else: + kwargs[name] = value + return self.raw_function(*args_, **kwargs, **var_kwargs) + else: + return self.raw_function(**d, **var_kwargs) + + def create_model(self, fields: Dict[str, Any], takes_args: bool, takes_kwargs: bool, config: 'ConfigType') -> None: + pos_args = len(self.arg_mapping) + + class CustomConfig: + pass + + if not TYPE_CHECKING: # pragma: no branch + if isinstance(config, dict): + CustomConfig = type('Config', (), config) # noqa: F811 + elif config is not None: + CustomConfig = config # noqa: F811 + + if hasattr(CustomConfig, 'fields') or hasattr(CustomConfig, 'alias_generator'): + raise ConfigError( + 'Setting the "fields" and "alias_generator" property on custom Config for ' + '@validate_arguments is not yet supported, please remove.' + ) + + class DecoratorBaseModel(BaseModel): + @validator(self.v_args_name, check_fields=False, allow_reuse=True) + def check_args(cls, v: Optional[List[Any]]) -> Optional[List[Any]]: + if takes_args or v is None: + return v + + raise TypeError(f'{pos_args} positional arguments expected but {pos_args + len(v)} given') + + @validator(self.v_kwargs_name, check_fields=False, allow_reuse=True) + def check_kwargs(cls, v: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]: + if takes_kwargs or v is None: + return v + + plural = '' if len(v) == 1 else 's' + keys = ', '.join(map(repr, v.keys())) + raise TypeError(f'unexpected keyword argument{plural}: {keys}') + + @validator(V_POSITIONAL_ONLY_NAME, check_fields=False, allow_reuse=True) + def check_positional_only(cls, v: Optional[List[str]]) -> None: + if v is None: + return + + plural = '' if len(v) == 1 else 's' + keys = ', '.join(map(repr, v)) + raise TypeError(f'positional-only argument{plural} passed as keyword argument{plural}: {keys}') + + @validator(V_DUPLICATE_KWARGS, check_fields=False, allow_reuse=True) + def check_duplicate_kwargs(cls, v: Optional[List[str]]) -> None: + if v is None: + return + + plural = '' if len(v) == 1 else 's' + keys = ', '.join(map(repr, v)) + raise TypeError(f'multiple values for argument{plural}: {keys}') + + class Config(CustomConfig): + extra = getattr(CustomConfig, 'extra', Extra.forbid) + + self.model = create_model(to_camel(self.raw_function.__name__), __base__=DecoratorBaseModel, **fields) diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/env_settings.py b/backend/.venv/Lib/site-packages/pydantic/v1/env_settings.py new file mode 100644 index 0000000..5f6f217 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/env_settings.py @@ -0,0 +1,350 @@ +import os +import warnings +from pathlib import Path +from typing import AbstractSet, Any, Callable, ClassVar, Dict, List, Mapping, Optional, Tuple, Type, Union + +from pydantic.v1.config import BaseConfig, Extra +from pydantic.v1.fields import ModelField +from pydantic.v1.main import BaseModel +from pydantic.v1.types import JsonWrapper +from pydantic.v1.typing import StrPath, display_as_type, get_origin, is_union +from pydantic.v1.utils import deep_update, lenient_issubclass, path_type, sequence_like + +env_file_sentinel = str(object()) + +SettingsSourceCallable = Callable[['BaseSettings'], Dict[str, Any]] +DotenvType = Union[StrPath, List[StrPath], Tuple[StrPath, ...]] + + +class SettingsError(ValueError): + pass + + +class BaseSettings(BaseModel): + """ + Base class for settings, allowing values to be overridden by environment variables. + + This is useful in production for secrets you do not wish to save in code, it plays nicely with docker(-compose), + Heroku and any 12 factor app design. + """ + + def __init__( + __pydantic_self__, + _env_file: Optional[DotenvType] = env_file_sentinel, + _env_file_encoding: Optional[str] = None, + _env_nested_delimiter: Optional[str] = None, + _secrets_dir: Optional[StrPath] = None, + **values: Any, + ) -> None: + # Uses something other than `self` the first arg to allow "self" as a settable attribute + super().__init__( + **__pydantic_self__._build_values( + values, + _env_file=_env_file, + _env_file_encoding=_env_file_encoding, + _env_nested_delimiter=_env_nested_delimiter, + _secrets_dir=_secrets_dir, + ) + ) + + def _build_values( + self, + init_kwargs: Dict[str, Any], + _env_file: Optional[DotenvType] = None, + _env_file_encoding: Optional[str] = None, + _env_nested_delimiter: Optional[str] = None, + _secrets_dir: Optional[StrPath] = None, + ) -> Dict[str, Any]: + # Configure built-in sources + init_settings = InitSettingsSource(init_kwargs=init_kwargs) + env_settings = EnvSettingsSource( + env_file=(_env_file if _env_file != env_file_sentinel else self.__config__.env_file), + env_file_encoding=( + _env_file_encoding if _env_file_encoding is not None else self.__config__.env_file_encoding + ), + env_nested_delimiter=( + _env_nested_delimiter if _env_nested_delimiter is not None else self.__config__.env_nested_delimiter + ), + env_prefix_len=len(self.__config__.env_prefix), + ) + file_secret_settings = SecretsSettingsSource(secrets_dir=_secrets_dir or self.__config__.secrets_dir) + # Provide a hook to set built-in sources priority and add / remove sources + sources = self.__config__.customise_sources( + init_settings=init_settings, env_settings=env_settings, file_secret_settings=file_secret_settings + ) + if sources: + return deep_update(*reversed([source(self) for source in sources])) + else: + # no one should mean to do this, but I think returning an empty dict is marginally preferable + # to an informative error and much better than a confusing error + return {} + + class Config(BaseConfig): + env_prefix: str = '' + env_file: Optional[DotenvType] = None + env_file_encoding: Optional[str] = None + env_nested_delimiter: Optional[str] = None + secrets_dir: Optional[StrPath] = None + validate_all: bool = True + extra: Extra = Extra.forbid + arbitrary_types_allowed: bool = True + case_sensitive: bool = False + + @classmethod + def prepare_field(cls, field: ModelField) -> None: + env_names: Union[List[str], AbstractSet[str]] + field_info_from_config = cls.get_field_info(field.name) + + env = field_info_from_config.get('env') or field.field_info.extra.get('env') + if env is None: + if field.has_alias: + warnings.warn( + 'aliases are no longer used by BaseSettings to define which environment variables to read. ' + 'Instead use the "env" field setting. ' + 'See https://pydantic-docs.helpmanual.io/usage/settings/#environment-variable-names', + FutureWarning, + ) + env_names = {cls.env_prefix + field.name} + elif isinstance(env, str): + env_names = {env} + elif isinstance(env, (set, frozenset)): + env_names = env + elif sequence_like(env): + env_names = list(env) + else: + raise TypeError(f'invalid field env: {env!r} ({display_as_type(env)}); should be string, list or set') + + if not cls.case_sensitive: + env_names = env_names.__class__(n.lower() for n in env_names) + field.field_info.extra['env_names'] = env_names + + @classmethod + def customise_sources( + cls, + init_settings: SettingsSourceCallable, + env_settings: SettingsSourceCallable, + file_secret_settings: SettingsSourceCallable, + ) -> Tuple[SettingsSourceCallable, ...]: + return init_settings, env_settings, file_secret_settings + + @classmethod + def parse_env_var(cls, field_name: str, raw_val: str) -> Any: + return cls.json_loads(raw_val) + + # populated by the metaclass using the Config class defined above, annotated here to help IDEs only + __config__: ClassVar[Type[Config]] + + +class InitSettingsSource: + __slots__ = ('init_kwargs',) + + def __init__(self, init_kwargs: Dict[str, Any]): + self.init_kwargs = init_kwargs + + def __call__(self, settings: BaseSettings) -> Dict[str, Any]: + return self.init_kwargs + + def __repr__(self) -> str: + return f'InitSettingsSource(init_kwargs={self.init_kwargs!r})' + + +class EnvSettingsSource: + __slots__ = ('env_file', 'env_file_encoding', 'env_nested_delimiter', 'env_prefix_len') + + def __init__( + self, + env_file: Optional[DotenvType], + env_file_encoding: Optional[str], + env_nested_delimiter: Optional[str] = None, + env_prefix_len: int = 0, + ): + self.env_file: Optional[DotenvType] = env_file + self.env_file_encoding: Optional[str] = env_file_encoding + self.env_nested_delimiter: Optional[str] = env_nested_delimiter + self.env_prefix_len: int = env_prefix_len + + def __call__(self, settings: BaseSettings) -> Dict[str, Any]: # noqa C901 + """ + Build environment variables suitable for passing to the Model. + """ + d: Dict[str, Any] = {} + + if settings.__config__.case_sensitive: + env_vars: Mapping[str, Optional[str]] = os.environ + else: + env_vars = {k.lower(): v for k, v in os.environ.items()} + + dotenv_vars = self._read_env_files(settings.__config__.case_sensitive) + if dotenv_vars: + env_vars = {**dotenv_vars, **env_vars} + + for field in settings.__fields__.values(): + env_val: Optional[str] = None + for env_name in field.field_info.extra['env_names']: + env_val = env_vars.get(env_name) + if env_val is not None: + break + + is_complex, allow_parse_failure = self.field_is_complex(field) + if is_complex: + if env_val is None: + # field is complex but no value found so far, try explode_env_vars + env_val_built = self.explode_env_vars(field, env_vars) + if env_val_built: + d[field.alias] = env_val_built + else: + # field is complex and there's a value, decode that as JSON, then add explode_env_vars + try: + env_val = settings.__config__.parse_env_var(field.name, env_val) + except ValueError as e: + if not allow_parse_failure: + raise SettingsError(f'error parsing env var "{env_name}"') from e + + if isinstance(env_val, dict): + d[field.alias] = deep_update(env_val, self.explode_env_vars(field, env_vars)) + else: + d[field.alias] = env_val + elif env_val is not None: + # simplest case, field is not complex, we only need to add the value if it was found + d[field.alias] = env_val + + return d + + def _read_env_files(self, case_sensitive: bool) -> Dict[str, Optional[str]]: + env_files = self.env_file + if env_files is None: + return {} + + if isinstance(env_files, (str, os.PathLike)): + env_files = [env_files] + + dotenv_vars = {} + for env_file in env_files: + env_path = Path(env_file).expanduser() + if env_path.is_file(): + dotenv_vars.update( + read_env_file(env_path, encoding=self.env_file_encoding, case_sensitive=case_sensitive) + ) + + return dotenv_vars + + def field_is_complex(self, field: ModelField) -> Tuple[bool, bool]: + """ + Find out if a field is complex, and if so whether JSON errors should be ignored + """ + if lenient_issubclass(field.annotation, JsonWrapper): + return False, False + + if field.is_complex(): + allow_parse_failure = False + elif is_union(get_origin(field.type_)) and field.sub_fields and any(f.is_complex() for f in field.sub_fields): + allow_parse_failure = True + else: + return False, False + + return True, allow_parse_failure + + def explode_env_vars(self, field: ModelField, env_vars: Mapping[str, Optional[str]]) -> Dict[str, Any]: + """ + Process env_vars and extract the values of keys containing env_nested_delimiter into nested dictionaries. + + This is applied to a single field, hence filtering by env_var prefix. + """ + prefixes = [f'{env_name}{self.env_nested_delimiter}' for env_name in field.field_info.extra['env_names']] + result: Dict[str, Any] = {} + for env_name, env_val in env_vars.items(): + if not any(env_name.startswith(prefix) for prefix in prefixes): + continue + # we remove the prefix before splitting in case the prefix has characters in common with the delimiter + env_name_without_prefix = env_name[self.env_prefix_len :] + _, *keys, last_key = env_name_without_prefix.split(self.env_nested_delimiter) + env_var = result + for key in keys: + env_var = env_var.setdefault(key, {}) + env_var[last_key] = env_val + + return result + + def __repr__(self) -> str: + return ( + f'EnvSettingsSource(env_file={self.env_file!r}, env_file_encoding={self.env_file_encoding!r}, ' + f'env_nested_delimiter={self.env_nested_delimiter!r})' + ) + + +class SecretsSettingsSource: + __slots__ = ('secrets_dir',) + + def __init__(self, secrets_dir: Optional[StrPath]): + self.secrets_dir: Optional[StrPath] = secrets_dir + + def __call__(self, settings: BaseSettings) -> Dict[str, Any]: + """ + Build fields from "secrets" files. + """ + secrets: Dict[str, Optional[str]] = {} + + if self.secrets_dir is None: + return secrets + + secrets_path = Path(self.secrets_dir).expanduser() + + if not secrets_path.exists(): + warnings.warn(f'directory "{secrets_path}" does not exist') + return secrets + + if not secrets_path.is_dir(): + raise SettingsError(f'secrets_dir must reference a directory, not a {path_type(secrets_path)}') + + for field in settings.__fields__.values(): + for env_name in field.field_info.extra['env_names']: + path = find_case_path(secrets_path, env_name, settings.__config__.case_sensitive) + if not path: + # path does not exist, we currently don't return a warning for this + continue + + if path.is_file(): + secret_value = path.read_text().strip() + if field.is_complex(): + try: + secret_value = settings.__config__.parse_env_var(field.name, secret_value) + except ValueError as e: + raise SettingsError(f'error parsing env var "{env_name}"') from e + + secrets[field.alias] = secret_value + else: + warnings.warn( + f'attempted to load secret file "{path}" but found a {path_type(path)} instead.', + stacklevel=4, + ) + return secrets + + def __repr__(self) -> str: + return f'SecretsSettingsSource(secrets_dir={self.secrets_dir!r})' + + +def read_env_file( + file_path: StrPath, *, encoding: str = None, case_sensitive: bool = False +) -> Dict[str, Optional[str]]: + try: + from dotenv import dotenv_values + except ImportError as e: + raise ImportError('python-dotenv is not installed, run `pip install pydantic[dotenv]`') from e + + file_vars: Dict[str, Optional[str]] = dotenv_values(file_path, encoding=encoding or 'utf8') + if not case_sensitive: + return {k.lower(): v for k, v in file_vars.items()} + else: + return file_vars + + +def find_case_path(dir_path: Path, file_name: str, case_sensitive: bool) -> Optional[Path]: + """ + Find a file within path's directory matching filename, optionally ignoring case. + """ + for f in dir_path.iterdir(): + if f.name == file_name: + return f + elif not case_sensitive and f.name.lower() == file_name.lower(): + return f + return None diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/error_wrappers.py b/backend/.venv/Lib/site-packages/pydantic/v1/error_wrappers.py new file mode 100644 index 0000000..bc7f263 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/error_wrappers.py @@ -0,0 +1,161 @@ +import json +from typing import TYPE_CHECKING, Any, Dict, Generator, List, Optional, Sequence, Tuple, Type, Union + +from pydantic.v1.json import pydantic_encoder +from pydantic.v1.utils import Representation + +if TYPE_CHECKING: + from typing_extensions import TypedDict + + from pydantic.v1.config import BaseConfig + from pydantic.v1.types import ModelOrDc + from pydantic.v1.typing import ReprArgs + + Loc = Tuple[Union[int, str], ...] + + class _ErrorDictRequired(TypedDict): + loc: Loc + msg: str + type: str + + class ErrorDict(_ErrorDictRequired, total=False): + ctx: Dict[str, Any] + + +__all__ = 'ErrorWrapper', 'ValidationError' + + +class ErrorWrapper(Representation): + __slots__ = 'exc', '_loc' + + def __init__(self, exc: Exception, loc: Union[str, 'Loc']) -> None: + self.exc = exc + self._loc = loc + + def loc_tuple(self) -> 'Loc': + if isinstance(self._loc, tuple): + return self._loc + else: + return (self._loc,) + + def __repr_args__(self) -> 'ReprArgs': + return [('exc', self.exc), ('loc', self.loc_tuple())] + + +# ErrorList is something like Union[List[Union[List[ErrorWrapper], ErrorWrapper]], ErrorWrapper] +# but recursive, therefore just use: +ErrorList = Union[Sequence[Any], ErrorWrapper] + + +class ValidationError(Representation, ValueError): + __slots__ = 'raw_errors', 'model', '_error_cache' + + def __init__(self, errors: Sequence[ErrorList], model: 'ModelOrDc') -> None: + self.raw_errors = errors + self.model = model + self._error_cache: Optional[List['ErrorDict']] = None + + def errors(self) -> List['ErrorDict']: + if self._error_cache is None: + try: + config = self.model.__config__ # type: ignore + except AttributeError: + config = self.model.__pydantic_model__.__config__ # type: ignore + self._error_cache = list(flatten_errors(self.raw_errors, config)) + return self._error_cache + + def json(self, *, indent: Union[None, int, str] = 2) -> str: + return json.dumps(self.errors(), indent=indent, default=pydantic_encoder) + + def __str__(self) -> str: + errors = self.errors() + no_errors = len(errors) + return ( + f'{no_errors} validation error{"" if no_errors == 1 else "s"} for {self.model.__name__}\n' + f'{display_errors(errors)}' + ) + + def __repr_args__(self) -> 'ReprArgs': + return [('model', self.model.__name__), ('errors', self.errors())] + + +def display_errors(errors: List['ErrorDict']) -> str: + return '\n'.join(f'{_display_error_loc(e)}\n {e["msg"]} ({_display_error_type_and_ctx(e)})' for e in errors) + + +def _display_error_loc(error: 'ErrorDict') -> str: + return ' -> '.join(str(e) for e in error['loc']) + + +def _display_error_type_and_ctx(error: 'ErrorDict') -> str: + t = 'type=' + error['type'] + ctx = error.get('ctx') + if ctx: + return t + ''.join(f'; {k}={v}' for k, v in ctx.items()) + else: + return t + + +def flatten_errors( + errors: Sequence[Any], config: Type['BaseConfig'], loc: Optional['Loc'] = None +) -> Generator['ErrorDict', None, None]: + for error in errors: + if isinstance(error, ErrorWrapper): + if loc: + error_loc = loc + error.loc_tuple() + else: + error_loc = error.loc_tuple() + + if isinstance(error.exc, ValidationError): + yield from flatten_errors(error.exc.raw_errors, config, error_loc) + else: + yield error_dict(error.exc, config, error_loc) + elif isinstance(error, list): + yield from flatten_errors(error, config, loc=loc) + else: + raise RuntimeError(f'Unknown error object: {error}') + + +def error_dict(exc: Exception, config: Type['BaseConfig'], loc: 'Loc') -> 'ErrorDict': + type_ = get_exc_type(exc.__class__) + msg_template = config.error_msg_templates.get(type_) or getattr(exc, 'msg_template', None) + ctx = exc.__dict__ + if msg_template: + msg = msg_template.format(**ctx) + else: + msg = str(exc) + + d: 'ErrorDict' = {'loc': loc, 'msg': msg, 'type': type_} + + if ctx: + d['ctx'] = ctx + + return d + + +_EXC_TYPE_CACHE: Dict[Type[Exception], str] = {} + + +def get_exc_type(cls: Type[Exception]) -> str: + # slightly more efficient than using lru_cache since we don't need to worry about the cache filling up + try: + return _EXC_TYPE_CACHE[cls] + except KeyError: + r = _get_exc_type(cls) + _EXC_TYPE_CACHE[cls] = r + return r + + +def _get_exc_type(cls: Type[Exception]) -> str: + if issubclass(cls, AssertionError): + return 'assertion_error' + + base_name = 'type_error' if issubclass(cls, TypeError) else 'value_error' + if cls in (TypeError, ValueError): + # just TypeError or ValueError, no extra code + return base_name + + # if it's not a TypeError or ValueError, we just take the lowercase of the exception name + # no chaining or snake case logic, use "code" for more complex error types. + code = getattr(cls, 'code', None) or cls.__name__.replace('Error', '').lower() + return base_name + '.' + code diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/errors.py b/backend/.venv/Lib/site-packages/pydantic/v1/errors.py new file mode 100644 index 0000000..6e86442 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/errors.py @@ -0,0 +1,646 @@ +from decimal import Decimal +from pathlib import Path +from typing import TYPE_CHECKING, Any, Callable, Sequence, Set, Tuple, Type, Union + +from pydantic.v1.typing import display_as_type + +if TYPE_CHECKING: + from pydantic.v1.typing import DictStrAny + +# explicitly state exports to avoid "from pydantic.v1.errors import *" also importing Decimal, Path etc. +__all__ = ( + 'PydanticTypeError', + 'PydanticValueError', + 'ConfigError', + 'MissingError', + 'ExtraError', + 'NoneIsNotAllowedError', + 'NoneIsAllowedError', + 'WrongConstantError', + 'NotNoneError', + 'BoolError', + 'BytesError', + 'DictError', + 'EmailError', + 'UrlError', + 'UrlSchemeError', + 'UrlSchemePermittedError', + 'UrlUserInfoError', + 'UrlHostError', + 'UrlHostTldError', + 'UrlPortError', + 'UrlExtraError', + 'EnumError', + 'IntEnumError', + 'EnumMemberError', + 'IntegerError', + 'FloatError', + 'PathError', + 'PathNotExistsError', + 'PathNotAFileError', + 'PathNotADirectoryError', + 'PyObjectError', + 'SequenceError', + 'ListError', + 'SetError', + 'FrozenSetError', + 'TupleError', + 'TupleLengthError', + 'ListMinLengthError', + 'ListMaxLengthError', + 'ListUniqueItemsError', + 'SetMinLengthError', + 'SetMaxLengthError', + 'FrozenSetMinLengthError', + 'FrozenSetMaxLengthError', + 'AnyStrMinLengthError', + 'AnyStrMaxLengthError', + 'StrError', + 'StrRegexError', + 'NumberNotGtError', + 'NumberNotGeError', + 'NumberNotLtError', + 'NumberNotLeError', + 'NumberNotMultipleError', + 'DecimalError', + 'DecimalIsNotFiniteError', + 'DecimalMaxDigitsError', + 'DecimalMaxPlacesError', + 'DecimalWholeDigitsError', + 'DateTimeError', + 'DateError', + 'DateNotInThePastError', + 'DateNotInTheFutureError', + 'TimeError', + 'DurationError', + 'HashableError', + 'UUIDError', + 'UUIDVersionError', + 'ArbitraryTypeError', + 'ClassError', + 'SubclassError', + 'JsonError', + 'JsonTypeError', + 'PatternError', + 'DataclassTypeError', + 'CallableError', + 'IPvAnyAddressError', + 'IPvAnyInterfaceError', + 'IPvAnyNetworkError', + 'IPv4AddressError', + 'IPv6AddressError', + 'IPv4NetworkError', + 'IPv6NetworkError', + 'IPv4InterfaceError', + 'IPv6InterfaceError', + 'ColorError', + 'StrictBoolError', + 'NotDigitError', + 'LuhnValidationError', + 'InvalidLengthForBrand', + 'InvalidByteSize', + 'InvalidByteSizeUnit', + 'MissingDiscriminator', + 'InvalidDiscriminator', +) + + +def cls_kwargs(cls: Type['PydanticErrorMixin'], ctx: 'DictStrAny') -> 'PydanticErrorMixin': + """ + For built-in exceptions like ValueError or TypeError, we need to implement + __reduce__ to override the default behaviour (instead of __getstate__/__setstate__) + By default pickle protocol 2 calls `cls.__new__(cls, *args)`. + Since we only use kwargs, we need a little constructor to change that. + Note: the callable can't be a lambda as pickle looks in the namespace to find it + """ + return cls(**ctx) + + +class PydanticErrorMixin: + code: str + msg_template: str + + def __init__(self, **ctx: Any) -> None: + self.__dict__ = ctx + + def __str__(self) -> str: + return self.msg_template.format(**self.__dict__) + + def __reduce__(self) -> Tuple[Callable[..., 'PydanticErrorMixin'], Tuple[Type['PydanticErrorMixin'], 'DictStrAny']]: + return cls_kwargs, (self.__class__, self.__dict__) + + +class PydanticTypeError(PydanticErrorMixin, TypeError): + pass + + +class PydanticValueError(PydanticErrorMixin, ValueError): + pass + + +class ConfigError(RuntimeError): + pass + + +class MissingError(PydanticValueError): + msg_template = 'field required' + + +class ExtraError(PydanticValueError): + msg_template = 'extra fields not permitted' + + +class NoneIsNotAllowedError(PydanticTypeError): + code = 'none.not_allowed' + msg_template = 'none is not an allowed value' + + +class NoneIsAllowedError(PydanticTypeError): + code = 'none.allowed' + msg_template = 'value is not none' + + +class WrongConstantError(PydanticValueError): + code = 'const' + + def __str__(self) -> str: + permitted = ', '.join(repr(v) for v in self.permitted) # type: ignore + return f'unexpected value; permitted: {permitted}' + + +class NotNoneError(PydanticTypeError): + code = 'not_none' + msg_template = 'value is not None' + + +class BoolError(PydanticTypeError): + msg_template = 'value could not be parsed to a boolean' + + +class BytesError(PydanticTypeError): + msg_template = 'byte type expected' + + +class DictError(PydanticTypeError): + msg_template = 'value is not a valid dict' + + +class EmailError(PydanticValueError): + msg_template = 'value is not a valid email address' + + +class UrlError(PydanticValueError): + code = 'url' + + +class UrlSchemeError(UrlError): + code = 'url.scheme' + msg_template = 'invalid or missing URL scheme' + + +class UrlSchemePermittedError(UrlError): + code = 'url.scheme' + msg_template = 'URL scheme not permitted' + + def __init__(self, allowed_schemes: Set[str]): + super().__init__(allowed_schemes=allowed_schemes) + + +class UrlUserInfoError(UrlError): + code = 'url.userinfo' + msg_template = 'userinfo required in URL but missing' + + +class UrlHostError(UrlError): + code = 'url.host' + msg_template = 'URL host invalid' + + +class UrlHostTldError(UrlError): + code = 'url.host' + msg_template = 'URL host invalid, top level domain required' + + +class UrlPortError(UrlError): + code = 'url.port' + msg_template = 'URL port invalid, port cannot exceed 65535' + + +class UrlExtraError(UrlError): + code = 'url.extra' + msg_template = 'URL invalid, extra characters found after valid URL: {extra!r}' + + +class EnumMemberError(PydanticTypeError): + code = 'enum' + + def __str__(self) -> str: + permitted = ', '.join(repr(v.value) for v in self.enum_values) # type: ignore + return f'value is not a valid enumeration member; permitted: {permitted}' + + +class IntegerError(PydanticTypeError): + msg_template = 'value is not a valid integer' + + +class FloatError(PydanticTypeError): + msg_template = 'value is not a valid float' + + +class PathError(PydanticTypeError): + msg_template = 'value is not a valid path' + + +class _PathValueError(PydanticValueError): + def __init__(self, *, path: Path) -> None: + super().__init__(path=str(path)) + + +class PathNotExistsError(_PathValueError): + code = 'path.not_exists' + msg_template = 'file or directory at path "{path}" does not exist' + + +class PathNotAFileError(_PathValueError): + code = 'path.not_a_file' + msg_template = 'path "{path}" does not point to a file' + + +class PathNotADirectoryError(_PathValueError): + code = 'path.not_a_directory' + msg_template = 'path "{path}" does not point to a directory' + + +class PyObjectError(PydanticTypeError): + msg_template = 'ensure this value contains valid import path or valid callable: {error_message}' + + +class SequenceError(PydanticTypeError): + msg_template = 'value is not a valid sequence' + + +class IterableError(PydanticTypeError): + msg_template = 'value is not a valid iterable' + + +class ListError(PydanticTypeError): + msg_template = 'value is not a valid list' + + +class SetError(PydanticTypeError): + msg_template = 'value is not a valid set' + + +class FrozenSetError(PydanticTypeError): + msg_template = 'value is not a valid frozenset' + + +class DequeError(PydanticTypeError): + msg_template = 'value is not a valid deque' + + +class TupleError(PydanticTypeError): + msg_template = 'value is not a valid tuple' + + +class TupleLengthError(PydanticValueError): + code = 'tuple.length' + msg_template = 'wrong tuple length {actual_length}, expected {expected_length}' + + def __init__(self, *, actual_length: int, expected_length: int) -> None: + super().__init__(actual_length=actual_length, expected_length=expected_length) + + +class ListMinLengthError(PydanticValueError): + code = 'list.min_items' + msg_template = 'ensure this value has at least {limit_value} items' + + def __init__(self, *, limit_value: int) -> None: + super().__init__(limit_value=limit_value) + + +class ListMaxLengthError(PydanticValueError): + code = 'list.max_items' + msg_template = 'ensure this value has at most {limit_value} items' + + def __init__(self, *, limit_value: int) -> None: + super().__init__(limit_value=limit_value) + + +class ListUniqueItemsError(PydanticValueError): + code = 'list.unique_items' + msg_template = 'the list has duplicated items' + + +class SetMinLengthError(PydanticValueError): + code = 'set.min_items' + msg_template = 'ensure this value has at least {limit_value} items' + + def __init__(self, *, limit_value: int) -> None: + super().__init__(limit_value=limit_value) + + +class SetMaxLengthError(PydanticValueError): + code = 'set.max_items' + msg_template = 'ensure this value has at most {limit_value} items' + + def __init__(self, *, limit_value: int) -> None: + super().__init__(limit_value=limit_value) + + +class FrozenSetMinLengthError(PydanticValueError): + code = 'frozenset.min_items' + msg_template = 'ensure this value has at least {limit_value} items' + + def __init__(self, *, limit_value: int) -> None: + super().__init__(limit_value=limit_value) + + +class FrozenSetMaxLengthError(PydanticValueError): + code = 'frozenset.max_items' + msg_template = 'ensure this value has at most {limit_value} items' + + def __init__(self, *, limit_value: int) -> None: + super().__init__(limit_value=limit_value) + + +class AnyStrMinLengthError(PydanticValueError): + code = 'any_str.min_length' + msg_template = 'ensure this value has at least {limit_value} characters' + + def __init__(self, *, limit_value: int) -> None: + super().__init__(limit_value=limit_value) + + +class AnyStrMaxLengthError(PydanticValueError): + code = 'any_str.max_length' + msg_template = 'ensure this value has at most {limit_value} characters' + + def __init__(self, *, limit_value: int) -> None: + super().__init__(limit_value=limit_value) + + +class StrError(PydanticTypeError): + msg_template = 'str type expected' + + +class StrRegexError(PydanticValueError): + code = 'str.regex' + msg_template = 'string does not match regex "{pattern}"' + + def __init__(self, *, pattern: str) -> None: + super().__init__(pattern=pattern) + + +class _NumberBoundError(PydanticValueError): + def __init__(self, *, limit_value: Union[int, float, Decimal]) -> None: + super().__init__(limit_value=limit_value) + + +class NumberNotGtError(_NumberBoundError): + code = 'number.not_gt' + msg_template = 'ensure this value is greater than {limit_value}' + + +class NumberNotGeError(_NumberBoundError): + code = 'number.not_ge' + msg_template = 'ensure this value is greater than or equal to {limit_value}' + + +class NumberNotLtError(_NumberBoundError): + code = 'number.not_lt' + msg_template = 'ensure this value is less than {limit_value}' + + +class NumberNotLeError(_NumberBoundError): + code = 'number.not_le' + msg_template = 'ensure this value is less than or equal to {limit_value}' + + +class NumberNotFiniteError(PydanticValueError): + code = 'number.not_finite_number' + msg_template = 'ensure this value is a finite number' + + +class NumberNotMultipleError(PydanticValueError): + code = 'number.not_multiple' + msg_template = 'ensure this value is a multiple of {multiple_of}' + + def __init__(self, *, multiple_of: Union[int, float, Decimal]) -> None: + super().__init__(multiple_of=multiple_of) + + +class DecimalError(PydanticTypeError): + msg_template = 'value is not a valid decimal' + + +class DecimalIsNotFiniteError(PydanticValueError): + code = 'decimal.not_finite' + msg_template = 'value is not a valid decimal' + + +class DecimalMaxDigitsError(PydanticValueError): + code = 'decimal.max_digits' + msg_template = 'ensure that there are no more than {max_digits} digits in total' + + def __init__(self, *, max_digits: int) -> None: + super().__init__(max_digits=max_digits) + + +class DecimalMaxPlacesError(PydanticValueError): + code = 'decimal.max_places' + msg_template = 'ensure that there are no more than {decimal_places} decimal places' + + def __init__(self, *, decimal_places: int) -> None: + super().__init__(decimal_places=decimal_places) + + +class DecimalWholeDigitsError(PydanticValueError): + code = 'decimal.whole_digits' + msg_template = 'ensure that there are no more than {whole_digits} digits before the decimal point' + + def __init__(self, *, whole_digits: int) -> None: + super().__init__(whole_digits=whole_digits) + + +class DateTimeError(PydanticValueError): + msg_template = 'invalid datetime format' + + +class DateError(PydanticValueError): + msg_template = 'invalid date format' + + +class DateNotInThePastError(PydanticValueError): + code = 'date.not_in_the_past' + msg_template = 'date is not in the past' + + +class DateNotInTheFutureError(PydanticValueError): + code = 'date.not_in_the_future' + msg_template = 'date is not in the future' + + +class TimeError(PydanticValueError): + msg_template = 'invalid time format' + + +class DurationError(PydanticValueError): + msg_template = 'invalid duration format' + + +class HashableError(PydanticTypeError): + msg_template = 'value is not a valid hashable' + + +class UUIDError(PydanticTypeError): + msg_template = 'value is not a valid uuid' + + +class UUIDVersionError(PydanticValueError): + code = 'uuid.version' + msg_template = 'uuid version {required_version} expected' + + def __init__(self, *, required_version: int) -> None: + super().__init__(required_version=required_version) + + +class ArbitraryTypeError(PydanticTypeError): + code = 'arbitrary_type' + msg_template = 'instance of {expected_arbitrary_type} expected' + + def __init__(self, *, expected_arbitrary_type: Type[Any]) -> None: + super().__init__(expected_arbitrary_type=display_as_type(expected_arbitrary_type)) + + +class ClassError(PydanticTypeError): + code = 'class' + msg_template = 'a class is expected' + + +class SubclassError(PydanticTypeError): + code = 'subclass' + msg_template = 'subclass of {expected_class} expected' + + def __init__(self, *, expected_class: Type[Any]) -> None: + super().__init__(expected_class=display_as_type(expected_class)) + + +class JsonError(PydanticValueError): + msg_template = 'Invalid JSON' + + +class JsonTypeError(PydanticTypeError): + code = 'json' + msg_template = 'JSON object must be str, bytes or bytearray' + + +class PatternError(PydanticValueError): + code = 'regex_pattern' + msg_template = 'Invalid regular expression' + + +class DataclassTypeError(PydanticTypeError): + code = 'dataclass' + msg_template = 'instance of {class_name}, tuple or dict expected' + + +class CallableError(PydanticTypeError): + msg_template = '{value} is not callable' + + +class EnumError(PydanticTypeError): + code = 'enum_instance' + msg_template = '{value} is not a valid Enum instance' + + +class IntEnumError(PydanticTypeError): + code = 'int_enum_instance' + msg_template = '{value} is not a valid IntEnum instance' + + +class IPvAnyAddressError(PydanticValueError): + msg_template = 'value is not a valid IPv4 or IPv6 address' + + +class IPvAnyInterfaceError(PydanticValueError): + msg_template = 'value is not a valid IPv4 or IPv6 interface' + + +class IPvAnyNetworkError(PydanticValueError): + msg_template = 'value is not a valid IPv4 or IPv6 network' + + +class IPv4AddressError(PydanticValueError): + msg_template = 'value is not a valid IPv4 address' + + +class IPv6AddressError(PydanticValueError): + msg_template = 'value is not a valid IPv6 address' + + +class IPv4NetworkError(PydanticValueError): + msg_template = 'value is not a valid IPv4 network' + + +class IPv6NetworkError(PydanticValueError): + msg_template = 'value is not a valid IPv6 network' + + +class IPv4InterfaceError(PydanticValueError): + msg_template = 'value is not a valid IPv4 interface' + + +class IPv6InterfaceError(PydanticValueError): + msg_template = 'value is not a valid IPv6 interface' + + +class ColorError(PydanticValueError): + msg_template = 'value is not a valid color: {reason}' + + +class StrictBoolError(PydanticValueError): + msg_template = 'value is not a valid boolean' + + +class NotDigitError(PydanticValueError): + code = 'payment_card_number.digits' + msg_template = 'card number is not all digits' + + +class LuhnValidationError(PydanticValueError): + code = 'payment_card_number.luhn_check' + msg_template = 'card number is not luhn valid' + + +class InvalidLengthForBrand(PydanticValueError): + code = 'payment_card_number.invalid_length_for_brand' + msg_template = 'Length for a {brand} card must be {required_length}' + + +class InvalidByteSize(PydanticValueError): + msg_template = 'could not parse value and unit from byte string' + + +class InvalidByteSizeUnit(PydanticValueError): + msg_template = 'could not interpret byte unit: {unit}' + + +class MissingDiscriminator(PydanticValueError): + code = 'discriminated_union.missing_discriminator' + msg_template = 'Discriminator {discriminator_key!r} is missing in value' + + +class InvalidDiscriminator(PydanticValueError): + code = 'discriminated_union.invalid_discriminator' + msg_template = ( + 'No match for discriminator {discriminator_key!r} and value {discriminator_value!r} ' + '(allowed values: {allowed_values})' + ) + + def __init__(self, *, discriminator_key: str, discriminator_value: Any, allowed_values: Sequence[Any]) -> None: + super().__init__( + discriminator_key=discriminator_key, + discriminator_value=discriminator_value, + allowed_values=', '.join(map(repr, allowed_values)), + ) diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/fields.py b/backend/.venv/Lib/site-packages/pydantic/v1/fields.py new file mode 100644 index 0000000..002b60c --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/fields.py @@ -0,0 +1,1253 @@ +import copy +import re +from collections import Counter as CollectionCounter, defaultdict, deque +from collections.abc import Callable, Hashable as CollectionsHashable, Iterable as CollectionsIterable +from typing import ( + TYPE_CHECKING, + Any, + Counter, + DefaultDict, + Deque, + Dict, + ForwardRef, + FrozenSet, + Generator, + Iterable, + Iterator, + List, + Mapping, + Optional, + Pattern, + Sequence, + Set, + Tuple, + Type, + TypeVar, + Union, +) + +from typing_extensions import Annotated, Final + +from pydantic.v1 import errors as errors_ +from pydantic.v1.class_validators import Validator, make_generic_validator, prep_validators +from pydantic.v1.error_wrappers import ErrorWrapper +from pydantic.v1.errors import ConfigError, InvalidDiscriminator, MissingDiscriminator, NoneIsNotAllowedError +from pydantic.v1.types import Json, JsonWrapper +from pydantic.v1.typing import ( + NoArgAnyCallable, + convert_generics, + display_as_type, + get_args, + get_origin, + is_finalvar, + is_literal_type, + is_new_type, + is_none_type, + is_typeddict, + is_typeddict_special, + is_union, + new_type_supertype, +) +from pydantic.v1.utils import ( + PyObjectStr, + Representation, + ValueItems, + get_discriminator_alias_and_values, + get_unique_discriminator_alias, + lenient_isinstance, + lenient_issubclass, + sequence_like, + smart_deepcopy, +) +from pydantic.v1.validators import constant_validator, dict_validator, find_validators, validate_json + +Required: Any = Ellipsis + +T = TypeVar('T') + + +class UndefinedType: + def __repr__(self) -> str: + return 'PydanticUndefined' + + def __copy__(self: T) -> T: + return self + + def __reduce__(self) -> str: + return 'Undefined' + + def __deepcopy__(self: T, _: Any) -> T: + return self + + +Undefined = UndefinedType() + +if TYPE_CHECKING: + from pydantic.v1.class_validators import ValidatorsList + from pydantic.v1.config import BaseConfig + from pydantic.v1.error_wrappers import ErrorList + from pydantic.v1.types import ModelOrDc + from pydantic.v1.typing import AbstractSetIntStr, MappingIntStrAny, ReprArgs + + ValidateReturn = Tuple[Optional[Any], Optional[ErrorList]] + LocStr = Union[Tuple[Union[int, str], ...], str] + BoolUndefined = Union[bool, UndefinedType] + + +class FieldInfo(Representation): + """ + Captures extra information about a field. + """ + + __slots__ = ( + 'default', + 'default_factory', + 'alias', + 'alias_priority', + 'title', + 'description', + 'exclude', + 'include', + 'const', + 'gt', + 'ge', + 'lt', + 'le', + 'multiple_of', + 'allow_inf_nan', + 'max_digits', + 'decimal_places', + 'min_items', + 'max_items', + 'unique_items', + 'min_length', + 'max_length', + 'allow_mutation', + 'repr', + 'regex', + 'discriminator', + 'extra', + ) + + # field constraints with the default value, it's also used in update_from_config below + __field_constraints__ = { + 'min_length': None, + 'max_length': None, + 'regex': None, + 'gt': None, + 'lt': None, + 'ge': None, + 'le': None, + 'multiple_of': None, + 'allow_inf_nan': None, + 'max_digits': None, + 'decimal_places': None, + 'min_items': None, + 'max_items': None, + 'unique_items': None, + 'allow_mutation': True, + } + + def __init__(self, default: Any = Undefined, **kwargs: Any) -> None: + self.default = default + self.default_factory = kwargs.pop('default_factory', None) + self.alias = kwargs.pop('alias', None) + self.alias_priority = kwargs.pop('alias_priority', 2 if self.alias is not None else None) + self.title = kwargs.pop('title', None) + self.description = kwargs.pop('description', None) + self.exclude = kwargs.pop('exclude', None) + self.include = kwargs.pop('include', None) + self.const = kwargs.pop('const', None) + self.gt = kwargs.pop('gt', None) + self.ge = kwargs.pop('ge', None) + self.lt = kwargs.pop('lt', None) + self.le = kwargs.pop('le', None) + self.multiple_of = kwargs.pop('multiple_of', None) + self.allow_inf_nan = kwargs.pop('allow_inf_nan', None) + self.max_digits = kwargs.pop('max_digits', None) + self.decimal_places = kwargs.pop('decimal_places', None) + self.min_items = kwargs.pop('min_items', None) + self.max_items = kwargs.pop('max_items', None) + self.unique_items = kwargs.pop('unique_items', None) + self.min_length = kwargs.pop('min_length', None) + self.max_length = kwargs.pop('max_length', None) + self.allow_mutation = kwargs.pop('allow_mutation', True) + self.regex = kwargs.pop('regex', None) + self.discriminator = kwargs.pop('discriminator', None) + self.repr = kwargs.pop('repr', True) + self.extra = kwargs + + def __repr_args__(self) -> 'ReprArgs': + field_defaults_to_hide: Dict[str, Any] = { + 'repr': True, + **self.__field_constraints__, + } + + attrs = ((s, getattr(self, s)) for s in self.__slots__) + return [(a, v) for a, v in attrs if v != field_defaults_to_hide.get(a, None)] + + def get_constraints(self) -> Set[str]: + """ + Gets the constraints set on the field by comparing the constraint value with its default value + + :return: the constraints set on field_info + """ + return {attr for attr, default in self.__field_constraints__.items() if getattr(self, attr) != default} + + def update_from_config(self, from_config: Dict[str, Any]) -> None: + """ + Update this FieldInfo based on a dict from get_field_info, only fields which have not been set are dated. + """ + for attr_name, value in from_config.items(): + try: + current_value = getattr(self, attr_name) + except AttributeError: + # attr_name is not an attribute of FieldInfo, it should therefore be added to extra + # (except if extra already has this value!) + self.extra.setdefault(attr_name, value) + else: + if current_value is self.__field_constraints__.get(attr_name, None): + setattr(self, attr_name, value) + elif attr_name == 'exclude': + self.exclude = ValueItems.merge(value, current_value) + elif attr_name == 'include': + self.include = ValueItems.merge(value, current_value, intersect=True) + + def _validate(self) -> None: + if self.default is not Undefined and self.default_factory is not None: + raise ValueError('cannot specify both default and default_factory') + + +def Field( + default: Any = Undefined, + *, + default_factory: Optional[NoArgAnyCallable] = None, + alias: Optional[str] = None, + title: Optional[str] = None, + description: Optional[str] = None, + exclude: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny', Any]] = None, + include: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny', Any]] = None, + const: Optional[bool] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + multiple_of: Optional[float] = None, + allow_inf_nan: Optional[bool] = None, + max_digits: Optional[int] = None, + decimal_places: Optional[int] = None, + min_items: Optional[int] = None, + max_items: Optional[int] = None, + unique_items: Optional[bool] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + allow_mutation: bool = True, + regex: Optional[str] = None, + discriminator: Optional[str] = None, + repr: bool = True, + **extra: Any, +) -> Any: + """ + Used to provide extra information about a field, either for the model schema or complex validation. Some arguments + apply only to number fields (``int``, ``float``, ``Decimal``) and some apply only to ``str``. + + :param default: since this is replacing the field’s default, its first argument is used + to set the default, use ellipsis (``...``) to indicate the field is required + :param default_factory: callable that will be called when a default value is needed for this field + If both `default` and `default_factory` are set, an error is raised. + :param alias: the public name of the field + :param title: can be any string, used in the schema + :param description: can be any string, used in the schema + :param exclude: exclude this field while dumping. + Takes same values as the ``include`` and ``exclude`` arguments on the ``.dict`` method. + :param include: include this field while dumping. + Takes same values as the ``include`` and ``exclude`` arguments on the ``.dict`` method. + :param const: this field is required and *must* take it's default value + :param gt: only applies to numbers, requires the field to be "greater than". The schema + will have an ``exclusiveMinimum`` validation keyword + :param ge: only applies to numbers, requires the field to be "greater than or equal to". The + schema will have a ``minimum`` validation keyword + :param lt: only applies to numbers, requires the field to be "less than". The schema + will have an ``exclusiveMaximum`` validation keyword + :param le: only applies to numbers, requires the field to be "less than or equal to". The + schema will have a ``maximum`` validation keyword + :param multiple_of: only applies to numbers, requires the field to be "a multiple of". The + schema will have a ``multipleOf`` validation keyword + :param allow_inf_nan: only applies to numbers, allows the field to be NaN or infinity (+inf or -inf), + which is a valid Python float. Default True, set to False for compatibility with JSON. + :param max_digits: only applies to Decimals, requires the field to have a maximum number + of digits within the decimal. It does not include a zero before the decimal point or trailing decimal zeroes. + :param decimal_places: only applies to Decimals, requires the field to have at most a number of decimal places + allowed. It does not include trailing decimal zeroes. + :param min_items: only applies to lists, requires the field to have a minimum number of + elements. The schema will have a ``minItems`` validation keyword + :param max_items: only applies to lists, requires the field to have a maximum number of + elements. The schema will have a ``maxItems`` validation keyword + :param unique_items: only applies to lists, requires the field not to have duplicated + elements. The schema will have a ``uniqueItems`` validation keyword + :param min_length: only applies to strings, requires the field to have a minimum length. The + schema will have a ``minLength`` validation keyword + :param max_length: only applies to strings, requires the field to have a maximum length. The + schema will have a ``maxLength`` validation keyword + :param allow_mutation: a boolean which defaults to True. When False, the field raises a TypeError if the field is + assigned on an instance. The BaseModel Config must set validate_assignment to True + :param regex: only applies to strings, requires the field match against a regular expression + pattern string. The schema will have a ``pattern`` validation keyword + :param discriminator: only useful with a (discriminated a.k.a. tagged) `Union` of sub models with a common field. + The `discriminator` is the name of this common field to shorten validation and improve generated schema + :param repr: show this field in the representation + :param **extra: any additional keyword arguments will be added as is to the schema + """ + field_info = FieldInfo( + default, + default_factory=default_factory, + alias=alias, + title=title, + description=description, + exclude=exclude, + include=include, + const=const, + gt=gt, + ge=ge, + lt=lt, + le=le, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, + min_items=min_items, + max_items=max_items, + unique_items=unique_items, + min_length=min_length, + max_length=max_length, + allow_mutation=allow_mutation, + regex=regex, + discriminator=discriminator, + repr=repr, + **extra, + ) + field_info._validate() + return field_info + + +# used to be an enum but changed to int's for small performance improvement as less access overhead +SHAPE_SINGLETON = 1 +SHAPE_LIST = 2 +SHAPE_SET = 3 +SHAPE_MAPPING = 4 +SHAPE_TUPLE = 5 +SHAPE_TUPLE_ELLIPSIS = 6 +SHAPE_SEQUENCE = 7 +SHAPE_FROZENSET = 8 +SHAPE_ITERABLE = 9 +SHAPE_GENERIC = 10 +SHAPE_DEQUE = 11 +SHAPE_DICT = 12 +SHAPE_DEFAULTDICT = 13 +SHAPE_COUNTER = 14 +SHAPE_NAME_LOOKUP = { + SHAPE_LIST: 'List[{}]', + SHAPE_SET: 'Set[{}]', + SHAPE_TUPLE_ELLIPSIS: 'Tuple[{}, ...]', + SHAPE_SEQUENCE: 'Sequence[{}]', + SHAPE_FROZENSET: 'FrozenSet[{}]', + SHAPE_ITERABLE: 'Iterable[{}]', + SHAPE_DEQUE: 'Deque[{}]', + SHAPE_DICT: 'Dict[{}]', + SHAPE_DEFAULTDICT: 'DefaultDict[{}]', + SHAPE_COUNTER: 'Counter[{}]', +} + +MAPPING_LIKE_SHAPES: Set[int] = {SHAPE_DEFAULTDICT, SHAPE_DICT, SHAPE_MAPPING, SHAPE_COUNTER} + + +class ModelField(Representation): + __slots__ = ( + 'type_', + 'outer_type_', + 'annotation', + 'sub_fields', + 'sub_fields_mapping', + 'key_field', + 'validators', + 'pre_validators', + 'post_validators', + 'default', + 'default_factory', + 'required', + 'final', + 'model_config', + 'name', + 'alias', + 'has_alias', + 'field_info', + 'discriminator_key', + 'discriminator_alias', + 'validate_always', + 'allow_none', + 'shape', + 'class_validators', + 'parse_json', + ) + + def __init__( + self, + *, + name: str, + type_: Type[Any], + class_validators: Optional[Dict[str, Validator]], + model_config: Type['BaseConfig'], + default: Any = None, + default_factory: Optional[NoArgAnyCallable] = None, + required: 'BoolUndefined' = Undefined, + final: bool = False, + alias: Optional[str] = None, + field_info: Optional[FieldInfo] = None, + ) -> None: + self.name: str = name + self.has_alias: bool = alias is not None + self.alias: str = alias if alias is not None else name + self.annotation = type_ + self.type_: Any = convert_generics(type_) + self.outer_type_: Any = type_ + self.class_validators = class_validators or {} + self.default: Any = default + self.default_factory: Optional[NoArgAnyCallable] = default_factory + self.required: 'BoolUndefined' = required + self.final: bool = final + self.model_config = model_config + self.field_info: FieldInfo = field_info or FieldInfo(default) + self.discriminator_key: Optional[str] = self.field_info.discriminator + self.discriminator_alias: Optional[str] = self.discriminator_key + + self.allow_none: bool = False + self.validate_always: bool = False + self.sub_fields: Optional[List[ModelField]] = None + self.sub_fields_mapping: Optional[Dict[str, 'ModelField']] = None # used for discriminated union + self.key_field: Optional[ModelField] = None + self.validators: 'ValidatorsList' = [] + self.pre_validators: Optional['ValidatorsList'] = None + self.post_validators: Optional['ValidatorsList'] = None + self.parse_json: bool = False + self.shape: int = SHAPE_SINGLETON + self.model_config.prepare_field(self) + self.prepare() + + def get_default(self) -> Any: + return smart_deepcopy(self.default) if self.default_factory is None else self.default_factory() + + @staticmethod + def _get_field_info( + field_name: str, annotation: Any, value: Any, config: Type['BaseConfig'] + ) -> Tuple[FieldInfo, Any]: + """ + Get a FieldInfo from a root typing.Annotated annotation, value, or config default. + + The FieldInfo may be set in typing.Annotated or the value, but not both. If neither contain + a FieldInfo, a new one will be created using the config. + + :param field_name: name of the field for use in error messages + :param annotation: a type hint such as `str` or `Annotated[str, Field(..., min_length=5)]` + :param value: the field's assigned value + :param config: the model's config object + :return: the FieldInfo contained in the `annotation`, the value, or a new one from the config. + """ + field_info_from_config = config.get_field_info(field_name) + + field_info = None + if get_origin(annotation) is Annotated: + field_infos = [arg for arg in get_args(annotation)[1:] if isinstance(arg, FieldInfo)] + if len(field_infos) > 1: + raise ValueError(f'cannot specify multiple `Annotated` `Field`s for {field_name!r}') + field_info = next(iter(field_infos), None) + if field_info is not None: + field_info = copy.copy(field_info) + field_info.update_from_config(field_info_from_config) + if field_info.default not in (Undefined, Required): + raise ValueError(f'`Field` default cannot be set in `Annotated` for {field_name!r}') + if value is not Undefined and value is not Required: + # check also `Required` because of `validate_arguments` that sets `...` as default value + field_info.default = value + + if isinstance(value, FieldInfo): + if field_info is not None: + raise ValueError(f'cannot specify `Annotated` and value `Field`s together for {field_name!r}') + field_info = value + field_info.update_from_config(field_info_from_config) + elif field_info is None: + field_info = FieldInfo(value, **field_info_from_config) + value = None if field_info.default_factory is not None else field_info.default + field_info._validate() + return field_info, value + + @classmethod + def infer( + cls, + *, + name: str, + value: Any, + annotation: Any, + class_validators: Optional[Dict[str, Validator]], + config: Type['BaseConfig'], + ) -> 'ModelField': + from pydantic.v1.schema import get_annotation_from_field_info + + field_info, value = cls._get_field_info(name, annotation, value, config) + required: 'BoolUndefined' = Undefined + if value is Required: + required = True + value = None + elif value is not Undefined: + required = False + annotation = get_annotation_from_field_info(annotation, field_info, name, config.validate_assignment) + + return cls( + name=name, + type_=annotation, + alias=field_info.alias, + class_validators=class_validators, + default=value, + default_factory=field_info.default_factory, + required=required, + model_config=config, + field_info=field_info, + ) + + def set_config(self, config: Type['BaseConfig']) -> None: + self.model_config = config + info_from_config = config.get_field_info(self.name) + config.prepare_field(self) + new_alias = info_from_config.get('alias') + new_alias_priority = info_from_config.get('alias_priority') or 0 + if new_alias and new_alias_priority >= (self.field_info.alias_priority or 0): + self.field_info.alias = new_alias + self.field_info.alias_priority = new_alias_priority + self.alias = new_alias + new_exclude = info_from_config.get('exclude') + if new_exclude is not None: + self.field_info.exclude = ValueItems.merge(self.field_info.exclude, new_exclude) + new_include = info_from_config.get('include') + if new_include is not None: + self.field_info.include = ValueItems.merge(self.field_info.include, new_include, intersect=True) + + @property + def alt_alias(self) -> bool: + return self.name != self.alias + + def prepare(self) -> None: + """ + Prepare the field but inspecting self.default, self.type_ etc. + + Note: this method is **not** idempotent (because _type_analysis is not idempotent), + e.g. calling it it multiple times may modify the field and configure it incorrectly. + """ + self._set_default_and_type() + if self.type_.__class__ is ForwardRef or self.type_.__class__ is DeferredType: + # self.type_ is currently a ForwardRef and there's nothing we can do now, + # user will need to call model.update_forward_refs() + return + + self._type_analysis() + if self.required is Undefined: + self.required = True + if self.default is Undefined and self.default_factory is None: + self.default = None + self.populate_validators() + + def _set_default_and_type(self) -> None: + """ + Set the default value, infer the type if needed and check if `None` value is valid. + """ + if self.default_factory is not None: + if self.type_ is Undefined: + raise errors_.ConfigError( + f'you need to set the type of field {self.name!r} when using `default_factory`' + ) + return + + default_value = self.get_default() + + if default_value is not None and self.type_ is Undefined: + self.type_ = default_value.__class__ + self.outer_type_ = self.type_ + self.annotation = self.type_ + + if self.type_ is Undefined: + raise errors_.ConfigError(f'unable to infer type for attribute "{self.name}"') + + if self.required is False and default_value is None: + self.allow_none = True + + def _type_analysis(self) -> None: # noqa: C901 (ignore complexity) + # typing interface is horrible, we have to do some ugly checks + if lenient_issubclass(self.type_, JsonWrapper): + self.type_ = self.type_.inner_type + self.parse_json = True + elif lenient_issubclass(self.type_, Json): + self.type_ = Any + self.parse_json = True + elif isinstance(self.type_, TypeVar): + if self.type_.__bound__: + self.type_ = self.type_.__bound__ + elif self.type_.__constraints__: + self.type_ = Union[self.type_.__constraints__] + else: + self.type_ = Any + elif is_new_type(self.type_): + self.type_ = new_type_supertype(self.type_) + + if self.type_ is Any or self.type_ is object: + if self.required is Undefined: + self.required = False + self.allow_none = True + return + elif self.type_ is Pattern or self.type_ is re.Pattern: + # python 3.7 only, Pattern is a typing object but without sub fields + return + elif is_literal_type(self.type_): + return + elif is_typeddict(self.type_): + return + + if is_finalvar(self.type_): + self.final = True + + if self.type_ is Final: + self.type_ = Any + else: + self.type_ = get_args(self.type_)[0] + + self._type_analysis() + return + + origin = get_origin(self.type_) + + if origin is Annotated or is_typeddict_special(origin): + self.type_ = get_args(self.type_)[0] + self._type_analysis() + return + + if self.discriminator_key is not None and not is_union(origin): + raise TypeError('`discriminator` can only be used with `Union` type with more than one variant') + + # add extra check for `collections.abc.Hashable` for python 3.10+ where origin is not `None` + if origin is None or origin is CollectionsHashable: + # field is not "typing" object eg. Union, Dict, List etc. + # allow None for virtual superclasses of NoneType, e.g. Hashable + if isinstance(self.type_, type) and isinstance(None, self.type_): + self.allow_none = True + return + elif origin is Callable: + return + elif is_union(origin): + types_ = [] + for type_ in get_args(self.type_): + if is_none_type(type_) or type_ is Any or type_ is object: + if self.required is Undefined: + self.required = False + self.allow_none = True + if is_none_type(type_): + continue + types_.append(type_) + + if len(types_) == 1: + # Optional[] + self.type_ = types_[0] + # this is the one case where the "outer type" isn't just the original type + self.outer_type_ = self.type_ + # re-run to correctly interpret the new self.type_ + self._type_analysis() + else: + self.sub_fields = [self._create_sub_type(t, f'{self.name}_{display_as_type(t)}') for t in types_] + + if self.discriminator_key is not None: + self.prepare_discriminated_union_sub_fields() + return + elif issubclass(origin, Tuple): # type: ignore + # origin == Tuple without item type + args = get_args(self.type_) + if not args: # plain tuple + self.type_ = Any + self.shape = SHAPE_TUPLE_ELLIPSIS + elif len(args) == 2 and args[1] is Ellipsis: # e.g. Tuple[int, ...] + self.type_ = args[0] + self.shape = SHAPE_TUPLE_ELLIPSIS + self.sub_fields = [self._create_sub_type(args[0], f'{self.name}_0')] + elif args == ((),): # Tuple[()] means empty tuple + self.shape = SHAPE_TUPLE + self.type_ = Any + self.sub_fields = [] + else: + self.shape = SHAPE_TUPLE + self.sub_fields = [self._create_sub_type(t, f'{self.name}_{i}') for i, t in enumerate(args)] + return + elif issubclass(origin, List): + # Create self validators + get_validators = getattr(self.type_, '__get_validators__', None) + if get_validators: + self.class_validators.update( + {f'list_{i}': Validator(validator, pre=True) for i, validator in enumerate(get_validators())} + ) + + self.type_ = get_args(self.type_)[0] + self.shape = SHAPE_LIST + elif issubclass(origin, Set): + # Create self validators + get_validators = getattr(self.type_, '__get_validators__', None) + if get_validators: + self.class_validators.update( + {f'set_{i}': Validator(validator, pre=True) for i, validator in enumerate(get_validators())} + ) + + self.type_ = get_args(self.type_)[0] + self.shape = SHAPE_SET + elif issubclass(origin, FrozenSet): + # Create self validators + get_validators = getattr(self.type_, '__get_validators__', None) + if get_validators: + self.class_validators.update( + {f'frozenset_{i}': Validator(validator, pre=True) for i, validator in enumerate(get_validators())} + ) + + self.type_ = get_args(self.type_)[0] + self.shape = SHAPE_FROZENSET + elif issubclass(origin, Deque): + self.type_ = get_args(self.type_)[0] + self.shape = SHAPE_DEQUE + elif issubclass(origin, Sequence): + self.type_ = get_args(self.type_)[0] + self.shape = SHAPE_SEQUENCE + # priority to most common mapping: dict + elif origin is dict or origin is Dict: + self.key_field = self._create_sub_type(get_args(self.type_)[0], 'key_' + self.name, for_keys=True) + self.type_ = get_args(self.type_)[1] + self.shape = SHAPE_DICT + elif issubclass(origin, DefaultDict): + self.key_field = self._create_sub_type(get_args(self.type_)[0], 'key_' + self.name, for_keys=True) + self.type_ = get_args(self.type_)[1] + self.shape = SHAPE_DEFAULTDICT + elif issubclass(origin, Counter): + self.key_field = self._create_sub_type(get_args(self.type_)[0], 'key_' + self.name, for_keys=True) + self.type_ = int + self.shape = SHAPE_COUNTER + elif issubclass(origin, Mapping): + self.key_field = self._create_sub_type(get_args(self.type_)[0], 'key_' + self.name, for_keys=True) + self.type_ = get_args(self.type_)[1] + self.shape = SHAPE_MAPPING + # Equality check as almost everything inherits form Iterable, including str + # check for Iterable and CollectionsIterable, as it could receive one even when declared with the other + elif origin in {Iterable, CollectionsIterable}: + self.type_ = get_args(self.type_)[0] + self.shape = SHAPE_ITERABLE + self.sub_fields = [self._create_sub_type(self.type_, f'{self.name}_type')] + elif issubclass(origin, Type): # type: ignore + return + elif hasattr(origin, '__get_validators__') or self.model_config.arbitrary_types_allowed: + # Is a Pydantic-compatible generic that handles itself + # or we have arbitrary_types_allowed = True + self.shape = SHAPE_GENERIC + self.sub_fields = [self._create_sub_type(t, f'{self.name}_{i}') for i, t in enumerate(get_args(self.type_))] + self.type_ = origin + return + else: + raise TypeError(f'Fields of type "{origin}" are not supported.') + + # type_ has been refined eg. as the type of a List and sub_fields needs to be populated + self.sub_fields = [self._create_sub_type(self.type_, '_' + self.name)] + + def prepare_discriminated_union_sub_fields(self) -> None: + """ + Prepare the mapping -> and update `sub_fields` + Note that this process can be aborted if a `ForwardRef` is encountered + """ + assert self.discriminator_key is not None + + if self.type_.__class__ is DeferredType: + return + + assert self.sub_fields is not None + sub_fields_mapping: Dict[str, 'ModelField'] = {} + all_aliases: Set[str] = set() + + for sub_field in self.sub_fields: + t = sub_field.type_ + if t.__class__ is ForwardRef: + # Stopping everything...will need to call `update_forward_refs` + return + + alias, discriminator_values = get_discriminator_alias_and_values(t, self.discriminator_key) + all_aliases.add(alias) + for discriminator_value in discriminator_values: + sub_fields_mapping[discriminator_value] = sub_field + + self.sub_fields_mapping = sub_fields_mapping + self.discriminator_alias = get_unique_discriminator_alias(all_aliases, self.discriminator_key) + + def _create_sub_type(self, type_: Type[Any], name: str, *, for_keys: bool = False) -> 'ModelField': + if for_keys: + class_validators = None + else: + # validators for sub items should not have `each_item` as we want to check only the first sublevel + class_validators = { + k: Validator( + func=v.func, + pre=v.pre, + each_item=False, + always=v.always, + check_fields=v.check_fields, + skip_on_failure=v.skip_on_failure, + ) + for k, v in self.class_validators.items() + if v.each_item + } + + field_info, _ = self._get_field_info(name, type_, None, self.model_config) + + return self.__class__( + type_=type_, + name=name, + class_validators=class_validators, + model_config=self.model_config, + field_info=field_info, + ) + + def populate_validators(self) -> None: + """ + Prepare self.pre_validators, self.validators, and self.post_validators based on self.type_'s __get_validators__ + and class validators. This method should be idempotent, e.g. it should be safe to call multiple times + without mis-configuring the field. + """ + self.validate_always = getattr(self.type_, 'validate_always', False) or any( + v.always for v in self.class_validators.values() + ) + + class_validators_ = self.class_validators.values() + if not self.sub_fields or self.shape == SHAPE_GENERIC: + get_validators = getattr(self.type_, '__get_validators__', None) + v_funcs = ( + *[v.func for v in class_validators_ if v.each_item and v.pre], + *(get_validators() if get_validators else list(find_validators(self.type_, self.model_config))), + *[v.func for v in class_validators_ if v.each_item and not v.pre], + ) + self.validators = prep_validators(v_funcs) + + self.pre_validators = [] + self.post_validators = [] + + if self.field_info and self.field_info.const: + self.post_validators.append(make_generic_validator(constant_validator)) + + if class_validators_: + self.pre_validators += prep_validators(v.func for v in class_validators_ if not v.each_item and v.pre) + self.post_validators += prep_validators(v.func for v in class_validators_ if not v.each_item and not v.pre) + + if self.parse_json: + self.pre_validators.append(make_generic_validator(validate_json)) + + self.pre_validators = self.pre_validators or None + self.post_validators = self.post_validators or None + + def validate( + self, v: Any, values: Dict[str, Any], *, loc: 'LocStr', cls: Optional['ModelOrDc'] = None + ) -> 'ValidateReturn': + assert self.type_.__class__ is not DeferredType + + if self.type_.__class__ is ForwardRef: + assert cls is not None + raise ConfigError( + f'field "{self.name}" not yet prepared so type is still a ForwardRef, ' + f'you might need to call {cls.__name__}.update_forward_refs().' + ) + + errors: Optional['ErrorList'] + if self.pre_validators: + v, errors = self._apply_validators(v, values, loc, cls, self.pre_validators) + if errors: + return v, errors + + if v is None: + if is_none_type(self.type_): + # keep validating + pass + elif self.allow_none: + if self.post_validators: + return self._apply_validators(v, values, loc, cls, self.post_validators) + else: + return None, None + else: + return v, ErrorWrapper(NoneIsNotAllowedError(), loc) + + if self.shape == SHAPE_SINGLETON: + v, errors = self._validate_singleton(v, values, loc, cls) + elif self.shape in MAPPING_LIKE_SHAPES: + v, errors = self._validate_mapping_like(v, values, loc, cls) + elif self.shape == SHAPE_TUPLE: + v, errors = self._validate_tuple(v, values, loc, cls) + elif self.shape == SHAPE_ITERABLE: + v, errors = self._validate_iterable(v, values, loc, cls) + elif self.shape == SHAPE_GENERIC: + v, errors = self._apply_validators(v, values, loc, cls, self.validators) + else: + # sequence, list, set, generator, tuple with ellipsis, frozen set + v, errors = self._validate_sequence_like(v, values, loc, cls) + + if not errors and self.post_validators: + v, errors = self._apply_validators(v, values, loc, cls, self.post_validators) + return v, errors + + def _validate_sequence_like( # noqa: C901 (ignore complexity) + self, v: Any, values: Dict[str, Any], loc: 'LocStr', cls: Optional['ModelOrDc'] + ) -> 'ValidateReturn': + """ + Validate sequence-like containers: lists, tuples, sets and generators + Note that large if-else blocks are necessary to enable Cython + optimization, which is why we disable the complexity check above. + """ + if not sequence_like(v): + e: errors_.PydanticTypeError + if self.shape == SHAPE_LIST: + e = errors_.ListError() + elif self.shape in (SHAPE_TUPLE, SHAPE_TUPLE_ELLIPSIS): + e = errors_.TupleError() + elif self.shape == SHAPE_SET: + e = errors_.SetError() + elif self.shape == SHAPE_FROZENSET: + e = errors_.FrozenSetError() + else: + e = errors_.SequenceError() + return v, ErrorWrapper(e, loc) + + loc = loc if isinstance(loc, tuple) else (loc,) + result = [] + errors: List[ErrorList] = [] + for i, v_ in enumerate(v): + v_loc = *loc, i + r, ee = self._validate_singleton(v_, values, v_loc, cls) + if ee: + errors.append(ee) + else: + result.append(r) + + if errors: + return v, errors + + converted: Union[List[Any], Set[Any], FrozenSet[Any], Tuple[Any, ...], Iterator[Any], Deque[Any]] = result + + if self.shape == SHAPE_SET: + converted = set(result) + elif self.shape == SHAPE_FROZENSET: + converted = frozenset(result) + elif self.shape == SHAPE_TUPLE_ELLIPSIS: + converted = tuple(result) + elif self.shape == SHAPE_DEQUE: + converted = deque(result, maxlen=getattr(v, 'maxlen', None)) + elif self.shape == SHAPE_SEQUENCE: + if isinstance(v, tuple): + converted = tuple(result) + elif isinstance(v, set): + converted = set(result) + elif isinstance(v, Generator): + converted = iter(result) + elif isinstance(v, deque): + converted = deque(result, maxlen=getattr(v, 'maxlen', None)) + return converted, None + + def _validate_iterable( + self, v: Any, values: Dict[str, Any], loc: 'LocStr', cls: Optional['ModelOrDc'] + ) -> 'ValidateReturn': + """ + Validate Iterables. + + This intentionally doesn't validate values to allow infinite generators. + """ + + try: + iterable = iter(v) + except TypeError: + return v, ErrorWrapper(errors_.IterableError(), loc) + return iterable, None + + def _validate_tuple( + self, v: Any, values: Dict[str, Any], loc: 'LocStr', cls: Optional['ModelOrDc'] + ) -> 'ValidateReturn': + e: Optional[Exception] = None + if not sequence_like(v): + e = errors_.TupleError() + else: + actual_length, expected_length = len(v), len(self.sub_fields) # type: ignore + if actual_length != expected_length: + e = errors_.TupleLengthError(actual_length=actual_length, expected_length=expected_length) + + if e: + return v, ErrorWrapper(e, loc) + + loc = loc if isinstance(loc, tuple) else (loc,) + result = [] + errors: List[ErrorList] = [] + for i, (v_, field) in enumerate(zip(v, self.sub_fields)): # type: ignore + v_loc = *loc, i + r, ee = field.validate(v_, values, loc=v_loc, cls=cls) + if ee: + errors.append(ee) + else: + result.append(r) + + if errors: + return v, errors + else: + return tuple(result), None + + def _validate_mapping_like( + self, v: Any, values: Dict[str, Any], loc: 'LocStr', cls: Optional['ModelOrDc'] + ) -> 'ValidateReturn': + try: + v_iter = dict_validator(v) + except TypeError as exc: + return v, ErrorWrapper(exc, loc) + + loc = loc if isinstance(loc, tuple) else (loc,) + result, errors = {}, [] + for k, v_ in v_iter.items(): + v_loc = *loc, '__key__' + key_result, key_errors = self.key_field.validate(k, values, loc=v_loc, cls=cls) # type: ignore + if key_errors: + errors.append(key_errors) + continue + + v_loc = *loc, k + value_result, value_errors = self._validate_singleton(v_, values, v_loc, cls) + if value_errors: + errors.append(value_errors) + continue + + result[key_result] = value_result + if errors: + return v, errors + elif self.shape == SHAPE_DICT: + return result, None + elif self.shape == SHAPE_DEFAULTDICT: + return defaultdict(self.type_, result), None + elif self.shape == SHAPE_COUNTER: + return CollectionCounter(result), None + else: + return self._get_mapping_value(v, result), None + + def _get_mapping_value(self, original: T, converted: Dict[Any, Any]) -> Union[T, Dict[Any, Any]]: + """ + When type is `Mapping[KT, KV]` (or another unsupported mapping), we try to avoid + coercing to `dict` unwillingly. + """ + original_cls = original.__class__ + + if original_cls == dict or original_cls == Dict: + return converted + elif original_cls in {defaultdict, DefaultDict}: + return defaultdict(self.type_, converted) + else: + try: + # Counter, OrderedDict, UserDict, ... + return original_cls(converted) # type: ignore + except TypeError: + raise RuntimeError(f'Could not convert dictionary to {original_cls.__name__!r}') from None + + def _validate_singleton( + self, v: Any, values: Dict[str, Any], loc: 'LocStr', cls: Optional['ModelOrDc'] + ) -> 'ValidateReturn': + if self.sub_fields: + if self.discriminator_key is not None: + return self._validate_discriminated_union(v, values, loc, cls) + + errors = [] + + if self.model_config.smart_union and is_union(get_origin(self.type_)): + # 1st pass: check if the value is an exact instance of one of the Union types + # (e.g. to avoid coercing a bool into an int) + for field in self.sub_fields: + if v.__class__ is field.outer_type_: + return v, None + + # 2nd pass: check if the value is an instance of any subclass of the Union types + for field in self.sub_fields: + # This whole logic will be improved later on to support more complex `isinstance` checks + # It will probably be done once a strict mode is added and be something like: + # ``` + # value, error = field.validate(v, values, strict=True) + # if error is None: + # return value, None + # ``` + try: + if isinstance(v, field.outer_type_): + return v, None + except TypeError: + # compound type + if lenient_isinstance(v, get_origin(field.outer_type_)): + value, error = field.validate(v, values, loc=loc, cls=cls) + if not error: + return value, None + + # 1st pass by default or 3rd pass with `smart_union` enabled: + # check if the value can be coerced into one of the Union types + for field in self.sub_fields: + value, error = field.validate(v, values, loc=loc, cls=cls) + if error: + errors.append(error) + else: + return value, None + return v, errors + else: + return self._apply_validators(v, values, loc, cls, self.validators) + + def _validate_discriminated_union( + self, v: Any, values: Dict[str, Any], loc: 'LocStr', cls: Optional['ModelOrDc'] + ) -> 'ValidateReturn': + assert self.discriminator_key is not None + assert self.discriminator_alias is not None + + try: + try: + discriminator_value = v[self.discriminator_alias] + except KeyError: + if self.model_config.allow_population_by_field_name: + discriminator_value = v[self.discriminator_key] + else: + raise + except KeyError: + return v, ErrorWrapper(MissingDiscriminator(discriminator_key=self.discriminator_key), loc) + except TypeError: + try: + # BaseModel or dataclass + discriminator_value = getattr(v, self.discriminator_key) + except (AttributeError, TypeError): + return v, ErrorWrapper(MissingDiscriminator(discriminator_key=self.discriminator_key), loc) + + if self.sub_fields_mapping is None: + assert cls is not None + raise ConfigError( + f'field "{self.name}" not yet prepared so type is still a ForwardRef, ' + f'you might need to call {cls.__name__}.update_forward_refs().' + ) + + try: + sub_field = self.sub_fields_mapping[discriminator_value] + except (KeyError, TypeError): + # KeyError: `discriminator_value` is not in the dictionary. + # TypeError: `discriminator_value` is unhashable. + assert self.sub_fields_mapping is not None + return v, ErrorWrapper( + InvalidDiscriminator( + discriminator_key=self.discriminator_key, + discriminator_value=discriminator_value, + allowed_values=list(self.sub_fields_mapping), + ), + loc, + ) + else: + if not isinstance(loc, tuple): + loc = (loc,) + return sub_field.validate(v, values, loc=(*loc, display_as_type(sub_field.type_)), cls=cls) + + def _apply_validators( + self, v: Any, values: Dict[str, Any], loc: 'LocStr', cls: Optional['ModelOrDc'], validators: 'ValidatorsList' + ) -> 'ValidateReturn': + for validator in validators: + try: + v = validator(cls, v, values, self, self.model_config) + except (ValueError, TypeError, AssertionError) as exc: + return v, ErrorWrapper(exc, loc) + return v, None + + def is_complex(self) -> bool: + """ + Whether the field is "complex" eg. env variables should be parsed as JSON. + """ + from pydantic.v1.main import BaseModel + + return ( + self.shape != SHAPE_SINGLETON + or hasattr(self.type_, '__pydantic_model__') + or lenient_issubclass(self.type_, (BaseModel, list, set, frozenset, dict)) + ) + + def _type_display(self) -> PyObjectStr: + t = display_as_type(self.type_) + + if self.shape in MAPPING_LIKE_SHAPES: + t = f'Mapping[{display_as_type(self.key_field.type_)}, {t}]' # type: ignore + elif self.shape == SHAPE_TUPLE: + t = 'Tuple[{}]'.format(', '.join(display_as_type(f.type_) for f in self.sub_fields)) # type: ignore + elif self.shape == SHAPE_GENERIC: + assert self.sub_fields + t = '{}[{}]'.format( + display_as_type(self.type_), ', '.join(display_as_type(f.type_) for f in self.sub_fields) + ) + elif self.shape != SHAPE_SINGLETON: + t = SHAPE_NAME_LOOKUP[self.shape].format(t) + + if self.allow_none and (self.shape != SHAPE_SINGLETON or not self.sub_fields): + t = f'Optional[{t}]' + return PyObjectStr(t) + + def __repr_args__(self) -> 'ReprArgs': + args = [('name', self.name), ('type', self._type_display()), ('required', self.required)] + + if not self.required: + if self.default_factory is not None: + args.append(('default_factory', f'')) + else: + args.append(('default', self.default)) + + if self.alt_alias: + args.append(('alias', self.alias)) + return args + + +class ModelPrivateAttr(Representation): + __slots__ = ('default', 'default_factory') + + def __init__(self, default: Any = Undefined, *, default_factory: Optional[NoArgAnyCallable] = None) -> None: + self.default = default + self.default_factory = default_factory + + def get_default(self) -> Any: + return smart_deepcopy(self.default) if self.default_factory is None else self.default_factory() + + def __eq__(self, other: Any) -> bool: + return isinstance(other, self.__class__) and (self.default, self.default_factory) == ( + other.default, + other.default_factory, + ) + + +def PrivateAttr( + default: Any = Undefined, + *, + default_factory: Optional[NoArgAnyCallable] = None, +) -> Any: + """ + Indicates that attribute is only used internally and never mixed with regular fields. + + Types or values of private attrs are not checked by pydantic and it's up to you to keep them relevant. + + Private attrs are stored in model __slots__. + + :param default: the attribute’s default value + :param default_factory: callable that will be called when a default value is needed for this attribute + If both `default` and `default_factory` are set, an error is raised. + """ + if default is not Undefined and default_factory is not None: + raise ValueError('cannot specify both default and default_factory') + + return ModelPrivateAttr( + default, + default_factory=default_factory, + ) + + +class DeferredType: + """ + Used to postpone field preparation, while creating recursive generic models. + """ + + +def is_finalvar_with_default_val(type_: Type[Any], val: Any) -> bool: + return is_finalvar(type_) and val is not Undefined and not isinstance(val, FieldInfo) diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/generics.py b/backend/.venv/Lib/site-packages/pydantic/v1/generics.py new file mode 100644 index 0000000..9a69f2b --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/generics.py @@ -0,0 +1,400 @@ +import sys +import types +import typing +from typing import ( + TYPE_CHECKING, + Any, + ClassVar, + Dict, + ForwardRef, + Generic, + Iterator, + List, + Mapping, + Optional, + Tuple, + Type, + TypeVar, + Union, + cast, +) +from weakref import WeakKeyDictionary, WeakValueDictionary + +from typing_extensions import Annotated, Literal as ExtLiteral + +from pydantic.v1.class_validators import gather_all_validators +from pydantic.v1.fields import DeferredType +from pydantic.v1.main import BaseModel, create_model +from pydantic.v1.types import JsonWrapper +from pydantic.v1.typing import display_as_type, get_all_type_hints, get_args, get_origin, typing_base +from pydantic.v1.utils import all_identical, lenient_issubclass + +if sys.version_info >= (3, 10): + from typing import _UnionGenericAlias +if sys.version_info >= (3, 8): + from typing import Literal + +GenericModelT = TypeVar('GenericModelT', bound='GenericModel') +TypeVarType = Any # since mypy doesn't allow the use of TypeVar as a type + +CacheKey = Tuple[Type[Any], Any, Tuple[Any, ...]] +Parametrization = Mapping[TypeVarType, Type[Any]] + +# weak dictionaries allow the dynamically created parametrized versions of generic models to get collected +# once they are no longer referenced by the caller. +if sys.version_info >= (3, 9): # Typing for weak dictionaries available at 3.9 + GenericTypesCache = WeakValueDictionary[CacheKey, Type[BaseModel]] + AssignedParameters = WeakKeyDictionary[Type[BaseModel], Parametrization] +else: + GenericTypesCache = WeakValueDictionary + AssignedParameters = WeakKeyDictionary + +# _generic_types_cache is a Mapping from __class_getitem__ arguments to the parametrized version of generic models. +# This ensures multiple calls of e.g. A[B] return always the same class. +_generic_types_cache = GenericTypesCache() + +# _assigned_parameters is a Mapping from parametrized version of generic models to assigned types of parametrizations +# as captured during construction of the class (not instances). +# E.g., for generic model `Model[A, B]`, when parametrized model `Model[int, str]` is created, +# `Model[int, str]`: {A: int, B: str}` will be stored in `_assigned_parameters`. +# (This information is only otherwise available after creation from the class name string). +_assigned_parameters = AssignedParameters() + + +class GenericModel(BaseModel): + __slots__ = () + __concrete__: ClassVar[bool] = False + + if TYPE_CHECKING: + # Putting this in a TYPE_CHECKING block allows us to replace `if Generic not in cls.__bases__` with + # `not hasattr(cls, "__parameters__")`. This means we don't need to force non-concrete subclasses of + # `GenericModel` to also inherit from `Generic`, which would require changes to the use of `create_model` below. + __parameters__: ClassVar[Tuple[TypeVarType, ...]] + + # Setting the return type as Type[Any] instead of Type[BaseModel] prevents PyCharm warnings + def __class_getitem__(cls: Type[GenericModelT], params: Union[Type[Any], Tuple[Type[Any], ...]]) -> Type[Any]: + """Instantiates a new class from a generic class `cls` and type variables `params`. + + :param params: Tuple of types the class . Given a generic class + `Model` with 2 type variables and a concrete model `Model[str, int]`, + the value `(str, int)` would be passed to `params`. + :return: New model class inheriting from `cls` with instantiated + types described by `params`. If no parameters are given, `cls` is + returned as is. + + """ + + def _cache_key(_params: Any) -> CacheKey: + args = get_args(_params) + # python returns a list for Callables, which is not hashable + if len(args) == 2 and isinstance(args[0], list): + args = (tuple(args[0]), args[1]) + return cls, _params, args + + cached = _generic_types_cache.get(_cache_key(params)) + if cached is not None: + return cached + if cls.__concrete__ and Generic not in cls.__bases__: + raise TypeError('Cannot parameterize a concrete instantiation of a generic model') + if not isinstance(params, tuple): + params = (params,) + if cls is GenericModel and any(isinstance(param, TypeVar) for param in params): + raise TypeError('Type parameters should be placed on typing.Generic, not GenericModel') + if not hasattr(cls, '__parameters__'): + raise TypeError(f'Type {cls.__name__} must inherit from typing.Generic before being parameterized') + + check_parameters_count(cls, params) + # Build map from generic typevars to passed params + typevars_map: Dict[TypeVarType, Type[Any]] = dict(zip(cls.__parameters__, params)) + if all_identical(typevars_map.keys(), typevars_map.values()) and typevars_map: + return cls # if arguments are equal to parameters it's the same object + + # Create new model with original model as parent inserting fields with DeferredType. + model_name = cls.__concrete_name__(params) + validators = gather_all_validators(cls) + + type_hints = get_all_type_hints(cls).items() + instance_type_hints = {k: v for k, v in type_hints if get_origin(v) is not ClassVar} + + fields = {k: (DeferredType(), cls.__fields__[k].field_info) for k in instance_type_hints if k in cls.__fields__} + + model_module, called_globally = get_caller_frame_info() + created_model = cast( + Type[GenericModel], # casting ensures mypy is aware of the __concrete__ and __parameters__ attributes + create_model( + model_name, + __module__=model_module or cls.__module__, + __base__=(cls,) + tuple(cls.__parameterized_bases__(typevars_map)), + __config__=None, + __validators__=validators, + __cls_kwargs__=None, + **fields, + ), + ) + + _assigned_parameters[created_model] = typevars_map + + if called_globally: # create global reference and therefore allow pickling + object_by_reference = None + reference_name = model_name + reference_module_globals = sys.modules[created_model.__module__].__dict__ + while object_by_reference is not created_model: + object_by_reference = reference_module_globals.setdefault(reference_name, created_model) + reference_name += '_' + + created_model.Config = cls.Config + + # Find any typevars that are still present in the model. + # If none are left, the model is fully "concrete", otherwise the new + # class is a generic class as well taking the found typevars as + # parameters. + new_params = tuple( + {param: None for param in iter_contained_typevars(typevars_map.values())} + ) # use dict as ordered set + created_model.__concrete__ = not new_params + if new_params: + created_model.__parameters__ = new_params + + # Save created model in cache so we don't end up creating duplicate + # models that should be identical. + _generic_types_cache[_cache_key(params)] = created_model + if len(params) == 1: + _generic_types_cache[_cache_key(params[0])] = created_model + + # Recursively walk class type hints and replace generic typevars + # with concrete types that were passed. + _prepare_model_fields(created_model, fields, instance_type_hints, typevars_map) + + return created_model + + @classmethod + def __concrete_name__(cls: Type[Any], params: Tuple[Type[Any], ...]) -> str: + """Compute class name for child classes. + + :param params: Tuple of types the class . Given a generic class + `Model` with 2 type variables and a concrete model `Model[str, int]`, + the value `(str, int)` would be passed to `params`. + :return: String representing a the new class where `params` are + passed to `cls` as type variables. + + This method can be overridden to achieve a custom naming scheme for GenericModels. + """ + param_names = [display_as_type(param) for param in params] + params_component = ', '.join(param_names) + return f'{cls.__name__}[{params_component}]' + + @classmethod + def __parameterized_bases__(cls, typevars_map: Parametrization) -> Iterator[Type[Any]]: + """ + Returns unbound bases of cls parameterised to given type variables + + :param typevars_map: Dictionary of type applications for binding subclasses. + Given a generic class `Model` with 2 type variables [S, T] + and a concrete model `Model[str, int]`, + the value `{S: str, T: int}` would be passed to `typevars_map`. + :return: an iterator of generic sub classes, parameterised by `typevars_map` + and other assigned parameters of `cls` + + e.g.: + ``` + class A(GenericModel, Generic[T]): + ... + + class B(A[V], Generic[V]): + ... + + assert A[int] in B.__parameterized_bases__({V: int}) + ``` + """ + + def build_base_model( + base_model: Type[GenericModel], mapped_types: Parametrization + ) -> Iterator[Type[GenericModel]]: + base_parameters = tuple(mapped_types[param] for param in base_model.__parameters__) + parameterized_base = base_model.__class_getitem__(base_parameters) + if parameterized_base is base_model or parameterized_base is cls: + # Avoid duplication in MRO + return + yield parameterized_base + + for base_model in cls.__bases__: + if not issubclass(base_model, GenericModel): + # not a class that can be meaningfully parameterized + continue + elif not getattr(base_model, '__parameters__', None): + # base_model is "GenericModel" (and has no __parameters__) + # or + # base_model is already concrete, and will be included transitively via cls. + continue + elif cls in _assigned_parameters: + if base_model in _assigned_parameters: + # cls is partially parameterised but not from base_model + # e.g. cls = B[S], base_model = A[S] + # B[S][int] should subclass A[int], (and will be transitively via B[int]) + # but it's not viable to consistently subclass types with arbitrary construction + # So don't attempt to include A[S][int] + continue + else: # base_model not in _assigned_parameters: + # cls is partially parameterized, base_model is original generic + # e.g. cls = B[str, T], base_model = B[S, T] + # Need to determine the mapping for the base_model parameters + mapped_types: Parametrization = { + key: typevars_map.get(value, value) for key, value in _assigned_parameters[cls].items() + } + yield from build_base_model(base_model, mapped_types) + else: + # cls is base generic, so base_class has a distinct base + # can construct the Parameterised base model using typevars_map directly + yield from build_base_model(base_model, typevars_map) + + +def replace_types(type_: Any, type_map: Mapping[Any, Any]) -> Any: + """Return type with all occurrences of `type_map` keys recursively replaced with their values. + + :param type_: Any type, class or generic alias + :param type_map: Mapping from `TypeVar` instance to concrete types. + :return: New type representing the basic structure of `type_` with all + `typevar_map` keys recursively replaced. + + >>> replace_types(Tuple[str, Union[List[str], float]], {str: int}) + Tuple[int, Union[List[int], float]] + + """ + if not type_map: + return type_ + + type_args = get_args(type_) + origin_type = get_origin(type_) + + if origin_type is Annotated: + annotated_type, *annotations = type_args + return Annotated[replace_types(annotated_type, type_map), tuple(annotations)] + + if (origin_type is ExtLiteral) or (sys.version_info >= (3, 8) and origin_type is Literal): + return type_map.get(type_, type_) + # Having type args is a good indicator that this is a typing module + # class instantiation or a generic alias of some sort. + if type_args: + resolved_type_args = tuple(replace_types(arg, type_map) for arg in type_args) + if all_identical(type_args, resolved_type_args): + # If all arguments are the same, there is no need to modify the + # type or create a new object at all + return type_ + if ( + origin_type is not None + and isinstance(type_, typing_base) + and not isinstance(origin_type, typing_base) + and getattr(type_, '_name', None) is not None + ): + # In python < 3.9 generic aliases don't exist so any of these like `list`, + # `type` or `collections.abc.Callable` need to be translated. + # See: https://www.python.org/dev/peps/pep-0585 + origin_type = getattr(typing, type_._name) + assert origin_type is not None + # PEP-604 syntax (Ex.: list | str) is represented with a types.UnionType object that does not have __getitem__. + # We also cannot use isinstance() since we have to compare types. + if sys.version_info >= (3, 10) and origin_type is types.UnionType: # noqa: E721 + return _UnionGenericAlias(origin_type, resolved_type_args) + return origin_type[resolved_type_args] + + # We handle pydantic generic models separately as they don't have the same + # semantics as "typing" classes or generic aliases + if not origin_type and lenient_issubclass(type_, GenericModel) and not type_.__concrete__: + type_args = type_.__parameters__ + resolved_type_args = tuple(replace_types(t, type_map) for t in type_args) + if all_identical(type_args, resolved_type_args): + return type_ + return type_[resolved_type_args] + + # Handle special case for typehints that can have lists as arguments. + # `typing.Callable[[int, str], int]` is an example for this. + if isinstance(type_, (List, list)): + resolved_list = list(replace_types(element, type_map) for element in type_) + if all_identical(type_, resolved_list): + return type_ + return resolved_list + + # For JsonWrapperValue, need to handle its inner type to allow correct parsing + # of generic Json arguments like Json[T] + if not origin_type and lenient_issubclass(type_, JsonWrapper): + type_.inner_type = replace_types(type_.inner_type, type_map) + return type_ + + # If all else fails, we try to resolve the type directly and otherwise just + # return the input with no modifications. + new_type = type_map.get(type_, type_) + # Convert string to ForwardRef + if isinstance(new_type, str): + return ForwardRef(new_type) + else: + return new_type + + +def check_parameters_count(cls: Type[GenericModel], parameters: Tuple[Any, ...]) -> None: + actual = len(parameters) + expected = len(cls.__parameters__) + if actual != expected: + description = 'many' if actual > expected else 'few' + raise TypeError(f'Too {description} parameters for {cls.__name__}; actual {actual}, expected {expected}') + + +DictValues: Type[Any] = {}.values().__class__ + + +def iter_contained_typevars(v: Any) -> Iterator[TypeVarType]: + """Recursively iterate through all subtypes and type args of `v` and yield any typevars that are found.""" + if isinstance(v, TypeVar): + yield v + elif hasattr(v, '__parameters__') and not get_origin(v) and lenient_issubclass(v, GenericModel): + yield from v.__parameters__ + elif isinstance(v, (DictValues, list)): + for var in v: + yield from iter_contained_typevars(var) + else: + args = get_args(v) + for arg in args: + yield from iter_contained_typevars(arg) + + +def get_caller_frame_info() -> Tuple[Optional[str], bool]: + """ + Used inside a function to check whether it was called globally + + Will only work against non-compiled code, therefore used only in pydantic.generics + + :returns Tuple[module_name, called_globally] + """ + try: + previous_caller_frame = sys._getframe(2) + except ValueError as e: + raise RuntimeError('This function must be used inside another function') from e + except AttributeError: # sys module does not have _getframe function, so there's nothing we can do about it + return None, False + frame_globals = previous_caller_frame.f_globals + return frame_globals.get('__name__'), previous_caller_frame.f_locals is frame_globals + + +def _prepare_model_fields( + created_model: Type[GenericModel], + fields: Mapping[str, Any], + instance_type_hints: Mapping[str, type], + typevars_map: Mapping[Any, type], +) -> None: + """ + Replace DeferredType fields with concrete type hints and prepare them. + """ + + for key, field in created_model.__fields__.items(): + if key not in fields: + assert field.type_.__class__ is not DeferredType + # https://github.com/nedbat/coveragepy/issues/198 + continue # pragma: no cover + + assert field.type_.__class__ is DeferredType, field.type_.__class__ + + field_type_hint = instance_type_hints[key] + concrete_type = replace_types(field_type_hint, typevars_map) + field.type_ = concrete_type + field.outer_type_ = concrete_type + field.prepare() + created_model.__annotations__[key] = concrete_type diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/json.py b/backend/.venv/Lib/site-packages/pydantic/v1/json.py new file mode 100644 index 0000000..41d0d5f --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/json.py @@ -0,0 +1,112 @@ +import datetime +from collections import deque +from decimal import Decimal +from enum import Enum +from ipaddress import IPv4Address, IPv4Interface, IPv4Network, IPv6Address, IPv6Interface, IPv6Network +from pathlib import Path +from re import Pattern +from types import GeneratorType +from typing import Any, Callable, Dict, Type, Union +from uuid import UUID + +from pydantic.v1.color import Color +from pydantic.v1.networks import NameEmail +from pydantic.v1.types import SecretBytes, SecretStr + +__all__ = 'pydantic_encoder', 'custom_pydantic_encoder', 'timedelta_isoformat' + + +def isoformat(o: Union[datetime.date, datetime.time]) -> str: + return o.isoformat() + + +def decimal_encoder(dec_value: Decimal) -> Union[int, float]: + """ + Encodes a Decimal as int of there's no exponent, otherwise float + + This is useful when we use ConstrainedDecimal to represent Numeric(x,0) + where a integer (but not int typed) is used. Encoding this as a float + results in failed round-tripping between encode and parse. + Our Id type is a prime example of this. + + >>> decimal_encoder(Decimal("1.0")) + 1.0 + + >>> decimal_encoder(Decimal("1")) + 1 + """ + if dec_value.as_tuple().exponent >= 0: + return int(dec_value) + else: + return float(dec_value) + + +ENCODERS_BY_TYPE: Dict[Type[Any], Callable[[Any], Any]] = { + bytes: lambda o: o.decode(), + Color: str, + datetime.date: isoformat, + datetime.datetime: isoformat, + datetime.time: isoformat, + datetime.timedelta: lambda td: td.total_seconds(), + Decimal: decimal_encoder, + Enum: lambda o: o.value, + frozenset: list, + deque: list, + GeneratorType: list, + IPv4Address: str, + IPv4Interface: str, + IPv4Network: str, + IPv6Address: str, + IPv6Interface: str, + IPv6Network: str, + NameEmail: str, + Path: str, + Pattern: lambda o: o.pattern, + SecretBytes: str, + SecretStr: str, + set: list, + UUID: str, +} + + +def pydantic_encoder(obj: Any) -> Any: + from dataclasses import asdict, is_dataclass + + from pydantic.v1.main import BaseModel + + if isinstance(obj, BaseModel): + return obj.dict() + elif is_dataclass(obj): + return asdict(obj) + + # Check the class type and its superclasses for a matching encoder + for base in obj.__class__.__mro__[:-1]: + try: + encoder = ENCODERS_BY_TYPE[base] + except KeyError: + continue + return encoder(obj) + else: # We have exited the for loop without finding a suitable encoder + raise TypeError(f"Object of type '{obj.__class__.__name__}' is not JSON serializable") + + +def custom_pydantic_encoder(type_encoders: Dict[Any, Callable[[Type[Any]], Any]], obj: Any) -> Any: + # Check the class type and its superclasses for a matching encoder + for base in obj.__class__.__mro__[:-1]: + try: + encoder = type_encoders[base] + except KeyError: + continue + + return encoder(obj) + else: # We have exited the for loop without finding a suitable encoder + return pydantic_encoder(obj) + + +def timedelta_isoformat(td: datetime.timedelta) -> str: + """ + ISO 8601 encoding for Python timedelta object. + """ + minutes, seconds = divmod(td.seconds, 60) + hours, minutes = divmod(minutes, 60) + return f'{"-" if td.days < 0 else ""}P{abs(td.days)}DT{hours:d}H{minutes:d}M{seconds:d}.{td.microseconds:06d}S' diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/main.py b/backend/.venv/Lib/site-packages/pydantic/v1/main.py new file mode 100644 index 0000000..8000967 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/main.py @@ -0,0 +1,1113 @@ +import warnings +from abc import ABCMeta +from copy import deepcopy +from enum import Enum +from functools import partial +from pathlib import Path +from types import FunctionType, prepare_class, resolve_bases +from typing import ( + TYPE_CHECKING, + AbstractSet, + Any, + Callable, + ClassVar, + Dict, + List, + Mapping, + Optional, + Tuple, + Type, + TypeVar, + Union, + cast, + no_type_check, + overload, +) + +from typing_extensions import dataclass_transform + +from pydantic.v1.class_validators import ValidatorGroup, extract_root_validators, extract_validators, inherit_validators +from pydantic.v1.config import BaseConfig, Extra, inherit_config, prepare_config +from pydantic.v1.error_wrappers import ErrorWrapper, ValidationError +from pydantic.v1.errors import ConfigError, DictError, ExtraError, MissingError +from pydantic.v1.fields import ( + MAPPING_LIKE_SHAPES, + Field, + ModelField, + ModelPrivateAttr, + PrivateAttr, + Undefined, + is_finalvar_with_default_val, +) +from pydantic.v1.json import custom_pydantic_encoder, pydantic_encoder +from pydantic.v1.parse import Protocol, load_file, load_str_bytes +from pydantic.v1.schema import default_ref_template, model_schema +from pydantic.v1.types import PyObject, StrBytes +from pydantic.v1.typing import ( + AnyCallable, + get_args, + get_origin, + is_classvar, + is_namedtuple, + is_union, + resolve_annotations, + update_model_forward_refs, +) +from pydantic.v1.utils import ( + DUNDER_ATTRIBUTES, + ROOT_KEY, + ClassAttribute, + GetterDict, + Representation, + ValueItems, + generate_model_signature, + is_valid_field, + is_valid_private_name, + lenient_issubclass, + sequence_like, + smart_deepcopy, + unique_list, + validate_field_name, +) + +if TYPE_CHECKING: + from inspect import Signature + + from pydantic.v1.class_validators import ValidatorListDict + from pydantic.v1.types import ModelOrDc + from pydantic.v1.typing import ( + AbstractSetIntStr, + AnyClassMethod, + CallableGenerator, + DictAny, + DictStrAny, + MappingIntStrAny, + ReprArgs, + SetStr, + TupleGenerator, + ) + + Model = TypeVar('Model', bound='BaseModel') + +__all__ = 'BaseModel', 'create_model', 'validate_model' + +_T = TypeVar('_T') + + +def validate_custom_root_type(fields: Dict[str, ModelField]) -> None: + if len(fields) > 1: + raise ValueError(f'{ROOT_KEY} cannot be mixed with other fields') + + +def generate_hash_function(frozen: bool) -> Optional[Callable[[Any], int]]: + def hash_function(self_: Any) -> int: + return hash(self_.__class__) + hash(tuple(self_.__dict__.values())) + + return hash_function if frozen else None + + +# If a field is of type `Callable`, its default value should be a function and cannot to ignored. +ANNOTATED_FIELD_UNTOUCHED_TYPES: Tuple[Any, ...] = (property, type, classmethod, staticmethod) +# When creating a `BaseModel` instance, we bypass all the methods, properties... added to the model +UNTOUCHED_TYPES: Tuple[Any, ...] = (FunctionType,) + ANNOTATED_FIELD_UNTOUCHED_TYPES +# Note `ModelMetaclass` refers to `BaseModel`, but is also used to *create* `BaseModel`, so we need to add this extra +# (somewhat hacky) boolean to keep track of whether we've created the `BaseModel` class yet, and therefore whether it's +# safe to refer to it. If it *hasn't* been created, we assume that the `__new__` call we're in the middle of is for +# the `BaseModel` class, since that's defined immediately after the metaclass. +_is_base_model_class_defined = False + + +@dataclass_transform(kw_only_default=True, field_specifiers=(Field,)) +class ModelMetaclass(ABCMeta): + @no_type_check # noqa C901 + def __new__(mcs, name, bases, namespace, **kwargs): # noqa C901 + fields: Dict[str, ModelField] = {} + config = BaseConfig + validators: 'ValidatorListDict' = {} + + pre_root_validators, post_root_validators = [], [] + private_attributes: Dict[str, ModelPrivateAttr] = {} + base_private_attributes: Dict[str, ModelPrivateAttr] = {} + slots: SetStr = namespace.get('__slots__', ()) + slots = {slots} if isinstance(slots, str) else set(slots) + class_vars: SetStr = set() + hash_func: Optional[Callable[[Any], int]] = None + + for base in reversed(bases): + if _is_base_model_class_defined and issubclass(base, BaseModel) and base != BaseModel: + fields.update(smart_deepcopy(base.__fields__)) + config = inherit_config(base.__config__, config) + validators = inherit_validators(base.__validators__, validators) + pre_root_validators += base.__pre_root_validators__ + post_root_validators += base.__post_root_validators__ + base_private_attributes.update(base.__private_attributes__) + class_vars.update(base.__class_vars__) + hash_func = base.__hash__ + + resolve_forward_refs = kwargs.pop('__resolve_forward_refs__', True) + allowed_config_kwargs: SetStr = { + key + for key in dir(config) + if not (key.startswith('__') and key.endswith('__')) # skip dunder methods and attributes + } + config_kwargs = {key: kwargs.pop(key) for key in kwargs.keys() & allowed_config_kwargs} + config_from_namespace = namespace.get('Config') + if config_kwargs and config_from_namespace: + raise TypeError('Specifying config in two places is ambiguous, use either Config attribute or class kwargs') + config = inherit_config(config_from_namespace, config, **config_kwargs) + + validators = inherit_validators(extract_validators(namespace), validators) + vg = ValidatorGroup(validators) + + for f in fields.values(): + f.set_config(config) + extra_validators = vg.get_validators(f.name) + if extra_validators: + f.class_validators.update(extra_validators) + # re-run prepare to add extra validators + f.populate_validators() + + prepare_config(config, name) + + untouched_types = ANNOTATED_FIELD_UNTOUCHED_TYPES + + def is_untouched(v: Any) -> bool: + return isinstance(v, untouched_types) or v.__class__.__name__ == 'cython_function_or_method' + + if (namespace.get('__module__'), namespace.get('__qualname__')) != ('pydantic.main', 'BaseModel'): + annotations = resolve_annotations(namespace.get('__annotations__', {}), namespace.get('__module__', None)) + # annotation only fields need to come first in fields + for ann_name, ann_type in annotations.items(): + if is_classvar(ann_type): + class_vars.add(ann_name) + elif is_finalvar_with_default_val(ann_type, namespace.get(ann_name, Undefined)): + class_vars.add(ann_name) + elif is_valid_field(ann_name): + validate_field_name(bases, ann_name) + value = namespace.get(ann_name, Undefined) + allowed_types = get_args(ann_type) if is_union(get_origin(ann_type)) else (ann_type,) + if ( + is_untouched(value) + and ann_type != PyObject + and not any( + lenient_issubclass(get_origin(allowed_type), Type) for allowed_type in allowed_types + ) + ): + continue + fields[ann_name] = ModelField.infer( + name=ann_name, + value=value, + annotation=ann_type, + class_validators=vg.get_validators(ann_name), + config=config, + ) + elif ann_name not in namespace and config.underscore_attrs_are_private: + private_attributes[ann_name] = PrivateAttr() + + untouched_types = UNTOUCHED_TYPES + config.keep_untouched + for var_name, value in namespace.items(): + can_be_changed = var_name not in class_vars and not is_untouched(value) + if isinstance(value, ModelPrivateAttr): + if not is_valid_private_name(var_name): + raise NameError( + f'Private attributes "{var_name}" must not be a valid field name; ' + f'Use sunder or dunder names, e. g. "_{var_name}" or "__{var_name}__"' + ) + private_attributes[var_name] = value + elif config.underscore_attrs_are_private and is_valid_private_name(var_name) and can_be_changed: + private_attributes[var_name] = PrivateAttr(default=value) + elif is_valid_field(var_name) and var_name not in annotations and can_be_changed: + validate_field_name(bases, var_name) + inferred = ModelField.infer( + name=var_name, + value=value, + annotation=annotations.get(var_name, Undefined), + class_validators=vg.get_validators(var_name), + config=config, + ) + if var_name in fields: + if lenient_issubclass(inferred.type_, fields[var_name].type_): + inferred.type_ = fields[var_name].type_ + else: + raise TypeError( + f'The type of {name}.{var_name} differs from the new default value; ' + f'if you wish to change the type of this field, please use a type annotation' + ) + fields[var_name] = inferred + + _custom_root_type = ROOT_KEY in fields + if _custom_root_type: + validate_custom_root_type(fields) + vg.check_for_unused() + if config.json_encoders: + json_encoder = partial(custom_pydantic_encoder, config.json_encoders) + else: + json_encoder = pydantic_encoder + pre_rv_new, post_rv_new = extract_root_validators(namespace) + + if hash_func is None: + hash_func = generate_hash_function(config.frozen) + + exclude_from_namespace = fields | private_attributes.keys() | {'__slots__'} + new_namespace = { + '__config__': config, + '__fields__': fields, + '__exclude_fields__': { + name: field.field_info.exclude for name, field in fields.items() if field.field_info.exclude is not None + } + or None, + '__include_fields__': { + name: field.field_info.include for name, field in fields.items() if field.field_info.include is not None + } + or None, + '__validators__': vg.validators, + '__pre_root_validators__': unique_list( + pre_root_validators + pre_rv_new, + name_factory=lambda v: v.__name__, + ), + '__post_root_validators__': unique_list( + post_root_validators + post_rv_new, + name_factory=lambda skip_on_failure_and_v: skip_on_failure_and_v[1].__name__, + ), + '__schema_cache__': {}, + '__json_encoder__': staticmethod(json_encoder), + '__custom_root_type__': _custom_root_type, + '__private_attributes__': {**base_private_attributes, **private_attributes}, + '__slots__': slots | private_attributes.keys(), + '__hash__': hash_func, + '__class_vars__': class_vars, + **{n: v for n, v in namespace.items() if n not in exclude_from_namespace}, + } + + cls = super().__new__(mcs, name, bases, new_namespace, **kwargs) + # set __signature__ attr only for model class, but not for its instances + cls.__signature__ = ClassAttribute('__signature__', generate_model_signature(cls.__init__, fields, config)) + + if not _is_base_model_class_defined: + # Cython does not understand the `if TYPE_CHECKING:` condition in the + # BaseModel's body (where annotations are set), so clear them manually: + getattr(cls, '__annotations__', {}).clear() + + if resolve_forward_refs: + cls.__try_update_forward_refs__() + + # preserve `__set_name__` protocol defined in https://peps.python.org/pep-0487 + # for attributes not in `new_namespace` (e.g. private attributes) + for name, obj in namespace.items(): + if name not in new_namespace: + set_name = getattr(obj, '__set_name__', None) + if callable(set_name): + set_name(cls, name) + + return cls + + def __instancecheck__(self, instance: Any) -> bool: + """ + Avoid calling ABC _abc_subclasscheck unless we're pretty sure. + + See #3829 and python/cpython#92810 + """ + return hasattr(instance, '__post_root_validators__') and super().__instancecheck__(instance) + + +object_setattr = object.__setattr__ + + +class BaseModel(Representation, metaclass=ModelMetaclass): + if TYPE_CHECKING: + # populated by the metaclass, defined here to help IDEs only + __fields__: ClassVar[Dict[str, ModelField]] = {} + __include_fields__: ClassVar[Optional[Mapping[str, Any]]] = None + __exclude_fields__: ClassVar[Optional[Mapping[str, Any]]] = None + __validators__: ClassVar[Dict[str, AnyCallable]] = {} + __pre_root_validators__: ClassVar[List[AnyCallable]] + __post_root_validators__: ClassVar[List[Tuple[bool, AnyCallable]]] + __config__: ClassVar[Type[BaseConfig]] = BaseConfig + __json_encoder__: ClassVar[Callable[[Any], Any]] = lambda x: x + __schema_cache__: ClassVar['DictAny'] = {} + __custom_root_type__: ClassVar[bool] = False + __signature__: ClassVar['Signature'] + __private_attributes__: ClassVar[Dict[str, ModelPrivateAttr]] + __class_vars__: ClassVar[SetStr] + __fields_set__: ClassVar[SetStr] = set() + + Config = BaseConfig + __slots__ = ('__dict__', '__fields_set__') + __doc__ = '' # Null out the Representation docstring + + def __init__(__pydantic_self__, **data: Any) -> None: + """ + Create a new model by parsing and validating input data from keyword arguments. + + Raises ValidationError if the input data cannot be parsed to form a valid model. + """ + # Uses something other than `self` the first arg to allow "self" as a settable attribute + values, fields_set, validation_error = validate_model(__pydantic_self__.__class__, data) + if validation_error: + raise validation_error + try: + object_setattr(__pydantic_self__, '__dict__', values) + except TypeError as e: + raise TypeError( + 'Model values must be a dict; you may not have returned a dictionary from a root validator' + ) from e + object_setattr(__pydantic_self__, '__fields_set__', fields_set) + __pydantic_self__._init_private_attributes() + + @no_type_check + def __setattr__(self, name, value): # noqa: C901 (ignore complexity) + if name in self.__private_attributes__ or name in DUNDER_ATTRIBUTES: + return object_setattr(self, name, value) + + if self.__config__.extra is not Extra.allow and name not in self.__fields__: + raise ValueError(f'"{self.__class__.__name__}" object has no field "{name}"') + elif not self.__config__.allow_mutation or self.__config__.frozen: + raise TypeError(f'"{self.__class__.__name__}" is immutable and does not support item assignment') + elif name in self.__fields__ and self.__fields__[name].final: + raise TypeError( + f'"{self.__class__.__name__}" object "{name}" field is final and does not support reassignment' + ) + elif self.__config__.validate_assignment: + new_values = {**self.__dict__, name: value} + + for validator in self.__pre_root_validators__: + try: + new_values = validator(self.__class__, new_values) + except (ValueError, TypeError, AssertionError) as exc: + raise ValidationError([ErrorWrapper(exc, loc=ROOT_KEY)], self.__class__) + + known_field = self.__fields__.get(name, None) + if known_field: + # We want to + # - make sure validators are called without the current value for this field inside `values` + # - keep other values (e.g. submodels) untouched (using `BaseModel.dict()` will change them into dicts) + # - keep the order of the fields + if not known_field.field_info.allow_mutation: + raise TypeError(f'"{known_field.name}" has allow_mutation set to False and cannot be assigned') + dict_without_original_value = {k: v for k, v in self.__dict__.items() if k != name} + value, error_ = known_field.validate(value, dict_without_original_value, loc=name, cls=self.__class__) + if error_: + raise ValidationError([error_], self.__class__) + else: + new_values[name] = value + + errors = [] + for skip_on_failure, validator in self.__post_root_validators__: + if skip_on_failure and errors: + continue + try: + new_values = validator(self.__class__, new_values) + except (ValueError, TypeError, AssertionError) as exc: + errors.append(ErrorWrapper(exc, loc=ROOT_KEY)) + if errors: + raise ValidationError(errors, self.__class__) + + # update the whole __dict__ as other values than just `value` + # may be changed (e.g. with `root_validator`) + object_setattr(self, '__dict__', new_values) + else: + self.__dict__[name] = value + + self.__fields_set__.add(name) + + def __getstate__(self) -> 'DictAny': + private_attrs = ((k, getattr(self, k, Undefined)) for k in self.__private_attributes__) + return { + '__dict__': self.__dict__, + '__fields_set__': self.__fields_set__, + '__private_attribute_values__': {k: v for k, v in private_attrs if v is not Undefined}, + } + + def __setstate__(self, state: 'DictAny') -> None: + object_setattr(self, '__dict__', state['__dict__']) + object_setattr(self, '__fields_set__', state['__fields_set__']) + for name, value in state.get('__private_attribute_values__', {}).items(): + object_setattr(self, name, value) + + def _init_private_attributes(self) -> None: + for name, private_attr in self.__private_attributes__.items(): + default = private_attr.get_default() + if default is not Undefined: + object_setattr(self, name, default) + + def dict( + self, + *, + include: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']] = None, + exclude: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']] = None, + by_alias: bool = False, + skip_defaults: Optional[bool] = None, + exclude_unset: bool = False, + exclude_defaults: bool = False, + exclude_none: bool = False, + ) -> 'DictStrAny': + """ + Generate a dictionary representation of the model, optionally specifying which fields to include or exclude. + + """ + if skip_defaults is not None: + warnings.warn( + f'{self.__class__.__name__}.dict(): "skip_defaults" is deprecated and replaced by "exclude_unset"', + DeprecationWarning, + ) + exclude_unset = skip_defaults + + return dict( + self._iter( + to_dict=True, + by_alias=by_alias, + include=include, + exclude=exclude, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + ) + + def json( + self, + *, + include: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']] = None, + exclude: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']] = None, + by_alias: bool = False, + skip_defaults: Optional[bool] = None, + exclude_unset: bool = False, + exclude_defaults: bool = False, + exclude_none: bool = False, + encoder: Optional[Callable[[Any], Any]] = None, + models_as_dict: bool = True, + **dumps_kwargs: Any, + ) -> str: + """ + Generate a JSON representation of the model, `include` and `exclude` arguments as per `dict()`. + + `encoder` is an optional function to supply as `default` to json.dumps(), other arguments as per `json.dumps()`. + """ + if skip_defaults is not None: + warnings.warn( + f'{self.__class__.__name__}.json(): "skip_defaults" is deprecated and replaced by "exclude_unset"', + DeprecationWarning, + ) + exclude_unset = skip_defaults + encoder = cast(Callable[[Any], Any], encoder or self.__json_encoder__) + + # We don't directly call `self.dict()`, which does exactly this with `to_dict=True` + # because we want to be able to keep raw `BaseModel` instances and not as `dict`. + # This allows users to write custom JSON encoders for given `BaseModel` classes. + data = dict( + self._iter( + to_dict=models_as_dict, + by_alias=by_alias, + include=include, + exclude=exclude, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + ) + if self.__custom_root_type__: + data = data[ROOT_KEY] + return self.__config__.json_dumps(data, default=encoder, **dumps_kwargs) + + @classmethod + def _enforce_dict_if_root(cls, obj: Any) -> Any: + if cls.__custom_root_type__ and ( + not (isinstance(obj, dict) and obj.keys() == {ROOT_KEY}) + and not (isinstance(obj, BaseModel) and obj.__fields__.keys() == {ROOT_KEY}) + or cls.__fields__[ROOT_KEY].shape in MAPPING_LIKE_SHAPES + ): + return {ROOT_KEY: obj} + else: + return obj + + @classmethod + def parse_obj(cls: Type['Model'], obj: Any) -> 'Model': + obj = cls._enforce_dict_if_root(obj) + if not isinstance(obj, dict): + try: + obj = dict(obj) + except (TypeError, ValueError) as e: + exc = TypeError(f'{cls.__name__} expected dict not {obj.__class__.__name__}') + raise ValidationError([ErrorWrapper(exc, loc=ROOT_KEY)], cls) from e + return cls(**obj) + + @classmethod + def parse_raw( + cls: Type['Model'], + b: StrBytes, + *, + content_type: str = None, + encoding: str = 'utf8', + proto: Protocol = None, + allow_pickle: bool = False, + ) -> 'Model': + try: + obj = load_str_bytes( + b, + proto=proto, + content_type=content_type, + encoding=encoding, + allow_pickle=allow_pickle, + json_loads=cls.__config__.json_loads, + ) + except (ValueError, TypeError, UnicodeDecodeError) as e: + raise ValidationError([ErrorWrapper(e, loc=ROOT_KEY)], cls) + return cls.parse_obj(obj) + + @classmethod + def parse_file( + cls: Type['Model'], + path: Union[str, Path], + *, + content_type: str = None, + encoding: str = 'utf8', + proto: Protocol = None, + allow_pickle: bool = False, + ) -> 'Model': + obj = load_file( + path, + proto=proto, + content_type=content_type, + encoding=encoding, + allow_pickle=allow_pickle, + json_loads=cls.__config__.json_loads, + ) + return cls.parse_obj(obj) + + @classmethod + def from_orm(cls: Type['Model'], obj: Any) -> 'Model': + if not cls.__config__.orm_mode: + raise ConfigError('You must have the config attribute orm_mode=True to use from_orm') + obj = {ROOT_KEY: obj} if cls.__custom_root_type__ else cls._decompose_class(obj) + m = cls.__new__(cls) + values, fields_set, validation_error = validate_model(cls, obj) + if validation_error: + raise validation_error + object_setattr(m, '__dict__', values) + object_setattr(m, '__fields_set__', fields_set) + m._init_private_attributes() + return m + + @classmethod + def construct(cls: Type['Model'], _fields_set: Optional['SetStr'] = None, **values: Any) -> 'Model': + """ + Creates a new model setting __dict__ and __fields_set__ from trusted or pre-validated data. + Default values are respected, but no other validation is performed. + Behaves as if `Config.extra = 'allow'` was set since it adds all passed values + """ + m = cls.__new__(cls) + fields_values: Dict[str, Any] = {} + for name, field in cls.__fields__.items(): + if field.alt_alias and field.alias in values: + fields_values[name] = values[field.alias] + elif name in values: + fields_values[name] = values[name] + elif not field.required: + fields_values[name] = field.get_default() + fields_values.update(values) + object_setattr(m, '__dict__', fields_values) + if _fields_set is None: + _fields_set = set(values.keys()) + object_setattr(m, '__fields_set__', _fields_set) + m._init_private_attributes() + return m + + def _copy_and_set_values(self: 'Model', values: 'DictStrAny', fields_set: 'SetStr', *, deep: bool) -> 'Model': + if deep: + # chances of having empty dict here are quite low for using smart_deepcopy + values = deepcopy(values) + + cls = self.__class__ + m = cls.__new__(cls) + object_setattr(m, '__dict__', values) + object_setattr(m, '__fields_set__', fields_set) + for name in self.__private_attributes__: + value = getattr(self, name, Undefined) + if value is not Undefined: + if deep: + value = deepcopy(value) + object_setattr(m, name, value) + + return m + + def copy( + self: 'Model', + *, + include: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']] = None, + exclude: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']] = None, + update: Optional['DictStrAny'] = None, + deep: bool = False, + ) -> 'Model': + """ + Duplicate a model, optionally choose which fields to include, exclude and change. + + :param include: fields to include in new model + :param exclude: fields to exclude from new model, as with values this takes precedence over include + :param update: values to change/add in the new model. Note: the data is not validated before creating + the new model: you should trust this data + :param deep: set to `True` to make a deep copy of the model + :return: new model instance + """ + + values = dict( + self._iter(to_dict=False, by_alias=False, include=include, exclude=exclude, exclude_unset=False), + **(update or {}), + ) + + # new `__fields_set__` can have unset optional fields with a set value in `update` kwarg + if update: + fields_set = self.__fields_set__ | update.keys() + else: + fields_set = set(self.__fields_set__) + + return self._copy_and_set_values(values, fields_set, deep=deep) + + @classmethod + def schema(cls, by_alias: bool = True, ref_template: str = default_ref_template) -> 'DictStrAny': + cached = cls.__schema_cache__.get((by_alias, ref_template)) + if cached is not None: + return cached + s = model_schema(cls, by_alias=by_alias, ref_template=ref_template) + cls.__schema_cache__[(by_alias, ref_template)] = s + return s + + @classmethod + def schema_json( + cls, *, by_alias: bool = True, ref_template: str = default_ref_template, **dumps_kwargs: Any + ) -> str: + from pydantic.v1.json import pydantic_encoder + + return cls.__config__.json_dumps( + cls.schema(by_alias=by_alias, ref_template=ref_template), default=pydantic_encoder, **dumps_kwargs + ) + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.validate + + @classmethod + def validate(cls: Type['Model'], value: Any) -> 'Model': + if isinstance(value, cls): + copy_on_model_validation = cls.__config__.copy_on_model_validation + # whether to deep or shallow copy the model on validation, None means do not copy + deep_copy: Optional[bool] = None + if copy_on_model_validation not in {'deep', 'shallow', 'none'}: + # Warn about deprecated behavior + warnings.warn( + "`copy_on_model_validation` should be a string: 'deep', 'shallow' or 'none'", DeprecationWarning + ) + if copy_on_model_validation: + deep_copy = False + + if copy_on_model_validation == 'shallow': + # shallow copy + deep_copy = False + elif copy_on_model_validation == 'deep': + # deep copy + deep_copy = True + + if deep_copy is None: + return value + else: + return value._copy_and_set_values(value.__dict__, value.__fields_set__, deep=deep_copy) + + value = cls._enforce_dict_if_root(value) + + if isinstance(value, dict): + return cls(**value) + elif cls.__config__.orm_mode: + return cls.from_orm(value) + else: + try: + value_as_dict = dict(value) + except (TypeError, ValueError) as e: + raise DictError() from e + return cls(**value_as_dict) + + @classmethod + def _decompose_class(cls: Type['Model'], obj: Any) -> GetterDict: + if isinstance(obj, GetterDict): + return obj + return cls.__config__.getter_dict(obj) + + @classmethod + @no_type_check + def _get_value( + cls, + v: Any, + to_dict: bool, + by_alias: bool, + include: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']], + exclude: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']], + exclude_unset: bool, + exclude_defaults: bool, + exclude_none: bool, + ) -> Any: + if isinstance(v, BaseModel): + if to_dict: + v_dict = v.dict( + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + include=include, + exclude=exclude, + exclude_none=exclude_none, + ) + if ROOT_KEY in v_dict: + return v_dict[ROOT_KEY] + return v_dict + else: + return v.copy(include=include, exclude=exclude) + + value_exclude = ValueItems(v, exclude) if exclude else None + value_include = ValueItems(v, include) if include else None + + if isinstance(v, dict): + return { + k_: cls._get_value( + v_, + to_dict=to_dict, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + include=value_include and value_include.for_element(k_), + exclude=value_exclude and value_exclude.for_element(k_), + exclude_none=exclude_none, + ) + for k_, v_ in v.items() + if (not value_exclude or not value_exclude.is_excluded(k_)) + and (not value_include or value_include.is_included(k_)) + } + + elif sequence_like(v): + seq_args = ( + cls._get_value( + v_, + to_dict=to_dict, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + include=value_include and value_include.for_element(i), + exclude=value_exclude and value_exclude.for_element(i), + exclude_none=exclude_none, + ) + for i, v_ in enumerate(v) + if (not value_exclude or not value_exclude.is_excluded(i)) + and (not value_include or value_include.is_included(i)) + ) + + return v.__class__(*seq_args) if is_namedtuple(v.__class__) else v.__class__(seq_args) + + elif isinstance(v, Enum) and getattr(cls.Config, 'use_enum_values', False): + return v.value + + else: + return v + + @classmethod + def __try_update_forward_refs__(cls, **localns: Any) -> None: + """ + Same as update_forward_refs but will not raise exception + when forward references are not defined. + """ + update_model_forward_refs(cls, cls.__fields__.values(), cls.__config__.json_encoders, localns, (NameError,)) + + @classmethod + def update_forward_refs(cls, **localns: Any) -> None: + """ + Try to update ForwardRefs on fields based on this Model, globalns and localns. + """ + update_model_forward_refs(cls, cls.__fields__.values(), cls.__config__.json_encoders, localns) + + def __iter__(self) -> 'TupleGenerator': + """ + so `dict(model)` works + """ + yield from self.__dict__.items() + + def _iter( + self, + to_dict: bool = False, + by_alias: bool = False, + include: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']] = None, + exclude: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']] = None, + exclude_unset: bool = False, + exclude_defaults: bool = False, + exclude_none: bool = False, + ) -> 'TupleGenerator': + # Merge field set excludes with explicit exclude parameter with explicit overriding field set options. + # The extra "is not None" guards are not logically necessary but optimizes performance for the simple case. + if exclude is not None or self.__exclude_fields__ is not None: + exclude = ValueItems.merge(self.__exclude_fields__, exclude) + + if include is not None or self.__include_fields__ is not None: + include = ValueItems.merge(self.__include_fields__, include, intersect=True) + + allowed_keys = self._calculate_keys( + include=include, exclude=exclude, exclude_unset=exclude_unset # type: ignore + ) + if allowed_keys is None and not (to_dict or by_alias or exclude_unset or exclude_defaults or exclude_none): + # huge boost for plain _iter() + yield from self.__dict__.items() + return + + value_exclude = ValueItems(self, exclude) if exclude is not None else None + value_include = ValueItems(self, include) if include is not None else None + + for field_key, v in self.__dict__.items(): + if (allowed_keys is not None and field_key not in allowed_keys) or (exclude_none and v is None): + continue + + if exclude_defaults: + model_field = self.__fields__.get(field_key) + if not getattr(model_field, 'required', True) and getattr(model_field, 'default', _missing) == v: + continue + + if by_alias and field_key in self.__fields__: + dict_key = self.__fields__[field_key].alias + else: + dict_key = field_key + + if to_dict or value_include or value_exclude: + v = self._get_value( + v, + to_dict=to_dict, + by_alias=by_alias, + include=value_include and value_include.for_element(field_key), + exclude=value_exclude and value_exclude.for_element(field_key), + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + yield dict_key, v + + def _calculate_keys( + self, + include: Optional['MappingIntStrAny'], + exclude: Optional['MappingIntStrAny'], + exclude_unset: bool, + update: Optional['DictStrAny'] = None, + ) -> Optional[AbstractSet[str]]: + if include is None and exclude is None and exclude_unset is False: + return None + + keys: AbstractSet[str] + if exclude_unset: + keys = self.__fields_set__.copy() + else: + keys = self.__dict__.keys() + + if include is not None: + keys &= include.keys() + + if update: + keys -= update.keys() + + if exclude: + keys -= {k for k, v in exclude.items() if ValueItems.is_true(v)} + + return keys + + def __eq__(self, other: Any) -> bool: + if isinstance(other, BaseModel): + return self.dict() == other.dict() + else: + return self.dict() == other + + def __repr_args__(self) -> 'ReprArgs': + return [ + (k, v) + for k, v in self.__dict__.items() + if k not in DUNDER_ATTRIBUTES and (k not in self.__fields__ or self.__fields__[k].field_info.repr) + ] + + +_is_base_model_class_defined = True + + +@overload +def create_model( + __model_name: str, + *, + __config__: Optional[Type[BaseConfig]] = None, + __base__: None = None, + __module__: str = __name__, + __validators__: Dict[str, 'AnyClassMethod'] = None, + __cls_kwargs__: Dict[str, Any] = None, + **field_definitions: Any, +) -> Type['BaseModel']: + ... + + +@overload +def create_model( + __model_name: str, + *, + __config__: Optional[Type[BaseConfig]] = None, + __base__: Union[Type['Model'], Tuple[Type['Model'], ...]], + __module__: str = __name__, + __validators__: Dict[str, 'AnyClassMethod'] = None, + __cls_kwargs__: Dict[str, Any] = None, + **field_definitions: Any, +) -> Type['Model']: + ... + + +def create_model( + __model_name: str, + *, + __config__: Optional[Type[BaseConfig]] = None, + __base__: Union[None, Type['Model'], Tuple[Type['Model'], ...]] = None, + __module__: str = __name__, + __validators__: Dict[str, 'AnyClassMethod'] = None, + __cls_kwargs__: Dict[str, Any] = None, + __slots__: Optional[Tuple[str, ...]] = None, + **field_definitions: Any, +) -> Type['Model']: + """ + Dynamically create a model. + :param __model_name: name of the created model + :param __config__: config class to use for the new model + :param __base__: base class for the new model to inherit from + :param __module__: module of the created model + :param __validators__: a dict of method names and @validator class methods + :param __cls_kwargs__: a dict for class creation + :param __slots__: Deprecated, `__slots__` should not be passed to `create_model` + :param field_definitions: fields of the model (or extra fields if a base is supplied) + in the format `=(, )` or `=, e.g. + `foobar=(str, ...)` or `foobar=123`, or, for complex use-cases, in the format + `=` or `=(, )`, e.g. + `foo=Field(datetime, default_factory=datetime.utcnow, alias='bar')` or + `foo=(str, FieldInfo(title='Foo'))` + """ + if __slots__ is not None: + # __slots__ will be ignored from here on + warnings.warn('__slots__ should not be passed to create_model', RuntimeWarning) + + if __base__ is not None: + if __config__ is not None: + raise ConfigError('to avoid confusion __config__ and __base__ cannot be used together') + if not isinstance(__base__, tuple): + __base__ = (__base__,) + else: + __base__ = (cast(Type['Model'], BaseModel),) + + __cls_kwargs__ = __cls_kwargs__ or {} + + fields = {} + annotations = {} + + for f_name, f_def in field_definitions.items(): + if not is_valid_field(f_name): + warnings.warn(f'fields may not start with an underscore, ignoring "{f_name}"', RuntimeWarning) + if isinstance(f_def, tuple): + try: + f_annotation, f_value = f_def + except ValueError as e: + raise ConfigError( + 'field definitions should either be a tuple of (, ) or just a ' + 'default value, unfortunately this means tuples as ' + 'default values are not allowed' + ) from e + else: + f_annotation, f_value = None, f_def + + if f_annotation: + annotations[f_name] = f_annotation + fields[f_name] = f_value + + namespace: 'DictStrAny' = {'__annotations__': annotations, '__module__': __module__} + if __validators__: + namespace.update(__validators__) + namespace.update(fields) + if __config__: + namespace['Config'] = inherit_config(__config__, BaseConfig) + resolved_bases = resolve_bases(__base__) + meta, ns, kwds = prepare_class(__model_name, resolved_bases, kwds=__cls_kwargs__) + if resolved_bases is not __base__: + ns['__orig_bases__'] = __base__ + namespace.update(ns) + return meta(__model_name, resolved_bases, namespace, **kwds) + + +_missing = object() + + +def validate_model( # noqa: C901 (ignore complexity) + model: Type[BaseModel], input_data: 'DictStrAny', cls: 'ModelOrDc' = None +) -> Tuple['DictStrAny', 'SetStr', Optional[ValidationError]]: + """ + validate data against a model. + """ + values = {} + errors = [] + # input_data names, possibly alias + names_used = set() + # field names, never aliases + fields_set = set() + config = model.__config__ + check_extra = config.extra is not Extra.ignore + cls_ = cls or model + + for validator in model.__pre_root_validators__: + try: + input_data = validator(cls_, input_data) + except (ValueError, TypeError, AssertionError) as exc: + return {}, set(), ValidationError([ErrorWrapper(exc, loc=ROOT_KEY)], cls_) + + for name, field in model.__fields__.items(): + value = input_data.get(field.alias, _missing) + using_name = False + if value is _missing and config.allow_population_by_field_name and field.alt_alias: + value = input_data.get(field.name, _missing) + using_name = True + + if value is _missing: + if field.required: + errors.append(ErrorWrapper(MissingError(), loc=field.alias)) + continue + + value = field.get_default() + + if not config.validate_all and not field.validate_always: + values[name] = value + continue + else: + fields_set.add(name) + if check_extra: + names_used.add(field.name if using_name else field.alias) + + v_, errors_ = field.validate(value, values, loc=field.alias, cls=cls_) + if isinstance(errors_, ErrorWrapper): + errors.append(errors_) + elif isinstance(errors_, list): + errors.extend(errors_) + else: + values[name] = v_ + + if check_extra: + if isinstance(input_data, GetterDict): + extra = input_data.extra_keys() - names_used + else: + extra = input_data.keys() - names_used + if extra: + fields_set |= extra + if config.extra is Extra.allow: + for f in extra: + values[f] = input_data[f] + else: + for f in sorted(extra): + errors.append(ErrorWrapper(ExtraError(), loc=f)) + + for skip_on_failure, validator in model.__post_root_validators__: + if skip_on_failure and errors: + continue + try: + values = validator(cls_, values) + except (ValueError, TypeError, AssertionError) as exc: + errors.append(ErrorWrapper(exc, loc=ROOT_KEY)) + + if errors: + return values, fields_set, ValidationError(errors, cls_) + else: + return values, fields_set, None diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/mypy.py b/backend/.venv/Lib/site-packages/pydantic/v1/mypy.py new file mode 100644 index 0000000..0a77569 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/mypy.py @@ -0,0 +1,949 @@ +import sys +from configparser import ConfigParser +from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Type as TypingType, Union + +from mypy.errorcodes import ErrorCode +from mypy.nodes import ( + ARG_NAMED, + ARG_NAMED_OPT, + ARG_OPT, + ARG_POS, + ARG_STAR2, + MDEF, + Argument, + AssignmentStmt, + Block, + CallExpr, + ClassDef, + Context, + Decorator, + EllipsisExpr, + FuncBase, + FuncDef, + JsonDict, + MemberExpr, + NameExpr, + PassStmt, + PlaceholderNode, + RefExpr, + StrExpr, + SymbolNode, + SymbolTableNode, + TempNode, + TypeInfo, + TypeVarExpr, + Var, +) +from mypy.options import Options +from mypy.plugin import ( + CheckerPluginInterface, + ClassDefContext, + FunctionContext, + MethodContext, + Plugin, + ReportConfigContext, + SemanticAnalyzerPluginInterface, +) +from mypy.plugins import dataclasses +from mypy.semanal import set_callable_name # type: ignore +from mypy.server.trigger import make_wildcard_trigger +from mypy.types import ( + AnyType, + CallableType, + Instance, + NoneType, + Overloaded, + ProperType, + Type, + TypeOfAny, + TypeType, + TypeVarId, + TypeVarType, + UnionType, + get_proper_type, +) +from mypy.typevars import fill_typevars +from mypy.util import get_unique_redefinition_name +from mypy.version import __version__ as mypy_version + +from pydantic.v1.utils import is_valid_field + +try: + from mypy.types import TypeVarDef # type: ignore[attr-defined] +except ImportError: # pragma: no cover + # Backward-compatible with TypeVarDef from Mypy 0.910. + from mypy.types import TypeVarType as TypeVarDef + +CONFIGFILE_KEY = 'pydantic-mypy' +METADATA_KEY = 'pydantic-mypy-metadata' +_NAMESPACE = __name__[:-5] # 'pydantic' in 1.10.X, 'pydantic.v1' in v2.X +BASEMODEL_FULLNAME = f'{_NAMESPACE}.main.BaseModel' +BASESETTINGS_FULLNAME = f'{_NAMESPACE}.env_settings.BaseSettings' +MODEL_METACLASS_FULLNAME = f'{_NAMESPACE}.main.ModelMetaclass' +FIELD_FULLNAME = f'{_NAMESPACE}.fields.Field' +DATACLASS_FULLNAME = f'{_NAMESPACE}.dataclasses.dataclass' + + +def parse_mypy_version(version: str) -> Tuple[int, ...]: + return tuple(map(int, version.partition('+')[0].split('.'))) + + +MYPY_VERSION_TUPLE = parse_mypy_version(mypy_version) +BUILTINS_NAME = 'builtins' if MYPY_VERSION_TUPLE >= (0, 930) else '__builtins__' + +# Increment version if plugin changes and mypy caches should be invalidated +__version__ = 2 + + +def plugin(version: str) -> 'TypingType[Plugin]': + """ + `version` is the mypy version string + + We might want to use this to print a warning if the mypy version being used is + newer, or especially older, than we expect (or need). + """ + return PydanticPlugin + + +class PydanticPlugin(Plugin): + def __init__(self, options: Options) -> None: + self.plugin_config = PydanticPluginConfig(options) + self._plugin_data = self.plugin_config.to_data() + super().__init__(options) + + def get_base_class_hook(self, fullname: str) -> 'Optional[Callable[[ClassDefContext], None]]': + sym = self.lookup_fully_qualified(fullname) + if sym and isinstance(sym.node, TypeInfo): # pragma: no branch + # No branching may occur if the mypy cache has not been cleared + if any(get_fullname(base) == BASEMODEL_FULLNAME for base in sym.node.mro): + return self._pydantic_model_class_maker_callback + return None + + def get_metaclass_hook(self, fullname: str) -> Optional[Callable[[ClassDefContext], None]]: + if fullname == MODEL_METACLASS_FULLNAME: + return self._pydantic_model_metaclass_marker_callback + return None + + def get_function_hook(self, fullname: str) -> 'Optional[Callable[[FunctionContext], Type]]': + sym = self.lookup_fully_qualified(fullname) + if sym and sym.fullname == FIELD_FULLNAME: + return self._pydantic_field_callback + return None + + def get_method_hook(self, fullname: str) -> Optional[Callable[[MethodContext], Type]]: + if fullname.endswith('.from_orm'): + return from_orm_callback + return None + + def get_class_decorator_hook(self, fullname: str) -> Optional[Callable[[ClassDefContext], None]]: + """Mark pydantic.dataclasses as dataclass. + + Mypy version 1.1.1 added support for `@dataclass_transform` decorator. + """ + if fullname == DATACLASS_FULLNAME and MYPY_VERSION_TUPLE < (1, 1): + return dataclasses.dataclass_class_maker_callback # type: ignore[return-value] + return None + + def report_config_data(self, ctx: ReportConfigContext) -> Dict[str, Any]: + """Return all plugin config data. + + Used by mypy to determine if cache needs to be discarded. + """ + return self._plugin_data + + def _pydantic_model_class_maker_callback(self, ctx: ClassDefContext) -> None: + transformer = PydanticModelTransformer(ctx, self.plugin_config) + transformer.transform() + + def _pydantic_model_metaclass_marker_callback(self, ctx: ClassDefContext) -> None: + """Reset dataclass_transform_spec attribute of ModelMetaclass. + + Let the plugin handle it. This behavior can be disabled + if 'debug_dataclass_transform' is set to True', for testing purposes. + """ + if self.plugin_config.debug_dataclass_transform: + return + info_metaclass = ctx.cls.info.declared_metaclass + assert info_metaclass, "callback not passed from 'get_metaclass_hook'" + if getattr(info_metaclass.type, 'dataclass_transform_spec', None): + info_metaclass.type.dataclass_transform_spec = None # type: ignore[attr-defined] + + def _pydantic_field_callback(self, ctx: FunctionContext) -> 'Type': + """ + Extract the type of the `default` argument from the Field function, and use it as the return type. + + In particular: + * Check whether the default and default_factory argument is specified. + * Output an error if both are specified. + * Retrieve the type of the argument which is specified, and use it as return type for the function. + """ + default_any_type = ctx.default_return_type + + assert ctx.callee_arg_names[0] == 'default', '"default" is no longer first argument in Field()' + assert ctx.callee_arg_names[1] == 'default_factory', '"default_factory" is no longer second argument in Field()' + default_args = ctx.args[0] + default_factory_args = ctx.args[1] + + if default_args and default_factory_args: + error_default_and_default_factory_specified(ctx.api, ctx.context) + return default_any_type + + if default_args: + default_type = ctx.arg_types[0][0] + default_arg = default_args[0] + + # Fallback to default Any type if the field is required + if not isinstance(default_arg, EllipsisExpr): + return default_type + + elif default_factory_args: + default_factory_type = ctx.arg_types[1][0] + + # Functions which use `ParamSpec` can be overloaded, exposing the callable's types as a parameter + # Pydantic calls the default factory without any argument, so we retrieve the first item + if isinstance(default_factory_type, Overloaded): + if MYPY_VERSION_TUPLE > (0, 910): + default_factory_type = default_factory_type.items[0] + else: + # Mypy0.910 exposes the items of overloaded types in a function + default_factory_type = default_factory_type.items()[0] # type: ignore[operator] + + if isinstance(default_factory_type, CallableType): + ret_type = get_proper_type(default_factory_type.ret_type) + if ( + isinstance(ret_type, Instance) + and ret_type.args + and all(isinstance(arg, TypeVarType) for arg in ret_type.args) + ): + # Looks like the default factory is a type like `list` or `dict`, replace all args with `Any` + ret_type = ret_type.copy_modified(args=[default_any_type] * len(ret_type.args)) + return ret_type + + return default_any_type + + +class PydanticPluginConfig: + __slots__ = ( + 'init_forbid_extra', + 'init_typed', + 'warn_required_dynamic_aliases', + 'warn_untyped_fields', + 'debug_dataclass_transform', + ) + init_forbid_extra: bool + init_typed: bool + warn_required_dynamic_aliases: bool + warn_untyped_fields: bool + debug_dataclass_transform: bool # undocumented + + def __init__(self, options: Options) -> None: + if options.config_file is None: # pragma: no cover + return + + toml_config = parse_toml(options.config_file) + if toml_config is not None: + config = toml_config.get('tool', {}).get('pydantic-mypy', {}) + for key in self.__slots__: + setting = config.get(key, False) + if not isinstance(setting, bool): + raise ValueError(f'Configuration value must be a boolean for key: {key}') + setattr(self, key, setting) + else: + plugin_config = ConfigParser() + plugin_config.read(options.config_file) + for key in self.__slots__: + setting = plugin_config.getboolean(CONFIGFILE_KEY, key, fallback=False) + setattr(self, key, setting) + + def to_data(self) -> Dict[str, Any]: + return {key: getattr(self, key) for key in self.__slots__} + + +def from_orm_callback(ctx: MethodContext) -> Type: + """ + Raise an error if orm_mode is not enabled + """ + model_type: Instance + ctx_type = ctx.type + if isinstance(ctx_type, TypeType): + ctx_type = ctx_type.item + if isinstance(ctx_type, CallableType) and isinstance(ctx_type.ret_type, Instance): + model_type = ctx_type.ret_type # called on the class + elif isinstance(ctx_type, Instance): + model_type = ctx_type # called on an instance (unusual, but still valid) + else: # pragma: no cover + detail = f'ctx.type: {ctx_type} (of type {ctx_type.__class__.__name__})' + error_unexpected_behavior(detail, ctx.api, ctx.context) + return ctx.default_return_type + pydantic_metadata = model_type.type.metadata.get(METADATA_KEY) + if pydantic_metadata is None: + return ctx.default_return_type + orm_mode = pydantic_metadata.get('config', {}).get('orm_mode') + if orm_mode is not True: + error_from_orm(get_name(model_type.type), ctx.api, ctx.context) + return ctx.default_return_type + + +class PydanticModelTransformer: + tracked_config_fields: Set[str] = { + 'extra', + 'allow_mutation', + 'frozen', + 'orm_mode', + 'allow_population_by_field_name', + 'alias_generator', + } + + def __init__(self, ctx: ClassDefContext, plugin_config: PydanticPluginConfig) -> None: + self._ctx = ctx + self.plugin_config = plugin_config + + def transform(self) -> None: + """ + Configures the BaseModel subclass according to the plugin settings. + + In particular: + * determines the model config and fields, + * adds a fields-aware signature for the initializer and construct methods + * freezes the class if allow_mutation = False or frozen = True + * stores the fields, config, and if the class is settings in the mypy metadata for access by subclasses + """ + ctx = self._ctx + info = ctx.cls.info + + self.adjust_validator_signatures() + config = self.collect_config() + fields = self.collect_fields(config) + is_settings = any(get_fullname(base) == BASESETTINGS_FULLNAME for base in info.mro[:-1]) + self.add_initializer(fields, config, is_settings) + self.add_construct_method(fields) + self.set_frozen(fields, frozen=config.allow_mutation is False or config.frozen is True) + info.metadata[METADATA_KEY] = { + 'fields': {field.name: field.serialize() for field in fields}, + 'config': config.set_values_dict(), + } + + def adjust_validator_signatures(self) -> None: + """When we decorate a function `f` with `pydantic.validator(...), mypy sees + `f` as a regular method taking a `self` instance, even though pydantic + internally wraps `f` with `classmethod` if necessary. + + Teach mypy this by marking any function whose outermost decorator is a + `validator()` call as a classmethod. + """ + for name, sym in self._ctx.cls.info.names.items(): + if isinstance(sym.node, Decorator): + first_dec = sym.node.original_decorators[0] + if ( + isinstance(first_dec, CallExpr) + and isinstance(first_dec.callee, NameExpr) + and first_dec.callee.fullname == f'{_NAMESPACE}.class_validators.validator' + ): + sym.node.func.is_class = True + + def collect_config(self) -> 'ModelConfigData': + """ + Collects the values of the config attributes that are used by the plugin, accounting for parent classes. + """ + ctx = self._ctx + cls = ctx.cls + config = ModelConfigData() + for stmt in cls.defs.body: + if not isinstance(stmt, ClassDef): + continue + if stmt.name == 'Config': + for substmt in stmt.defs.body: + if not isinstance(substmt, AssignmentStmt): + continue + config.update(self.get_config_update(substmt)) + if ( + config.has_alias_generator + and not config.allow_population_by_field_name + and self.plugin_config.warn_required_dynamic_aliases + ): + error_required_dynamic_aliases(ctx.api, stmt) + for info in cls.info.mro[1:]: # 0 is the current class + if METADATA_KEY not in info.metadata: + continue + + # Each class depends on the set of fields in its ancestors + ctx.api.add_plugin_dependency(make_wildcard_trigger(get_fullname(info))) + for name, value in info.metadata[METADATA_KEY]['config'].items(): + config.setdefault(name, value) + return config + + def collect_fields(self, model_config: 'ModelConfigData') -> List['PydanticModelField']: + """ + Collects the fields for the model, accounting for parent classes + """ + # First, collect fields belonging to the current class. + ctx = self._ctx + cls = self._ctx.cls + fields = [] # type: List[PydanticModelField] + known_fields = set() # type: Set[str] + for stmt in cls.defs.body: + if not isinstance(stmt, AssignmentStmt): # `and stmt.new_syntax` to require annotation + continue + + lhs = stmt.lvalues[0] + if not isinstance(lhs, NameExpr) or not is_valid_field(lhs.name): + continue + + if not stmt.new_syntax and self.plugin_config.warn_untyped_fields: + error_untyped_fields(ctx.api, stmt) + + # if lhs.name == '__config__': # BaseConfig not well handled; I'm not sure why yet + # continue + + sym = cls.info.names.get(lhs.name) + if sym is None: # pragma: no cover + # This is likely due to a star import (see the dataclasses plugin for a more detailed explanation) + # This is the same logic used in the dataclasses plugin + continue + + node = sym.node + if isinstance(node, PlaceholderNode): # pragma: no cover + # See the PlaceholderNode docstring for more detail about how this can occur + # Basically, it is an edge case when dealing with complex import logic + # This is the same logic used in the dataclasses plugin + continue + if not isinstance(node, Var): # pragma: no cover + # Don't know if this edge case still happens with the `is_valid_field` check above + # but better safe than sorry + continue + + # x: ClassVar[int] is ignored by dataclasses. + if node.is_classvar: + continue + + is_required = self.get_is_required(cls, stmt, lhs) + alias, has_dynamic_alias = self.get_alias_info(stmt) + if ( + has_dynamic_alias + and not model_config.allow_population_by_field_name + and self.plugin_config.warn_required_dynamic_aliases + ): + error_required_dynamic_aliases(ctx.api, stmt) + fields.append( + PydanticModelField( + name=lhs.name, + is_required=is_required, + alias=alias, + has_dynamic_alias=has_dynamic_alias, + line=stmt.line, + column=stmt.column, + ) + ) + known_fields.add(lhs.name) + all_fields = fields.copy() + for info in cls.info.mro[1:]: # 0 is the current class, -2 is BaseModel, -1 is object + if METADATA_KEY not in info.metadata: + continue + + superclass_fields = [] + # Each class depends on the set of fields in its ancestors + ctx.api.add_plugin_dependency(make_wildcard_trigger(get_fullname(info))) + + for name, data in info.metadata[METADATA_KEY]['fields'].items(): + if name not in known_fields: + field = PydanticModelField.deserialize(info, data) + known_fields.add(name) + superclass_fields.append(field) + else: + (field,) = (a for a in all_fields if a.name == name) + all_fields.remove(field) + superclass_fields.append(field) + all_fields = superclass_fields + all_fields + return all_fields + + def add_initializer(self, fields: List['PydanticModelField'], config: 'ModelConfigData', is_settings: bool) -> None: + """ + Adds a fields-aware `__init__` method to the class. + + The added `__init__` will be annotated with types vs. all `Any` depending on the plugin settings. + """ + ctx = self._ctx + typed = self.plugin_config.init_typed + use_alias = config.allow_population_by_field_name is not True + force_all_optional = is_settings or bool( + config.has_alias_generator and not config.allow_population_by_field_name + ) + init_arguments = self.get_field_arguments( + fields, typed=typed, force_all_optional=force_all_optional, use_alias=use_alias + ) + if not self.should_init_forbid_extra(fields, config): + var = Var('kwargs') + init_arguments.append(Argument(var, AnyType(TypeOfAny.explicit), None, ARG_STAR2)) + + if '__init__' not in ctx.cls.info.names: + add_method(ctx, '__init__', init_arguments, NoneType()) + + def add_construct_method(self, fields: List['PydanticModelField']) -> None: + """ + Adds a fully typed `construct` classmethod to the class. + + Similar to the fields-aware __init__ method, but always uses the field names (not aliases), + and does not treat settings fields as optional. + """ + ctx = self._ctx + set_str = ctx.api.named_type(f'{BUILTINS_NAME}.set', [ctx.api.named_type(f'{BUILTINS_NAME}.str')]) + optional_set_str = UnionType([set_str, NoneType()]) + fields_set_argument = Argument(Var('_fields_set', optional_set_str), optional_set_str, None, ARG_OPT) + construct_arguments = self.get_field_arguments(fields, typed=True, force_all_optional=False, use_alias=False) + construct_arguments = [fields_set_argument] + construct_arguments + + obj_type = ctx.api.named_type(f'{BUILTINS_NAME}.object') + self_tvar_name = '_PydanticBaseModel' # Make sure it does not conflict with other names in the class + tvar_fullname = ctx.cls.fullname + '.' + self_tvar_name + if MYPY_VERSION_TUPLE >= (1, 4): + tvd = TypeVarType( + self_tvar_name, + tvar_fullname, + ( + TypeVarId(-1, namespace=ctx.cls.fullname + '.construct') + if MYPY_VERSION_TUPLE >= (1, 11) + else TypeVarId(-1) + ), + [], + obj_type, + AnyType(TypeOfAny.from_omitted_generics), # type: ignore[arg-type] + ) + self_tvar_expr = TypeVarExpr( + self_tvar_name, + tvar_fullname, + [], + obj_type, + AnyType(TypeOfAny.from_omitted_generics), # type: ignore[arg-type] + ) + else: + tvd = TypeVarDef(self_tvar_name, tvar_fullname, -1, [], obj_type) + self_tvar_expr = TypeVarExpr(self_tvar_name, tvar_fullname, [], obj_type) + ctx.cls.info.names[self_tvar_name] = SymbolTableNode(MDEF, self_tvar_expr) + + # Backward-compatible with TypeVarDef from Mypy 0.910. + if isinstance(tvd, TypeVarType): + self_type = tvd + else: + self_type = TypeVarType(tvd) + + add_method( + ctx, + 'construct', + construct_arguments, + return_type=self_type, + self_type=self_type, + tvar_def=tvd, + is_classmethod=True, + ) + + def set_frozen(self, fields: List['PydanticModelField'], frozen: bool) -> None: + """ + Marks all fields as properties so that attempts to set them trigger mypy errors. + + This is the same approach used by the attrs and dataclasses plugins. + """ + ctx = self._ctx + info = ctx.cls.info + for field in fields: + sym_node = info.names.get(field.name) + if sym_node is not None: + var = sym_node.node + if isinstance(var, Var): + var.is_property = frozen + elif isinstance(var, PlaceholderNode) and not ctx.api.final_iteration: + # See https://github.com/pydantic/pydantic/issues/5191 to hit this branch for test coverage + ctx.api.defer() + else: # pragma: no cover + # I don't know whether it's possible to hit this branch, but I've added it for safety + try: + var_str = str(var) + except TypeError: + # This happens for PlaceholderNode; perhaps it will happen for other types in the future.. + var_str = repr(var) + detail = f'sym_node.node: {var_str} (of type {var.__class__})' + error_unexpected_behavior(detail, ctx.api, ctx.cls) + else: + var = field.to_var(info, use_alias=False) + var.info = info + var.is_property = frozen + var._fullname = get_fullname(info) + '.' + get_name(var) + info.names[get_name(var)] = SymbolTableNode(MDEF, var) + + def get_config_update(self, substmt: AssignmentStmt) -> Optional['ModelConfigData']: + """ + Determines the config update due to a single statement in the Config class definition. + + Warns if a tracked config attribute is set to a value the plugin doesn't know how to interpret (e.g., an int) + """ + lhs = substmt.lvalues[0] + if not (isinstance(lhs, NameExpr) and lhs.name in self.tracked_config_fields): + return None + if lhs.name == 'extra': + if isinstance(substmt.rvalue, StrExpr): + forbid_extra = substmt.rvalue.value == 'forbid' + elif isinstance(substmt.rvalue, MemberExpr): + forbid_extra = substmt.rvalue.name == 'forbid' + else: + error_invalid_config_value(lhs.name, self._ctx.api, substmt) + return None + return ModelConfigData(forbid_extra=forbid_extra) + if lhs.name == 'alias_generator': + has_alias_generator = True + if isinstance(substmt.rvalue, NameExpr) and substmt.rvalue.fullname == 'builtins.None': + has_alias_generator = False + return ModelConfigData(has_alias_generator=has_alias_generator) + if isinstance(substmt.rvalue, NameExpr) and substmt.rvalue.fullname in ('builtins.True', 'builtins.False'): + return ModelConfigData(**{lhs.name: substmt.rvalue.fullname == 'builtins.True'}) + error_invalid_config_value(lhs.name, self._ctx.api, substmt) + return None + + @staticmethod + def get_is_required(cls: ClassDef, stmt: AssignmentStmt, lhs: NameExpr) -> bool: + """ + Returns a boolean indicating whether the field defined in `stmt` is a required field. + """ + expr = stmt.rvalue + if isinstance(expr, TempNode): + # TempNode means annotation-only, so only non-required if Optional + value_type = get_proper_type(cls.info[lhs.name].type) + return not PydanticModelTransformer.type_has_implicit_default(value_type) + if isinstance(expr, CallExpr) and isinstance(expr.callee, RefExpr) and expr.callee.fullname == FIELD_FULLNAME: + # The "default value" is a call to `Field`; at this point, the field is + # only required if default is Ellipsis (i.e., `field_name: Annotation = Field(...)`) or if default_factory + # is specified. + for arg, name in zip(expr.args, expr.arg_names): + # If name is None, then this arg is the default because it is the only positional argument. + if name is None or name == 'default': + return arg.__class__ is EllipsisExpr + if name == 'default_factory': + return False + # In this case, default and default_factory are not specified, so we need to look at the annotation + value_type = get_proper_type(cls.info[lhs.name].type) + return not PydanticModelTransformer.type_has_implicit_default(value_type) + # Only required if the "default value" is Ellipsis (i.e., `field_name: Annotation = ...`) + return isinstance(expr, EllipsisExpr) + + @staticmethod + def type_has_implicit_default(type_: Optional[ProperType]) -> bool: + """ + Returns True if the passed type will be given an implicit default value. + + In pydantic v1, this is the case for Optional types and Any (with default value None). + """ + if isinstance(type_, AnyType): + # Annotated as Any + return True + if isinstance(type_, UnionType) and any( + isinstance(item, NoneType) or isinstance(item, AnyType) for item in type_.items + ): + # Annotated as Optional, or otherwise having NoneType or AnyType in the union + return True + return False + + @staticmethod + def get_alias_info(stmt: AssignmentStmt) -> Tuple[Optional[str], bool]: + """ + Returns a pair (alias, has_dynamic_alias), extracted from the declaration of the field defined in `stmt`. + + `has_dynamic_alias` is True if and only if an alias is provided, but not as a string literal. + If `has_dynamic_alias` is True, `alias` will be None. + """ + expr = stmt.rvalue + if isinstance(expr, TempNode): + # TempNode means annotation-only + return None, False + + if not ( + isinstance(expr, CallExpr) and isinstance(expr.callee, RefExpr) and expr.callee.fullname == FIELD_FULLNAME + ): + # Assigned value is not a call to pydantic.fields.Field + return None, False + + for i, arg_name in enumerate(expr.arg_names): + if arg_name != 'alias': + continue + arg = expr.args[i] + if isinstance(arg, StrExpr): + return arg.value, False + else: + return None, True + return None, False + + def get_field_arguments( + self, fields: List['PydanticModelField'], typed: bool, force_all_optional: bool, use_alias: bool + ) -> List[Argument]: + """ + Helper function used during the construction of the `__init__` and `construct` method signatures. + + Returns a list of mypy Argument instances for use in the generated signatures. + """ + info = self._ctx.cls.info + arguments = [ + field.to_argument(info, typed=typed, force_optional=force_all_optional, use_alias=use_alias) + for field in fields + if not (use_alias and field.has_dynamic_alias) + ] + return arguments + + def should_init_forbid_extra(self, fields: List['PydanticModelField'], config: 'ModelConfigData') -> bool: + """ + Indicates whether the generated `__init__` should get a `**kwargs` at the end of its signature + + We disallow arbitrary kwargs if the extra config setting is "forbid", or if the plugin config says to, + *unless* a required dynamic alias is present (since then we can't determine a valid signature). + """ + if not config.allow_population_by_field_name: + if self.is_dynamic_alias_present(fields, bool(config.has_alias_generator)): + return False + if config.forbid_extra: + return True + return self.plugin_config.init_forbid_extra + + @staticmethod + def is_dynamic_alias_present(fields: List['PydanticModelField'], has_alias_generator: bool) -> bool: + """ + Returns whether any fields on the model have a "dynamic alias", i.e., an alias that cannot be + determined during static analysis. + """ + for field in fields: + if field.has_dynamic_alias: + return True + if has_alias_generator: + for field in fields: + if field.alias is None: + return True + return False + + +class PydanticModelField: + def __init__( + self, name: str, is_required: bool, alias: Optional[str], has_dynamic_alias: bool, line: int, column: int + ): + self.name = name + self.is_required = is_required + self.alias = alias + self.has_dynamic_alias = has_dynamic_alias + self.line = line + self.column = column + + def to_var(self, info: TypeInfo, use_alias: bool) -> Var: + name = self.name + if use_alias and self.alias is not None: + name = self.alias + return Var(name, info[self.name].type) + + def to_argument(self, info: TypeInfo, typed: bool, force_optional: bool, use_alias: bool) -> Argument: + if typed and info[self.name].type is not None: + type_annotation = info[self.name].type + else: + type_annotation = AnyType(TypeOfAny.explicit) + return Argument( + variable=self.to_var(info, use_alias), + type_annotation=type_annotation, + initializer=None, + kind=ARG_NAMED_OPT if force_optional or not self.is_required else ARG_NAMED, + ) + + def serialize(self) -> JsonDict: + return self.__dict__ + + @classmethod + def deserialize(cls, info: TypeInfo, data: JsonDict) -> 'PydanticModelField': + return cls(**data) + + +class ModelConfigData: + def __init__( + self, + forbid_extra: Optional[bool] = None, + allow_mutation: Optional[bool] = None, + frozen: Optional[bool] = None, + orm_mode: Optional[bool] = None, + allow_population_by_field_name: Optional[bool] = None, + has_alias_generator: Optional[bool] = None, + ): + self.forbid_extra = forbid_extra + self.allow_mutation = allow_mutation + self.frozen = frozen + self.orm_mode = orm_mode + self.allow_population_by_field_name = allow_population_by_field_name + self.has_alias_generator = has_alias_generator + + def set_values_dict(self) -> Dict[str, Any]: + return {k: v for k, v in self.__dict__.items() if v is not None} + + def update(self, config: Optional['ModelConfigData']) -> None: + if config is None: + return + for k, v in config.set_values_dict().items(): + setattr(self, k, v) + + def setdefault(self, key: str, value: Any) -> None: + if getattr(self, key) is None: + setattr(self, key, value) + + +ERROR_ORM = ErrorCode('pydantic-orm', 'Invalid from_orm call', 'Pydantic') +ERROR_CONFIG = ErrorCode('pydantic-config', 'Invalid config value', 'Pydantic') +ERROR_ALIAS = ErrorCode('pydantic-alias', 'Dynamic alias disallowed', 'Pydantic') +ERROR_UNEXPECTED = ErrorCode('pydantic-unexpected', 'Unexpected behavior', 'Pydantic') +ERROR_UNTYPED = ErrorCode('pydantic-field', 'Untyped field disallowed', 'Pydantic') +ERROR_FIELD_DEFAULTS = ErrorCode('pydantic-field', 'Invalid Field defaults', 'Pydantic') + + +def error_from_orm(model_name: str, api: CheckerPluginInterface, context: Context) -> None: + api.fail(f'"{model_name}" does not have orm_mode=True', context, code=ERROR_ORM) + + +def error_invalid_config_value(name: str, api: SemanticAnalyzerPluginInterface, context: Context) -> None: + api.fail(f'Invalid value for "Config.{name}"', context, code=ERROR_CONFIG) + + +def error_required_dynamic_aliases(api: SemanticAnalyzerPluginInterface, context: Context) -> None: + api.fail('Required dynamic aliases disallowed', context, code=ERROR_ALIAS) + + +def error_unexpected_behavior( + detail: str, api: Union[CheckerPluginInterface, SemanticAnalyzerPluginInterface], context: Context +) -> None: # pragma: no cover + # Can't think of a good way to test this, but I confirmed it renders as desired by adding to a non-error path + link = 'https://github.com/pydantic/pydantic/issues/new/choose' + full_message = f'The pydantic mypy plugin ran into unexpected behavior: {detail}\n' + full_message += f'Please consider reporting this bug at {link} so we can try to fix it!' + api.fail(full_message, context, code=ERROR_UNEXPECTED) + + +def error_untyped_fields(api: SemanticAnalyzerPluginInterface, context: Context) -> None: + api.fail('Untyped fields disallowed', context, code=ERROR_UNTYPED) + + +def error_default_and_default_factory_specified(api: CheckerPluginInterface, context: Context) -> None: + api.fail('Field default and default_factory cannot be specified together', context, code=ERROR_FIELD_DEFAULTS) + + +def add_method( + ctx: ClassDefContext, + name: str, + args: List[Argument], + return_type: Type, + self_type: Optional[Type] = None, + tvar_def: Optional[TypeVarDef] = None, + is_classmethod: bool = False, + is_new: bool = False, + # is_staticmethod: bool = False, +) -> None: + """ + Adds a new method to a class. + + This can be dropped if/when https://github.com/python/mypy/issues/7301 is merged + """ + info = ctx.cls.info + + # First remove any previously generated methods with the same name + # to avoid clashes and problems in the semantic analyzer. + if name in info.names: + sym = info.names[name] + if sym.plugin_generated and isinstance(sym.node, FuncDef): + ctx.cls.defs.body.remove(sym.node) # pragma: no cover + + self_type = self_type or fill_typevars(info) + if is_classmethod or is_new: + first = [Argument(Var('_cls'), TypeType.make_normalized(self_type), None, ARG_POS)] + # elif is_staticmethod: + # first = [] + else: + self_type = self_type or fill_typevars(info) + first = [Argument(Var('__pydantic_self__'), self_type, None, ARG_POS)] + args = first + args + arg_types, arg_names, arg_kinds = [], [], [] + for arg in args: + assert arg.type_annotation, 'All arguments must be fully typed.' + arg_types.append(arg.type_annotation) + arg_names.append(get_name(arg.variable)) + arg_kinds.append(arg.kind) + + function_type = ctx.api.named_type(f'{BUILTINS_NAME}.function') + signature = CallableType( + arg_types, arg_kinds, arg_names, return_type, function_type, variables=[tvar_def] if tvar_def else None + ) + + func = FuncDef(name, args, Block([PassStmt()])) + func.info = info + func.type = set_callable_name(signature, func) + func.is_class = is_classmethod + # func.is_static = is_staticmethod + func._fullname = get_fullname(info) + '.' + name + func.line = info.line + + # NOTE: we would like the plugin generated node to dominate, but we still + # need to keep any existing definitions so they get semantically analyzed. + if name in info.names: + # Get a nice unique name instead. + r_name = get_unique_redefinition_name(name, info.names) + info.names[r_name] = info.names[name] + + if is_classmethod: # or is_staticmethod: + func.is_decorated = True + v = Var(name, func.type) + v.info = info + v._fullname = func._fullname + # if is_classmethod: + v.is_classmethod = True + dec = Decorator(func, [NameExpr('classmethod')], v) + # else: + # v.is_staticmethod = True + # dec = Decorator(func, [NameExpr('staticmethod')], v) + + dec.line = info.line + sym = SymbolTableNode(MDEF, dec) + else: + sym = SymbolTableNode(MDEF, func) + sym.plugin_generated = True + + info.names[name] = sym + info.defn.defs.body.append(func) + + +def get_fullname(x: Union[FuncBase, SymbolNode]) -> str: + """ + Used for compatibility with mypy 0.740; can be dropped once support for 0.740 is dropped. + """ + fn = x.fullname + if callable(fn): # pragma: no cover + return fn() + return fn + + +def get_name(x: Union[FuncBase, SymbolNode]) -> str: + """ + Used for compatibility with mypy 0.740; can be dropped once support for 0.740 is dropped. + """ + fn = x.name + if callable(fn): # pragma: no cover + return fn() + return fn + + +def parse_toml(config_file: str) -> Optional[Dict[str, Any]]: + if not config_file.endswith('.toml'): + return None + + read_mode = 'rb' + if sys.version_info >= (3, 11): + import tomllib as toml_ + else: + try: + import tomli as toml_ + except ImportError: + # older versions of mypy have toml as a dependency, not tomli + read_mode = 'r' + try: + import toml as toml_ # type: ignore[no-redef] + except ImportError: # pragma: no cover + import warnings + + warnings.warn('No TOML parser installed, cannot read configuration from `pyproject.toml`.') + return None + + with open(config_file, read_mode) as rf: + return toml_.load(rf) # type: ignore[arg-type] diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/networks.py b/backend/.venv/Lib/site-packages/pydantic/v1/networks.py new file mode 100644 index 0000000..ba07b74 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/networks.py @@ -0,0 +1,747 @@ +import re +from ipaddress import ( + IPv4Address, + IPv4Interface, + IPv4Network, + IPv6Address, + IPv6Interface, + IPv6Network, + _BaseAddress, + _BaseNetwork, +) +from typing import ( + TYPE_CHECKING, + Any, + Collection, + Dict, + Generator, + List, + Match, + Optional, + Pattern, + Set, + Tuple, + Type, + Union, + cast, + no_type_check, +) + +from pydantic.v1 import errors +from pydantic.v1.utils import Representation, update_not_none +from pydantic.v1.validators import constr_length_validator, str_validator + +if TYPE_CHECKING: + import email_validator + from typing_extensions import TypedDict + + from pydantic.v1.config import BaseConfig + from pydantic.v1.fields import ModelField + from pydantic.v1.typing import AnyCallable + + CallableGenerator = Generator[AnyCallable, None, None] + + class Parts(TypedDict, total=False): + scheme: str + user: Optional[str] + password: Optional[str] + ipv4: Optional[str] + ipv6: Optional[str] + domain: Optional[str] + port: Optional[str] + path: Optional[str] + query: Optional[str] + fragment: Optional[str] + + class HostParts(TypedDict, total=False): + host: str + tld: Optional[str] + host_type: Optional[str] + port: Optional[str] + rebuild: bool + +else: + email_validator = None + + class Parts(dict): + pass + + +NetworkType = Union[str, bytes, int, Tuple[Union[str, bytes, int], Union[str, int]]] + +__all__ = [ + 'AnyUrl', + 'AnyHttpUrl', + 'FileUrl', + 'HttpUrl', + 'stricturl', + 'EmailStr', + 'NameEmail', + 'IPvAnyAddress', + 'IPvAnyInterface', + 'IPvAnyNetwork', + 'PostgresDsn', + 'CockroachDsn', + 'AmqpDsn', + 'RedisDsn', + 'MongoDsn', + 'KafkaDsn', + 'validate_email', +] + +_url_regex_cache = None +_multi_host_url_regex_cache = None +_ascii_domain_regex_cache = None +_int_domain_regex_cache = None +_host_regex_cache = None + +_host_regex = ( + r'(?:' + r'(?P(?:\d{1,3}\.){3}\d{1,3})(?=$|[/:#?])|' # ipv4 + r'(?P\[[A-F0-9]*:[A-F0-9:]+\])(?=$|[/:#?])|' # ipv6 + r'(?P[^\s/:?#]+)' # domain, validation occurs later + r')?' + r'(?::(?P\d+))?' # port +) +_scheme_regex = r'(?:(?P[a-z][a-z0-9+\-.]+)://)?' # scheme https://tools.ietf.org/html/rfc3986#appendix-A +_user_info_regex = r'(?:(?P[^\s:/]*)(?::(?P[^\s/]*))?@)?' +_path_regex = r'(?P/[^\s?#]*)?' +_query_regex = r'(?:\?(?P[^\s#]*))?' +_fragment_regex = r'(?:#(?P[^\s#]*))?' + + +def url_regex() -> Pattern[str]: + global _url_regex_cache + if _url_regex_cache is None: + _url_regex_cache = re.compile( + rf'{_scheme_regex}{_user_info_regex}{_host_regex}{_path_regex}{_query_regex}{_fragment_regex}', + re.IGNORECASE, + ) + return _url_regex_cache + + +def multi_host_url_regex() -> Pattern[str]: + """ + Compiled multi host url regex. + + Additionally to `url_regex` it allows to match multiple hosts. + E.g. host1.db.net,host2.db.net + """ + global _multi_host_url_regex_cache + if _multi_host_url_regex_cache is None: + _multi_host_url_regex_cache = re.compile( + rf'{_scheme_regex}{_user_info_regex}' + r'(?P([^/]*))' # validation occurs later + rf'{_path_regex}{_query_regex}{_fragment_regex}', + re.IGNORECASE, + ) + return _multi_host_url_regex_cache + + +def ascii_domain_regex() -> Pattern[str]: + global _ascii_domain_regex_cache + if _ascii_domain_regex_cache is None: + ascii_chunk = r'[_0-9a-z](?:[-_0-9a-z]{0,61}[_0-9a-z])?' + ascii_domain_ending = r'(?P\.[a-z]{2,63})?\.?' + _ascii_domain_regex_cache = re.compile( + fr'(?:{ascii_chunk}\.)*?{ascii_chunk}{ascii_domain_ending}', re.IGNORECASE + ) + return _ascii_domain_regex_cache + + +def int_domain_regex() -> Pattern[str]: + global _int_domain_regex_cache + if _int_domain_regex_cache is None: + int_chunk = r'[_0-9a-\U00040000](?:[-_0-9a-\U00040000]{0,61}[_0-9a-\U00040000])?' + int_domain_ending = r'(?P(\.[^\W\d_]{2,63})|(\.(?:xn--)[_0-9a-z-]{2,63}))?\.?' + _int_domain_regex_cache = re.compile(fr'(?:{int_chunk}\.)*?{int_chunk}{int_domain_ending}', re.IGNORECASE) + return _int_domain_regex_cache + + +def host_regex() -> Pattern[str]: + global _host_regex_cache + if _host_regex_cache is None: + _host_regex_cache = re.compile( + _host_regex, + re.IGNORECASE, + ) + return _host_regex_cache + + +class AnyUrl(str): + strip_whitespace = True + min_length = 1 + max_length = 2**16 + allowed_schemes: Optional[Collection[str]] = None + tld_required: bool = False + user_required: bool = False + host_required: bool = True + hidden_parts: Set[str] = set() + + __slots__ = ('scheme', 'user', 'password', 'host', 'tld', 'host_type', 'port', 'path', 'query', 'fragment') + + @no_type_check + def __new__(cls, url: Optional[str], **kwargs) -> object: + return str.__new__(cls, cls.build(**kwargs) if url is None else url) + + def __init__( + self, + url: str, + *, + scheme: str, + user: Optional[str] = None, + password: Optional[str] = None, + host: Optional[str] = None, + tld: Optional[str] = None, + host_type: str = 'domain', + port: Optional[str] = None, + path: Optional[str] = None, + query: Optional[str] = None, + fragment: Optional[str] = None, + ) -> None: + str.__init__(url) + self.scheme = scheme + self.user = user + self.password = password + self.host = host + self.tld = tld + self.host_type = host_type + self.port = port + self.path = path + self.query = query + self.fragment = fragment + + @classmethod + def build( + cls, + *, + scheme: str, + user: Optional[str] = None, + password: Optional[str] = None, + host: str, + port: Optional[str] = None, + path: Optional[str] = None, + query: Optional[str] = None, + fragment: Optional[str] = None, + **_kwargs: str, + ) -> str: + parts = Parts( + scheme=scheme, + user=user, + password=password, + host=host, + port=port, + path=path, + query=query, + fragment=fragment, + **_kwargs, # type: ignore[misc] + ) + + url = scheme + '://' + if user: + url += user + if password: + url += ':' + password + if user or password: + url += '@' + url += host + if port and ('port' not in cls.hidden_parts or cls.get_default_parts(parts).get('port') != port): + url += ':' + port + if path: + url += path + if query: + url += '?' + query + if fragment: + url += '#' + fragment + return url + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none(field_schema, minLength=cls.min_length, maxLength=cls.max_length, format='uri') + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.validate + + @classmethod + def validate(cls, value: Any, field: 'ModelField', config: 'BaseConfig') -> 'AnyUrl': + if value.__class__ == cls: + return value + value = str_validator(value) + if cls.strip_whitespace: + value = value.strip() + url: str = cast(str, constr_length_validator(value, field, config)) + + m = cls._match_url(url) + # the regex should always match, if it doesn't please report with details of the URL tried + assert m, 'URL regex failed unexpectedly' + + original_parts = cast('Parts', m.groupdict()) + parts = cls.apply_default_parts(original_parts) + parts = cls.validate_parts(parts) + + if m.end() != len(url): + raise errors.UrlExtraError(extra=url[m.end() :]) + + return cls._build_url(m, url, parts) + + @classmethod + def _build_url(cls, m: Match[str], url: str, parts: 'Parts') -> 'AnyUrl': + """ + Validate hosts and build the AnyUrl object. Split from `validate` so this method + can be altered in `MultiHostDsn`. + """ + host, tld, host_type, rebuild = cls.validate_host(parts) + + return cls( + None if rebuild else url, + scheme=parts['scheme'], + user=parts['user'], + password=parts['password'], + host=host, + tld=tld, + host_type=host_type, + port=parts['port'], + path=parts['path'], + query=parts['query'], + fragment=parts['fragment'], + ) + + @staticmethod + def _match_url(url: str) -> Optional[Match[str]]: + return url_regex().match(url) + + @staticmethod + def _validate_port(port: Optional[str]) -> None: + if port is not None and int(port) > 65_535: + raise errors.UrlPortError() + + @classmethod + def validate_parts(cls, parts: 'Parts', validate_port: bool = True) -> 'Parts': + """ + A method used to validate parts of a URL. + Could be overridden to set default values for parts if missing + """ + scheme = parts['scheme'] + if scheme is None: + raise errors.UrlSchemeError() + + if cls.allowed_schemes and scheme.lower() not in cls.allowed_schemes: + raise errors.UrlSchemePermittedError(set(cls.allowed_schemes)) + + if validate_port: + cls._validate_port(parts['port']) + + user = parts['user'] + if cls.user_required and user is None: + raise errors.UrlUserInfoError() + + return parts + + @classmethod + def validate_host(cls, parts: 'Parts') -> Tuple[str, Optional[str], str, bool]: + tld, host_type, rebuild = None, None, False + for f in ('domain', 'ipv4', 'ipv6'): + host = parts[f] # type: ignore[literal-required] + if host: + host_type = f + break + + if host is None: + if cls.host_required: + raise errors.UrlHostError() + elif host_type == 'domain': + is_international = False + d = ascii_domain_regex().fullmatch(host) + if d is None: + d = int_domain_regex().fullmatch(host) + if d is None: + raise errors.UrlHostError() + is_international = True + + tld = d.group('tld') + if tld is None and not is_international: + d = int_domain_regex().fullmatch(host) + assert d is not None + tld = d.group('tld') + is_international = True + + if tld is not None: + tld = tld[1:] + elif cls.tld_required: + raise errors.UrlHostTldError() + + if is_international: + host_type = 'int_domain' + rebuild = True + host = host.encode('idna').decode('ascii') + if tld is not None: + tld = tld.encode('idna').decode('ascii') + + return host, tld, host_type, rebuild # type: ignore + + @staticmethod + def get_default_parts(parts: 'Parts') -> 'Parts': + return {} + + @classmethod + def apply_default_parts(cls, parts: 'Parts') -> 'Parts': + for key, value in cls.get_default_parts(parts).items(): + if not parts[key]: # type: ignore[literal-required] + parts[key] = value # type: ignore[literal-required] + return parts + + def __repr__(self) -> str: + extra = ', '.join(f'{n}={getattr(self, n)!r}' for n in self.__slots__ if getattr(self, n) is not None) + return f'{self.__class__.__name__}({super().__repr__()}, {extra})' + + +class AnyHttpUrl(AnyUrl): + allowed_schemes = {'http', 'https'} + + __slots__ = () + + +class HttpUrl(AnyHttpUrl): + tld_required = True + # https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers + max_length = 2083 + hidden_parts = {'port'} + + @staticmethod + def get_default_parts(parts: 'Parts') -> 'Parts': + return {'port': '80' if parts['scheme'] == 'http' else '443'} + + +class FileUrl(AnyUrl): + allowed_schemes = {'file'} + host_required = False + + __slots__ = () + + +class MultiHostDsn(AnyUrl): + __slots__ = AnyUrl.__slots__ + ('hosts',) + + def __init__(self, *args: Any, hosts: Optional[List['HostParts']] = None, **kwargs: Any): + super().__init__(*args, **kwargs) + self.hosts = hosts + + @staticmethod + def _match_url(url: str) -> Optional[Match[str]]: + return multi_host_url_regex().match(url) + + @classmethod + def validate_parts(cls, parts: 'Parts', validate_port: bool = True) -> 'Parts': + return super().validate_parts(parts, validate_port=False) + + @classmethod + def _build_url(cls, m: Match[str], url: str, parts: 'Parts') -> 'MultiHostDsn': + hosts_parts: List['HostParts'] = [] + host_re = host_regex() + for host in m.groupdict()['hosts'].split(','): + d: Parts = host_re.match(host).groupdict() # type: ignore + host, tld, host_type, rebuild = cls.validate_host(d) + port = d.get('port') + cls._validate_port(port) + hosts_parts.append( + { + 'host': host, + 'host_type': host_type, + 'tld': tld, + 'rebuild': rebuild, + 'port': port, + } + ) + + if len(hosts_parts) > 1: + return cls( + None if any([hp['rebuild'] for hp in hosts_parts]) else url, + scheme=parts['scheme'], + user=parts['user'], + password=parts['password'], + path=parts['path'], + query=parts['query'], + fragment=parts['fragment'], + host_type=None, + hosts=hosts_parts, + ) + else: + # backwards compatibility with single host + host_part = hosts_parts[0] + return cls( + None if host_part['rebuild'] else url, + scheme=parts['scheme'], + user=parts['user'], + password=parts['password'], + host=host_part['host'], + tld=host_part['tld'], + host_type=host_part['host_type'], + port=host_part.get('port'), + path=parts['path'], + query=parts['query'], + fragment=parts['fragment'], + ) + + +class PostgresDsn(MultiHostDsn): + allowed_schemes = { + 'postgres', + 'postgresql', + 'postgresql+asyncpg', + 'postgresql+pg8000', + 'postgresql+psycopg', + 'postgresql+psycopg2', + 'postgresql+psycopg2cffi', + 'postgresql+py-postgresql', + 'postgresql+pygresql', + } + user_required = True + + __slots__ = () + + +class CockroachDsn(AnyUrl): + allowed_schemes = { + 'cockroachdb', + 'cockroachdb+psycopg2', + 'cockroachdb+asyncpg', + } + user_required = True + + +class AmqpDsn(AnyUrl): + allowed_schemes = {'amqp', 'amqps'} + host_required = False + + +class RedisDsn(AnyUrl): + __slots__ = () + allowed_schemes = {'redis', 'rediss'} + host_required = False + + @staticmethod + def get_default_parts(parts: 'Parts') -> 'Parts': + return { + 'domain': 'localhost' if not (parts['ipv4'] or parts['ipv6']) else '', + 'port': '6379', + 'path': '/0', + } + + +class MongoDsn(AnyUrl): + allowed_schemes = {'mongodb'} + + # TODO: Needed to generic "Parts" for "Replica Set", "Sharded Cluster", and other mongodb deployment modes + @staticmethod + def get_default_parts(parts: 'Parts') -> 'Parts': + return { + 'port': '27017', + } + + +class KafkaDsn(AnyUrl): + allowed_schemes = {'kafka'} + + @staticmethod + def get_default_parts(parts: 'Parts') -> 'Parts': + return { + 'domain': 'localhost', + 'port': '9092', + } + + +def stricturl( + *, + strip_whitespace: bool = True, + min_length: int = 1, + max_length: int = 2**16, + tld_required: bool = True, + host_required: bool = True, + allowed_schemes: Optional[Collection[str]] = None, +) -> Type[AnyUrl]: + # use kwargs then define conf in a dict to aid with IDE type hinting + namespace = dict( + strip_whitespace=strip_whitespace, + min_length=min_length, + max_length=max_length, + tld_required=tld_required, + host_required=host_required, + allowed_schemes=allowed_schemes, + ) + return type('UrlValue', (AnyUrl,), namespace) + + +def import_email_validator() -> None: + global email_validator + try: + import email_validator + except ImportError as e: + raise ImportError('email-validator is not installed, run `pip install pydantic[email]`') from e + + +class EmailStr(str): + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update(type='string', format='email') + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + # included here and below so the error happens straight away + import_email_validator() + + yield str_validator + yield cls.validate + + @classmethod + def validate(cls, value: Union[str]) -> str: + return validate_email(value)[1] + + +class NameEmail(Representation): + __slots__ = 'name', 'email' + + def __init__(self, name: str, email: str): + self.name = name + self.email = email + + def __eq__(self, other: Any) -> bool: + return isinstance(other, NameEmail) and (self.name, self.email) == (other.name, other.email) + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update(type='string', format='name-email') + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + import_email_validator() + + yield cls.validate + + @classmethod + def validate(cls, value: Any) -> 'NameEmail': + if value.__class__ == cls: + return value + value = str_validator(value) + return cls(*validate_email(value)) + + def __str__(self) -> str: + return f'{self.name} <{self.email}>' + + +class IPvAnyAddress(_BaseAddress): + __slots__ = () + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update(type='string', format='ipvanyaddress') + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.validate + + @classmethod + def validate(cls, value: Union[str, bytes, int]) -> Union[IPv4Address, IPv6Address]: + try: + return IPv4Address(value) + except ValueError: + pass + + try: + return IPv6Address(value) + except ValueError: + raise errors.IPvAnyAddressError() + + +class IPvAnyInterface(_BaseAddress): + __slots__ = () + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update(type='string', format='ipvanyinterface') + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.validate + + @classmethod + def validate(cls, value: NetworkType) -> Union[IPv4Interface, IPv6Interface]: + try: + return IPv4Interface(value) + except ValueError: + pass + + try: + return IPv6Interface(value) + except ValueError: + raise errors.IPvAnyInterfaceError() + + +class IPvAnyNetwork(_BaseNetwork): # type: ignore + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update(type='string', format='ipvanynetwork') + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.validate + + @classmethod + def validate(cls, value: NetworkType) -> Union[IPv4Network, IPv6Network]: + # Assume IP Network is defined with a default value for ``strict`` argument. + # Define your own class if you want to specify network address check strictness. + try: + return IPv4Network(value) + except ValueError: + pass + + try: + return IPv6Network(value) + except ValueError: + raise errors.IPvAnyNetworkError() + + +pretty_email_regex = re.compile(r'([\w ]*?) *<(.*)> *') +MAX_EMAIL_LENGTH = 2048 +"""Maximum length for an email. +A somewhat arbitrary but very generous number compared to what is allowed by most implementations. +""" + + +def validate_email(value: Union[str]) -> Tuple[str, str]: + """ + Email address validation using https://pypi.org/project/email-validator/ + Notes: + * raw ip address (literal) domain parts are not allowed. + * "John Doe " style "pretty" email addresses are processed + * spaces are striped from the beginning and end of addresses but no error is raised + """ + if email_validator is None: + import_email_validator() + + if len(value) > MAX_EMAIL_LENGTH: + raise errors.EmailError() + + m = pretty_email_regex.fullmatch(value) + name: Union[str, None] = None + if m: + name, value = m.groups() + email = value.strip() + try: + parts = email_validator.validate_email(email, check_deliverability=False) + except email_validator.EmailNotValidError as e: + raise errors.EmailError from e + + if hasattr(parts, 'normalized'): + # email-validator >= 2 + email = parts.normalized + assert email is not None + name = name or parts.local_part + return name, email + else: + # email-validator >1, <2 + at_index = email.index('@') + local_part = email[:at_index] # RFC 5321, local part must be case-sensitive. + global_part = email[at_index:].lower() + + return name or local_part, local_part + global_part diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/parse.py b/backend/.venv/Lib/site-packages/pydantic/v1/parse.py new file mode 100644 index 0000000..431d75a --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/parse.py @@ -0,0 +1,66 @@ +import json +import pickle +from enum import Enum +from pathlib import Path +from typing import Any, Callable, Union + +from pydantic.v1.types import StrBytes + + +class Protocol(str, Enum): + json = 'json' + pickle = 'pickle' + + +def load_str_bytes( + b: StrBytes, + *, + content_type: str = None, + encoding: str = 'utf8', + proto: Protocol = None, + allow_pickle: bool = False, + json_loads: Callable[[str], Any] = json.loads, +) -> Any: + if proto is None and content_type: + if content_type.endswith(('json', 'javascript')): + pass + elif allow_pickle and content_type.endswith('pickle'): + proto = Protocol.pickle + else: + raise TypeError(f'Unknown content-type: {content_type}') + + proto = proto or Protocol.json + + if proto == Protocol.json: + if isinstance(b, bytes): + b = b.decode(encoding) + return json_loads(b) + elif proto == Protocol.pickle: + if not allow_pickle: + raise RuntimeError('Trying to decode with pickle with allow_pickle=False') + bb = b if isinstance(b, bytes) else b.encode() + return pickle.loads(bb) + else: + raise TypeError(f'Unknown protocol: {proto}') + + +def load_file( + path: Union[str, Path], + *, + content_type: str = None, + encoding: str = 'utf8', + proto: Protocol = None, + allow_pickle: bool = False, + json_loads: Callable[[str], Any] = json.loads, +) -> Any: + path = Path(path) + b = path.read_bytes() + if content_type is None: + if path.suffix in ('.js', '.json'): + proto = Protocol.json + elif path.suffix == '.pkl': + proto = Protocol.pickle + + return load_str_bytes( + b, proto=proto, content_type=content_type, encoding=encoding, allow_pickle=allow_pickle, json_loads=json_loads + ) diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/py.typed b/backend/.venv/Lib/site-packages/pydantic/v1/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/schema.py b/backend/.venv/Lib/site-packages/pydantic/v1/schema.py new file mode 100644 index 0000000..a91fe2c --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/schema.py @@ -0,0 +1,1163 @@ +import re +import warnings +from collections import defaultdict +from dataclasses import is_dataclass +from datetime import date, datetime, time, timedelta +from decimal import Decimal +from enum import Enum +from ipaddress import IPv4Address, IPv4Interface, IPv4Network, IPv6Address, IPv6Interface, IPv6Network +from pathlib import Path +from typing import ( + TYPE_CHECKING, + Any, + Callable, + Dict, + ForwardRef, + FrozenSet, + Generic, + Iterable, + List, + Optional, + Pattern, + Sequence, + Set, + Tuple, + Type, + TypeVar, + Union, + cast, +) +from uuid import UUID + +from typing_extensions import Annotated, Literal + +from pydantic.v1.fields import ( + MAPPING_LIKE_SHAPES, + SHAPE_DEQUE, + SHAPE_FROZENSET, + SHAPE_GENERIC, + SHAPE_ITERABLE, + SHAPE_LIST, + SHAPE_SEQUENCE, + SHAPE_SET, + SHAPE_SINGLETON, + SHAPE_TUPLE, + SHAPE_TUPLE_ELLIPSIS, + FieldInfo, + ModelField, +) +from pydantic.v1.json import pydantic_encoder +from pydantic.v1.networks import AnyUrl, EmailStr +from pydantic.v1.types import ( + ConstrainedDecimal, + ConstrainedFloat, + ConstrainedFrozenSet, + ConstrainedInt, + ConstrainedList, + ConstrainedSet, + ConstrainedStr, + SecretBytes, + SecretStr, + StrictBytes, + StrictStr, + conbytes, + condecimal, + confloat, + confrozenset, + conint, + conlist, + conset, + constr, +) +from pydantic.v1.typing import ( + all_literal_values, + get_args, + get_origin, + get_sub_types, + is_callable_type, + is_literal_type, + is_namedtuple, + is_none_type, + is_union, +) +from pydantic.v1.utils import ROOT_KEY, get_model, lenient_issubclass + +if TYPE_CHECKING: + from pydantic.v1.dataclasses import Dataclass + from pydantic.v1.main import BaseModel + +default_prefix = '#/definitions/' +default_ref_template = '#/definitions/{model}' + +TypeModelOrEnum = Union[Type['BaseModel'], Type[Enum]] +TypeModelSet = Set[TypeModelOrEnum] + + +def _apply_modify_schema( + modify_schema: Callable[..., None], field: Optional[ModelField], field_schema: Dict[str, Any] +) -> None: + from inspect import signature + + sig = signature(modify_schema) + args = set(sig.parameters.keys()) + if 'field' in args or 'kwargs' in args: + modify_schema(field_schema, field=field) + else: + modify_schema(field_schema) + + +def schema( + models: Sequence[Union[Type['BaseModel'], Type['Dataclass']]], + *, + by_alias: bool = True, + title: Optional[str] = None, + description: Optional[str] = None, + ref_prefix: Optional[str] = None, + ref_template: str = default_ref_template, +) -> Dict[str, Any]: + """ + Process a list of models and generate a single JSON Schema with all of them defined in the ``definitions`` + top-level JSON key, including their sub-models. + + :param models: a list of models to include in the generated JSON Schema + :param by_alias: generate the schemas using the aliases defined, if any + :param title: title for the generated schema that includes the definitions + :param description: description for the generated schema + :param ref_prefix: the JSON Pointer prefix for schema references with ``$ref``, if None, will be set to the + default of ``#/definitions/``. Update it if you want the schemas to reference the definitions somewhere + else, e.g. for OpenAPI use ``#/components/schemas/``. The resulting generated schemas will still be at the + top-level key ``definitions``, so you can extract them from there. But all the references will have the set + prefix. + :param ref_template: Use a ``string.format()`` template for ``$ref`` instead of a prefix. This can be useful + for references that cannot be represented by ``ref_prefix`` such as a definition stored in another file. For + a sibling json file in a ``/schemas`` directory use ``"/schemas/${model}.json#"``. + :return: dict with the JSON Schema with a ``definitions`` top-level key including the schema definitions for + the models and sub-models passed in ``models``. + """ + clean_models = [get_model(model) for model in models] + flat_models = get_flat_models_from_models(clean_models) + model_name_map = get_model_name_map(flat_models) + definitions = {} + output_schema: Dict[str, Any] = {} + if title: + output_schema['title'] = title + if description: + output_schema['description'] = description + for model in clean_models: + m_schema, m_definitions, m_nested_models = model_process_schema( + model, + by_alias=by_alias, + model_name_map=model_name_map, + ref_prefix=ref_prefix, + ref_template=ref_template, + ) + definitions.update(m_definitions) + model_name = model_name_map[model] + definitions[model_name] = m_schema + if definitions: + output_schema['definitions'] = definitions + return output_schema + + +def model_schema( + model: Union[Type['BaseModel'], Type['Dataclass']], + by_alias: bool = True, + ref_prefix: Optional[str] = None, + ref_template: str = default_ref_template, +) -> Dict[str, Any]: + """ + Generate a JSON Schema for one model. With all the sub-models defined in the ``definitions`` top-level + JSON key. + + :param model: a Pydantic model (a class that inherits from BaseModel) + :param by_alias: generate the schemas using the aliases defined, if any + :param ref_prefix: the JSON Pointer prefix for schema references with ``$ref``, if None, will be set to the + default of ``#/definitions/``. Update it if you want the schemas to reference the definitions somewhere + else, e.g. for OpenAPI use ``#/components/schemas/``. The resulting generated schemas will still be at the + top-level key ``definitions``, so you can extract them from there. But all the references will have the set + prefix. + :param ref_template: Use a ``string.format()`` template for ``$ref`` instead of a prefix. This can be useful for + references that cannot be represented by ``ref_prefix`` such as a definition stored in another file. For a + sibling json file in a ``/schemas`` directory use ``"/schemas/${model}.json#"``. + :return: dict with the JSON Schema for the passed ``model`` + """ + model = get_model(model) + flat_models = get_flat_models_from_model(model) + model_name_map = get_model_name_map(flat_models) + model_name = model_name_map[model] + m_schema, m_definitions, nested_models = model_process_schema( + model, by_alias=by_alias, model_name_map=model_name_map, ref_prefix=ref_prefix, ref_template=ref_template + ) + if model_name in nested_models: + # model_name is in Nested models, it has circular references + m_definitions[model_name] = m_schema + m_schema = get_schema_ref(model_name, ref_prefix, ref_template, False) + if m_definitions: + m_schema.update({'definitions': m_definitions}) + return m_schema + + +def get_field_info_schema(field: ModelField, schema_overrides: bool = False) -> Tuple[Dict[str, Any], bool]: + # If no title is explicitly set, we don't set title in the schema for enums. + # The behaviour is the same as `BaseModel` reference, where the default title + # is in the definitions part of the schema. + schema_: Dict[str, Any] = {} + if field.field_info.title or not lenient_issubclass(field.type_, Enum): + schema_['title'] = field.field_info.title or field.alias.title().replace('_', ' ') + + if field.field_info.title: + schema_overrides = True + + if field.field_info.description: + schema_['description'] = field.field_info.description + schema_overrides = True + + if not field.required and field.default is not None and not is_callable_type(field.outer_type_): + schema_['default'] = encode_default(field.default) + schema_overrides = True + + return schema_, schema_overrides + + +def field_schema( + field: ModelField, + *, + by_alias: bool = True, + model_name_map: Dict[TypeModelOrEnum, str], + ref_prefix: Optional[str] = None, + ref_template: str = default_ref_template, + known_models: Optional[TypeModelSet] = None, +) -> Tuple[Dict[str, Any], Dict[str, Any], Set[str]]: + """ + Process a Pydantic field and return a tuple with a JSON Schema for it as the first item. + Also return a dictionary of definitions with models as keys and their schemas as values. If the passed field + is a model and has sub-models, and those sub-models don't have overrides (as ``title``, ``default``, etc), they + will be included in the definitions and referenced in the schema instead of included recursively. + + :param field: a Pydantic ``ModelField`` + :param by_alias: use the defined alias (if any) in the returned schema + :param model_name_map: used to generate the JSON Schema references to other models included in the definitions + :param ref_prefix: the JSON Pointer prefix to use for references to other schemas, if None, the default of + #/definitions/ will be used + :param ref_template: Use a ``string.format()`` template for ``$ref`` instead of a prefix. This can be useful for + references that cannot be represented by ``ref_prefix`` such as a definition stored in another file. For a + sibling json file in a ``/schemas`` directory use ``"/schemas/${model}.json#"``. + :param known_models: used to solve circular references + :return: tuple of the schema for this field and additional definitions + """ + s, schema_overrides = get_field_info_schema(field) + + validation_schema = get_field_schema_validations(field) + if validation_schema: + s.update(validation_schema) + schema_overrides = True + + f_schema, f_definitions, f_nested_models = field_type_schema( + field, + by_alias=by_alias, + model_name_map=model_name_map, + schema_overrides=schema_overrides, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models or set(), + ) + + # $ref will only be returned when there are no schema_overrides + if '$ref' in f_schema: + return f_schema, f_definitions, f_nested_models + else: + s.update(f_schema) + return s, f_definitions, f_nested_models + + +numeric_types = (int, float, Decimal) +_str_types_attrs: Tuple[Tuple[str, Union[type, Tuple[type, ...]], str], ...] = ( + ('max_length', numeric_types, 'maxLength'), + ('min_length', numeric_types, 'minLength'), + ('regex', str, 'pattern'), +) + +_numeric_types_attrs: Tuple[Tuple[str, Union[type, Tuple[type, ...]], str], ...] = ( + ('gt', numeric_types, 'exclusiveMinimum'), + ('lt', numeric_types, 'exclusiveMaximum'), + ('ge', numeric_types, 'minimum'), + ('le', numeric_types, 'maximum'), + ('multiple_of', numeric_types, 'multipleOf'), +) + + +def get_field_schema_validations(field: ModelField) -> Dict[str, Any]: + """ + Get the JSON Schema validation keywords for a ``field`` with an annotation of + a Pydantic ``FieldInfo`` with validation arguments. + """ + f_schema: Dict[str, Any] = {} + + if lenient_issubclass(field.type_, Enum): + # schema is already updated by `enum_process_schema`; just update with field extra + if field.field_info.extra: + f_schema.update(field.field_info.extra) + return f_schema + + if lenient_issubclass(field.type_, (str, bytes)): + for attr_name, t, keyword in _str_types_attrs: + attr = getattr(field.field_info, attr_name, None) + if isinstance(attr, t): + f_schema[keyword] = attr + if lenient_issubclass(field.type_, numeric_types) and not issubclass(field.type_, bool): + for attr_name, t, keyword in _numeric_types_attrs: + attr = getattr(field.field_info, attr_name, None) + if isinstance(attr, t): + f_schema[keyword] = attr + if field.field_info is not None and field.field_info.const: + f_schema['const'] = field.default + if field.field_info.extra: + f_schema.update(field.field_info.extra) + modify_schema = getattr(field.outer_type_, '__modify_schema__', None) + if modify_schema: + _apply_modify_schema(modify_schema, field, f_schema) + return f_schema + + +def get_model_name_map(unique_models: TypeModelSet) -> Dict[TypeModelOrEnum, str]: + """ + Process a set of models and generate unique names for them to be used as keys in the JSON Schema + definitions. By default the names are the same as the class name. But if two models in different Python + modules have the same name (e.g. "users.Model" and "items.Model"), the generated names will be + based on the Python module path for those conflicting models to prevent name collisions. + + :param unique_models: a Python set of models + :return: dict mapping models to names + """ + name_model_map = {} + conflicting_names: Set[str] = set() + for model in unique_models: + model_name = normalize_name(model.__name__) + if model_name in conflicting_names: + model_name = get_long_model_name(model) + name_model_map[model_name] = model + elif model_name in name_model_map: + conflicting_names.add(model_name) + conflicting_model = name_model_map.pop(model_name) + name_model_map[get_long_model_name(conflicting_model)] = conflicting_model + name_model_map[get_long_model_name(model)] = model + else: + name_model_map[model_name] = model + return {v: k for k, v in name_model_map.items()} + + +def get_flat_models_from_model(model: Type['BaseModel'], known_models: Optional[TypeModelSet] = None) -> TypeModelSet: + """ + Take a single ``model`` and generate a set with itself and all the sub-models in the tree. I.e. if you pass + model ``Foo`` (subclass of Pydantic ``BaseModel``) as ``model``, and it has a field of type ``Bar`` (also + subclass of ``BaseModel``) and that model ``Bar`` has a field of type ``Baz`` (also subclass of ``BaseModel``), + the return value will be ``set([Foo, Bar, Baz])``. + + :param model: a Pydantic ``BaseModel`` subclass + :param known_models: used to solve circular references + :return: a set with the initial model and all its sub-models + """ + known_models = known_models or set() + flat_models: TypeModelSet = set() + flat_models.add(model) + known_models |= flat_models + fields = cast(Sequence[ModelField], model.__fields__.values()) + flat_models |= get_flat_models_from_fields(fields, known_models=known_models) + return flat_models + + +def get_flat_models_from_field(field: ModelField, known_models: TypeModelSet) -> TypeModelSet: + """ + Take a single Pydantic ``ModelField`` (from a model) that could have been declared as a subclass of BaseModel + (so, it could be a submodel), and generate a set with its model and all the sub-models in the tree. + I.e. if you pass a field that was declared to be of type ``Foo`` (subclass of BaseModel) as ``field``, and that + model ``Foo`` has a field of type ``Bar`` (also subclass of ``BaseModel``) and that model ``Bar`` has a field of + type ``Baz`` (also subclass of ``BaseModel``), the return value will be ``set([Foo, Bar, Baz])``. + + :param field: a Pydantic ``ModelField`` + :param known_models: used to solve circular references + :return: a set with the model used in the declaration for this field, if any, and all its sub-models + """ + from pydantic.v1.main import BaseModel + + flat_models: TypeModelSet = set() + + field_type = field.type_ + if lenient_issubclass(getattr(field_type, '__pydantic_model__', None), BaseModel): + field_type = field_type.__pydantic_model__ + + if field.sub_fields and not lenient_issubclass(field_type, BaseModel): + flat_models |= get_flat_models_from_fields(field.sub_fields, known_models=known_models) + elif lenient_issubclass(field_type, BaseModel) and field_type not in known_models: + flat_models |= get_flat_models_from_model(field_type, known_models=known_models) + elif lenient_issubclass(field_type, Enum): + flat_models.add(field_type) + return flat_models + + +def get_flat_models_from_fields(fields: Sequence[ModelField], known_models: TypeModelSet) -> TypeModelSet: + """ + Take a list of Pydantic ``ModelField``s (from a model) that could have been declared as subclasses of ``BaseModel`` + (so, any of them could be a submodel), and generate a set with their models and all the sub-models in the tree. + I.e. if you pass a the fields of a model ``Foo`` (subclass of ``BaseModel``) as ``fields``, and on of them has a + field of type ``Bar`` (also subclass of ``BaseModel``) and that model ``Bar`` has a field of type ``Baz`` (also + subclass of ``BaseModel``), the return value will be ``set([Foo, Bar, Baz])``. + + :param fields: a list of Pydantic ``ModelField``s + :param known_models: used to solve circular references + :return: a set with any model declared in the fields, and all their sub-models + """ + flat_models: TypeModelSet = set() + for field in fields: + flat_models |= get_flat_models_from_field(field, known_models=known_models) + return flat_models + + +def get_flat_models_from_models(models: Sequence[Type['BaseModel']]) -> TypeModelSet: + """ + Take a list of ``models`` and generate a set with them and all their sub-models in their trees. I.e. if you pass + a list of two models, ``Foo`` and ``Bar``, both subclasses of Pydantic ``BaseModel`` as models, and ``Bar`` has + a field of type ``Baz`` (also subclass of ``BaseModel``), the return value will be ``set([Foo, Bar, Baz])``. + """ + flat_models: TypeModelSet = set() + for model in models: + flat_models |= get_flat_models_from_model(model) + return flat_models + + +def get_long_model_name(model: TypeModelOrEnum) -> str: + return f'{model.__module__}__{model.__qualname__}'.replace('.', '__') + + +def field_type_schema( + field: ModelField, + *, + by_alias: bool, + model_name_map: Dict[TypeModelOrEnum, str], + ref_template: str, + schema_overrides: bool = False, + ref_prefix: Optional[str] = None, + known_models: TypeModelSet, +) -> Tuple[Dict[str, Any], Dict[str, Any], Set[str]]: + """ + Used by ``field_schema()``, you probably should be using that function. + + Take a single ``field`` and generate the schema for its type only, not including additional + information as title, etc. Also return additional schema definitions, from sub-models. + """ + from pydantic.v1.main import BaseModel # noqa: F811 + + definitions = {} + nested_models: Set[str] = set() + f_schema: Dict[str, Any] + if field.shape in { + SHAPE_LIST, + SHAPE_TUPLE_ELLIPSIS, + SHAPE_SEQUENCE, + SHAPE_SET, + SHAPE_FROZENSET, + SHAPE_ITERABLE, + SHAPE_DEQUE, + }: + items_schema, f_definitions, f_nested_models = field_singleton_schema( + field, + by_alias=by_alias, + model_name_map=model_name_map, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + ) + definitions.update(f_definitions) + nested_models.update(f_nested_models) + f_schema = {'type': 'array', 'items': items_schema} + if field.shape in {SHAPE_SET, SHAPE_FROZENSET}: + f_schema['uniqueItems'] = True + + elif field.shape in MAPPING_LIKE_SHAPES: + f_schema = {'type': 'object'} + key_field = cast(ModelField, field.key_field) + regex = getattr(key_field.type_, 'regex', None) + items_schema, f_definitions, f_nested_models = field_singleton_schema( + field, + by_alias=by_alias, + model_name_map=model_name_map, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + ) + definitions.update(f_definitions) + nested_models.update(f_nested_models) + if regex: + # Dict keys have a regex pattern + # items_schema might be a schema or empty dict, add it either way + f_schema['patternProperties'] = {ConstrainedStr._get_pattern(regex): items_schema} + if items_schema: + # The dict values are not simply Any, so they need a schema + f_schema['additionalProperties'] = items_schema + elif field.shape == SHAPE_TUPLE or (field.shape == SHAPE_GENERIC and not issubclass(field.type_, BaseModel)): + sub_schema = [] + sub_fields = cast(List[ModelField], field.sub_fields) + for sf in sub_fields: + sf_schema, sf_definitions, sf_nested_models = field_type_schema( + sf, + by_alias=by_alias, + model_name_map=model_name_map, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + ) + definitions.update(sf_definitions) + nested_models.update(sf_nested_models) + sub_schema.append(sf_schema) + + sub_fields_len = len(sub_fields) + if field.shape == SHAPE_GENERIC: + all_of_schemas = sub_schema[0] if sub_fields_len == 1 else {'type': 'array', 'items': sub_schema} + f_schema = {'allOf': [all_of_schemas]} + else: + f_schema = { + 'type': 'array', + 'minItems': sub_fields_len, + 'maxItems': sub_fields_len, + } + if sub_fields_len >= 1: + f_schema['items'] = sub_schema + else: + assert field.shape in {SHAPE_SINGLETON, SHAPE_GENERIC}, field.shape + f_schema, f_definitions, f_nested_models = field_singleton_schema( + field, + by_alias=by_alias, + model_name_map=model_name_map, + schema_overrides=schema_overrides, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + ) + definitions.update(f_definitions) + nested_models.update(f_nested_models) + + # check field type to avoid repeated calls to the same __modify_schema__ method + if field.type_ != field.outer_type_: + if field.shape == SHAPE_GENERIC: + field_type = field.type_ + else: + field_type = field.outer_type_ + modify_schema = getattr(field_type, '__modify_schema__', None) + if modify_schema: + _apply_modify_schema(modify_schema, field, f_schema) + return f_schema, definitions, nested_models + + +def model_process_schema( + model: TypeModelOrEnum, + *, + by_alias: bool = True, + model_name_map: Dict[TypeModelOrEnum, str], + ref_prefix: Optional[str] = None, + ref_template: str = default_ref_template, + known_models: Optional[TypeModelSet] = None, + field: Optional[ModelField] = None, +) -> Tuple[Dict[str, Any], Dict[str, Any], Set[str]]: + """ + Used by ``model_schema()``, you probably should be using that function. + + Take a single ``model`` and generate its schema. Also return additional schema definitions, from sub-models. The + sub-models of the returned schema will be referenced, but their definitions will not be included in the schema. All + the definitions are returned as the second value. + """ + from inspect import getdoc, signature + + known_models = known_models or set() + if lenient_issubclass(model, Enum): + model = cast(Type[Enum], model) + s = enum_process_schema(model, field=field) + return s, {}, set() + model = cast(Type['BaseModel'], model) + s = {'title': model.__config__.title or model.__name__} + doc = getdoc(model) + if doc: + s['description'] = doc + known_models.add(model) + m_schema, m_definitions, nested_models = model_type_schema( + model, + by_alias=by_alias, + model_name_map=model_name_map, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + ) + s.update(m_schema) + schema_extra = model.__config__.schema_extra + if callable(schema_extra): + if len(signature(schema_extra).parameters) == 1: + schema_extra(s) + else: + schema_extra(s, model) + else: + s.update(schema_extra) + return s, m_definitions, nested_models + + +def model_type_schema( + model: Type['BaseModel'], + *, + by_alias: bool, + model_name_map: Dict[TypeModelOrEnum, str], + ref_template: str, + ref_prefix: Optional[str] = None, + known_models: TypeModelSet, +) -> Tuple[Dict[str, Any], Dict[str, Any], Set[str]]: + """ + You probably should be using ``model_schema()``, this function is indirectly used by that function. + + Take a single ``model`` and generate the schema for its type only, not including additional + information as title, etc. Also return additional schema definitions, from sub-models. + """ + properties = {} + required = [] + definitions: Dict[str, Any] = {} + nested_models: Set[str] = set() + for k, f in model.__fields__.items(): + try: + f_schema, f_definitions, f_nested_models = field_schema( + f, + by_alias=by_alias, + model_name_map=model_name_map, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + ) + except SkipField as skip: + warnings.warn(skip.message, UserWarning) + continue + definitions.update(f_definitions) + nested_models.update(f_nested_models) + if by_alias: + properties[f.alias] = f_schema + if f.required: + required.append(f.alias) + else: + properties[k] = f_schema + if f.required: + required.append(k) + if ROOT_KEY in properties: + out_schema = properties[ROOT_KEY] + out_schema['title'] = model.__config__.title or model.__name__ + else: + out_schema = {'type': 'object', 'properties': properties} + if required: + out_schema['required'] = required + if model.__config__.extra == 'forbid': + out_schema['additionalProperties'] = False + return out_schema, definitions, nested_models + + +def enum_process_schema(enum: Type[Enum], *, field: Optional[ModelField] = None) -> Dict[str, Any]: + """ + Take a single `enum` and generate its schema. + + This is similar to the `model_process_schema` function, but applies to ``Enum`` objects. + """ + import inspect + + schema_: Dict[str, Any] = { + 'title': enum.__name__, + # Python assigns all enums a default docstring value of 'An enumeration', so + # all enums will have a description field even if not explicitly provided. + 'description': inspect.cleandoc(enum.__doc__ or 'An enumeration.'), + # Add enum values and the enum field type to the schema. + 'enum': [item.value for item in cast(Iterable[Enum], enum)], + } + + add_field_type_to_schema(enum, schema_) + + modify_schema = getattr(enum, '__modify_schema__', None) + if modify_schema: + _apply_modify_schema(modify_schema, field, schema_) + + return schema_ + + +def field_singleton_sub_fields_schema( + field: ModelField, + *, + by_alias: bool, + model_name_map: Dict[TypeModelOrEnum, str], + ref_template: str, + schema_overrides: bool = False, + ref_prefix: Optional[str] = None, + known_models: TypeModelSet, +) -> Tuple[Dict[str, Any], Dict[str, Any], Set[str]]: + """ + This function is indirectly used by ``field_schema()``, you probably should be using that function. + + Take a list of Pydantic ``ModelField`` from the declaration of a type with parameters, and generate their + schema. I.e., fields used as "type parameters", like ``str`` and ``int`` in ``Tuple[str, int]``. + """ + sub_fields = cast(List[ModelField], field.sub_fields) + definitions = {} + nested_models: Set[str] = set() + if len(sub_fields) == 1: + return field_type_schema( + sub_fields[0], + by_alias=by_alias, + model_name_map=model_name_map, + schema_overrides=schema_overrides, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + ) + else: + s: Dict[str, Any] = {} + # https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#discriminator-object + field_has_discriminator: bool = field.discriminator_key is not None + if field_has_discriminator: + assert field.sub_fields_mapping is not None + + discriminator_models_refs: Dict[str, Union[str, Dict[str, Any]]] = {} + + for discriminator_value, sub_field in field.sub_fields_mapping.items(): + if isinstance(discriminator_value, Enum): + discriminator_value = str(discriminator_value.value) + # sub_field is either a `BaseModel` or directly an `Annotated` `Union` of many + if is_union(get_origin(sub_field.type_)): + sub_models = get_sub_types(sub_field.type_) + discriminator_models_refs[discriminator_value] = { + model_name_map[sub_model]: get_schema_ref( + model_name_map[sub_model], ref_prefix, ref_template, False + ) + for sub_model in sub_models + } + else: + sub_field_type = sub_field.type_ + if hasattr(sub_field_type, '__pydantic_model__'): + sub_field_type = sub_field_type.__pydantic_model__ + + discriminator_model_name = model_name_map[sub_field_type] + discriminator_model_ref = get_schema_ref(discriminator_model_name, ref_prefix, ref_template, False) + discriminator_models_refs[discriminator_value] = discriminator_model_ref['$ref'] + + s['discriminator'] = { + 'propertyName': field.discriminator_alias if by_alias else field.discriminator_key, + 'mapping': discriminator_models_refs, + } + + sub_field_schemas = [] + for sf in sub_fields: + sub_schema, sub_definitions, sub_nested_models = field_type_schema( + sf, + by_alias=by_alias, + model_name_map=model_name_map, + schema_overrides=schema_overrides, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + ) + definitions.update(sub_definitions) + if schema_overrides and 'allOf' in sub_schema: + # if the sub_field is a referenced schema we only need the referenced + # object. Otherwise we will end up with several allOf inside anyOf/oneOf. + # See https://github.com/pydantic/pydantic/issues/1209 + sub_schema = sub_schema['allOf'][0] + + if sub_schema.keys() == {'discriminator', 'oneOf'}: + # we don't want discriminator information inside oneOf choices, this is dealt with elsewhere + sub_schema.pop('discriminator') + sub_field_schemas.append(sub_schema) + nested_models.update(sub_nested_models) + s['oneOf' if field_has_discriminator else 'anyOf'] = sub_field_schemas + return s, definitions, nested_models + + +# Order is important, e.g. subclasses of str must go before str +# this is used only for standard library types, custom types should use __modify_schema__ instead +field_class_to_schema: Tuple[Tuple[Any, Dict[str, Any]], ...] = ( + (Path, {'type': 'string', 'format': 'path'}), + (datetime, {'type': 'string', 'format': 'date-time'}), + (date, {'type': 'string', 'format': 'date'}), + (time, {'type': 'string', 'format': 'time'}), + (timedelta, {'type': 'number', 'format': 'time-delta'}), + (IPv4Network, {'type': 'string', 'format': 'ipv4network'}), + (IPv6Network, {'type': 'string', 'format': 'ipv6network'}), + (IPv4Interface, {'type': 'string', 'format': 'ipv4interface'}), + (IPv6Interface, {'type': 'string', 'format': 'ipv6interface'}), + (IPv4Address, {'type': 'string', 'format': 'ipv4'}), + (IPv6Address, {'type': 'string', 'format': 'ipv6'}), + (Pattern, {'type': 'string', 'format': 'regex'}), + (str, {'type': 'string'}), + (bytes, {'type': 'string', 'format': 'binary'}), + (bool, {'type': 'boolean'}), + (int, {'type': 'integer'}), + (float, {'type': 'number'}), + (Decimal, {'type': 'number'}), + (UUID, {'type': 'string', 'format': 'uuid'}), + (dict, {'type': 'object'}), + (list, {'type': 'array', 'items': {}}), + (tuple, {'type': 'array', 'items': {}}), + (set, {'type': 'array', 'items': {}, 'uniqueItems': True}), + (frozenset, {'type': 'array', 'items': {}, 'uniqueItems': True}), +) + +json_scheme = {'type': 'string', 'format': 'json-string'} + + +def add_field_type_to_schema(field_type: Any, schema_: Dict[str, Any]) -> None: + """ + Update the given `schema` with the type-specific metadata for the given `field_type`. + + This function looks through `field_class_to_schema` for a class that matches the given `field_type`, + and then modifies the given `schema` with the information from that type. + """ + for type_, t_schema in field_class_to_schema: + # Fallback for `typing.Pattern` and `re.Pattern` as they are not a valid class + if lenient_issubclass(field_type, type_) or field_type is type_ is Pattern: + schema_.update(t_schema) + break + + +def get_schema_ref(name: str, ref_prefix: Optional[str], ref_template: str, schema_overrides: bool) -> Dict[str, Any]: + if ref_prefix: + schema_ref = {'$ref': ref_prefix + name} + else: + schema_ref = {'$ref': ref_template.format(model=name)} + return {'allOf': [schema_ref]} if schema_overrides else schema_ref + + +def field_singleton_schema( # noqa: C901 (ignore complexity) + field: ModelField, + *, + by_alias: bool, + model_name_map: Dict[TypeModelOrEnum, str], + ref_template: str, + schema_overrides: bool = False, + ref_prefix: Optional[str] = None, + known_models: TypeModelSet, +) -> Tuple[Dict[str, Any], Dict[str, Any], Set[str]]: + """ + This function is indirectly used by ``field_schema()``, you should probably be using that function. + + Take a single Pydantic ``ModelField``, and return its schema and any additional definitions from sub-models. + """ + from pydantic.v1.main import BaseModel + + definitions: Dict[str, Any] = {} + nested_models: Set[str] = set() + field_type = field.type_ + + # Recurse into this field if it contains sub_fields and is NOT a + # BaseModel OR that BaseModel is a const + if field.sub_fields and ( + (field.field_info and field.field_info.const) or not lenient_issubclass(field_type, BaseModel) + ): + return field_singleton_sub_fields_schema( + field, + by_alias=by_alias, + model_name_map=model_name_map, + schema_overrides=schema_overrides, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + ) + if field_type is Any or field_type is object or field_type.__class__ == TypeVar or get_origin(field_type) is type: + return {}, definitions, nested_models # no restrictions + if is_none_type(field_type): + return {'type': 'null'}, definitions, nested_models + if is_callable_type(field_type): + raise SkipField(f'Callable {field.name} was excluded from schema since JSON schema has no equivalent type.') + f_schema: Dict[str, Any] = {} + if field.field_info is not None and field.field_info.const: + f_schema['const'] = field.default + + if is_literal_type(field_type): + values = tuple(x.value if isinstance(x, Enum) else x for x in all_literal_values(field_type)) + + if len({v.__class__ for v in values}) > 1: + return field_schema( + multitypes_literal_field_for_schema(values, field), + by_alias=by_alias, + model_name_map=model_name_map, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + ) + + # All values have the same type + field_type = values[0].__class__ + f_schema['enum'] = list(values) + add_field_type_to_schema(field_type, f_schema) + elif lenient_issubclass(field_type, Enum): + enum_name = model_name_map[field_type] + f_schema, schema_overrides = get_field_info_schema(field, schema_overrides) + f_schema.update(get_schema_ref(enum_name, ref_prefix, ref_template, schema_overrides)) + definitions[enum_name] = enum_process_schema(field_type, field=field) + elif is_namedtuple(field_type): + sub_schema, *_ = model_process_schema( + field_type.__pydantic_model__, + by_alias=by_alias, + model_name_map=model_name_map, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + field=field, + ) + items_schemas = list(sub_schema['properties'].values()) + f_schema.update( + { + 'type': 'array', + 'items': items_schemas, + 'minItems': len(items_schemas), + 'maxItems': len(items_schemas), + } + ) + elif not hasattr(field_type, '__pydantic_model__'): + add_field_type_to_schema(field_type, f_schema) + + modify_schema = getattr(field_type, '__modify_schema__', None) + if modify_schema: + _apply_modify_schema(modify_schema, field, f_schema) + + if f_schema: + return f_schema, definitions, nested_models + + # Handle dataclass-based models + if lenient_issubclass(getattr(field_type, '__pydantic_model__', None), BaseModel): + field_type = field_type.__pydantic_model__ + + if issubclass(field_type, BaseModel): + model_name = model_name_map[field_type] + if field_type not in known_models: + sub_schema, sub_definitions, sub_nested_models = model_process_schema( + field_type, + by_alias=by_alias, + model_name_map=model_name_map, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + field=field, + ) + definitions.update(sub_definitions) + definitions[model_name] = sub_schema + nested_models.update(sub_nested_models) + else: + nested_models.add(model_name) + schema_ref = get_schema_ref(model_name, ref_prefix, ref_template, schema_overrides) + return schema_ref, definitions, nested_models + + # For generics with no args + args = get_args(field_type) + if args is not None and not args and Generic in field_type.__bases__: + return f_schema, definitions, nested_models + + raise ValueError(f'Value not declarable with JSON Schema, field: {field}') + + +def multitypes_literal_field_for_schema(values: Tuple[Any, ...], field: ModelField) -> ModelField: + """ + To support `Literal` with values of different types, we split it into multiple `Literal` with same type + e.g. `Literal['qwe', 'asd', 1, 2]` becomes `Union[Literal['qwe', 'asd'], Literal[1, 2]]` + """ + literal_distinct_types = defaultdict(list) + for v in values: + literal_distinct_types[v.__class__].append(v) + distinct_literals = (Literal[tuple(same_type_values)] for same_type_values in literal_distinct_types.values()) + + return ModelField( + name=field.name, + type_=Union[tuple(distinct_literals)], # type: ignore + class_validators=field.class_validators, + model_config=field.model_config, + default=field.default, + required=field.required, + alias=field.alias, + field_info=field.field_info, + ) + + +def encode_default(dft: Any) -> Any: + from pydantic.v1.main import BaseModel + + if isinstance(dft, BaseModel) or is_dataclass(dft): + dft = cast('dict[str, Any]', pydantic_encoder(dft)) + + if isinstance(dft, dict): + return {encode_default(k): encode_default(v) for k, v in dft.items()} + elif isinstance(dft, Enum): + return dft.value + elif isinstance(dft, (int, float, str)): + return dft + elif isinstance(dft, (list, tuple)): + t = dft.__class__ + seq_args = (encode_default(v) for v in dft) + return t(*seq_args) if is_namedtuple(t) else t(seq_args) + elif dft is None: + return None + else: + return pydantic_encoder(dft) + + +_map_types_constraint: Dict[Any, Callable[..., type]] = {int: conint, float: confloat, Decimal: condecimal} + + +def get_annotation_from_field_info( + annotation: Any, field_info: FieldInfo, field_name: str, validate_assignment: bool = False +) -> Type[Any]: + """ + Get an annotation with validation implemented for numbers and strings based on the field_info. + :param annotation: an annotation from a field specification, as ``str``, ``ConstrainedStr`` + :param field_info: an instance of FieldInfo, possibly with declarations for validations and JSON Schema + :param field_name: name of the field for use in error messages + :param validate_assignment: default False, flag for BaseModel Config value of validate_assignment + :return: the same ``annotation`` if unmodified or a new annotation with validation in place + """ + constraints = field_info.get_constraints() + used_constraints: Set[str] = set() + if constraints: + annotation, used_constraints = get_annotation_with_constraints(annotation, field_info) + if validate_assignment: + used_constraints.add('allow_mutation') + + unused_constraints = constraints - used_constraints + if unused_constraints: + raise ValueError( + f'On field "{field_name}" the following field constraints are set but not enforced: ' + f'{", ".join(unused_constraints)}. ' + f'\nFor more details see https://docs.pydantic.dev/usage/schema/#unenforced-field-constraints' + ) + + return annotation + + +def get_annotation_with_constraints(annotation: Any, field_info: FieldInfo) -> Tuple[Type[Any], Set[str]]: # noqa: C901 + """ + Get an annotation with used constraints implemented for numbers and strings based on the field_info. + + :param annotation: an annotation from a field specification, as ``str``, ``ConstrainedStr`` + :param field_info: an instance of FieldInfo, possibly with declarations for validations and JSON Schema + :return: the same ``annotation`` if unmodified or a new annotation along with the used constraints. + """ + used_constraints: Set[str] = set() + + def go(type_: Any) -> Type[Any]: + if ( + is_literal_type(type_) + or isinstance(type_, ForwardRef) + or lenient_issubclass(type_, (ConstrainedList, ConstrainedSet, ConstrainedFrozenSet)) + ): + return type_ + origin = get_origin(type_) + if origin is not None: + args: Tuple[Any, ...] = get_args(type_) + if any(isinstance(a, ForwardRef) for a in args): + # forward refs cause infinite recursion below + return type_ + + if origin is Annotated: + return go(args[0]) + if is_union(origin): + return Union[tuple(go(a) for a in args)] # type: ignore + + if issubclass(origin, List) and ( + field_info.min_items is not None + or field_info.max_items is not None + or field_info.unique_items is not None + ): + used_constraints.update({'min_items', 'max_items', 'unique_items'}) + return conlist( + go(args[0]), + min_items=field_info.min_items, + max_items=field_info.max_items, + unique_items=field_info.unique_items, + ) + + if issubclass(origin, Set) and (field_info.min_items is not None or field_info.max_items is not None): + used_constraints.update({'min_items', 'max_items'}) + return conset(go(args[0]), min_items=field_info.min_items, max_items=field_info.max_items) + + if issubclass(origin, FrozenSet) and (field_info.min_items is not None or field_info.max_items is not None): + used_constraints.update({'min_items', 'max_items'}) + return confrozenset(go(args[0]), min_items=field_info.min_items, max_items=field_info.max_items) + + for t in (Tuple, List, Set, FrozenSet, Sequence): + if issubclass(origin, t): # type: ignore + return t[tuple(go(a) for a in args)] # type: ignore + + if issubclass(origin, Dict): + return Dict[args[0], go(args[1])] # type: ignore + + attrs: Optional[Tuple[str, ...]] = None + constraint_func: Optional[Callable[..., type]] = None + if isinstance(type_, type): + if issubclass(type_, (SecretStr, SecretBytes)): + attrs = ('max_length', 'min_length') + + def constraint_func(**kw: Any) -> Type[Any]: # noqa: F811 + return type(type_.__name__, (type_,), kw) + + elif issubclass(type_, str) and not issubclass(type_, (EmailStr, AnyUrl)): + attrs = ('max_length', 'min_length', 'regex') + if issubclass(type_, StrictStr): + + def constraint_func(**kw: Any) -> Type[Any]: + return type(type_.__name__, (type_,), kw) + + else: + constraint_func = constr + elif issubclass(type_, bytes): + attrs = ('max_length', 'min_length', 'regex') + if issubclass(type_, StrictBytes): + + def constraint_func(**kw: Any) -> Type[Any]: + return type(type_.__name__, (type_,), kw) + + else: + constraint_func = conbytes + elif issubclass(type_, numeric_types) and not issubclass( + type_, + ( + ConstrainedInt, + ConstrainedFloat, + ConstrainedDecimal, + ConstrainedList, + ConstrainedSet, + ConstrainedFrozenSet, + bool, + ), + ): + # Is numeric type + attrs = ('gt', 'lt', 'ge', 'le', 'multiple_of') + if issubclass(type_, float): + attrs += ('allow_inf_nan',) + if issubclass(type_, Decimal): + attrs += ('max_digits', 'decimal_places') + numeric_type = next(t for t in numeric_types if issubclass(type_, t)) # pragma: no branch + constraint_func = _map_types_constraint[numeric_type] + + if attrs: + used_constraints.update(set(attrs)) + kwargs = { + attr_name: attr + for attr_name, attr in ((attr_name, getattr(field_info, attr_name)) for attr_name in attrs) + if attr is not None + } + if kwargs: + constraint_func = cast(Callable[..., type], constraint_func) + return constraint_func(**kwargs) + return type_ + + return go(annotation), used_constraints + + +def normalize_name(name: str) -> str: + """ + Normalizes the given name. This can be applied to either a model *or* enum. + """ + return re.sub(r'[^a-zA-Z0-9.\-_]', '_', name) + + +class SkipField(Exception): + """ + Utility exception used to exclude fields from schema. + """ + + def __init__(self, message: str) -> None: + self.message = message diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/tools.py b/backend/.venv/Lib/site-packages/pydantic/v1/tools.py new file mode 100644 index 0000000..6838a23 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/tools.py @@ -0,0 +1,92 @@ +import json +from functools import lru_cache +from pathlib import Path +from typing import TYPE_CHECKING, Any, Callable, Optional, Type, TypeVar, Union + +from pydantic.v1.parse import Protocol, load_file, load_str_bytes +from pydantic.v1.types import StrBytes +from pydantic.v1.typing import display_as_type + +__all__ = ('parse_file_as', 'parse_obj_as', 'parse_raw_as', 'schema_of', 'schema_json_of') + +NameFactory = Union[str, Callable[[Type[Any]], str]] + +if TYPE_CHECKING: + from pydantic.v1.typing import DictStrAny + + +def _generate_parsing_type_name(type_: Any) -> str: + return f'ParsingModel[{display_as_type(type_)}]' + + +@lru_cache(maxsize=2048) +def _get_parsing_type(type_: Any, *, type_name: Optional[NameFactory] = None) -> Any: + from pydantic.v1.main import create_model + + if type_name is None: + type_name = _generate_parsing_type_name + if not isinstance(type_name, str): + type_name = type_name(type_) + return create_model(type_name, __root__=(type_, ...)) + + +T = TypeVar('T') + + +def parse_obj_as(type_: Type[T], obj: Any, *, type_name: Optional[NameFactory] = None) -> T: + model_type = _get_parsing_type(type_, type_name=type_name) # type: ignore[arg-type] + return model_type(__root__=obj).__root__ + + +def parse_file_as( + type_: Type[T], + path: Union[str, Path], + *, + content_type: str = None, + encoding: str = 'utf8', + proto: Protocol = None, + allow_pickle: bool = False, + json_loads: Callable[[str], Any] = json.loads, + type_name: Optional[NameFactory] = None, +) -> T: + obj = load_file( + path, + proto=proto, + content_type=content_type, + encoding=encoding, + allow_pickle=allow_pickle, + json_loads=json_loads, + ) + return parse_obj_as(type_, obj, type_name=type_name) + + +def parse_raw_as( + type_: Type[T], + b: StrBytes, + *, + content_type: str = None, + encoding: str = 'utf8', + proto: Protocol = None, + allow_pickle: bool = False, + json_loads: Callable[[str], Any] = json.loads, + type_name: Optional[NameFactory] = None, +) -> T: + obj = load_str_bytes( + b, + proto=proto, + content_type=content_type, + encoding=encoding, + allow_pickle=allow_pickle, + json_loads=json_loads, + ) + return parse_obj_as(type_, obj, type_name=type_name) + + +def schema_of(type_: Any, *, title: Optional[NameFactory] = None, **schema_kwargs: Any) -> 'DictStrAny': + """Generate a JSON schema (as dict) for the passed model or dynamically generated one""" + return _get_parsing_type(type_, type_name=title).schema(**schema_kwargs) + + +def schema_json_of(type_: Any, *, title: Optional[NameFactory] = None, **schema_json_kwargs: Any) -> str: + """Generate a JSON schema (as JSON) for the passed model or dynamically generated one""" + return _get_parsing_type(type_, type_name=title).schema_json(**schema_json_kwargs) diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/types.py b/backend/.venv/Lib/site-packages/pydantic/v1/types.py new file mode 100644 index 0000000..e1840d9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/types.py @@ -0,0 +1,1205 @@ +import abc +import math +import re +import warnings +from datetime import date +from decimal import Decimal, InvalidOperation +from enum import Enum +from pathlib import Path +from types import new_class +from typing import ( + TYPE_CHECKING, + Any, + Callable, + ClassVar, + Dict, + FrozenSet, + List, + Optional, + Pattern, + Set, + Tuple, + Type, + TypeVar, + Union, + cast, + overload, +) +from uuid import UUID +from weakref import WeakSet + +from pydantic.v1 import errors +from pydantic.v1.datetime_parse import parse_date +from pydantic.v1.utils import import_string, update_not_none +from pydantic.v1.validators import ( + bytes_validator, + constr_length_validator, + constr_lower, + constr_strip_whitespace, + constr_upper, + decimal_validator, + float_finite_validator, + float_validator, + frozenset_validator, + int_validator, + list_validator, + number_multiple_validator, + number_size_validator, + path_exists_validator, + path_validator, + set_validator, + str_validator, + strict_bytes_validator, + strict_float_validator, + strict_int_validator, + strict_str_validator, +) + +__all__ = [ + 'NoneStr', + 'NoneBytes', + 'StrBytes', + 'NoneStrBytes', + 'StrictStr', + 'ConstrainedBytes', + 'conbytes', + 'ConstrainedList', + 'conlist', + 'ConstrainedSet', + 'conset', + 'ConstrainedFrozenSet', + 'confrozenset', + 'ConstrainedStr', + 'constr', + 'PyObject', + 'ConstrainedInt', + 'conint', + 'PositiveInt', + 'NegativeInt', + 'NonNegativeInt', + 'NonPositiveInt', + 'ConstrainedFloat', + 'confloat', + 'PositiveFloat', + 'NegativeFloat', + 'NonNegativeFloat', + 'NonPositiveFloat', + 'FiniteFloat', + 'ConstrainedDecimal', + 'condecimal', + 'UUID1', + 'UUID3', + 'UUID4', + 'UUID5', + 'FilePath', + 'DirectoryPath', + 'Json', + 'JsonWrapper', + 'SecretField', + 'SecretStr', + 'SecretBytes', + 'StrictBool', + 'StrictBytes', + 'StrictInt', + 'StrictFloat', + 'PaymentCardNumber', + 'ByteSize', + 'PastDate', + 'FutureDate', + 'ConstrainedDate', + 'condate', +] + +NoneStr = Optional[str] +NoneBytes = Optional[bytes] +StrBytes = Union[str, bytes] +NoneStrBytes = Optional[StrBytes] +OptionalInt = Optional[int] +OptionalIntFloat = Union[OptionalInt, float] +OptionalIntFloatDecimal = Union[OptionalIntFloat, Decimal] +OptionalDate = Optional[date] +StrIntFloat = Union[str, int, float] + +if TYPE_CHECKING: + from typing_extensions import Annotated + + from pydantic.v1.dataclasses import Dataclass + from pydantic.v1.main import BaseModel + from pydantic.v1.typing import CallableGenerator + + ModelOrDc = Type[Union[BaseModel, Dataclass]] + +T = TypeVar('T') +_DEFINED_TYPES: 'WeakSet[type]' = WeakSet() + + +@overload +def _registered(typ: Type[T]) -> Type[T]: + pass + + +@overload +def _registered(typ: 'ConstrainedNumberMeta') -> 'ConstrainedNumberMeta': + pass + + +def _registered(typ: Union[Type[T], 'ConstrainedNumberMeta']) -> Union[Type[T], 'ConstrainedNumberMeta']: + # In order to generate valid examples of constrained types, Hypothesis needs + # to inspect the type object - so we keep a weakref to each contype object + # until it can be registered. When (or if) our Hypothesis plugin is loaded, + # it monkeypatches this function. + # If Hypothesis is never used, the total effect is to keep a weak reference + # which has minimal memory usage and doesn't even affect garbage collection. + _DEFINED_TYPES.add(typ) + return typ + + +class ConstrainedNumberMeta(type): + def __new__(cls, name: str, bases: Any, dct: Dict[str, Any]) -> 'ConstrainedInt': # type: ignore + new_cls = cast('ConstrainedInt', type.__new__(cls, name, bases, dct)) + + if new_cls.gt is not None and new_cls.ge is not None: + raise errors.ConfigError('bounds gt and ge cannot be specified at the same time') + if new_cls.lt is not None and new_cls.le is not None: + raise errors.ConfigError('bounds lt and le cannot be specified at the same time') + + return _registered(new_cls) # type: ignore + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ BOOLEAN TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +if TYPE_CHECKING: + StrictBool = bool +else: + + class StrictBool(int): + """ + StrictBool to allow for bools which are not type-coerced. + """ + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update(type='boolean') + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.validate + + @classmethod + def validate(cls, value: Any) -> bool: + """ + Ensure that we only allow bools. + """ + if isinstance(value, bool): + return value + + raise errors.StrictBoolError() + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTEGER TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +class ConstrainedInt(int, metaclass=ConstrainedNumberMeta): + strict: bool = False + gt: OptionalInt = None + ge: OptionalInt = None + lt: OptionalInt = None + le: OptionalInt = None + multiple_of: OptionalInt = None + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none( + field_schema, + exclusiveMinimum=cls.gt, + exclusiveMaximum=cls.lt, + minimum=cls.ge, + maximum=cls.le, + multipleOf=cls.multiple_of, + ) + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield strict_int_validator if cls.strict else int_validator + yield number_size_validator + yield number_multiple_validator + + +def conint( + *, + strict: bool = False, + gt: Optional[int] = None, + ge: Optional[int] = None, + lt: Optional[int] = None, + le: Optional[int] = None, + multiple_of: Optional[int] = None, +) -> Type[int]: + # use kwargs then define conf in a dict to aid with IDE type hinting + namespace = dict(strict=strict, gt=gt, ge=ge, lt=lt, le=le, multiple_of=multiple_of) + return type('ConstrainedIntValue', (ConstrainedInt,), namespace) + + +if TYPE_CHECKING: + PositiveInt = int + NegativeInt = int + NonPositiveInt = int + NonNegativeInt = int + StrictInt = int +else: + + class PositiveInt(ConstrainedInt): + gt = 0 + + class NegativeInt(ConstrainedInt): + lt = 0 + + class NonPositiveInt(ConstrainedInt): + le = 0 + + class NonNegativeInt(ConstrainedInt): + ge = 0 + + class StrictInt(ConstrainedInt): + strict = True + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FLOAT TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +class ConstrainedFloat(float, metaclass=ConstrainedNumberMeta): + strict: bool = False + gt: OptionalIntFloat = None + ge: OptionalIntFloat = None + lt: OptionalIntFloat = None + le: OptionalIntFloat = None + multiple_of: OptionalIntFloat = None + allow_inf_nan: Optional[bool] = None + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none( + field_schema, + exclusiveMinimum=cls.gt, + exclusiveMaximum=cls.lt, + minimum=cls.ge, + maximum=cls.le, + multipleOf=cls.multiple_of, + ) + # Modify constraints to account for differences between IEEE floats and JSON + if field_schema.get('exclusiveMinimum') == -math.inf: + del field_schema['exclusiveMinimum'] + if field_schema.get('minimum') == -math.inf: + del field_schema['minimum'] + if field_schema.get('exclusiveMaximum') == math.inf: + del field_schema['exclusiveMaximum'] + if field_schema.get('maximum') == math.inf: + del field_schema['maximum'] + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield strict_float_validator if cls.strict else float_validator + yield number_size_validator + yield number_multiple_validator + yield float_finite_validator + + +def confloat( + *, + strict: bool = False, + gt: float = None, + ge: float = None, + lt: float = None, + le: float = None, + multiple_of: float = None, + allow_inf_nan: Optional[bool] = None, +) -> Type[float]: + # use kwargs then define conf in a dict to aid with IDE type hinting + namespace = dict(strict=strict, gt=gt, ge=ge, lt=lt, le=le, multiple_of=multiple_of, allow_inf_nan=allow_inf_nan) + return type('ConstrainedFloatValue', (ConstrainedFloat,), namespace) + + +if TYPE_CHECKING: + PositiveFloat = float + NegativeFloat = float + NonPositiveFloat = float + NonNegativeFloat = float + StrictFloat = float + FiniteFloat = float +else: + + class PositiveFloat(ConstrainedFloat): + gt = 0 + + class NegativeFloat(ConstrainedFloat): + lt = 0 + + class NonPositiveFloat(ConstrainedFloat): + le = 0 + + class NonNegativeFloat(ConstrainedFloat): + ge = 0 + + class StrictFloat(ConstrainedFloat): + strict = True + + class FiniteFloat(ConstrainedFloat): + allow_inf_nan = False + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ BYTES TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +class ConstrainedBytes(bytes): + strip_whitespace = False + to_upper = False + to_lower = False + min_length: OptionalInt = None + max_length: OptionalInt = None + strict: bool = False + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none(field_schema, minLength=cls.min_length, maxLength=cls.max_length) + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield strict_bytes_validator if cls.strict else bytes_validator + yield constr_strip_whitespace + yield constr_upper + yield constr_lower + yield constr_length_validator + + +def conbytes( + *, + strip_whitespace: bool = False, + to_upper: bool = False, + to_lower: bool = False, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + strict: bool = False, +) -> Type[bytes]: + # use kwargs then define conf in a dict to aid with IDE type hinting + namespace = dict( + strip_whitespace=strip_whitespace, + to_upper=to_upper, + to_lower=to_lower, + min_length=min_length, + max_length=max_length, + strict=strict, + ) + return _registered(type('ConstrainedBytesValue', (ConstrainedBytes,), namespace)) + + +if TYPE_CHECKING: + StrictBytes = bytes +else: + + class StrictBytes(ConstrainedBytes): + strict = True + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ STRING TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +class ConstrainedStr(str): + strip_whitespace = False + to_upper = False + to_lower = False + min_length: OptionalInt = None + max_length: OptionalInt = None + curtail_length: OptionalInt = None + regex: Optional[Union[str, Pattern[str]]] = None + strict = False + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none( + field_schema, + minLength=cls.min_length, + maxLength=cls.max_length, + pattern=cls.regex and cls._get_pattern(cls.regex), + ) + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield strict_str_validator if cls.strict else str_validator + yield constr_strip_whitespace + yield constr_upper + yield constr_lower + yield constr_length_validator + yield cls.validate + + @classmethod + def validate(cls, value: Union[str]) -> Union[str]: + if cls.curtail_length and len(value) > cls.curtail_length: + value = value[: cls.curtail_length] + + if cls.regex: + if not re.match(cls.regex, value): + raise errors.StrRegexError(pattern=cls._get_pattern(cls.regex)) + + return value + + @staticmethod + def _get_pattern(regex: Union[str, Pattern[str]]) -> str: + return regex if isinstance(regex, str) else regex.pattern + + +def constr( + *, + strip_whitespace: bool = False, + to_upper: bool = False, + to_lower: bool = False, + strict: bool = False, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + curtail_length: Optional[int] = None, + regex: Optional[str] = None, +) -> Type[str]: + # use kwargs then define conf in a dict to aid with IDE type hinting + namespace = dict( + strip_whitespace=strip_whitespace, + to_upper=to_upper, + to_lower=to_lower, + strict=strict, + min_length=min_length, + max_length=max_length, + curtail_length=curtail_length, + regex=regex and re.compile(regex), + ) + return _registered(type('ConstrainedStrValue', (ConstrainedStr,), namespace)) + + +if TYPE_CHECKING: + StrictStr = str +else: + + class StrictStr(ConstrainedStr): + strict = True + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SET TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +# This types superclass should be Set[T], but cython chokes on that... +class ConstrainedSet(set): # type: ignore + # Needed for pydantic to detect that this is a set + __origin__ = set + __args__: Set[Type[T]] # type: ignore + + min_items: Optional[int] = None + max_items: Optional[int] = None + item_type: Type[T] # type: ignore + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.set_length_validator + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none(field_schema, minItems=cls.min_items, maxItems=cls.max_items) + + @classmethod + def set_length_validator(cls, v: 'Optional[Set[T]]') -> 'Optional[Set[T]]': + if v is None: + return None + + v = set_validator(v) + v_len = len(v) + + if cls.min_items is not None and v_len < cls.min_items: + raise errors.SetMinLengthError(limit_value=cls.min_items) + + if cls.max_items is not None and v_len > cls.max_items: + raise errors.SetMaxLengthError(limit_value=cls.max_items) + + return v + + +def conset(item_type: Type[T], *, min_items: Optional[int] = None, max_items: Optional[int] = None) -> Type[Set[T]]: + # __args__ is needed to conform to typing generics api + namespace = {'min_items': min_items, 'max_items': max_items, 'item_type': item_type, '__args__': [item_type]} + # We use new_class to be able to deal with Generic types + return new_class('ConstrainedSetValue', (ConstrainedSet,), {}, lambda ns: ns.update(namespace)) + + +# This types superclass should be FrozenSet[T], but cython chokes on that... +class ConstrainedFrozenSet(frozenset): # type: ignore + # Needed for pydantic to detect that this is a set + __origin__ = frozenset + __args__: FrozenSet[Type[T]] # type: ignore + + min_items: Optional[int] = None + max_items: Optional[int] = None + item_type: Type[T] # type: ignore + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.frozenset_length_validator + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none(field_schema, minItems=cls.min_items, maxItems=cls.max_items) + + @classmethod + def frozenset_length_validator(cls, v: 'Optional[FrozenSet[T]]') -> 'Optional[FrozenSet[T]]': + if v is None: + return None + + v = frozenset_validator(v) + v_len = len(v) + + if cls.min_items is not None and v_len < cls.min_items: + raise errors.FrozenSetMinLengthError(limit_value=cls.min_items) + + if cls.max_items is not None and v_len > cls.max_items: + raise errors.FrozenSetMaxLengthError(limit_value=cls.max_items) + + return v + + +def confrozenset( + item_type: Type[T], *, min_items: Optional[int] = None, max_items: Optional[int] = None +) -> Type[FrozenSet[T]]: + # __args__ is needed to conform to typing generics api + namespace = {'min_items': min_items, 'max_items': max_items, 'item_type': item_type, '__args__': [item_type]} + # We use new_class to be able to deal with Generic types + return new_class('ConstrainedFrozenSetValue', (ConstrainedFrozenSet,), {}, lambda ns: ns.update(namespace)) + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LIST TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +# This types superclass should be List[T], but cython chokes on that... +class ConstrainedList(list): # type: ignore + # Needed for pydantic to detect that this is a list + __origin__ = list + __args__: Tuple[Type[T], ...] # type: ignore + + min_items: Optional[int] = None + max_items: Optional[int] = None + unique_items: Optional[bool] = None + item_type: Type[T] # type: ignore + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.list_length_validator + if cls.unique_items: + yield cls.unique_items_validator + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none(field_schema, minItems=cls.min_items, maxItems=cls.max_items, uniqueItems=cls.unique_items) + + @classmethod + def list_length_validator(cls, v: 'Optional[List[T]]') -> 'Optional[List[T]]': + if v is None: + return None + + v = list_validator(v) + v_len = len(v) + + if cls.min_items is not None and v_len < cls.min_items: + raise errors.ListMinLengthError(limit_value=cls.min_items) + + if cls.max_items is not None and v_len > cls.max_items: + raise errors.ListMaxLengthError(limit_value=cls.max_items) + + return v + + @classmethod + def unique_items_validator(cls, v: 'Optional[List[T]]') -> 'Optional[List[T]]': + if v is None: + return None + + for i, value in enumerate(v, start=1): + if value in v[i:]: + raise errors.ListUniqueItemsError() + + return v + + +def conlist( + item_type: Type[T], *, min_items: Optional[int] = None, max_items: Optional[int] = None, unique_items: bool = None +) -> Type[List[T]]: + # __args__ is needed to conform to typing generics api + namespace = dict( + min_items=min_items, max_items=max_items, unique_items=unique_items, item_type=item_type, __args__=(item_type,) + ) + # We use new_class to be able to deal with Generic types + return new_class('ConstrainedListValue', (ConstrainedList,), {}, lambda ns: ns.update(namespace)) + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PYOBJECT TYPE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +if TYPE_CHECKING: + PyObject = Callable[..., Any] +else: + + class PyObject: + validate_always = True + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.validate + + @classmethod + def validate(cls, value: Any) -> Any: + if isinstance(value, Callable): + return value + + try: + value = str_validator(value) + except errors.StrError: + raise errors.PyObjectError(error_message='value is neither a valid import path not a valid callable') + + try: + return import_string(value) + except ImportError as e: + raise errors.PyObjectError(error_message=str(e)) + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DECIMAL TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +class ConstrainedDecimal(Decimal, metaclass=ConstrainedNumberMeta): + gt: OptionalIntFloatDecimal = None + ge: OptionalIntFloatDecimal = None + lt: OptionalIntFloatDecimal = None + le: OptionalIntFloatDecimal = None + max_digits: OptionalInt = None + decimal_places: OptionalInt = None + multiple_of: OptionalIntFloatDecimal = None + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none( + field_schema, + exclusiveMinimum=cls.gt, + exclusiveMaximum=cls.lt, + minimum=cls.ge, + maximum=cls.le, + multipleOf=cls.multiple_of, + ) + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield decimal_validator + yield number_size_validator + yield number_multiple_validator + yield cls.validate + + @classmethod + def validate(cls, value: Decimal) -> Decimal: + try: + normalized_value = value.normalize() + except InvalidOperation: + normalized_value = value + digit_tuple, exponent = normalized_value.as_tuple()[1:] + if exponent in {'F', 'n', 'N'}: + raise errors.DecimalIsNotFiniteError() + + if exponent >= 0: + # A positive exponent adds that many trailing zeros. + digits = len(digit_tuple) + exponent + decimals = 0 + else: + # If the absolute value of the negative exponent is larger than the + # number of digits, then it's the same as the number of digits, + # because it'll consume all of the digits in digit_tuple and then + # add abs(exponent) - len(digit_tuple) leading zeros after the + # decimal point. + if abs(exponent) > len(digit_tuple): + digits = decimals = abs(exponent) + else: + digits = len(digit_tuple) + decimals = abs(exponent) + whole_digits = digits - decimals + + if cls.max_digits is not None and digits > cls.max_digits: + raise errors.DecimalMaxDigitsError(max_digits=cls.max_digits) + + if cls.decimal_places is not None and decimals > cls.decimal_places: + raise errors.DecimalMaxPlacesError(decimal_places=cls.decimal_places) + + if cls.max_digits is not None and cls.decimal_places is not None: + expected = cls.max_digits - cls.decimal_places + if whole_digits > expected: + raise errors.DecimalWholeDigitsError(whole_digits=expected) + + return value + + +def condecimal( + *, + gt: Decimal = None, + ge: Decimal = None, + lt: Decimal = None, + le: Decimal = None, + max_digits: Optional[int] = None, + decimal_places: Optional[int] = None, + multiple_of: Decimal = None, +) -> Type[Decimal]: + # use kwargs then define conf in a dict to aid with IDE type hinting + namespace = dict( + gt=gt, ge=ge, lt=lt, le=le, max_digits=max_digits, decimal_places=decimal_places, multiple_of=multiple_of + ) + return type('ConstrainedDecimalValue', (ConstrainedDecimal,), namespace) + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UUID TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +if TYPE_CHECKING: + UUID1 = UUID + UUID3 = UUID + UUID4 = UUID + UUID5 = UUID +else: + + class UUID1(UUID): + _required_version = 1 + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update(type='string', format=f'uuid{cls._required_version}') + + class UUID3(UUID1): + _required_version = 3 + + class UUID4(UUID1): + _required_version = 4 + + class UUID5(UUID1): + _required_version = 5 + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PATH TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +if TYPE_CHECKING: + FilePath = Path + DirectoryPath = Path +else: + + class FilePath(Path): + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update(format='file-path') + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield path_validator + yield path_exists_validator + yield cls.validate + + @classmethod + def validate(cls, value: Path) -> Path: + if not value.is_file(): + raise errors.PathNotAFileError(path=value) + + return value + + class DirectoryPath(Path): + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update(format='directory-path') + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield path_validator + yield path_exists_validator + yield cls.validate + + @classmethod + def validate(cls, value: Path) -> Path: + if not value.is_dir(): + raise errors.PathNotADirectoryError(path=value) + + return value + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON TYPE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +class JsonWrapper: + pass + + +class JsonMeta(type): + def __getitem__(self, t: Type[Any]) -> Type[JsonWrapper]: + if t is Any: + return Json # allow Json[Any] to replicate plain Json + return _registered(type('JsonWrapperValue', (JsonWrapper,), {'inner_type': t})) + + +if TYPE_CHECKING: + Json = Annotated[T, ...] # Json[list[str]] will be recognized by type checkers as list[str] + +else: + + class Json(metaclass=JsonMeta): + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update(type='string', format='json-string') + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SECRET TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +class SecretField(abc.ABC): + """ + Note: this should be implemented as a generic like `SecretField(ABC, Generic[T])`, + the `__init__()` should be part of the abstract class and the + `get_secret_value()` method should use the generic `T` type. + + However Cython doesn't support very well generics at the moment and + the generated code fails to be imported (see + https://github.com/cython/cython/issues/2753). + """ + + def __eq__(self, other: Any) -> bool: + return isinstance(other, self.__class__) and self.get_secret_value() == other.get_secret_value() + + def __str__(self) -> str: + return '**********' if self.get_secret_value() else '' + + def __hash__(self) -> int: + return hash(self.get_secret_value()) + + @abc.abstractmethod + def get_secret_value(self) -> Any: # pragma: no cover + ... + + +class SecretStr(SecretField): + min_length: OptionalInt = None + max_length: OptionalInt = None + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none( + field_schema, + type='string', + writeOnly=True, + format='password', + minLength=cls.min_length, + maxLength=cls.max_length, + ) + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.validate + yield constr_length_validator + + @classmethod + def validate(cls, value: Any) -> 'SecretStr': + if isinstance(value, cls): + return value + value = str_validator(value) + return cls(value) + + def __init__(self, value: str): + self._secret_value = value + + def __repr__(self) -> str: + return f"SecretStr('{self}')" + + def __len__(self) -> int: + return len(self._secret_value) + + def display(self) -> str: + warnings.warn('`secret_str.display()` is deprecated, use `str(secret_str)` instead', DeprecationWarning) + return str(self) + + def get_secret_value(self) -> str: + return self._secret_value + + +class SecretBytes(SecretField): + min_length: OptionalInt = None + max_length: OptionalInt = None + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none( + field_schema, + type='string', + writeOnly=True, + format='password', + minLength=cls.min_length, + maxLength=cls.max_length, + ) + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.validate + yield constr_length_validator + + @classmethod + def validate(cls, value: Any) -> 'SecretBytes': + if isinstance(value, cls): + return value + value = bytes_validator(value) + return cls(value) + + def __init__(self, value: bytes): + self._secret_value = value + + def __repr__(self) -> str: + return f"SecretBytes(b'{self}')" + + def __len__(self) -> int: + return len(self._secret_value) + + def display(self) -> str: + warnings.warn('`secret_bytes.display()` is deprecated, use `str(secret_bytes)` instead', DeprecationWarning) + return str(self) + + def get_secret_value(self) -> bytes: + return self._secret_value + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PAYMENT CARD TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +class PaymentCardBrand(str, Enum): + # If you add another card type, please also add it to the + # Hypothesis strategy in `pydantic._hypothesis_plugin`. + amex = 'American Express' + mastercard = 'Mastercard' + visa = 'Visa' + other = 'other' + + def __str__(self) -> str: + return self.value + + +class PaymentCardNumber(str): + """ + Based on: https://en.wikipedia.org/wiki/Payment_card_number + """ + + strip_whitespace: ClassVar[bool] = True + min_length: ClassVar[int] = 12 + max_length: ClassVar[int] = 19 + bin: str + last4: str + brand: PaymentCardBrand + + def __init__(self, card_number: str): + self.bin = card_number[:6] + self.last4 = card_number[-4:] + self.brand = self._get_brand(card_number) + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield str_validator + yield constr_strip_whitespace + yield constr_length_validator + yield cls.validate_digits + yield cls.validate_luhn_check_digit + yield cls + yield cls.validate_length_for_brand + + @property + def masked(self) -> str: + num_masked = len(self) - 10 # len(bin) + len(last4) == 10 + return f'{self.bin}{"*" * num_masked}{self.last4}' + + @classmethod + def validate_digits(cls, card_number: str) -> str: + if not card_number.isdigit(): + raise errors.NotDigitError + return card_number + + @classmethod + def validate_luhn_check_digit(cls, card_number: str) -> str: + """ + Based on: https://en.wikipedia.org/wiki/Luhn_algorithm + """ + sum_ = int(card_number[-1]) + length = len(card_number) + parity = length % 2 + for i in range(length - 1): + digit = int(card_number[i]) + if i % 2 == parity: + digit *= 2 + if digit > 9: + digit -= 9 + sum_ += digit + valid = sum_ % 10 == 0 + if not valid: + raise errors.LuhnValidationError + return card_number + + @classmethod + def validate_length_for_brand(cls, card_number: 'PaymentCardNumber') -> 'PaymentCardNumber': + """ + Validate length based on BIN for major brands: + https://en.wikipedia.org/wiki/Payment_card_number#Issuer_identification_number_(IIN) + """ + required_length: Union[None, int, str] = None + if card_number.brand in PaymentCardBrand.mastercard: + required_length = 16 + valid = len(card_number) == required_length + elif card_number.brand == PaymentCardBrand.visa: + required_length = '13, 16 or 19' + valid = len(card_number) in {13, 16, 19} + elif card_number.brand == PaymentCardBrand.amex: + required_length = 15 + valid = len(card_number) == required_length + else: + valid = True + if not valid: + raise errors.InvalidLengthForBrand(brand=card_number.brand, required_length=required_length) + return card_number + + @staticmethod + def _get_brand(card_number: str) -> PaymentCardBrand: + if card_number[0] == '4': + brand = PaymentCardBrand.visa + elif 51 <= int(card_number[:2]) <= 55: + brand = PaymentCardBrand.mastercard + elif card_number[:2] in {'34', '37'}: + brand = PaymentCardBrand.amex + else: + brand = PaymentCardBrand.other + return brand + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ BYTE SIZE TYPE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +BYTE_SIZES = { + 'b': 1, + 'kb': 10**3, + 'mb': 10**6, + 'gb': 10**9, + 'tb': 10**12, + 'pb': 10**15, + 'eb': 10**18, + 'kib': 2**10, + 'mib': 2**20, + 'gib': 2**30, + 'tib': 2**40, + 'pib': 2**50, + 'eib': 2**60, +} +BYTE_SIZES.update({k.lower()[0]: v for k, v in BYTE_SIZES.items() if 'i' not in k}) +byte_string_re = re.compile(r'^\s*(\d*\.?\d+)\s*(\w+)?', re.IGNORECASE) + + +class ByteSize(int): + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.validate + + @classmethod + def validate(cls, v: StrIntFloat) -> 'ByteSize': + try: + return cls(int(v)) + except ValueError: + pass + + str_match = byte_string_re.match(str(v)) + if str_match is None: + raise errors.InvalidByteSize() + + scalar, unit = str_match.groups() + if unit is None: + unit = 'b' + + try: + unit_mult = BYTE_SIZES[unit.lower()] + except KeyError: + raise errors.InvalidByteSizeUnit(unit=unit) + + return cls(int(float(scalar) * unit_mult)) + + def human_readable(self, decimal: bool = False) -> str: + if decimal: + divisor = 1000 + units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'] + final_unit = 'EB' + else: + divisor = 1024 + units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB'] + final_unit = 'EiB' + + num = float(self) + for unit in units: + if abs(num) < divisor: + return f'{num:0.1f}{unit}' + num /= divisor + + return f'{num:0.1f}{final_unit}' + + def to(self, unit: str) -> float: + try: + unit_div = BYTE_SIZES[unit.lower()] + except KeyError: + raise errors.InvalidByteSizeUnit(unit=unit) + + return self / unit_div + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DATE TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +if TYPE_CHECKING: + PastDate = date + FutureDate = date +else: + + class PastDate(date): + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield parse_date + yield cls.validate + + @classmethod + def validate(cls, value: date) -> date: + if value >= date.today(): + raise errors.DateNotInThePastError() + + return value + + class FutureDate(date): + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield parse_date + yield cls.validate + + @classmethod + def validate(cls, value: date) -> date: + if value <= date.today(): + raise errors.DateNotInTheFutureError() + + return value + + +class ConstrainedDate(date, metaclass=ConstrainedNumberMeta): + gt: OptionalDate = None + ge: OptionalDate = None + lt: OptionalDate = None + le: OptionalDate = None + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none(field_schema, exclusiveMinimum=cls.gt, exclusiveMaximum=cls.lt, minimum=cls.ge, maximum=cls.le) + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield parse_date + yield number_size_validator + + +def condate( + *, + gt: date = None, + ge: date = None, + lt: date = None, + le: date = None, +) -> Type[date]: + # use kwargs then define conf in a dict to aid with IDE type hinting + namespace = dict(gt=gt, ge=ge, lt=lt, le=le) + return type('ConstrainedDateValue', (ConstrainedDate,), namespace) diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/typing.py b/backend/.venv/Lib/site-packages/pydantic/v1/typing.py new file mode 100644 index 0000000..9741161 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/typing.py @@ -0,0 +1,614 @@ +import functools +import operator +import sys +import typing +from collections.abc import Callable +from os import PathLike +from typing import ( # type: ignore + TYPE_CHECKING, + AbstractSet, + Any, + Callable as TypingCallable, + ClassVar, + Dict, + ForwardRef, + Generator, + Iterable, + List, + Mapping, + NewType, + Optional, + Sequence, + Set, + Tuple, + Type, + TypeVar, + Union, + _eval_type, + cast, + get_type_hints, +) + +from typing_extensions import ( + Annotated, + Final, + Literal, + NotRequired as TypedDictNotRequired, + Required as TypedDictRequired, +) + +try: + from typing import _TypingBase as typing_base # type: ignore +except ImportError: + from typing import _Final as typing_base # type: ignore + +try: + from typing import GenericAlias as TypingGenericAlias # type: ignore +except ImportError: + # python < 3.9 does not have GenericAlias (list[int], tuple[str, ...] and so on) + TypingGenericAlias = () + +try: + from types import UnionType as TypesUnionType # type: ignore +except ImportError: + # python < 3.10 does not have UnionType (str | int, byte | bool and so on) + TypesUnionType = () + + +if sys.version_info < (3, 9): + + def evaluate_forwardref(type_: ForwardRef, globalns: Any, localns: Any) -> Any: + return type_._evaluate(globalns, localns) + +elif sys.version_info < (3, 12, 4): + + def evaluate_forwardref(type_: ForwardRef, globalns: Any, localns: Any) -> Any: + # Even though it is the right signature for python 3.9, mypy complains with + # `error: Too many arguments for "_evaluate" of "ForwardRef"` hence the cast... + # Python 3.13/3.12.4+ made `recursive_guard` a kwarg, so name it explicitly to avoid: + # TypeError: ForwardRef._evaluate() missing 1 required keyword-only argument: 'recursive_guard' + return cast(Any, type_)._evaluate(globalns, localns, recursive_guard=set()) + +else: + + def evaluate_forwardref(type_: ForwardRef, globalns: Any, localns: Any) -> Any: + # Pydantic 1.x will not support PEP 695 syntax, but provide `type_params` to avoid + # warnings: + return cast(Any, type_)._evaluate(globalns, localns, type_params=(), recursive_guard=set()) + + +if sys.version_info < (3, 9): + # Ensure we always get all the whole `Annotated` hint, not just the annotated type. + # For 3.7 to 3.8, `get_type_hints` doesn't recognize `typing_extensions.Annotated`, + # so it already returns the full annotation + get_all_type_hints = get_type_hints + +else: + + def get_all_type_hints(obj: Any, globalns: Any = None, localns: Any = None) -> Any: + return get_type_hints(obj, globalns, localns, include_extras=True) + + +_T = TypeVar('_T') + +AnyCallable = TypingCallable[..., Any] +NoArgAnyCallable = TypingCallable[[], Any] + +# workaround for https://github.com/python/mypy/issues/9496 +AnyArgTCallable = TypingCallable[..., _T] + + +# Annotated[...] is implemented by returning an instance of one of these classes, depending on +# python/typing_extensions version. +AnnotatedTypeNames = {'AnnotatedMeta', '_AnnotatedAlias'} + + +LITERAL_TYPES: Set[Any] = {Literal} +if hasattr(typing, 'Literal'): + LITERAL_TYPES.add(typing.Literal) + + +if sys.version_info < (3, 8): + + def get_origin(t: Type[Any]) -> Optional[Type[Any]]: + if type(t).__name__ in AnnotatedTypeNames: + # weirdly this is a runtime requirement, as well as for mypy + return cast(Type[Any], Annotated) + return getattr(t, '__origin__', None) + +else: + from typing import get_origin as _typing_get_origin + + def get_origin(tp: Type[Any]) -> Optional[Type[Any]]: + """ + We can't directly use `typing.get_origin` since we need a fallback to support + custom generic classes like `ConstrainedList` + It should be useless once https://github.com/cython/cython/issues/3537 is + solved and https://github.com/pydantic/pydantic/pull/1753 is merged. + """ + if type(tp).__name__ in AnnotatedTypeNames: + return cast(Type[Any], Annotated) # mypy complains about _SpecialForm + return _typing_get_origin(tp) or getattr(tp, '__origin__', None) + + +if sys.version_info < (3, 8): + from typing import _GenericAlias + + def get_args(t: Type[Any]) -> Tuple[Any, ...]: + """Compatibility version of get_args for python 3.7. + + Mostly compatible with the python 3.8 `typing` module version + and able to handle almost all use cases. + """ + if type(t).__name__ in AnnotatedTypeNames: + return t.__args__ + t.__metadata__ + if isinstance(t, _GenericAlias): + res = t.__args__ + if t.__origin__ is Callable and res and res[0] is not Ellipsis: + res = (list(res[:-1]), res[-1]) + return res + return getattr(t, '__args__', ()) + +else: + from typing import get_args as _typing_get_args + + def _generic_get_args(tp: Type[Any]) -> Tuple[Any, ...]: + """ + In python 3.9, `typing.Dict`, `typing.List`, ... + do have an empty `__args__` by default (instead of the generic ~T for example). + In order to still support `Dict` for example and consider it as `Dict[Any, Any]`, + we retrieve the `_nparams` value that tells us how many parameters it needs. + """ + if hasattr(tp, '_nparams'): + return (Any,) * tp._nparams + # Special case for `tuple[()]`, which used to return ((),) with `typing.Tuple` + # in python 3.10- but now returns () for `tuple` and `Tuple`. + # This will probably be clarified in pydantic v2 + try: + if tp == Tuple[()] or sys.version_info >= (3, 9) and tp == tuple[()]: # type: ignore[misc] + return ((),) + # there is a TypeError when compiled with cython + except TypeError: # pragma: no cover + pass + return () + + def get_args(tp: Type[Any]) -> Tuple[Any, ...]: + """Get type arguments with all substitutions performed. + + For unions, basic simplifications used by Union constructor are performed. + Examples:: + get_args(Dict[str, int]) == (str, int) + get_args(int) == () + get_args(Union[int, Union[T, int], str][int]) == (int, str) + get_args(Union[int, Tuple[T, int]][str]) == (int, Tuple[str, int]) + get_args(Callable[[], T][int]) == ([], int) + """ + if type(tp).__name__ in AnnotatedTypeNames: + return tp.__args__ + tp.__metadata__ + # the fallback is needed for the same reasons as `get_origin` (see above) + return _typing_get_args(tp) or getattr(tp, '__args__', ()) or _generic_get_args(tp) + + +if sys.version_info < (3, 9): + + def convert_generics(tp: Type[Any]) -> Type[Any]: + """Python 3.9 and older only supports generics from `typing` module. + They convert strings to ForwardRef automatically. + + Examples:: + typing.List['Hero'] == typing.List[ForwardRef('Hero')] + """ + return tp + +else: + + def convert_generics(tp: Type[Any]) -> Type[Any]: + """ + Recursively searches for `str` type hints and replaces them with ForwardRef. + + Examples:: + convert_generics(list['Hero']) == list[ForwardRef('Hero')] + convert_generics(dict['Hero', 'Team']) == dict[ForwardRef('Hero'), ForwardRef('Team')] + convert_generics(typing.Dict['Hero', 'Team']) == typing.Dict[ForwardRef('Hero'), ForwardRef('Team')] + convert_generics(list[str | 'Hero'] | int) == list[str | ForwardRef('Hero')] | int + """ + origin = get_origin(tp) + if not origin or not hasattr(tp, '__args__'): + return tp + + args = get_args(tp) + + # typing.Annotated needs special treatment + if origin is Annotated: + return Annotated[(convert_generics(args[0]), *args[1:])] # type: ignore + + # recursively replace `str` instances inside of `GenericAlias` with `ForwardRef(arg)` + converted = tuple( + ForwardRef(arg) if isinstance(arg, str) and isinstance(tp, TypingGenericAlias) else convert_generics(arg) + for arg in args + ) + + if converted == args: + return tp + elif isinstance(tp, TypingGenericAlias): + return TypingGenericAlias(origin, converted) + elif isinstance(tp, TypesUnionType): + # recreate types.UnionType (PEP604, Python >= 3.10) + return functools.reduce(operator.or_, converted) # type: ignore + else: + try: + setattr(tp, '__args__', converted) + except AttributeError: + pass + return tp + + +if sys.version_info < (3, 10): + + def is_union(tp: Optional[Type[Any]]) -> bool: + return tp is Union + + WithArgsTypes = (TypingGenericAlias,) + +else: + import types + import typing + + def is_union(tp: Optional[Type[Any]]) -> bool: + return tp is Union or tp is types.UnionType # noqa: E721 + + WithArgsTypes = (typing._GenericAlias, types.GenericAlias, types.UnionType) + + +StrPath = Union[str, PathLike] + + +if TYPE_CHECKING: + from pydantic.v1.fields import ModelField + + TupleGenerator = Generator[Tuple[str, Any], None, None] + DictStrAny = Dict[str, Any] + DictAny = Dict[Any, Any] + SetStr = Set[str] + ListStr = List[str] + IntStr = Union[int, str] + AbstractSetIntStr = AbstractSet[IntStr] + DictIntStrAny = Dict[IntStr, Any] + MappingIntStrAny = Mapping[IntStr, Any] + CallableGenerator = Generator[AnyCallable, None, None] + ReprArgs = Sequence[Tuple[Optional[str], Any]] + + MYPY = False + if MYPY: + AnyClassMethod = classmethod[Any] + else: + # classmethod[TargetType, CallableParamSpecType, CallableReturnType] + AnyClassMethod = classmethod[Any, Any, Any] + +__all__ = ( + 'AnyCallable', + 'NoArgAnyCallable', + 'NoneType', + 'is_none_type', + 'display_as_type', + 'resolve_annotations', + 'is_callable_type', + 'is_literal_type', + 'all_literal_values', + 'is_namedtuple', + 'is_typeddict', + 'is_typeddict_special', + 'is_new_type', + 'new_type_supertype', + 'is_classvar', + 'is_finalvar', + 'update_field_forward_refs', + 'update_model_forward_refs', + 'TupleGenerator', + 'DictStrAny', + 'DictAny', + 'SetStr', + 'ListStr', + 'IntStr', + 'AbstractSetIntStr', + 'DictIntStrAny', + 'CallableGenerator', + 'ReprArgs', + 'AnyClassMethod', + 'CallableGenerator', + 'WithArgsTypes', + 'get_args', + 'get_origin', + 'get_sub_types', + 'typing_base', + 'get_all_type_hints', + 'is_union', + 'StrPath', + 'MappingIntStrAny', +) + + +NoneType = None.__class__ + + +NONE_TYPES: Tuple[Any, Any, Any] = (None, NoneType, Literal[None]) + + +if sys.version_info < (3, 8): + # Even though this implementation is slower, we need it for python 3.7: + # In python 3.7 "Literal" is not a builtin type and uses a different + # mechanism. + # for this reason `Literal[None] is Literal[None]` evaluates to `False`, + # breaking the faster implementation used for the other python versions. + + def is_none_type(type_: Any) -> bool: + return type_ in NONE_TYPES + +elif sys.version_info[:2] == (3, 8): + + def is_none_type(type_: Any) -> bool: + for none_type in NONE_TYPES: + if type_ is none_type: + return True + # With python 3.8, specifically 3.8.10, Literal "is" check sare very flakey + # can change on very subtle changes like use of types in other modules, + # hopefully this check avoids that issue. + if is_literal_type(type_): # pragma: no cover + return all_literal_values(type_) == (None,) + return False + +else: + + def is_none_type(type_: Any) -> bool: + return type_ in NONE_TYPES + + +def display_as_type(v: Type[Any]) -> str: + if not isinstance(v, typing_base) and not isinstance(v, WithArgsTypes) and not isinstance(v, type): + v = v.__class__ + + if is_union(get_origin(v)): + return f'Union[{", ".join(map(display_as_type, get_args(v)))}]' + + if isinstance(v, WithArgsTypes): + # Generic alias are constructs like `list[int]` + return str(v).replace('typing.', '') + + try: + return v.__name__ + except AttributeError: + # happens with typing objects + return str(v).replace('typing.', '') + + +def resolve_annotations(raw_annotations: Dict[str, Type[Any]], module_name: Optional[str]) -> Dict[str, Type[Any]]: + """ + Partially taken from typing.get_type_hints. + + Resolve string or ForwardRef annotations into type objects if possible. + """ + base_globals: Optional[Dict[str, Any]] = None + if module_name: + try: + module = sys.modules[module_name] + except KeyError: + # happens occasionally, see https://github.com/pydantic/pydantic/issues/2363 + pass + else: + base_globals = module.__dict__ + + annotations = {} + for name, value in raw_annotations.items(): + if isinstance(value, str): + if (3, 10) > sys.version_info >= (3, 9, 8) or sys.version_info >= (3, 10, 1): + value = ForwardRef(value, is_argument=False, is_class=True) + else: + value = ForwardRef(value, is_argument=False) + try: + if sys.version_info >= (3, 13): + value = _eval_type(value, base_globals, None, type_params=()) + else: + value = _eval_type(value, base_globals, None) + except NameError: + # this is ok, it can be fixed with update_forward_refs + pass + annotations[name] = value + return annotations + + +def is_callable_type(type_: Type[Any]) -> bool: + return type_ is Callable or get_origin(type_) is Callable + + +def is_literal_type(type_: Type[Any]) -> bool: + return Literal is not None and get_origin(type_) in LITERAL_TYPES + + +def literal_values(type_: Type[Any]) -> Tuple[Any, ...]: + return get_args(type_) + + +def all_literal_values(type_: Type[Any]) -> Tuple[Any, ...]: + """ + This method is used to retrieve all Literal values as + Literal can be used recursively (see https://www.python.org/dev/peps/pep-0586) + e.g. `Literal[Literal[Literal[1, 2, 3], "foo"], 5, None]` + """ + if not is_literal_type(type_): + return (type_,) + + values = literal_values(type_) + return tuple(x for value in values for x in all_literal_values(value)) + + +def is_namedtuple(type_: Type[Any]) -> bool: + """ + Check if a given class is a named tuple. + It can be either a `typing.NamedTuple` or `collections.namedtuple` + """ + from pydantic.v1.utils import lenient_issubclass + + return lenient_issubclass(type_, tuple) and hasattr(type_, '_fields') + + +def is_typeddict(type_: Type[Any]) -> bool: + """ + Check if a given class is a typed dict (from `typing` or `typing_extensions`) + In 3.10, there will be a public method (https://docs.python.org/3.10/library/typing.html#typing.is_typeddict) + """ + from pydantic.v1.utils import lenient_issubclass + + return lenient_issubclass(type_, dict) and hasattr(type_, '__total__') + + +def _check_typeddict_special(type_: Any) -> bool: + return type_ is TypedDictRequired or type_ is TypedDictNotRequired + + +def is_typeddict_special(type_: Any) -> bool: + """ + Check if type is a TypedDict special form (Required or NotRequired). + """ + return _check_typeddict_special(type_) or _check_typeddict_special(get_origin(type_)) + + +test_type = NewType('test_type', str) + + +def is_new_type(type_: Type[Any]) -> bool: + """ + Check whether type_ was created using typing.NewType + """ + return isinstance(type_, test_type.__class__) and hasattr(type_, '__supertype__') # type: ignore + + +def new_type_supertype(type_: Type[Any]) -> Type[Any]: + while hasattr(type_, '__supertype__'): + type_ = type_.__supertype__ + return type_ + + +def _check_classvar(v: Optional[Type[Any]]) -> bool: + if v is None: + return False + + return v.__class__ == ClassVar.__class__ and getattr(v, '_name', None) == 'ClassVar' + + +def _check_finalvar(v: Optional[Type[Any]]) -> bool: + """ + Check if a given type is a `typing.Final` type. + """ + if v is None: + return False + + return v.__class__ == Final.__class__ and (sys.version_info < (3, 8) or getattr(v, '_name', None) == 'Final') + + +def is_classvar(ann_type: Type[Any]) -> bool: + if _check_classvar(ann_type) or _check_classvar(get_origin(ann_type)): + return True + + # this is an ugly workaround for class vars that contain forward references and are therefore themselves + # forward references, see #3679 + if ann_type.__class__ == ForwardRef and ann_type.__forward_arg__.startswith('ClassVar['): + return True + + return False + + +def is_finalvar(ann_type: Type[Any]) -> bool: + return _check_finalvar(ann_type) or _check_finalvar(get_origin(ann_type)) + + +def update_field_forward_refs(field: 'ModelField', globalns: Any, localns: Any) -> None: + """ + Try to update ForwardRefs on fields based on this ModelField, globalns and localns. + """ + prepare = False + if field.type_.__class__ == ForwardRef: + prepare = True + field.type_ = evaluate_forwardref(field.type_, globalns, localns or None) + if field.outer_type_.__class__ == ForwardRef: + prepare = True + field.outer_type_ = evaluate_forwardref(field.outer_type_, globalns, localns or None) + if prepare: + field.prepare() + + if field.sub_fields: + for sub_f in field.sub_fields: + update_field_forward_refs(sub_f, globalns=globalns, localns=localns) + + if field.discriminator_key is not None: + field.prepare_discriminated_union_sub_fields() + + +def update_model_forward_refs( + model: Type[Any], + fields: Iterable['ModelField'], + json_encoders: Dict[Union[Type[Any], str, ForwardRef], AnyCallable], + localns: 'DictStrAny', + exc_to_suppress: Tuple[Type[BaseException], ...] = (), +) -> None: + """ + Try to update model fields ForwardRefs based on model and localns. + """ + if model.__module__ in sys.modules: + globalns = sys.modules[model.__module__].__dict__.copy() + else: + globalns = {} + + globalns.setdefault(model.__name__, model) + + for f in fields: + try: + update_field_forward_refs(f, globalns=globalns, localns=localns) + except exc_to_suppress: + pass + + for key in set(json_encoders.keys()): + if isinstance(key, str): + fr: ForwardRef = ForwardRef(key) + elif isinstance(key, ForwardRef): + fr = key + else: + continue + + try: + new_key = evaluate_forwardref(fr, globalns, localns or None) + except exc_to_suppress: # pragma: no cover + continue + + json_encoders[new_key] = json_encoders.pop(key) + + +def get_class(type_: Type[Any]) -> Union[None, bool, Type[Any]]: + """ + Tries to get the class of a Type[T] annotation. Returns True if Type is used + without brackets. Otherwise returns None. + """ + if type_ is type: + return True + + if get_origin(type_) is None: + return None + + args = get_args(type_) + if not args or not isinstance(args[0], type): + return True + else: + return args[0] + + +def get_sub_types(tp: Any) -> List[Any]: + """ + Return all the types that are allowed by type `tp` + `tp` can be a `Union` of allowed types or an `Annotated` type + """ + origin = get_origin(tp) + if origin is Annotated: + return get_sub_types(get_args(tp)[0]) + elif is_union(origin): + return [x for t in get_args(tp) for x in get_sub_types(t)] + else: + return [tp] diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/utils.py b/backend/.venv/Lib/site-packages/pydantic/v1/utils.py new file mode 100644 index 0000000..02543fd --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/utils.py @@ -0,0 +1,806 @@ +import keyword +import warnings +import weakref +from collections import OrderedDict, defaultdict, deque +from copy import deepcopy +from itertools import islice, zip_longest +from types import BuiltinFunctionType, CodeType, FunctionType, GeneratorType, LambdaType, ModuleType +from typing import ( + TYPE_CHECKING, + AbstractSet, + Any, + Callable, + Collection, + Dict, + Generator, + Iterable, + Iterator, + List, + Mapping, + NoReturn, + Optional, + Set, + Tuple, + Type, + TypeVar, + Union, +) + +from typing_extensions import Annotated + +from pydantic.v1.errors import ConfigError +from pydantic.v1.typing import ( + NoneType, + WithArgsTypes, + all_literal_values, + display_as_type, + get_args, + get_origin, + is_literal_type, + is_union, +) +from pydantic.v1.version import version_info + +if TYPE_CHECKING: + from inspect import Signature + from pathlib import Path + + from pydantic.v1.config import BaseConfig + from pydantic.v1.dataclasses import Dataclass + from pydantic.v1.fields import ModelField + from pydantic.v1.main import BaseModel + from pydantic.v1.typing import AbstractSetIntStr, DictIntStrAny, IntStr, MappingIntStrAny, ReprArgs + + RichReprResult = Iterable[Union[Any, Tuple[Any], Tuple[str, Any], Tuple[str, Any, Any]]] + +__all__ = ( + 'import_string', + 'sequence_like', + 'validate_field_name', + 'lenient_isinstance', + 'lenient_issubclass', + 'in_ipython', + 'is_valid_identifier', + 'deep_update', + 'update_not_none', + 'almost_equal_floats', + 'get_model', + 'to_camel', + 'to_lower_camel', + 'is_valid_field', + 'smart_deepcopy', + 'PyObjectStr', + 'Representation', + 'GetterDict', + 'ValueItems', + 'version_info', # required here to match behaviour in v1.3 + 'ClassAttribute', + 'path_type', + 'ROOT_KEY', + 'get_unique_discriminator_alias', + 'get_discriminator_alias_and_values', + 'DUNDER_ATTRIBUTES', +) + +ROOT_KEY = '__root__' +# these are types that are returned unchanged by deepcopy +IMMUTABLE_NON_COLLECTIONS_TYPES: Set[Type[Any]] = { + int, + float, + complex, + str, + bool, + bytes, + type, + NoneType, + FunctionType, + BuiltinFunctionType, + LambdaType, + weakref.ref, + CodeType, + # note: including ModuleType will differ from behaviour of deepcopy by not producing error. + # It might be not a good idea in general, but considering that this function used only internally + # against default values of fields, this will allow to actually have a field with module as default value + ModuleType, + NotImplemented.__class__, + Ellipsis.__class__, +} + +# these are types that if empty, might be copied with simple copy() instead of deepcopy() +BUILTIN_COLLECTIONS: Set[Type[Any]] = { + list, + set, + tuple, + frozenset, + dict, + OrderedDict, + defaultdict, + deque, +} + + +def import_string(dotted_path: str) -> Any: + """ + Stolen approximately from django. Import a dotted module path and return the attribute/class designated by the + last name in the path. Raise ImportError if the import fails. + """ + from importlib import import_module + + try: + module_path, class_name = dotted_path.strip(' ').rsplit('.', 1) + except ValueError as e: + raise ImportError(f'"{dotted_path}" doesn\'t look like a module path') from e + + module = import_module(module_path) + try: + return getattr(module, class_name) + except AttributeError as e: + raise ImportError(f'Module "{module_path}" does not define a "{class_name}" attribute') from e + + +def truncate(v: Union[str], *, max_len: int = 80) -> str: + """ + Truncate a value and add a unicode ellipsis (three dots) to the end if it was too long + """ + warnings.warn('`truncate` is no-longer used by pydantic and is deprecated', DeprecationWarning) + if isinstance(v, str) and len(v) > (max_len - 2): + # -3 so quote + string + … + quote has correct length + return (v[: (max_len - 3)] + '…').__repr__() + try: + v = v.__repr__() + except TypeError: + v = v.__class__.__repr__(v) # in case v is a type + if len(v) > max_len: + v = v[: max_len - 1] + '…' + return v + + +def sequence_like(v: Any) -> bool: + return isinstance(v, (list, tuple, set, frozenset, GeneratorType, deque)) + + +def validate_field_name(bases: Iterable[Type[Any]], field_name: str) -> None: + """ + Ensure that the field's name does not shadow an existing attribute of the model. + """ + for base in bases: + if getattr(base, field_name, None): + raise NameError( + f'Field name "{field_name}" shadows a BaseModel attribute; ' + f'use a different field name with "alias=\'{field_name}\'".' + ) + + +def lenient_isinstance(o: Any, class_or_tuple: Union[Type[Any], Tuple[Type[Any], ...], None]) -> bool: + try: + return isinstance(o, class_or_tuple) # type: ignore[arg-type] + except TypeError: + return False + + +def lenient_issubclass(cls: Any, class_or_tuple: Union[Type[Any], Tuple[Type[Any], ...], None]) -> bool: + try: + return isinstance(cls, type) and issubclass(cls, class_or_tuple) # type: ignore[arg-type] + except TypeError: + if isinstance(cls, WithArgsTypes): + return False + raise # pragma: no cover + + +def in_ipython() -> bool: + """ + Check whether we're in an ipython environment, including jupyter notebooks. + """ + try: + eval('__IPYTHON__') + except NameError: + return False + else: # pragma: no cover + return True + + +def is_valid_identifier(identifier: str) -> bool: + """ + Checks that a string is a valid identifier and not a Python keyword. + :param identifier: The identifier to test. + :return: True if the identifier is valid. + """ + return identifier.isidentifier() and not keyword.iskeyword(identifier) + + +KeyType = TypeVar('KeyType') + + +def deep_update(mapping: Dict[KeyType, Any], *updating_mappings: Dict[KeyType, Any]) -> Dict[KeyType, Any]: + updated_mapping = mapping.copy() + for updating_mapping in updating_mappings: + for k, v in updating_mapping.items(): + if k in updated_mapping and isinstance(updated_mapping[k], dict) and isinstance(v, dict): + updated_mapping[k] = deep_update(updated_mapping[k], v) + else: + updated_mapping[k] = v + return updated_mapping + + +def update_not_none(mapping: Dict[Any, Any], **update: Any) -> None: + mapping.update({k: v for k, v in update.items() if v is not None}) + + +def almost_equal_floats(value_1: float, value_2: float, *, delta: float = 1e-8) -> bool: + """ + Return True if two floats are almost equal + """ + return abs(value_1 - value_2) <= delta + + +def generate_model_signature( + init: Callable[..., None], fields: Dict[str, 'ModelField'], config: Type['BaseConfig'] +) -> 'Signature': + """ + Generate signature for model based on its fields + """ + from inspect import Parameter, Signature, signature + + from pydantic.v1.config import Extra + + present_params = signature(init).parameters.values() + merged_params: Dict[str, Parameter] = {} + var_kw = None + use_var_kw = False + + for param in islice(present_params, 1, None): # skip self arg + if param.kind is param.VAR_KEYWORD: + var_kw = param + continue + merged_params[param.name] = param + + if var_kw: # if custom init has no var_kw, fields which are not declared in it cannot be passed through + allow_names = config.allow_population_by_field_name + for field_name, field in fields.items(): + param_name = field.alias + if field_name in merged_params or param_name in merged_params: + continue + elif not is_valid_identifier(param_name): + if allow_names and is_valid_identifier(field_name): + param_name = field_name + else: + use_var_kw = True + continue + + # TODO: replace annotation with actual expected types once #1055 solved + kwargs = {'default': field.default} if not field.required else {} + merged_params[param_name] = Parameter( + param_name, Parameter.KEYWORD_ONLY, annotation=field.annotation, **kwargs + ) + + if config.extra is Extra.allow: + use_var_kw = True + + if var_kw and use_var_kw: + # Make sure the parameter for extra kwargs + # does not have the same name as a field + default_model_signature = [ + ('__pydantic_self__', Parameter.POSITIONAL_OR_KEYWORD), + ('data', Parameter.VAR_KEYWORD), + ] + if [(p.name, p.kind) for p in present_params] == default_model_signature: + # if this is the standard model signature, use extra_data as the extra args name + var_kw_name = 'extra_data' + else: + # else start from var_kw + var_kw_name = var_kw.name + + # generate a name that's definitely unique + while var_kw_name in fields: + var_kw_name += '_' + merged_params[var_kw_name] = var_kw.replace(name=var_kw_name) + + return Signature(parameters=list(merged_params.values()), return_annotation=None) + + +def get_model(obj: Union[Type['BaseModel'], Type['Dataclass']]) -> Type['BaseModel']: + from pydantic.v1.main import BaseModel + + try: + model_cls = obj.__pydantic_model__ # type: ignore + except AttributeError: + model_cls = obj + + if not issubclass(model_cls, BaseModel): + raise TypeError('Unsupported type, must be either BaseModel or dataclass') + return model_cls + + +def to_camel(string: str) -> str: + return ''.join(word.capitalize() for word in string.split('_')) + + +def to_lower_camel(string: str) -> str: + if len(string) >= 1: + pascal_string = to_camel(string) + return pascal_string[0].lower() + pascal_string[1:] + return string.lower() + + +T = TypeVar('T') + + +def unique_list( + input_list: Union[List[T], Tuple[T, ...]], + *, + name_factory: Callable[[T], str] = str, +) -> List[T]: + """ + Make a list unique while maintaining order. + We update the list if another one with the same name is set + (e.g. root validator overridden in subclass) + """ + result: List[T] = [] + result_names: List[str] = [] + for v in input_list: + v_name = name_factory(v) + if v_name not in result_names: + result_names.append(v_name) + result.append(v) + else: + result[result_names.index(v_name)] = v + + return result + + +class PyObjectStr(str): + """ + String class where repr doesn't include quotes. Useful with Representation when you want to return a string + representation of something that valid (or pseudo-valid) python. + """ + + def __repr__(self) -> str: + return str(self) + + +class Representation: + """ + Mixin to provide __str__, __repr__, and __pretty__ methods. See #884 for more details. + + __pretty__ is used by [devtools](https://python-devtools.helpmanual.io/) to provide human readable representations + of objects. + """ + + __slots__: Tuple[str, ...] = tuple() + + def __repr_args__(self) -> 'ReprArgs': + """ + Returns the attributes to show in __str__, __repr__, and __pretty__ this is generally overridden. + + Can either return: + * name - value pairs, e.g.: `[('foo_name', 'foo'), ('bar_name', ['b', 'a', 'r'])]` + * or, just values, e.g.: `[(None, 'foo'), (None, ['b', 'a', 'r'])]` + """ + attrs = ((s, getattr(self, s)) for s in self.__slots__) + return [(a, v) for a, v in attrs if v is not None] + + def __repr_name__(self) -> str: + """ + Name of the instance's class, used in __repr__. + """ + return self.__class__.__name__ + + def __repr_str__(self, join_str: str) -> str: + return join_str.join(repr(v) if a is None else f'{a}={v!r}' for a, v in self.__repr_args__()) + + def __pretty__(self, fmt: Callable[[Any], Any], **kwargs: Any) -> Generator[Any, None, None]: + """ + Used by devtools (https://python-devtools.helpmanual.io/) to provide a human readable representations of objects + """ + yield self.__repr_name__() + '(' + yield 1 + for name, value in self.__repr_args__(): + if name is not None: + yield name + '=' + yield fmt(value) + yield ',' + yield 0 + yield -1 + yield ')' + + def __str__(self) -> str: + return self.__repr_str__(' ') + + def __repr__(self) -> str: + return f'{self.__repr_name__()}({self.__repr_str__(", ")})' + + def __rich_repr__(self) -> 'RichReprResult': + """Get fields for Rich library""" + for name, field_repr in self.__repr_args__(): + if name is None: + yield field_repr + else: + yield name, field_repr + + +class GetterDict(Representation): + """ + Hack to make object's smell just enough like dicts for validate_model. + + We can't inherit from Mapping[str, Any] because it upsets cython so we have to implement all methods ourselves. + """ + + __slots__ = ('_obj',) + + def __init__(self, obj: Any): + self._obj = obj + + def __getitem__(self, key: str) -> Any: + try: + return getattr(self._obj, key) + except AttributeError as e: + raise KeyError(key) from e + + def get(self, key: Any, default: Any = None) -> Any: + return getattr(self._obj, key, default) + + def extra_keys(self) -> Set[Any]: + """ + We don't want to get any other attributes of obj if the model didn't explicitly ask for them + """ + return set() + + def keys(self) -> List[Any]: + """ + Keys of the pseudo dictionary, uses a list not set so order information can be maintained like python + dictionaries. + """ + return list(self) + + def values(self) -> List[Any]: + return [self[k] for k in self] + + def items(self) -> Iterator[Tuple[str, Any]]: + for k in self: + yield k, self.get(k) + + def __iter__(self) -> Iterator[str]: + for name in dir(self._obj): + if not name.startswith('_'): + yield name + + def __len__(self) -> int: + return sum(1 for _ in self) + + def __contains__(self, item: Any) -> bool: + return item in self.keys() + + def __eq__(self, other: Any) -> bool: + return dict(self) == dict(other.items()) + + def __repr_args__(self) -> 'ReprArgs': + return [(None, dict(self))] + + def __repr_name__(self) -> str: + return f'GetterDict[{display_as_type(self._obj)}]' + + +class ValueItems(Representation): + """ + Class for more convenient calculation of excluded or included fields on values. + """ + + __slots__ = ('_items', '_type') + + def __init__(self, value: Any, items: Union['AbstractSetIntStr', 'MappingIntStrAny']) -> None: + items = self._coerce_items(items) + + if isinstance(value, (list, tuple)): + items = self._normalize_indexes(items, len(value)) + + self._items: 'MappingIntStrAny' = items + + def is_excluded(self, item: Any) -> bool: + """ + Check if item is fully excluded. + + :param item: key or index of a value + """ + return self.is_true(self._items.get(item)) + + def is_included(self, item: Any) -> bool: + """ + Check if value is contained in self._items + + :param item: key or index of value + """ + return item in self._items + + def for_element(self, e: 'IntStr') -> Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']]: + """ + :param e: key or index of element on value + :return: raw values for element if self._items is dict and contain needed element + """ + + item = self._items.get(e) + return item if not self.is_true(item) else None + + def _normalize_indexes(self, items: 'MappingIntStrAny', v_length: int) -> 'DictIntStrAny': + """ + :param items: dict or set of indexes which will be normalized + :param v_length: length of sequence indexes of which will be + + >>> self._normalize_indexes({0: True, -2: True, -1: True}, 4) + {0: True, 2: True, 3: True} + >>> self._normalize_indexes({'__all__': True}, 4) + {0: True, 1: True, 2: True, 3: True} + """ + + normalized_items: 'DictIntStrAny' = {} + all_items = None + for i, v in items.items(): + if not (isinstance(v, Mapping) or isinstance(v, AbstractSet) or self.is_true(v)): + raise TypeError(f'Unexpected type of exclude value for index "{i}" {v.__class__}') + if i == '__all__': + all_items = self._coerce_value(v) + continue + if not isinstance(i, int): + raise TypeError( + 'Excluding fields from a sequence of sub-models or dicts must be performed index-wise: ' + 'expected integer keys or keyword "__all__"' + ) + normalized_i = v_length + i if i < 0 else i + normalized_items[normalized_i] = self.merge(v, normalized_items.get(normalized_i)) + + if not all_items: + return normalized_items + if self.is_true(all_items): + for i in range(v_length): + normalized_items.setdefault(i, ...) + return normalized_items + for i in range(v_length): + normalized_item = normalized_items.setdefault(i, {}) + if not self.is_true(normalized_item): + normalized_items[i] = self.merge(all_items, normalized_item) + return normalized_items + + @classmethod + def merge(cls, base: Any, override: Any, intersect: bool = False) -> Any: + """ + Merge a ``base`` item with an ``override`` item. + + Both ``base`` and ``override`` are converted to dictionaries if possible. + Sets are converted to dictionaries with the sets entries as keys and + Ellipsis as values. + + Each key-value pair existing in ``base`` is merged with ``override``, + while the rest of the key-value pairs are updated recursively with this function. + + Merging takes place based on the "union" of keys if ``intersect`` is + set to ``False`` (default) and on the intersection of keys if + ``intersect`` is set to ``True``. + """ + override = cls._coerce_value(override) + base = cls._coerce_value(base) + if override is None: + return base + if cls.is_true(base) or base is None: + return override + if cls.is_true(override): + return base if intersect else override + + # intersection or union of keys while preserving ordering: + if intersect: + merge_keys = [k for k in base if k in override] + [k for k in override if k in base] + else: + merge_keys = list(base) + [k for k in override if k not in base] + + merged: 'DictIntStrAny' = {} + for k in merge_keys: + merged_item = cls.merge(base.get(k), override.get(k), intersect=intersect) + if merged_item is not None: + merged[k] = merged_item + + return merged + + @staticmethod + def _coerce_items(items: Union['AbstractSetIntStr', 'MappingIntStrAny']) -> 'MappingIntStrAny': + if isinstance(items, Mapping): + pass + elif isinstance(items, AbstractSet): + items = dict.fromkeys(items, ...) + else: + class_name = getattr(items, '__class__', '???') + assert_never( + items, + f'Unexpected type of exclude value {class_name}', + ) + return items + + @classmethod + def _coerce_value(cls, value: Any) -> Any: + if value is None or cls.is_true(value): + return value + return cls._coerce_items(value) + + @staticmethod + def is_true(v: Any) -> bool: + return v is True or v is ... + + def __repr_args__(self) -> 'ReprArgs': + return [(None, self._items)] + + +class ClassAttribute: + """ + Hide class attribute from its instances + """ + + __slots__ = ( + 'name', + 'value', + ) + + def __init__(self, name: str, value: Any) -> None: + self.name = name + self.value = value + + def __get__(self, instance: Any, owner: Type[Any]) -> None: + if instance is None: + return self.value + raise AttributeError(f'{self.name!r} attribute of {owner.__name__!r} is class-only') + + +path_types = { + 'is_dir': 'directory', + 'is_file': 'file', + 'is_mount': 'mount point', + 'is_symlink': 'symlink', + 'is_block_device': 'block device', + 'is_char_device': 'char device', + 'is_fifo': 'FIFO', + 'is_socket': 'socket', +} + + +def path_type(p: 'Path') -> str: + """ + Find out what sort of thing a path is. + """ + assert p.exists(), 'path does not exist' + for method, name in path_types.items(): + if getattr(p, method)(): + return name + + return 'unknown' + + +Obj = TypeVar('Obj') + + +def smart_deepcopy(obj: Obj) -> Obj: + """ + Return type as is for immutable built-in types + Use obj.copy() for built-in empty collections + Use copy.deepcopy() for non-empty collections and unknown objects + """ + + obj_type = obj.__class__ + if obj_type in IMMUTABLE_NON_COLLECTIONS_TYPES: + return obj # fastest case: obj is immutable and not collection therefore will not be copied anyway + try: + if not obj and obj_type in BUILTIN_COLLECTIONS: + # faster way for empty collections, no need to copy its members + return obj if obj_type is tuple else obj.copy() # type: ignore # tuple doesn't have copy method + except (TypeError, ValueError, RuntimeError): + # do we really dare to catch ALL errors? Seems a bit risky + pass + + return deepcopy(obj) # slowest way when we actually might need a deepcopy + + +def is_valid_field(name: str) -> bool: + if not name.startswith('_'): + return True + return ROOT_KEY == name + + +DUNDER_ATTRIBUTES = { + '__annotations__', + '__classcell__', + '__doc__', + '__module__', + '__orig_bases__', + '__orig_class__', + '__qualname__', + '__firstlineno__', + '__static_attributes__', +} + + +def is_valid_private_name(name: str) -> bool: + return not is_valid_field(name) and name not in DUNDER_ATTRIBUTES + + +_EMPTY = object() + + +def all_identical(left: Iterable[Any], right: Iterable[Any]) -> bool: + """ + Check that the items of `left` are the same objects as those in `right`. + + >>> a, b = object(), object() + >>> all_identical([a, b, a], [a, b, a]) + True + >>> all_identical([a, b, [a]], [a, b, [a]]) # new list object, while "equal" is not "identical" + False + """ + for left_item, right_item in zip_longest(left, right, fillvalue=_EMPTY): + if left_item is not right_item: + return False + return True + + +def assert_never(obj: NoReturn, msg: str) -> NoReturn: + """ + Helper to make sure that we have covered all possible types. + + This is mostly useful for ``mypy``, docs: + https://mypy.readthedocs.io/en/latest/literal_types.html#exhaustive-checks + """ + raise TypeError(msg) + + +def get_unique_discriminator_alias(all_aliases: Collection[str], discriminator_key: str) -> str: + """Validate that all aliases are the same and if that's the case return the alias""" + unique_aliases = set(all_aliases) + if len(unique_aliases) > 1: + raise ConfigError( + f'Aliases for discriminator {discriminator_key!r} must be the same (got {", ".join(sorted(all_aliases))})' + ) + return unique_aliases.pop() + + +def get_discriminator_alias_and_values(tp: Any, discriminator_key: str) -> Tuple[str, Tuple[str, ...]]: + """ + Get alias and all valid values in the `Literal` type of the discriminator field + `tp` can be a `BaseModel` class or directly an `Annotated` `Union` of many. + """ + is_root_model = getattr(tp, '__custom_root_type__', False) + + if get_origin(tp) is Annotated: + tp = get_args(tp)[0] + + if hasattr(tp, '__pydantic_model__'): + tp = tp.__pydantic_model__ + + if is_union(get_origin(tp)): + alias, all_values = _get_union_alias_and_all_values(tp, discriminator_key) + return alias, tuple(v for values in all_values for v in values) + elif is_root_model: + union_type = tp.__fields__[ROOT_KEY].type_ + alias, all_values = _get_union_alias_and_all_values(union_type, discriminator_key) + + if len(set(all_values)) > 1: + raise ConfigError( + f'Field {discriminator_key!r} is not the same for all submodels of {display_as_type(tp)!r}' + ) + + return alias, all_values[0] + + else: + try: + t_discriminator_type = tp.__fields__[discriminator_key].type_ + except AttributeError as e: + raise TypeError(f'Type {tp.__name__!r} is not a valid `BaseModel` or `dataclass`') from e + except KeyError as e: + raise ConfigError(f'Model {tp.__name__!r} needs a discriminator field for key {discriminator_key!r}') from e + + if not is_literal_type(t_discriminator_type): + raise ConfigError(f'Field {discriminator_key!r} of model {tp.__name__!r} needs to be a `Literal`') + + return tp.__fields__[discriminator_key].alias, all_literal_values(t_discriminator_type) + + +def _get_union_alias_and_all_values( + union_type: Type[Any], discriminator_key: str +) -> Tuple[str, Tuple[Tuple[str, ...], ...]]: + zipped_aliases_values = [get_discriminator_alias_and_values(t, discriminator_key) for t in get_args(union_type)] + # unzip: [('alias_a',('v1', 'v2)), ('alias_b', ('v3',))] => [('alias_a', 'alias_b'), (('v1', 'v2'), ('v3',))] + all_aliases, all_values = zip(*zipped_aliases_values) + return get_unique_discriminator_alias(all_aliases, discriminator_key), all_values diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/validators.py b/backend/.venv/Lib/site-packages/pydantic/v1/validators.py new file mode 100644 index 0000000..c0940e8 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/validators.py @@ -0,0 +1,768 @@ +import math +import re +from collections import OrderedDict, deque +from collections.abc import Hashable as CollectionsHashable +from datetime import date, datetime, time, timedelta +from decimal import Decimal, DecimalException +from enum import Enum, IntEnum +from ipaddress import IPv4Address, IPv4Interface, IPv4Network, IPv6Address, IPv6Interface, IPv6Network +from pathlib import Path +from typing import ( + TYPE_CHECKING, + Any, + Callable, + Deque, + Dict, + ForwardRef, + FrozenSet, + Generator, + Hashable, + List, + NamedTuple, + Pattern, + Set, + Tuple, + Type, + TypeVar, + Union, +) +from uuid import UUID +from warnings import warn + +from pydantic.v1 import errors +from pydantic.v1.datetime_parse import parse_date, parse_datetime, parse_duration, parse_time +from pydantic.v1.typing import ( + AnyCallable, + all_literal_values, + display_as_type, + get_class, + is_callable_type, + is_literal_type, + is_namedtuple, + is_none_type, + is_typeddict, +) +from pydantic.v1.utils import almost_equal_floats, lenient_issubclass, sequence_like + +if TYPE_CHECKING: + from typing_extensions import Literal, TypedDict + + from pydantic.v1.config import BaseConfig + from pydantic.v1.fields import ModelField + from pydantic.v1.types import ConstrainedDecimal, ConstrainedFloat, ConstrainedInt + + ConstrainedNumber = Union[ConstrainedDecimal, ConstrainedFloat, ConstrainedInt] + AnyOrderedDict = OrderedDict[Any, Any] + Number = Union[int, float, Decimal] + StrBytes = Union[str, bytes] + + +def str_validator(v: Any) -> Union[str]: + if isinstance(v, str): + if isinstance(v, Enum): + return v.value + else: + return v + elif isinstance(v, (float, int, Decimal)): + # is there anything else we want to add here? If you think so, create an issue. + return str(v) + elif isinstance(v, (bytes, bytearray)): + return v.decode() + else: + raise errors.StrError() + + +def strict_str_validator(v: Any) -> Union[str]: + if isinstance(v, str) and not isinstance(v, Enum): + return v + raise errors.StrError() + + +def bytes_validator(v: Any) -> Union[bytes]: + if isinstance(v, bytes): + return v + elif isinstance(v, bytearray): + return bytes(v) + elif isinstance(v, str): + return v.encode() + elif isinstance(v, (float, int, Decimal)): + return str(v).encode() + else: + raise errors.BytesError() + + +def strict_bytes_validator(v: Any) -> Union[bytes]: + if isinstance(v, bytes): + return v + elif isinstance(v, bytearray): + return bytes(v) + else: + raise errors.BytesError() + + +BOOL_FALSE = {0, '0', 'off', 'f', 'false', 'n', 'no'} +BOOL_TRUE = {1, '1', 'on', 't', 'true', 'y', 'yes'} + + +def bool_validator(v: Any) -> bool: + if v is True or v is False: + return v + if isinstance(v, bytes): + v = v.decode() + if isinstance(v, str): + v = v.lower() + try: + if v in BOOL_TRUE: + return True + if v in BOOL_FALSE: + return False + except TypeError: + raise errors.BoolError() + raise errors.BoolError() + + +# matches the default limit cpython, see https://github.com/python/cpython/pull/96500 +max_str_int = 4_300 + + +def int_validator(v: Any) -> int: + if isinstance(v, int) and not (v is True or v is False): + return v + + # see https://github.com/pydantic/pydantic/issues/1477 and in turn, https://github.com/python/cpython/issues/95778 + # this check should be unnecessary once patch releases are out for 3.7, 3.8, 3.9 and 3.10 + # but better to check here until then. + # NOTICE: this does not fully protect user from the DOS risk since the standard library JSON implementation + # (and other std lib modules like xml) use `int()` and are likely called before this, the best workaround is to + # 1. update to the latest patch release of python once released, 2. use a different JSON library like ujson + if isinstance(v, (str, bytes, bytearray)) and len(v) > max_str_int: + raise errors.IntegerError() + + try: + return int(v) + except (TypeError, ValueError, OverflowError): + raise errors.IntegerError() + + +def strict_int_validator(v: Any) -> int: + if isinstance(v, int) and not (v is True or v is False): + return v + raise errors.IntegerError() + + +def float_validator(v: Any) -> float: + if isinstance(v, float): + return v + + try: + return float(v) + except (TypeError, ValueError): + raise errors.FloatError() + + +def strict_float_validator(v: Any) -> float: + if isinstance(v, float): + return v + raise errors.FloatError() + + +def float_finite_validator(v: 'Number', field: 'ModelField', config: 'BaseConfig') -> 'Number': + allow_inf_nan = getattr(field.type_, 'allow_inf_nan', None) + if allow_inf_nan is None: + allow_inf_nan = config.allow_inf_nan + + if allow_inf_nan is False and (math.isnan(v) or math.isinf(v)): + raise errors.NumberNotFiniteError() + return v + + +def number_multiple_validator(v: 'Number', field: 'ModelField') -> 'Number': + field_type: ConstrainedNumber = field.type_ + if field_type.multiple_of is not None: + mod = float(v) / float(field_type.multiple_of) % 1 + if not almost_equal_floats(mod, 0.0) and not almost_equal_floats(mod, 1.0): + raise errors.NumberNotMultipleError(multiple_of=field_type.multiple_of) + return v + + +def number_size_validator(v: 'Number', field: 'ModelField') -> 'Number': + field_type: ConstrainedNumber = field.type_ + if field_type.gt is not None and not v > field_type.gt: + raise errors.NumberNotGtError(limit_value=field_type.gt) + elif field_type.ge is not None and not v >= field_type.ge: + raise errors.NumberNotGeError(limit_value=field_type.ge) + + if field_type.lt is not None and not v < field_type.lt: + raise errors.NumberNotLtError(limit_value=field_type.lt) + if field_type.le is not None and not v <= field_type.le: + raise errors.NumberNotLeError(limit_value=field_type.le) + + return v + + +def constant_validator(v: 'Any', field: 'ModelField') -> 'Any': + """Validate ``const`` fields. + + The value provided for a ``const`` field must be equal to the default value + of the field. This is to support the keyword of the same name in JSON + Schema. + """ + if v != field.default: + raise errors.WrongConstantError(given=v, permitted=[field.default]) + + return v + + +def anystr_length_validator(v: 'StrBytes', config: 'BaseConfig') -> 'StrBytes': + v_len = len(v) + + min_length = config.min_anystr_length + if v_len < min_length: + raise errors.AnyStrMinLengthError(limit_value=min_length) + + max_length = config.max_anystr_length + if max_length is not None and v_len > max_length: + raise errors.AnyStrMaxLengthError(limit_value=max_length) + + return v + + +def anystr_strip_whitespace(v: 'StrBytes') -> 'StrBytes': + return v.strip() + + +def anystr_upper(v: 'StrBytes') -> 'StrBytes': + return v.upper() + + +def anystr_lower(v: 'StrBytes') -> 'StrBytes': + return v.lower() + + +def ordered_dict_validator(v: Any) -> 'AnyOrderedDict': + if isinstance(v, OrderedDict): + return v + + try: + return OrderedDict(v) + except (TypeError, ValueError): + raise errors.DictError() + + +def dict_validator(v: Any) -> Dict[Any, Any]: + if isinstance(v, dict): + return v + + try: + return dict(v) + except (TypeError, ValueError): + raise errors.DictError() + + +def list_validator(v: Any) -> List[Any]: + if isinstance(v, list): + return v + elif sequence_like(v): + return list(v) + else: + raise errors.ListError() + + +def tuple_validator(v: Any) -> Tuple[Any, ...]: + if isinstance(v, tuple): + return v + elif sequence_like(v): + return tuple(v) + else: + raise errors.TupleError() + + +def set_validator(v: Any) -> Set[Any]: + if isinstance(v, set): + return v + elif sequence_like(v): + return set(v) + else: + raise errors.SetError() + + +def frozenset_validator(v: Any) -> FrozenSet[Any]: + if isinstance(v, frozenset): + return v + elif sequence_like(v): + return frozenset(v) + else: + raise errors.FrozenSetError() + + +def deque_validator(v: Any) -> Deque[Any]: + if isinstance(v, deque): + return v + elif sequence_like(v): + return deque(v) + else: + raise errors.DequeError() + + +def enum_member_validator(v: Any, field: 'ModelField', config: 'BaseConfig') -> Enum: + try: + enum_v = field.type_(v) + except ValueError: + # field.type_ should be an enum, so will be iterable + raise errors.EnumMemberError(enum_values=list(field.type_)) + return enum_v.value if config.use_enum_values else enum_v + + +def uuid_validator(v: Any, field: 'ModelField') -> UUID: + try: + if isinstance(v, str): + v = UUID(v) + elif isinstance(v, (bytes, bytearray)): + try: + v = UUID(v.decode()) + except ValueError: + # 16 bytes in big-endian order as the bytes argument fail + # the above check + v = UUID(bytes=v) + except ValueError: + raise errors.UUIDError() + + if not isinstance(v, UUID): + raise errors.UUIDError() + + required_version = getattr(field.type_, '_required_version', None) + if required_version and v.version != required_version: + raise errors.UUIDVersionError(required_version=required_version) + + return v + + +def decimal_validator(v: Any) -> Decimal: + if isinstance(v, Decimal): + return v + elif isinstance(v, (bytes, bytearray)): + v = v.decode() + + v = str(v).strip() + + try: + v = Decimal(v) + except DecimalException: + raise errors.DecimalError() + + if not v.is_finite(): + raise errors.DecimalIsNotFiniteError() + + return v + + +def hashable_validator(v: Any) -> Hashable: + if isinstance(v, Hashable): + return v + + raise errors.HashableError() + + +def ip_v4_address_validator(v: Any) -> IPv4Address: + if isinstance(v, IPv4Address): + return v + + try: + return IPv4Address(v) + except ValueError: + raise errors.IPv4AddressError() + + +def ip_v6_address_validator(v: Any) -> IPv6Address: + if isinstance(v, IPv6Address): + return v + + try: + return IPv6Address(v) + except ValueError: + raise errors.IPv6AddressError() + + +def ip_v4_network_validator(v: Any) -> IPv4Network: + """ + Assume IPv4Network initialised with a default ``strict`` argument + + See more: + https://docs.python.org/library/ipaddress.html#ipaddress.IPv4Network + """ + if isinstance(v, IPv4Network): + return v + + try: + return IPv4Network(v) + except ValueError: + raise errors.IPv4NetworkError() + + +def ip_v6_network_validator(v: Any) -> IPv6Network: + """ + Assume IPv6Network initialised with a default ``strict`` argument + + See more: + https://docs.python.org/library/ipaddress.html#ipaddress.IPv6Network + """ + if isinstance(v, IPv6Network): + return v + + try: + return IPv6Network(v) + except ValueError: + raise errors.IPv6NetworkError() + + +def ip_v4_interface_validator(v: Any) -> IPv4Interface: + if isinstance(v, IPv4Interface): + return v + + try: + return IPv4Interface(v) + except ValueError: + raise errors.IPv4InterfaceError() + + +def ip_v6_interface_validator(v: Any) -> IPv6Interface: + if isinstance(v, IPv6Interface): + return v + + try: + return IPv6Interface(v) + except ValueError: + raise errors.IPv6InterfaceError() + + +def path_validator(v: Any) -> Path: + if isinstance(v, Path): + return v + + try: + return Path(v) + except TypeError: + raise errors.PathError() + + +def path_exists_validator(v: Any) -> Path: + if not v.exists(): + raise errors.PathNotExistsError(path=v) + + return v + + +def callable_validator(v: Any) -> AnyCallable: + """ + Perform a simple check if the value is callable. + + Note: complete matching of argument type hints and return types is not performed + """ + if callable(v): + return v + + raise errors.CallableError(value=v) + + +def enum_validator(v: Any) -> Enum: + if isinstance(v, Enum): + return v + + raise errors.EnumError(value=v) + + +def int_enum_validator(v: Any) -> IntEnum: + if isinstance(v, IntEnum): + return v + + raise errors.IntEnumError(value=v) + + +def make_literal_validator(type_: Any) -> Callable[[Any], Any]: + permitted_choices = all_literal_values(type_) + + # To have a O(1) complexity and still return one of the values set inside the `Literal`, + # we create a dict with the set values (a set causes some problems with the way intersection works). + # In some cases the set value and checked value can indeed be different (see `test_literal_validator_str_enum`) + allowed_choices = {v: v for v in permitted_choices} + + def literal_validator(v: Any) -> Any: + try: + return allowed_choices[v] + except (KeyError, TypeError): + raise errors.WrongConstantError(given=v, permitted=permitted_choices) + + return literal_validator + + +def constr_length_validator(v: 'StrBytes', field: 'ModelField', config: 'BaseConfig') -> 'StrBytes': + v_len = len(v) + + min_length = field.type_.min_length if field.type_.min_length is not None else config.min_anystr_length + if v_len < min_length: + raise errors.AnyStrMinLengthError(limit_value=min_length) + + max_length = field.type_.max_length if field.type_.max_length is not None else config.max_anystr_length + if max_length is not None and v_len > max_length: + raise errors.AnyStrMaxLengthError(limit_value=max_length) + + return v + + +def constr_strip_whitespace(v: 'StrBytes', field: 'ModelField', config: 'BaseConfig') -> 'StrBytes': + strip_whitespace = field.type_.strip_whitespace or config.anystr_strip_whitespace + if strip_whitespace: + v = v.strip() + + return v + + +def constr_upper(v: 'StrBytes', field: 'ModelField', config: 'BaseConfig') -> 'StrBytes': + upper = field.type_.to_upper or config.anystr_upper + if upper: + v = v.upper() + + return v + + +def constr_lower(v: 'StrBytes', field: 'ModelField', config: 'BaseConfig') -> 'StrBytes': + lower = field.type_.to_lower or config.anystr_lower + if lower: + v = v.lower() + return v + + +def validate_json(v: Any, config: 'BaseConfig') -> Any: + if v is None: + # pass None through to other validators + return v + try: + return config.json_loads(v) # type: ignore + except ValueError: + raise errors.JsonError() + except TypeError: + raise errors.JsonTypeError() + + +T = TypeVar('T') + + +def make_arbitrary_type_validator(type_: Type[T]) -> Callable[[T], T]: + def arbitrary_type_validator(v: Any) -> T: + if isinstance(v, type_): + return v + raise errors.ArbitraryTypeError(expected_arbitrary_type=type_) + + return arbitrary_type_validator + + +def make_class_validator(type_: Type[T]) -> Callable[[Any], Type[T]]: + def class_validator(v: Any) -> Type[T]: + if lenient_issubclass(v, type_): + return v + raise errors.SubclassError(expected_class=type_) + + return class_validator + + +def any_class_validator(v: Any) -> Type[T]: + if isinstance(v, type): + return v + raise errors.ClassError() + + +def none_validator(v: Any) -> 'Literal[None]': + if v is None: + return v + raise errors.NotNoneError() + + +def pattern_validator(v: Any) -> Pattern[str]: + if isinstance(v, Pattern): + return v + + str_value = str_validator(v) + + try: + return re.compile(str_value) + except re.error: + raise errors.PatternError() + + +NamedTupleT = TypeVar('NamedTupleT', bound=NamedTuple) + + +def make_namedtuple_validator( + namedtuple_cls: Type[NamedTupleT], config: Type['BaseConfig'] +) -> Callable[[Tuple[Any, ...]], NamedTupleT]: + from pydantic.v1.annotated_types import create_model_from_namedtuple + + NamedTupleModel = create_model_from_namedtuple( + namedtuple_cls, + __config__=config, + __module__=namedtuple_cls.__module__, + ) + namedtuple_cls.__pydantic_model__ = NamedTupleModel # type: ignore[attr-defined] + + def namedtuple_validator(values: Tuple[Any, ...]) -> NamedTupleT: + annotations = NamedTupleModel.__annotations__ + + if len(values) > len(annotations): + raise errors.ListMaxLengthError(limit_value=len(annotations)) + + dict_values: Dict[str, Any] = dict(zip(annotations, values)) + validated_dict_values: Dict[str, Any] = dict(NamedTupleModel(**dict_values)) + return namedtuple_cls(**validated_dict_values) + + return namedtuple_validator + + +def make_typeddict_validator( + typeddict_cls: Type['TypedDict'], config: Type['BaseConfig'] # type: ignore[valid-type] +) -> Callable[[Any], Dict[str, Any]]: + from pydantic.v1.annotated_types import create_model_from_typeddict + + TypedDictModel = create_model_from_typeddict( + typeddict_cls, + __config__=config, + __module__=typeddict_cls.__module__, + ) + typeddict_cls.__pydantic_model__ = TypedDictModel # type: ignore[attr-defined] + + def typeddict_validator(values: 'TypedDict') -> Dict[str, Any]: # type: ignore[valid-type] + return TypedDictModel.parse_obj(values).dict(exclude_unset=True) + + return typeddict_validator + + +class IfConfig: + def __init__(self, validator: AnyCallable, *config_attr_names: str, ignored_value: Any = False) -> None: + self.validator = validator + self.config_attr_names = config_attr_names + self.ignored_value = ignored_value + + def check(self, config: Type['BaseConfig']) -> bool: + return any(getattr(config, name) not in {None, self.ignored_value} for name in self.config_attr_names) + + +# order is important here, for example: bool is a subclass of int so has to come first, datetime before date same, +# IPv4Interface before IPv4Address, etc +_VALIDATORS: List[Tuple[Type[Any], List[Any]]] = [ + (IntEnum, [int_validator, enum_member_validator]), + (Enum, [enum_member_validator]), + ( + str, + [ + str_validator, + IfConfig(anystr_strip_whitespace, 'anystr_strip_whitespace'), + IfConfig(anystr_upper, 'anystr_upper'), + IfConfig(anystr_lower, 'anystr_lower'), + IfConfig(anystr_length_validator, 'min_anystr_length', 'max_anystr_length'), + ], + ), + ( + bytes, + [ + bytes_validator, + IfConfig(anystr_strip_whitespace, 'anystr_strip_whitespace'), + IfConfig(anystr_upper, 'anystr_upper'), + IfConfig(anystr_lower, 'anystr_lower'), + IfConfig(anystr_length_validator, 'min_anystr_length', 'max_anystr_length'), + ], + ), + (bool, [bool_validator]), + (int, [int_validator]), + (float, [float_validator, IfConfig(float_finite_validator, 'allow_inf_nan', ignored_value=True)]), + (Path, [path_validator]), + (datetime, [parse_datetime]), + (date, [parse_date]), + (time, [parse_time]), + (timedelta, [parse_duration]), + (OrderedDict, [ordered_dict_validator]), + (dict, [dict_validator]), + (list, [list_validator]), + (tuple, [tuple_validator]), + (set, [set_validator]), + (frozenset, [frozenset_validator]), + (deque, [deque_validator]), + (UUID, [uuid_validator]), + (Decimal, [decimal_validator]), + (IPv4Interface, [ip_v4_interface_validator]), + (IPv6Interface, [ip_v6_interface_validator]), + (IPv4Address, [ip_v4_address_validator]), + (IPv6Address, [ip_v6_address_validator]), + (IPv4Network, [ip_v4_network_validator]), + (IPv6Network, [ip_v6_network_validator]), +] + + +def find_validators( # noqa: C901 (ignore complexity) + type_: Type[Any], config: Type['BaseConfig'] +) -> Generator[AnyCallable, None, None]: + from pydantic.v1.dataclasses import is_builtin_dataclass, make_dataclass_validator + + if type_ is Any or type_ is object: + return + type_type = type_.__class__ + if type_type == ForwardRef or type_type == TypeVar: + return + + if is_none_type(type_): + yield none_validator + return + if type_ is Pattern or type_ is re.Pattern: + yield pattern_validator + return + if type_ is Hashable or type_ is CollectionsHashable: + yield hashable_validator + return + if is_callable_type(type_): + yield callable_validator + return + if is_literal_type(type_): + yield make_literal_validator(type_) + return + if is_builtin_dataclass(type_): + yield from make_dataclass_validator(type_, config) + return + if type_ is Enum: + yield enum_validator + return + if type_ is IntEnum: + yield int_enum_validator + return + if is_namedtuple(type_): + yield tuple_validator + yield make_namedtuple_validator(type_, config) + return + if is_typeddict(type_): + yield make_typeddict_validator(type_, config) + return + + class_ = get_class(type_) + if class_ is not None: + if class_ is not Any and isinstance(class_, type): + yield make_class_validator(class_) + else: + yield any_class_validator + return + + for val_type, validators in _VALIDATORS: + try: + if issubclass(type_, val_type): + for v in validators: + if isinstance(v, IfConfig): + if v.check(config): + yield v.validator + else: + yield v + return + except TypeError: + raise RuntimeError(f'error checking inheritance of {type_!r} (type: {display_as_type(type_)})') + + if config.arbitrary_types_allowed: + yield make_arbitrary_type_validator(type_) + else: + if hasattr(type_, '__pydantic_core_schema__'): + warn(f'Mixing V1 and V2 models is not supported. `{type_.__name__}` is a V2 model.', UserWarning) + raise RuntimeError(f'no validator found for {type_}, see `arbitrary_types_allowed` in Config') diff --git a/backend/.venv/Lib/site-packages/pydantic/v1/version.py b/backend/.venv/Lib/site-packages/pydantic/v1/version.py new file mode 100644 index 0000000..c77cde1 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/v1/version.py @@ -0,0 +1,38 @@ +__all__ = 'compiled', 'VERSION', 'version_info' + +VERSION = '1.10.21' + +try: + import cython # type: ignore +except ImportError: + compiled: bool = False +else: # pragma: no cover + try: + compiled = cython.compiled + except AttributeError: + compiled = False + + +def version_info() -> str: + import platform + import sys + from importlib import import_module + from pathlib import Path + + optional_deps = [] + for p in ('devtools', 'dotenv', 'email-validator', 'typing-extensions'): + try: + import_module(p.replace('-', '_')) + except ImportError: + continue + optional_deps.append(p) + + info = { + 'pydantic version': VERSION, + 'pydantic compiled': compiled, + 'install path': Path(__file__).resolve().parent, + 'python version': sys.version, + 'platform': platform.platform(), + 'optional deps. installed': optional_deps, + } + return '\n'.join('{:>30} {}'.format(k + ':', str(v).replace('\n', ' ')) for k, v in info.items()) diff --git a/backend/.venv/Lib/site-packages/pydantic/validate_call_decorator.py b/backend/.venv/Lib/site-packages/pydantic/validate_call_decorator.py new file mode 100644 index 0000000..fe4d9c9 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/validate_call_decorator.py @@ -0,0 +1,116 @@ +"""Decorator for validating function calls.""" + +from __future__ import annotations as _annotations + +import inspect +from functools import partial +from types import BuiltinFunctionType +from typing import TYPE_CHECKING, Any, Callable, TypeVar, cast, overload + +from ._internal import _generate_schema, _typing_extra, _validate_call +from .errors import PydanticUserError + +__all__ = ('validate_call',) + +if TYPE_CHECKING: + from .config import ConfigDict + + AnyCallableT = TypeVar('AnyCallableT', bound=Callable[..., Any]) + + +_INVALID_TYPE_ERROR_CODE = 'validate-call-type' + + +def _check_function_type(function: object) -> None: + """Check if the input function is a supported type for `validate_call`.""" + if isinstance(function, _generate_schema.VALIDATE_CALL_SUPPORTED_TYPES): + try: + inspect.signature(cast(_generate_schema.ValidateCallSupportedTypes, function)) + except ValueError: + raise PydanticUserError( + f"Input function `{function}` doesn't have a valid signature", code=_INVALID_TYPE_ERROR_CODE + ) + + if isinstance(function, partial): + try: + assert not isinstance(partial.func, partial), 'Partial of partial' + _check_function_type(function.func) + except PydanticUserError as e: + raise PydanticUserError( + f'Partial of `{function.func}` is invalid because the type of `{function.func}` is not supported by `validate_call`', + code=_INVALID_TYPE_ERROR_CODE, + ) from e + + return + + if isinstance(function, BuiltinFunctionType): + raise PydanticUserError(f'Input built-in function `{function}` is not supported', code=_INVALID_TYPE_ERROR_CODE) + if isinstance(function, (classmethod, staticmethod, property)): + name = type(function).__name__ + raise PydanticUserError( + f'The `@{name}` decorator should be applied after `@validate_call` (put `@{name}` on top)', + code=_INVALID_TYPE_ERROR_CODE, + ) + + if inspect.isclass(function): + raise PydanticUserError( + f'Unable to validate {function}: `validate_call` should be applied to functions, not classes (put `@validate_call` on top of `__init__` or `__new__` instead)', + code=_INVALID_TYPE_ERROR_CODE, + ) + if callable(function): + raise PydanticUserError( + f'Unable to validate {function}: `validate_call` should be applied to functions, not instances or other callables. Use `validate_call` explicitly on `__call__` instead.', + code=_INVALID_TYPE_ERROR_CODE, + ) + + raise PydanticUserError( + f'Unable to validate {function}: `validate_call` should be applied to one of the following: function, method, partial, or lambda', + code=_INVALID_TYPE_ERROR_CODE, + ) + + +@overload +def validate_call( + *, config: ConfigDict | None = None, validate_return: bool = False +) -> Callable[[AnyCallableT], AnyCallableT]: ... + + +@overload +def validate_call(func: AnyCallableT, /) -> AnyCallableT: ... + + +def validate_call( + func: AnyCallableT | None = None, + /, + *, + config: ConfigDict | None = None, + validate_return: bool = False, +) -> AnyCallableT | Callable[[AnyCallableT], AnyCallableT]: + """!!! abstract "Usage Documentation" + [Validation Decorator](../concepts/validation_decorator.md) + + Returns a decorated wrapper around the function that validates the arguments and, optionally, the return value. + + Usage may be either as a plain decorator `@validate_call` or with arguments `@validate_call(...)`. + + Args: + func: The function to be decorated. + config: The configuration dictionary. + validate_return: Whether to validate the return value. + + Returns: + The decorated function. + """ + parent_namespace = _typing_extra.parent_frame_namespace() + + def validate(function: AnyCallableT) -> AnyCallableT: + _check_function_type(function) + validate_call_wrapper = _validate_call.ValidateCallWrapper( + cast(_generate_schema.ValidateCallSupportedTypes, function), config, validate_return, parent_namespace + ) + return _validate_call.update_wrapper_attributes(function, validate_call_wrapper.__call__) # type: ignore + + if func is not None: + return validate(func) + else: + return validate diff --git a/backend/.venv/Lib/site-packages/pydantic/validators.py b/backend/.venv/Lib/site-packages/pydantic/validators.py new file mode 100644 index 0000000..7921b04 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/validators.py @@ -0,0 +1,5 @@ +"""The `validators` module is a backport module from V1.""" + +from ._migration import getattr_migration + +__getattr__ = getattr_migration(__name__) diff --git a/backend/.venv/Lib/site-packages/pydantic/version.py b/backend/.venv/Lib/site-packages/pydantic/version.py new file mode 100644 index 0000000..eaf2619 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/version.py @@ -0,0 +1,113 @@ +"""The `version` module holds the version information for Pydantic.""" + +from __future__ import annotations as _annotations + +import sys + +from pydantic_core import __version__ as __pydantic_core_version__ + +__all__ = 'VERSION', 'version_info' + +VERSION = '2.12.5' +"""The version of Pydantic. + +This version specifier is guaranteed to be compliant with the [specification], +introduced by [PEP 440]. + +[specification]: https://packaging.python.org/en/latest/specifications/version-specifiers/ +[PEP 440]: https://peps.python.org/pep-0440/ +""" + +# Keep this in sync with the version constraint in the `pyproject.toml` dependencies: +_COMPATIBLE_PYDANTIC_CORE_VERSION = '2.41.5' + + +def version_short() -> str: + """Return the `major.minor` part of Pydantic version. + + It returns '2.1' if Pydantic version is '2.1.1'. + """ + return '.'.join(VERSION.split('.')[:2]) + + +def version_info() -> str: + """Return complete version information for Pydantic and its dependencies.""" + import importlib.metadata + import platform + from pathlib import Path + + import pydantic_core._pydantic_core as pdc + + from ._internal import _git as git + + # get data about packages that are closely related to pydantic, use pydantic or often conflict with pydantic + package_names = { + 'email-validator', + 'fastapi', + 'mypy', + 'pydantic-extra-types', + 'pydantic-settings', + 'pyright', + 'typing_extensions', + } + related_packages = [] + + for dist in importlib.metadata.distributions(): + name = dist.metadata['Name'] + if name in package_names: + related_packages.append(f'{name}-{dist.version}') + + pydantic_dir = Path(__file__).parents[1].resolve() + most_recent_commit = ( + git.git_revision(pydantic_dir) if git.is_git_repo(pydantic_dir) and git.have_git() else 'unknown' + ) + + info = { + 'pydantic version': VERSION, + 'pydantic-core version': __pydantic_core_version__, + 'pydantic-core build': getattr(pdc, 'build_info', None) or pdc.build_profile, # pyright: ignore[reportPrivateImportUsage] + 'python version': sys.version, + 'platform': platform.platform(), + 'related packages': ' '.join(related_packages), + 'commit': most_recent_commit, + } + return '\n'.join('{:>30} {}'.format(k + ':', str(v).replace('\n', ' ')) for k, v in info.items()) + + +def check_pydantic_core_version() -> bool: + """Check that the installed `pydantic-core` dependency is compatible.""" + return __pydantic_core_version__ == _COMPATIBLE_PYDANTIC_CORE_VERSION + + +def _ensure_pydantic_core_version() -> None: # pragma: no cover + if not check_pydantic_core_version(): + raise_error = True + # Do not raise the error if pydantic is installed in editable mode (i.e. in development): + if sys.version_info >= (3, 13): # origin property added in 3.13 + from importlib.metadata import distribution + + dist = distribution('pydantic') + if getattr(getattr(dist.origin, 'dir_info', None), 'editable', False): + raise_error = False + + if raise_error: + raise SystemError( + f'The installed pydantic-core version ({__pydantic_core_version__}) is incompatible ' + f'with the current pydantic version, which requires {_COMPATIBLE_PYDANTIC_CORE_VERSION}. ' + "If you encounter this error, make sure that you haven't upgraded pydantic-core manually." + ) + + +def parse_mypy_version(version: str) -> tuple[int, int, int]: + """Parse `mypy` string version to a 3-tuple of ints. + + It parses normal version like `1.11.0` and extra info followed by a `+` sign + like `1.11.0+dev.d6d9d8cd4f27c52edac1f537e236ec48a01e54cb.dirty`. + + Args: + version: The mypy version string. + + Returns: + A triple of ints, e.g. `(1, 11, 0)`. + """ + return tuple(map(int, version.partition('+')[0].split('.'))) # pyright: ignore[reportReturnType] diff --git a/backend/.venv/Lib/site-packages/pydantic/warnings.py b/backend/.venv/Lib/site-packages/pydantic/warnings.py new file mode 100644 index 0000000..2e2dd83 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic/warnings.py @@ -0,0 +1,122 @@ +"""Pydantic-specific warnings.""" + +from __future__ import annotations as _annotations + +from .version import version_short + +__all__ = ( + 'PydanticDeprecatedSince20', + 'PydanticDeprecatedSince26', + 'PydanticDeprecatedSince29', + 'PydanticDeprecatedSince210', + 'PydanticDeprecatedSince211', + 'PydanticDeprecatedSince212', + 'PydanticDeprecationWarning', + 'PydanticExperimentalWarning', + 'ArbitraryTypeWarning', + 'UnsupportedFieldAttributeWarning', + 'TypedDictExtraConfigWarning', +) + + +class PydanticDeprecationWarning(DeprecationWarning): + """A Pydantic specific deprecation warning. + + This warning is raised when using deprecated functionality in Pydantic. It provides information on when the + deprecation was introduced and the expected version in which the corresponding functionality will be removed. + + Attributes: + message: Description of the warning. + since: Pydantic version in what the deprecation was introduced. + expected_removal: Pydantic version in what the corresponding functionality expected to be removed. + """ + + message: str + since: tuple[int, int] + expected_removal: tuple[int, int] + + def __init__( + self, message: str, *args: object, since: tuple[int, int], expected_removal: tuple[int, int] | None = None + ) -> None: + super().__init__(message, *args) + self.message = message.rstrip('.') + self.since = since + self.expected_removal = expected_removal if expected_removal is not None else (since[0] + 1, 0) + + def __str__(self) -> str: + message = ( + f'{self.message}. Deprecated in Pydantic V{self.since[0]}.{self.since[1]}' + f' to be removed in V{self.expected_removal[0]}.{self.expected_removal[1]}.' + ) + if self.since == (2, 0): + message += f' See Pydantic V2 Migration Guide at https://errors.pydantic.dev/{version_short()}/migration/' + return message + + +class PydanticDeprecatedSince20(PydanticDeprecationWarning): + """A specific `PydanticDeprecationWarning` subclass defining functionality deprecated since Pydantic 2.0.""" + + def __init__(self, message: str, *args: object) -> None: + super().__init__(message, *args, since=(2, 0), expected_removal=(3, 0)) + + +class PydanticDeprecatedSince26(PydanticDeprecationWarning): + """A specific `PydanticDeprecationWarning` subclass defining functionality deprecated since Pydantic 2.6.""" + + def __init__(self, message: str, *args: object) -> None: + super().__init__(message, *args, since=(2, 6), expected_removal=(3, 0)) + + +class PydanticDeprecatedSince29(PydanticDeprecationWarning): + """A specific `PydanticDeprecationWarning` subclass defining functionality deprecated since Pydantic 2.9.""" + + def __init__(self, message: str, *args: object) -> None: + super().__init__(message, *args, since=(2, 9), expected_removal=(3, 0)) + + +class PydanticDeprecatedSince210(PydanticDeprecationWarning): + """A specific `PydanticDeprecationWarning` subclass defining functionality deprecated since Pydantic 2.10.""" + + def __init__(self, message: str, *args: object) -> None: + super().__init__(message, *args, since=(2, 10), expected_removal=(3, 0)) + + +class PydanticDeprecatedSince211(PydanticDeprecationWarning): + """A specific `PydanticDeprecationWarning` subclass defining functionality deprecated since Pydantic 2.11.""" + + def __init__(self, message: str, *args: object) -> None: + super().__init__(message, *args, since=(2, 11), expected_removal=(3, 0)) + + +class PydanticDeprecatedSince212(PydanticDeprecationWarning): + """A specific `PydanticDeprecationWarning` subclass defining functionality deprecated since Pydantic 2.12.""" + + def __init__(self, message: str, *args: object) -> None: + super().__init__(message, *args, since=(2, 12), expected_removal=(3, 0)) + + +class GenericBeforeBaseModelWarning(Warning): + pass + + +class PydanticExperimentalWarning(Warning): + """A Pydantic specific experimental functionality warning. + + It is raised to warn users that the functionality may change or be removed in future versions of Pydantic. + """ + + +class CoreSchemaGenerationWarning(UserWarning): + """A warning raised during core schema generation.""" + + +class ArbitraryTypeWarning(CoreSchemaGenerationWarning): + """A warning raised when Pydantic fails to generate a core schema for an arbitrary type.""" + + +class UnsupportedFieldAttributeWarning(CoreSchemaGenerationWarning): + """A warning raised when a `Field()` attribute isn't supported in the context it is used.""" + + +class TypedDictExtraConfigWarning(CoreSchemaGenerationWarning): + """A warning raised when the [`extra`][pydantic.ConfigDict.extra] configuration is incompatible with the `closed` or `extra_items` specification.""" diff --git a/backend/.venv/Lib/site-packages/pydantic_core-2.41.5.dist-info/INSTALLER b/backend/.venv/Lib/site-packages/pydantic_core-2.41.5.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic_core-2.41.5.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/backend/.venv/Lib/site-packages/pydantic_core-2.41.5.dist-info/METADATA b/backend/.venv/Lib/site-packages/pydantic_core-2.41.5.dist-info/METADATA new file mode 100644 index 0000000..468d2a5 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic_core-2.41.5.dist-info/METADATA @@ -0,0 +1,180 @@ +Metadata-Version: 2.4 +Name: pydantic_core +Version: 2.41.5 +Classifier: Development Status :: 3 - Alpha +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +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 :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Programming Language :: Python :: Implementation :: GraalPy +Classifier: Programming Language :: Rust +Classifier: Framework :: Pydantic +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: Information Technology +Classifier: Operating System :: POSIX :: Linux +Classifier: Operating System :: Microsoft :: Windows +Classifier: Operating System :: MacOS +Classifier: Typing :: Typed +Requires-Dist: typing-extensions>=4.14.1 +License-File: LICENSE +Summary: Core functionality for Pydantic validation and serialization +Home-Page: https://github.com/pydantic/pydantic-core +Author-email: Samuel Colvin , Adrian Garcia Badaracco <1755071+adriangb@users.noreply.github.com>, David Montague , David Hewitt , Sydney Runkle , Victorien Plot +License-Expression: MIT +Requires-Python: >=3.9 +Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM +Project-URL: Homepage, https://github.com/pydantic/pydantic-core +Project-URL: Funding, https://github.com/sponsors/samuelcolvin +Project-URL: Source, https://github.com/pydantic/pydantic-core + +# pydantic-core + +[![CI](https://github.com/pydantic/pydantic-core/workflows/ci/badge.svg?event=push)](https://github.com/pydantic/pydantic-core/actions?query=event%3Apush+branch%3Amain+workflow%3Aci) +[![Coverage](https://codecov.io/gh/pydantic/pydantic-core/branch/main/graph/badge.svg)](https://codecov.io/gh/pydantic/pydantic-core) +[![pypi](https://img.shields.io/pypi/v/pydantic-core.svg)](https://pypi.python.org/pypi/pydantic-core) +[![versions](https://img.shields.io/pypi/pyversions/pydantic-core.svg)](https://github.com/pydantic/pydantic-core) +[![license](https://img.shields.io/github/license/pydantic/pydantic-core.svg)](https://github.com/pydantic/pydantic-core/blob/main/LICENSE) + +This package provides the core functionality for [pydantic](https://docs.pydantic.dev) validation and serialization. + +Pydantic-core is currently around 17x faster than pydantic V1. +See [`tests/benchmarks/`](./tests/benchmarks/) for details. + +## Example of direct usage + +_NOTE: You should not need to use pydantic-core directly; instead, use pydantic, which in turn uses pydantic-core._ + +```py +from pydantic_core import SchemaValidator, ValidationError + + +v = SchemaValidator( + { + 'type': 'typed-dict', + 'fields': { + 'name': { + 'type': 'typed-dict-field', + 'schema': { + 'type': 'str', + }, + }, + 'age': { + 'type': 'typed-dict-field', + 'schema': { + 'type': 'int', + 'ge': 18, + }, + }, + 'is_developer': { + 'type': 'typed-dict-field', + 'schema': { + 'type': 'default', + 'schema': {'type': 'bool'}, + 'default': True, + }, + }, + }, + } +) + +r1 = v.validate_python({'name': 'Samuel', 'age': 35}) +assert r1 == {'name': 'Samuel', 'age': 35, 'is_developer': True} + +# pydantic-core can also validate JSON directly +r2 = v.validate_json('{"name": "Samuel", "age": 35}') +assert r1 == r2 + +try: + v.validate_python({'name': 'Samuel', 'age': 11}) +except ValidationError as e: + print(e) + """ + 1 validation error for model + age + Input should be greater than or equal to 18 + [type=greater_than_equal, context={ge: 18}, input_value=11, input_type=int] + """ +``` + +## Getting Started + +### Prerequisites + +You'll need: +1. **[Rust](https://rustup.rs/)** - Rust stable (or nightly for coverage) +2. **[uv](https://docs.astral.sh/uv/getting-started/installation/)** - Fast Python package manager (will install Python 3.9+ automatically) +3. **[git](https://git-scm.com/)** - For version control +4. **[make](https://www.gnu.org/software/make/)** - For running development commands (or use `nmake` on Windows) + +### Quick Start + +```bash +# Clone the repository (or from your fork) +git clone git@github.com:pydantic/pydantic-core.git +cd pydantic-core + +# Install all dependencies using uv, setup pre-commit hooks, and build the development version +make install +``` + +Verify your installation by running: + +```bash +make +``` + +This runs a full development cycle: formatting, building, linting, and testing + +### Development Commands + +Run `make help` to see all available commands, or use these common ones: + +```bash +make build-dev # to build the package during development +make build-prod # to perform an optimised build for benchmarking +make test # to run the tests +make testcov # to run the tests and generate a coverage report +make lint # to run the linter +make format # to format python and rust code +make all # to run to run build-dev + format + lint + test +``` + +### Useful Resources + +* [`python/pydantic_core/_pydantic_core.pyi`](./python/pydantic_core/_pydantic_core.pyi) - Python API types +* [`python/pydantic_core/core_schema.py`](./python/pydantic_core/core_schema.py) - Core schema definitions +* [`tests/`](./tests) - Comprehensive usage examples + +## Profiling + +It's possible to profile the code using the [`flamegraph` utility from `flamegraph-rs`](https://github.com/flamegraph-rs/flamegraph). (Tested on Linux.) You can install this with `cargo install flamegraph`. + +Run `make build-profiling` to install a release build with debugging symbols included (needed for profiling). + +Once that is built, you can profile pytest benchmarks with (e.g.): + +```bash +flamegraph -- pytest tests/benchmarks/test_micro_benchmarks.py -k test_list_of_ints_core_py --benchmark-enable +``` +The `flamegraph` command will produce an interactive SVG at `flamegraph.svg`. + +## Releasing + +1. Bump package version locally. Do not just edit `Cargo.toml` on Github, you need both `Cargo.toml` and `Cargo.lock` to be updated. +2. Make a PR for the version bump and merge it. +3. Go to https://github.com/pydantic/pydantic-core/releases and click "Draft a new release" +4. In the "Choose a tag" dropdown enter the new tag `v` and select "Create new tag on publish" when the option appears. +5. Enter the release title in the form "v " +6. Click Generate release notes button +7. Click Publish release +8. Go to https://github.com/pydantic/pydantic-core/actions and ensure that all build for release are done successfully. +9. Go to https://pypi.org/project/pydantic-core/ and ensure that the latest release is published. +10. Done 🎉 + diff --git a/backend/.venv/Lib/site-packages/pydantic_core-2.41.5.dist-info/RECORD b/backend/.venv/Lib/site-packages/pydantic_core-2.41.5.dist-info/RECORD new file mode 100644 index 0000000..a90617a --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic_core-2.41.5.dist-info/RECORD @@ -0,0 +1,12 @@ +pydantic_core-2.41.5.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pydantic_core-2.41.5.dist-info/METADATA,sha256=Ex83HNMObeb0Be1hbVnx5CewzvIq2S18OeUn7UwBhKk,7420 +pydantic_core-2.41.5.dist-info/RECORD,, +pydantic_core-2.41.5.dist-info/WHEEL,sha256=n8ZdhGDUio-M1d1jdBhS3kD6MKEN1SRxo8BOjWwZdsg,96 +pydantic_core-2.41.5.dist-info/licenses/LICENSE,sha256=--f2FfGNE1wHAA5ahjJdsn9Cx3KWme8WasH3o_RYa_Q,1101 +pydantic_core/__init__.py,sha256=5kQVCp6sQ3LE_4Jsj2FN8oilYeOSUOlsWORH8XgGxr8,5286 +pydantic_core/__pycache__/__init__.cpython-312.pyc,, +pydantic_core/__pycache__/core_schema.cpython-312.pyc,, +pydantic_core/_pydantic_core.cp312-win_amd64.pyd,sha256=8RVtUmeKamoYJxhbwNSE-4sjYG8FOnIc7zbGLJm522s,5436928 +pydantic_core/_pydantic_core.pyi,sha256=9MaxWCkerllI7ar2Spz_0LSGSZJcmcGqC02rU-9Mdl4,45973 +pydantic_core/core_schema.py,sha256=k4n4J4QNy8uFumsUTXwzR5KbPh7EyLzWGX0x7pRdzxk,159165 +pydantic_core/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/backend/.venv/Lib/site-packages/pydantic_core-2.41.5.dist-info/WHEEL b/backend/.venv/Lib/site-packages/pydantic_core-2.41.5.dist-info/WHEEL new file mode 100644 index 0000000..956a98b --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic_core-2.41.5.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: maturin (1.9.6) +Root-Is-Purelib: false +Tag: cp312-cp312-win_amd64 diff --git a/backend/.venv/Lib/site-packages/pydantic_core-2.41.5.dist-info/licenses/LICENSE b/backend/.venv/Lib/site-packages/pydantic_core-2.41.5.dist-info/licenses/LICENSE new file mode 100644 index 0000000..0716871 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic_core-2.41.5.dist-info/licenses/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2022 Samuel Colvin + +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/pydantic_core/__init__.py b/backend/.venv/Lib/site-packages/pydantic_core/__init__.py new file mode 100644 index 0000000..d5facd1 --- /dev/null +++ b/backend/.venv/Lib/site-packages/pydantic_core/__init__.py @@ -0,0 +1,171 @@ +from __future__ import annotations + +import sys as _sys +from typing import Any as _Any + +from typing_extensions import Sentinel + +from ._pydantic_core import ( + ArgsKwargs, + MultiHostUrl, + PydanticCustomError, + PydanticKnownError, + PydanticOmit, + PydanticSerializationError, + PydanticSerializationUnexpectedValue, + PydanticUndefined, + PydanticUndefinedType, + PydanticUseDefault, + SchemaError, + SchemaSerializer, + SchemaValidator, + Some, + TzInfo, + Url, + ValidationError, + __version__, + from_json, + to_json, + to_jsonable_python, +) +from .core_schema import CoreConfig, CoreSchema, CoreSchemaType, ErrorType + +if _sys.version_info < (3, 11): + from typing_extensions import NotRequired as _NotRequired +else: + from typing import NotRequired as _NotRequired + +if _sys.version_info < (3, 12): + from typing_extensions import TypedDict as _TypedDict +else: + from typing import TypedDict as _TypedDict + +__all__ = [ + '__version__', + 'UNSET', + 'CoreConfig', + 'CoreSchema', + 'CoreSchemaType', + 'SchemaValidator', + 'SchemaSerializer', + 'Some', + 'Url', + 'MultiHostUrl', + 'ArgsKwargs', + 'PydanticUndefined', + 'PydanticUndefinedType', + 'SchemaError', + 'ErrorDetails', + 'InitErrorDetails', + 'ValidationError', + 'PydanticCustomError', + 'PydanticKnownError', + 'PydanticOmit', + 'PydanticUseDefault', + 'PydanticSerializationError', + 'PydanticSerializationUnexpectedValue', + 'TzInfo', + 'to_json', + 'from_json', + 'to_jsonable_python', +] + + +class ErrorDetails(_TypedDict): + type: str + """ + The type of error that occurred, this is an identifier designed for + programmatic use that will change rarely or never. + + `type` is unique for each error message, and can hence be used as an identifier to build custom error messages. + """ + loc: tuple[int | str, ...] + """Tuple of strings and ints identifying where in the schema the error occurred.""" + msg: str + """A human readable error message.""" + input: _Any + """The input data at this `loc` that caused the error.""" + ctx: _NotRequired[dict[str, _Any]] + """ + Values which are required to render the error message, and could hence be useful in rendering custom error messages. + Also useful for passing custom error data forward. + """ + url: _NotRequired[str] + """ + The documentation URL giving information about the error. No URL is available if + a [`PydanticCustomError`][pydantic_core.PydanticCustomError] is used. + """ + + +class InitErrorDetails(_TypedDict): + type: str | PydanticCustomError + """The type of error that occurred, this should be a "slug" identifier that changes rarely or never.""" + loc: _NotRequired[tuple[int | str, ...]] + """Tuple of strings and ints identifying where in the schema the error occurred.""" + input: _Any + """The input data at this `loc` that caused the error.""" + ctx: _NotRequired[dict[str, _Any]] + """ + Values which are required to render the error message, and could hence be useful in rendering custom error messages. + Also useful for passing custom error data forward. + """ + + +class ErrorTypeInfo(_TypedDict): + """ + Gives information about errors. + """ + + type: ErrorType + """The type of error that occurred, this should be a "slug" identifier that changes rarely or never.""" + message_template_python: str + """String template to render a human readable error message from using context, when the input is Python.""" + example_message_python: str + """Example of a human readable error message, when the input is Python.""" + message_template_json: _NotRequired[str] + """String template to render a human readable error message from using context, when the input is JSON data.""" + example_message_json: _NotRequired[str] + """Example of a human readable error message, when the input is JSON data.""" + example_context: dict[str, _Any] | None + """Example of context values.""" + + +class MultiHostHost(_TypedDict): + """ + A host part of a multi-host URL. + """ + + username: str | None + """The username part of this host, or `None`.""" + password: str | None + """The password part of this host, or `None`.""" + host: str | None + """The host part of this host, or `None`.""" + port: int | None + """The port part of this host, or `None`.""" + + +MISSING = Sentinel('MISSING') +"""A singleton indicating a field value was not provided during validation. + +This singleton can be used a default value, as an alternative to `None` when it has +an explicit meaning. During serialization, any field with `MISSING` as a value is excluded +from the output. + +Example: + ```python + from pydantic import BaseModel + + from pydantic_core import MISSING + + + class Configuration(BaseModel): + timeout: int | None | MISSING = MISSING + + + # configuration defaults, stored somewhere else: + defaults = {'timeout': 200} + + conf = Configuration.model_validate({...}) + timeout = conf.timeout if timeout.timeout is not MISSING else defaults['timeout'] +""" diff --git a/backend/.venv/Lib/site-packages/pydantic_core/__pycache__/__init__.cpython-312.pyc b/backend/.venv/Lib/site-packages/pydantic_core/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..68b25addc97e3a05561fdb028d491f93fcc9f2b5 GIT binary patch literal 3149 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⋘>yHGEM~@rr4J(K25c?M17{L#h`I~8Smt{ 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 qSJU%bzP_UIGf&g#+?uBDxualQZQ^3LaRop^1z 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

    l+fruX#O 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�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 qx=AREBHUYN60uK9*x)5n=X&#;oHrl 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 z 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%0DuweAksm#g+^X`wML| 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%0D0SVR~iSP6as8p8VRa+!CN@d#9fFhDvPROU%? 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 z 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�Q{1|9uo+DBDNXWE5CZl%45pQ1CJAv)7; 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

    !pnfi#b)SVl0Qm~>~tYi_10VuMB^2% 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

    iOMD%M>NN;7wnF2Bq&nT%T>2l-( z;}fvz?*kGYI&IMX2+~^oN{4+RD_g~^hMyP>$Vv6%=q-bA(&F?|aus45nC~JrItRxRU8ds-uWl^|MTyqSV&_-(yFt$9dl{I`{u_JBc6GK1m&z zJVQo~2jHcC+W=7xLzk0gGOSvQX_dW}lZi|w-(@2I{vnv?9!8{Q9tq)Qk;Dm}Q&k-O zyh&A*7~wcNrK7!1Ipo7|$%i8|@}aeMb6)M9bmR)|qChLL8kCO10|@4hXcBXG01|T- zBqU;y#QMeXTwsm^nAG>Yd`Vd(4oF?-wFi}gISCwZfU*ErkTq4B&OT0X|8+naX#vgn z?5CE~AbD{6&PraqNIKQjk+F%RTx_mJihMX!Qp7k}x0tVkk`W_Cp5*c)4sPz+oIDCL z?Q8EDB7zVlPCm#t;>1yjBu8a$lG@hmN()y)Q1~IPZZi|+kZ`` z$w^_HVWIf!6`Xi}Q#AquIc7u;_l&eTYYq9&7C%{vQq)rYaDFI$UAKG>+bJ3A+|?P1 zM?2)yyelL);;!1tZH%;3{tRw%O;DP^>dzsMbF{FKy8pQhSCEoZlj`6OMi1kuIE3rOSSy#Ium7f(d^hpGs1QpX!+crV z_a6rTp5kyE@R_BK;?Li1mk{LSHEGc@$#8PyS0+9K{lT=K_U%_Q@;-oxC23##douU; z%iQnXN?-nSfWBketF76e7numuEx=aO9iQ1_;#}6IeLwN~!RjEd9o=MrkJWTG&g3{s zpB^*s-NB(BH2M!LcJHCar`$u4(X`YV*wBSOYM_Cxih4n_@!kG(FpovL`P6#r*`LyW zyUN&aA3*5P3sZzMv6ubUVPC(ke`)O6Y=3rawi&{g>mveDp3OEAz{SvX%Hk6ZE#-af z-_XLZQ2zi;IJTC|Dy!j724>IRGUBhdt+fJCDqHL0p&45X@s2fb|MSm?_nj;lfi|1v z*2|=%sY95QYSsQZ9N#s%+$I;Q$zRbV0&`7a#_ak(^EE%YK>}0Aor0O;$bJEvW7J6t zL0;RxB3(qbX(=Pesp$!7AjfXgjWoUEX|ulCL)dQ*zLTA%wC|R;vt*Scah>~^DmTE= zgJiB1RbFTkL%cX8er9KN?W*+Tk!NlWC%%ziZT*O}3!Twz{`!rPQ%OX4<9TGHa8x7A zXH&Fp)JPm$KU%eb6p*WnLX}%0$E4m0kY-SM3~}v8&JEU$gZvUzMUieyoI!&mh1j4w zq>a-JV(qV-_ObE7a|@KW7WCJwd{+}L3&n3J#xe_)@4ksdZ=@&9tYUU2xE+AaK{6lh zwZHZU3@wCsAbw>r*^su9Txh_2^2_ZG?0$g^N#m3l(Ga-(=5U+2+!4xuJ=przK$Q)Z zV<@-u1oA&hQD#S=9nxe(X|(+RoV2|AllBN{n{)a5J0yQlRS2&t3@f4n3N{?+Plrpr!s}vcNg23Hi#c%e`^PheK6&ssX+iD>8<)rh9BT`GZ|S> z8M;}mv@TV{NoZ%)wFx{GR%XVmYOrp*OXp6TY2SY(aaJl}nzRF};Z;g!w1OvxqZKGk z4OliF2*)*G)ysXGLG~aQ*>93p#JcNq298b1U$YL|2IaHruRqeL$>@d?OEmq-yQvMb zoEBvj{gbB-X0{J?F(arAW@b8=(WbIJ-x6k!+8$=Mm<^&m_J48|5cSQmy3h@U8IyHO zm~m1Cx|kuw;O|6&D!f!*GHJK|0wN3@8_bY)>o(iPjNBns!+%lQ#mruNS+PvaP=0ri zH166SPrl6LjD0cr2mVwy8`BySn<{z9apI$KvJ#?N3AP1aAthJ1Poa-Bx4DJRviIsTa@=0B^1UB&QF zr&bTtnLov{oJigx9{k*W&|??#z@S$P2&P_5x7lyJuXp1!Y25SfWgR~UIUgi{5Aa>o zyNP2AeElhFpT>VwWt6ond>_zS&fuHh><>Qpe=mDcxwmuov_nckh^2^hBW~pKVuFjf zAI7?~O{+x9<#;VgQi*Xl=0=hwy-?el4h=8pKx-#2Z!3Eh(Igifqs+2mVRJj#MeMQn z{IB+dKJ+Xx67Otf+pZ@RpMynoTQRw;_u0QVTqYl(OgG|W=B}rs>By>APJkd=%87!P z%)-cryx+Czwg65rpIpDB-)eoG+*@0#m**S836d?z#LiULK7q11qKL&EEJDIQG5?L^ z15{I@L~+EQ>U;dEA`-Nb+BiP6T@`}Ehps_pNOC_xN-Ih3cOvtU50Oflk{$;%Me9b4 zljMG4!893<7#dNGimf=pyd|&8u#u45A{ad9>}Uxlw1~v5q(~0MzXfa$ zJrRr*>?1{L5ZK7xYIZ>J?w|t=&`zftFOabaSTcVxEfGNhOYF8ckH%^tt#9G9i8_BQ zi|G*AjpNj{KSvc#&z?{PKpFp7u6=RsEYxn?%Is~qj?W*z;S!iJ0cO7b>FBGsJa>E$ z;rKPoW4Jp=V%$({HQA_cyxmNSgaQeb*9GGv))%CM$6oR@v(E=}2zkL)o{7Fuk1O%M zcC)Ur{|6BcuKIR4$yxEvy*i@g-rq5PzM))1T93|^Q>h*+^wD&>bKHH-`1)2$PScFi3q9*K>2mPS(q-v!eBS(BcXZ{ON?m zo%@;|7_0k4iL8uVoqrf|^+~lRYx_i5+YrzZir{lozxL+GY2T5wo#E#2w=J(`t?MV` zvoGH}pY*j(<_(5x#*`@h&h+7V&PAAZ6{q7Fu5p}t7C7M=GQvk?jBsDZ2tN#`i;0EF z^6-4*nA7gCQ$IRPBXenR`bh`+TYJ$H{OVx)CY1(9o@G3cVI9a>Vg3g{pY8J39n{QW zfh)TV|3A>A&Q*u;=Q;^*duN8n-s?f;8hTi3&($<3rMbB)M9#i^XJJ-oi{Jd~6A!LN z1=X0$Dw1Q52ISZadT^SRbQEBk@j8AzZ>O@1oZre@1iE$;`38VSS)dE|Jd$nk5T#F<73P5ZXew!sMEmSCr}@6TI#z{bw$u9)3vZy$`9tvjz^ z{z+-yGK#wtMuoI*A*GG~#-YmdJV{DUYrOI1-wD05z2sz(KU{RAEb=DP%Vm@{TQ@K^ z<$##PZ!-`5*i*MT_SEF~nVV%KO*!_=&MC1oJ9BL+<#oU58yHqF)`MG1ojs7~Ct6Ee zC}kI(kg=9zsr??!L(lOIeZ-%YCqe=CSjzO3pS}GGL_~(-+=w$D{?>(Wwc5Iubb1{D ztBO3c0b;e*T6NmlKnip^C2&f2OlX|G-&&;mUqU!Zxq%M%T$gpnBDCnqiE+kDD$Tf? zS;oxxla%WfBxTe;Vu;(VyME3if9$DDgz>;D#k62IXugicAtUZb`L13)$EfG6;n;2y z!Aay^k9}-`o%Y9Gg?D!OmHS4nM`CqJ7HHMa12Ru|Bd%JjcQG%o67=@a2J#`w4>~n| z$w0!XHp!>@I&`~fJC4<MfYcLz%CJk4af(L$Iq~Jv*{4E z?IWKjFfd-Tf`!wMvRhAQrt_4=(;I^FsI4X-!L5y6R zHwx@foZ|Kw1MPHmY%{t^IJPZW06tAW+XBQK-s_BBqqFL@e?v;y_gQXS!;}e#zF5)B z^>^u|J5OofcVEsfIkTgB&P#*PI-H>B3c65~g&8vu6RtGaYhPV}G>~JPTZfXmj1fT8 zb?S#1`2~aLMucyPoXjl^ne~;rP{T79+@yW)&>N0YZ_%fHe}Bm@9@c_9SolDR*0Sx{qtH3H?+jG>I~J7jtt()y>>dyI ziX3AcgT&mV8Js&*%$s#v`js60@#h2e{ds8mT}IRYz1OI`%f$82s-epR%!q^LPZ#H( zm-c-try;;Qg@&5^`}^~P=13&hUs)l&d<@E@*}?Gy!S~HY0%t26LyAcnO}ofyP~eg$ z_y3l^(ionV8zSM_)lz|rd3Q0{L|4z>o|>yYLRd}@ODN&{8IvlpW|!>W%u3T`C$#JM zXLKV9OUbzh4cGaPgXdI4kEPPB4kf4&yX)g@J?kN&a)fIW-Mr8#YSBY5sl9Mc2$Ek{Va8yeD$aW%h$SLHh<>rG(OTbzJ_tCI3|$l7rJ zsxSpf!4>_P*u6ZNz3kUTZ!e|CoQQ~0*cwrCGgv2Bt2+2^6ewKQim6Gcuy)?-UlXA5 z$xPrpY`4znajYNL7qu>O4AIj^C<<^$kI`UK)=#xzUB51Rjagh{*Vz;IzKpYpCOeR& z<_0HLVn%%@(6PAimh@rT87{%)RYq@l>{AKYUSf-4mzZLM#8wsZMfupoveZUrV?6o| z+>o#IJgx}{Sj~F^b-Tw~4Fg!1PVhC_x4DpI+j_PkOkOM3P52NaPbC!V7^piZpPTBn zOCQ@I_xz)jHTP@>5=56d^?%1RK`_X>MoGXVCretXVxk6Rn6n}+_H7gl#j%8EQd-v< z*r&ayLPrJSQy`dI2rFJt!l-WB&)~}k2HGz$TfxZ5$d_4}3{FXIeUm8Hm#+}KcFaf`1PQb75@;N!IWE`3E85{&0k1tF_zdEQ;7yYXZC8F$W zoEMB;3fSQ##ya7y`p#+&j%?`C)ez@}V{`P5xt-qPzIm88FhEEmtXD0HgMoXju&}M59B{i^j;7yOXx?$32 zGpUo6e15WE3B|a_@B3(u*Mg!jLGK3WyRq5mnc*wuSxl7@xcJ0FVqgWR`CH20qGYQ) zY)-Tm*J1e8M_y_bj)C<14!#fR7`Tc_u|Gb_b-@`*x1aiGAC5Qv^|5abke}XuXEqS| zKN)_O^?Yd)zv^mA459+wD-czj_6_IVffk>2LapFGh<@Ppx5U|BU7Gg2uO2di*v%XJ zZ}XGdb7t~)UR%yg&g-|aL;52<_?!V>meU>sF73BHha>mlZ}K?j@V8>a->@=b>vXRt zONv`L9x9M#O$PC1z8L@A^G*yXDifDOi z>h*ji3MFBM!TgVcbxhz>#GvF=+^ z)xq{vD#sm8`c2a$g5QcZJ$2xS&G-b{g5|4%BcJEe=KQI#5oRyYT-360f2i`sXh(22 zx2!x17g@XDIH1rCV#KAqP=F_O1W~*4q~hw@6y45xv2jv0J3Od+YHTR1?RqiCWmDs$ zdEJW5wLMs8=Ua7(a0s1qT}Sk|Hov8Kl@Ge5vG1_QeXyBBPq$%SUDuH+(6R26>64osJ*>j<`jg(Ogh_DKcS9mNNur?-MufJ?4o(cZ{Y?KCTGGK4Pjl^m3$6V zL2G6#oGLUqYF7wGV_D(o^X|XX{R-AyI!l=Rx!xN^6=&UH7&y+B3|Bebs-b7t&P1T& zt-B=y@x!n$E5nn^(X>e=ftVGD-30%hRE##DrQJ&#K>BovPRj{M)a4Sd%DX)>{?vQq$d6zgLxb*oFl1?04DGNu5JO1w0+Q(SAk0PbJ&xex4O& z8ezwCjou7b8yOCC7Cl;re+vF9iJjxZ?f@6rx%&B2{fUS}$(ywA9yRi~JGTaL%g)%16PgN!`xAl7{IONlwNH+zuI)LD zaMxA*x6W^!zji|7(BbA%;*RKZ?iF+Ll5(gP<1h6~qaZusfVaGlLXrEgkGxZM=d8SI zs09`gHCzAOo3cWB@MNob0)|Lk_jn`6UKz&eemt%24(np^kagOQ;EC&lL)yl+?6iu9 zg{U#dI(@Cq{p1C?o|hkmKcHm5nz(lCMsbawwOEa1h1#bYz-Qwsdsb_wV-+0FZvp~m zAl`IdbgtS!r|WXgx7rn}rA1$d8|b=ebBJ*4nnQ?V6*r5Gx9+?MdB(HCagNHSSJ`uS z3E!|JYjy6sXw9%JJ63RVdy`pHv3y43G^8ykh4CSqubW0lfj#mtF}L;=dIm%lp#+L+ z0vABsUy5^fK?qLjy76yINIvHzI9mKO%&t>ZpLaO+pxAc1#LOj);2hqb?2#iA&e!aR}q?9Y!}GH zcDi0Bl!37&&MsmN1D%bXQ&VNmVWkA4!;oQr%hwu+mjN88F7q!jsFvFjMjH=T1S^RZ z*^tNGyUs=12!=OZ=prX_GY|WNQ{oc_qu*=~?0$brjIY7ibH=5)O=%L|F*;IsOyp8W za9H)jMZv~d%LP+w7T_Z!?qicdeY9nA;!M+g+Bd-i(}XYJnmTg_ z^k9F1Ri{95W_6w*OBJX{D8`oR2Z{wiSbTI;pl%aPsOQL=m~cC|`>jBX+h=O#hR&&( zfjfW@J?eC{`EOGo^$fIwId4Hm|MM#3+WPLmM8R2!g4*ixC&2HliH)aK1k->~GZ(*T z>Q~(U6^gx;ol9^%4?#61`KS>#H3n)NgGSg)Y9EyMxG`;9V3D~=x&Dz8flT~o;6$!3 zT^AW~fWS3}J3^IR2&gXOuEZ0dqje>{I(e-Py9&|<+S26zAlMZn;?OMqPaw#$_=mls zk9tHIN}PM~n@G0A>=~>#^v5Njw9S8ehS-9cb!A`llp(n;XlEXs+58>jl3;~Mulg}} zmCeGXMC?+-6j0K2Y$zc-*UD9{Ikw)JQLNE?Yirzv_Dw4|EO@{ z#{Bt@@opaNSMe9#><=)&3bBXerC`r$(2h5+cswSMICtS28bQqrnbj9)V?cc~;j@|W z*)yUR;~_rA9Ghs~+Ix--5EC2EEDfgDKoiXIuG9)zp37pux>Z66{|p`VHOmR}G8!O0 z2sCDqdesw>ON-WsRrk_g41`8qp`EFdc0un#%`+$`NvU!ap^X&(2{vArb_u_mH^lIkpVnVcTXVb9ADr7IwJ-JRZ}+NyYk!Pv zhSSrmv~RURoVV+o=(i^%Sug$MzD8PSnkze-PW{OFYF0Mj*>XqYwvi|HLRb~YL7(`el>O|Ha-xWgj;@+@uXpd zz0dwlDDl-zU0N-n%GWuo7#ZKVA(S|co0^XuyNld2gKsK__1jU*4M}$U;TPco2+#8y zN4d$A6Ty7$w`mjK9(T*`ihRMeaJcK{i)LCl(`y0IQIta6 z)3&x$8^b%eI$CS4ckF_@*!S8s$$e?$n9cYk&$3Ow|` zKUBqJ+RkL6i0^96CDWFc{>a8rOETxxXL)-F=Da%mvq^U$UWB2{?Z^oZT;MVMi@AyM zrXrI_fDAA5abmV|X(@;4*iIb7MjQ~cvF>jgKCx-k0Dt4iiH#!$=rBXN6+W+tL4Z}xQF)J;FxwW#|)yHK)^@Vh~~i6%>MEF%-lyX&_pX4}f?y2&&doq9^bQ9 zJA|gGaxFK#sf7ja!E_l`_$q>BRz4f_ef~L--?IXD4UcuyDN30+F#8+Bn7!y%T%@iJ z5hgGu*e-%(1r%ONbLM(YtkF}>P*fE+y)sWFY+MH7=WYX&x)nWsISUg#jXJEDQ`^oj z&R>>)=ftvc>F6Nb>t*Q|x&!GW*h;|>v*3AFH@9_jGxwTQqv8vodb@dlAA87w7v<(6 z_V71G2ajz@Y9R#T80A&@6Pk*!xi%2^u<+(kJXq|HZK`ff6;6te`kCK)VAK4oi7+oF zcUNpD8|IarRo4COk;>|(lKK}H9#hr0KbYSg%75N^=%d(2)T*YI^}t69HUzmJuzchE ziENJ-hhlgOSp~6;DJ#&fOM6+V)zaxCR;EEZt3jMwiqO4_!B&Z|mA`f+rb}LGGY{HN z5XwTI5T^dBl!3cH?u`I<{2{{mHRJ;BRbCaeCU$Uf`w-{yROx{p`g6@q+Ow0*z zBjW_?p<;jH^2e*|Uf)_>xB4)D;`|OSqdD7eU9h^ku7{|>A9L#9NrL2B{Y4w1XHcFp z7g7E-%C9=CI&l%@_ncjAT|fpN>!#uIHL)*H-O^Psp=i~ze75vbA7ugX;*ly$@Dur$ z7`hVyRnCUQ*(Q@2)a^$P=K@VF*5PKi8tiVVPG4G5-xArX%{X$*c-iN2hiCHD^gT}- zFT7{Pv3aut@e!Y&A-anftP0c_&r{xQCxeiNmW6D7uLbG|cHf$LO1a?vP5yDiHUN1h zUYPpZv3bzMWr0K#?z_YO3Zz_j9(#XgyF4E5Z1Q(C`ggPUieC=qe9jF;(P2n4JCFzz z*$tG2Z`)?nv2iS8!sBl!X_~&<{`rqyNT(X(g-xb|$giOHZ}Jt(iheM#{JR32g2ZUW zF9)p^o`S7qcnNF%QVQZ+dk+)jule?}iw5O6TXDoWG~xU+b@Hkk1FHAh0ELU0k55wsc#|d^i2|*gS0}7C!b612$)}qSc6vgl{HqCNvdZ#vkOFUs0ND;lfB7 zt6?caMA&jM6@HZhEF7egy>qHo%8t}Be%qf9nIC87r~aDLx#(Ykbn)SVb`T*h7Ihfyf-kig@zFwhDubIB{v%)5Yqj6$Iv9Vk?r5f#0)llc_U_U5@+%b2pOP4b zJAm6!CvCyAs?*8$F~EWbHb!{98uw2pZ0|6F;zKx$cXtL(T+5Q){rbFVK^z|DUv0R2 z6DNOeI!`{h3F1>QB91g?IFEajxn=j>w3yF0m-#64^Z1+DssRn2wG!HKL>H6^8>^dRmFgmB%(#7qwLn$+H(v z-|Ucy$8;Qg4`G$T{WTgb=}~hO6(Sx6WfB=;O#E1_2;d_kOiC$4ulUrPVykTvg# znx!u1eE_-1;H`S&@{89jYnr(tPp2iE`{EN7NRlkUWwYQP}%X|ye-Bywp{XRG9 zmdbR`9A=%lI$n6x0UgF0XHlCt-2v8}TloevsP4Az86y@^*V-M3UuKj>9uI+5kXMes zr=D)lz!DlqgnLRp46hQZY5p@P)V`yqAO|kR_Y|rR4!{)qZ zyzXBPOOK&EM?J;ulB;p*&_GY)%x?SF7aB>{G?UjgJxP*Md9UEjhkb zL(8x}^aPQN4uFe7tjk(RQ3=WUzDFVZ*T!q_=<|*g1x9C|RDM0}uD~yW!v6i!nz~c| ztf`BLcgVb)x!Ufc(Nwp#qxI>fFJmDjKa9TsF)48PhGNAM z#%^HYI@7}U68ky5=S;)o_|UT)iHbhFmPw2j+Sfd}ja{ZTbdKFo$?nJrY2W>SH^iWr zpYCio9JIdVZ;nynnI@8;O}d`e-;t%@N&B)CT=!!`!7rixIuv}&UhU@ej+gSZ4#%Fs zerlS|c_Co#-+qBvx!R`9c~-|o;c6NEp8pkhi&uC@5p^D9*o^PZFmpku3-Hfee;#NeD% zir1!l*Q8>Wk7ME!v#aVXXGKoh-+*UmRTzJHoYBSnZ?J{dZ7bEh{X^yo-UpM8`|&f| zyjM+Z)yQC^-{riH7gikrce>HAaHWG0zlaQH+MpvidVE@`-TAVja>CuB7(mg2F5wSg z$O&3q3IUii%&S!>^#hpM9O8ZK9XkvI>u4glnQR)_>0g4n<1w)MADZcJe#M*qV|(xo zPElB>n9i4`7&hhd> z`|vxXpdAXaZoPx|M^7u7rnlHfHTGd{x&D$2e>44wN!YL7m0R9nZhRu|=i0lO<)!)2 zA#BKNa_6qLR(2IFm=G^KZ>dqD2iw}%PrVVqgeq&x!!9$Xl%z`N#q8V`QyMMxA|9dL zZk&kWLssd+MY|;;FrWi5@`Mzg0)`02L^Ub=UV~#NR={{%cZkU!Qp#LHF&s#a8Ts)z zE!bDR=js=LTqWmC6)q&#c?0q}p`X6Egt!2iW};?en=vt@%#%<#>bLTNO)RQgvD9fj z+O=?^5ti}7w78pG>%*2yu%1Ez`#+{~NK4#cm3>A#i%en?mrzK@FXG`Y&{Ty`N{-|A zt~>ugjjG6lF83&+d}?EFc>~a;ItG{p&0TXYc#+?98s=6iN!Jg(W$TB#?RGZ9#0lNP z{n2|)`7ZmXx#crcZ@y5jEM9p0ANsC>xWgeD*4;MJ{;w^}nAr%03Y1o3h!oSZ)y|aF zk;vyH`DVgs^UbY5IPZ&K~rZ(f9 zA@|p%om9HP>1O^*Vu~zO7%*YnrW=KG3ty;Y)z14N%u876@6r}~!X#0)x2jxkB zr^gD-haxh~<~yFZKpcx;8rnqR-~ViuN_7==T_5jqVNhAzS2V=4L^=QFn?5?L&&?A~=Ve)z{739=+nxgv-cr=+;F6Rl zVrVi4rxxcX3sNBcJi3q%7(e|oob&dSY1`7Za4T=eh!k&AZXGiGS+2)!2 zJBkSYzF_#l3tdyNW* zlRj&Xh>~AyjehgPPCUMi8*lmLY~H5+XdDR!Q}))5eF~6D6xJpXOK5=)^1wRW_!m+( zIOs}&qi^8pI)I;e`l?v`ybK%*eOVX~uIhgn{Tt5h&Z4v47J9VduDA8=ep}8|Sx`!* z=Y>YM`-Nd(o8E;g23Af3tw82a8=-7;E@rpNlgX^_OP)2Bo`3uxt_5-O@&QOE6w-y` zu{1v2j$K+7pZ<32($nPFgW^h@0~-sWvCMv?w_fK#WNZ#f-7!trf7;}#JCrsI%jnyS z-u^Fv>E-^W{VUrW*IU90oun4ApE7nj=OHf~Pqei!L!6%dho z0QHmmcV>=Vp(oXY0%X_~Vu$y~zZs;Pa1Ek+H*Dq;=1(-z^)rWam?57jhCP=dk7_IO z5J(Zn-Nw?Gy_2QUjUPTMNu6)gsnCb@vBBn;hgC!yaM->aGAR7V|44TXv-N{5H|)3k zf;lb=#Ri08lTj6M)W%3!PQ2g_Iy(AE_>?G-Z5BA9+%{MIx)-l6fY(olM4`0Uz2eyR z^k(tu=N21Yz0SUmTgg+a=G^P(=Kxu1maZZ1vGKxTpVZtS)7+h=xrm@B#X&J%jlSOt z1;UptKh-i5i?EvY5m@y0G9Gx#gQZahLxNdy)EB!{Vm46h8mIBXI#4k?6fZCiuwcBP z#T!ulKQy2M2Z9=qHUy`Rll}6i7l>`Q^K7`Dy{+-r=~;Z(IH)ZYA5tA3l5UM&#QFn4 z;>sMzFSWmkfFPzKKXNV{nPn0#1)_$Qo9F9*Cg*|7Y4~-~XdqU>a2Bo6FpOtrA`(1# zGlQs(4N3i;7!unm=1@}cbos%TF~!qL`3SH(VJ3SwPpI;{gh%LM3Q+qI%x zZ^WJUi;uvuZ#DSQ`H`AZ8@o-*nDxL)sVPlf&r6i;-u4f8N1ylHON;}#;PK;9SdQVx zrFIRiiys>|c{U${=O1_Kn|$x$d21o64*QYyuFq6M_w2jg{W-9KzF3jhxJwnLCvnj1a-%Y@4s4UJILhf7>7(pcRlIL~Z^G!R_pRGPqo<{U zp0xkN6AmZij+SAU!TbdRTA(B5hedg!XvuZ@V5j!Gtt%vG=2+LSwJzIe)OTyR_M;}2 zyl>q;v2>30{M0e#aq`=sIY(MPxXvv0K;6ykeIa`>)Z!O0;MU~Np5C0!?D4qrz^0QN zf}iCOymTP@`#aFo{Z|A?UK}UTA>kW>n5|xc)@2;lv6?`me_EUWB1W>qe)%bm945k5 zhD{uoK3u}^3T=`2I_2I>gag$pT?ViCg56Oc6D%?4MKJQo8n0rXy3p zN~);{#J(0V7oXUpKo89p)!odQxEt)38Jn7|Ss|5%!wWIW&H(CRx0uGKBOeY6w4Yxj zOGzw??R3Nq`gP$B-+@+>cfZ%!U0 z!X1^tTZIQf#>HlF4086BAAM*W0)d^xazD#~b~vI0KOJpQGr^#yE$N^p7)w^KAcb0< zed&2p^uhuAWe|XVr&B~`JIBP~a2WA7OLB$M_kJaz6s|JdU}4r%IG(=a;VT?}%DWGX zA3giuefhBCPa%F`(Hc>KBeVLIS7n(6dtg`3E_W8{C-_I)1s|^H3+jEJseWH{{6q-I zMETG9Wj4O#Q1aIsPhHIw10qEr%6?J^D_r)A{&57WaE6y7K_owr!SP^O!@B6{Y&7TV z`1?Y(FK~>vNDDCW4}ZGc>?T~f!Q-O!uV8bcT=PCT_pPi!qW0p|Wo%4+m6e+xJ(>kf zW3<^?Dl1RrzYCO5^w*s>56iSUhBobEX^e(b8(sOXqhK<+7QHRf%~|7PvTHm5UEGgE zj}Lp!{P8`nKXrS#6YB+*BINqCd0u3XWSUroR=rXLutKT%eW&IvPR(20n#ijXtD)Jc z{XHIrkOt<&-;?&-^RW)%HB0MimgKXWKYYjvaEz-w;Dr>qnxdQx7)LiT1A=3~OWIA?g7bQ=i zEJ2v|m;Y`?#Ce|*t6rPX*i%9EW0r9+HaJSK#UA^Ezv6VytnOfp)ve<@FY{QO5ufo( zG*s6E?q`--^$PF?H|O1FusYuS@m1-M!Rkx!K(P8X9yoXbKLv1pBm$=FC-leC&((o!b3)4q}sIMDZq*bcxtqhk`orO7XAaH?@yriM}; zGe=$2>dwxS(IAv~NOM{zY&QT`4RdwB!B3!Q*P=hrm$-1T)$nIMG_Ek7)uN&<5x+;$ zJ|P64skWbQ94)Z^64U>PZgYj0Qv3BJfTZx&jb%`A9>w(50nH==OXQvwFjP{o)GJW%M5BvKQ@p8aQE%Gk-1&#Z#Dgps^lKxkes8ShX+ z^vZszpj60Anmi+vmJ@dYN_cHeXP#C6FjJ=~@hHJ1dQi_=n95qXU7nYTB}r*19 zhlgv^v{k=alt6yEC;N`?$U}^;%r_3fdML_|57gW*AcET9dZ5+tZGDezPTmbPOtsz1 zO=2~MfCJ{zWz{!mNkGM$?=dbDtA2t&M7ry)HFGc5S057ta49TDj^FfW^Bn3^Y)w|a ze^bxJ24cF_fh>VU^{ErjFt8dg&Jsm^Cwr60Y92gFzj>)fRR1rtLO6RsfD!(Fa~!1=fPGz7;Zd3x834+fd0axj0Y$u|AHs(~K>FPE-*{cR3-V#4>Tu#9l2dqg)pb&X&_I|0=tw!s({M^pR`t*}q~S z$d^Nyc{OJnt%9^xibs^KC)u1e^Co-zXwAcpnKzv!HLtBN54wjZ2jj72z7@adp9eX1 z-kjcc-nvJ7IdyuC=Rzj>(Bt`2<)<9a2M=Y(v&0BfM58CahCRlUgOA7l`DYl7k_YTWpzUa&uS8COz= zyB`yff4B-qk>?*Kv$6BgWm?mw$QwVTOvk zwdjegQ`peUTpjh&c86RSZoo7{E?Mf3&qybR&E4?u+#hpY_s1B?wAo*C=}1eWLW?6{ z*2OgA{+N|@fBf<9&T!@an6bL=y10=i2cx6U=KlEW3Wtp3-<+oDnU-;J#|!`R6WPnf z@d0L&4CzM>Vhs4=AObLqrOqXx+(kH67-rYZY*w$CCU<)k4|LvvMoaNWPD9d?-}6~_ zw^uH9$A4&ca$NU%puM4ymK?B>w%*S3V{GKJ&pW|L%Ic@4DO1lY_0hvj0cho4`j^osZuclEI+FJ1EhJ zR!2omToYF!h#APh9h`x3y~2quACu2a#9Th*dgrM1?mRnb;W029E4 zfK>svXj`~rT!K~!Xr1@_oO5SQ!qWfm%}1P>yPV}Y&w0+XKZV7Mc7uMGKbt|nYs+)0 zwGM-H)ONrR`WFM**x(nyAqfIdEN#MF+_OApKfF2JNFkKVFO85&8AV9-p=pf>_%4a9 zUMektQ3{8Z#X)?TajYXhcr>+;>S;XUM%^NI^u(XifA+Mf6QD4YvB?J8=IqIk(mf+Oilr->+X6qYBci)*;ENBP0_jzq=75}{+*6Qck|C3E4s6rdAKp{yfy8fhMW6!jhN3FjthKFx&F$NFhgjo1*$HD=>iZJYk2$){)!s zmA+?@zdN%yKxUEpOP>!3Gn~K3O7C!CwjZ~PQwltuTA0sY$ez+(JDk!foPfK$Fk_xf zO(}go&Ik818FZpMK(k{Lv)P&5?7Bat7{^0;%;pTP^tC{{$2iXXOKLJKQ~G>leFp!2 zXX|s(vAeiF5B@Q=K9Qx_>+?&l^fja6!bKcEySzS+K9QPI`h1+TcfLNi9OKSrXY2FU zlGOUlc|LnK_j9GM+3eo>Z1{6(GOW+e{NYwC;7GMglm2icf2Y^4SAV$Y+aR4oHt4gu z9=Z=Vsrdbb`~ICl|Z3*_nRm509iaf7M^JXLB`I`kGB~;oa75Z2mv~F?~8c=-F(hREO!@ zXdUB8M_3Gy6g&0gbap1fahEDX*TOV^@NSl%fcc!qu03kF1?I* zbG&wB4zY?>cjx=?XAZkwT%wvnmWj?Un4^4j`O+m{^6}$EaP53lCMtTRXu+9NR1ih? zpRx8HLkG?~t)iAm=?@fEl_um*#Sy3cSGGN_MM>rJl7WBwy94i=Yy04cUBthk52x_2 z{i*CV`hqKctx<7d(fr-Ozmmr?@K4xYC)b@v(mm~Xfag5;7CdYEeC517`cA>mzKF*c zLw6A+PkAUsJU(v9o^G5geNDGdlWOpJ@?yXkEoetuTQ0#PhaaZ{&2lMC-lxe^x?|X`D{XqK6|mA+39Smqo2%PHj^tm zS+>sm(hNus{2^;`dg1SGzhg)EHv6z$#J5*}pTf6m|B^lMTe-56f%gHLY%j0Z9?qIl z`udQn=?11FCst8X6Wy1*_wb?a)OL1qefof&npigOd?I^lf8|PFQ!6g~@aEm19A7@f z+!Vcd{c^ zGx3*NzeK*rA)I^SS$MdL?n+asilc%tNc_RaF>O#)T9vX4+Y`qa3 z$=Gazg;FPpUz-(l5(bM;@6+plq4H`gj&$tEU=ds)a7!61lw*z7_U)mPLsaR*m(=Mi z`fOd086ch@&|QJyiL=GeIVk-9li7TlMdcR4Ez1>G$@6~KkHA~81@UU>^6q=ke~M$q_SkSX zP-1)aSkI}fJ@j!eIg<;82ky)hwzoIYZ7wt4B^Te7_oSA!dP(-O-p-Z(gJoTNzgpIW zeU!BkZ(Y=T&hLIBTL`z3ZO)zQYn$XlZ6+V;j5DiGX(SA6n=|oO$_J(T^o+2bXGJ)+ zMv}lDkP@(?m66nSaHDbF2Ee&^9Xi+3xr)0HOa53r5)ERtUl`1r&S2fQaMXtSO2_0} zTOl#`$>k7xnfN9;3g7-bv{pXbg6aOp+gFJH@p;nDttfw$#R`n9%1@f_aR0>)G|6ek z^|5YNzNhA=sImPz45k=MS*i2rVzCiKCS~vZgYC`nXFPV~JnbU;+AX60ed^k5jdyP@ zvd9JCc+l*v*|r71G0HtR@j}%5$W_}IIpPOtG3+_{Y^{CAiHr~w=|OE1$$W%-;p4N2 za6mtR0Fjle#MHOf$I0m+5lUvP9BdZDHj{R)c~qtqWcI;HDrpuy7A|{9+_Q)1*W(uy ziTg0AZh1F*_I`$0QBR2^sfDN-91jFzpUW?MBD<-k3#bFy3g>N99?ZxgV+9YcHS3c&~@O z&(-fI`mf07zar6pg>zqKI|~!%Th{wouzFOWlQd9HyEffUv_pGCpYs{aIM_9la;o=L zm{9pISI4FN!Cgu)d3mqntDAM6@}EA>SpYO`?=)y|T3jb4qeMOf*SNu945o5oz*2>A zIv`wNpD?L&N+oqpF*d2$4}eZ0OiNB1lt^ox_%r$xQ}ksjndcxek`-t%c#fw*{m>=q z%N!BF)k!UpjQ2Af;eJn&U>n9&EjWdxW&%ZJ)>aod$IKVvZ`41kHp}c}WJiW;!-D-> zvMzg*v2uD{83QF^d&mkWD9+?y)XNyL(5S98Wg zN@RD5L5yl}Qnfrq`qek|w|#l0!=H@uhsc*~Rrp=AW?GOEQ5kIvK|%V2U#j4==8$-Q z6&%1X44O+4!D%`$Z8Y`{XZCLu!R&_ffMp4;BnoQ1_=Uqt!?aKrNNQotqL{>ie00wTtw)IG!j52l|EeMC7B z+b$>fUWO)pS7RGJerG)%rFwkq3S}Ejgw;EjO2=PiKsdG+vq-z5@}=rCcfA5$^31JL zN;BaK(VO*QIlc4BJ}jqqH3$UuSK~42yQF1_7rG$dd81D4L8JcPTm*+i0ryrt*Z3-X zZ=<^WLoY7(bJd%~5!aYT{X%>|OnWcWJ~!XFG126^Y6hx|5Jwju?nT4ca*dy}13Wyfd7^wf zIVpO`*4jmQYs3&gu!I|h25uVl!(NzJs!W;Vib_zR$|#vt0WQ>(X2krSF5>RDwU4uZ zJT-oio=yWmig+zn)Bwu?ks($t^_V-!cJLMnpvBaMuUcC$A9r`KQDlW}&c3p7;787= zlzLhfrUOo+#`(I^m>uk{lvvs(?y0t$Xj^+f zTfydv=lfMQ&O#g}0+y(3XTI{WC%;@nbA|ET8kNn|2;%r5QKQ!cSE>+-#`E!r5u%Wz zYHjbUz59xc;+j&UcveLv8?uU1P$aVik&AutxTN!k518f;wS0krBqr&r8^w`OX!GQJ zQq(>xO-edQhRV!0y2Y&r%wc}axV}hWrplrPoA8rb3VoLegzDlSQQwMDjEm+yL+sr5 zj9%tUFcm}(5@T5V^F{8$6_ziT1eVc(cJ;pYzFRk1`;t`ly3L*aw~}Y0CC?bz1VWO&Ky0++#Z8G)E#7RF~!A&XI-^Ju5(A|uskt_cN^U?+$M90 z7RBFLuIYg z2=)_l(MY>+9~XMdKb9a0lFUatg$h9chmDe(hC-I+R1f8B6XpypX$|qWN2EqZdh;)T z+CPVC7mdNApk+L26w6zc5*WaQR!mClpXCYpa##BMHh7dr$^1pm4NExnixUmAGqc-G zkvJ{6RtXbVzKqQ1s8#8mjH`JPY$e%3;cYEy!M;l#VX|qwYqoUY0G*wXS*Vtq7FFbX z`1%($A=~2o>7nh)Ji511Hk+2DWFFpmXDZJr^4k@+!Mf~YBV;7=B~DA^P;pa&y@`+W zRvSEtqCqYpi85S@MR>L?G1&p18fMSgXQit=Iiro)}5NvTvlhc;PjylPflNt7>HY&dqh%1t%`1X@`SrjD%sYzt3@J9Z4;eVv3 zL{<-0#Z420KkCz$Y3V(gIOs)CU;YjWANm#bZq(St?U2=K*R`b+70_aof;Q&w$+Nn4 zJN5mn*4TEoNS6O)LQCj(lV~7$2qH7NA1B78s#P4xSdybA7m0#TV$|`%J=~%C6+)|w zGAT?hmAdMZXZ=ROD*GY|R8iwqPE9;x(Liqfnm`PaY^*0b>{_aHign%>DrpasD*ilE z9C(o!%D-kD)R$RaX%C<{t*3ggO8e}*P|GL&$bhu~V{TZ=uMY$c)TsHkW=)8yqlt|9 z2$#xZx2^>x+M8s5sw#H$~M9p_nW zGNOkVC2?jg&e+C;yqv`6s?4AQRa^oj_K{QAXeb3kGirN1Tjx^9k=$XCS_LYzI$#XI zlv!PY1(hRF@y+-}?XQc#X6yphCRBf-t;lHaij0yo6VU5GS>WUr6+j_ct2m;R+(T?D4V6x3Q@;*c-TM9eO0gYgj z-UFvO&o}d-)=pO|dt;si(NAt?53XnB@}sQW#m|WQ)(-H$N;Y>2|AC9UvmxY1UZSCt zK=35JcI!9D{*m{|vBd81C*IYWdSa6^Usgo9*Z7mT+GZK?Ckk^(%4%9wK9x*DM&(?x z76_+@pe)q-!E|eubKyg2@h6F$UL4k$7OmIBi{ey}h0?zesI&6J9#pz0Xu6zMOP_~YT%0Q zc)O#8ZJ~zaeRIE)SFhWz@gRnQ1N!WYj;)QgpPX5{x;8**-4>_6Zu+{t1GOugD;x9j z8_&!4bgm54cAUu-9@-FSi4B}f6lqS*4f_UaS9MV4F2Ay|GT+0K{W>2A)PBs9t7=<1 z_o;oYi!Li0!}%V0pdSz9#%=`dUYBI}a`XtT$>k^j@dsIZ5^nO+dSx^c#f^GKkt?&L zT`F6+cIX6?>u$}!!&#K2nmnuC;UhH($*Wf+MB1Y&pEIOJivmfL_P(5j&I3(prYeO$ z`aGZFnsz>{R!nrYVU5WvYv!cU8HJal<4@S<-t*wSbY@QVVPcX)xe$gOL1$Uj(^}kY zt?ztZ#^Xe3mbs_WMLn>9!3>hYsPR6(%DFQ8k;mncFA&L7yoY>C*-I1l>x)=%vyKt% zPg%^NoQCLy7?h+$H=Tm{q8#vUI#=wE;-*gybyTy3&cbWSqS#W_Ocgp+nm~L86&=jd zZ@K*uryxx*2hc8{6uFYmNqHJtYn;~0grIuoxX%oL#z@tk&UY1SBc`Q4ZD*S`*ETe2c}e7YbvefQik`jBnCbQDFzcH^To^ zcXUMJqe-2~h}frZ(tzXOEVx7%Kg9G@1nEs&=?iehg^zNqiP)Q+k0LfA6Jmd_&4yU- z^cPBvAs}f$B>t~=`upK)yFh<8a9Aw_fMghR@xNFqB1p!iwVzNVhMbi)>AkHs;)Eup zpEgS`kYAZLQ5i2LHl5xxkv*5u4REH@4ZIoON%9ZRGdVUzuB68!mL~2y!Speuut(J^ zVXFB_BCqVPy~ID+l7q%*n9t^|`!#uJFsZ_t)cn|tj`oW`_1*-wdZ~zFm&)$hc#S3? zu&A&Hko{%OnbWwG;qC#}{+e7=I69uiMnBi@`0CjFnNd^SAjjN&Rj!;9Auu}Q*d(kK z@Z{EH^!6K^(|<2;nB1)s^}{S&copelw0r4ohSlFwK zEijWSeQkl=^C)_DR&pDt_&N9Vs6s<++WAh?)q1sth>=L9Hx@f`8YLinjxDZ(tdxKK zR6)ooXq?W{gal4gj$l#mNm9;BOuy`rFUyo4b^9FUT+saDX#(2?_h{JG z^CPw2HQ6M&D@GR0+;_wa=VbI1qA$TW zyw*|u{8zN~^WQ|VGHOV4_c!Lf%I&sM{eL$7vR}20$_@Xb8cXLQ)n{Gv-nevNRYROM z@l6r`D#@tVpzcP!p4mda8>H{BrTS)K2Yn$vAq^{KKvC}(^Vu}fMYZxPEi^r>2*$}9#aZ+ZmjCB(gbyZcdDTq7 zP&H^;&o-)ykqRmyJCALQvn`E=H*$GU_9L>l6)dJ()iQkv8=;pBGld`cgX|wt8A@z^Blk{$(wz`y|(Dsbe92I{3GyXJh;m^6DMIl~sA_gz7S$ zib^LnZ+8x=TjfdqZ0$VGYS9S*bXFKuaT@Nu5dV?c+iH=P}ArYC`#ptHT`ef|&Z^i9jXIY-^JRAZKUB)K#y(c^&| zWZwsi(ibmmJzGm#?y9vmZ03h2uvBWJfc#Qx^b|7H$_hTp=75O$Sj8guITkqHF83D5 zy}DUdIYzNsR-;%A$tYeV&^1aHEmj{I(@GScRPRSalW1@X%sgqgSt@79?V>KcM%|aG zFO;{6-Ira&6pX2e{X@=gZMi{exh9CgV-9naA*htoG(2&NbNWok0+rGdXdLwxnX+#c zHnUfkni_Om(NscgV+}H7GwS^yrpSk^Fuy3ZA}`kR>jl9o-qdLB(ht28tmxfxudQJ* zAMz&zf#QJ?%W;nTiyTl!!`E^-Q8;~8QM~Z-NRpP|dv?5(H?xDqF$Z-5%w;-hmUqpJZtG4IYy^AJ-hM&c~)1 zay~X}qHldf{v1PfOr`6HdcV6_hM~{X$9R`qzO`x3AHz$|Y4W^BI*WQ=BliraPOX|q zk2(l4U*@W+e$1SW2H;mH`D3lj$i+@tXqlVp@f6+T-q}6AdK<6Z%4=Gir<{r6(^VOU zqo1JY%`OdK@sqwBrxS&JEJ#cA{NbIG{q2G{-a?KjJBPF~IBOQ<^8-go>!n(Gl=?)R zSf-`2!6Yna_g|%1&>51b)-HHQJt5@<3(lgqOlbhvuTtPrHpbX=@BwFu@q!kXq&$ht zFj1-_q+@`H42y%qq*0M7D@Of6-^=LusjICFa~`Q!kFyF_)6@-ft`){gxesRND-bPz zU}Dlw%(aoJyy<4$OHE8KhqMItvrG9BFU(hUv=XJ8*RlK46PKs(K8-)#QTwwhG(%^` z3;z;I?pn09Gx}_Kx5huKSaIX$B-)k(KVEoX-;MX~kFe|TaTGmFz~||)|F7`LAisaR zE;9jrI=CxALnR;Ycs-lddJ;?$RRr2r=ZW)^J{#UWc<8O|?E9s*Y5L*FUH3qj90~?z z`P1%jytBGAen7{611wV<;v^~@^^SSF(|%$XDg8le2mSO6azta3{eK<*E*-s^xb`)f z-GW!`OTumB;1gT-Qtt~r^V&W!=>K58$y2z7Q~1MR`g$#?{J&T)r0agy9YQzl8ZFkx z3vbBiCeUX$NOZmG3+D(y%apf!*BAapX++XehAqs{&s9N~yPQ8Zrpwz}H8A(HE*2#r zIU*HKb>+oLN?r_N3WPN@^Rc5vQC3=eBAFqU$)R`Sv<>*=Nbmrqs-oTl2^Qd|a3H0> z<{-uq7SU@dhdVoC6pkn&x{oR%w8q~W{5khYXz*A-S@^o)e3<8~`~=q%zry8u=JK|y zB%%6-C`fqEhuL1+CJC&jQN{Hfdt(OI!=W=NEo4nbV+=Znu(ff7t;uNmIrn}pga9YN z;)vfUo`_Rm$`^O;3IU62vP92fqGzc}JEdR0(mk@W=|#$3_orG~sGY@38489?r3w@U zQW1xt-?`;#H+0PH#HEi}?}JUIIwX!8?IJ9PL=|=I1O0Op6w&^=4G8t>Nxyow=hr+l zs$$|(`ZEgJ5tBut9am}V>a*s4rWxd@Eo{X?Et0;j&f4^KaIA>&{Pfz{Y*Ea~_r1WcZSICT0OAmuHxgu@p z*G`qCclTGCeod`+a-cN~bS8_GIuu4TP|*S<;JmBrh2aX7-EoPwSpN#v|IEzB(676- zb?s55!irsvOTaL3q``>jiKti^f(Qs%!!p?ND{3XMaZNTZpG90cRdx@K{gcGyCAlK( z*sK+CzTxy)hB0s9)g2t|%a{*EFogNIGV1x!+C0h9u5U_1@#Y8!y&mQGB@N-hB8$R#X6fYs9{wwmb3J*Xxi%t zQly53A~ZQHHN;fb%qpk;bcLYP6i*>ZG7o2IQV9C_aD|{8@RKJ&{-z|z-%FS7B7**B zdNzW}0;kAd1?106BY*3Ds!qPX>7O2{WV4((A~{m)3TAFnZc!y!4EPNry;|u zmuYI1lJ9!*8!{a*NmRoQqfnF_FH&-R7v5ko`vkB8#+QUuz;sg*M|_#i^p_0#oz#|1w{$Dw@=n;ku{ct`Enx$ULA%f~&tl(jiem{Dl zq69|06nP0-#ZuBRjEyza)=v(^5P}+GcLFbQoBLNeXGI5IABhfpT?EKT`487!1u3G( zQ1tAgK<&(8PsmzZvw2+Ih~>Pyw&nv#RBE9Fx5=MiMY_YouUcP2gzdXwB5B9bCPb?v zWNimn%H~DYG}9UkmdFu(UVeTk{%WVy8tnEcFXv9G4oP8-JA!b6zmhOdtVg0zhRM9@ z8iLJV*n?4`aCgq6X_ft1cHmT@S4karyzr}2+zkz>=*qs2hw7hB?(h2USJ0fZ<;VCi zT(QvQzq0j%S58r5QX~yS@12RZl^63AS`uQBrB=$S50Rm-yK;(*y9SDOR-!2xX1s84 zuWhA}NV%Cvp5XF93HLd13-mDsEgJ_Eopy%)njMkuc3iy<@EyFLDDzvK%@-#eHqzpg z#MGWT@fvDrG9mQYFFE|;)a!^?{Ug?Rad@kXlaQntw(r7U3ft$sNIs0p7PGEvKsY+9 zJ!0(uI69cZnWZjg zS4bzYP>XlY*$s07Wwd7B-@(XPyefUXPKp<9ILSo}b-X@&qB>sHp!D%->f;pyi#}cl zY!|vgZUUTuI9_uSyw=(0>*Mvzor#)_zsNpb1=Q+z)zyq@rgFeeOFLjMr>;$gKL_}j zl_NmUh!d6>?U9&~LdUgb8XdKJtqy3*K3{ulZ>r+B{suhMIS4*Zix<|@SZi>OoUpsq zUhS+o`h@M$d_Z@+@Ule9YLv(H7^On;9nwds>H(QSg7BF(I;ED5yhwBeH9dY}PKX}6 zG9-u9*7arYm8}Xq;|aW&&&r4DKJyqietZ(!n-a z4+^?I0k|pT5yc=hvC_u@x4iT2u&N6SsSFr*EU#=7cQxvrglRF16e;8~c%_ibJ@t^= zg=7w-@jglBE2XKm?~P>Ma6$&jeE9+)nZ5FFJE5QFCpuE7;HTODnSSn-XiC%1e;nUi zTPgaPbP+VjF8Ca>Y})0vq3UbkQEX6kem^r# zx(K6YZzNa};5ZdQ{1qr{Xya4dT|I&)eCmmOsm$2o94fa_d5?H{YeFmg;#5U4m-MQYP01mSGl*Ib z&^ZS>2d$gcouG5SINL@2n;Bmgt&_;@wxEQcfYQkKQSa|A7h)HzXbYN310&MBJ+aF9 z=eug)(DjK+oc-1-9W44+sx%Z&tVo9g5K>B0cqrB+sW?6NLXy9}%N5kJK6Y498o4}W z;?CreM5D@;54i+QY(E+ltn<4d$0cw_@{CVW$NP^sn)*^ z0~i&~yh)jT_ky2I0@4(Ix+Q^?S7EfK3Ac?vyuEH#6O6pYlaQ=ppiV(uAKuu8k1TB^ z5qvU)bCO!1;v7l%YxL4$du%a!!ZH<9W7TwXB+DZXD|g!kvT};gD)^l5AQxn8!_yvT z|K(osUm6~4x^{vTB&(@LNWn8qG#EK(1!b%*6jKA>8~Nf&CZe|2BT0`4a0601m!XMo z0t;k#Af3dcpqb|d)m_)L+k{te_85Tra2~A2!I$9zaL+FxJDL7;iPN#vwG_L9C9ZBo zsXH(lYI0uYNa*}D1#LGzJHeXG{cOEV$c1{PxJTh~GD`w73B+y-7HJ|Oix9D=6@~1B zLv~ICK3gb8NUAhP2Ztijq42#b)(SfOvu;A^jE2M5AzXA?gZrZ?WBU@j?37v?h)5ci zV>FE7Hg3v(+?0!XB**#LH9~eSE|o~9E~9BLqoG_q;yv#u!VXmB38O)(N0v1k&zY+(aUv@5)dpwUDCHAv)IY~->dCrS ziz4O!u6ZM3ZI1n(r>U1Yw{Zz~B{VsN$M0xfiT!~)!hqiXvNuQ7W^q>j&6{(wC$^j$ zOkhdKDhf2B7LR)GQnZU50IGE=51E3z^KrsZPAfNGgA;~?Y&(s-FHSx$(Ln2Hk0zO@kedk#TZ;da{(i~sr*M9fNmL|K2bRY*} zq3A1?In`$`{PC{L&&Bv^uTx2;^PP5M9KsSR{eA|2)c1U7f5`$8ES&noJF=2Fy8ym) z;>LHeFIQx_rms}_)`jScdye>3_vfgF`Z~%J`M`MLb4R9*Ibj4VB&2iZ5&E#JzMM^fuy!!`-)4)JkfQY4Yb%FfBoQg{c4qLD07pu^k4zg~Fop5&DKk z;~%El8ZZLPAXrpACu|K1ThsDW=HiZC%*BNT93Uv`lTLEJT*G%30g&f1{GO)bYt|?> zr9+iTE1sB>&ZhKIk`~S+T}%4=uxy$>`Qsk)92Q!@CU8o~UuZb z_Gqt2mekkN1U;b2jbTtHIdUc00=$2PMhcT0IV+)=(Czi=AJHZ-+7*wkI5h}nhd&f-d z5Y4A-6%bQYA#@*M`*8Y|uY|j=TT!9H2}D0A*CoDdPaNQjM7(o~>7et?bpBFx;_ev2 z`H!h_swsLmi?NGW}`L@@bHYmEetg{fvGxeQJUN695(AMxm6Vs1L_hC}=31nTB= z_nST_WFHcU|3e`vs^~x*-DjIG#Be`Sv6n;H|GeYg7ZRdaWS8JVOpc|gB=_xJW;m}) zB+fK9N|Gq~F=XEwzah?sKd>AL2vumQN(ou;pNO1Zn1Q2(b0>p3n7k`Y3%mWyF^T8~8J?QKko$Xla9{KVb5JI5*y63WvgNZ zd?d#E#3;={Nd(-5XD7#c9E0G>4P43ec}=9~T50qd0jK-=b0&lI%orD^RDQuFs`;ev zj9;H*WFYBh_%K6Tj!{CD!V-oMS&8z9r}40mhb0g6}t0@YV_GM}I!U1sJJ+*!SyYUoIM zy`48HP$-Ttz1G_qI|b>#g---PNE>*!6~(`HcmLugYmaO;uJ5Yj#O zv)+aCR4PN*DslK~Q(f5JH3#&O#<2Zl0Yg=xN~=g#?g{xXe!~WF?gKnBi=ftZqh!I8 z0l^`@zeo+$S72YuH|>6+X%cyBgG@wfa`G&}s{w4<=9DgTH@nVG zh-3%nB(jGH-wKgRf;o~Fa6K0~I*$g&cKnF+>5Q8qJ5*)n^DF*QGV}2*k(tk*WW^Vb z6})Ab$;^D$Fv&56Y+pEK%tTW zs`E_X-h)3&ocGD+vp@h}FVQVMQrAIHd!(-G=$X1su?IUCpMslm->qZ#YINk<_i3cT?5ox11oS<9un=EMIRli25<3@tRkKU9q;r z-{Q=;LlTgiS(*0#LKF4xRTq~v+XdqwHpChZK4OxzV-H+y#w~RK&0Qh0=UAM~xft;| z16~o~oEUUcT1-S&r~=u7)ZLyPspz~|wj~*dmUqs3#?yIg;+zSNaL>hBX*^o+`M7Lc z-0Q5Jo;4yU8zqB;XHhXPEPklixiLtvH2A2KajFn^qwyGiD=_Y1G#nz|+1@S3qwSE* zk%qYkR)`ED4a1a9LPb8s8NzuZ7tlvQ99K& zpHoV9<_@1tNcA$0AE$a#lUf?sm*MZK4PF7Y*y#VEVoaB&rn>IcS* zMT(`Wz@To?3ZAQs5er><4p*lry6WHdjvt(T9%W^SPV$3Ec{JNLue>&}V%sy|z#`3J zuZh1a`xYuv?LFo2{_NFvo6nH!Fh)az3{XyJ(#D7F3J&l{v$M8T>DQal{jG%AZ%>G_ z15S5wM>wW5{W@rLJlZEQJGy*TW{kKsK3SKWyzSV6oCzm&Db(%V zaiUo zs`L5q&GE!+hL^juna@+qCM>Q7)->T^rl2v5m4P^kU1R8HWeC;dcwi5uUQ{|Rl~+1i zP#~}T0RNO3^e$A|Ir9v%?F}zm1zYstHXnU`Oi@$KYBM*u{BPb$)F!M zjJ*^uN9yDq%F|a)fv<6taQ;A{E7NFW)6WNI3+FEWWys@c?_ZMn{!zR7zLvT>oU6<9 z0;jYAia$buqzjI_27AO*+dJK-g^`*{M2xHWVS5z8#%`1lQAY`4vhB!<3u{{9aW0uJ zq@=}pR90Wf&8UP{OoB2>0tR{5d3-7?#S~95RkGY?5Tbj3Wvu7D^~gmcAm9 zZ=p)%S~!xef{2L6v#<_~eOi9J@FZZ95Fg`(|J}!hG($=5Rr#Xx2UH~hAR1R@u;yi9 zs@3W`W2k^AMEhtxSILYr6UuQdya!v^!V=QzoZ7XOw-|#e3d2c)=uI5ndC-+#!$S4Q z@0B>uuVlh9;IursT@Wh@8jGM^TA~w9q@?%6cq@8pG-f6P+&BaUplA!1@@k}fHC7S3Rv-1v)dN%4tDQ*0x|%^{ z&1CmU+^<>L`DG~nNoI4Y{7s1X=ebj3b^0h0eD(8+gRS9IuEfhqxG-U#FlVitulFEgGa>-;{ zS0HFQWj}NCTQSu|?o^Xc{8*ka(s6g~g zN+@J5r^b(x?5F=CPY;r()%rc0jXy8T{VhM?zQPBXFgEyFC(+J62~#ZlM(DMx;qeP( zhyQg`T!9}|k(8M1-}!-PP}n?SU0niQN_JhZ4XHsV@u60TMM^?&2`$e5Eb&U=+}cvP zT9*1HaRdfeIa)+37xf-{x-5|7b}d|rZ8@-19pML$RQX&k!tDT-XmUGj(fR}<@l~l_ z`=6(=M7?IpDGz0@y^Pged%8aRGq^~xYeNeP_)dtz7v;)!xmAa+FF98;320*R+)2Zd z4^B>K@UzaZ1iqA}@CBU+RH>#N|M!CQlWX)qjWP*4bg%q&FYR?G{5vku77T}j|NCB< zjd7mnS6vn6|GqxA3`?$0DNJWzsbZgIkLY`S&N*Qh*XN$GJ6@lsK25F9ReWcC#xojd zi@QGg=k&2YXPorEtj`93nBpuR-ZK-VySF~kL|b}&&d+KrnV(JM)V0n(57$)UILTrq z-19Q$#KX8`?~T9D5albhcg;S^=eyPU%Fi9EOJ&-Hkz!BFuGEs5UzJTEtMXdsR<})R z&d}xt;RZ;NdZNSy+$gtH+XuRBleK&c?9N>@P0L;-RzfiRY?kHD**xC4Cbjj|x1RO} zXBCmuqUtC`@LQ<)2dEai>&jB+T9zuK1y{dNtc1>lMzrB>HmGoF$)urd(~Hg&G$Cg| zTZ8OhrE56;RAj-Zs3;}SAudWUIr~vB*%P5)RCFj2f2v>wpHu37=vRGV#kZ}V>Z4F0 zRbjN7!n=+!DC8IQlJb~3JO5?6jXOusaA%&`@`c~_mZ4hBEVts;-|9k@CIbgLs0OS> z3mKNF^C@)ZNYkdhsF7=7TO|f@nkjOjnwNXdvQy~d!32MmE{~dabTO|vD;^Y)T7^<2 zT911F!0-UBaQG?sX3FEv*pqfBPut#0yuD8;)o>R7o*^$gk5~23cV&z}$||`Tx}x4I zPfp6~Pkx}}^(8xz*G(7$=i#vmQ+6FcPCuh3e(WuMr|{#Q|10$9PrC{9*e9=dSRyX$ z9(p{;zDc3S!zT%Pxcet_eG~Zchu`;tA0&OdyJNjXCij&I5mh_O9R4k9Q> zA4J2HN_=5SAAQ&kh=wEWp+qe7_R9d=z_lqQqKwfc6hai(*tL8l35EQCP{=LkE<(^1 zjd*}&J0I&sK9-`XP*hi6tP&16i|$wGAPqq-R3B0A0~#Hah?&Z7l8{fe`mKnQ8izS~ zkvG%jJy$(;f+u5E=>^nO!#(Bq^zk`2;pnh~_EGOmOOcD=rAc(C-LOmOaKL!bp?b7J z2gM(oWIOFO=;4HMz*R~8%(PZa^GW}L_f5f&7U%P$bvubeDrNsBo=aCMl^CdD0;f`9 zw>WyXllz?j-OI%&XnMx^0lThW;Hlx7~~zpNV~GG1CG6!f7|i`FVh7f6r;OdD3vb|n5`ch zwQ-&cS+7Q-vk|=hYkFQaZvKo*=2B92$=@8a{8eNA1}@cm!Tygb1Y6Q>zNwBTeh3p%riuM!lGR zL(#GA!ah&AB4Avz2bx1?>)R5Oq%Ka9g(&7JhWnjq^WGH=pBweZvlqTL{{D@bOQK*= ztZZFxM)OE-hr_;Ixkr1%4)3vEEV_W01isEZso7+;gb$57`wK03}X>cGlsq zA3pTcK<$XZRAt$Zi_u8@(3lxt!<5R2TkDD(>I53|29Iv6%=4Kon@FpdcYPQg!IV%* zvpCT6`yApB5mOpGw z)oM%zO=jX%)v*3~A(;@%cP2Q{WqJsG+4g1i{-F{w?^b(UCKKRN*C2;qN`C;PYB@KA z0m_INM3X$)XVxwE34qNyfa;q|2pI;Ie{X#|)&#ZFEP2?I38he7vyYU&PV8+Skrm1t zN((p={(Y_TmIkV^t7!=K$+WgcWKkyrKf&7;C$G}lR`;>Nu*n3W1aOAo4Z*~s??val z>I&oX0aqBEQof3ytQOqaSJrH%a?T(d^(Q&WDz(br4$L@ zI8-fS-hR|Pc^7;6+MuYV3k6w%#^0MGo|U0PSB|bFcG$3v;%dm+5-M36v6h8O)JH(aV2~Ll5aZCbU=TU1_iwD+)7Qz){wiGlow)PYwbQ^m{4j17zXTaW z*dB`&Ab=`$85;9kO#<41W4>vOY6*jL)>vO`PnN{AR?@>6H6sXo%Qav8?ab4>e!`*~FRj|THq_QC`#SX27ew5}y1tXM!h4G^AC@ybbgHniIJq!# zTuB04#oi$KW0fW3QGPq2krd07l@V$%#a6P{%&KTj}7`}@MWqb#}`8S5|L5JTCzxg+Y@6;5r$9M6Y ze`EMAVL0Qdo)Y2T7%Ua1#Xb~t-n!weXx`rJy>>G?zRNs(LVlnrPS*Yt$+y3!Pf?Mf z^8fHq+2lmS7=x;0mz%Q7b7F@wHFX4V&Q7BK;r1apKMUJ=$~G9X^P0^%6^fWMyCA7G zN3Vi?(EH0V93(6RWUa4-aN0&B4;fcJS58g88Y&Em(wykBmz*c)jvm<;(klool~<_M zp`|zx;4ap8s*g%4L_>CeO0o@PABOO!u3s#xOfFkj*@2Ct3%+8hGv*;NVJ;=TJbX_x zW=sgeHNo{_!gM5*tut9f^p-=^X(1P@e~yCWR3;eLN#-1`^sOwtDR)Q8QqE&A zXiI8{v4f~fm}Z~+_2DAH)9-)a?j56wRZ#+XANm$pqARC~Zr#i>^u9XCRkgd2NF49j z2jo~+a7rmhidcPiCSlkTP8G>XCT7=$J)g7bS5n!z*;8`{nn3dVir-@gGN2A7pA|LTr9qbWvEp6di*DCF#;Ffgt9)cw18p8 zDcHcy^JBDW4CJ>42IM%$-6MHv&_yI_eDnHLaT8>F3ZUOOLP1s9*=LP#ndOs8Rbzs9 zGv4%;@)C0`h71+t1sUb7S;hx}pK#`r!k%Tu&5L)YyD7>nMmu;u{(fDU8XU1 znMzSmFLHz~qf*|@)$X&RgE@*;hpAHn({^ZkNDy59Y9pLhTQ>)c+m?rMeY|T~5YLJW z>etl_haIXpN0?7xjf6Bx0-}nrwNC0EUCgW0;VAZ0kI{a7qNBD(G7nKxE9-3|a)5K* zA>YSek<%=89h>uMPv;{cNMAXB8lv@-$8#pDIFuW}UvW88TCb4AQo}$U7@`1_6cOIyl#o)o^9|FwR9CCu zD~;h#wgoMebIa%4Y=SN5Y*J_|_$JXto@;+>N=+$d?pIqqiGthbvp;383r3$q*nL42 zYbSUyETT8L+Su+Umo-mpa_6H9G zUGmu)EXr*S^8C_%?jIVw!&-w!=Mw(6T|E%qGf^nk1G^NAv<4^A4BB`x0Hk||vk%VX zWCz$YriSgG4WlAzMfFeg8g44mYj`ooqnszA4(xKSKX7yWtZ3exkahBkh*iA;<5Tqt zoRINMm{ozq*%VOqcEt*E7LQ8)st!7pBSO`No(%eR7U<+0olBJ5h%dqIB9($S%SmF& z(WK~^k`mpj)og7omPqkxlHwEhAm{8WtDa*c8>7T%ak+*b9Upv7mblSKv#A*I{a zDx1T&fU-HnwN2;_4uH;Lp4>O>$u;^(f5wwn@?>BBq*a=IfD5Z3Ys3^*#$6{eJska& zCi>!K+NXa+#{2$^_dngTEANXRg6wnwm-Hm(t3Q41JT>UPISASJ>W{Tkrvq!(#o9?p zJTYvJ5G;{mJdau-~>mT=fPOerxz^*oOLqZuZmqu3?=m&Bf6c58o5ThG^!<%}9$ij)Yc(q)6#>&R*@edy{I z^7j=+WnbsBZm(`Nqhbc^>!rHbcDK41v@4^!m?u=yg^U_5Z!_lKM{m&Ld|j99y8S3R zNB(}Qi_J`ojKW6C1J>F^L9l?eF3|F6|GBF1>x@9{>gFKt1RKLSp3YYT6d~gh1;*YA zv~&)fOSTCLj13OdzSa?JJcy^x%kjvg{W|Xr)c%u4U#o5Tbf4PQUD9u`@yBxayqtdW zNN%iJ7+ayP=^%MciZ*>E0>y`0<8kX#5iso0zSwCz+*>^|Z0WJf&(`(GG`^s4GoCe#Sw{I1;yoP0+3_JE-^-!~Jq%z3P#+Arn7%BSr z^cRAV-+5|IVRQKv0c}e?z{b3d2aM-}`B2bt92qi*H0o}~UkgXC_lNB>ZsRSe_D^^` zR5x3b>yd#t(ZQM&6CXp$haz66`Ka@^(B7vZXI+Z+E`cdWh9TuccKfmK`fZQ*(6^?a zKai}%`Lo!$9}vja7G5TCs3kzHJ`y#jqN^MkXNnqH+L>-zja z;~2yZ71|wW9Yektlu{Co;y0}!#Gt^ycy9>2FJhf@h=tOK&vzGSKE;$#q}Eyn0J#~a zHuc%OILc!@R||H-{h0kCsAmr*lWTrUhtKO_yR|s^idMID$utovB&^IClIb4qJpS;{R>^<}1gYm<8Dwkk#xw&zY& zAC}}lFl}p?`gJzAapABD(St4ywfr;B%ssn`sPJ=4PwTj7-aP)bhjTBS6!I)5bJts8 z&q~wVE^kAfAsWo#>m@P=?`I^C)5+ggADcG(1ivc>uswJ29@6j9#muDk1zE^`HI(U- z^jY&3^UJjFT%taDnUiV%rb*r=e4xHlAYtF8Co@+j6V{W7*k}7AOon=>xoSf8g;i$m zJu-PUx9Gr&L(##vhdmoZxo1zJI`(SRljhtOnNi)##o$mb16tRK1?EmN&C~3>seGVN z${iOSd~@x~OBsTvx`yjZ_!hAn1%wfMq4W^3@0JmT>}&lY#$ZNAykfR&&NDr2$S@Zx zRWh(0A3f;zk?28RM*!*slvD!P+(wxLoZ)Mtla1!>X?p!&jJr)>`eK&~nT!_9e@wx; z>AD20FF7V1)`Bz%e0kHk8E#tquk3lv3hZ~TR3E*;)`L;Nwb&;-L9Nwcdw`r8!LoG$ zl_e%Lw_D-$1d?`r8|t6vN}?Fl>+H_wn=RWr0H-kB>M7|*@d^0Ci&uD#`x`~j=^xokkY+MCp@ zE&EoTdu8uc;v#4~@?FGgrM7ym_Vf+Cg?e{WSK!;`3i|peYy^Ke>+m0!E;`07QS&j+KE;+@gN28&$`51;tKCkzAJPlX>IW0;&Fd3-U$_SvOu5;XN4 zl)DK`1KpY!e+0Gq9(-?>@3|NG!@2heryR*8rETuq#e5Crjv~{~;EPR9yO}$830Gu8 z@voMhl;$5XC2V1kA(bAY?=3^+IT3-S1yYnT4v_v~ejpu3N|2Oa=X$)LEvMVFXZVCk%BM!V}yJXI8^!ThI?v=l@X&6#(@g61ar_f zi4L59i!=h4iOPW+N+YfdC!-)hCNA~Vz}a$}Xf{{Y?57eXh&EgbBtj7w)(tm`MGE?c zxkL`}ZHubS5w$R z3NW#x2#;8cvY_rMI9iQD)DqFc zWA2a>pCe4VcDgveg?Sj3~34?M%KONWzZI6GP$-iw{B<+c> ze(bN(sH?Qo%-xUfl$$=ed6(Q|NEL#0b?EcW1=W=&RFPjCP*$?p{U0eNIh7$0@JK!J{7%!M`0udXSH)S z*qFkj1(Wz{{xol{$!YB>aqMwLG#`q8oYX%xi@9;Cm_Vn5%DbnJhrPKW1OZwA9v(C- zvI~e^Vvt%P@)9IX=r>ne@q81zPOCu8fH5m}rP7DvD@QGuGV33Jm zU1s^V4CS!W{Z|ORv+o!x?_DYU0$`Tol?U$i$-!E_VfrYD znQ7lFazHF8e!Ig^=f&rW3h?^p3QA1WyNevzk zmO3&LC5P1k;c7We0gO2SFd>1>7#orUala(j5BQ07O|Rd!>1PY!4XgEAaE>R$5=P)9 zZ0|qb8-i|r{r|9pjA*PLQHm%Z-(y62JZy}1F;~x!@k}$zw@;q}FMPwrjHhye*>6Gq zf(kVz^t@raa2R6}I^(yN1qC%W1mf#<2gAfQRWPjiR0S{>y>35Dpq1cXP!Vuy`zkrk zgH{Wbuwel-Uv7r2cS7-HVdAkWhYdWDjNg^{&7`*ZsO-If^|kR_Ihi8+)$r7Mj{9OU z2XBRs^P2#b19@|r zjKC0bwQD@fLeUXO!EI0q?v{NE(?+V*5kqon4&cx?@!P^dM2P9dx|~tp(|P2xMDuimYafi~B458uz775WSeA`MQIFO!lK(2Ej2SQSvLLf2xRAA zz>{m{N|_0a7IwhTn~?i}pViLkj6o_270SV;taA=iBXng&*t9G;%#1%&%UhcNXy#j* zVqlnS&ogaRuPtn=3XpIi#c&~|!i8LJx?Bh*97)&RgA0-NX0^K<$R0uud*MLPLH5Rh z$Y>M?LN-3lg3vEo7U4jS^=5D&pI?*YK-LKlp~A0r$br1ZW6t#lD-HxTr=uB=C)DC{ zZqkK^?|^dMO)wy0vvt-(aaG7tCDZ7Y|Hz3KzV%@`|8f5ZeeoY+PcjK5g7kz)nFjP>$n%|VCU%nk{Qqmc;W|_6y}#PW~}#ruS%}>Cvqz8e7)b} zF=rmO2RP2udcSm%Y-YXQgZR#Re{y4Dy&Wj^PS^XN@29W#6Yur0-U9DzX9YGyA{X_DnQtcV;v;g~l?9>IS>8zI5nt-d_t6ATe^j6vHVecy4wWmwV;8Ego~~4^(qn zn1;XL`jyjA^1&|em(hR6Mpw-!n=li7QuR?_>qK?cI5dr!U0|YZuHZ7PsM=SRLr-Yr zC#GAQ^Rbp1d&xH1<3=Z@s4_=BO)NzF{x4guM3?;|8 z{88x)+q*EAEinkPcxw5Ftv2dz=DzXVy2|J{51H- zYvwr~qv5q&rO=UXrUg_M8t=hUH`ygG zUp+5Mv4YVzKwgd!P+A;5$pzB-dABs<+|QIcFR7t#=s?|=G&)Dy`4y(PFdqxX?L#s2 z5Fr{h!N4nWFf175Yitmm<$_Uz8XG?1OD!3Y?r3g|HuF7yB@8S&zw_C45$w34-g4&s zcT;@9Zw&Ti=S>0PJdFBEOa}_%DN@W^T8Gv7hcc9Vs%mavsi@enEKlZD@ok*-v6tZY zYYH0p#1X9ij3yc;+ZJw@-=n#V%i}eh6p@O)B=>aJVq(ab-fxwGz;N|9ezU(%X7^pC z)m_)&2{1D~udos9Zj7#BG@#4J5wz-_i18Axe6O0(m;8D3rVP{4j#~BaH$my=iKf%^ zG>5G@O{N`{xtP|3r3<10pvDQ!3!(y`#tAJ86m%LVEEDEz!b-DkYXmucP5UD^1U^c1$9mzjmFCq@!r=wa5ielPayF6ZIzHpNl!orauThaK_z zkmm;s;Mz9^|47riU#q$kC3^1`*x3r{OuI?Vr>$WU7v*oMhE2m1e!DPhm?|$=4Kw%v zBN}Su=hjvpt~DCIp+qv1kk`c}ATFbhMyI(yyVN8a8s%s7*_ASETo&=PQ~mK7m9{Cm zEo~EJ*+Ki`+xg#^=5!?3;yke(B+&R~Mi;fC3kfWpp;l;{a~tlZVMB|OI zwRPL(%-OFp8j1(%ww-yy=@H}MmDinIwz}ry&g189i}TW)edcbH=c_-RyG`x7{W?3i zL%YVUb!e!#3P7tlz?aJAh{wrvHh*uXWZDad$)M~}ewa;Cp99Q+uhLSEnTu9NeDLpB zR++!7dLOiw*e&tqeiNN^Y#slzL*KK@%8*b{eUDySx7}~de_z!2(WpQj;5X5Zvso>y zS_tz6uvz|UDb_8Il&>}#jt1$iU=u!@4Mz(F(yy8J%|5{ae6{RGwV^Gwf9=|7j8{`v z)eWTI8N81?*`Rt&b|FgRhPSYgeA`e?OPuOs1@5+5BL)tdF4Y&Rq$BYeJxh(=1h12mhQMTf3GIwh?>EfQ18U|YU=L)!?-{a{0Zm{z58Df-o||%z z4N$Pj2nL42(Sa)icmhNVVnZ-MYSml3BVu31Qvnk8pS*&iW99!r*AR&wyTYiiq3ZxO zbKH5OFfrzR$|5mvnR2Cl^3tGCs~4FfXZCqR^AN8qhk6%8C0k(FR?rB&)e*L%?E(dR z(Rx0N=b{21JhzWVb#P2*z?+c)Ka{PKV4*`OZeo_V-EcWoO%~j8hT8k_w!pC0s$&7` zwa!7JbTh{+xUW#|grYZkMj6lDQmAM!YNYbDM%|GNFJvFIDuiyK<8Y zD%(3BP#@v)udDBfISe3TeHI%iz|B}3Cm=LfuS})=tU}IAOnL!Qkq(iqYWHY}SSK%q z{wkCiet!jnBtdjEDqm0&pIHhAe$Ja>Qg1N1WR19+f&-9Rc|P_x&WZ?0B4sH^c0Dgr zz9|yDeCYQ^{TFO8SqAH+KP%i=)Fkc6VuV!Ji|&@+cEb`r?14*xyWm}@eC72+6fT%N z#S$#!VxWA4Wz_$c*~3AYw1)D-sC$<$Vz#mu$uri71(jCbQe~1-Et$igoyPT=flNid zI1e1C`coK)qX6|GtPyA^Zpug1!O@`*H8uj!Vr5kG!OA#~LOW*p4@SM8*$_1YmsQuA zCr1su_9l2aQ?MvUv{9z<hm3gv%MT zbS^^uAKOTjLO^_j>_v(~f&N2uh}51X?Z)G<;2-Z9n7diEHDHbOk=aTF26&J(ben2u zCPRS1&FDxT`C{MR!RTgC&v-syb;~P%Sdk3W3V$|J)M^5VHaJi!G#=MmZ#cQX42awc8Mc)Yuvo>l`!Z}fRhh7Qi z7W#;gk>y^+jtHCcQEctEbfUbRxmo+7m@tr5uRa!OjD@5t5kW(ED2Jjm!LypC7sMm_ zYx5D21VU{dmWG|Hm|mw*Q$9JfVO8_l4t7+2IJdqmNqgt65UyQRo5}pw!LoSlm;Vt8 zqv;4GxMgkfz_~ zZTtN1*%#7!C^}>C3qO+9nL|Z>fU2aSwjAjoc9MQxXdeQp%i|c0j{T+N< zkNdK!f`ogKQGcvpQuO5exq&Wi{%c9yN;e+F@xt?0b3u;hcVr4ygTrHx&kp&p@0YWM zR#)<&T2)7mwE7=){+;{*H)ypiyVaaTtGDV_)q9p|2j~jsx@==&o?kiVcEMTJy)3+A zPW6GD)@h0}XXozPDwsV%aNvu{>EwYtbZybBfvnGrb|buT7BDOq%yfaN^Mp7p(FT zZBU1e)zGDWc~37CST}U*U$3hqG?IzLvy>~`Nz*xLUK`!HkIPtv3*VH;^Z^4%^e_Au z?C6;=sz>n2E|_xzEGZ|dQNM_G_|9QvG)(>m*0Nq*5Wl@SQ@K$AgsS6-wR14PU?-{v%4a{W z{zJB}a;4)vHiO>5DBi4bz8Lu{``ia7%1##j7F+lj>628pteN*|qOjp?;-tm3ml>n8TGr)3ec=%q0Mz|Cxfa#eE>tgWa~|Sa=S{qIxAc97{JNT7 z=eW1)K=PV-{WDyB(({*j+O@`Wk?Jy&Ux%1g+elTE9)lZe9c!ZX^ESb~~!k5;YNRO#N5 z#99KRvg4yN>IoDlJp`5H>P%Y3!qvSb(jq>Q@xt{qt5A_GDRN`H@PSu*>nIgZ-pBa$ zdFzM_D1HQ4!%VNI)7SW9{?2-^;eUExi}{&n+~d!uC8kfpEUCZJ_PHvh$wv7b;!JH0 z5xrf$?E32n#58WU84-3h2sE+UW7ksW()%~TOytFlFbXZ7j;y&V9L-adKlFm|NBqqZ zYybIB{F+n6A6@B>g@1u3RL;_Zsy~5-h<=Zfl$8>mB=-J;fm)TazP5Cb%~#yxRoKw~ z$K0F1M^&DE{|N*Q8hU~nMT;6W)}Yn~rJ4Xr1|~40GZ+^vwl26K)mo_}fQk~BN#JA{ zYpvQvtGu;Up1SXdiV17PE$#ud2CRCtW*{bMc)x$Q<+0myjW{mq4*t(dD>PO53NQUJIC&z;|e3!1>c-Q16jz ziDHGc`r1<7iC&e4ESv=H*6NWtQR_M72hTdgKkwcK#1=5d1kG+6bL)wIE^XA$f966^Vrya9YqnWJuv+a$@6 zE zdy**OnB4D*(olS^oZQ31P~LX-LmW6UA%RQLlM*O}?d@r4Qpm=Pn`c&WEpX{0DSu&O z(|c1bDQT^Xxu>)7f!H~PT{m|jc9%&N8^h!41D5`Y?TUW*rKG0m{c%p!C6{#-FaIsa zhW8(}6X|=QWQF!+`4VAN-Pg+>FonLCQ>eSu6lzHqYBPoMa|%7DLi5&ikR=;wv!#iN z%eQ7kxn@UmPj-bl7e6i!#U7eWMPKCoF+uw+Kkn17eiWSd6*HJSYakzad8K(X4-G7Z z(A2*MS!1jn&y7{e=-nrmQZfCFu^}x4Ui}~tM?M2vKdb}R*;;TnHN*DSQ0$UY3}Fn> z6Uujd=HfG5cCs#5^Rr*KeZYR@zZ0@M@mPls3fk9}2m3co(d4RntjHZSB};$TSB*m% zv_q>gA!rh6%C9>L(M*HNwtmnb&2lwc|4Up{X6_w$0y&qU`h7!+>Ix#H7>wmFx%fqo}+-3Y=OrnG)fQ?5EF&B$u zpkMTpecgcOKgt!Q)j7=(z{ptCIatSF&x=?a<^R=19swV)`;!G{v6voB zTmxgvy!8Mx!crPrb|g8@_9SzZLYZ;z#<->6s3e@AP$tJ(=4xF^1`7g;Jfusx4ZIy- z>>LfUaHg_q9xl=!8k;7YhF0f5y|O2R3cTgw1O72Vt%@gm~ zPI!{>cEP-0)f@Gn(taN1E#$W#mB4+T%@5fZEe*%+Dbr~Q+yC&}pC#9YTI#Ko7H9TuZ zwAWa8X$|#=L%el&7`;iI7@+9}xQEK&st>FtvERf=>+r!YPly#QuCa?2jSsIdzc zao$2zpVqeqV>i_*3Av*yXn}0SaNDesjD3)SA7_?I(MdwFq4*%KNAGxqY3vimjOcR_ zQjjCU2R#=Y_*}>yx)!sYU~*mkv&gT)9Kr{Qbx_Umt>fkINtJXoHdZv>EZ`5!;EEQF zwMoDvv#O;YoA7H|OoYJQp9atC{$OQ0lO?b5HW_)m)$@a7$={#y^1^l}2V-_N&(HO~ zgtG2c)*v>mR{<>fYFff}Y3^POSUFhd)3rpne?RTZpq?MIFK}IX&N&=T^F|uy_IwVq zfP7DmP~u&3NjnNmz+i=ozWSQv=iTI8&6#g?9Hog6aCreL|K!~-g(F`y^0$qCDRo-xqc|Ex{;|1QZ4F$B}-m-qOT^??*aAEo(nXDJYB|UQUFCu5n9Tc zw6W#N9p}HokEG^L`#;WVAAmii&yl7Pu0|@F-L*OQ19(UJ?UqpN2AE#Na~$1^%z?YX z;ZGp;kdT-^Hnb@aTUID^Q}xcw%5c>Nt4XI9+tN<{jIS!VrT*Y7xsb8-ID8+$kc)gJ z%IdmUageYcd((>iir+roFL&!tunT@|k8Uz|qUnWx+tvK2hg$ekcRb{VNU|VKcf=k7 zITuf~L&dJl*)5qxUFgA%#k8+QHRNV|zFLvTwjqDQ_Dg<(IlKzZ?6X01SO9;pY`(8bgGicFaJQ=Z?OFS%tA!wQWxjg^uRh0{%B~0IS}7oo>_MtD8fybHGLft9|UcA-V+7%RrkS z5!ju(Oe;39%~j4E0!bgPdeK@SW&#RxZ1bXHhX`DfYpN?>s{5P$Qddcsn`uEK`D2@( zIzgG?_$(=DLMPOQh{sd)@{H->SlM$tEr~HH+L@qT@Z5v>G}iS8^Cwufs_xg>Ak?2F zeP(Yh&p70drIfT-l%AdDNYvUdx?Rm)V-}NE5=8Yk&_2!-|nj^KIX`0Y4 zm$mszHD7M#rVnX{-w*IRR)9vb?qGp%dR3uuQs9MCs_P-R(r>R0Vt?%shC%x^XNw+Z zkL?9QA4seJB`vq--&t!BLNtUC&?8 zQhcF4ASC}GDr(n9)+edr)H6Dy{3(Ejk|z@tVw$m7DA2$nUk;velnBbt zoaPRX2y4?)_KFeVi8S1Exz{o1Lw}Mg{yPU^W0zFOuE`c zyTd${l}5GZ!h=TI>2@R0H!VQG)3Y`WB)S=;RF=lrTpsS*-pqNHZ$){>`=~p|gzQ=HQN&0|%ku>MZfru- zL|re#qg{S80*=k=zf5{U&<)PR{BYri4J{4Yxar~$E4&@qGzLbZ2LFv$H-}?Bd^t}k z_k8uM+Gm^)ta@d};o;cOmXl&5+6m;*a4j-D79Vt& z0dJ|g)KuYFDW{<<`HhJMi9f7Fc|TIY$hF1T=JTgK55M!sn(B<0E75NS6F4C+8sLEH|r{@wZTv26&2-y@QB_S}69z1F47OdH4MT@?sOZ@sF!3 ziS+DJR~+ftl_(97wWWG5^1ZJ80w#LMCjq_D$i-`hz#ENkc5T!urU(twqk$(wsdB@Z zv&aJ(a?Qk1f|w6gdG&)0B)GT7*@i;F{+A(p?RNLhhOs!A0is03IlhLkljBFuoEV$) zN#TjHpM65ZAL}_8T{n{H9Vg?vK=Ot9zXPe*d3|Eu0U6BuAE_=tdGe%Bt_fD*JF>0* zfrJcAjHpv)<$>6bfL9ZBr`7r7Pm);hqicz`p6U2&P)I+6O!DHdA?FIkt|;}}p9kmZ z5skUl0^P_GXyVdP6Dxi~Xbn%=Cr0s6W8LxcjLV4@h7ahEri4b#Dz5ucfDnM39Egws zFq_@p+kV#IP+_q(xS){na*|5H1S}w=4F)6wLj7k=30AF{HG}IcV8mSX(IDBGCo{u* zS@75PG*Mx1U)Dmd-@4<}Z@Xni>QZWF-FGhLr}yPJJJ1*_jhd^Nl?;K4B4q5hAZrU%f zT*O!0dF>VCmY7jOu}4-_nu90d)EM(poxhCb9u!$*%xzB(2@$1Z7L3O$(FX@-Ts7^%(_r95lzAj;PARGuVcEmh^dmYc zU9ht2o!yj5c#%--q>5ncrpnOnCsp$3_>hp~G5w7rR)u5V3&&;_PPKl{T1{#B%$nZ95>D^-*9`x7 zsx>n?JQ+S{>*o`!%L_&;#3qI6)+o#?m~ae%T33hgZ#*a!BR4pzZdG^v{&*a&3dBxx znr>@YeJ7~A1I(SQv7Zl%QEuk~K^0XRid_lePaN7WK-ld>f@*WNg2OqqT#LmV zhNpm3#dTHa;MhKLOF|B`bjRHrPWaoIyh>Bk9*)m0W);EnZJ~pnBRJ~i1^Z?1WHWigb9{$YJ`Tyw#G(H6^IL}nTOs3&!Y4&sc5mrht% zv>)+^b|V4>z^+rVX24kP^L`+plR+$B5{`84$;H8~8==O361M#-fK(Q%#=dYx&$o5W z6)7kaCv-denivic7(fce&TdKQ`qS3*r`3gqKFVB{9HX@UkFY2e0G<=OU6<4H zfY7DU@YV8_Eb-q3GEU!1-?@`tv8HmeO!s>PV%O;hJ)xORZ2do;j=L8#MSu8jiH@sG zQ9Ev&d^EIys^K%Mq3n1uc1zs^>>Q0AB3bgBy7EXw04-Va`#+NaHra>AaC$rf{|o1p z7mRdMcXRqOJ9{PeKUvk0Yf{%$T(8fKCu#;Ixh2%^nW-wkKTPbw)Dfj2R@;kD7R!$i zcMP(&U)}DJo`O1$0N^q!&a3+z6$=;no~c%J)kfTK2ygzWcQ^!h{bvW3)?YMZ`bC#r zJ|i%^Ex7Em%P;)-c~@M1VG#YvljmJ=(a$fs_{yIJhd&p1X2wNzSDt_2MRkGU5P}3m zg0u=jTZL>KQS57n;GtiN|9g2bUR!LUE|2G89AC{=vWB1HYU>m|;NFQp$hs3hb++8U z9z-(HyALOFAJSfIqV7a#%k$eqa&T&0G05C~+=8ve=I(1L4d%Bi>_F>^!J*+wFLCe6 z))4cU*R4B|+UD+CF(_b45LKncz5BRBR}7}MS2MtUsEhVLEpP5sw{6|g;z4zNx3jdm zl~E&Pfn_gxMR-K4Zn-FkQoxZV-C*MDUy2OQP~|&`udm?xz-iDLi^;SXU4P~ejXE?P zR9`VsCR>raI4L`cte<#}yl;zweylu&#z81@jX(hXccY-c+s4aVbceF9X87O2_IpTk z#*HjG%9?j4iSRlf^9Ks7pgLrK9vB8;c&WohZElaz)x<#G?hpfgd$(a|WLr?~9A)TO zi44~D9Rs}rjJRVA^s%Id?L@Gz80aH)H*ysQkFyQ>3HtD_c}3O~QUE=GSDSNbN~jOHSGZ|kejFJA`o zVZ(bo`h|cdD;%O?tjLDIdt?labq`E-Ew{Z1v~JOud9ESG@My+;u3;U~3-%!Z|L;gd zOnT7zVDbe+bD8HF+6cD456?C13cA85gD9?wpHdkd1~%EO-=_-Vs|h6#)cd)_?@?Fs z(CR1h6IzT(S&fIXtH$OhIE=_yCwSX=3Y_nJQcBP$Nbg)Nn%v;; zlssKGFXTf#{ilrmjAR@cqcAyQx>*G1Pp?y_Z|iG%wq$Be9EI zW?=nb!r-CM2(S{h-Of?JMo|D4ob(^m>9bcUbmEGxL)<~~)I(=*-kJu+C?>}@j~N2F zo9U$M4gh8*|E)eugExAUXfZryD>2IX6de;xL`<6TLvOoD2Q)sSQ? zQ;e_wfZ+?bfy$Vvk-Zz`hJIGF2wSiNSE{V})Ste+vGP^QG}o#`d{Er8tAo zvv&&iO@K26MUfhIMPkikZ@S`fPd`yD!BUL)Mk)PD9Aj&DxlE9Il%&Yu3l~m6zoLc7 zTQdRu3TQE_nfle{O%@s?Ryp^taymzUgnh^WL#L z>Cf;U68;aAf~3N=>AKj_r4cd%fuCG*vb{_N0Z#?BA;8lEbf4>0G~@8)a1wJgFX0dF>j zV?P~Yf?ig=KJ&n}J|kcq-ePp9s+l7r383{97l)<6H2&1+t()$^upS<8>Ig=@EcGof zRcH3CMj}TDqR+$j^dY*xh!rrDtY3~2C*4SblnY1+#-1wE7zHWMb+8xcCUKj^ zDD6gwq52cJTJnvI**t7uY@EQd^3r8mubgQ6Ux(CL7d~hmzIFe7E+AeBSP`uH z?21lZ+yP#xZfp^yS}D?CIVAu%%J zp?bsU%H6E!hy0{QsTDm$LsPqihpJT3=wMQ)Xf>`@9ci}9)0O8`CMj``Tf5qd{+$sf zZd4Qf-4zdva`(iF+=hi-YO&DyVTkbdy!W&$R`hNb%UuqCX-CLDt8AJt@@_xh%U!<0 zl~&`UfFrpfth=Yx9q6|^cD68!DCpa=vas$uH6w5I7HhU!nFS$-*MM$ZsWzjt7@}#A z)KaU_<|kj(RwFw3Jl?jj79I{L`mAN|7FzRP1dQi>Et?}N@=v}^G&5&dAkvnv=?M>T zC}KC7lN_>-dYcwI!# z6EZG~E#q8k_HM_!xgtL6sdi$EhpKKgD8^^~ro~s<=4v zy`HzMlr|yJ+aq5bI13Wv6|6>QZ4S0}9o{gfYyyxqLeK;D!O)Yi77yivcrNs_9Y==k z4N-sDc&qVE?Qa>xGr+=X{h0=L=u|-KI5WjRxA1nKf8#&ZklsXqZOUWVww~A zB9wmOZ6?NhTAZoNNKc%vd9s}q8f&fW&4)2?v#kd4nyuzlgQF6Sg7ch`@0jxjI?gU> zHBO@-BRJA$uiOF_B#z2pjErmS4P1)C+8oF0f%KE&1;`z5bT2u%8W$VD|Eo^0dtnu= zL=j*`ujZT}&X~kXV_HGMZW4G!Yb6A;75%Ax5L~zMdD;vnpAC;9ZdgRujSxK1=L(;( zuDhO4{fWCt)1}lnlHnvK@IMcYr*L)EN^8EJl(IW~&BnMut^oZFdY4&&>HB=scd!&C zV`~QMavZGay^Jp$n}(zJY|L|BsoPx$mLLmTSr5Cr-3j8Ue$$F*yVdv}DJpT8i-Jpo z@v%wcXmBX4`eRj9Fx?Q{>$d&-Dz zu@)Xil6!b&aQIS(=Qn%@QBQL;-7{p6O$ZbrWJ9RT83TjyQ+ZP5^wpr1Hf@x_9mCpZ z&cLSMYW$i8LiR=^y)GgVYmeX@BSx2eaE^NnMMLW+yU8{^PMe(0H387o_1eZX0twn1 zXC5rrn=CQi!x&WUwRUMKMN~Y}bKtB2Qfa>rdPqDCy!vQeH?I$@Sf_!irWM_l{SCwy zm9h#8A|DrI_!B63rV=^b3zDl$EYW$Qb zB<>YZH_%yhvwqIuCoJ36eT7ow#reEa;Y;u~*@yxtvki$UAib;=1bFgn9>L1*@961I zQxFM&8%8>DBI6ObMHY}ZuGwFb1+RE7CKFS%Rl4n>d$>cWOAR3!)DXU6#vA}E>Z4#9 z`X|zw0%r^`#6a{=@(kX3OcDxpwMWY&)a)6S9XOS+w}8NJ&M2=fbU z9@!96|08BKj`$oU;;lB3!8Xy<8EUGXahs;bXE*gwc2oCfHFaNhQ#YrYYTR8-U8l9o z!IZDljC;S5oQp1_mB3me$*Sa5nGcz;vnm5rMKEhcL`*Rywm_8E56pTs0da{fj0Ejj z^h*6e-LD^wKhqB!UkUk>_|QW_KhTOoV>Lcvz%q5SC#osSGVRtq(72PJcWrUre*R1E zUY1V>=*0krhyGnY!#$C9v)f5KorENn{32|llYGlD0&@FZQ!3}$h_(YMiLdQXLFIM>~$_wA^Y#far03kwy_BKtujNza|NMoNAy=`*SFjgD}z4DxB*w(IPT}hud8k^vWj;hGMv$T ztu&S*ri63&Ln%$V+dxX5RVmx*`KJPm*e}*i492UI#J$jysF4o~;OW+Jqs-hF*Agpo zHH8{R=eJygJtU5?ZL<me`dJS7qzsK;F>dG}R zGz`kKbs=Q9wVap#EPDkjJi6tIw?=o)xWEmmhpkY*E1vJVg4AaiM|jw}(VbT0PRcE% zAJ{~)?+n>1&3isC1@j5gQHKOUntjEzcjjBf%R7PV`z=Znvc+Mmiuu+N}kXMa{Vuo9o05k5(&VxPHcvL0~9_<Gg9Ueo1qsc# z6g|XPS>W1)+{V}ZUF)%x(H15%`}-)+&{NwOrmS?1W}w)00)DKSy(V!c<7(Zsi+|wD zcAJT?QL}KJk5JAG5&Se_PkcQY;pxIvd*-*kuK^D1ZuqkMirNVbZO?ubB<8XioMz)2 zxT0p@IzIz!1_{-GV5J~wH-WlaoJnn8(pk~Kw#2h^OSN5m13&fC@sC*;eir%3Qos%B zCa5cw0tQtFP>qyl(kW7@zVfU&*BeN5{;)O|ytCd{Gxm#>)sN)^;8yfGt&%|gI_|9D z8>OX;I0ZOycZB1!lRV~&k3h)CWVR6qeI^QnwlG9$)C~BYB5xTfZyrFo*0#`M2hp zGM5&)XQQ!+^2VMhy5P%*Q;@I+{Bri3+ zs*~Hcdk10RIJ(h?DCHfw=tZ1*kx%6fl?Vuh0yL>B_EZ;{LmaN^nYC|foU&)Wn#Od1 z8y}_y7^q@R;v9io!!`|Yr4E=YJ`YCL9h^15Rjfj4fG9|~1ySoIEJ_F!{8)c8YXRQ07K|q?aU1_juP_MY_eK5l>^0R5 zTk;c2$l}y^I0vXb&vb#<-rw90gwRtRP0pSJmYPbP#6fIn3KbYkaE!Jk2SZ(X`;JJ* zY7*VhH{yBF&FK^I7-x)ytqN~>AfYUab^`&7VKd&DIox_|&Tb&FO}j)s0ExYX#G(6& zbCHkj)-TezYis8otsm?{*@4>zw%RWlk7^Ja2i{(5yb(CyFJiQvjV`{o%AEUm_DW-d zy+}!8t2L}sYiH5GwTW(h8N4FUp{0AMqAQh0xdtsvSJxiig8mBHdWKuT!%IyjanN-n zI;X4zmzehr1G1K>PI>WyL~$$a46J2&*>N<(Fx=iF+r{QRQywGfw2H&s*5HX4`^q{c zfayw>eUWZ$S-Vu@Ro7`kFw{G|{};)Kta<+r0@CP*a)K6n_ChhdwM=kBj!(gAjU&{b zcT0%D9qEC`Z1opDTUUUBzQ7j?n2?4^H>4o|{6*l1Gm2;K2GVy9q+VBniD)3>6;xhX zmKnM90g_W3WzbI|J3{G&@R<-^6GNCa2IEEBabW3pMHNGN8@>P_bOtSfcZ?StNG6K5 z)*hVm1Id?CONIlo8%4pW*l-0$`TTBImr)aGEmQ9EAOtLBJDdqGf(DEY7nu!&MXTQh zYu)0m2B@M-FL2%CNBoz;{ARy;SvT=ExO3x>jnLa(=+ksK~VtWyA6`Mwlb&_eKXOm}MW$dwg<)>QybymyClCx=Y$IWDk1qrCq zUR)-G2K_elPcHp7eCk@vzRa8hap~!@9QM|XEoEG02lqe1HN&nwXQe4?nsI8Dq;ElE z?=|luX(v*4lE85-hXcfV6|M=FV6GWhJGPtzbTE?w7?f7v*}KHIHcwjtq_;V5wv!jD z2?UbW=sht?j9*<8FhnIK8gQl7mK50gbn#Mm{cE1jzl{~I-5=XPqZx7I-wztJ4dOe% z*?qom`>($=sLxba0HiVc@@QTCnPk?B<5-(E)i=}Nbf)LP<-4N7y!+X%$YH^?)x|I& z5IfaFm=zKl-fwnigwmB6MOM{fSRWtc^f0))b?SS^&!N*&j%zI=OI0a#&G>dUo}+q? zhc#^vvZv~O!AoX6Q%$+OAFSTLZ+hP$e$O}e-^+Eutj8g}`*%*g&H#R@(+V@?{kPKT z(iOe;!|M;3;tunb!tfj5$qg>i2TXCnV65F)&R@*cHkAejg1Ty!1nocpn<7+dK<#Hb z>Z$$zk3g-TruKHLc5{dIbhVzG=>GwDLnxZ(-1I^pJ3jrNjBu10VXt^iJKyg<^p!RC z3)o#7SA^$KO&n2z3v$4{{M0$m_5%vpb$Y}4 z{ZRZub+k#A+|MIgLG)YZgUwcK5v%bZjEb-m=6xZMZ3T8oBfQ?N$Y*5w7yhj5Fj0xs z=pYWugDND^P>Y{AA4}W-iG#(YkR)H#v7e#UsOq#D4-@$#qVhB6SPWuKreC?RMZ6_M ziPCh58k~sigmWLG3so^%t5H0cTN}^R8uD()eT7Bh}X zj03rPL%ACnMItC<%Zx%fuD|_3nTdx%&3^k!Gv8Dn9kDtjlw8=n-p1@)vgH-p+Cym!o*lra>sI2%BL1f5&M$D z#9>|*cu%XVaF22THXGm1PYL_SMTveC${^@o@VP|5Xuq*#?4J4cd--CMah;mBm%plO z#x()^h2+YvJ+sq(N}4bELNHbwmTFhyhf2{6Txkp}oXce!9ovO?kA?o&RHC@nA$5*F zWu(Tbkp;~o@r<$o2W14VPsqkZKe?k&mbnTkiG~ioQMWjr)(kO+Q}d%0_6Gn%X3P+L zTgEf^K@8f8+)hJ`y2$*vfgcQ4Lu7f-YooMrp1;k7w1B{(7HB)&3{0b}q$4wA)=$pU z<5M$aGz3O*hD%;oHK#04f3?s4sB1wW4xtr)#LN!}Txfg|RdG-pxRIH&L(D`E%w< zL}~R7I!dilW=cX!_Gv|IuSS@&y)t~P42`<5ti0}GpZz+vVpGDh4D?3EQ3Kj=ALw-Q z+~N80!3E?p1I$^yoB?v+vcS!6e`q!Sfu;5aV~+ybTr6&c~&>UL*_lLBC!O8kOVs={q(W>%>^Xe%@d7>_g&b$up-!$1!AoA{>*ww8TBb|yxxx%9q#d>zf6h)Mu2U@!fO2-#?(erx;{1#&O2}VYE^VCgYUf^}XeRDd3hRCP zj@UcqWqBvaen%Kq`dgK+rF>xqBll07t&D7lsozt3M+6A|l&bSKQ`LoVtxOh#y91n2 zl-P$dX#@=Az%}SAmumG!90EFdVc1v7TbVL!Xz>*yQS8Yl5*AN%@e=SL?9kwZh;Lfe zj!XA2Rp3D`U!izGJ=J&3+eT!K_muO;MKE5Et-!K_-FXE zv_Jk{Z@IGX_$_KB^DnzS!}@vciC}k5-g$d(ZFJi^{u|m8!ILw-Lm~+upWT*c-%u5*U3WOjIqWEeBthzVnL zBxQz*?~km_zTbbWFeBVob=eE<$Mu$y@Eeh)ID$G3u#s9gif!Dt2?V{GaHV;ASj4c zaF?L{b+Glla=io?jLa#JIYqv(eeBV0bw29RPX5#%w5IV~s`F66IsD;4fVh%T8V=Y1 zX)TI3Fz}twz`qk`+fjx+8ukZL*))Q-^SHP}4o+t{h3wPu6@d-_r5 zZa>VK*?mht$I%Z=6R$5`HYBtC>^)?xyJ+IUSv2ifAB(1B7Oi4Ei+1(Tg_|4ON%GrA zKHx5ws`nm6yoW@m=z6+_`_TH;X#J4s#_m=5(5QRAxx4ipbXSz=Zmd0Y3D4k!Y*QUz z*v>{7@Ua^OK8gE4bfMVOTAa|Rr#t!6$6S=mT!yOgF;J_)fnR%DIMF_`huC+3w%dY< zh+V%Q+w%Z*oca4wkrxM4-v!{{r7uno^p6XceM_gCc5l*@oMAU%GbsoDM_c%rhT=fH zrr2s4#flRLh@dS1^X7t3{$_XO@?9XM@m6P-As#9xu)MqY^~Ky2=o}KyLgF(Ftso=& zt^Q!RZxuJHoHaP#1q%r=9>`y40Ary6ez@n};8!Yimja92%hc$|BcBj&>6&6|{-J_d zcQV0C*Gvz@%$%74(Y#i0S6tEKTRM#%#VmgRMkIUaH@0?I4Ii7))h{-&=83?L@9K74 z+~V5>5ZK?dq~R9!636$J9+RkuM1C8oi`hXpxUoYT^3R`V&?fTF%LcgDU1p6I>o!HU z#cc{kb0hA-m1JQxF(tIDwQ^f-H!bgy({lUI=x4|7H_;)RW1baCmfWpE9%$^k5774_ zW`K;`E{2PbT^;^VB1K$7?3+^R4oIm#rA-$}5oog(1lW?H3+x-;r zFj@*&C^A2*$OreC;L$tCGcr`U8>GXNYk0#C?ET-1pWOThVbzAG4fd%&w2yVYPm7dZ zve}mo$lJ0qpFoE@E^aiZ~#`)H?yPs zXQ%5Wz;OaJ+3U>qZZb{47}4-F(YI65`hnP3sD&B_Xvf36r+ysn=e?zIFiMyP)U+9y zBv*mY8q5<1Yx9KeooP>+bDNUXO_P{8KIn!`fYBgegy`YD<&!CW!W52Ps#-bKre2>b zzn_=cj!OtTQWTB8~}7nJ8NF`j_uSrAL=YelZ#O zg>%a?BeKX`OFqNha5X)uEmV{o6Gsmw=15m9J2g4J)QZYbD-@er5sLl15+B-13S*k^ zaoy2j#8%*>?;ox4#*XjLK!YZpjTMd^mwerTW7zIaz6r%&iceYnCKH1Pc9a$f&uJHw z1u+;bbVb7cvSQyFf7uW&;PJY;X;O@tg0K;nfbS#iaYM3$vGjL?w(($WPIOy@-JYa7 zTLLE0{p6`@#}0K#seXWg=~o26+Ob14Cp>#`s~Hq}bs%Je;XOZf9_QYIsB^{)mSAo? z1m1YacNui-k|0Jd=x-vjiIQpW01@9cHk?x{jQa0i@9!V4V3cwl{##!3L;=1lLJTf1 z)VM^zv(f>So_deUPhzO*IG!bEklEY~(^g%bTf#3PnE|wMO7J5+5h?X^epWQh9)dDA zMlodZW+(CJ0{#)41??c08|uelD3*vD?Dps&8D%H-i7DpaXZ7ESO)O?d?30jY9Mcuw zk@r&2yu=ldb80idb0->qfOw*R6_)@n1s=U&gGCZ@EVL{QcN>#|$Kh_s>E@3cA^F<7 za;bmMzbzI2$c?8$oC~9`eE~-iW(&-t%ne%Ohylxlu$qDJm5)SKYcSF-)7BX%`_~ca zae&nA4Ob1xuOC*^{NsJcA3gM>@y(%=@@tMhaX*YW{PsKk!k1vvR)q84s3}|z+NfI= ztlDBl4$@g*X%I|o1GJsTx&AXS8LZmXY7}srv6wrykP2orkkbPi=H&OV{6%U6*+<31 z_y|JTxB9HdcUj}>$)9Tbc(SKxMliCbUy!JX(YTsom&=0)O4-V{1Fi2B1R^gC;@Lz* z7udTTRnvSecI^k$9j`7qEpw*5kMeHXCocIqXWEuE{%PCu5!_Bo`WKF##^X>yY{VbxKA?4X-nqZ` z0Mqgd|Ff>V;RWm>Q*G(*H;qrH!HMnAX72dr>n_176VPH!j45JT?Zcd~s;hv2_H}8c%2n^R5~1d==Vf6&6-6 zoKsk2c$b;Q7=N)+26Gd_Z}`TpPdJXZtkpz6bq--Wx|VaOP9cFqaw&h7?WY-?`Nym! zaK~$GtIDz8GQqMRrxajS9f;KtrvhiT`PZA2(fCFkS9e+L9%Dl8Z+6|){LPP)HIPq$ zLSx7f=zlJEZ+B=|%S@h}JE_nBry}XMI1es(KZ*X3Fyls#_@bvrBqqYZHtCwh+9Spi zQ0f+TqjHw`%#2u|mCjN0BNL@7nH<-{VVar@;*4$VHS7cv9qH}#)pux`z4uplV+v-> z{@#6WZLw1J+gt6Den0`TnY>ShIs=W#=xjcSv1LtxYibw^iQ zkFEA*%iAKGO3|9KYs}Wfg)G?S#@*MHOWi3$DV9{OFM&*9M~f zbN1!|zd8@@zRf(&-Lun)w?*W|O5~kW{LKW+@Hb--Ygjn>W7vDOj9++qOTqYsp_cUN z*oCHrEhf-9>-xcJv##2*ANK06m%K})Lq^_JQ!QZ^$Q46D@K5a2V$Cl`;I!Dp%HY#l zd;TFaA#h^U5G7EVM3IKF~48ekO{6k5fKvo|dKfHkaUvDj8W2OL`W z0SNO7ViqkXz0^H5Ac?TO$&rgE1s2C9EeTaQ@`$6ws+X?#qn`B}n`&GBeUa8qM`$u+ zAJJ6;`*%-Yq+p6BO206}Nosk`oTN?saj&7j{|VSoc$Ce}sQSQ9r3^d;zgkbH>o4C7zi&0>z^{v&O0CCz`)=_K$zS8+1(}0@&{C`e z2eMaZ0=N6hClML4J-Wj@3rU*b6Wb!;mp26}FFJQf&H-e;E-ae)*9$&G$YkK7v4IhL zAc9sgNVFp2cTMAQM%?hX)P+Owq2~SyEIss)gQI`D^|R+-=9fN98+rVPky>cag5dC0 z0;{(17PSL#f*Q9mlJKO>ai8K|0Gj0lkd!Mp?thrd$O?0>nyKhpndLH)7% z9-!|5^@rEQ3SRb)DtNUX2woB3d4@N5m>q3yhO{H{NMbvq#|Uvv&0JO@93bivR0im< z+v#RFfb3+~j-q-9W@mwHM$)U&rmJBup()8_(qxoBRxi69t8qRZkTp#Y)7mvt2$%^1 zAgK8Zr2DPM=ay=!VCT{kBcn@^ZwF#mGxO(@B@djH20`L9UG)XS}=Z1N|qC}Yj|HliVCKy!9^eePpMrZo$ z=%X2g?4SKuqdI%KJNrQ!!9~tYuuzu;4t&&Lrftq`e-I!2E%JqiYv$(FADHf)*!0Vp zqhT-!O*Nf&{pe~(F~+}ho~M{M8ZORlwt{9EJ;JwM@(_-R!3?Q*8!kc@l1jAQW+8QZ?18Km#9+ocH)t1YxN!j5gEeBrjz+9o>Vag*{%2+Y6q(NZKO%nV@63@Wp17vEre+^j4=rq))33o3 zCVt!fgE^&0g_Vuv!}i}yC+ zi%;_IrqpAn(AG22@*V#w{Sct|PiG)rvR?>BuIB@6#z-+FGtftN02~-c^kA$K`?6cMAgfU*gH+ zd~Y*5jcB9P8azB;V-{j7Fq*HFrzy)FdnTDU?VJMj*lrag?ST5h<+&JzHLuFoVuj3K zXd`?46zHUBQtIvE1@47ly# z2!rW)A2sNN#P2CHe={MTv4BPJXHV)@z{7BhbNfgArScqA(_+oLO;tF*&Td^BIQ#@Z zi=D^{O=NNVS;Z%E_Fda<){OJ2hGpVP?f9e?1=?9VR#zOYk45W;oH}xM|2%NVV(h{n zP-oU)U!gTP2&=4@qVt?PK2$fDm76XYL2LBuoCrm{aH4JiYKR zO>(Lf=JJ|u19LJY?7B)g)1__|v$;aclPtM2t2Xne>QZfL*M{po`MbBi3U7H;sw|5I zt{j&dx>|DWn|qITpzbN>;FlSC$>{9b8h{Melc&gFy@4K?gY41W-BfQy+2xZZuT#=& zYbpq-yFRsApNvH{d^|5-0y-Vohk$5!FKca0x7$46!$VT$KvcC8*q-Nv0+HEl&kvI& zw` zoWrys(#oawLVtIpPl~-*d0-yFSpCijl%rW?2$cRz>YE9a+BAW3U$W#YihFntxN<{o zd(;^x^|5eo0%hm$!WAMspx}!fv9%r<3fyw!oIq7g2ehF%@lGKA;9^$Jks*a3;I9UQ zhLUhktny$jdLR)82tczEA`9u%c>lnx8sdOBH>fe*c=h2Vxgal0y2YE*RN?xp~ z`+`s6M^TIbX;xImpNSuG?-{V$$@sfmqMq6T+Pb!g2_O1AMMB7 z`)h@+-jX>iYI=>$vas1>PTJ}H70NE3EGeO6PQT`+;1#5`TESj*3j(w4BWuhI}>)=-$!Pe-rgol9;IYXf8KgZtw%Uh zxP3j6@_4EeOmMPf9(9r>cVyB8BkpmUN>*xT+`le8kNkHW^5101Wx2HsF+V)JQeW$v zIZxLboKl`@Bzuj!#`k%izM}Co{z;asrc};+`|8i#&p(>=eJZns@V=@QZ%S zPpDEGX;O8ee_?I0e_>!Sk0^}YgZ~ZMA9A1PL)!SRC1K;sQ>}OS(Y0=>b!}h|@fQ*} z%=<_(qb!DaieZb)Ba9f)I}1#1c(FL1tN9i&)F1V)adej83ylYu;}i2bwhaCvD`z9W zU2J{_jL|#1s`@~RpzFIgz3NImppcAQNnMtu=p$1j12e*J^FC@Z14{GnmFeNWL|xCT z*p0G*_}oY|u(d@#0+U^iH}b{vBt8ib;qxqg#%j32H9a3vk{a0ZaIsZ9sni;F3jbk` zGAv&+_F;GAt1hH#x5WTSleHvE&1k&oYWnk5X@HvQ^|}0BdV2q?-iotP3e)wm9_|h6 zmY2BToB3hsPiPUtCMXx~s+rZilTedEU+PJG@%!UE@J{o^p1dg#`@IYq16x-z@CGk* zke+UNkvUh8mZ#VWKWNapO=PP#IEUyv_Dk7F!T!qo-1RSzyTA~5Bzc_|zKqj(OIQC` z^;gJ}pv`_cO~nb#Qq>x;#k%8mwKN5eI6dTq8w8P+|dJQdLwHpxp)}3Bu|M( zSv1?@#rC8mQR^Nu+OsbHER*cddC)e>#>1aS@`GJZsTSm z6vL0RfxNxxE2TE`!|TCj=<$*%lyi=W7{QT|U%QKhSke_57?qP$KCBLo_n7w>V_MM( zKMBT8ris1K3a-Gs^_994r6~2srhg?HkSSz z6E87B-Cq8r;xf`_PFzV%4>xdOy{OC{r|o#ppPiML(mb0(=_St>@tK7;irs_ATWOCj z)QDqGH>g0YU&B&G&&{j5vbuSxG^=t2EmsWt(m?#|ZY)QF_Un4##ts)c!^m$KrLxgv z-38$A9>3)1@ft+%)S1GxXBUTvjccsRs&2puu}GH)DT%zuHfJ$`!7Zd$^?!gf68AYL1v4Y6HinV+3@D^T<49HtpFC4VcLco5c%;E3Cv&zmD zs);T-Ozrzs;;FJ8a`Z^YO-MNXWz~A<_NJETbM==T>_+;nKQ9=&xrM%hvFkK-W0gf* zG~Qvg=KmC42hn=}VE@~M$b%Tm1VuAnENf%xIs&spEUnCiLshG- z=&^^Qs*PR43jIdNHAJkvrjs?#$m)VXY(aoDo&}i8D+F!67(*H~&o;8Gc_86rr#x3@ zcRi*s$JH}Gb4RA(6VwI!MmdMAvzlhpoHi~tbRlv4pGR$e?KBo)3a=Fqei}J*sB9YV zuHj5jtpTtqL-`2uctg1VwUg7UyeoX=j;oAiQhIr#idUpTOaqm!HtWFh36OccQX62Z zV|wS0U06}DrJy3e?qKD5$@JMn;1%ie)~e=y2ox_Ognli zw`#N1^b50XO~PE^Sd&m&O{{2PICir+H5lgXttdTBODPtP-PS<8oO+spVv^xX*z&iio^@rW0=Ga z*nMGfUhsmwuIGi?B%Y2_3W%dw&22VlZ!!=+dRxX`;lwzEnI(ijRWLT4ovPD1>_bX0 zHgsz^_VeQKsH3dt>AZGX>-*S7ZZD`i2^cGMNxNZ)j*E^#n)VfMaqx0rK{y`^+tvbXZLyvm z9~(Mv+*<#yzM{jt3HH!m1tTk%Y+KM?8P0#TzLN-9L0)MxaNxH$d7xmn;-@~Q_c`Rf zwr#;iekm506<@>b0!bp@t(f&*qI*|p37~|Da#XX;bT0Xc>&b)U^jY&ek;;v zZZ`@e9z8>O3v=?C3kpXrXvl{cZ#-CyA7dKN9bn0es|G4oXvm$z?}3EGy*aHA<&}w) z+?iAE1Fg+18kt*9VI&j($J7%NCp4M6mb_}iu2~CyO;$p$1bXF{sC6uU;0#^hzfPbXFiQ({YD}oaXQR(r3-_Qi=e}q9G5R%D^kgcU5Vja$UDrlQ5V9%+V}^EN z4|rzNntv9zhq+r$<3n+}r&*0fm8O^(68Bqn1mpU%-%lp~L734H$7#Vd;T52{B4J{K zDQOZ(iRXYMQ(!{6z!n2s?rocx&ZJFP*1wpR%<*`X)fU_a8WbA;S7anGF@lC6u)FDj zA68Q>Q#Ylo$J~gxH?XFrsdH6hx+%1Ks!(%YVm|{4xG-3c4IEi8*oq#fasktsn_5X~ z<3UP2+N5ezAInRuQ$-d@CpIxDlT$HoyOz81h0>`T}YyPp!EIW+n z=uS6cA}?yRj^1jhPHVwRnp4ok1oH$S(X8 zS|8h+D^w10XZdbAP&J2p2kJbAXAac+pa*w(6{ysjA0Q)P$nO3MNAFhKFIDaIRJBif zRU4&hB6nRda*yxl!@S=5r>bp9S5vUS>GbCS0}0WGX^<4iWk&o7vo$E7i;XlRRxjBj zekBV6oF6XB-kitDN_;syg&!9G5&Uo(5w#M(B_@O0Mrs^073r7&o%BHv#A*Cez(sSR z2Ne<3g|=Fi!rnT$aD^V`%fv)&*!GUqB!?8tzC&JM)J?<`d|7cDiC3#JyMa;Nz=DJv zBrxi_fh+8n6SvWx384NN(XO#*_dVH9JJ|RxKNJ68q^-`biN9!;>3a^0OI-aGD)1@= z2nv``EN1=vv-fu+e@(c;cDpq(DmAg6lA1Fy18k>}ngVj?v!&TfSV>mm`J=Q6tc#$1 z$Lc3!SARIC`XQ=b_ye!{muziLb#GbU)t2WRvdeN>St&ene5w`2%Sa4AEH6)?6k8ML zs&^qXg0<)ZtaRG%qCkz>%t`(o7Q~68NHz?F)pYOYDv`RGxwn0l2;~;sOtNpJZ=khc z5nns!AKpvh__z2-@ejV(nFVR8vp-|}79L`lH->+ohX`<;F#6s+M8{`+^AO+X&ft>z zHXfpmVms#{F8JQgc!&*9;XCIco-<6hVefKyh}-AvgopSG8UKSk#EIay{~aD;3|RVq zl80E(!v&lu{UN=IhxiR2-^4@AGWk2_A%2vu|DW;@Ge9v$MQmuo|0y2AQ20%K@(@Q5 z@8+9$h}~29|64pn^HP_GaObdd9^(9*av2`Nt@oes5NZJ)BA*Vd1^)pL(eij|ssHzR zhzoxYjqrmu4#|!@M8|{KH)CHs#6<{McE&?o^6( zPs!#X%7j;R`=xn^rgrhFMWh=ZqJO%;H}DWHi2Q3jL=jVWiN9~)A=W~RnL_`M^AMlh zpS{z)c!&l=?f*wS#C19C8y@27vdsGZ|G`6imoC4VhgbrEmEw(D9-?1qA3VhKfTN+v z|2-ZeUG3lFA=*>D{m=0bpWd6j`G$x1vCg8AF`RWX_`zDmQTl(Hhxq!w|5YC1zI(El z(C`qK9Qv>G5SQmvH$24osp|ha4>2sK6~jaPDAkJLAqu~{a~@*REo||QJjA5iNY3IR ze)>T#9wLnDLAr>b^rLzKT8|Hnqm-|*y2x5k#aA%SyQ-*ReIu&}@i^|Rx6(XD*wsyqml)Q&xL9=^oVRMgQ)ja@K5m~25= zs7|sq6&I1)m!{%{%d@zQ*yOaLVm;{|lYs|#StZ8OdbDk@bQOoguv0Xns@Ru=aI7q& zs<;tV>`qk`A^XBUR2A>;&njfADpoNAdO=%}QB{0`EM&(mMIDgVJS8M&Nb4%jmsF4j ze6gWr-=M50KZH7cDk}(mKjJ@BRtO$YmAhIiqpDb5j==IG3H!_=g-su_T9WXf0gZ$Z z3k7(H&Q&4&HSvb>ctbLBjO0Z|qk%D@G#Y_XXcT9?o4BOVD=|1-VtQ_gQz;?3CbF82 z-8SAzMu;HkCYptR-jgC_*QwIGlFv$`v_ZtzO;j?!6uvnlgKwpdHGeq0 z8H%m93|{YpO9p?X8oa@4uyFxxC9o%R8@yW0uShk2nSQPDMz~-YJMViW-^@|(CIzeh zX+@8uF?ZOmsIH6N&85C48Ai-@87Ya=`JXAjpPC#YF`Z_!yOv-!9VoA{6X8-~8;fd6 zc58Kqrb@o1RvNvbL|#+gq2y^kyo11)NpUaMuIsp1AA5?l?F`|Y#p_>#xD8tT2Ol13 zd~d1FO`oLk-s2&SN79|y@MpOLG<8?OmG}uG(9euk!)SJfk!&R3{Y*V0OfT_@y2A8? zL|b|nPREE^cLn*K|ZK-?(vNVA%~^4q=q8uG2Cm%KF(K=;?1lz*gBQYweDn7dhU zqonu?t8SLedMvFP*q;(o4fvkogIHQ`W$6ZZ`D>M{8#vVn_>68qFK?z6+SLN>{ikfY z~JBYCWwIxC;wDbMo^@Hsd)aYdqT#(SM+6jHH-p<`^{t#1F&8`N5o))}&e@G_Bjx zR*rgVW<9io^K~+DCdE>Tt`6XKMA%&i83FT+eD)QlIq4?4>@7{N4(^j)TDx zJ1X>=fK2D@JNkj!SMf$P6%(ViMmoYkTkiSfj2wIyOZlqr{bX}=gc$F{7|q)3s6qMt z$Txzb=$jHucN;;ytCAyDf;GP%uh$sKmKMM94qE72JN`Rr8}0b@e5idLxg72I%t1P2 zhN~}T#D$qo?8b)h;1q8cHkN1x z5~$~@t~S%qx2mqb$E6VDeqXS^uEZ36`_tkb*v_wYm(0UTy-y{I1X+D6QC7P-dgN(G zCCcG6YLqCax=NI<(2GlnGEO=YL5I1xPSb}rTB}&?YEceSiIHST&2k>i=qT4FUN(qL zU*7>SO0)8N^3ocWWh5Gi-5>z^zNM8$LGq-2^%Q%*ex>C-jhULfH?+75_DJy@vpsw( zy#-f@^Tn^o-cuW>9rh9j{F21&G`b~ftf=zqM)-_(y&u4Si{11?KS#CCbIL9T9k|wL z&9X)_s{F zIhFixYAvBV#*;R9qH>K!K`9g%eDgxHMa9NONr_Y#e49E@$tC>dhSnc`UZ=C9G71H9 zr_6a|p`~(dZh^M`8#}q+TGI-tpdxn$TC_?%X)oQS)ik|>bt`6u z#{8~D_C}Q`b)&AC9}gq54W+1e-{!BLE0<)1&;(Yrnu>u~euyY!!Ptq#3fU9cgh9_< zV%dsyJs9OEmTfrmpltH2EL~Froz{x5o$w`3ElsOxqgR?f+=4TU zV{F%^&wvY>7~Anv**%=P5i(9WR4sK3{gUhit6Y(CRftnbv$L!SF?Dr+~y)y>xxc`uW%UGM8QEhf& z`+i(>y9gOVz&0JVtLE);Z`bLeuti z`=j@(v6GL)J*j#RDDPlkzzpSXZJXH3wWJK+!l+#Bb7KeN@<+E@(K&RV5Db`68f!BQ z0NgQ{$Fjj}7|128$n$K<1B4&NMk`eHp?ggbclkE4kDF-@(}Tf!pHr4w-=kG=SqG@~ z{k_&3rPDAkJ(|9>zlrlweI2aXi&Znjl?#tya5u4RU00gVH?+uSP+kqM7A?1m6qn#U zavoID*851yCk^&(qGxqGetOC%YQlHaB*Lr{_z*8qX*Dj`$DEbPSWJTTHi%pk26HZ` zgk?M5BeZ7Aa_B2{C5C zM~_GzjOwbb$fqokT9|Dtrrr_l`&W{bTWdvrl4-+VfhCgygXaIi<@L-Som$`yU^cv7 zWiBo0Tz8z|^+xOFOB`Verp8^8YFA9(VP>kPzh}J3G9UF9FS+s745K%c{Sy?hKCTs( zUgk+uWJWu$ckMH>YPWg=NY!rq9GWumnYZS(=DZv8@CvKxZh?g%i+<=WPj3F}Ir-Rh zdmYb)-#e2UR#QPLCB^TZO!sE(=cwDOGh3bJ_w*Q^;rE{51AgzFTz+q@%kLd8N*G`Y zSPPEkGZ4>M{mpj1cXKwAV4jH2@Ow+a65qz}5$4y}g7FHF)%XU>o7?`Ho3h(~Ov}Hk zfLrk6p_yB`GYp!sSOx zeGSKN_T3aaQi~vduUTY=$Eba&k*E2BX3()2(%(onL)s&2NMh8U(@ggFu=av#wIt4Q zw8oik=7Cf*hmvfXSr2YV%}ktQk;XlaVyQ%yljLUTS&!eF%jXXK9$QId^Ij|RlN+;_ zdII^q`91lf^}+9532Zta-z0vIx1PR3#l#@ih#1{gG*8{Q=we64Z`kix(+$UD7(em* z1`*=A<>Cle=$A)9mjir2B>w$|hCdzO39*0uA^%hCU;Tu>S-&f(W>~-JUc^u=o`xvCa*o|TLU!mX( zU-_2SDZTOYIgSQ?R+DTt{u5HN`O15=%I82`^~vJdD&41@+#_yI-z?s7pgY6jo#?W7 z``+lXc%xDboMG{Xds{lYVRjN5xdW8BKWXCb-i94vV?KqTVpkDC&3r<6~OO_?}NZ3o?^iZEEo}K_v%sE z#gui14JY>OgZW$hW#_`h2oFWCe4Z{>f7S4D*xO zoQA#cBJDkzb8fw%U!J`(@!ePWzFyz%OVG#YcSGj)Kz_URzpMIh+)4dJN3ZTYE5Pd= zG6#Ij)_@9K`60&ou6jtGNlTe3zHRf7kLYKMe&Sptc2U3EO}3x+4fxSvehk<$NgEw4 z>vVrE__Z7@7nK!iQSr58SNWUeYZ<@M?Iq)L8KsKzOb`#wUQT19ekoy!6@BJeW^+|( z|3LgiS?oVQlP++BmM7U_n%6%Qu@M{j|j-01gVYgOcY}O?ymTMF%;**Ka;io-Bj95N~=}c z6KX$m8QzTqBXt={`F~}<(VdtNpTc&~=+<{~3SZlI;RDS*kYzP%#6i5UoJQr&P1j{( z@igBA1@y9s?-D(=a9huWnAz8gU(i3I>A9HU4 zUqz8Md?%1VK(K>D6!)l6gKNMo0hC-wpfB7gE+{StqYk2?fFyznns9R=o$FOlaNGyC z8Pri37erJ{*b;XZ71U7?w{9aEH;jyu?|-Vg?~-(I=6&9GzK5UYR@ZXs)TvWd=Tx0K z~swXH1VU)kMK+3BjXhCt=d>CPFH zZPPM#)K(`~c1B8Nf=AoRKJMw;vKyqb&u*5n>Xf&wN6iMuf0op!uWm|i)ZQeut!KJ# zJyzw{9oR=7#B$<4?_Z`<{OA1w;HA(+;TmK8+3|4u9u4R73+CwIm7Jv(tovbTQWYzUUyP?y$TVOUvDN>c7CI{LKLG)El$!My_HJjlWg@g?g+0yKeQ?o6gep z%q`kSf4dz%J*Dv6rfH4h<-p=>=dYNvv_(`n(+|-_A9jT3Gc5PMh<>#TL{A5ta>9>r z>pJ0Q^0If1BKmn|KKWOvy#EG4NN(Rb7LygiNI^y>fu!F*Xjb6Z~s`=~pTXqF6hgsPdznvnw`0j?tYu6p(*B^KgwfZvQR{L>o_~}iE zi&R(1#kfo2q05uIZ=LEf>7;kI=_}3Vm=#IjA=gxTO*LdiCR9c?rR?3gHx$KlU9dmP4MOwU=>h?x7q zr-T=T6>03A`t$MgNJ=NnhD5&!B)O^}y9zjN%A(^?+5_1v_^wkf@!xa@8SQCBYDW2t z+Qf6ewbK4h#biE34Lp-2F^lO<>a3(?dS$Y2*DWtsbfBnXXbbc=b>EPK5$d7V#rdIud`H2!>sq3z5M0%l} zrPFI_NRM*vjV~}*Yom)@5WaMj|D_i9f5l! zAg}*iEP)LK9+lD$6X+%}_YmkqK)@99AYdE+LM=jYaeGyrr#4W!x4weApXvLX19`zX zygU7YTl6fB#$GmV>BN_l%byUs(L{bdPwClbmvZip z_pInS_}o$MFea04G^h7ihXkX0$gdfUo}p5U%c7TOmqo9mzt6?X!j@@xaiUD+pib0W z1LP)LomTQ|Mm{jAy9pMtsp;YbYK+OFcjH4vpL6k4(g#8>BV0u=gp(oJ{1U%Z`SLU# z)rZ725B16xUvZF*jxL3ZWxub4oxnKg?*c^`-pBXTCFc6Q4t9edh8r z=q-gOJ8jI|^iR@GTVjW81HEdGJyG%W1PNCWmiL}eP}jL{FLt9Qth)gblE&v8`A|3Z zn^B#JskfW&+@ze=72-G0`$zeS;-d(slhJO*Qd|^f-a918ia@zM!j*N1ri~BsQeUj6 zv$X}>#ld)o)j1`;wkCU;=#lYc5Hj42O)u$|adal|? zmO)sw?wa0=0V$U<26&B)D;-?tXu-kQ>m>r<%}N|4EG)@8ZTre}V?mwrFeWUMZ&VND zKCE&xb~=GT^yVpmX1`a)Gmp2P%Gv!*cs)o<%cXQ%?_!g2SD4LfF_>!AQH&Euv8HL1 zU=eS`u4Bf)m0?|XiejlG_a`*Eat^w#2Ov+42i1oNqP&LyXGnUa9mCg9W z2a9=7k6JT*ed{MOIZg=;)M!>b?hHLtx}6#In$KlXDHy`O8%&JPQgI{p8&$x{S<&Nb zaFDplG@iU-B2=IWBd2h5Bp8m86S3L13>Gk0HOwKv3#9m&ykbl!dIc{V9%)op^%pSm zq>dvVgvr@SGO|f=pOe zp-?m|y(RWsq3CTgFvO%w`w`oBh@{_LN#xL?w=hi1x}qnY8p{xOFv^FR8Rf~bGvhwQ7EvXg+X)AT_z;7^v=6aRUwcHX$Fctd zt1ivTH(jJ4J} zFa6+n`qRnfmq|M3nKG!9L?Q>8a~_l|*pRh0Dxl5d3Nj*fiG*w2tv z{={oN3$rJal1d82Y1lqqTJ>$DIe$^zE3yFXggIZu_ajkGy0kOFuhr8fvX>jFD^j*c z<0SrW7oh?S_zMFA=2XIpM&vkwKUl#};Ffb22dG@}(A6Ovg8!m48YPBh$&JXF+CF0w z6m_0y)A|pgp(A?$;uaB%X9R_iyxwfg{X4PFYceiWOEk3}m;8SrMQqTd&4L88Y&!KB zvrkt|^yX3en579HugVBb47r@ED4vXG&sU~<#1>7?IaSj8GO?(YR4zq0cM442uj2NS zmk<#?3Kq3!M`8l6*fq2fVkoPGA3dvbJzgR3!7QXGkifUX^hwGM)$GOrMk zvN@pp$D+9T?q&l||rI<+Sl6x)2ob3=n_m1lhU>4L>@J36CKdMZ%UM9@M z3R$UpMr1Vm9vMck>eCCKT!3Xkkpv{0ZbdH z{H<9Tl9?Ei@v%kQtKd|OtOK#jk!+|Ozrg#Cnxv%t&+~Up6>JN-3Llr zb%$4aPQ|2(tM}orb}BX#xZ0^0hGZARe5vqfrNAF5%-MW&f`W{DuJ_z4BvNj<5?;j) zplQEj`(w;~5_m!UH_rWQQpI*R>hwGU2s<C12bg zXwtEI*jEJ>7?~HVgOQTUpE|59eC1SeaL>dr~pT zi6L2klAPW|$NT>h*dtN(w=_yk3E$IUs%oh!sp{G9CH1u3a%FNSuOP{p2NvSMIhJ$r z*~|%hRulJE4zxTN8jsoAiGByxQ&vIce5IUMyIggF?X4LHD5UB(Q^_?ectEg}Ic6PXiPftiQnJWvh4lcwhYP}?WNTS?pnJb;i@2&jG z_gDNvtZDmtjcn;O?TDtK@r}8YyoUB-zDQ{(W*F1=^%&cJWKt42Bm2S5{nQRczB5VH zfN|AvDv)9^k__R}6bQY5pjHRxS9)2IS`1!OFmOq|H}M`GdfMJE8C3NzGK>6nlyC=F zye%DbKgx{W4?IT-%d{ya^Oc-p&pMwh{e-#NB$Ql8LLU;8Dq+kK?_ny>klG$ag(m*Q zs)-q3;!f;(N%HiFkk%vQs{bf;)qgl%#I$uZ0Z)%W292u{{ZZC_N0r!HRsMgZN-V`i zm!B%JmJL%MRbr}MgKA*fU8xf5$kwqcG2_qPV0fTqj;k5q|4D5w8zRYIwybK0pA zO_Mz7w!JFxmY4SblPYl<^~Y6-B2gvgEMg?LS0xT>pRtW9p9-+?Nz&!zvF zDsfOAutb&UL%>xf7BFXYph|p_k*rGG$XcnEwS+3MRmrCb?E=W>#&i9iDxuln-%}+X z6V*p4db?01278(Q*Q*k@UYy+PZB&U>$4FcMN2)~s6!=P&IOX631^=I@5-TqHJyqf> z#VyII#0OkLZKp~+jYuF8yT2;&x|{kRsuJtHV*fo=;_*Kwcd}9?E&vOyO7t1QobcLo z=7j&HI3{_9@n7+J#NSIoq(Sl#r0 zcC2i?FDEy$7OW=_S2hacM@X66!_|A;$wx?*zQL@{j;bFQvwmjfcE=XnK9?M-IIo{X zXS#mHIJ8h(^;6kGpkRR|Ttd97a404VMK8(2yI5J|GhP9Z;|qC2E;_^WF2?c2ABf=i zLe6m9iHFu9!vErb}`C5 zXBqevo5iVi;#zu}1B~4d0&M(Rdi(&x?Ay!%25(sYA3uVk4lrN`Y-ExSFn)nwoo%w? zCua(8LnL-CFtaeipNe|Sy>xZD@QEYFx$<~U_%-6SW^rsLIdCeb4l(3Pxk`U5o<24? zy^wTajj)`N>hkjVR{W48m-P6Cy}EtQu*P-&YGdv_$XE2W8oEZLYiA~_?TH=eBQj(M z`WvHKTt_+kNFn&5T8`}0TO9%-+?g*=8VyY@Fdq9ebn-;z3Mu)KI zo;^hh3vRpIb>H4cn1ktY8v$2TzD)Vd@ZEJ^`pf6M^Fnp>olBJ4^JMt8$nc-xj1nY- zw(6Kko&Fq5l-dpdRc$tLHX+q;q!WJ{NA0eEM5@BqJ)p{2c%kQ4jONa!@ruZ)e#I6u z`t5_kN&Je*hq|z+5#X3fz0s0D$GIm3JCv|~)Pa$gW-^{h$gYc@E1Zhq_7r5&(Top3Oc7juN41bGV~ZuTjenEwx2#1|6yu0j+0iq zVOUrPbN^BLo;(YVPsQ z#;@raKO#9yDv-(TF~tV5&n-uw^W=yi-nqX}jpDUyiB_F^75I1*7Z(BJ<#;3u&j9Y- z^y38iYI?ct3Drk{`rQ+%zOoK7+0V_DmCqd+_N8aFQ!CSCY2c}0|C{BvQkVZB%1b)M z-`2Z7tB<-_eii2;Tt9nxv{rn^$uY@vI#;bVR|)&5XXbWMK9mDn`6HZ z&qlWLS6EIg)6AkFS=W%MySS05$TC}pWUu83K4GS~@svDbi4~d=`I9QBP1?kI%^VoW z5~JEictr+{Hc)$bGp(MPH<|Ory9gTDLuVM-Bl{THXXYE(=NB5;7mqS}4eev}8cDpe zPU17)=yh8ScoTDn{PY@HX!N>U1+$faZbqXrnvCqI3|7)jqt}B=2x49{g;I?w@yzjn z9RsX7ooS+J-L_6LH7Fp2kTEvl#udcMtOmJRIwwZhY2HNt4b-N1;y4U};zObi4&|L{ zRI40s@+s_)AL`qJ*o`72ydltdnU%!o~gvg z&soIpT4W43IIly2=)?@IluS%jN?L^D+LDMHuPbZxvW%5~`z97PsGlDrYuB)t;m_lOILRtnwvuClaDhZx08x4ge zvictK2}c*Y<~5tCN395ABdS(}^N4YH6c|Yy+gMRb9PzEGzBb91_&Zi#ugKTK?pMSn z;N0VtdtA~A;DZD{+gMc;|A@Vo(wzjO$j_jrG$(lx)TyAHK69;BO37yOs>(i<5ho|N zGSlIMWj%rj)DnNom^sOE7t1;IOgU%x7=Q@Yp(0Tl)9^@4Ng3$(^Xufq;Ya4ncV_&% zdIyuRbDdXT4EPvyN&Hb( z4&%v@6SbM?P|QsAV}cVIxJnxtM?ee}Bd_$9CaR4SBO=n0b0XI$b#Gx2Blsn#S&oY> zNt&V>?~InJ6=k#ySqXb0YUWZNvtCxIDa6}7IfGJOc7Ul8xMv6(i3u%CE!YdYD7|GI z32G@+XsGH!xPK2n-N&sAvX>OH(C4f^-BV~783Pc{6%ZeV=Jc=`mD61yPV}^8q%r4eSVcqybugqlC^_{$H?=27V7lv8Scn=V zsucQ@7vrfxr&71-m94bjIoqw0CdD0U8RYnVHRwT#iyAb_n5$eu#}aB#q5aN?WPw?^ zFiogIU0jD+vI@uTpxUWHqg;nts6qb_aWMscMGE}+q&ov-PD`4IzN8guB5J0IY9hLw zaqNkvY%wC7iY<<_h-h8VQ**=xm$GbKgEJjjp+)fBT__b7d`lT)3i{8~t)SnK1YML6 zi*M&I{85muPl9xM3ZxS~NL+@}kjmRYx=|o4Op4UV%d@erCbJj8cA5+w(<(Kk5N=Q~ zxnn*iy{#rQkx9cxlX(%yYBF*n=j{;3*3S*pe#xMEc3LSp;Cpssv;t%2y{UNu-V5U;&NZjGXky{;;-a%p|DbN zeiPPFgNAWi;5-OCR}uMCnC5m#ZeuDpf|mY{A~M~=Om2F$M_T)f;q4Rr?V$Ds^zq&pen;p`_qa@q9`Sz^o)^t zlRX^Sd6eHD_>C(&e`6j|DvU|r_%U&T@IVR^Pal@d#Mz`f8Em>LDB=+=1xl*1*`Va2 z5%rEZNas5Rsu$uvaaX*dQC3cmE#+gY5*8AbL=WuD14^}zEu~M1!zwqqPJUx0 zXeH!rR3DkQc9$AF|67@dm~!p!ro7FtUPnH*R4s`cfVmX0&)>NNcUZ|crUCUKVLB+#xrk9PhXkGoIe&Xu_3o7<4e z-SN8&&m+!CJPqOPYTtL%&q<1_l|8r=-$#mn`5DzDMt^U{bn@tTy=I-yZDrsb@JXAx z)DFj2R1#;H$j~IVtA2~5w$t`MT+dO`6-n0Q*Rs0UdzC6@PIpnPJ!5W6u4n(0dY1Xr z6ZEg=k5bQ*C2{W(vwZ71Qw{^&p=|$SNOGHSXF75V4KzWSXCl%p9{paE`s-&CKtv+DA;jGxm;vMTb;s}_1Ec>;r+H?96{%*&P zc8KlU0b*-D?hvsqOoSaE#!ca5O14F83P9Tqi@WgW)LxpgUX^b2dz<-hXx9ELv=h8K zWTET)`|-jq?fP*D2+7SZyK<-#PEugzT3Wm&vU!EeFJN@BVE`B1{jYG&XXJ3 z7n|*0OhkX%E|%3~weo8Bv`^V#{$&r5vVT`)^-A=@>+LzUJ7tqN6@qHVW>0+8(YX4u zqj7Z^9n#Ub8V9(xtZ)n5)1Fe+_pFS*tZ+RQ`?JC?no0aOi5~!7+p2r}R$UX7PP%Sz zeA1lC(%rV`d$h7W)-|HE*n?G3XQofF2YicJgON>q8~ZG~6aI}oVpom*7SW|G#)tb> zU2}?H9K){@961q@qiwNf+0$xo!+4GqJDXx2M^5r7`;33tE2Qi`s;uV7a-RV-!?&z; z*asa@YBOx^PpN#(F#c@u?)$FHD{h;X;*`Z_>>t~y-E{E>uv62;%O9y(_w`cox?`^FLhO*NG^;`A2zdnG}Xv{ugSMbDpyDxt8 zJB0VG#@wHN@*Y^CXK~LiynfO_ir4#Xu%BhyC9XmK<~r+H>s*LzglIB%sN@qz5ZJfb z&wnoirRUW;lA$9i)k8Wmq98i+bkcS#M3Af3eX$tAz| zhZv5y4eHO_7?02A17H^h^lY=$E?4k+;4bPGP2)qblTl8GR@!4oBXchugMuG~z(a}j zrO(kF(&q}D;?EE#ac9XF-d9NI{!`JRyMlKb@U*`D4r`(gbz&jaq2pD^CG$o#%ZMke zEZkh{3@a~G*wl0U9SgVcB(4z7%piXsGZOZ7`;I$?1!bDjR&C!3_J2G*M0#FWS(|RwHwbZkpFsJ7Vfj> z>kOB9b#1k8)G?c+5#s3phfMYrI&PJUbC^@k(-BXph+mrC1Ly=CklI6Z{QD9ViBFJ-*R7_nQvF$lzaA5^-oo`v(0UiIR-x!aYO_T>JH)8K%}zn( zGVQgcTXF4T+2w2M)NdQF&T<+p{-HuKuJKb@NPO*W7WYsyDHn`(EsGAvM!2O@#eU-W z2?tM1UAQJ%JtoEJ&EoX(eM6AJEUw;Gu}_kxs1Tl_n$~%Kp&G<(6<(Sy;5`~@HKl%> zC$VuXj#+Z0N9eU7hlAZcZT$1x0m>m-X00-VacG*rVFn_*Z zoW>ZHQ4WZL7H?*W+ZLfg{g%#^gVUbJ6_0pj$LY))#@q>HGC?0B0oql{$>a7lg9FCG zwZZyrT~3P)I>wA%ksmDjc6!&4bvh<9V1Rt#$U5vupuK) zAz8IrD4){V%H>0}YoxCHkKq>O*?JqwLwR|Am^9^x3YSIGKfmKDfusuY|?MHdU)fs18xuY8f@nP|oW*_GGk<3zt_ zbT5V=JyIL!Q-hHS-q$cGIgRd4$4^wYY&6bOSkXAF9+)?ZZI( z=*EogKItZ3oQf=iQ$jqpSHqXbmM)>nN3=I+5F!b{iTsHZsp2fbZep-?ZD=6g-(;+E`bjHzOzM6PNQPo`Jt*#1>b!#l z@nUd2zNS==mp4g*txTnw>?KyS6DCSp>AiAy!FE=}i!-Xs^v2dLF67|?8TtS?3wYUb z@k1sx<;X}L!z>)ZwUC1dgkm^lX1w4mu`0T0FEgL@%-)Dhp#jI*qB zwo88~A1wO8m@`aKeu0{@&FE3z$1kfdbKxcYUJ18|-z&TvW@Wj~uP};Ys?PY{*$JNV zHu#(eQ0qMVnf-GKV?V|jXZN-xofv9;~p3i!t zFm?{(;}Wka}xkmv7HE(sl|Q;nI-9*$};yH zTF@ETbB?d_eAq^`|0F?CQVU)#IM>Oa}-@-m2H8+w9{9Tls3T*&2N^56^TMcg7!0RQd&O8*o%TLS7ka0?@@&=>f`*(D zsB>4mG8qx^Zx&>OO$-}UdjO>MDCQDi=V!bJ5Lq-S@f_KV(r0>I_Gbya^Az&Cv#fKP!i`172;V8S z)-n`2(Z@#kdW}TJAZ4p0MTsS7ptNNpqSpsnn#2_kh)Y@hSgX^ ziKO$ryUA*wgroi9>NQ@?M)m1}<9diE<{5|&$H(WTjvz+v6>{9WUqfOPVSZjo z9m+|aE)MUPk_$Jqw8)7HwOz0dYO)NEJhB{27Hyxtkyz(LC?t;)i_yjpA_gTHZ4~<( zZQM;cWwddt04M^0YpOAuZ<#@^llUDpC6vC^Ncc7?1|vs2a!RxwJZU*@*Zl=34yWTu zY5RIr$fY9tW$mwByvcg&$|3utMHS~Kh=4tBbk=yx{4Fts}OwL& zx%~0nvFLbPWBi~o9U!e&T|qe?5C&Y^QFX}NcbJ=9b@iHrWxhvY8nCOT8^~EOl5*h zK9z$8bvLTB1r!g6G00asrvXxaN5D%8nb#@c#Q3AW_Tq5gd0${`arb6qzEC5-KPB6Y z{5oUqege;>o&DG$Ni?e-!@)q?k$)vRme0t)1nXD(%LnserE4 zklRcDhm)$L{{sm4N&m67(*NVGv@Sa~NnUD|)_O@o`XBA~fG7QJ^nJn?^v5gsH)&Px2BnUhvG^JC|JPyQe2 z$^V~Y+O2Yl{O{)Krxbv#M)+4O^K|U2OI!`$OXq%JbGa7$Q9RX%oxxJ!=J?dX>pUvJ zXZk`9DnN0t=tpC2fH{v#K;_2q>AdR%$?rG!^-~r&@igTj?C72Z#}=Qw0oF@H@WR6#M~1A`t>lKk(8EkH|XCI0}hApc$c%MM3EUpOqii5ib~X?}P@5AIg|_Jbt(w zj6;3DFsjANB8&J@u1s?@?5D(xtGsn+DFpBqMNtSw3m$bs73P2NSdANGzJff3SWmlj z$BVp^-0^4xmmVw{fygVG=vpIy+TwsfbzquS34RoL{2CWj@ zi%I|zTt@sW9TBwNc6bLvBOww{3KB;60Vv>gdFHzu%f*q9+i*!pR8N))IKS}N`wN1k zPdYTs(+ci{NmR#c5xrSXJi`4c;AsWonoxDS5nd+s*2>uUg?i8uJUkThS6?BZuA@hi zI$|O=EUF{qPO@_`IYci|63KbsqAR^kD&3t*+vx?}sa#11e{C-vpckkMmY#GF+c#M{ z@Y4%U6LaDAdckzM**4OYYAxYpbq{3d*mgq;2rh zZj^5Qo-{!+JXdH|DLGxN@5iRiyP15sTd9U_!{<#m#JOxO@?&&(hFMglO;PW|cGQeo z<6-{jQB}^XeD>SmwDQ9ROku|O7x;Ega!vRv=qor1+ou7BME3E_9th{}qD%t}Zl+oNQ(16_@q> zQtpGz9ZZCbUa#G92r$t;u1|8~O(yyzMQDezxZAZNv@@;<<;Ed1<4v^R+baoj>D)ukMBlS7K00ZB9E35htRXNYOa_}Zeg1D~Ri`j+lvZ_u ztO?!}_UfLAyAhQFtm2>~O3zdFfSS^Y_k`mFYl0@CntjTzkR%P=Y%(YJ&UZ9Hbh76l zjr_jMKvX2+k=zs#Js=r8TuuQO)LlU%-H6->i8u}Q7KQ6PD$D)mWGYVvb{xdNa*{zz zOQ!O0^2K#Pd465%fC_A??^<*~Vx53+orl{402WL8G_GO`f~jDgq^qj>u-j`X(P$<&YwR&jFXlTQIY zPzBlo?nZ3WbIE`Y!Z%eM@PcH()z5z0UM)U5%Xe;?Opn-y?U_0^1z=yN9;Q|ZEmMKE z2t7coGZV46!^vm?HtpI}qLz>d_p*g92d@*lQ1%vV{*xo8b|&&VB2}gPz_9JN0y1PI zj%AWldAj(rO0!ITvSXq0v|z8%9?n)`okL(bjbA5OmgMp=5}25gtj&bj*~u|)V`>=h zs)=BsP0Hs9<8g1_sQy`$CpiHnLL0!_GILqQVtikpYEjOdj79k&44b$?Iriiwo;~>p zB&1|RU1d%#*5nwIf48lD)iXP&`Ze0;U-k1HRo%3Us%HYu#|ZP$%{$xL-v10wi4kU; zU?0kDnbh}$We%O(zUYf>i{9tM%JNvR&oX-(vw?m7AL2VaM}u(N6?&9^(O0Bst`uG4 z^kOz{TWoLtVq2w{vxgKbmb*m9Qq*@jzg(tB-{t&e=70`IP>9}EGh`!pZD$5(i&qu> z-3**wk2)YoMTZ3WSf}{QH~X^!#0k>Gij2PN?CqNP3Sz&$(t#PBT!r`Vff>81@Jr?q z-yYpY*Zafkzbkleb_7rEi~7U+TBrCEBtREIgU|c8hKJ729);w6$R4na%y4U*=UJD0 z+u=Tj=_6>0FP;uL^S+MSA+O*0x1(@Z@FKvY9ly~IZSN+_#IYzpzDPeI{OCKJe$XlY z#G1jp9Tzw@h^VA!^Pot;v7S|4-O7^i>4qdr!cSCQceh&ZmB*pfD;Y+t85cp}c(kZQ z@sCH6KYoncQOdPuz5IyxC>@e#40LE>9I!lFqvOUC0?{pdx(qK~01EAH3R6Mh4q%gB z=cZ#q!ajrTtW^ec*QG1tLi<68${xnhFSDR@y}dwxmZ;SC?TG#yE7n5tc=HZ>nvUuG zQ&yUNsSXeJQn%Wpi9u$M0S40S71EyA)1WE+_x%?_J&mmh#?ZwO}jnUG57iKJQ)L zC+Y0oahQ7>!GG($%f~jcR3isX5$2g;hIe!-4<$W)sb9U67y2R-kp24AHJ$XIy?H72 zk$MBe>eBR%TzbWN3ym;@QC%$g1><1T^4W(&Jp47tmO|Xw?mEuui zRIa`EA};MlD_Ypax37fI;TsA%S9Ha=v+%;PtIY7)0@>bIU(ORGPmq7d7zaw{2s&rw zWvfc?!+v>z2S-e;<8bl?PP7ciM)d`@7iruHdU#gR=(T9{%9^p-Yc^Z6%6ps9 zQa*~a)mI;|C=gH*$N9ymEc>M~@3l6)uVYM%nMilK5jPo?THiQI@RA#mwdJ!^8TY7l)wdPDpF4CHF0-5JglA1IH z0%xCn&Y5J-SEKS=Y!;{T4BU2FZheeZsC|=29pQ%JVC$O|-I3Y55 zeJ#Jjj=8F>fn4d-3f@^gHP=3L=4SR=Xx#y3^qMS9C$~mvU9Pn3mm6K$UFgzI!PD)- z%Jb*VQ-x^-i)lcanq^vVwdQ=SkfqBYQ)|vrKtNS9#`xjYUncRJ1~MSRYiA@dzK)m# z#xDJU4@Hhht|VTCl~To-ZWZBc`=ph>O{Uz|oJ*5(XcTGA5oC1f5iaUf(M2^Av*tH# z>{QcUqPxEj_1HhE@TueNBjv%`*v)tFZ67G%@QQVW(-b>wCeWI5M+&%$RBbElc&28R zXe3tbY`M2lKR_vOOZb+ zbK!UP;i}|daBR)_m!KnK)EyV&gmqTTatB36@S@jdnUU568%O(@(bM6P@9crJ2CLH> z`G3vf5)N-^Hq#r-aO=0_>&?DvTXQVG8bj15_$J18WJCFMQ|$8JnqW*$pHO0KY7YGT zt{FQwdjbZX zo~pJVy;_E1L$*NQs{13U4-)NBU65@?&+Wq!UEUkB_Yu(^+c8VF3n5de=m(jvZp>mx zx8_WM8p)mFO;(3thb+^fhh1WRu*Ka=YtGTB1=T$8-SwKZiZRse7VV{!?_%l=s4cU= z^AfhdZET~(Rb)zKs}QIL^%McH-v02x)Fsn*z2trH?xE@QPAoVL@Ww649mWRjQsZ5!Ea#guw2f}w}oP}>@w@v zV8ie%QN+uv$=M@g$2W#ze`+*~el9;Y6y@T?C)`P~56JHblFx%z|h{${Mqek$F*YTwSxEF$NWZ9!?J4Wc=qv=4)=txQ6BzcOJV3r^M#s{LtvSn2UL#5_ue^hGUegNWK)1h>i6(1(?9oa<=qji7@&-w13#Ub7CmPA?f}S=BfHxmi%~Mg+JR;#)@_j&MUbul8NzYkPDK;9EHvImSFhW z?6k62Ft_4sQ=Vm&f0an1X6)fc_H)$m4U8MRis!A>d_Dw@93qchBR0#jRhwom*QKOb zubMzs(`r&XRq!si$dLlTmi%}J$1oN24-nrVGfGb1?-}gCVxMf6mWL_-Bx z_cpOwxd$roM#?u0G5mRuQ{novoV`jp6eDy)HPQ^~8!xrQv zWq5)N<}xHL`3Jqal+;|4<;;_*9FSm=twkz3LPlo>@jNDO#x9VnQgGW!`%AdZjJ}}P z(Whk{-5%C!?LcVq!{H<9j3){*o-)&V^|DORY zEAsgbT1yM~am4fY3li_lpobFO12UWKk!(Z-DsSl3xuQpc6`S^x(K`;psa0y4VFFxYKA%9paTfPFRu>2|g7y!z zWm#*^s)`Ki_XOowc}7~(d-3_J4ZN~uwZ>)IS547!ngXT>I$F;)GQB1dROy}8M&a67 zn?5S~+nkjv1#_SDQS81}k^SGkxX6S0SrR%C6 z5_H|`EJfGGJv_QTv0T%2R!b6Hzr0)MY8+Te8z6~VuU#EY&)e+@+RdH9HATPI6rBnU z6BHdd4T^4_=MT>n8ZzzuC%b|#Q>;=Ep=U?@Da3?7f3cT+(w3M*AZDCDAGuuridGx&Sd6%BaeER3ReCYZ6{3%Ez z@#i7XFG0<1Q&agkcQiVWir!=q8UB2(0=RB zGMzprQOhg&!<4b-Lfs`-n@I8DFDNvO%?*Tz*qP%4%f_q1-`TfI!C21T-wDOJZ1(UN z5)@y-8t^80zvfL=`aEYuxtvT1xHHnTYnUaw3$F7>-&;J@e zu*av)Q#}>+wR)hL;TuRku{CGUlsdLdh8f;w%cn$$?lWFp__1gusM>qKnw|z=M0cfk zcsnuPdLZL%o-DX=u{I)i2{c2*T4>|iNLL~dhGN1-cF{+voDq@Oipgg5*)0SZq;=j3 z4nHgu0QQRuKi6mba7#1)x4<8=$S=?55B#zHR?Qz*n6c4I0?Q;8lEN(ZY)Zltqg6*Y zGhPK%JziD4Mt01mhPJcdOW!0IqZcM(FvdzWAk7$ypH+;ZRu-ws{v0=$G6N>jGi7|W zT~7>;A}lN3u>D$3f|KZ*1UH<>)9OtdeD)8M$8W#w#Wl|gg^_FP?CV#ir+MEl_}?jC z`H~bCC-fdVQPpj>IK4^Qdi2(-4(3;OV!R3VoPVbFaMy~_YJ%+prRgnmzV5B-QzzJZ z_B*pZA?bVRyfwGUOt3;m41M^?w|ZRv{+!$Tb)xsqEK|Lgftil(y|125opS{#`;djY z2jk;mm;INZR6-tj`pV>vn}yq*WO*RDzfi6`dEml{?dMy_E1OA);Z&Nf$5L6^+ERm2 zRJO$4{(dTfOP5sqkyUmX3Ncg8h-|dU79+cp(W}&UX}FSNZp{fm5jW7tRRSm=D*Fmti&5*;vxj8kY|#l&kmGbr$>g>w?j#^np$>3s7 zH5$yuBab*>C|Y^V7%q%oJq5j*+q&ybWB7UwXS%&Cvl1rlJJ_C^aVGLWMNvO`4D}<3 zN~e?{eXGQJPrS_h_RP-K@WAx)lSDsYPaUUo#(7470~p3BZF z``A~eWI2f}qV&%Z2_wE+%~r2`qiIM#vS&Wy^_IAbl2m_@-p>W>tv1hQUTPfYAn|07Enw8ke7%hs|GD)UO^2@m5TD@MhO>5K0SVk}y%cwJP${^+O z%z+|RnbN0dEzxQI(LddjNUSjIGlO}jUjKCmii*{4li=}8=>gc@Q{iT^p*&Ea?y6P zz=G!rLjwzq>N^y$xfA&rW*xOmuJ*Rl9Ji9WqAFL;z*0JL13AR=$qduFN8P$Jt!I>T z>*$k<$y65EW>jBEp0f0xg0W%gdUum1a?>PGdqB`yYkd>gzM3ndzkvv?5XgaN(ko|V z5!WBC5<-ZM6av{r{NhRTU&7?YCDx8o22784TVQ$@qwZidSXeRoXOTwCqVJ74qgBJ^ zX32M~$I@s?O$ME9R3Ak?yyD+9SOgF=y`D0~stj%(3ZzW^C!NgBw-gc=?HAq&ItNmM z&f&)3!g{)Q_fYgEg;FT}m7vvV{Uj;Xv&rNfME_W?$TJypUZp&5SmuUeJzg0Z>yb4a zPyHo@tBg4fG$tC%jJ#6uj;M}x>;Kl$Dmhgy>7GQt(!|+-cQ&|)6x!7f zr>8mR$|i~O_QUI9cGcT0tb9k%Y&RVaE>xDtLYI%?`c_;ukk?5$4v$}Req{4T2*2UX;I{i z6AW6FqB1{BFL<=7z7#BJ;{}p4-x|?dPzo8nhGbZsoFM(f?##9oS;))~JZPl{U0+xH zX3OeioKqJ7cc!S!cgf~%;_wm|X`z^&BalzN{+lxLIG-$b>%%I1pvwN8-K;w{Nz@_TzQHrPCopv-swU0GOPu?KES)E1rWaDBl&CbrO{xJL@Nrk8(N(^$VH(`tpY)F}v_ zf8>Ck?K7UNwVSU&CV5$HaJA7-6Y_>+*C&Y_V97_8{RmLwvPVbw<-7QCnl9!BfdaL7 z#Ssh^Xbi_DFjO`OYzS%$v%#>BeX3yiQhR+Q6~AHyJZ^7LV0TSm*b#m+T>NqrepU4{ z(P)&;OQ1Af5$!`4rSYIN(SD%$ab6Gl|s zC-Se>w-fD+XR%?aR8xmtz^@H>?d_}kqiPAYsMhu3hKzjZD&IK6RWOwFO2-vz8oZK1 zgXhYj!O|rCHG!Y7NM#&2y(kei5@AnuVaIJV1YynttG?bW4UKOHl#XIP!ZOGl*lFqk z@{>OG98=~s`By2YBvq@Wgp#oJ$p|ZU$Qpscb!l;skrhm@3t43*+6(@oN()SDbfHMY zJmd27`%{@m%JS{w|D2xIw3Oj(@59u|7;U--WhfuRlY&sRtS}TET}&~S^-{*lXh4n5 z1tc|$#=BW*R_Msmv|zoR$tiX=ua)rTfibrpoI=rH7WxqnsFf8OebM8irGmyfqc3`p z>=UDOk-35cw9+LZi;CrhU0F&zz&jGs+Ac=rzA`Byu6pfs_UzV~-TV!~`mLE|czp`j zX9bxk%H*xNb!E{rwv<^LgFk;T<I7#*8o7KY z%wbyV%=I{FTNmtGw`|@zIg|CQJ*pkHg@+o*oHYJCs{wC|w(=#_&Whb+RC}#)D>#A* zL=)BjQuGC7CdHb^8Ti$l{awxQJ;P?zf@OX#>)TLf3_+Ox&c0+e{c=a7E@YIp6xUwS zhueVzu4plCtwZ``@w=nmD6JoaNc3kK5Q+|r4&4uZ@Q~=xz2*2NX#Eod3YZZgK>mjE z;M88BJkDu);n$?-U*#tUkrNur5Fgf+A+`2hTA1d&HL@-7E<&7`~*K;)&V7_%+=F;mc4E28@VhbP_RUA|L0a4~-4FKJXGV zWSTlvWqK&@MM95Gf!LsHOVhWZ+BAK&wj}SEH2xfw&er0W`Q5~`&Tc~oWEj&5B`IB! zU1I+#7d*OMq+B-9vR#3ARH`$RJTy<1e}j193a2d&R_zqJ8{xya$yHL*Tmt?_Q1g^h>&>RBcK5C#*{jkYD!B9ka~BLY%3+37vEe$KOSU+CuCA-(70+f zR!cn%?n+NEKB$-6>nXgUWP0V% z?^B9}=F+qBiuij$-T+~P!kTk~+OA+-p#GEWQeM5N-`c0N+p8tk=_BgD$SUdf(FAMi zslW@+B@6P_sj5#OUs5x5A`CaM=Jd-1;t4=3$s5eyP~M5Ejw4kaM@Sw0I;!CEcm-Dp z+JPyeq)ee@mDD0&PpRLUr63oSbX%zc#{w%m&~2Th_6Jjmham=))Kt|_NWv!*wg_AE zYh5tMd0>tw`vhzL&BRNE);t2zDkTG1^B3_+qe^S$FV>-wn)#0qlFEirz3|0b{BqHZ zzZc};o1r`}&_V0wKT1ijf&X}d52^CbB?RPdW25|9RdxIbr`J?Tgc=7`uMo1H-@@M# z>ygj+k+Cq5%r;>oUrlL7zMA1mjC?iY@vEjle$|}FubL$JRkJ2~(hRsoR-?H2Oi5u& zMUI+A0@nA|MMWA|)oVFQ8>_>7Y1eI3>(4U)x%Eh1P5wuv$i_#S)h}tAHipI@CbrW>)??D zpVGk-2@1W*dqPR=J$e5iEENtL6^srWFT-mJ^-U!CBvsets;;X#mDZkpnW}FQ1%UCe zhH)Ihhjj3Gf)DCoe}WI_;IRZ3>0klD`w2>Qr%nk*Z?5FSWWP#SEl_)Vjik}OIl`k- z?HplBYQ9-mS5+>|DaG%TKd$%ek$9%r^ ztR!~rvJMR7f5u6O0m6C#LC(rMk^he*x`^K+_#MD+KYk0rXmXu98ug$jrGS(ZAl6_8 z*|Ged$ZvmskL34wevcr}apdVIShHv5jVs10$IgQq5fm3zL?+sGWQ=(;Q)n? zlR{XfWNzB|YwFA=`zP$S!bv5y<#{JLZ%a$@uZ(O@g7_odUfZKn(0J@k7Hg63F@C}w zzHlBcs)Z}r4X`VJ(_q=1=ia)&93wEt2bQGUmym{sKN)7Dc%@c&bRru9D?#v%Hr3yi5f@xe;&%mC%NkT0Xj7crB0yIo0Gp_oA_(@x6(lcr@cgK7z^PTSQ z+%5z;S~bs-b&S>>?d;8+Fo_=`BpU{mh6NeLRQ{Z- zaIMWqm-Rx^rFS}XdDo*0^bk^1&hMyvf42R(R{jIDI~$|4*WIgQRnhb{BtPU>PAa zcp&3eh6H3Bn;~?Ilkw(mE*TkWw@79-s0qqAA~=Acn7k1zDydzNC)aLd4v4DXoAPAb zDbknJ&dkFnO5PCXKJ*LO)7nB(P_|&1!(u)EEVeizddY^;QMU0#3-jZT=w@ZsTDIia zr?OW!i5B~QiS@5COc_Mb`og(Uc^t^Jk}RJp3eyu&p- zYyuWxVIsI=z&w?lKz!&kAnLbYH+qOH@d|!SO>Gb{o*SAqAz%&9t{vJvP&0fFIgb{k z&L^uG8o3$LRa?D1i~nnJ@UrZa1{Wtg@Te ztoNq6^bp~$O|yi)r8U#Bn$Ov=mEywEu-|g23^ecaif&U~!uWn41MaNk9unVUVej1D z{sZ^{YYwP14Gl#va<$I$`Yg`}0uVzUL=k1$AX8>tnq6j1?-R7fSA!M+-5)rc0rf|qoHYz$%T4aA!PVPLCrDDc} zU_!1&exA=I!*b~=do{VlK%^Ml#NI|}>8_2sr{f!a<&Yx$k^o9G79hY+jtDdsfg9>g zj{6qWXVq8qY0U|ixyO~EXhiC1%`rk5u$(Hcw+Ai|>vS=o|K0k;nxK&9D*TK8KE6?f zqwGAE_x6L~bxu_EmR&ZUoyJY=?!$FV4_(guH>uqpcq;jd@NRXn`BcsB*#6i*6p zt(peIb|<{a)gv-xa$PBUMpn}oOoKb_GSW`P%Xl!oG0?ij{@|fbOrq+2h^F4r>#~pt z#^@+CzclLxIC)q;+Z!`d1Z^{VT_1DVV~?tTolH(t!(&kD&FFay3~^AN5sDpO%*8mP z`Z2)BcIx-`x+~p@ph&Xf2pyXUtj(E5<+fxt`6SksSLCrCD92`}v^f+T#1`zA8KKUz zFcqy}-YsoWQuzD!cjRMlRM~`JJAzF}uXA$wbDC`ZbfvHy;s(PF91W~0kV6nmre*h- z|FP2I?xtKX*kbf$>*PB-qxrp7b-1Ut$#Cm5junMgX0wIL9@L%nMvWXb)4;623K=2g zd)G9I#UK-Fez9wrEq=y0NT55ECB;PQap4Hq}+6d6}Oy=N|q_ zK{>#$w@)@A7=rQM#(r|zj!8K5l7DQrt}?>)DldDI0!7ZcUxq6Mlyf8>nqv>R!sXbx zM0L!u@_hHd!?A`cFJ_qg1p$lXFw ztD(&L6^4{;Xl(x%PWrr+`$0{I$~tj*vn5R`X6=w^29K*3*Y#@^b*L6V>7;)5*72s+-ie9zjB;B+y4{0(qAN zWk27P>Bha!?FqHVJuhkfi{H{h$hmw9_hcc5GQ;6u1?mhaO<2Mvb{KY1zF%tj9VP!! zdHTS%Z~lI#zDJod*|tBgOzg7jyU5_L<~y0+WG6a#PsHy$)~~$qz%gg*rmC@X|8VVn!bV?+#J7*Z5Vp*VYcn zMM|Bu1$MRPeAh{xjdh)JkXjG0hUx?F+bmp}{Wh#E>D7k~_LbZbTUYVD3=XcQZTw6Z zDcv%)hdQPYub!f8XQQJz(tz&pYwO4ESlW}!O&=!YErm3Ue)$wRkpqNSaOSGwLiR5| zCHpqj%p}pQ>g#plNGX1f88P`}7_(@+TRS@fvk&TIELfSfQoJ8jk7a5^edACG`vx<% za6I3#wlxe95knsZK$c?uAGLPKjLuASB{dIJk`#EZQ%TKof!8p*ioc!s7m7s+SpQ3F zW^lYYYmw0Gf#K=s=6{nMMt)Z#pV>d3**|~Wc%yGb+!z^sV{-l6=(})=`nfk7e2x6! zQ%KL1;B#{;DLlc76!3+y%N)K;D^jS_)DETq@sB8|p8^%JS&$2B%wxP-82#pKo&l6#%}G(;NtQR}U>aGj3X%ujbg z(wH34=*I+gHm@RENTP|&^7C9wnlQnNrSVe}=_DTwkJsvgPYm-eZK(LR|%jptOu zX#4Jb!BPclBf}-T-Bhp{?+4$~Wo3(~MqXx1?yx{H;?bzJff=0}swx31oim}Ks#*o< zW@)3n*FNvHHV0d~7&nVYby3)3G3kF%-0ZK8RWisTJD|98;S>^R-jL=AMtSC}Q)Neg zQ{BmO`?%uJ6{N9FcI7YsxH=V)+}E7fueIqgl|~>JLwN-}`jRNjf_Gq99U=Sn3DhL> zem?{qI2dse>GLZdrP z!$wwhiW2_CrZzVjZZswxW=0p{6%P=)JM1Srgx-$k(|NHZCd9V~%-`7oN-|;i+oRae?kkJ=Xr$fQ zb@ZkpQQTOjR-(-4t&Q@dEJIE_vqfBRl<=+e!#4I8DIhSnP;+LqMuV9rVC)~yfWV(9 z`-||`g`R^Dce*NTvGWu{a^QD_Wy{NY1;1c>C|b!MvJ$bC!7duoSvk zKI|LSSeZOWDi$)oJTi&Q2^T0;YZYe7K9_skPT_}$T^;#9QNnjJR(mRcD^@a6dx4Z^ zUZ9rKcK7#0&2t@=unMvdRoNc<`eS9JC$LXX#=hKO0l`{FFt_Lavo&5{^5RDr>y}1_ zrWh>5<_nIYSd~;2idj-L6q_&WV2G=rb!02E{t$}g)T|+f2PBpd6T)tFvHZqz9>n94 zMBkx5hpg4P=BZrT3N`RNqm@iI6mig^xl0!~D$!4;pvQS+{lXr_^IkP|4+*Y9MiOmLm&Y-4a6yxG7DpVS>NabW7 zK~c60Pva-B47awBpx)m3)w^m^5t3*Fw`GMQsduhg3^61oMPKG-!)^lX?|GF1pdpgY zr(RJpZ=Wq?FfI}Z@MpSlb3WrwG_>eE1vM6H6fV3Bp(FSb0OVg~$a)D&G_N=0d4&5lo&YD-LjiQ4@AN`7Mt1t=;|3)9)+z%sD_uy>9ZFVHGKl}l-6 zPMhk?*u81cnSDNPYeb}RTu0h0KfOkB?|$fJ;7Q{G%Qk}mQ@i~%pvWpsCF>&fvrzcY z=oOYcMz5%?er{`#646KjLs_y>(3?vW) zys-tvr8QQpP<`6aswIM&fehTy8I2ppx?yWAwk{}%Vk??33CYc6)N0*r>(fUqS|4lG zDk^FMN&q*ORzX_@7rd9KfLa!}{NJB*?j(~C)aUj4^8)5B=bq)epYQpe?-?r$`Ii6` zqZi}zt7$V>f0i_3whlZoJLjb_nxdCW&C44E-T3^OQY9F859=Z7l|3myv4@#0_0=Um zcd(D|trIx1SphDneoSVf>0|KTd~sqdjnCVgR*RtPj{eGiCu1yDor|yq9TA~?E zqo}2G_|M1oH7V)aAC^Bq%Jtt+arL8p_0tNfuDlmYoIR94M1RUeyvWKTW~{)@y>62y?sLRdVP9x0+L^CGef z!tZc;1M||?*zpoPa#?PZdQ1I0P#gu@0+Mb@F#9KNHnh%mhi8fPN_x-7{Xy9{8M0%S zofNNoN`@Dv{Ezt2iqZgyg4dWvc9FQ#a2b@GnN>h?f&(a(L`%XG(IK&%-Nj8s%L5r& z32)|FtFu#0ljkV>@=qmN*q)RbTc}hi-D-nS zYaMV}sw@L*fu}L_SQIn0TiI>mTBKl_c^L0p#l{||aTC{^#LCAFM)Aa3=14=ahBY~v zHJV&+rcsLi7>k74ndbIttI--|Kk73E%x9C5Y}%oWga~WixD6UcO0Iy=%w}eOb4O0s z8}H*Wuc^aRIfziprgob~%3m;20xDVlhBJG-5tR>*++>FH@W@tvQ{Do51}_IYx=zy% zpcD@1i*Z1o)ASu~P*Y`8&tFDm_d}@3u{_Yyo2#1&-O!-Ruj;EZFYN{wy|3n;GfF43 zd*ghnR6XjlJ9w@cxYMAZn|Nj{NdB$b_deIUK9JW5sw_bZScH?OvU5#eg0a3TQ9OlT zgEN@C9Ztg}U^Wl%k1}mH7~Ri-5;M+8W)L`(o9Z-JMj>)vAfo!Y7O}Kouu4S79fF94 z)kz{@Y9h7uS{~7*_fm*KAIRe7OnDo1NUH1zr}0+wDLcM=2rlUrj#T7aagwF&62-}l z2!G6gl(D0Wh>Yuq(97+?Zlh$g_Sb=(b_^K=Gh=A@0P&ClNWxP^!xpFUdLvYhvny4p z^0wOI6v;)G^3<8LNbj;mCpBn^Ga3;gzP--7){N^T!gEGoS^SNn!80>H>16SHrtns3 zU^dslO!zV|B!CQhC=|Z3ap-}=e7DjRrix}k1sFKzD+cBcu1yq%3HH*Jsj|*IwnmkT z%`^9$amz2HFp2R2FsJcA)z5nox0~72&mC-u+i8#h#8_Lv2U^Upw)An7>Caq4x*`qX zKrt=Tf{%!nP))5ovEcl^f!ghcyywM$r|NPVv&8nwk&4j zpW&fAG;fA?OvjzZ2FBl4pY4zuo~2eRv1U*(=|5s5)>GOz6ssLn+47X6RR{hEG(jI! z@#z7EDmaokqKZ0(%)!;)%~3?6q0?#HO4X557~o8G%Y)jzUGG^{`+nLx7&6qM3y^t9 zsOHHbKb2MsYIpVLi1o(J(ILgPB|@4$cA6ezNdLFhpk!Y?l_AdA-;Y24Amm z+rqKUb4M!lHQBad6p3+uXQE~hdJ2b0XYXEapgKoj$sHEHZ_0ZvQUe_$-166*rVV&` z=c@J<8W!}qPI;}s%A&cc znR-K}s$j7p;vgdqS+mH2PvR>(blDW#w#b6%mN~LTUK>7Q##2Z4;M`x%?ZLSwhBaCu zDy0NP6ztNSRrA*iVc(+Z#ut3`B~Um+^U6LMNEft)#wkjS5uM;3Vb+FPycOpPo~Q%OlevQuZ4^m(o~WG7g5wHt}^ z{C1P<7i;^CX}X(};-+b*;VvL$o0kxx4{7g%@P6>wo9zv%!;cLTAW=RSgFwRu$wqAE zcqKdZ&65O?xt3)>?{f25(QQv#Y-_dv^si{?0sTI({kxH^6b*NQw3K^HT?|L7bJ?Mn zZ7}E#{zl}$5JP%JBf0((x!;Y=!4wQ$v`Yxr==wu@oq2%k^|}@o1qyUaaKrIT+)Pe0 zASq>a4tNZINt>oa5zO8(W7-+{TWw9Zmz-!JV~hqMQz1ZRi|U`Uka6wpPrV)^=@T+# z6b&~Sj(#yG54#jknNFe45#jB|RET(IO;B{Vp@p2Tt@-Xewh};eo1Ml8wtFwpe7k4? zKW4{%u#yF6>{c^gmpvD=*;ZpgV)RkC9$@TX@5*RMd(RtV_l3A0>s->y)>Uf$E?aja z^OZbXH-?O{YA&QyZ(Fw!xtFtbf5WwLG$c7VW<(mIELFTeX2CfltJ6H|)7U+J2V>Vt zD%r84T<;3mMCVKXhdO>!uug%kB_Nr&Ia$U+V7zlB+6_yqE~f(62-Abr)utmMs65Gn@TB z@T!y!uL3?*eA_0Cr2I3dN#`@C8EPz5zR_uVmpjbdDk|VFpXGSiTCTEar}9EINvWx( z>AI)fT9t?AXL27|xQ83C%(WKH;JHRMI1PvJ)S~uuy$6<~OqE7p+HJbhl>$^`>8d-y zv2|+4YDd?<&zL*bxY-j5kiDxU*j;81Mp}lI7|ff`WZnn{$Vphjn7dN#v{9xus58PV zmafoB@2Ao<`D+?X*K|6oi>>Q2fe>h&#y>*u<}h8UQc4>Y`XL$W(quMFd}~c-4;?DA zR5EsYMd@N$R8He>=uXm0KuZaPytaY`i1%jd?y-?1uWnWR-em&ZQL$RqtBCcL(x8&! zI2Fw2(}IqE(jAF{jt8*F?=a}N&k7jO(`xSL+KEZ|cBg5oKw`|By_pWnzhJYOyF%82{OpcUyl4L|3NBuAB{ zgJu=X&W(uk!xWe5NpMh;tw2O;Q9YO5x&G~je2EsI@>Wyf5XNsX-MG8a1w-fGizwfF z+9#N>&$3eu1Uii;@p06(D=6Pr*IfT}O_s0VxY7olK9(8BeCijfyvJ<2c2Lg5>eqt; zSO}Mbn25u>2L*gY%RMNd;R|d`m#GngI%h4&DATYN)rPgOYmHhZ-b_=v+e`%!7Qp5m zDyLC}f2Sf#pzR4Bq7(kAs>}cFG}(^~?VbUZ)RrVE!dM8kQ<1FIJ}GZ(4)$VS^#DCp znznjMXczkLFprDYJZkmSJbU~2Z0RXuC-;&4Jo`IaTerQojA)PG7;h3Vf$=u|W{YYcu`m{@xSdkpJ?1_Q0o4`~KPI4_z0Lr2B_j>*Hjj#S<@&2( zw(ZZr=81C*%&rie-rzbnWY_yB>3t?!$m6iJyx~Ic;ZLzya|I1Jx_L-noU+3ga7b8Y z9KJ>O)_k454XLF+`_dolX6*XEmw!#-lU3A*jYdj)&v1}EE8=m#z#1MW)IAaT*!s!t zP$FhrY%|C7FgqTF=Mk}R-1|m%WqP>S&V>srTIL%U+v(y+>;(2+)X40>JrzEt#B?&COneGadLpTPjw+jLkS24&V2tmlN&?7l zCWPTPlhME@@1W)}Bb>%XaORj+XOtz?zBE6nqO%W2#DGWoRZgIh1+Zb56w83LT%SfS zNFP>|wpVOvr=Rls@i;~RZ^xfBf16HUa6#Q?B#Ydj0(5Fzjl5YGsPH)J)o_~5;;zLP ze{?yuD&^FYO9YVNufRK?D^p#a8IIl4APT&LdkL^>`K{ZIw_py{MI5#`�fx<2<#0 zuet#EL@12WI3t1|U&Re|nummf`B_E+-};&n<0t-4PB&g`o)=AEuz7X%R)Oc{ zc{bk_TsE9(s{2USyV|Oo{+sK5_WDP*nbT>e<0iDnqPuywo^Pb%Mu=7raIDdu9!({c zzGNB^r_zrX{Yv_gxB|?R#yQ3aflegxe?CF$C=oJ(t#_cEc8lzdY1HZF!P96wxZJ=s zJM=G=0%;E04I}4UNS^ao3)ohBoA`APAoQsdRbePAol&Je0CO}b!jep(Mx|V0XS*x!(pq#Khaz%COKu$ zW85!})`@1JPwYZBkBa+`vPvJspWKe8IR4CZk!c zT#B@!o!jOq#ySJYE{%AtxsCKBGB28s^R-=pItmA#s+;u9{F)Dm9o={5lODPp!%% zyp~!BIFGbuwYn^bX^N(f1oNk>206dcH&d-rItEZlZyo~*B+7-zq~_y_{ZA^3u2vl2 zN_v{JeI(Ud&A=ku@?A6c(xeq=(s?vSzg2`Pwz%Hv9D8Uw=&DP6AuzK<1e1p^zz|(L za56z7IUbmEU=JQ>|7MN{TnhE(fzP1m91ncRb=tq^|CN@F|Ka~e%i0>5jMh&zGzwsFI(Sci;y*R zr=e9(v72w^&Jy&g!f_937R;C|bP@Es7pSJ51ijWSMmAmyP2~vM?0eaw!6UCTpQAD@ zn4E@~Y2ymXEwg6+^$9ygk{GC1-Ayr}sFE?$cs10lMb$fvGLXEf)_Xuam0#J$)A$7< z)A<1+ddt{f;D4A^58Z4bdj^M`tQV>BwKE*Ciat(uwx+$p#q;fpbxuYZGxSn5hR-k# zEzIT7>Z^FbwQu;RyJ%rI~e8V`tk@2vciYl}?w;B{A{k-McV=)oJ-FIH~ zKwGt|{GZ0e{p=g6y7ojQZ2dD!=vWUI8CeH~;21qshBq>8I5Sc9x!f1z8N^s1l@$pHn-Zb%bcboMkWGWS%7 zH=AQ$G!FQW_<0=p#QCYGu|$pCDYP5(BJm1cQ6&=vk?KqpxR%1Au{wU4R~-d!oj^T$HC7{!+<0YNI}OKZv{d9; z=6aV~AoH23K%5(u1_`bHjc> z%`@ZFu%+2VwXW5a+r)9%$#&Qs+88PQwD~$qAG2Vf-X<uf^4?-YQQCh> zmB;IB?X`pAEl-;ufqp$i5s@RB55HPu-{@aWR*EgrVm+nX|9c&Ksq;S<5%)wdFnSIF+7B}B<@XP?}KGuqzHTb;9f4s$Xsniie8F! zd6p9`nx%zz&`0tx4~r9$3g+YEnhXInPLn1B0!<6a&k)YU7`0S}(s3F;L#std+$Yj_ zy?H;Ujv{2fOw$&b{rMp6eV+0SjeHdvjb|eazFF7{jRo)kGkwzM<*AYi%|Rl78Wc)X znL!iraWKo1tbc$Is{v(nOEAj&A#GL}Dai0uvLf^akvR+@uR^D39s;Q20SU5dQx86v z?ZJ6x%GXL2(#QZSJcsKpVJAP$_8_4$31HYm#%~Lg42qV&VNsF8L>Q4r(^v_-e`%u3 zpfxOM86!6s!X2iRtf|>Aijs4&CvAqT?L5Wk0pzV@S$FJ-IuF>0;WAa8B+*a8AH|+b zi`*CIkDN)=NgeO`E*Evu#9dd^Nh3D^v|c5$|Fc|#>}T?#PMpSnnnqu&i~`<_lLx^qW*O!7h=d}OjTj>EcneHt@d(co_X0?}@hF7# zG4L-NwM_G!jatz|*ui;2PG)b^cv;r!fyNgs8e48Q()<~Fhh)^+RI9;0db~Ses3MqY zmq|3Yx8~ZRj6@Q+7Bmu5VC3O*Vg|8GQXxaukae0SZ-L-b(JG1X+EE4A{P3oF2HSN0NIzFOcutlpX(9Z+Z7!ii?-C4S$`!q7)hjKKDa%2HvJ;r`77n2;F z*`jxT(WALO{7WRt$qPdI&+loq&a^tzQxER6*WbFD>zlcjGq*SRHb_8i0;0iT7Yhwt zAy>6~%dKvyj^=Y((^{k;)#5Z>#0#bTjmkPrA8@odYti8~NR*WK zB7p(Dn%A7DS=eO66~W)9_vnDr@Tr~dG(4z^z0D2mk-mmUAkS&KE~+~r;)7szrwA2!(}kl@`N(&Ij;+Tc?Y$em%z@$9_;d;2f*N&hn#u8p zE~>_8`IG`CjG@PLCYUiqN@!}&xlHI}Uep2PyqRX-ycj;o1H)r#qpQmrM5&8olU7lg z8x$>d{S?#RZnNTjw3=WqFPluJX*nv+=_A+sG@K@IM@Y!oXZyN#(_Fq zW^gB$4&aw{ZlV#xsmwjB)zYo=jDD9=n+^(dgAQ-poDa#!iPHm&Zwid5lY4>jE{k@~ z=LCe|1@OOB*p@YKA9)9(k;0zGuN3wJ{4%4}YvG?(5sP~0_9B5{(%g6O0$dvqGp%hi zYA00=DJJB3xtEICm68M$}EE?uQo{QFnlksB43GsPyb8B(9YX^)ZX>7IiKKgTa%n zsB1MiG&<0TIwSgW)d>dBQVg`P%{=A?aS>4KmGFYxLF%w9LCJJhE7or z9-CyuTO`xND?up(8%OwB@CRP)C?Uk!rH0)&N1$6m>~|tvVl|;_)_*2L62}eLB-BZ> zYm$PT5T~8Y!@PSfI&2!P-6WFkUd~DJ z(e@e9fg;Sw`0!Op0J_w-w#t#?(BB?pQ7Es2MpB~RY|+s-+Le(J_V%E&zZ!)adw8U% zEf1hKoA0e>DXcXWW4Xx4f);t2A8;7Sf6GOigWt_E$jy0+YK9YV zC?FtLoW_vEVxe&nD8A5uCI|X3*lU!q+GT-9(kKjTj22>rq<1eQ-lW-tQ6@shZQZLk z1A6tQWL}KGW~cF6z$AQ{Z<$Fb#_|EPj=rew7{N^{3T72rY-Xu8HJr>1891n7pM9q68=_##UOu-SS zmGp3x|A!AuY{YmK&az1+-adI04_W<4dXvleHzK}x@>sm&cRv8xCzU5%6IK7b;+9FH zn#qhO(|l~&Kd&T?T({c*c8Ry#J~Eo(6T+zdS0w0@&UufTN##~MLsaILF50pvR_kh7 z$ZfS-{_Lfkde2m*ZhSw&_miC_Vt;JPJFjGMVLz1S`!xfx9DZC-bG=sBsjG+M(1ki( zBY;Q-xIJja&8D`<9Yk9lx46iZ+YbQn$eyw6E!18%d=srjqAdbIKOv4jIA|E!x8+9d zGMD*Nieb$9zOry1Pd4+8W<=rgCyk7cKaraq{5cLMXNNXRME-{ByfwjI`&CC7ro3-t zoxsrEcn3e&!<@~^b9H7qD-qQkXZ!l4yBpuA%J64l#c&;g`mwYt{KN*huvoM(=@pioKsu8T>)`GLlRik3H`&atEIGAS`mp{Q>mGUnuKZBOl9OGuqqlC9E-WK+cXVz_so9qo~?~TNm*DAerY3Ht0$yINTS;`SQ z6=^5&D*aw@?Ea_kQheR?e_N11%`(JB%@m|M3H6H(4KT-xSO*Fn; zvuix_84FXhWmsj}P&ZR5IKRrtTvDQ5zsddBN`GVvMV;nb@I5Bm-Y!kHy;sVyN%&lj zE!i>v$1=tnDWHbA-ZFReLU;5MmqhVyY>vbuFNK_xcPT5K)A%>DglqCHzwTrdP|4xm zPKG1>3P`nEd8p3hY3P3~UogOW5}|btG>7v{8D%=Pw-(?0Nu~afW-_ofzW^r4RPH^G zHffx~yLdfwr_OZ`T*ZBavAQF{;$=pp4;^=#kqamB^Z34e z5q!ded%FBnC$pG4`gFy&OrOT>v`y18DX*wn96bf%X$ zM6{Ulem>S|l)CGt$+qI&H0d;b0xZJaAty*KbB%tzwFd}16S6}JI?3KDpmIjh|MVWf ze?u~M0LM`+0JcL|08f*1)cZIOxKvWyO#x2B{c_ad!XLdNHTqSkV1*mI(J0A_=nU;M zet@B!VqAUOnY}M{TA17i)I?MHwf)=Fw%HxsmKwc@+S($TBAMr*27t|RpmDL_7ygv* zyBKgIFiU2qz<^aS;5zP7-tVQgl72;T%a9TvvQ&JK@~;;YrUqXxCQSLai3wAKZxa)y z2d%0(Gi8}D<=r6uNf0~N)&VcRwJE*;_~RgbA1-_+x$5mLZDPUq(%!PT*EXM5k|Jv> zy(MXHManl{AGiPcdletI|H!@4gWhu*@1no(&59jzrKJt8~<`Q|0uWOgFzEa5yzYvcZ{iIDNo zfp{-;R+ZMxTFvz9W@8r5TFd$A&Yb5==dUWu%sK>w+Ob%?roGTTU@2Hm$A8K8RJd)uy;nQ2Cm;|sKcwRn9wq$%y|UoN9~9tESDTS z1x>eWdhoF&$w4b>5@S}zO=_={bC>APC=8=4&=1laP$x%!t$d71MVBj%+5e{kiEwu5Z1-%5^Eihyf;#;Mm+!_(Hs`K$*t`1yshqBE$B9 z+(0dt6_eq%w@_SyCXr3pTPTLR$kN@h#$uUioLIq8Os2K&wubR0$_VGAysOk$7hha< zFlk%qPIseDOQPO8Q51Sk;W%974sVH)O6_C*BcG} zYksVTu0G-*Mn zGjAd+4NQ@`);q2zR4nR%N&;QlrPAJITvnx}U;?Ys*3gaK*xQAE_k}&q8~I^4nt@9k zF@!x0mW^6Sc!r8}M}=IHtJsD!r8-&uvXfa&v9xB1S3yjZsw%w?+up>q90Jvx zR8kxa-Gk!gq#6t&72{+k{0DoPg<-dS@(5AcPUvu?>_PvyvWOOy!x!=h?`EdggM^`7 zKijN&awObv1PeCt`nT0#*H4#*r_zkLLY7Vk&KO-?j?PAPzZSg4ra{>}^FUKH^luvw znW0BI;maWKvP%0G^*Q`qch~TNPGcQC>;l0mTrx>57v+JVk8yl1S9=c77a4k+R26Sq zUwE`Xr0i(_q_Se*8twx|gcU2020fFl`W&x+f0KCDnYav9)UW^skjb1O4!F?)8YU6! z)q2{=AlFC?s_FH#Vpl?a*=Vbm(Z@`BH#eO?4^{6ey zS5@S+h0gjxXZ=hYA2RV1BL6}&CewJ>A^7#edoqXjx29RV|HpXF(p6r(u+lr5xBbJL zA-$buf9&AuU;FyWl9~EU_A8!_V&2f3h+_)K@-K%;gOC3 z6Zjj1j6WHH8*$>XhGBLfkZr*lrqSWwXoQumT;&e&2%|a zFFsbDt8^7UPeWflHhp*RA8Jv$hT&SgF=ZpVL90gt2tor2^*QN1gS>(|i=2k?4^h=s zT3YQAwA->q(C)?>jTN*Tf2<^-@dcu8Oe0qSJJ@9fJAwp(6?D-n1*?b3za?YtxI-FcUw z#h}8J-X3-AO}VzRiK?_$>Sl}P;_#MZi0h$c%jF*#x{h@-dw4+mVZ>!o6da67dIcTI z-oJN~LDnJsSY-XQOofWBp949Z1vzlNRiM=h&L=@yPrP+3`<5b{E}4N**1zUJ{x7Wk zg`|<0PEu_HpY!Ei{5(DqNCX{+TFSE1tXOc+&&fgirw>HUMGo~_i0%+u*6o#Vp-@o! z1J#m%dZre7Zt>!R{^3K^PD>}|`nW8(XN>9fd2*uv-d-oTW(2|2_V&d_Ud`5Z_fQTq zLz%3h5T@odo?_za(^X6jfmemNCj6HcJAelcCONSxsDZNK!4&23S{_qjFj|j|yt=$N zEJ1xCoe8Q@znfj=F;(ndms$2HvOqpB1P4UzM=n zT^`IB6t5d!`1Dm}9sOzuFTv@jM8|R#o`~C3&ce}K2F7YQ^m1}>$4eZh-Hy$S!AEfN zCdOKtH&(KbFYXA)1Y7^!Hj01`th8~((|5r$sRufP8-Hr4(g#xiTWsCKH5oj2K71DC zUo&~B%D!oGkaa9EUc+AgLQ`}0zL9lmp*=Aj#KFxkReFg^@8k-ddc5A~_1)$x28c}C zQ{DcvWs+C=r78bnyj61oK27?6*u+oTzh4z5+s#9+bg377t4qDqA5sUTMhD2*L7Z>N z0Mhs%mPsaNKHuUrok5Gq?5sh@WDg#Ms+sumDqAI$?3;LB$0}w-+8{TK6xQn)I_8gFm|ZxlCp+&9%5VaUo!2wu~eWj(fqJj|&8t z=zHqxtg#e`F|5^Sz)``GD^|02%XD>d;sTD|ORRRuWPQrY)!2fMJlR0qB)?pZs9x*( zX9Q$-k;y9N=bTVw*naY#v>=$>3(Uw|4m66L=8d|UAA)QC*zD&2gOq3Xy#!D19_~|! zUi)gl#Y*G-VUXB0O5<%J^x6$Vb#k*1OYd=t6QREt-v;M$+Lj+Hd8ae&Upb2W1J$HS zE~LL%sp-dQyTD!bCJ7A6_?j85$JVrpbZlF?|D@^Z{&Qq2^E1!>wAvp*QHK?03!9Vu zEy?wt~$WTtY1Q*gObw>PwK!(8pV zN&oNaPiFm5HW84wIk^fS^d#nVc+<9XNW3#=G6gu5{0DA!7^JuYQe45=okdTWF*p-n z1vqURjwF`@RFKLR{+{Lvl8<4^80hJ|y(VK93j@Qc%TR3@=zRdH9c4ffeD4sE>;sVO zcxpi;&rf=jN|WB1BS2|Y=G|D^yZclQ>WpXJj$ya%J)ymDKCRS=B^n+80u$ORjX7Co z4q?ArFqIplPXCVfQuB*5U$8Y*?5mO`xyQqjnP<0i+5uCz?WyeLvGzg%zK*+O=L@y( z#|M3u_O2WSHm8#5@@D$(4xVit@h!$7HMqq(;@h0Y<7FYl{vdS73L+O~fphh*<$~}p ztxk@+)O8v*s|fQi5lGuQ3}YM{-Z125g1Js*F$bhCPI{MCFHT%U73t;p^n>eOS2axP-)wc*zqjz-(&DpM{>AOOqy?{B|yKp50{mq*2bCx2VZ^ z#LN}l_JzU~1i5u(<3gu#39rzKLfD0-&r>Rr<*zuIYs}50v6H-!^XG%7+-xRglI%#Z z<%#Yy7D;}EjhOC0xG?-HVwKUChTqpkXM6Yu{bt(xg*R{kcl2ZJ7b%cN3M9tb$-ydP zdY-Ww2^p9PWjNT(1d3XIQUuFcOX$1p#uB=U1ck_kQPvuIjHUbVQ_)g(=oxj!T$#hq z;|J5p;PeBf+Rv!wyaMvAF4>h0+`Cfzc@_7TWoA_{1A9~0*5O{?m_HqyhDCTc65d-a zzir^I#jE50wD$={A4b?`hdBkuaXLuaoDO0nAt+#H&jnM{-YW_3Urs~7=XHY%!?pbO z7OKN`5USz*@}>AwOLCY;Ge*e&Qp8K;zd^<+V?-F0f6qJIK@MT3v3QE^!Dh<=?)_&C z;GV)>>IPgL%lhF$csoiJ`C+hNC{G^X351EYlr9Mtl!^$?sN$&C?@GLBpyBmkrmMuQ zT_v0bof#3aL~+HVvDzWj0pY(I9PrvJona~c(q~}e^BKjsfX1v0o&`VQk=-p$m7Zv) z%7#`o%SI(ll>EfhmS#yWn}B=OdY98iji{3x*K0RBUu;_cB9BYSl@^`A`WnmDZvCf{ zi>A7!N~#;vTFFUU&Rs!@<*Bv}{o{t-k~p9==ra&15#)bu=2!9trkRGL{ZmBnI)qdYkSF&0b z?o0KwGa&p7%o;70QzbQgVsL(+d~gD^JzZQKEU%aE%sRTo)T9-jDgy9UgfHMxY2XZ( zf79T+GVDJ8qwgB^EMZ9ilNoDh~vF1xL zKPL5W+c2VeN?~X!8(;I?zKR#_P`ppxOff6NZH}Zkk#*g=@x?gprQ9KoYVqtab8SXx zl;ygkdU+CWpg_)(_%@vTV9C7kH3yg;oyh=J+X1YJ7q2iKy3+Q)V?^_rh4c1dv3>h4 zHHUSa;w{X)S=zRth+B@0Qp$J(9$R8)&9II`>$VT&O|D$SikkgR8^^}HWo;WG3ym>P ziZx%@uX&0w(2gzabI7NH3dE4NWN1M}tf2XrSo6>N0p;e2kyRItRX`Hs|FS~e@+};s z;>;_})@|&z9rqD+&-JdPP~h#SX`E)NWkzU_1N(|@$#f#;Y$I0->vNOa4M>EJALxU$ zhjoY?$`;*tdG`n3u^+6Gh?jjEJjMskU_M|qrj)|R=hgn7R#W@kU4`dT`1!A!&(|vV z;#xB4BgXubtAaCLe#J_@Os`W!dgf2>jv|T9ABpCFvq}qUhIbA>a9t!Aum`F;hi`hr z&is0vD)QC&lIc<1tcwb2zL}G`wS&~t;L(4+(nq4?udXjMtJw6fX>E7^n5$ONKg@CF zuR9DHX5VqXJ1Tb~!K@1kY7TKTERE^-klMAK!~ZK+vk{3~UsuK0|Gg{j^WoR&Kk(gq z3pLgP#78=w1x+j!PV*19FHKSNyDyeLV#kaJ^Y6oJsQgD&c3q0vpqsi*1 z(1G5N!W9=p%BvX4&WlaaWv;%|nAR=vl72ONVX!w2g-khwB{{nF5+{kf<RoR#v`q`u}1BsUQ)lF z=4Q6eBTaQYX*NC#9k*f@C@a0?#;eQ;qRCZZvU~+b9cBOr!Em^ilPLfmOw1}U{$3KE%`2G)j}&eEVRtgikmP zbL6d+-kSKT_3843PSbLhLlc8OsPs0k2;-UcvG~^4<6~Y-#5ngeJ)SUuW-8Qr;+$tG znDS4Xp7I~6KcRvG|nmR>kYyDvY;w^rPBV4wMeh zEmjMKWr?yy@h8wh1y9w1yttG2sB+MY^a7jbS{lW6<2lt9I*s>G6X!?AIT#yXd!m7m zlf>q&EB0H`xXEd}iI+wq6I|-gsz{CACfACS(Lp)nJ;9~o17sG^2f5ip1|`e4aJ20f z<5HQya~;*#cmd-#lT!kg&E&MW%catCKyH5eZ4+FSn2$SUtZ}D|1&lzwb{dpB9cTAU z*T2TNRlJ#uYD*jbkw^OSM@=0 zI(zU<{@(@bwhxLcoJa6Q5{y#nd8aDqQyrm7U{1H%9SXATL&~@F?Sab0fGk&OGAM@oCOQ^P><{(nf8{pOnxPOa9 zUZ*QWaFB4rm0ZjN&=2x!yM*K;9I0-=MArPOI@h6$4e>Lp-P@ z&TvHpN<5ntEWgZvZivVCITO&xVj?Ht+KOasQK~=u-QVy$Kl4;m|Jz#akN6VbP7?pj zaX4>M{fz+SM;PJB&FR?k)VQWr!vHt665CPY9>K5&#+~b*O%y-NxfNn&r|~$&IAk9h z!Dl!T*r&*PP4N1{$h|eGkY+e{vH4%3=q}e5OS>!q^9~|q5%Gcw7Iyn`Z=L(;tHw>% zpfC>@Wu)8N#br>^?d6Kv|HtQV6YcpcAU4rBxgs5s^KqqOn^=N30Q4u~;tEpzCjzNV zvw=;p$lj7uV71H~?s<=K^uW zfg+C@bm87I8z1G~dY67$_ZCX%C1;L29DTUA;#!X-3}zyslh(gA2AVoHTX+|bd;7Oa zd1X9|r%+ih5u$2>qxZ|nkN4>sOf#SJLrPQL&qf%<(Y9VLErG(iw6;SDII8C9TkFzN z4viizt$Eg^rQBgES)!77y5`~1YRBWgfrAJJy4j;~X-T@&;nzrVn&)5JAHn{$bYIocW7yB}Mj2j&I zjQD6`w|C2gvsnk1sVC>-a=jVViyQx!x+Jix68P)?!new0o_Qj$k007(-Zs|h$FuC> z8z$f+6!Wgz+yK!RR5*=4rN<_%`6cG!eW&q0ME~N(zo^DBTPn@$Tp1!?t@IP;MEWm? z!#v(5A|hB&ke$@Sfn~G>);I^{g+rLv8Fjeyd*O$;hNY6?^DFB6p}0uTg(})4#U(}6 zpbbqZu2IbB&)`y0-iY`0^epAiK%$Sok%-osAIAONlbOXxLL-$HH{P$l=F8Byw<#w^ z4}1i7!cwPX;#8;PnCVW*^>vhWN^UcfVYkz!awv?sEHNy_K{V4jS4Je|lw{`XXSa;` zVz=vchgr8oKc2Cx@@%T`Q3i*2#uEK9WbA+ir=eL!`&GYik_yY2;2%>;VLnKVupYwS z;-p}D_v=aB{=nTIGSj<@Dvdv|*v<#<*%KGY)4)GcR9Nf-4lyQnaLRCAY2SO7$#M_9 za0$dFPZVHi)6u;B#oi6q@}gqw#Y3E?IVzGpz8IhTHl7T{zj4XGD*Ycq(P;FOXGYBg zacr0_^hPSu=pD_GN})Semvb0SJdC3JFDmZpNU7-vp@!pbFu0vFPm-U=G}q7SK`xrO zVXFx;=-KpQ!=n*peMQsD9-`?7sU)I7<{N)KOKv5s^o7Cs-vC0hiv>JGp#X2t>3Yiv z#jgf?4CC!Nyk!k^UdkJR!d;8P1xX5B*mTN&@U=#v3*OPZO^jzFSSd)W{gzhiCNMKB z+T}EGfzhQf26@8z3S-EzM|SuSN(Ym7qgjPVvdebNQpMO3p<;qzE3>B#jMu$;74~Ik zeAT;&L7z`*8P7h4h1l*$h?y@Fn!9iK1J>-jh+*jEgr=D&w=pXf3-fDLel3-EmpJR} z?)legdVO*J>!N8?V4Ro5-{jrNJ>JbdiqTn&1)*Sh7_W`<`H}~5&mFmKI~nYG1YCdn zO9R(np^7=CmK?|j;hi?Y1G#9EU3z_%_al;l69%IBWw-~oT}T`H@fn8V zh0tKKn4bSDGixkHbQ{)?qzioqAvWSnpR#O3| z@jH6s_VPhh#G0q|YpycxBsVAEd}9)an`zBfRsUuTFKk!KIvt|^6U_wK7f+#30XjM3 zbT2z&aUOYr<45lOi5zviVevht%Bo`C3T6dNBbuw!Fzc0=5AqOJ6^1uaq8p9Vj}V@M zTO5sF4u2iNN{Ex!W+I%9Gmj=#Y0ilw*dJ1CPc>`MbC%frvXno)IP*jSLyy&#B1Vh3 zqD*lu4i{fH81(XE29ut7rL#R_3IbPjj+ZIaYwsbIN_h{dRLW|#@Vj!znZmxWQeOI; zp4Hi!grSV)MhCzpCK1fuD40me!ELuPt%8c4;OFsClnss-bG8G?+@*>On$3Tl`Mm}bv#1F#2hwz6 z=&2%iBeCkn?*c{rQqQgNKZN!)XQ(TNDDq7CaFX!Ycqe^6pa)Gnk417s0Y($c%oGWg z{se)s4tGm#9pixiH3EMNE)yB{R^ZPU8@>pXy4Ep1{unk}z!PhHXepy0*bIx&*Jj#f zHRB-Jv82BZ?}4WCi!IA9<}{qDPITEr#c{i;k(GTE9Ji2FjUO6ODjP=&8zYfdMmD^s zWv24HE_mBf0l|CJ-q7ka`Vc{jnPBX&q>-YlwykN)T1B$79$Z*L4oR>iK*HpL`Al-$={m zeE0BgTmjelsKC~6AJz@>79?z?fMXW;3X&gzjqfuYc^vR3EUMh)_riXh&1z1=Q*8Q# z=1Ri9bAd=O_+QBG)t-We^?)xEG{5BoSaT5j`@m=L_f{~|VK8geVKzO@Ev{GKrTW7swYk0Vvd$GHpLko_k{k?-9i1%`5e-px?|xW_P5 z<9Ru6`mZD^>Z8xn-l*=+cGKqPXd(9Z_OoNVK0AcZI?`4;i4ShaN(cfV(J_|I2;m~4 zfx3bC1A1zJ*scP5bieq1?#2DQ(20RGxO4w<9$QKx8=j09Jb3si9QDzNd;5GjG4QL- z>%O-R2!J&F;kXEDOFDm?KY))xs-Jv;n%I-HU9QJa&_DFfVJ(aT(-cD zp7Ae-hY@adPf8dSD6Lg)8dt29SSzz`d$O;!0S>oq&_`bi@46>Nlm#_E1~AhsU^o{3 zCxD`Rm2>2m^nGVz`ai*o#Lc@H*pTlIC;z`_FVD$;*W$jM{9hX%Pu7_MvgXmyU9a)L zbq+t8s&m?R2b6y;eAhi`Ca78x>27H69U5BqY+qy8k<7k&Jw(T@k4ps3b**5`Enq>h zxJ^L&GegM(+Vnmfv!3jN#_b2&=r}v-SUCq6!rt8lXMLD{DY)eH&tOh&lcnsRvRfyr#xC-}@6XOr? zrb_3mVM)_bVhsHX)NlA(A1v3#f{2(^d+Tc6k+xR~594cpp zLKEGTf259B8hCD{^UB)z)_<^5n@NK5DnT5NO`+Yfq zr^d`DTIC~W!Adu_EVbVTB5QZYTA(4v`#vqiN!`&|x!*ds^Ch<}C{JZ4Y)bDJ#G4Cu zpV(YEpu}xk-=9V=RT743R=M1^H+6r4TAj)+Y<9U3uQMY=F$9@EU2o8;h0#TiK z>FP|E3U~D9Deth9N47xk!V)3~Ylz<~JdJQZ(n+@bIzc1osK1(WHAWit;FqIQu{6|KfA?Eyx(IINJ(enOFSw` zI}_SdF&yY02H$!2ZM#=VC!cb<$s%?#A6|HvQ-3Gr8K81E=(mCc>XM_MO=o`&_AM?C z7A`*!Eor(*SqgSTKEKBaUESdR)xZvw}C-l16DVyB=R)Ahy+j}%u?o!eL_kEZu z|CGGWE}nDF4CBU`J;tE#IE2(>JT6E|Z=vP_mQ9xf#A0ofPC*dbuQgQxc-|6PIHGnu zp^5$7$FComyiR}hc8bC zNx~iznk)ArW5*|*HRIBwUrhRmfEdRh>81HMiR%PWeaDhUBh9}_Tqm}1zm0qTP1**H zhqsC!wytrrlQy~gPcCMmVpoVeh(FL-*E*uFL$HEPKCQW1i zNZ*i^Hw9YCk{<5*p`Tpw85lPig@#XI-W;FL3I>9&EoePkr^8Dn<-YE99(?A#nL6QZ zI+60xG4KQrTwJVGk4dBWS3$mqDzjtEn^YZKTp>Afqn3YMMbi6d0u?oJ%Wmf!X1w7ZkNvmxHoTU785bTZSVfsI8aiWut)&#FHeb*QF zQzrN97nD)DhFeujW>$b-;~!kcv4X&(^GG$T#*;?a>AP7sCY;uO+ZNo$x9rZOizSIc zTQhIP+TPl`a?qz=u?kbOyZwGU&YGpRM-B4P(Oy7~1J?{Rv56Tjp~k1HTmF@-$Xsbw zWQaPv;a&t$_UaL)+@vZtU?gqW@us6~*l}>I4Lj!CgewUWKKIpuJ5SM>kdeR>9Dao6-E&I0W~sa8=;%4ZW48x8gTi%K2maN1 zyK`a6vFW06{ehrIaT$ISF2v@02eH_OiOMv6{?4VMA=vEjc@zwO^$E_A7HVReK0mDx zIp{K5bSD;V&a^AL)tGkca6MSluDyV1^QodmgDr)p!6hdL!Bc-#c-j{jR9H{Q5f<=B zd7p1=J<~{C%}>fCR1u@2+hNoRES!OFCk+k z>M`jdi;6C->PB|In+>%*bV`m|Zuw$+w}Mb)qMg%KnQdPf_#_&;7(tAQu-T-4xsB>E zwA|QsXSSRWy*7h%+3ug@R?FqMVzvB9etNE!Usl6XTJ1^X0Y)8-O|tXO&5{Djh6_mk z^kb=fT&xCCW+>7HDep*D#~+}gI`T?j>DF#iJ_(>vC0TQ3{4AzVlZrX$&MXm4xU3^EDBe*&whUtO5b4LGNoyL{$zZTfTX4ru z`qGaP_@?JH<2KBLPBdgIUy1Kmr{H~~72+oNEGUmDAYe7F&JR_>Ppn;B0lL~%o}a{O z`RrKcT+4M}t|dIOC$A2EaJ#JE+EzSJOHBNdY>@6~4-Q$MQG+Jh!+ip^r$1M@`z_Lx z=+&TMO*AEHHI=vT5a7`!!`W=t+Z25M8bU8KYd#s9h?9Jz%bsT+;Yokj9Y*?x;9$DJ z!5NDPecA-oZ5q|R5Lv`ZkM@-BX9u{x=V&C|f#mv32e!r+= zm@_IWy{+!JJ!`(@`tjn5=J6xkPBu)QTH+l)0>qS>8J0Fk7X2zNkiMwXkroDjc;TPW z_GWKG#}WeZrtwP8U!tPg!B|Y%>Gm6nux)-wo$mcpikl1fGF6{dLW^x12hxGgqh$Mh zL0XtOmqTP7PvnFpzW{O6mRP^8kXhU|>=+wzX^|fv)bTz_CqtuoUg;sM%;bHp?_KOw zWtyw7tH{5+W2@oEGNE>qX5OWiDTc@KHdEu#{Mb2wnDn4CEks>w#CAts1J(NXmWV|B z26OySrT>k1=Q4sEW5hd+o4{P_1M~I-Hn{eC+POwHn`;xth3j-Jq2QGCb4rdbaY{}o zRYJ?@acA_gCHyyle^W}+{<+xX$C85QLbirpSeoPn7njXtO8i%$V?>75T~Sm(-SWtG z46sLu8|TA8MkSnz32M>_ksml+{*KdRV*bt#zgpB`m?{#wQlrA$u4`i1&IH731(h`Xv5 zDQx9@DH&vL*IFQWDUP#Gk^U9#I{A<)u zs(h)F(c_fgr1q2k5ad3Ya&B0dDqj+Ju4_w_vNuLqLzKoX=@+(|Sd~Glo~e2#r?RxM zI;dMux^Ys8Hzf+Ud6&`o{dLS|zf1OHL^~XK(YO&shT$=;iQRPtPTev-aO)QeT1;Nl z9VS$!mswLn?19dPusFA9iGj+R;DYZVDs;A3!%b>0@w|WX^6&#HuKNu+6L)p%e^XKi z+?^(!Kjr!@rPQAC>#Hbi;!YQ-Q6hhEuet{vGa~6s05;ccqeIwZ{pZEvPZSiC7AUu2 zrMEh>c5Je(L&xjIl9|^)#cHPIhbP_EsppGwD<=N_s2VgS8b)Vx^l2VpNKI z5;!^PL;XTg0C+FePY&;Y)<6v~^!VZ<%<%phJoSBHe1qHGq{sR*znK4AuL)IHVD`N< znWQUTQ-vPv*5vXNrF~`ZdMY~$NRjaYC%~Fu`9T8KQDAeGfd<(?vbY6|yY_8z#OKWS zva5}5ZA<4Yx^{$U$24{`jzWpV~y7K zYjGbAy+1NO%>Iy9?z0-ZXG(T2a${pWX)d{A1$S$yRu-t$l1)U)kHbyr#jy)t4@>lOa3WzZJOprkI+1xbow(3Po! zCXK+mx{#5ILFI4GF=*=l#-QTP%@J!Z)MkyQM-6MX39?DRo_$FCW(Kc|i^-9@IT&-0 zG+9Ou^e5uPOcy8G^haK%f&xTDc5z}Jgp{P#FyrQ6;wTHD#@8(`Zh{xrT3)RFVK*<{ z*Cj`MB=Ah+Fzz zuZ)ONHZD}B-BfSfn@`>M+>>YDT8dh9ZQgqEj^F>W$M@&;@qN$rqRe~KlHLnxri)4c z^3qiK))`kMF-Kbp$2yO!j{C8Me>|Z+EjHY^#b(gFRdFn-!M7^hI63IKnu=7`Jn~*| z`=Ebj{U#f&O>m31hRm6t5wtyK>6S&xo%t?Qv^~B5IX@~+??3)W=|S(}q=T_4TW;U$ zTJYVmOVncgA?2=p4qwhtqgPjmG00q-^sC8SyT-}fOUzBupFY;#=V}rnG?z)EwY^p9 zvhgzQpFJX3{#oti#wh!Rx|+R;bgx@+#G9|;#Uuqhgz+`}@LKBi)^z2d#Zf@I)HWyc z6H~CFw2~yW31ynxl?H64yXUoR<2=5O6sK2EH`zZ;BDmQJX_uv8gWAJ@Ukx zQj$c_uK%ERKBW9xwG2oI<59#s0&XYs6jhTJ_Xvf&&+V7rqf~5Z+IL486T+huH>GiZ zh^G!cX_T4woP3&>&?PoR<7T+D+*?g|_P%7e%~K~Ar@A*|zwl)~!0C-EMS@ zg;ef)qzls|t4gt$Pc4yejvF2vVh)=4NGns-9SvJ%*V7!Hy;Y>DqN5Rr-10xDbIzPC z>P+?!)~SYE4DyGBU!V$=;?%4wfx{~fVB>GY;rSpVk#H9hZ$L<}fuDQuI1D_lbedNg zunB1I3JuQVZ-U3mXs*&*Zt++GFrCNWB5&YMN_eP~yUqHu5|gJ9v$F^TBsFX1nQ6Ud z0xkB#Tt>>E>%-2DXQ9IuGZ2e!G6@%VMo?Yi%&7;0y`lPG*HBui$U-$^ zv}+H4jt)Ea%~7J$_yAw#o?D94sRx2}${UsPW)?FII)oWZh`nYeKlXW5amRYQurBr= zv}lLad^O*eP%vrv>I6%jT>Zol@XUF|LyYy{7NfN|id!<~~%HUTJ4l-4}$^Qe92+36&Y_C>2 znX0Z{y{TT6(5n*DtB0N;x)~`D?gJo9IzIa4dia9yBH|gC%JG2`8wAxGnWOj&Z&mOf zpCx5pS;1k2$ttr39)6B@wFTK}x~Fttg4r26?b_c#D0<11u*1x?{<61_vx5@K{rge^ zv+kz9YxP3z6wEEwm9;>toO-tsup8b4P`ypPM!@2&`oBmC=gLi&SCjUDNo4pe-?*Kv zWU^BtyZkYmFWU9RK=TDD2UpN!xE^UPUoZ|<7J!RRAnG|cbJ$XEtd&1QG1eoO<=_r) zTd&S|ue#oUFm0(i?Y$n{!?c#1bXcga_W@gm!%wsyrjsPX>&UK0?u7163D6vVyO_PD zDesNoBEC#|pK7Vi+oCUbXW11;nlo08v}M8SxA6RBi>B_Y9x7K@u-HDiaJ-(h1&`X> z%gpVo!907r{KtArAiKRC#OF++I-aJgLn+DLgy2g1>M2Tg+`#j1ndd8lbM5oH^?ZR0 z{T}`yW6z**iF#24f~*QRJDDWmahyZ5#m;_GDf+*@bu+2Abz@>>IpPU%W(=IItc>Lh zoG&nNHmCQ$LI%zu7&u=b#GJ+tkdI$!nn^M!uQx7^B~*jqwxw0!A#vJsjEW>7=p_kD+t)@{9{)&&uK( z^<@^H$!D2wDV)=#)9UG8WGTD{0Y#R=j9-gu%B-M1&xpi}DEQ^db1yTBJbUDbu2#OA zYh}iMJLq+Ztz0sC&I*CC*K#5)i4C5KxlZEqq&F~0YUhM^){d$^-^kjFYI+)3my(hu z&%mljuBE(eiZ3i zT+SvBaWEw+_!I@BrqMc)W`35^Uus1-4L3@X(hgJDz79w?R16W7^B_j*^2NJ6jDp!k#?L` z&B_QMVPmfONQ>v`(HEshkGo%*2lq%XJ$e`wn$%%kdX!FeSpueS(xjw)PoRau1xnxb zDLLrT#%LkqBM;9~1W*qp)?J6y#V9dOWmOG-&egCnssSzAXjB=YmsZQZm*+LR_SZ(s z#t+YF*#kM486`AgjFi*LVBNpWZQCAQYVReU;4(N+1&GJz=kbwHNpSUAQ}QfRd0Q~g zemKqCz8c&T)l-Ht8_0LdxsYD0x6emYj9q-eCERxTw0h{f`uCb?#mssAi%XN`A9Fg8 zUGQKDK(Bfj{_(oYM-lmQ9nVpbqyyz#mT$q*cFND`1FZ>vw}gKxQ~q0T7HJQ@)lT^z zyq3Gv;0MLh$w9BzOipFZqc|yu+ct7q#=D!M^jz<|-g7KGJ9oWLEchwM5vEANJDmwgc(<4k}NR%n~Vke`V2wmOEc_NrTt6TUU z?8fKE)h&1MKX4WX+?v_j(*(1iQ1loDuJnCdH`h&+$iadDQkEJ8S$TFOOp(|XNKy;6E;Y|3brf44Lyy1aJY(tI=bgvVqYuEuhUEM3iM z-A?vV7sP7zL42`-R>jE?tCFJ^rA9BuOTQ=?tE(2l+2jOCZ#vaZ$M1K@HqWMrYO@B`TSY|3trK)+ll2JWY{!-B`$b21rn?1_py189tmP(`ES( zCKb)7h#Hjbla}rC(yoF*Rq14GA2UDS6C$wl^Fvvztn{9%|CAPro$Fh159~v3hqlUw zB{hdzTZqFvfV@^V%P2%wqb_$%&8rwR>-uQB%8@fItE9@;yV*-IiVl|*)Ib5AToUSZ zD?m32I4YntdvT0|EKVA#|9|%l7zN#o1p)w`N?5iBmI_p+0Q9 zTB+E}aetqOlqgT(C+C?uI=kvf#$KK554%1YMW-BTKK`QD$I-W=>BDEqOxx$_@^$pc z$xM?z?pz#><2T{G+%Y`axm3TqQ0NO-504J#uaXdC=Fm!en%k)GX*2~#W#f4HC(smj zz(>lQ1+`!ojVjK>BlbzMe4(ZB%#F~vx@g=s_kvN2i+cbw^_yMk_@r>c=Zr;+zUlcE z<0LBB(PC_uPwIP*h;E610A0A9@k*IS!_(-bs8;j~h3b#fus3ZJ$CeyTG|gHqG({wA zJW**Z=5Bu5k0x`uZ}=Y5Ho!{`Gv5 z_LIfC!9W zc8lPQ8E{_V-powQq%0K+;(lS1O&@dF>81)Xt*s&%Yn$jFat(4M47+p4o9>BAU;MuouoH&_Z@`-p>uM=L_u@A7R^n#AvlAX_ym8oM8h2h;c>P3 zI^g3jj@@7MW;u2r0r$SWEW@^?W1*3q*Td34^BVKrgZi%RE#hx*DkQx~b-Z9y$1C!( zJe%-VhkHw0_MTmQ1cjO~E0%?144z$#_skrc(WPVY6(5Ika;=Va%l~L~?9Jf8&5l1U zojv4Aqhl351()??K4h9Z|p%RTzaL84@V-rs5cL4$-uAl??aR{L&fQkb}gL$a%YQ-;|3&UEqvqNXk5?Z6q(xTys<4eMQ*-Rf{315E~ zp0=6+RQ06#pDc-k;hF!aMWI$ji;M0>X%*uPQk1P{-OZJM4JI1QNN}c#GNgs^#*w;3eWi%?^R~ z0j9PornVP%>f(Od^4X3q?sJ(~+CY6M=S9dY{up2$x4oXt1=&9k^OaXE~` zK9ZBA5zXib8Dl#GAK*0ZI5dCmUzx2ir~CB!bT3W*bD!3pVJ7=_m_IR3?Vw{Fskn)S z4QC)|try_WidNd03;zv}BO)9@@k;M_ox9R8plkXb+(Dozn|uJib!!|*)&}|7oD7FS z>`1E@0Rmxy3HRtWceFWAF_J;X7+yEOrAw_QaBFSFjpx`YTV@4!otbUM7xW$Nm~AtYE8_ z!XFs`8}Gh>c+kSu6}H&m?6E|&8~g4-@J@lOZH0CidFv!{_hSown~@k7|MqYpqW(*O z(MT;qmAovt+w;XTV=!X*q>!@Y-?O^mBLv6Ki=L1ysGNl|4$&1XpK8qLsMHd zwowx609I?FDCb}T``|eety-|6xz~w%tCdQEIG}-?5Ka!K4t1=y(pD?hq1dWLMNMSX zI)D>ktBuv_KE@%UGB}Xm=eyS4XGlPM|MxzBo`;-0ti9H|-t|uFUGI9=Di$t?Ws$?> zwOjNd3l|&>n`t~}0b@0|N>`ZSGI6q4V#}eZNAbyZ+Z&!OS|3Qu=RbbXkUP=EHh_*9l)xZSG()$e`nF%W& zJ)cg{7I}pj3>HD2$Q{qDn)O$OymRfBtZ|s;Hm18UF#IK&f?iQ|u=<*-Fydb41Cf2)#*v!(Kn8>%F+%k^gM9 zw1&)?xCtpv?xOQ@3NPBr#uKm7TlS0Vz#QjFLKO?r8~F28F~mQ`rSVf@h%YZ8mKaKy zLV`RNV!RntH0<#!W^%U9h00nQzm>|Osf&?2=MkXJD$b~AU9Z!TQnMW2(Gl1C#L}v( z^Z>OS+Fsc3JH3zx!X+f1t!u)DLndq(&y0;3ZfWbSZTW8IoaXU3){ozQknk$3DHJ-( z4C71ev0%}}{=F|6er6?JFbs$Ze)ldspV^q;dq!kpg0Fd95rzW#%VUE7fE(32oMloo zMtSkS*1s9#KXz)^W5AXQgbd98EP~I(?J{`d+}0)LV0EW`2uh`OiH=rh_O1=UZgTc4 zvZ1rTX?`tF$rw=S7C!IlObi`45G+(V@lxJGK0kST7(eGPLHK%Cf(~|eGH*Q}S;iQd zT^*LaW5`_P@KogX5xrlqBVqrA8?RPhid5QJyt7s z9bcowMyIUhMYsFyq4-JxvIh==@4ch{@MgdB^_fL>I5Imqy5gDeu=VWgXd7DKRD%-V z)ysC8)523t;2}E+;Bg>im5 zzA|IbUw#}1qC3^5z;ZWl-(yBr=pv6E2gal4Q(-`7<3?quQBK1QHQLeRm|T(nnPYD zfE9TZ0Q)8((k@w#314q1gKBbM?R_vA+maYxM8vx@Z<4EZT_)IcG~0kgl+)vuYo>84jUx6vgv0g^1^?B#s&Ytj=B^+)9 z5%n1&dY{f4To@u+a{17LL?8J|<}6oFEmJCx8hM5h?Z^2d@g&`XM*lWuTYu{@1vzP0}mP4?Lm{fgPSrv^^v zX%;ejb+QF;&bzIY4m5W*;+_QP>-H8|YfOl!A#f4q_`a^q`~ z#~(;A_u_EEJusXI)i`B4Ib~)O7p|Wg7ips7$3m6im7!`ZWyq9j3&Q?}LuO5%dcSAx zqS)eVyP&mJ-uhbzgJ69&)C>yNciJ1F1jVfT8)}j;MkZi?l>+vSiljDkQ7L@6si})y z1@24E;D_<#=3_JA5&TOa5ier)-Zb(!n3Uars+p8E>={hTjzfC) z9wJR4nzA3Lp5TKv`@tTW5B4;AfY#Cmsn%U#fEW2-n-CFh>sAY=n$t?yC%8|;>mo>(xv^Pm6 znAAtBD!ub~-OFy~(jOOs>w6y>C;_w|J7~NtuW_3!OD&Jkd;$Sh=5kal9rC`RN_(jE zUR63Jw^G}mCNoF7xTNjz0^l;qTRTd)3X)q~sT&f5l=0&weoAtS4i(fty5((tSo}m* zmsWYU-Q?m%72mv)*R3s+-PEKeWe~d6s8{6L61H9Oa2CSeyW3n}sjNqoSZ#hbde_^h zi~ZXU-6n1|wI&E_Ufv`mGiTq8{%9*KXdc4tt=m4P+&EBKe40oMjE>UmNT3=|@~Utp zmt3C!Zo))=me-4$s*docj z_pei0k?Zt2yu=JK*m>?(>=vK1(%hy_UX*?DATO>$K&rJfpipO@5TJ=Z0YYimeBun+ zLu_3|=POk<&uAHE&5;VIbc7v`5u#|wy@=J)Pi_F07QT-U z%H5qjHB+zOLH~OnF6HN8$0ShLk4Kn~wICuguN?R>b@=^*W#H51;#ZlZz^|+4;PZiD z_sNHT!o*BBE%Z6)_-+n5zMCy)(ee9l258-Ge{;vT5E*S)J<3M&`sUfWqwSWwId{TTsN^Bn5wOinAN`4Q`q%b z8nL$(I3FO4(pSpOTl^x&BL+*4vu|soiBm${o@Q^|XyWunZqK*3lMz%++`hGk`F7ev z!%RO6n;8qz4$H7_%4b=66(5EDoaNo#?)wQxbC#=faBp^efp$&Ke)c1?Ri1CESygR8%eT!! zmzxwXA;QWJOaog0l^8!{Eq3FB2=F%`UQNhteF)Mn=x@f>WX5u6G;w-XcHScL>hEk@f^5I@-LH|q2Mpa8?&V#EG8%S@iEXnn&RY|L9Ic|TMPfbRw zUAjd&LLtN%HC=v%Glovi=xVRwg_legEEC7O%C=y> z$D26cd=xicMSYjJrOK!`P|(V)cjuKtffN5bH;66r#+A&6$j?Eh?VHePh4W9U`YzsI zveH%3?W)=*T6SN=vEzwuI>(%3)H!wC&F4wSR|?X}a%|F@`YJNg)mKf^?Q}Y~XV5u$ z*5L4?D}6Y#EnVcKb}b%g^Z^$GaMebK`H zE9kG2xLI`9$oc#j;|C5Z{p0nr8?b?-qfUe(OG|;BCA4` z3<~+X*1lv^?X+ci{3ZWXhNsA1A)ZRIA`xCtB$klU z-&Et@J#J`W&8TntcTK%V1@t|{^ew3 zm*MENn=rRjxog1lDL~jutV$mU`GLiB6~9kA4>F*oGc`#_7IkxZGnXz03cH1?gJDf_ zbOuXj{jWnWo#9zyhBoguW=Jzb9&VBW+f4dRF7ZrHgWb}6NZjuVj zY2_-KiZr2V=a|cz=IUMQzBcpoP~7}X85K?4*KXcl3{p;LjHb@gMvFbFq|Q*CLvZzc zgqn?FlSUI0%eXB9aonPWl^~_K+}>746Q_>iajl!UFvKrto!CfcM;J6u1hM-rzS27>7+xZ8q>QQ`?`74tkYn|al1gP*)VHtNYKIJD(N9A=Hl{}W)(YWD zNa^KlIcrQ!DGQ7#%m1~^X$DsQtL#U4mKp|P@k77KR(^4|oUQzGC#UjE{e>+*V0RD# z!dSnmWREGzs$;F+!vce+& z#n6ESvEY~t4hIoLbq;{jvgIs*y`^~o`t;m7t6~t%)nq@-YXSjPykAZe#o2PUiTOEA zkYh=_8VuP9712}}y0E4}ETN+SZaQT%UT1=^m0W8Y56)!)Ru3j~efPN-qFf_$5i#hW zW6kO;i}_qnGBp$Gs=+r#P1A0A1ObGMy(~%~&;oH#K17wKO7|x0%jR7Zv)@}TWY`5S z%i|1+OCW1B36#l5g-J2q(>F1-EB@7P4i1vc&Hc9n`gw26j)y0gexA&hv$%`ynm0U8 z0}o;7M&DZfAH~*2x}B#P33(Z{XT)jf-kxeOVERO+Y^pn_uQ+vGe^!+F?`?+U=69e``&awHjOtN3fZzAuv=kh#la8vPi%1LGXbMnia|;#Et`v(J}Q z^83&+{Bi2LNtOK2>GqP2MP*cmWDP|1fuZ13@m04fTbea=^)93vDILkr_aubBvp`}(v z(`4`7Rn{!876!=bm6}xH)_veQ_4IQK$I3bFnssQN1s-plOeqp`7drFS8>q@R?Ml%)M@B8m+MtHx$MKH%XXoS(Am&q7fTGhp8$)d-6lPPZQ zg#uwOnz+r6I>70X5tR{zUNm3d#GA7JJqoC>SSR0dBiG?8DJ&#BUX$%+w* zBMAb-LM03zrfG=1`ypAcY&i*4^1~2QHN)Xm8A$FU4$z!tmn#49*Cc54o#6>Yd#?>} zx{%Es-iq6BDyNE%VO`8kU26%e#6C%L-s->o2WW>IUju#3qpQGYtW?h@qS6=Lvt zIVKWD|GGr?;=(vbLTLwXGg-?Vk59NeuV#_}&u?n}R)8)|b@$(Z9pAss*zU!Gxd9Ep>T9a_6(l>C zTev)=PP4Lx#Xfc#marPv$0VbRhpSm6S|eCAAxnHJXS{dCa?36gsZr@eGq9#L1?O!jX>h?y1{K5;5yp~L_hb=j~u znxIJe2cDE!Berpaq znLp=y$bP$+Z?{Lfy;I#(7!Vr(aX^jH1Vmq4hXzm_AGMazz>&5Aj=2dYm6LZCb2O-d zuu1f{-8tp%%QUAPjJsv@B8i5z0N8;Q#^|f2K96jCiCDD=lfW>Oz(~+6qa8-&sae2Q zzl>xDM6smUthXJqsr_z7q7m%Yzb<`=8CdeyE;;37^RL)!2%N;%9JyT`RW_YWX8$oE z_Tjdiy`+TdNS$&aD!*tuJxKpZ6se@R`IUZZC|#BQ$G}QClN6S)6+fR=<`)}$@`en)}B^WPG+G}Lmr@o>vLBu|BJc$;YG;yTMW3<(ox@13b= zy(IH^jt6kcNN+xT7!zB!ZB+$p^DWmz3*QjXylHf56do}Z)SSEpI%S~Nd!)C7d0Q5< z7FR|KOByJ{bQM31l7V|+t|?vJs_{kyvzkl- zl<`Ic^IIwWXnFnjT`%=>CP9GJJLdXWRZ=vC+Z#q4?ppcjV|Am~3S$vKWl`E8RC5UF zaj9KHQ7jBa6GLvZ!P?Y5G8n?b4Q@1Xb}lxrqyitCw;g7&=_Y0`i6&-u@teh@l5KAE zesh{dq;kLrkzr?egW7i^{Y2fbs6aZFu;ZuY`T&=-n8Bs@eYLe?MAn}MB8`w73feY( zx;^RIpuNSY@6Lkz}pz9tYpjN#IpYKYfjHyEj(>1u@&sRp}^w8^d45VO*)$N zy$`o@l!G`(3q(n7b`-ymiD#+KEd0d!yi0%liJ6?`r{Dh4_^izL0@|F%HMzh14FJT% zCv{wc#m#$8vx}qowSLw4VQ_%gd+PrUJU`5XXRrTH@IWi#A*QbR{n&nd$oBBt=zZ&d z(Vzc|_HUlDJ$#zEh_PShyemyt--&wdj1;r6xpp;46mcXRTt6Q}1t*oEu?}5o)uDQqGY4b-SgoAMns#E*v9GzV>mn^}S1;4tpt6GE zHq^u$eg{1@K3tx)lH0R+J=*#xW{{f77R@yVpzOaTSaktH2iSkI#dGXGf0g&ySbJA^ zshWy8^*v7fXd^b)ML6qtQtH4^gvbY6<3rs?d>wi+mfQMh!qeg?yUq6}>c?}3P67Xs ziWw{)l|J}rDL5}av9 z>^F^1(#uqg%DO%g5sdV4k*vd2er~T-VZ<|Y(I0g=!_89tz97*%??%E&MkCT^{5zk#zm!kv z_{1S6Yw2p;eXkX9Y{7WN`}_(kj=%D}1sf%zqfLxFMS}ifa;`j`%IWrUq2$ zKpi?)`suM5ANCdX(CChR*a5Bj{BLMfOQhR#7M)i=z*%%8^Q^#Gbj8U7oJAveDaR4^ zPWgAZ_dzx&LRK~!qe89LTm7)FJykg!u3K7 zAKdAS%-v0k`O(6)v4$Qp31L$=nbfSQtF^SNwN^aoM6zTY=?_b;WF6^$wYSJ2<48Ym zD-o56an;6=o+^IEzC|YDPfr!UW^d6Jmo#$wfxVrKJH3h9f}y77X>MZTbOvfTw_MKh zz3V*L$2{rOK$z6*IlfhJR|zs7RTZhy{rL&vB#1}Y$s$O&5Ibnm+xQoazc%YZEgfl) zWo!B?9my`5$F@pJwq=hT3jC8_9?3)0Ar;x%r#BO9;r ztKwXT;XPXhz(=4(p#m+M|1&2r%4xryltD(y`~A=9d~Q6)oeWHN>7j98<>DvByCiAC z#&eX~W_A$IaZz;!4Yqe#y;l5PgLCVE|6#VAMc2!lgKmB0c+;Vk0RG~JlD0)sIaUk?go`e zm0o995;ig{xow+;ds;@L=EalzZ-PmBKfyJV4JP^A-ok$4fu=O|k$DUI9Y2cOZT4-g zA57wGGH;nKm|&7hdkg!SV3M0QnzuU&CV80Bbo5w$vV5^(h-IxMbUYhO0?ym&hLV0X z^+n*<{c?J{xj=(w5#R0gd=iYhKX_SsYpWf!;;`rbJ0`CE&3IVi+O%J$oF%S{bDQ}} z`r5xlAeQMN)^;OH;pM_mldF$76-c@8;EV0}*$67>e%+?8;g;}#ukVwm0 z>GrSrvvpaoN15xBJeM`6UNEKan9TDq`C7TVHjS@B5)}E~D8H%1Y!nCYYV#Yf+G2heRQ2&odIpR+{N#9o zndyFFTK*Sv)EW-ZblMI!Psy+yv|6-U5L~4%+ey55ZB+qKH}8w}c0k}=Q`UyD1y0*~ zGodU$2yFD0WnRK*-{c9dU{}7kqv)Qz(Ga;|$c(?c>Sfv4fxo->b_QLjob310#G5Rz z&T&)*B7yZC80A+*Di_s8_jpySz{LF;k_#0*#pmAN7h4zI6VjBT_JRVC1A7tnJKDF11=jk=6)9SKAkzbrsZ)6?l7#jFy|;&%`TQ+yD{0)meh17xav z^-e@}_?X#O020Kro*JTs^h-A&MZuK*uSN2LF5PU87jgPCbM)pKm!@(`{R70cqYlzpuA1Bi6|8>*2=F zVJZsOzT0v^X#ROs2Wvwp;`658+!rphN$eSpY!HCFw0=!u|n zmoOdZ@7I_6u5{vGC`xF1%(hCjmceRqt5H7x3ktvJ9-Zm4RSbSA5T%JxW1sZX9IC;t zQce@;o{%bXAlcR7KNa$%c`6zF63>t*1o~=F61`QNsz{zcw$-ymk36tYSj(lZ-h9kq zUWSI5J2s>yFk?TC?V+FWtYrl?uWBe*72ft-B=v2kSTr@Px!lxq!qDd=w-Q)rzE2DL+7O2_W5RHtr!>2 zZ{a@5w-VOQ+!&c~Y5Ue8Qh`RuB+|jyGXuu?@3$6&%_T3w<-Do+BFP3-9VHEYn8Y0fkczK)T9 zhfi!fw7pt43EI2gXF#$u?iHdvvwtU5e01OT+9TK6s)6faro9oSz2;$mE=(_CUq#S6 z0zF-V=BI%fD?LDi<@Z~v78-Dhi~eT~-SY=^?9VK_h15=}{LK%f+^s}0s81|Q@26MY zZw(30UqSxyduWK&pB0f*5$C6N72yOZa%-M7bL4PxL?pqna_q}m;Hw!;7?B3KI!9Zm z4Y>SD&gkA3YWL8*ktIg?Sb1`quXGGh88KpZ8Csp^-DyS0v#5HUByHP@bf8b+JDf9J z#BM|~li`y1+-W}@c1TAkgn3wh7X!j(&cDysmU=@7z*$`WYukP$y0-8RV@OV91Mz`C`-EWS#qn#F3RppSj&19H5ik*i1XNz}O^r;@3;TGro3^q6DnEZ#I>2TH)T6fejA?$to~vDk1G6?(fGG1ls=n3 zqr1`?x4=rZ`%geN&Mh5BvT{}hY|3I|4E0##|TVG%`gnq^p?9Giu+#Lz0}FkVJ} z2cqPLJ48^;7cbUPn>v(_4UaU|^8>1L;#P!RQZnZaGtxAAVBR?VmuVX`rHY^Z*1v}w zjl*|Lqb*6c^dXg=Tb*5hNN}Q6m~A-kJ(C*D!&em7EE?NBqqK0!2n-*_Poi* z&Hnr&-Q=l&SAONELBzP$*ne1I0#Cj!@jc*-f^hQS@Z*)x*GKiv(l5eo{rk);Vu9}^ z4!!$6tL!!+KB|aSIbv!RVTwY5iS&o7YH)GrUnLFA2vJ1Vdr094O!A}};OoiM4*|1U z_li7`yZ_$E+;7x7fBquB@yZK--8+Xcgdc){f&EL?DEj4c4S~M`pE}Ab$6QD+Gj z61RjC?}azN8s7Ik(rw|Xro3}yiuS{)Sby8ru}+5(?++(i3tD;F>N>xB%4vI***mYm)Ggy3PAjMr+q4*ocPbwf2FP)!p&L1O<{r4{zrWyni1y%NDGO#xUhE!4&MPUe2)aNoKE|>J-#<6;}6?`Kj`RB#Rt37 z6FD41Z+*%9d{DUFB_qUVpoJJ8*vgPdje8azTn)%B4`A^Jl^$H)v zU*&!)p3U|DoG?l^c6+tZz1CkPTO9(<*jK`FG^- zOqG88W-f-dy=y_w`hW11Y4w;`y&N~e5gRfBIDij7Ym?5Cq#!P*nKK7Cj!)l`1@7XP zA%{H2aR?GJ^T!~#a73>Gt~)K@48RQEe+&W+{G=awbz4RmSbWvuFWUhkO63YBa4#pUp-zg zB3EUn@KqKi$M+5zFW+C79gj*H7d_-Pey*2oJTZ7YGQ_frC6;*%1dWg6t8C+I-x=6= zfIng^XAKUqt@-+n8EVCgq6y1T#o2O}q2~WHi)7IwDt)Fl=zc$F(#-EdHa0tdvbU*H4aovBvkaoG11hiAvbkly_>oOUOqJ%O{U);nmF25<$DgF_)a62oSxKE=1SDs*=BxHt06Azh@N?fgJU^MZYh303D8Mnlp zi@5`kMH>Xj)l0a0*b1`DDju?_k`nvBX88RKgDbn)quaaM2%9;}g_NAt+00Ubp&!{_ z)+VRdFLTm4i_GM**XlltMyc|pdyD<3p+H+Dv5BhZV;rrluNqCF*Z$_SBFb@-I{a{% z3{2Xqjd5mdC+3wU)*4iV(n+rp*4DOaOUoN(`{O8o`(w2Ubu!x@f0)}+X8WTypV&D? z^K-rFr=LEBQ4ZNrX2Z^f(bNeuqNypI@_hoxuGbirnT-+A#4e!voPP@W6X}S?=0wP$ z^cVIKqj@T$dBP>UW*#PL*lV(Rbt(iirHs-cA{HA^w_LiEtmKPEN?l`1P3CbEj~M5P zG+q8z;xc(Oi;^wT#5Jv8jLVtPgjq)9i3XY{(2T!P=bDA~Nhq55r5*5VG~nE6q$zq4 zUv=3_$ft9)d3ntmeh4(Um?!IXnds~>FFHN*Gq+C9-69^P%??x8Y0g0C?za<>2c z2dW8#e8*T6fzm$BXHwxfSifwo8?+cwTAGo{dBzsr%ku2k+4RbMzApTRtxQtBqJss*E7=>ziBDxeV~wGysO-~6Z`E`9NF zoDzS$$T}qqXWBoVbL32|Dh#+bZ@x6=U5$C`!&=e8->sy}ne;`t?}EG$>+5sZX5$kn z)^-#dQV-xFmb_OR&cm&bnuKpHJBK^(QMNZsdQK;|sq#$XJ0%Gr6{dIB0qaTYJ}gE! zijqw^@sB92Gn^-=_2g|;3jrwF+A)%M&LA>a#tN3y|F(T(UA9Q`>Tw$U_zTW}j#?Mral1XJBITuX8 z$e4g|j#stvv0PL0`HgTiW2A14)A6K$s@v+!?b1c+7ft*y*U+Y16q(knm?2)lWLDub@LE)#!`s<#)Wwn1^;+ePB5496j;RgF3CTdU;hjci-`r}O>y;M&DkH8-FIpoBP+YMV57{Wb@(#XK zVfm$Jd}zX#7BA&_wVwZ=#XNtG2i`7RlPeIS@E)HmYW6e8h&X=UhHL0V?Po#Ep(}*H zO6`Qjil)CrC~av-yzX6uH;gDEsAIP2YxAGz=PvRwH>ID#_S0b$2P^hEg+Pg zL!FDV?8Zr+HtnaM+-U4b@!C$YNM0M; z@gXhkCN-uKSv`7+D8O&kn?zgb^Kdg{1=s+2rNw2Avxwnjw!5g3cbnBnH#tX z-JJHi_8TBubsnr_YprSdHsftKvh|-- z0$F5b>mi($8)E!Aq@@YvC_lpW!W}&FIv*^zu^#v_^Q~6?Hi~-JPZz=2)q{rko2;_~d4&E%a9(nVPPs?M+H?SDm6zmo=n;BqvOzN>ZG@1eGOD`C>NaZUc*41nVe zO4kTBl;nE74V2{m0!>PCF9YKZ`ARYeM(G?x)@2zO10@NJR!N>O5Z%--27~CdUrU=A zMOmBHn49b?cU$VUGcm2FshR2C3D*W%!)nNu?;(K#QuMxm;urX9GDC|8T0nr3WI@j+Lwto+o@BQ zmp`1cz>ema3?IwNbgbmbyFe4^gAqv_ML!r4EoQ*@##Fq`_RK=?x;NTDP*fEIY#&EA zL#luQ$psR>eJzi`#2AbsX!liqtm*g>A|16K_)}9?ccIU7{NEpS@g0nVRcig;*S^3w z^8nvc`GYUmmrPLo*yODL8_mE_loyizn%U}=#-&uMXP6(`Ub3^vtpD4@`)iWOUQf-t zVBuC3Uezvj3|0Vw6|}k5+Azt3aZMIFKflS0;yQn#=B83IJG@6pixYXA3iPivns~GV zE1w_DA=@6eGd@-oJ96fDd^#EK_pbRp0x9{ZuA|8Zn)q?b+Lc+(scCPdZp@cqGGC57 z!kRCS@T%Zwr73G}poJ!iL=z88!KUNfi?CudM1ck`D&f74bBH_JpnkJY^;7NB}lz7i`W{GN~s^-nmf$3 zy6rV{oe9`CIdIuhRj#tJbI6Y>Bu%521sy2<-P5m*crE5*n|8W2F z%E;P&wKxh{G8uEeTH#wFD?M;K=gW+rAFUeeCW-E5nIDiVRlL~P36zy2RoOfU!cL~fDP@r7>Pvrfm4x$!f1(Gr#0 zq+@DYdP^JZjn<=r8_oUwRSW%c25`zrsG}!|9&JB=C{8X3FXo<+=(hvWy3`b)YhOeYeNOvo*|%uA5C`B;khnMM9KA`? zg&uCvCmaC4)QreBZ+V436~Uikz>0!C8BxrQ=!XsX3dJ`$?Qe?YlE+o}=0JA~B-WkY zlVZ-iJ@|`uAJ$@3x?1^)>A_hP^)5O~YIbY-U1XE8yS1+oE|kImGn@=^r(tx`57&wR zn8sttI~Ma3rn|<6<+Oj3;^EGvRfZ*YGv6vl8j0DKn10^olgPV@ZF8LtDVs>Dz6wHF z=5!p&T~3O(daUEP0Qd1LO3o)38>5!V=0G`1FgE)|25u*Quh5Zf7qmGJ0CTzm{x;;+ z{Z&FyKptl2{yU1L_`x^GGn(9qWX1ky=-4)mhAR`wsuiuEF3i_RC(d9bCg49I zg~6&}V4)!W3;wE|yG=XBlnhdLzc4~gGyvcErj6#As=teBv!hKrXY#;qwRY>?H^ju! zR^pTNtvn}`R&uAHWkeVpXr>fCDqdx$zN5I~3#a2fSu#JPw53E?h=5&J4u!__mD$H> z??1;IS1J42(yxIqY>w5h8GHEz;<~I`>el~+PB`cH_g_k0*&StXQ_$Pfd{p|8u8*+Z8bHnSMKM=r}7yus!^=4n$- zwvWI5iSan4iS3k|0(F$-mkk3Yt@rJDl6ga;Np{v7IreK{6lE*K$jGlME+TcF)A2*i zVsK1JLULSY`e|VxRk{&!^U7&3-~&Sl{t+`q!Z)jz*H*QvJO=npc)*k$*)(UJxK8|7 zp#~zKmOe!WG$*-YzFu*xPvV^7z;tzkcRVDNejg6;iOrlQa-Ot^CAMHa&GQa3jSO>> z7x?{plGY)%-2-AX0y2F9jgg4N^eLJk)%Znl>jh=$d1^!880lohpa6P*8~~~RrXh(Q zxdkVu&%|yHx-U5>C6<}kNVDmt+Dt370GNZ04c;p^n^!ewjHfW!M-&> z6=TT-!|N=hIwDE732lIn+k7>=)JU~#O!(ct)#uwa7+lh$zQJWJst;WZE`jRAe`}OQ zlrwQ;aIMsxHMo3Xi%e8|vbhAhgoHrwCSE9d3<~-C9NM;0hp2i}H>lHLLy@{yXN=>R z2TZS-s+$Z;j3IWcF}-}FP6E$jACpVE4`7>c=Y8QOJg0q~v9}m_PJ5*4g5L4cy>{%3 zrL~F!Z@g2T0lNJ;3XAQghbmWvHmw34x#8TzP@Pm4O&nLI=+ZgMMY{Rw!mm1g2gSu? zI?>UvP8j#Ktfr9RcCE8acH(zKn-P$cV~sfNL-`~i-mQQvL@m@W;@^()E&eEf7G?A& zJ00`*!cF}UeZ=b8#oYKqP3;AY;Qjmz9C1}> z;z^F}1YUzNHfvHyuPxper2~-rJQYg(7i5qu>q+sW3=)3}($_O;*>TDqh4ZI@RgI*o zym5+8=2Lk?bIb(UbRs(g(nfFgIU+t^H^_Juc}mAix^}6YhAHhB@#u3o_7UbTyr{++ zy#q+43WJ-1PF(Amgjlar2U2k}iHat0saPkuCO229R^lGUN(l%1i-H|W#Zfj8Xgn5~ zQpE?gNVtl+w|B@GO3u`l&AoN>UC7wglVygL*1TlQvp@YRFwY9681rm24}v;(EUk~D zly|wU=|{T$t-b!1uCKS(=Pu;B(_TOFqG|2TTd>ov`ZA<%R>p*4LeYJ^H=jEY=jnxL zNxuq(KwB|#zmGXTPc@3Yix}OYlAno)bb_5KyV3jxOS2llKN|gNhc=SfCf$0?QF7JU zG0jrdX%K`F*GCv(fy0nN#%FqL35;&0R4{&e7Xj!ulw|M_r<2r7J(gRe>OPnSc`+VadcA+}ilsXW+QosHa%nCr*bs8Va@P);;HR%%*u{ zX%~gK0^p_AcYwZK!@Vk4Z=U;;IZHQ|?@>b&a8lf9dLRJ4hV|{l@AL1i%3QBIOY4C) zJP8>p3qgXki^{#d*n%d5&#=8QXgBa!%HUw^&!(Dk-!Sy0o_^wIhhd1@?(1UrkY!$W4iF_g?|KbpI9X!7 zqxQs3^#3CKRRd!KRyy+@L@1)OI@lFCic=*;^m z@I_GQSp7`m%(_YpFBZp{wo7hBlBw;;Et0R1m}do69=b?2Cp=_Fz?wBtwDn@}?aM4t zXkhYh!yAMr!m^-m^>3l59@P3)|AH#P8%F5Tz`1+A&PdOd;bHmE2MjU_w=PRa$<}}mfhDJ^{ zqx*PgfClBQltoAgV#L`-B8gej(-c5JJMpbNaFf9lppwAXj69QgkuyO32^3*8#az~# zXiPBc^v#Mk+5a&H+SvcgcV=)nQ?%_KX{NT%kZ#YZDN=Xl42l(z(S+Ii?vDt9O#=eV zT{O&00EG1k4&lscUkSgYNhFj*r*o+|OQ#26>SxZEa^ml(sG-xJP;4NbUIuyP(CLNT zioBpU<|sb3UG^2!=KJ_Ht-eK8N6hD{0S9>`c?&G7Q13F~HnkrKyhyQBFk?7dstEjZW$~ zJKwyVn;j4ulU8*SLOab8ngKRTXo8esN|dPnvF|Up5Cm^G1eIwp? z`5Hod9j}Q9Y`&mI{a?kebqbx!uu6yik>5z&7c*k)d4Tm zm|B?a4c?AQeUB8F<@lMT@j?pL@pY=0F21ctgO9xK- zB2#U5@1z~qeSodoO|ph)ERt(TWg={@=UZbvOa{QbnK4f>NNg~TOu=aioSBZ1G`XPp z8T9@1d?fVE*i}|gQ$7YhoN=4+nAxX)?Y(~HA26T~Jk6@+E*k%erHuqdy<3j6p5#g` zsw*I}$Gh`%go1(z=(FZY1k`BmDm)%@Dz8rRoo^YuU5}uP05*POqNSc9lYWA^_XQLa z)0+SvR`68sb(ZLM%_1IkgktRXQHzu^PD~uet~Tg*yLY>Kn_o@+I78i1apJ3@!D= zP`}er1h6hiA0lt{P>;|#O|n4TD_U%lA%QG9OR|W_8@*HCHD0YMgVo>? zq^-CM;mV0`q}x7(=G48w1ONTN338y1lrViAh!o|c_K_lip5?>+tb zI?ZvjD@|uXY?|vH1_v9i75-!D;5IXBzRmagTe(or?8HbFUk1^x=}Rbm1>Re&HDa^g;k+2(?{*e@$CSZKUJ1Fr}~nqTR(|CK8o)V)I$@rX}RqD{U;y9g10 zv%r9pE>!D(%QvLpJ?l|f|C!(CK%(qrn#aDNttfI*oEQI_(>@jmBmpI*!hTpg!HPdI zkaVY?;qeX|nK7^tnX5u6)|-tD7~$u?W2 zVAhkZ;K*iRpAl6sUrhart{o!lAB3xD5WJZtL`U#fhv3!m>((A(F1 zRQjo|8|?LCx~{X=|7{z2WPv{~{3jRQUcB28z7Ga!QD?^|K$)J3$IDIp!$fQ1su4lq z28D!jJ!+y~q>VT81feBI%3O-D6f-ywx|rUM+GpukIo?+UU!b;N?rQTJHzGGyx5}A& zH8n<3Aw(`D5?A%mq?M$Km(}Kr$$Z1(yctJe2(s2BgJ2fxpRJSvxM2OWLw6?7_S&j; zu3?2adSsPEYtAAl{&}DdW{Y1JtHOkh22$gR70~I`d>kYs6Dw=X)ic9iVr4DtW>{IR zi;2XaQNoP#dJ=df<*h-nFn7Y5!FbTTG}9BN*5)xAH>Z$4Ywn^gKe{&LVGc1_U{P?LnO}Ev(DVppd9*cF=s`y(=maEvBZm_1z|8)7vDZD2!l|E z6^6*?GQ`2=n12E=Ss0FgrfZu6*bE_ z);fqJJTZ-!B>f@Gxc%n(=%8q73BO*EZ7#5)TaJt*p7gCTYn^4SvS{K-@1-h5S7&sD z+#aKWQkiP@r2FP(-xOE#)Mjs1EW8Mv}kj-Qpr1K2K-z72BzX9=ycIhN*nN0N& zG%{#=lbKGfXT@<~+cXzT{4;$ZEs2~h??IUU^ex2-iw*ESfB!s}-oaOATzX&6H}nUQ za5^NHzhc!5qB62iBvmQD|77iLK=xe{H3J=B-ibfWunC8uk7NkosEs6u-F+|pP4yyG zdSM5Qa2=~Rfia}XE6cVrRuNsOZZi|T-xvq3?aGJV9)2rkhLrSMm=1zO0mgjrEz9&M zI13IliwQI&LSa8vZfHyInfyN@%y$&N}b@(5~EChFk~XZp{EAT0TE+IM=SnKOPRK6lohSSi~8 zpE|8T1ovE@U>S(dEaRtJd?Z?3HY$Ax{F9+VI$=d-y-3806`vs0X(Cn(!bOn8NGXbK zO^Y8OMGy*f*<1<`?FWFyv`(<1MBWgZ`I@jYrE(Bf5O-P%-3LlZ@BcwQP!ex~!vH0j z_a$6%3=rkmAr_*C1kv++7(;31j&2q+5{XajBe3qb#+%lUn6&p;xH`aiGiIEu0zC*Evo{ZWeK>?+FA9dQKVf z;VveB!xm2TaLf3Em2`4n>%%g~hO~UE^^#dSljD_hY1pan3hS&r=eoIi8(tz&#BN3R z^r`6^DhUIp7B^X7vW5IswUCCOiL+d>aY%O9?LD)bj%oa`cV2!xxPT^d`@cgu0I4d$ zW58+X>kJ9%?{M(o-noqo=Y~dH8fl#7{gmoWlz8UE_4HjYuglrasQnGD%n8UkWL3tI zWg@Z6=6VdyN)!{yrQBOARG0q!kIGtp_EhbE))BJZTd4sWMCC$jb;nf>02Da1zQoPZC7P~_}CwJZy_vSjXW z_g?z0Cg(Xpjd5QX-$P}ArEaz)p3VdIU}v0pHV$|`Pn~%t7AaNS?^;H%l6cTMR_?a$ z(;~3K1+_?Nc5{n^r#WR4N}RGu70z%(xHFuI5~vPQeGVFQn?b|t#d&Brf_DZDXLAut zJ*I_Q_RckNH(>X6K2q+sv+fkrxvbA_1>UdRZPiX(XBtVU{*d21ybR$1ov7qs3!FmC zU$wE>9aQ;9aY0DSoLGtMjAe+W;i? zkACXySMQ6~3BL9CDz&19*;I|7OrJ%wvZHrWMsM1;ZJV`FQCOa{lorphkj%P_6rxH} z2KUx;ow1h&FG1!GT@6LO`+s0yf97(o*K;jb7qFXE1~^2pqiW6Gr>)*!@LfV=Mk#y; zs0m_ZPF9ae+X{5)$K+yMg&EBC1nE4zm1Y>br`NCSWVvSj_#&i)@wnwsgGd)^KYUG?{rq3y9SYsrG{s*if>mI(Cp5=>s zP94Y>hft;XVg$dotI7@W6fKG=-~-a*(of3=>0J%AmA2NUS?akjuv`vfxge;!WEByg%dwYId9$f4K#h1 za{U?CgNS=+)k1X;`W95)y7Mw1HJ=N8mx{C(QzE@3hqTMM&XD$5-@tnG89Yls2ah99 zU)$KimT$=ZZ-jEN#K)I_K;vOEdH51LrB`Yy;@fAv_XVtAevN+N{A+Ta&UsfLWHJ|o zlQw$C>9~o&(37+131q?wzqXdLOyfQLBMokz`}$kdlIhJF^@f9euIox4 zY^l58UPIkAGXv^gH`>tCe9_ijT#HX;Xm)=;W?1^62CU${9Mjn=<({?zG*B-nT5*}|%yXj%^GJh;HH;I`WVP=<>vpD^Th60@K^m*PO^#+3In?ghC z5zEYf+zvBm6Z6!Y#60!10Qmm00PNrfo1#4L^&i4GW=B-aH>&ny?1b(23^7}5vx;0# z$bi}DmTcQD**P73v_cY#N*!9!p*8yY#Oi3Os6icc3%jCqJu`;6{oQV2SG%h|R@dXS zCB(S>PfSegu`)e7r$sZq8|gANR^%-KH&g0Mb5Qt;zgklEcC3v=uf7^0Wg-AI~d!;Qd(F14St- zu6CB=y<2NkbFgWvd4|-pI7xGq^uu^cWH&>Ln&LIe*EU(f15FIO%c|@f6sSj9HyxKM z+L<%DV;WHn=dN1MX;jx3KBJtYb+0>Z4^UojCfhg9rf=hcFD0%(Y$d&!#!hE?^VY_}{~Y zuuN3r_e?@$lQXGoLSCbTT%b9-wDy}#LyHfPX@m#S*!{*4DwAfG>>?KjhD@WS1j+cO zzY~8HC?&SXH)?= z>!MbPs1$ax9a`d`%hYMaj_SohSbW%})*sl!b;bCv=(qZl)R5ch{7D9cDKEq>>r`_sJ)#Ap)idreU@7;VX8lA%y{y5^W@8p zP`l)M360V>D40D$?bRFQ9htLyJ++wK|JF;AHDUdHs?CKMg6x4fp#-l``Y)ev3h=od z|BM;#JpT-00~pJf{Ki1Al%Mbt!W`&AxA)mKdHxw?tX;BO)XCl^ zmDD(nK4s6BYE9azYI8af%B~R;{0Q6JKHp zA*&^T{P(AFTFFbhX^_q=LEL9tUMDn>Sytx|N8zGYo^oO}l(ON4P0%_MPOU#qvzXL9 zrAy1_i^gCnuCM+~<&dH#<$y|rXupyD9ePm9^(52MN$O~nj$i^*mgrHc{3KQbsp8go z!Y_u28LB=rRQU;I-L{7W;ZWxn7SX`J$P~wAr+nPxYfVLf=Gv--JdT+xp%tbBR+whC z0X!sv&;o6%epBVgu?(ZcKeM==aDxtEG?P0VQ|c3aE#8n)2^0j^zu}7f z@u_=0cYFY@6)XmTp7xUgnZKVU96T704=$C+%^iwyul4XR6wL+KZ| zw)Kv2C_SHsb)6Z94ZIA-K?X;59Q1jmVkcYqCK!* z70fd^b-f+u)a_rH(^?*L=jPPSO4kAMh=WVWK{UN2nw(XZl}mT#R+`_1ASG}S;9t01 z@XNB`huaPKeLDs}l-tt31^&}kmNMMH{!Jfd?Sn*Ob{R2>5Y#T{`4jLtX>bcxP8g0Y zAVy5=$(c;ZL?dbUhEe*T-30w_^+wKq31>`kC8Z7c8@+O#=*=^iTM^%gvN8k?#*!uJ z5jzJO1A1R=K3n73jMQYCZX_!;B!6Ov>?&?FbxTzjB_fHhLuV<|q7Cqf2BG$;^1H4S z)n04EVp8RIoU5Za>}I?`VDa&yxt4WjaebR<)QBjA^21hSo@DrA3Y7)?agdQyzGdr* z*Cmq=HO*O>{5ND>t_-kKc;&?lc*ST=$u4F`;+1!QZg|E0m1wWTz|rkp%lfJ$fshf% zF45g!e#y^2J!W|h1#h3&NGEo9yNoYv%Y0rb$`ad)a}BY5zGGs0fdk*d#!`n)c1Uc4 z;mzmo1-Z54!}~wx?@9~vm+<#KxvlLG=3M>`&f3<|I*nx{pc`<2WKRF03AQ_M!Shsc!A)viiRCBi%(QxlzVp0PO1GlclpFp|`YzaHl% z=O`j8L!z?(ZoK)kz`WG@AA({vii@*_x`)UPBs!W1?6q#<3Gev0t*koxJwYGLKB@_n zn^E4-SyWPAJEVE{`r2`Y&Aak%wttZR4rrT}X8d?(K8`l{JzA+zq4{+O7 z7rM@)s}rl&dTp;47Iqss;J(nKMBOjEqfIhv-;orY7DcKueQrh8(lXo_Z`>VDMu zx!&$5Mw4afkZB zd~~)+T}L|@J#l~4Lh2eHW2AwJu!Lr@+~}wBtD3&{eXZXcWrMhRkcs7 z?&*v6NO(JMY3nI$`C6=ySnapdQ$S2C@oKE*Uy<&A6~_u+QbuDZ{xOeD#)EjhOtZFr zz}lZ@Zrc}JeVZ$G`^4Bz?Tq^K(uai^G$Bz1y<|P0vJNc6EX3Qg`8JL)!}hn-f*=Vba+z5=&mD=t8lLAf-TkI zZl|F;p`OLNwB68YSm%@tampqt_9Lc04F%4FYrFqRPhVjxBW}-koOli0a~|w6{a*zL zPW&4@NvqdU=-6^#S6koMLjGLNpkjQB>VXKFKvU4DD_#;z->_VS2gfs8bIU>aX2j#A31XT1^1}ah*X$6 z9#<2!#h+}R$@ak^7sBkXNP*PH5s}2e06-PXkX&OA^;gHd_6kU&NndQ7j=dcHF^IL?O`M%ub6BW>M1I=Zocb;~k0wZ~M^0vJiZj0emb zHWL#|4UdkSzo6(r;kE8HXP!>gB@$n7t@R@KRX9_$Ne(#iykV|L^8D&pvSm~xd2$Kq z>C0k?&9RzQF=rfG)zaQupIcIiIs^c9Hq?%OGJIqM#L_+bd8Px-jZZiYPsN{f;=iIn zljHI}{5BFN!dzTyjq(vT3EB9M&LXa~@M%}URDI#ZDs7zY)22qYLwypfSrIh)vuvYY zxU;Bg^po|qh9hb7J=0WZS2eODc6C zoe*%0%yFJs&RJ%tnj;^*XL)2|3Qh1ZOj1vLL23`P4w1gsME4CAGIU#!Z;jfb)x@!V z6_EWP+!*BLl}z`+1d`^>dtmpAkn>iK6xs0QJdZ`S(LnBf1F(A^W(Ico4@wKXKaB_` zSJ($8->Wqcw4&`%Qp-85`d!t~#Aq>GF?^gj$6innS=*=k63`ZM+EP+6iIzq&s54jD zC?Y7~weQ9fZ*!qcOM7mGpKT>a)mG{SUx09b4 zk8Kb&Z$}enyRn*&XCBdz_#|xfP%JbtwMPw0N{!>3vZ8AKM61ij5zkbkzeP1(|IBS1 zlCz>R(*JbJnn>NY851~AIE-BoEBu_#__As5V`qj#em8u0QS+Ca-P**tnQIxtqZ4fi693xP(QaW4;2ex{yhjiy_v z!tL6RpuvdNz2&qY$qgJKQk9GQwD8oh$sS8)NV&ZkfU^4J15zpMCG6q0MA`#N4Y$2t z=*+zj)mNWrsj^AqNecB>xBHD@ZsA9<|JvHaN0GwKj9)E;4v{Obz8Swn3}fLORQ(T) zs>cWu1``bxNYv#TZ*T9-b}ShvLNFT|L!HwrI*+X&#Cd+h8KK&hVdt6^GI)f~dZ)qD zU__Evpbg%N)L@bw`!@U{(&0Fh9&gR2EM+uwo{I%hU;CDuY-u!BgrN;t5s}2EaP5i~ zmj){^KiryaSmiVy8^xfqw6n$Q@GAnWK2>t|8G#*QYBRP-c+?6;_8*bNYveg~YjhrW zF?_KT|6$9TSf5kV(8J!(GH@|FB)V!Q8lT;#Q$fga*g(f-h&#syDy3zW&DcT58p0Z1 z;rzl{eg=S>L|hm!sJM3J6pYrLUG2=(;=T-exTxaz)PW;M|1H8<^N9uwQ3TO!SH`Ma zxH(b>@wS9!G;7T&0%d1;Y=U^s_(%*N4Sqve_ZWjJvG&ICkH9NjDrEKHeMD(HI@gB0f^MO0tX;GszfOkBtKB zd@RcsIYII4H^Veo!&uJI2h5k#W5GH&_UAYn2s548;+_2wU?$;p44RtHn$Jakq8>o@ zdJ0fyRy#;v$zdUtAgR{!dbAGxHajHLUU-<9MoaKmbS}XBOZRB+q4WuM@fNR01f5u! zRz`TI?Pv<%Nx9+>7N#{MYrK<6xAuE~G~$aWyp7&%T!wW@OF{ZQD#ArniRsHE%#PlE zY&}SC))1zOZ#uXXNf%qZov@MY4#v+Z++?Jhxe;RMM+i)*oXp(llMge*(bqYlcJ$wju346y z46bKlHI0v_^D$C)0>hR0cuC&Jv)H$CsXei*=N08K4MIl~PP_}ZU4o`fqY69~yjBM(AO*-)oUbN4V|NRjC{25a-o zR{2LW{wVeW#1boXmO4(-wyhY5#nJ#ss*p*{nmi*%p#LK#g{%3iGmc3X6H-iVZ_x)9 zf$F=P*cR%%q9TkXMb1_{t0P0Ts~8YtO!;cJ&q%Ap2eIV&7-D~q)w~;Vj(ydyu38S( zQ?fOpFD|GU{d}kve@vfq%@dd|(ikY-wc*;ATP6zgqm0=50H8eKsaA%3bqvSDZhk$o z2S#^=YR{`0>1$pGSdClFpSP4eDj0}?^xXO zWG(g7i2%}@RvBW673rJ#wcbd(evsvS z#O1TBp|gZg;;%d)badeTl(JaO=H??J-5(U|T*_#2zh$e35HWYqwX23;nO(l6pm}&C zc}%$fMHX5|KaZFS_rF9*%;)D?{z2ZkN_p=Ok0xip2d7j->o#)GUy>|v#>w%7;xaM% z+(HbREfILqd-=UL`Xh+r1Ru1Sll}rjFXI|EUC8>|E6x0*f#c!hNqE~$&YK1?!T+IX z>aZ0RJc=eC(@re!#xmh;o!KPwHQ<%W|K`${@vba$naJbi+q`zuh9!Hb7F?LgpR1zd zQhPieO%-*zsa-o!1RT`3#}$#nmm`JG9+%pc<;J4<(ZW7NN60N+sSkai6>=MXOs)5} z3gG`o+nK;eRb7ui6M_y1zKJy&x0-6&CUpyHD>0}ukid-0u&5~3g;;#N?r#I3$@T%xuRsWSiXx%bVM1c>eL&*wwt zE%)7fwtMcm=bn2m992TsxP)4<(VoD)o#TVO4Ab(!|s@vIQiFTXzW?62po<+WAPK=|Mpqc-jS*B zI5~p8<0D#5h0oU49=ZNeL+kq!6O|)z$gb-6sGOpa$3w2ypz;mSeGqP)Srdba!T*v7 zsrUEgEIsEP&rjj`F|uRg`Ml@2{dsjbuX^N@hx1;s0KvQ2*FqNfRaMXdN3^F>{)CSL zn`d8c)!*Vy{cS|M5Y1;aw5JGQ8U8BOF^?y6`L6~OsFfJr#e*P6Q8Apy)sw-eON*mv zk=BO-Sde{hC+XXFc$NBu=VwZpZ|a9DxJDptgInE0>uwd{Gwx`2#6JC0-L0}!234Y- z)ZHp_t2)4f?}2gYCZR!c zoUka}>UBno$rCzLvHvtB>%?<+6sLwK{DV4@#i$aw74}AaR>{J6`@92#JX6vz`xjnv&X!JlQ6ckM|c-!IfRz}-I+3Rsx3o3R*?+{Q)FIZw zJJnryIBIUhCKEL!b>Y4=H`q_SFV&-ZyJbt2Ub1^5hd*rHWURQ^9fk1quuTiAB8EGU z7~h-;G2Vtz8aV#e-MWZIbNwa$B3&a(jc1;b{&TyO$o3xrQuiMLp3=SgPa98j6$pO_ zy)-v349xStWYYz91*}PMYV+&^0v1VOWCXD4J7m<7ZZPc6TPQq4u{rypOqzm`Ve<&`!0AJeg=YPWs9^IgS75Qvg9{3t+HsvBjcI@aMv zh|Xp0QuN*=y^xqFdx+3%WdNgz0)G{t)wIir`tyN1GV?Il`&rLCj0Ey~R0pEWX6v;@Bin-Q4{yO4Yfd>gwF{0BByo z@^K&&M~c^Oo`WnPkf6!ReC&yN#1S!@;D9KpY@M6L^s~Pu=Qf3`fJYXOs~iQc7d7o? zwtbmS9l3`BkG}C`I(m9h7%eIpBe3r2Hk;>uM}@|W!&h*gr*oXxcREQ^YA}jXHqyD0 zr2dr-dggFg#W>>U+3vTl|Cv(u+Aj-*6O8-fYe)m=(EhP?&D|5WZ@#$~Y@hv`#6h6FoF+AZR{GDSPX`a%jqV^igW{n@^!WVd^B9 z`of(3sJrApvFO9)E*GX zl&NwM@QE}cl3*dmd97?&Tn5P$N*Ferydb=hJroD4MeP<+z;Mr~JJFr|q2geYO*+E9 zKMWlR`}PsM580VxUtjzMdv+qLj`%fk_ac0|V_pXLV_(zE8>1%MS>}1?oD34%h71G= zAE?^re9@!jSGE?mkR5~tAAvb3(Rg_}2W`Vrz|Y)8tioBYC;{MXH1c^i6yXhgVk856 zJ?fYj$+kTx#tO0>9_7NJ7&Ns3se4?|9gz)3R^@??BYBu;`Q>qn<&?4a0ektE=s5&>*Jj9)C>u-OcWqNkv^SnuCBM_L zB}WkIU0-<;0qxh9OJGXNT@W~EeK&;h?2*g}C6%(beFwJd_g7#@=YnUsE*i3*D<(4X@-$91cSqVZyOD z{JXRMg__d(?}jTxGbn=^9s1F^8A;l$J}8X8e(a9^=&2%pGo6X#KHtAw(Crg{jo@Wu z;T+Ilk)mh!vT$~OOS_eY|2V#%tqIC><`CK=)(V?t{c5XSA5sDRvZBx35A>b=@dQn- zY1+4I+}92sP>>(!^MCSaj5(MUg`S#G0lzh=cYeud%o@ z=-L*j{WP3Nz2SFtlSU#PK0&PkNQj%y)9F)l9jzjgoC+k4&xwPD6&*qIMf>LN9x*4U z6!C=qSFuMk`VmUmPkoYS4rTVA{2$>z?cc^fvMpt0@IOXY1y}~@^r;DugFD$71oyK` zvbZk-6L3F2z0Uw}f0R=8b06p9E+QcEhSj%GCPO%uDlqJ4yO|8do|ts;`UcD6OFzZz z2gZ9nKB6J#8o}C*+1p^|uptD;r?v#)`p#h)9VPW#>J0UetpRGbf|W7_>R=y0d_pO^7+j#o zm_hLL#w=cHenhZ{n%xOP-~vi|el(TIy3eW+S)Qs;a%8zVTr~%c=2# z)wK>*PXri4Y;1hCvU8%qu{AUk;4M!=dfzT_JES)4MEqNf!g-So4E29DW}30 z=`fBez3)d)9dHk}NQNfaj}T(U2T6^VMl~DgV2vZ-R`Vm!x~dqo9$+aRqRjhB6Qyd8 z!u=Yh?2kU|#b8a3UJRD`lF*{TD)*(IW)AG|_g}8L2MB+K8pDQ0M==X|B^3~2oaGP$ z9AAVOLlrTef}fN;H9CrE3f=lM7%#+lk#0@Fzp^%iSpO2L1vrx3Cy5ZzOpDS6u z$tC>}kU{d7Uk(Jxe^SbJ=ONj@Kh1u{OGKR|jJnRZETJQ@4MUdNN;D2`n0 ze@^~*a=&996pSa*a8}J{#uEpH!tvx6KmL!$ljNiAU*Uc5&S z(DuLQD|4Jk-`uH%4zqL*-j^t)>|Z8T&+3cc?)+o1FZS#kJF8yF(yT=2!=Tz5B+l6)m6V8@p27 zYv0(#TyrWUnW;n-w(b}R2S1>c{ng)laj*~m{rSfRfcwMXwKv>r*6hJIwto9SkodMB zF%l${2rJ*%Bq4(KjeYWAE^s7kuVSz;5E2-^N^In!@VEW3$35!mFu(P?=`aJzDCGzz5n2)rI&g$>~xge*% zztgE-A{D!v4_r-g^!J1b`TG0gN&Ua%}eU$;w#-_zR0 zCyqw@`fD4GzP{!k0}-mtl(OG>=l@t=zb)EePuP|Id;0n}pAQ75FDYdk8mEk{A;15J z`r5Szb(hiC$L&d9Z~jbUvS)pLqF~bSwxhTD=&RkWXAD4Rc?Y1gu5xtN|E0d(`sqM8 zcq-JfLvQ_m(%1FiwKsj;^w=Ks^*08DM1)dyE1|~y>gzM!@1w7?{*{9DP(k*Z4+-xhRERuT z=$OzbKeTt0J0I18#|%uot!kCm0N>O@+Hxh`s@Oe?J{}0FpHa#loI&;L=)bB!o!>M2 zJz1^AcL9ry+dDu`f^mHAjUcFlaZ>E|UB^y?J+1rxlT33YqL-|vkvsH?s9Mq`TyyZI zk2D&4R)fa~8mGU}n`3*`hkDNLi!oOpukpb*BSK4HBSM?cE>5Q-fncvi+VFA~WLb8T z1={c*F-QaEWOu5KrPJMGoiTRPt27^3nsg$MVde{ShXr8euX6V5#t#R=$L~QV`?SCH zB0wMf^X=D6*3h}%Q{-*z(wgp`_REZt z`)!_*TTG{T*VY*9S;>tBPy76>8Rlfiqdm;e^YmLoKl)9x=Y@VX+oO4!?SYJDyJtWO zVDZCy)@&DPzJ2`uK=?KZ+Sr$FQCJU5pMATJK0}oaiEPcOvUlGYpelR%FB%h~jR>al z7pk)32L%5jO4+~vtAd~PX*FkNiF!!#$lJ2(W=a_O)4zRp(3`#NyIH}Ue!F7TUiF)o z;^?<;k$E_0-*x!<)o*9Z3P!-1Ni3I-Sgs9oJYrPjFJCoShbTAqWCnE~%NPuuM0;R$SumZFM1`n87s z9WETf7a3Bk-|Twb{{g;uJqz)@DUrjsvJl@98rRI4l*YAH;hJg&(R$GbSwy$LtPoxM z?m!Uz7UZx`<_kek^%v5^vSQxIZv%KE74;x<{mg zW%+XjK!VnZZw~~m+bL!L?+aP9RK5!7bp7Y5pa=OA5w~;NiNABKTf%_UHrTNqXG`1I z3Zrx^!Zmgzzh3VnE_V1ynvL)HnuXG)!}mDwfcb_2^oXB&RqO zaRJLtk#c#(w%esBBnj3TbL(Hzfwj^a|DwU#1xtSnn>Rfsh}o5HI1But7U;#)g(vjuw_jF*rNd&jeD1$n3%NPE+i#BUS=|VR?2DQ97gC!EMvrjM z2TNC}@H?}U5B%mBw(``aj+SWm4!gp?iZb#q>Noc@&vu(*hCyAoJ)XVklK3!_?m?w` zV7vEHc8ITZ(nO_RNtd0J2YI^et6PeTR0LS^FR(OSR+f9)oi5uZZzX0jxlO&@AxLK3 z(;eBj!}xTSlv4=VyH@n1Q>O^u)pi3(nVphHmFkg-!DJ`lR(VvK_vkbGNgm0T>w4kq zIhCHQ5R2>F*=wB$t+c1T^<|n5l_T5<#C7OK!6KC0)1FypW^b^yVE_)XuI3ytmgqQyGx0jOgh0htL z)cypo&ZKwkr&y)9*=w9QOJeY(YNB$UXF9}Cbp4qU0+orae0`+08vNR&-YfsiR<;e~ z^3TL4aVs1OndI0=__+(3@fvP7_eiw9LWQ^& zuFC-gOnns_d{w|_Bs zQ{QG)3}^I0soLuiO2f+Lz3t~15>wrUZx$npq+Wr&P&DQ zDYfEJ^=Q}}zj^pZzqMFbbIwLL$tpK`l+B@QvEoamWbJzLjj-WD-?^47<6*K3mTia& z4N#B?X~bS!v?HC|$a5a}1;WH)_56sVc8Ke;E-nveem`$RiKW;r7MWAUZ69w}iauHV%$_X-wARQQNfWqZs}cQ+urINAhCH%H_t4;-QmZ+($MB4{8BA>7$~#s0Pwk-( zLUHrDE;?abFcBAIA1b!5nJB<$lAQG|35mFy}YZV!0rwFbkSHKrUcj+!!(+mrUJBTTylRem@<~`2P^PXSmt{B|;J6*4S@1M3pM- z<4%At_fSLOex+QLs95tE9g~6F{gH6OQ8igMOz)-Na=Xg&zE_Q|Jl;7auz-yN`d;X0 zmsjlix7tsa?Z42`YA{n9F;5{qMz$V4KO9V_nU7SdrBbP|rk z8Yq(7ockIx*t(|BaeuIXIt(vqsqLwe1==>B)ohG&c&LSV^S zGuEEoU{3FGa4}+XOb@(Y3Sz+oS%hA+?+LO$!CJ1KV2McQxK|ZgvynnHdVP=a$hchq zF8XA;IcAqNZl^hBr*CB|?*$8;D21;;SMp50}XjC(? z-S+cG>`EseRsCnLfH&pv; z_uh&;Y56+e5B;~l2f>RD*IhTi@my!)s+T=b#Wsz+9@mD!se9b>D!cM?!NhXW>~dVz zEH;patoyZ0+R`_efyF(%Wq1!AitFq5kEz`h0mg zJAQ(7%ia8_O5}n{-k>Mgi#SbLNWh~rJ4?FdLn`81^^vt)vh?$f0V3jqWUw4&{6+AJMmjl5|5sf^cGc@RQp)$4BwP7uz++h`$XL`WAbWS__Iv;>W(l z9?2D}x7JANBwgw4l&&||%s>kIessfbKANVQSS(DcH&_2z!L7izE8gk_&2jxf(?CDI z19lX^J*cpx2!Od&wDaMp;ewK{ij0ts4nhTMmkYh-T!LM(kqhQvk;BquKZ|8e?Vfbm zm>Zm#OX^srW|ATpTn~??%g)Lx#*8~%_AN@P+0|o$lNpyPVXia*XWG<{M)ZHXmDw># zu}+ynzLiD5WnZ>bR8W?gpkZ5Y_CmE>iEBdWXJ6B$D#|cl9@Ww93J|sx#07P3K@bbd zJfX{|I)9_&B!y8WRmhV>R+qyS#!Q)mRl5PGkPOn$l$l6g1{w_U*hP zsI3Z)=b#$VA-eF(Rx0QZ48 zLH{||d$Ola`(vff-7<#8b4g@y}@MAItwLSkW~bBzOPVV4q` zV5L`)3nfiPtW1*lKr>Xukr(?Ty;8e=Jxs#&v-_2{#A1Jr<0zY?M$1|x&uX7zF3TzD z`p&ZM%sd=NPONL00qZBG-eeu9eZq(*rHHKS1nVk{mfxz%Vl(&|ZJyjFNn0f(#c3qA zlETq>Lr6t`6D1^7Gx?eyb`tGBrp_j@?p3pD@$$`)GOk^L#5k8vX&X?)aB12VqXHzxA|nmrT_`c7k7{d#0cUR7m$LkO(asOH{X+2Eek1?JQ5DECqdF&y-F29 zS#C%S+XMveaRgK}jND+{_za&~fx#r1c_sN2*ZELC%}3)CC4YdU0y(dQ=2m^P8zFY5w?X51-|)wNVc`CZNbBC@k>X2g&@fv$GR z-~J*s2@Z>R2@dig9{q}Rj8}q!FEMuQs6&m|yS%J7KZ`z9kxX$Zq^~hQuZS}y6uOO+tbPEJVLl~l{c7O z>NH*Z=(Ty(OGU}2sS=Nu;ubbMh51Ngh6nXa53pfhujT}nTAJcPeRsRuRL zXAkj3pR1@hcce-ME?@NTK!xOQFmTogrE-LWW8+rq zBFc^3Ab@w+cf9(t(&95ngkQFak9{i-kP;+pB577~?v2?!CTLn-7&rcrza!e4zbN{G zeshaRpD`LQ@!*&3p+&VfZyw1w5lr0BNvWVQZr$kGo7>A_T_7>((tt5;GbI-BO)xR~ z#LVlB6y^0H>UD5)BkzXkcfs}=UhLz%;0(0UgEBAh2Tv+?UXV9uv`fDj)^6OfZggF+ zy@bS26`R*DbH%=x7Vb$*-W=UIbXK?dRP^m_(RFL1JL$QcftgN8CMx}Jidq2mN`@eB zHbW4r)@Z}WZ73yF* za5PHn3GcLvFIrC_p782)Rq(HCu@8$f{qbN+G1qy#kAsK2b zq>4g#YkFlgdTzC!!bsnDWxAri|N4ERF_2NYf zH&VU;o*E$OwtvivK9FdL^nNGvxz#n40f3+bz~LkpRoSII=dv6(iT_SgV_ApLt;-ko z!X??IKUJY7#U#ORQkEa&!m(IiHXB%*^?La2;#D`FE2^?btjljr>1LrL@?CB?$AaVm z-%pnnF~%zMmjt&k>xoHV&oV~`xg}(YL&k1)mnCL;>=nP=LRb1U^{`WFJ4BbG z(9KF+m!C62$|QueukX*W?z>hBqj<@-Cc{N;NGzB2YnMDpNEmsJB-A1Y4~ z0%H$d#rjKUgL01eIRumO;3ydZ%?NJl2~+L6k-2o4kyl|4aEw&=zA#%3gD%8Jdws90 zNteB@sKM3^h{W{t4-{7Rog;Jo?Dr!H2r0Devrypavb*v=@21Hbq3|>+DX=eTPNbXW zuF5Z;F8jXITy{@if9(-lB7E}K*cackg*L15>&Ud3nk8*Q5s}|qdtcH(Mg~|Je3DX% z#+e?q=k_KbV(GG#`E_L4o8NzXH|Lj4mrWT+dzzjn{*T}m%>O>qmZ92;YJo4r@9_Nc z>9Y4`_QKEEk4RWTd%#%Ta|U`%4-kfbv*dH*;D(*9NY!c?;Y8t)PRQYl^G(nzc6_cZ&tY)#W5{rt8K1rWeR8*>ygc)Pj#d`KJZu(fhPL$2& zST_HqB{z^WF5R_0DW*X3=;4L3!&x{p+(uAfKgOy6k-5QMBkge(g@bgSXP}ThVp-^nex(Tf^mAWoJ>F z^gFG!-&7P6rGG@aY`=UUa>RM&8V!t$0W7)qT5r$CCjtYYN!^02DEJIPT%QU(wuyq@ zD?Pf@_=A3rDu!s)itY(GAoL#3WeKiO!!vIp{7<5-Rlmfj!;T}Ej+JG${m7hnCXBifu~w%I;SY!9_(x~YPg6xJVm!l(PK`5p*c?yv0$e~*K#uow@FN@nID z=e9W*O72v;x=NQ`617jc9ao4Pl);ybBRI@2T2FwL)EWL*>I1m))cw;Pe}s;btIDN7 z)FmeX3YNJXjtayM1jo}!Npg=ZwO1$}{H2CMYB8xrFG*%px58TuWKOn8>RA(e3@&AHD2Bb4t$O5JN*cD4kQfq_XeSHdCJKF2|s3 z+yB_9yWR6DykocW=2d;~m`Hb+AZ?_MIm>GKvbj@`;Uo+Ui{~Qm(vTxH=#$;c%OsuE zJ7D6i_R5Y5LB3EWvsU--ic6?A`4^c8BdS|AVnTDS5E1GMQk(r(B_*87< zgv*Y%OXRFS$Lx`8-reK@EwSCV6)-Awho7@C;X4T-R1M#9a)I~%^;5TIg)MnLMn&Iv znBB-13qbkurQ6y&v_Ev(>rbq-zW#UlKNI5==KuItS~0zt>mQCqlH)gr?`nRZDurX6 ze5slJeva8lxYA5jL2I-}HjqS)^OFvo&;cbJpV=*o-eJrt=WwRH!J2)wj0Ue?ArCi_ zCNOdw?#^KZ0BGjUcuGMORl;ma+1qfF}Wo6+0{eH>3o2G+B75c^b&b0 zPJxw|%)a!B%+o96saOjue{|I)*JPglM4tXlo?d!Qcvj}=Rq|9^MJq46;>XzyoBS*%|Wm9(j7zPv>5qc{)p;-Y!p@W?hkOP1SINdK$Ur(o9*NhQljoH(io_ zayd_?uZ%P`srmvXu}^0W>4;P=+b?zS%6WjqmyZNWnm@fF%(>Yek^PnpU*B9i_ouTi z3zsb0KlS;tVX03f8Tm3->iuQKsdttQN^M(Kl6rmF;MA67`=nl4wr}eBW$x6|%Z8*n zmkmwzVnBBOH4;FXe?4RA3E;6z0R7h38p8Ez3Z`ObF%?rMbFE~`4y$tWF{#1c`HTMa zVNGTN;$+Z$Zgo^QcahWFH&!XbP)GjtnP*C2yN#L&R_SMciBVT$zw?i@a!C}7j@W~$ z1N3dbNw@#T!o2zJ{ycN$yR6a)ZoTHa@{wJx;OI3Ul3j~xhN9-XzdG!z{$P;-Crj@d z4ZwvC0F}_YfX>-oCN9bXI?I>#ZMSGT?+(9ty85qJ2o$sY8>AoUa9C{%Q;1tzdeW~WHDme_`=a{cOOS`w;c3Yw+2Bi|pk4p_d$pV&vf4+SJ; zI5>aQdIgabtX8PNNpbOz@9`(w$e5lE&%!;81FC6c{lc?qe9m#T?E!PWZ{bgBLgwc| zbC)l=lM_-FZ}3LHlHbmTnjMi+xe3peSK*oUBVP$$6-vw=8LE9cWYmA|dknaWINs$Q zIW!^uu6)E{P7I~oMDFp|)rRZQ_k=mtm(z7QL67e0k#2iVIe&uX9KKS5DNLZ?&xjxi z($DF{j;B?QqtI)Y?-Q>iM;abRV}vU}Sk!?#b$34UTq{O6_LGpfz<&DVPrJ9Dj+6~1 z9rk@zAwBz%ABq2S%`}{;n~2K6AB%Am>aq8i3rqPh{PyHe#qinC1{4CVa$h8$;UJ`b z?12LLNlftD2Nry6FXl6udng&oN4X#P9+$Zx$tBDYjECJ zyhXt2W6$N_p>(Wcp8YTd`vV{&Z#wSI+ya;U)}cY`QH}NscHP}u()yUh)1tsJ`==q- zF5`xqxTMfBegZLE?kzGd1+CvN<;UN=zD=HsM0{cYi)rkLO|c#}*LEmLP{;ka-jaiR zO84P>I}D9;JwbC$If?lz2yUzrGG$|hILt))&1pptWmXF_c$afbRUr0eQL+i^jQojf ztH~pE)bAwBfB1jN^+8-~Dhqz9H#L9QN=1@>l8}A#1^ZIq!exF{tmi@_{xJGEXq_HP zJfa}CZW6@Aqu$7YLpRAYqgoaf&<2Oyza`C?B`t5N65LBYow2T-SPy3cM=>0H(X}1C zWR>ff5^702#!*^Q8>tmPvu~E^uQd*rxnBDrAdRpfz5F6e42|+4DqmO8ptRb=X*M2q zkB|bBGt62m_oXgtj@xMYkXl>C__cp^-pe}f{TsaG{2di$M<8yG{rQcu5==HF&N1Z`G@cYb%2{gyjbCt*u>>$j3MLsaYq)X1 zY|%ItKzc0$x`yp*%1FAE?IC`ffZ0<5n5_DZibvRh!qan0I}uvTdt(KjYX zSMQ4Tj5Ol1NZ@dTC8=53^I)IKvR?=XEUp0^puIp#shP{cf*)^SAOi* zpkzJ5t9w@RpMVxi|MdFrCdMs`_3Ufh^d4U#%m+QF98=AH*T!_0Q&uAM65|%ddfdiM z$7%UD@{5VUbqT;);H(*3YL1QbI7sg6UnvF&{}gma)xP>z>51h=)kF=xIi|vIj%NjJ ze2qF*%^c%Ro^y)lPTujH@!ZR%U=TainB@ZUaH1d4dQ~zg>Xh zT~eg_=E`pMdwXS(5RS#xHtwYgkMl7-Q5TkV#YTA}U-(ynw)}&PrJLu3>40_2>_aN-?~O%Q7R#ybD1WSK8V#zyF91pbg+2c zc5L-09d5ojv`UOo=1)fR@44_NS}Mz_NOG&{SK5@*@=@w#QAwfc_xls`-RfJ` zllVM&gZdg|JuQ`uf|Tdx$|m)Ddu3Gp-c`9seoHTCqCYeuK8EPeU)6B6T|P(I&ZD-4FG@5}32dlX%e$GA6)@w$`Wr{%=BTT~Bx zn>TdSX9rwchJ8|7=NPZ#8=u}erhcE2EL92H3H$oeg z*D^u`tbM%8OZ;_XJ>gOrqi$NVB^~RTZ?rs5O$F2zs;Vwxj-g-cAqYsAg=f@OKDOT0 zpLmnw6j;-Z7V^9T)-{p3-XQH(?SY>tXocUP`3a>*lko;2;2u)=jRnfFK`KP^o+6$rLK3@w(*|(=!btOAFj?@|YY)45-mzVGY3^HX@?f8+HZ)fN&3f_ft-7~Ab z(Otvv{UZfZm(1Ufr;@$d@JYj!hU=K2jiM`-qzXfTN{KbrHBrht+Z#nO2d$}%q1v61Gtigi z{>1X^Yk6nl=HMJ@a}0L&1@j1G74R^d1pch0eNoc$7UWRw0qTyD3fhQE^b;<-@bQ74 zw2zd4uosOL;h{CYzqn$%_6-k@K9u~izi+~)bgfJnX3)(U`_!ALZ!bgE5Lb3a2kqmF ze&(ugUDQsQ6-Q}Rm8%u7kGGp zhxXxjDwk2O^|}06b46xHtwZQEVWhFl38HFmRNwh|zu(8!hyWCYj|UO~*52GD+)s=Y zsLtU!19oBU`l<3P<@)maLVsd^?M2s!Vk!!g6<_HCyYvmmFT9-%- z8EA{I-;#Eo6av_ff1O)=2@I`hz>c^bGIRpe;kja+6l@CRHg4Sdb* zqJf{_Hr7*Z#DC5tG-RC~h+SX7Y@O872*^0q={VaRhg*BlT(g zb7ZSrTq-s^iOuRqX&t&@p4;FgTn4D$+2S@hh(ZCB1=1v>r+W%-v?yKVlYWp~_8Ri+ zdMcnCjuel27p~r_>du8`c`mLos+UOMwNbrT#wVjXAtAp+$Ja=;v2}g~rABK%`#|9I zM&D;s<9#+HMz2UAqe_2Lr7Nh?)s@D(rATR_NQ#s$_NbpF6;dmrhx*IZ`glaf|GS0K z{0JkdSo$Uvi?%eX7PqUPC7V@^@u;dQu}J+aZc{%?mht0jUE3~nakQgD8q?>^x|K?O zHOpMB@lPn+8vj`R{fNJ^!R*2RlJPCRnOpzhHmc!VKzJKs*$ns_aG=KpL}q$EW6={c z=QFmoQ!2Y&W-S*+F!DX^6Ga^Fk`~Q*Zb;T+uYH~Ax>{k=ZTS;p@es!q#XJdd${3!-cgj!o6lTyN zuTkAV0d5-_oydx&UQh$>hWLkkLVxYB-+Xh6G7EYG7$l=aux>$3gb}_hP$tSdRAV>& z5p)s}CN^U+c9c;NG*3oAf9`hUjSMP-pnyi%))YCS>R`j&lcQ*+Lypyo2z|(*b#zWAdSSh<>NgonjPC_GDIuQ zXCGqA(3nw%B7F8(IO(Xn6UbG7Hy;NfNZQKJe&1 zU#-=GC$74FwX(G607?T?$CZ-s#6=OHzC>3f&juJxU|G4uDiH!_tr9&>CCYw^g^Lqo zr5L)2gbY`9&ylkKYs4l8Q6jn*o`3@bW;{BJeL3ft7z) zvG0=y$K*Y@OCB7mzumAQ?zBJryEJScmA5{s#_K7W9ljWne~MDy!X=_fybG6$a`Eq2 zB1~^8+pg4@3%i2E0|NT0m(ywQ_6@G^0ZRCH64s`)N3*(6LS-+eO!OTr3Snbz0YDEN zedDA0hes?DrRSDNe;cvg+qzr;%*e?lbHqT&70A5KE;nRb>$9HHe|soktqvP{3Uzo! z#rCc_8z0zzeFDFzz6`+2A_A~_(z~W!@w5HcrzntL;WR1)>war2h$rm7zC3)jj_%8; zMS1pOA9+#m2>ll>5xTW1Hf6Zrbmqsx3dFs0X#ns>*9fLXoF^os!-+47nvjawo0&h> z_7S&%mCBD_?4Mo>l~VFs2{nYLeHE>$hxKW1H}iu&^z*Mog~&fb$JEeIh>SzFGU9I3 z@?O5dwZ3mld*n~1!@6I{Db(JAw+HCXW@b;gMs*`15R-kf}aq+Ac5#)>5DRizffUUkrjOG10g*JY*YS%;6GKv!v1} zRo)cwGRs>R*X zcIgz`C=G4JM%}0+mT>uH*sUx1ZO?%mG#4y&@bFtW8tUd&i8(is(WUGlH~j(_5aD+~M+8{#4m%4S}$NT{cgtm0t?`SR>_wQ{Xx%6NF*uYaP57w9{A56bd6 zPKgSB$mAjwD}RLJn-G@;&NV+iLkudLw*|eBQC`@e9p$z3Cdy`V#1o_ZEPm*DBE4P@JMYvpfgZH*8Gtn#q9IqCtDnLhMhf`(IN77JV zEiu6Q(q+ewaiVu5zYSHT%l_djW`?2rL2uoW+h5ebzKpIBaEij;a2N`t(t+)H&xk%! zJnjSQp7oLXMtL|?MJG^EUoE*i|3n}CtHv)u4R#4fZQ~j>SgA*Sk&RM>jw1Ub`o}k~ zzR*(pEZi>)hW%ESQ<()-HGe2-HqZaz<<`-c9(g14CKc@viRl%g_}e(;IYcwS+F%>t z1y}=8y3&jn@d4eXMLkD%bPJ;N03HVkomEG0zQiY?#81&oGdQcX$sOo;uVlPca{PEJ zcs%ngl~v2ppX^mDHe%ycB@#!V+=Ob?-EkkPhf&_kL+vR<52#3o?JCk?gIfT&o)w}C z24O7_>F}w2-w&Lb#7Df$tP-hwh(o5!Dv|OlqK;I(Rm!2*YbK#19hA#LLXnbB37u3B zz(67F&WQXMj9iFvy?oTz2`ufXwr&C?H3uniGveO*1}~pAB(Y zjzbB5VVjnYNV%}^@#qCx;M4LMJPleukOlrg?FOUeR9#0EUuWt_B%0L2o%Zp=DV%87 z>gz1RCB$W@&DZHVgiAzT1}~h?Qr4bw0M}MRYVp_Z&q}3K&_5NGU;(veiFU#`j$wjY zHYrwrkY)9S)Y!Vte)438&%5&Z%!n>6iihgZ%LYctJa!)n{13ViX@$rOUE*qA++MM9 z6tN*s2yWK$JNZeMO+7t7Ch@4#ii?te-~~+f{2MruL_*2tR|x!0y>tNh1x@9F14r?|34X9iX}ZW2YN%F9p!o^W68S??QqC({3(Ja< zjp8MLTwN|>HB3K@V0_4o<_uv*9BS|vDgfaZ_A$75V?D*`D3mdMr`klR{)dz>r_5PeKpc~mM{9R^XlJ$-2wV6fYR#YGAak~r$#t3 z@nBXa@VVrP{*jjqKr~h=Y0&Z^9$HpiqHAgdd<-~#jQHoUJNb;zA+cPJR>og6Y}FB5 zd`^hPpnCICck+JTVu}h}N){O8)wM{(1|<jrUa9Tz;lu!kC^>uewa%cRi-Pf|g z0UG;7v?|FMMaO15S5IZ#=$nkzYBZu|)O&nwA6?_HX==XnJdaKDrYSZ_`wU3ZFn;42 z`N?x_t;FCfN}dD3cGp!NosSx~mW$4U#zuTTjXNS6WF?WbW3^gVsaXU!8B{DCUdM5u z_<}CvXLTj7?4y3xlTQAzq^L;u@w@xwJQ^kG0vhEH~d&j zLT3&nD($JDxiS5=!S+XF)5n?|fdALqd(5t|Z3=F$MvhgkmpO=1{Mdr_DD44;c%!mFK+HzI}- zY*XLN_hdrlWOUVZllAN5Z;3PaiEBy5aZW1U<=yojSvt+8L`m8CYR%jayY)*k8a5O=mGiYNj@5}X)he7wLsp7bL7LD z`LJQcyPb-uTuc5d^69|!bXooPi{%~6k)8R9g5>=^xtQTGGbkqi1?@GoHw>ixP31Xk zw?mgqo=Fca+r7(C7+RJNAT@-4si6!AUOUEGX zJSpEGz4gT6qTN@q`!{*}rTd?cM%M_qvhmKbB2Sp+Y#PWn9{ces4v;_SR8gPy(#QIn zhU+kl~KmIHy`QoFx@BB>UzphX3SCm~1v0An1=sGqX&4q$Wk_nMd zm-(1o`D53W7e(Y;Y}r#tTw(?J@pGlR^$WH!9!TNbY`jnY&{jas&BrtOF^c`Ml~LZH zYi>~k-AlN`y8WF|c}VYKA!wQUGP47cO3a3yU}9+-1=t43)GbmJX7GB|zIXPPbi%(Q z_Ql}YL*?GW_)2xfdMd)7o+j1JI?L?nNV;QR9C^KmGaxEsUmO%UBssxVfxGpuha8eSx4x~KH*YJI!ePQ4be8koU1EW1l*&aB zn>*Bz27%Z%(3ZWlD@A29I!Hp(=u5C)w!c`-i+IX$-tv+Uqx{T1p}w`!9dJ2y)i+;8}zo4V>-hmkk8-tD4jaVqAEzD3bZQD4W02l%4TbPGWB ztwA>-N%ihx$_z?gNW%^_ZB5P6hOJmUZBVrx$nldlY}V9m5flM<^~@~850d-eU=T8# zanj(c_QhAj{LRAr_x?TR-=AUrGrNZ6Gk=Y~73Q-qnCNmHJ{Gn~5&ulSRBtltg`r5}%xYMMeNJQG~k1a9zpA@-K?x zJ}Ft~bae+yr$`Jxj}z|f6K8U&rz{_jDAg9~kIrFCE>(}d={%aqqs*xMiXNQb68CBE z{b&7;FRDkUmD1}oCT4W1PJG@5s2sK?JN1fZ9^~xhmF?fKR^Gwd^&EyHySWl)mb2y1 zzKo~ziV#U7So@ens;5T7b8eID9H=m=&uucQc~C7c1{t35%u&v+U^S@RD4oDwjB`i& zE%v#X6Z~ol!>%;R`Z3m{8cwxlV3Xf^%T-@j9GM|;ojsoGiRPDByfkd`S)Kxdy9XXLJ!dORpBFv7++*UWbJi;z_Uj9P)+UoIlcy5r=Jl^a3gqAQ1f&|V5hDM1kpkvKZ@`*3DP)bC zIx#V_4aVQpef2NSn;iHJ70OQB$$*^W&ZG+$_X z18sMMtaI_ZP}aZrz0J=rp+Q}Q25r^~@LK3jl2bXMh2XWc(JJ`|{T!AQZj>-z7=3Sr zqc8r8KNar zl&1C!r5+$E&+AVNKI|h5ibSa0&q|k*c~26rxv5`Rf^cs1ryUe@&_Lp2viALQ~`~sia38~=IQkdVfnm=5oaK*__ z8qpW*ML%IRlpKPwo(qil?}d%lzF8ZhRhK1!so{yX2^Q=eLFT`(14ISTbuO0c5LLu_ zPK`{Kn;QM1L9S1hy4S~gE{+V7+cN#?dm$?Virnk(SZd*>hc*0`_Q?AoD+CDVVZ6K$ zIYxFeA-FQPr(H4^HWWQr+&Waf3`|WEv9xgSyxhK9Jgs z*!|p%iHE#pso1jS5O35dwogIEQVR=D8JeffaTx-B+FGc`gp&bNI|W zx4d<1O;Wbw1vt!WIG~-f*7${FaZC~REj#@Xsct#YQo1Q1iI2D9$C8e*r7{Yz&gvkD zJj9t?EDOrHma>B>Xn#e_P*w%WZdSEdH$V zd1_4-bagRBBhdWeW>}T8l;eJGQ5;xh>(wg%a}xFrCxhlwcI%@;KINHHra_N=Bb#p7 z*WtyZC(}IfwmkX32m6ZKP4t|@W!tREpRW>SXiF!R~{3L=#y}p&A>THwR)vkm2Q~hb# z?-tV?PC2;^PfXfn6~0_5&c2iBQ05&A)9RgaJTv+*CTRz`#4j*ZaVy1ngY@Zo%&|4H zc)gFDJ0^-r#w_}ikXETRaw{f=eyeHWRpesV6-sHZ=$s1Ylp4>@LXY2f9oz)QXbwA5ey zPELR>S}m9pzJ6uzIiVabRl_9ClypG$UE>QTga!L|xWw}K7CQX_RC}HJx zV$>sC6$Rs{=g`!Qb}nu3=WmuXS|=*$nBxv#qc_X_?ht1n`~_8J212#zdzW7stTh{7ZY?IHjMA(=k!ph7gvraUe z?o&*YIJZI$Us1c2q`i0X1p3Sk3_FML?o&DA#2E}ewKwvP!C)?0p@v`#%|5kpYy!O| zyRW$3VqbCeUjj)YG78t-f!XDdF{I5O<4L{nj=#{_J zJ*Zp>DqXyP9$_HINOp7y?bQi<*x^R=Dn%!xH?cVTLO~{GdVOmXN3xDX%0^c)y6#I> z<8t*|UFt9{(rlM6&ZsZsi|JU8XCU_@sqnoHc^8vF!YvPLU?}Zm|AkloCjL z69i}k@|soq@xX6xli7ngW@_?K@eo_uLu^{Av_}Q#u+u>%xw&uW1LX27a{7CB@>x1` zUr8#F#k$N6b?ZF0(JV78bIQp4u?EQzqG-%nP;hADb7nM2V+h zV_rQrm0@&E>@_2Q5uOPO@W3UEi`1w&1%f948N<%k6uMvRkT$#r2=-T79Fhxa^S#gakd(SK(V4-SEl`JUa;KOvwz{gzn(u(Aj zGy-u>HJoskd~By6*r7(u=SkTL8pKraLp>Q-g68G^+%83)3{>XU-Ln^&b9o(^n@bPK zlezQik-6cj`JLGXQ>JcjLzSS~;T`8ntnyC|aMaja>H#|~@aw4|Yy4<6WVOMLWpK4! zQ891Gk|k_s$dZ7V!XYcRMi`Al@(gwvr^|lL8kX|zvQ8mXNtaDKj1Z2ac&P#%Qmtwl zChKf>jbU@RSWZgW*a>b^WAik8Mqm?Vf7q%N{oVY~e?^$>%gO1JDwpLuCGE_^ccdkW z<4(JZdNOX3-TO!SoR>wA@*7L@Y@!SG#B_K5l|J8Vg?jBc?X*{BRi=u8>|c~1>5FJz z9DYJx5lZ%x-{+j1B21^qph>z4oJPgp5Vuqc}H5@iSbWE_?RS-n{(fAx?_0 zJQJng`E+0Sz;D6-{>St^v>*I(a~zqU>ls>w-zu)RT4gB1J(muD*O%_7H`RT;N%ru3 zmt2O{7+fqq%#st#jqk2$nwEWR|Fi|}?&S%`-8JXo+ zLa#rp6utn6!k57jh2Jhe)l(Q2LkyD*6;9a)_E1&^$8O4YZD{c9D`7ZX+yQ{0jA zP$N$$M!Zcu6tWg*{Dc@DO5>l!m1z90hB+GlX7wOXqcLi1y`sLWIbZ&P!9oSkj7v~ewlb1w*bz)VB1LE-p?JwF4%pxzK{sZ(Q41!E3V zC78L}hKEUGu?16$!qfa#q%mFggM%EkM6YAQEmE)5k={bYI^l;0QX-F}h%U2pucGN# zjOJWkf_z0FyV`qK#vFd}9|eG1f{G)6JZK(W-})1G@-n(tzp!O9b zre}=}je(y$JCcn6Sj|B<{plQc1zTXBpjtM>KCFI}hpiuyz6x@hq&IOTOs(3_Vd}f; zK^{|EPF1s!HmR_%vy_fG9Ht%%Q%AA=koV@8VE?iU+co>gOd>H^9{cGBMac-FT8Qqc z2z3_SnF5jZpP>5{t!Q+A$CaR4JJdm!1xg;|p}V;D|0BA?1>GB&tmx>>`s~$8%rE^c z1~K&245UE$oWnb`33B(Tm@*Od=o07AZSv?x+6A3iyioc5 zMx0*p?^}f>Sr1ObBpGZ1=F7@6$|}lePcZSvHYsDRQa`nwMtlkP&Kj(nVG!fGv;ile zTH@~34^Y#&jC&F`8n7;`WYJRM4Yl{B((MSvALXr+a!)NoL{Cv_rAy5$s-{qTZqdP? zTbE#^;y?kc`3b=xUwf>tHyi$j;qDJ6R*9l#xm*31Z22}rUT#HOQlP@G2J51>Vwmxk zee2mWzMXEgyv%EP5aj`LuR!gBqDY8dQ68w>H&V|9b%ZMXwQ78goWx9HT6k2w*&XZJ z7HeM{>p67R@xJC=f1(!ShTFiH1DEWRyI#hJLY_zNQwGN!y%_5mF}Ivtc=kdVX7Ah*ha^K3m^weE zV(&{Qi3V@zGCUY(p5C1`pH$xfg5(5LuLH*2fFS{KKo>B#2VVGiVq(;H#wSWRu%fGk z^m&6=l&K%&37Jm@s=o>vV>%h5s_ZLh&wnS0MT`bJ6#pn>O#Cufy**@pDJaifF)>lO zHqh~I$(dI0X!iuG{%HIa8~oL~7QE>i*e+E?S4%XF12HTRDDwwET zA&`i)g$7M;lH6L=-E+zUEJ;lg6oW(>2n&{+2u4-|CzO>`^2>=|^$5CoVI^lo{Jaw7 zJ_VCp&I&`c+=F>M9>Ot4q6x01kLlI zWC+v)5aWEr^k<0Zf*b_jyxU1>w+#8 z8_`FeuzMz8_nbS55yl)F)ZI-~`Pf`{vl=#XKSSd(wn_NoPkZTx`4U))1g6U#-Om{( zL#Ex&;DPBmb7*mds-;rNd!PNhG3nsueGCSU-32LoUfcT6cHOl$c`JUc*{5r6*}Ys8x3w-4f* zj7Q{se`4?&Ra`HHLUxw#Lku#;nanT6-7&y;lGp-&QJ8~G{uhiLk59wMbXn7o{)~sc z@7K>Rq3+#-TeVlFoVvIcbp_jZY3gB~Kg$r4x zra$hqAGljg@o8!gpB|jlYnJoFbF?P@XxB?BfBgJ{K{j-}^cr*nowJf@$~mOtEwGyM zyMc!mQ%BIaD>anAC8-kr4$ANPvH&<$EUJsi9xdcd-HyEe@IyMmvnOOb!E5$^b5pK-5aE!W%NTSUz>~E@@DMq|j^aKxv>$gM~JXBoul;pjh zXRP?Zs87nvF6=SZp?q@vhX&cnLf+jw+k}F3(>&oCdHzg5ttCQDj*OHXp79m(KK8^U zo!>Y)AOENNaGEFUA>n|?tm8z&gfgBJNlcsz_Nd6%4D%wgtuj1Sv*d?gX_j17z>?L+ zirqs8%}=_SZ^-7eM1tCKAZCdEQ0`Ik?r%{dG5oI|z=Oc?c|16j8(uUhg){gTepX92 zu){252yc4X`{Lcm+57Q!ilW-FYKW*+!hW+~c-18AdDXsN-App#JwWKU2IazV&t-O% z7k}$GH+XU?v^%tn&B{|x{XIN2Cn6-M*r|4Iz5#;8{q?pIMhoPB70>#>C4ewjhWY!i|u zPlrqO<_DRGTU$rms-}BI+^)|>+$MFzEkn(q!@DXX$y*cCff&oNpabPGEi zM{I~tw4YZ??`g<$E#vYy;JjqFf<>jEq(C9p=z@8CUdLHoil z92}NO31?;bHHl7IS*1*w3QS|Ph`7h{argmt3^>dY9F7F`rLT z8&FPo62V?7Rh2P^opH14*`1-{+V82E(7 zb3Dmkp&*1_Kbk!s5#qKw*Zca~!9t9B({ z=Q@PEMs+&r;{0!fzhu4xCAiOnL z{kq@vFMoP{YLMTxp8T%xaH#;K+M9J(vP&idRKg+Iu}cM}GzVsr|GrMuHtY};j&}w( zzJ;TVF{h4lhhN5YXBx0BQ2mtO^>pg~=z>#0`cA3Gl5K$@nQAmGY#6DcMrHeKpmwVf zdxneA(NV5;BO#0Y$OQE9=z3-YO5X~Gk_LqU=qpBblziaJ?%Md&+)Xi^=<7b zwpGwdO^74`6%%YVfFe+zLX+?wqMrLs;CPDPETX>zq z&r^;61}AnoaNMrQtNM@|D^o3+3X+1NAx|57s zplZlyOS$A^2^YnSu9}$7hap4A^MM{$>{EAjea-lmRaI!u>sv(mgYVE780fg;1>xN8 ztFgnDQyELj+ppQ>q$Wh$WsUrQF6IGo6W(c7Txc)e+lET}o&&0|8Fym|_;O-ue%Lr1 zE+cQ=Bf=5OzDVy3fA&5!y`Rb`rykRD>me$9NGkCgFtKP)$ib@_`+&&Mrpx${*3c=< zLVWK1&>q?gv%fFm^D4ei_2sML4vabL@%*6iZqV2r+bGj9z9r(iIe$+Et?MFcPUmXIvUe!zlE3YS0ic-z_XDjAUVrJ7KaK7^lA+*cp1=c%RRl<(2%qiSZ=_+?^M zURHXnCoc$#H%MfkVtWw=Hrv0&Ayoap-7K1{-eqC5!#q+0NhQiS(6rTObo*j^$HU{3 z&jwMOQh#)hw&ve>Z>sj>yt5s?*0+Ym_D%5@9Q4+wd$l$7uolnGJ3F7ZhWlFgex`Nb zFdt9&3bqFdw)&0j$$Qn1vIW$U4A&V4eH*GM)?Defm{i$@(6ZQ~^(J_-?pDQ&H&Wdj z{(LHC^h>3GjlZ!ZFV|Ps*K|RD>ZwP9|^vqND9CH zT=DA~%CPu#^>~|KuTz6Qi(f}ysQA_KN&MQeF{i4+uRp1#p2sNgRQ%e_V2oTTy!z#X zHm`oDWP$x{;nnX=IEhys$=Ni`ZpU9Cz$kyg*5nx4rWVEBZ-}@4Q8WMZe7c@bTcg;w z;VL2cNUU6sIwIc^m9}xa)*yaX5L}B%t|y3&Tk)Sbg79PdTN77~ON@bsxnoO%Hjw+| zg;IKA^mLwN%~;RR)2dfLORE*ApS)9gBUe{=R9YPtp#DHiCB8JveqSdXxKHu)vTP@P&%B=yR zR4SiLO#Q@8{>(Ecb@F--w7_I{%1-WLj6|xWljrniI+;uT0#Q2ovGIdDSv53??`fu= zx2wMW=ymDagXYB(_~I`pMqPcwzUr2%vROT7OYs2O(!|zxXb(#;H0V~E6|-O)$r--J zleVx`#r#MWbJW~YOfl2BY1w5gcb3!-k?HCJJ$*M%nm?1riU-QDo?f3_;xxO&^C2#FGr zdF(Ut*e~U=@A4S$b$5uI+hi)c)VI0N!v#Fh&DCOb`X(2Cr!I8MLwCuwYq|CZ`=Nz$ zfzT5!)xSnT7W13G9na-S*=_tPcV)PJU+ypw^b;w_4RaM&Gr-gz?bobEJ|}Jh^k4EZ z6v)i+n*+zGXR`dGvz#E*PIAAl7gEGFs(C{kS)6?i8fyhl%e|9E-!g7HitUg8_GdjG>ho&Gg@Po-MPfFhNPUUJ9xErtE@ zS{AYC+wLojrTvl1V(G6$E{LVCi!OLPpRFmszE+R>kLRac>l}|eQfEC* zdPg}<bu^kVDFhTYA74t(&h`#9X6$!uK?Aywt=GVS#;TP*1iMg-G zj#e)p6Woy5Knj(;tIpAunA^x^rArU5K2pz%brTXkv6N{Kwj}008#{U)k$|pE3EzKW zkK>xFE8?VGTVs1y#g5dFw85-9joPx=>Z}CcoTmG8=pY|UVGky@7LVg9!La|gi&*0LPf-~u7wDa_xNvhdsf zPH&WH<)pfD8$JadE5&-J>Wan2o7pArHmYUC_sRq)K<5#2iD}pQ`u;kL?!xr`;yI_U z^M-M%pA}{U=D}hDn-<8NCFIm*WpuQ5zp$)~sx>9(e#w}6X@~jomnpT7aYeoBMkd?%{!?|4TbF*x#n+s%-bg`b^b6~TCB;8LS9c=3pmTdY zJ92;d&P80NJ`HLN$5~@pozxulin?=RDg%hQIIJiY4%*(luI@eMjOm*k&mqjs|?={ci zRz}Of{5ASoN;g}vlMyU;`uvbtdMuhksSFLf z;11!sud54{NMbGo@~$(73s z!|{KS0!Rj>mk}`7H)Lr?YPfxo$ZD7D@@d^%dXcz3XkajPuKF6!v-deuXGh0`NmOwm zSW4aJSP2(Ad*5f7aECl*tMM{G4}FnX#dmba5ej!iN+jN|VIeiI_gtzqN;*9P?YT8V zmq7cHWSlF+#yfs5LE4vEYbdom=ai8loXaYyVmpENV|io~@$*L+al!=d@GmOos%~u*PQa@6BoB{%c?S>2ovj@9a;V?t zB%fHP9>;6z8er-f0C$^$>AeH|UF=tSOwia?aR|2%0M>9>-^_%Q?OXb^<>!Pv$09Wq z+r5=FZuXW|=?@|kQ@vKu_%d?Pv#1^yOpH25_w1+}=BunZD>6Rlcvbd=@EogqJVj-h zPqxx~#hKo-Y=>{FahCaSkiO-T@zn2s)>u!YkvhsA75|JLds;4_;m8In{-(fvC|0-Y z9c$z&Po+5&nJ<6z_?mU{BVJtwF&^$U4|9slq~F7kdZ&3!lal9)ZSxQ*W8?{B1g2i5 zZ#OV|8B-$jx{S>TdY)({Go^x@Pc8%f_FR$4|GC4w?TfaFNNs+`6W4Gdp?AfOj96N% z+`ul<*4{6g*;7;aj{LJWK3yu;c>Y43|Hn;AfyMpmma->3mJoYVn5(%tT`XhLIsL|@ zz~Yc$S&}Y*aG%bS)IOj&eUc^V#{+89X)Q?-IW8nr+sazI$_4O8SK01RBBkSq>y+$u zWr1?BwOV;UUlI%k(~H(1*^NaNIbgo^hCQt%xtX!M0`~QqwVImNaE`HJHz}8pqMW2B zA!9LS3zhU_gv9}iZEXZ?N*FT7fMi!xpiqgi039760z!WCOo#uTR(U?~C~`UaU(M)(qQkp6vDK5c4u?5MW< z3%E8FbV=S8&r8v6qjmKGnF3a~${euzNP0Mvz}f;@K)*mF)!*XPU(Wd+&I$b@JWXPE z`!O})gC-n7EUo4)>HfE0w;S%v)kJ&EsiQx!;kwbE^Ts6&KaK`dKjqTsc|@PnMI@WK zkBLfySyN*yRr+Br7iepaLl&XIRov3FwN)~Xv?tF*4!0H?%Tw7T*_1RX#wPSk4y`D{ zaHl;GHZYhWj6`vft*0#TF!~P+%o;i#ZqbbyrTljC3&Fzc_(cVj#PBnUjoQlg+M1!w zf%}?jugX@{@~wzXTMCBQZF~@I_do@uG0qp-#$U5(YoS(RFjN|2ule>!XzLDu1~9bT z^XHsmXl2nBb7NleVRUGVh8vit@*Y8J8+nPX_KnyoYTrS#dNgVuQaL*;_{m?W$$33L zi0_GJ)zkDw$i|hFYWTty>+O$6@%H7}O5^YCJAacqMcH?LWZ&7sos2eVDtD<*=`R&W z`ko1#VUim(zrp)i^P7by2$+yPxlLelqsPm$Cbm%GX{G*W&2I@cp)o|@fXr04XJDG^ zVtSm7L9+!qe~1AjUb8v_EmRz0My$kjHl{ILaF8t%>Gb__Yl8F3VC4KO7m9&axi**T z9t4&6=E;qF5nY4lH8E-qp4VQGYdk-L=l=)uT4gA{P9}4JWO0)F%l&Fzt336*cCO58 z>GrVWLxu-#uRoJFljq8a{8T;?&wcut?cYAd%qBkDj6-@x8R&~Fdp$!|ouXTay}nmb z*VxqWBFSd-mqRmanf)^*6T@C}|Kwcnm1Cztwm>k+h1QIi3X;2l=ran&$pSJv>)_qQF zIckB>8ht5efnd!I;}jj#TtMTP3l!l_L0UL9mzGC)Q;D(L=?bse_Npz%K9&+QE8h$a zKR5gzp`n^5`jdzWd6IV^x-H4}%lgVo*=CF+E~tKbBFN++37k`GY)DeEHTyVL)KQBU z=8X$r7Fjr*iBe1)hj}lDTF)k5?xg%!vrzUeTM+Tcy4_nB2dGJA~Xq zjmQm(`|Co*%u+n?577WeE=lK+x#1xl02rzLW> zWS1^vvs#y|if&34kF+CuB}3*C@@QW6hHZq9FgSSx@8b_%cVs8X%=T~9A#09*>-dXK z>)$&0-({)WYQ8=+*GF?8|CRF6ygd{TvNgq)NI?jjf4FgbbPN@_UHMAd?z>1IJOk&I zAfUhMQjwwCD&Dozr?G$)f4$fqCKg|F=uVO;O>@;Yk6Tf>qwceMdUM$Gk`~(~1Jm=@ zrGHI!b5z^Bas^%-WAF42~ z#>>37BT%_hTf1KVY+wEM+Q4k6t^3?u-6B_O6XQmt+w|7IxkCkQsX}?s2wDmiE z#_PV;cU{`ke{ zKj?XfTusQ3klcA+%K3((`pEOH#3-Zr z)+~USN2iR!eks0ui{x5j=nn0~VfQfj?6IpnOgY zfPR?(0nx7~43-JG`J7&GHT9G65dkFSR$YUOac>NR_B!5`v5u1O#&X4_>ye{jL*wK7#%{OR~zuEh-zgbTQDm$ZR`J3mQ@HZDRhU>0Q71UMP=M3{CBe9o( z@7Jb(u>>kyFf2$sIZOxJ{kc#geY)iv7gse|}VrjUVyzbQvX@7ZfpOVkZjg zW`q)xudp%@&q$0V%6Nyl2}TIUI`YGw6VX)icOrEXqrYAwLx>KQQB=&^FvYD>sx^vU zJ(uz%{lY=>1Ika{!(08Vq7E$lQq5JR+LH&o^(Vf%;Z`2irnYNO9>q)R-ly)B)7qCR zJC|SX+*9AW2ij>*?x^fBUe{_(ZF)~QzSteEE|1(AjC))VRG_3gz$wr>hnS4OUs0-DCH@HRzOI0P*)R>=4)Rb*4C zClZDGr-`=&(R&@HIPl>7l4_!x-pyQYH>=d;-qi0^`_y`oLAXJuugu-=?@Q}t&t)N^ zEx0p56sXjtcbh?@D_GXDA+O*nl=-9T2d)5Y4{FoUKl>{FTu$|MZECN6mF&7uSKi+E zEG0M?Pd@EIKdBQF1dTlL>-diKHB8g?*I2FukqKYmOXLZErC;0W8}wQ9o@0M; zSnjG7hf?=~O;yb}IRu)9lEV~;^ z!3+jLs9G|B#y-zFmi;2;@B^A36$G3adJa+`=;?r6J9QG{;;Gtg%IgdC?j*sVCHl<7 z*gU;#(+o+-j4pG#uKli?f312&*PrfF&Dz)#`(R3HRK+fPmi3n`2#RE16P0O+cl4m> z3{Wr#)>UfvlXLqaNP+Q)~ETQ=Fx^N(IIrIw*HzEiwrmOOZ@?CM_c&b zY(3U-f)eKhV=X5_p7$dKOpPbPB)tB0(4Y$2gJtMnN%Nz_@^$HH!uQet>1jpN8Ht*& z(?G;MamH)^hM3;~==sy)+Y=9XCR z6bJu(hi)wvi<&5Sh~cCzF}yvdI7_OEt0vfup;^h4{LF^IpUd%CpPHXhT~)A02Rm!=mP=fW@k zrR0redx}=1?}6xFXCy`igf|COAo){1ZPB-QLoxT&B$;6qi9z8S0~$r8$6U+dAXY)I zvI|ywkjp410|D7);DsEu2|@e`Jk(9Q%s1KIoEXKMwhns z*icG{9UD&A2V*1Z*4ExJOlUg{k~&Ljwe`-s7fm&scUlYxZsrP=y&v|xS9i(G#N-H` z;=o95d5mcDjzxI&OZ3A*^BLLYC)SP@_;K`g@-@^|@%Wuca5csd9E(Gax5JM2GH)+l zWDJ*eCH^0))vF!(vi$W#UD4O1$oPDW*#WotCPpezR)hdK_PMa}95Fx&t26?8tc|{W z&sxifH-rSS_Z-@qb+k6fY}1-V-W=6q`}#r-y1FxnZ6;jSDSsVIsA;beJ+8&pGeP;A zNBEns0jU_~YhH!`W5~QBjE`PW*=Y&c=L5|}zUBqoJmjt1&CPZhVm&g%kZ;Jss2hFU zTX`T_T+!kKcTmGNP`N{f4MVTXU)~+m#KVW#eRH_%qp*<-b|;%%&0a@S_=2Xucrv`~ zfi+gSB1C&ZhdsVZuS5I(CMnLPeZNKXZ^B63c(w>6&noo(H>o*;WhH_FtqjgU6WB_s z>tHN7#P>9`%L`+uBOU#Uah!U^56o0?I;Pzq>~&&+l59jMi#CsrJ7*abO`^C1?$5S8bK3su!CbIH2~{WO0& zr7m$U@*9(vGi&t)8d}IH#CsoV>+c!1$f&s~FrhE#=n>dW+PLN-86tEA@kY|aw##o{SujBSi2Ed*=PR9#X6h;8B9!OV6H+)9TCwjUbex+Y!?Y= z7P7u^nd18C`?HI0JuUwsrX?ZD4e-;<#HfE3xgJc^@Mwpdg3W_GBG-lFb`eG9>jN(z z5%-Mqc{%wzGKt!t-$w2;W8aOYf2X;Q6W^baV0p>!@<=K3dfNTFa9LOJ2JnU}>}bK30X{cB&pfn$pTb2db0(br zrJ6cW>oqco&i@J;n!nkHipIjxr*z$H9j%*t!4Cx1Zx_Uln8W!43o{GWuOoAu(F^`VHo^zz2bbG-umL zh{GAUSzsqJ{B0iN=Xp+hn#V2iHLon8Vu4Mx%4ZeJ;g;H}ao0<0D0k~Lv;iNZJU`H| zC1CXUHPU0)mue9T{@rqRJrA(2i#%!64zpD!0Z%Nt4$xB!DM8el?i74F2c3egGo5o~ zWU=55#`c|nLSurCtwEOJ!Na>M(tlFqYc2~kFA?(itClFz$n0EIMjhL!_ z9`PF=dFwx-N$aODMOFGH>}FbA!itD)Tr33ys+KzZ&E<+}Ldwfo@P7oeF5${^l=XI? z;Z1yxDC;1jb6e0@V_M@Pq!0DXKeWjaxu{}0ax%m& z9N!1idysv2w&_~!0d4&ih>LQ{zn+q#t zVnH^M5@S6ohyu;GJ#2J^ z4Wfz48Dr$mW!`)&)iGzp8{X4 z5nCmesvvw9T@jRQl=A1kkf&q$9TwUui1|^o`)`WLBD0k#y>S3vWl}r}PQZ{BK-W0H zaFD^Vgzu#bcL6W3m;@mN#mxnGL0KOH!c#nABef80XNe-1d~w~|0a);QFWLvg9WVeOWG-3%wnRQ3 zOw8>QQB>`dx0rc$`Ko>L8q<}3CmLpS8*91ZU_ndRa16kyr?STh?`PTLDhAu*&b94v zxK@wafml-gWq$M~taGwW?th5aF8*|Q?Sg**uU!C4+b4^ITXJDqU0_+Oq@&yVA=?T5AeeUXr-5m2w_w^j28tkNfX&XW*)T2Q z+zFPP1Jlmr;eQmS9U>w)1JiD@VA|WcX2G$U1n9x>qKtdc)_g+Q2?xVm?^pd^|Qrjm;?Qe3B+L`L(AddoWdIh_xRAkLXY9D86 zOwN`zp9-msYw_taGTC-d24+P|bq1+5T0v(U5Hj5;gfE5T1z}KH3#3K;+RO?IkXD@F zERdFn06^NWa!wxfPYu%kKEn#C_I5jHQF1P|W+>X!|Fj^jM6f9m3@&bz6elcqMv#_? zDFf2pE(-LBunijH4q7NJ;`~5#M>a~ERfFVz@a<2F(yrzUgE}`0rIiho{$HT9;?JN^+Jom= zipA%TDaFEG27WqxmSLTR&l0n=SL$wvhA;T+pM_T0_$+Abn*;bP-VxCvZS6JSvpW0G z0ME{dJKvjWIQRF1vu+!lEn`*wp#{zs@lYSwEXtpa&DLAktV^(2QW~A8^YHY3bYnHN z5EZ@s*sQ$VtM@~*B$ETx?QmJptULO;1sf{H@l?eni&Eeud0M{`d%g{2He(KFk-t2|)#yzbpy>x&&qwW%hbL5HIq@7jyHF z=L7Bul1XkPg)r_01S|rNt=ysDSkFOgfCfBggku4W5;Ce7I zs}%!yY~Nr!)^q(R+A4UgXD+;wjmP%dc&uxtQPUnmK7|eEYhXXF0Wj8c{aD@>FxE5I zZIMdASaUEK>$!fMP*lKJ&)gz;1!vAHM{$v*kT36Uc!_h zy}$xj+FKVqRa?`3PZkv0Hvq*VNoE-1+6RzWmyN`3${?}0DS^bwR(Hm{9!z;H`~!?a z5eA99AGwbR9_~kCtLKijkl5;=djN?w z2P3i7bH`aoY;~~6LSk{?a?>-w&nG4l$CtWG^urOX&oRVK2fMIEef?-=SFf5F)syA}J;(+*=pfUC}3x$;j1%+LGGA|VD z=tpAbT1YJH04E#>#^*hU{1zYWSAfT4{8ik1J&$v~{+`vGu$UxYY7 zERS}0WfgY>&XMa>I8($e=9^r!QCtPYmhf`2Z2*XUj{8i?@1e`@H`jAw1F;XE3W)79 zhkigahtnnn#CDubt3C;cy<{xlL*l@x@rIoIFIjl3n?>CakQ2~{`7ZP8uYMvRJAj8F z?EG;b+89espVDZv)v<2w6~%qyMBnv^02Dm78jR%(cjz62aw-H*n`uk^?7U-qob3E#+{$GHx@tOlZw0vg<-kx9Uz>2Sx9WWED&EJgz;A|QB+}8u0A~w8;(y2XJFU^EO+R=a({e^{OJIl!h7HGYnwfmUH{lIm>)S&@4mAaY%Z_GX*gFtDRMI6dY{{u%SUrA4 zP@%9pn54QhC@f0rDNxvTA7*QUr^K%Xk6mgjE^$x%dRo)3wlI&rWU*VDt+rIW>-j)| zu{`qzQ?cfMy|PC^v7)UgD7If)IU^J+c5Vg7zBQCistA7TNaZOISaY_}1N(Vm?3Zl# zHB8P34_ASlLXJZg{EBS|_*L$VS9db-s~A>uvxuT2lhyRH59+qJu@*5YU5QH zD%hj;koXny1s`K{2Rx#8X$_Ll%1Wj@`WJQx$pc&p8f3HoJ3>(fAoiGxUf!2(CVhxX z&R-TX?s0{TTis1~QX};QrL`Rinne9#dniuLQ7?(+iWNNrVE*a1{rDI#RpVn8Or__T zc&wn;K*hVMHK3-qehdx_Lg*ViRP-iPyStaGrdN?8seAD8)B%T+pT;!1HsxOb+UfVR8_ysFyBWx@sck_oC*OT{fIl2W5H&jyWZ}#88yCDC`uvYuLOnob}pTsp$w4%3+zY%+45j+F>6qX6kx{#)YVta`4j_tWXB7XO1yxtNTn;oWcnLT zJeNZTd13MYPcc!GPi>_H)qp^}W1j!6y7D4dQfv}GbR`EYiUd>7=hjK`Q|&o!cOa=i z;`d@HUgC~^NoSfurJmM2$~&!U)b!|u)0#um9n&g9UPtt^wnx>z43279e{jbY?`x6ewn2ofT#(oFi<+hurT(u} zQsRrwgts%4z}toK&BuF>rge45S-tM*RCxPu;?}Y_(ydyZ$)8_J)QU;~uNDZ^71*#6 zh1b;y{SKH{%Ak};p{AOCXY3HUhUMNa?h!wL0&e@}W`ViXcfJHb=wj>1k}})KTPm9s ziJb)Dpp9|#n@he+abig!>a2IbT%zA}V_Ww4l|u0x9yDqnU|%~MN=H=O@TiSw^KO6l z=FX3E1_CFdINDyF7omTrxfXQ*%u5`Lkdd~@khRj$TOBITG#3G36AE)IRSlu;zsDlf zS)?&cJ#*rDz4~fG31|?5MUzpq@-5 z4pYSn8C#`nC6Yb1R20tf7Z|hS7?Bn<5lUP&gHHq#v#i?4E(o>Fp~dNXc69tFwNcMn zb!qHkyce%M(RyMlxFRY4y_HFyv0s~>B)DQPwZ&Zqhk&M%1>UAR7vOxaY8Ubxj{YJk z!BB9HT{E~XOL|!GKE=j1mDImti@9-&Rc@_47rA6!okP(& zT{VZ^(2KR}T8IWNU8LRJzDQf#lJ|jjpSRLjtS{>Dh8%hA-dQrViutB;?3e@f&A-0b z|4kVPnUBq}KUV#TALE0SEIueJFXuC**njorKy5`w_X;O2>*&uoarCsA{4)acdlEY2bEN6*5&CbC@0$^Q#j#ySUO=pnIEc57Ce?4w0qQ4}#^!#$?g% z-(Kjao$$!D*FnKbwO{8}J+ZQclGS?akC(_cLQ^u;`>4aJ-V|^BVMm6%RKo7b#o0ZX zMO<&w3RN$Ma89K#&Oj%+RYm&k;a(*pwX$e0+L+{=AQpwK_qN6FbsyB+mp9)q_UUrE z3!b{euFIDt1qJ`?%}up2b4c~5yR|WSq;1pAzM|tLOhKM=9`jWv{qEIw2xl2y2EN;99Iu~ z5U&v)D_oc!rz~xJ{Q&*#`j=xT&VD{!_|d~woBL}$Uk#|i6h*i12=uD* z$UIK>@4-7fDq+^%o23)eWC`MWVo5nWs+s0`P&j6Y)b>RW*!?S`)TUr`kA7*iH-go7 zl}UrmW_dW)!JC|?w?*Hk)M6=B^|Qob#gh3?i(Z7T%KG=Hvu;R53qF3Ej&qVUn|Kogu<}5~J?Z zTlaDZ1VAQgwI!L?9NjKi@6xMEyCf86`}I#Osco}W5}VH^ zub`AH|GR!)f^U}dA?mFf9GRuQs_HElt*`w9b)Rd0(XKnBlOenfd(2^;;Dr$S1v&<_l{^Lx%^h@;h@p!yj;xn0ig5*s z&*wbcL-OXxQubQ#2BCAx6N9ouUM`Vgv(@SL%VrMsccaG>zYQMmQ)2qj4ahdmJ*{g4m zi81v%mGr@NpDf^?LlI;-itHndDP`L2$&Qj|NN-UQuo-4D} zVn`{^<%E66kY;MZ^nQ&bNeCJzD&Cda6w7LxDz7Z5RB^!tK*GMb{~c#IzQ8p#KKYoZ zw~lmsn}Z%e;*Vrns7AIfeL0!rczXQKV=UK3z2oz|Sa&5ctkLtuRUlFL=Q~*nPauPj ztb$7=R<2l;XH5QJx^d?RPIP4nZpHeS`XzB@)3*6NCK`#tZILr1H9m2jK27x94S!14m0M4rvCPk2I$9Z)CQS~2tfDKBqKp1LZ5 zp1x=D_K@)_oyLL@8JF%b`UbK<`i$dOsXQM!!(gBbyVEkS8NLv~wGlo-($+J0} zj~KgCuV#_!@HZjXL9*NoCfB$RrWz~z$(8y!+mD#d)QlZZ1|B5_%F}MNX|=lv$cB>d zYio-5SipFJobho!P9@}H=URR9Gx=C!&c{^Xu`#)KnsH}uR^LbjSYtT zP}Cd=0mn}fhYD-i=0jSIQOOg8dt|+AcI}jD1fB&cu<`+L%WK0T`7$k%Tk2b^j}k)* zVL&U5!pNO!f%TJ*N9LJt>`=!Wh$P|}2aT~(D!k2g7G4WZj6~nG0gAJEkB9v7tQ8Et zb(gx5&y|6c3e26Q8-$fs9}%{STtKdp@#!tb*3}19V!2I{SkCB_twP>UFU3g1_I_0J zqvKR(j#Zs*IreibL%v@>UMxz?;*63O%H;U&_ZQuSzo<+3i(2_lCAn^c_y&Q!OtHK` z%b!t7yw)HKdjTGF11Hy97to))Cp2X?LzW<-lnba2{RFE--1)q3bzdIuk}D)0dfw@y zjhtyQaUAkD`Ddj4O`~SmE}>ngcL{y;&rGf-xr8pZ73$cEETH`wT{4HE1re&gX6Vr|4>;EEY3kn$NgwPfln8{^{{d z*T`KmfZ6RuUOzSS+N7#LLs*v^1) z%y>CNCr<)#a=21C@GN9^Y{9NN9VN{IA7+ zC?r8U3V6nC)f&aSniwZm&G`K)vwce_exbyrHoh78=McPE>Bp0?oPU$`cp01Pg8AL# z#=I1dkPZPri^xXFZ}V?MneLtBYZWAjn4=!Q5$SPe0IgVuGw3-U-HPm;2#!3Nk;e?0 zDEu4=ll&I2%$EX8cnzbeu@HDDzsVO6)4tWm#_qNQJBdUAG1kO}imIN>7lM zY!7MElNB>$DrV8 z(NvB%I$*mZK53lMRNX2gM=;ivmwboz+d5>9;v>60uz7HiWH|O4KximmL4$SE{_FEqVR5>GjDxa%_jG9%;5Mw zKTiu_VE!A|ZSBp%uL-4Co8k`az51whkm?_T>{~)s*UW|p6jAx3VR=(MV~Jpx*2*2} zA-R)vNqQ*vlD=@z`J_ST=L|X@Ip}=Ypz|Sv&K+ku$9U)U#hoqaZU5SeLiVpM#S(R) zrnrA^Q*`+QKTlsEbXmO}y5#ty4MxfpUS{mEA|3?N#bo_=ezGDSh%?h-zm`iG^nSoZ zCv!Kj=o9v=_W(}~Hqo`MKZA*`MHLISdel_u8Eg~XJs-kZ*(SQ82eW1Pz6Y#1V6cf! z78My2-Jhcj`HH9Pzy_&hJ|{$c(Tr2(haZIW|MGj;UtDZ|@&6b5oNps+NJCC(ppzIH zG0=UEXT;VuEnc&yHXe};(lOGpFo@54$LaTw5N-MqOvJSZeV)V1FUK|~3k9*66@HZ| zrSJ2i`DWY9rWrN8wMN8NMs35LXxF-N0yk8(0Xv4fxIanhoA8*i4R?&G7sYUQsTl4& zo4ERSBw%u|;ZAm`V!YjsrjS~B3e#NAnM`vtPH&nM|7G+@_lKfK+NQbZUs77*Sf!OD zg}2sViQ?;*bH%pEEw*e^A~e)|ia*0A+2i7)TBcQx>cAcs4|O=Fc|tADGuz{oAGmFk zyAo@P*yM1iv4+=xUG8Up%(2VeMY_$wcDeuR7j9BtTT^1b?f`{RMss(_wx5T26i)zFj-f3VxDUk_xmfX*G;WCw6=U0E^T&8H z5yovB*eSzR@c#!M)f1Dw zG6fzqul#R&3jFB^nF4X3Y3$-@-KfN{1Or-&ZnlOZ1v5}q4LB=-kPck28^O1Et`S=@ zKZ$kfXQQmd^u&z>I6;#qdgaX1r!~k%j^tm!V)cZ2K29@_jL;f>q23a>R|i>|S**Fe zF3qhMX=7$$tr?=U;Q77g-igv(52@nfjeSyB{I_}1o_L~2equ)pXl^NoTH`aqCPt!M zHTRgzJMkx6a*`Oe%tDEAd-$y?%V?BBIFllI$9gQ$rOpnTJ5xf>en6Sz96jpO8~5;o zmx2PFg=h}&jCaiM{Z0fTVV>$frK;kL69UEGTqF@~1t2oEVMA>Rn=X8*$-(z~#mg3| zC10WoHFu-+;zK`DEopq1A4+?aA8m}ao3fE;k&D$ErK-^hndT;}swWB`{R)HY(*KZ= z|A^FiX2MBj_c$qA3f0_dXJ5^&wn_zso#!m(|B%zo|4wina-rFc=uK8rr}oAv5DFDM zA-!&X?;My#4D<~TQJUHV;4lXjEqdaidLGb?e7&RA#Sw?K?m=%4c|$c)N}?j`IoAFibP?QqDe=6M%LwKP0jK>+c|G)gbYA0TLF3IBykXr5bKg32C}GPN?Rgfdkgy(?eHvK6*BUd2;VIia$-|4j>f z?&P8X5_VGA8`~;&F>0hrI%|gxuS;RX#sd6UETT&gwW0dkx6xAdNILd*Y|0Q~b$Kgf zVCI;O1^7M;xkt^f3vCTHtdQJCB9wiSkgM^J>PgvV^9vg|%!^zoY}0C9sumv+Ff}(y!~il2lcwCRQ&8A8JL!PfVR14iTt#^*8|i=I%!D%OSt2*XkJ zMj1w0<7|;EarLek0T1_R^}3X64>M~_(#TSt);EY8;tzZKv}rz{KNmVd0s+GkZK8UQWpOCK-+%rAy zyx(v5yN~+~XLl%33n0;UJo*;G&aIQADyG_!7a5x_Tz$Vi4)HHa7tUFf1~=gBnQAKx>pR-d|$Tp8S*WVQizY2DVYe zkhCCOI3)9RWu1Jn!GX?vD3nmog^eqN9n)R%Mi?gx<>#g+uF_|NrW$|u#a89PH7mIt zjIDBGwXlXlqXf*tN5Od5q1>Rij!#*(zg2O$X-RSZmr3$eAPwJ@^s$5XBz;+J*)w{3sNySa7x?z~nZv#RG$ z>Qd0eR(gs~rN&Y(I(1sJa|i(9TmVGpT=XL* z>R$`ec;-HpUdZaxV_%?8-N)diW#YL|Hmm~eV51ZST&`C?q{d={@Pr=Emyxcm6@SxE;+y4c zX@sGt7Gqj14i|XkZ!#Zymg1`wS1rDMkkBksT&$I;_Nx$*qvm7iYjCT4&f?ZbIZ7AK zhmr%T?s%HVT$j9?@eQhi`^f>bju++H4eHuPX@ONhlPX|rP64}DpG+TlA$Oio^x4&O zGJRC(kY={fXSmSk2}PgkM=av}l(LA`E3v2}Aa__S{E%mCF!mhP#RGSr$!=x%knB%& z5)o12CQznCh-UuU?5CJkpWxjyQ%#(C&9`1TCDnvZ15`^w6TX+6FH*6zQ7D8Ud4M0B zdpl1fMdC_tGaE00>y}7(L+m8dJ_Rucz7nHcSaXjQD_QBr*^|F7R#W1No)rWqEE4Qr zZG4b<&}b}{+PIb42Sd2!?f64-5sga9qQY{KdtK^YqK6-QSeU;ml*be5oBdOC5wFOz zwrDJ{y0XJYS8YW~An&F7s=$rLKHgL!`m&0ork)@C$S^?+HEGY5up|ua^5;QbSdmh4#iO`!R=l?4a2!&z!?Ed`&gZNG#@~L4Z{7 zyTt7r3vQ)63e+UNf-4*Nrxxvxi0nDkiWc+}X<=N6MwuR~6Y`wa@En(8WH)R47iL5~ zp_kj@Go<_ilurP7L!T(+hkI-Z8|>H&lOSTAP+yNLu^V!j^k_OV4ux2Bg#QB952iO0 zxqzv>qnzB6ucU?$Mg6#A1D|Aoz8`LUS8Ke5f|6&;x8tft`lVJCTa&qN7u~p=)SZ`U zX{I6KOwpOFp$yUM5_5zYhQp`K(N?N*K+Z&>N7`;UYzw#2!PVUkRdcBhGdh~hBlQ%( zj|c^rPv}gOAF$4ZUYz}ipI~B|i$ja{tT_zpQCpYdv`bo8{fI?kb|$t)I0~|qY>$1G z7J}gO^uy|+*xKV(e;PhiUA6)i&xBA3(>G2Jc-h7qTdWt{bSh`^9+0B~q>Gp_Klr&Yk9G%*$ij$(s6=LGH>O5{W7KJ|%>qA#^KUd{jL z@8LNzHpT#>(MA!OdUd1pAZrM_E3vOkXYugf_tYbMxCa%5)1iiXL3|w4QX()1SL9pR z0E3ywT6>L|mtV{>A|Hx6N%aK-*~_qmDdogA-a?g_t@)O;-~6{7N)9K#sK$q4F|(0t z)J-VGhvfxChCB_?=I|qO^kWpO_D0ztX6+u0YmjG$z3PoMqB!@N4C% zV~?3^E&26(v*)&7-GjrgtzHi0A`=c-lZK(uI2wTBmEp1D`-2t9*)mj;g9jzrWaKiaiAdf1G(xtuwx^zAZB#&kpLEEPuAs z(ogy~TQ9sSr}W`xXxXRhpZfmtMULbDDvh$T|FA~;)$-F*?$eb&xc;kh%AZd851d4o zQ}~yimOj=(g#K5$i0c2$7w9PIJ^Fvy>09wh{cn{o{ZCah{cjaZR@YPZf964}|JApp za{rI|Kd1EJXK2}{>z|YQUm7*g|7_E8x{>qg%0H?9bIPAi`Tv{#w`ZXhEcG%I)8IjN zrtw|BQOy_ZXKYVA_ifM2a3}Yc^?{SG{{#E~{lU@nQ_%=SAuw<2PN(hD!F8s{LH^pO z;r}yC*w(~ya&^y452+nKQqZGZCYFDujwkoesRrz)tFMiN-ToQdUp{B1%8sWxb$jbK zit>?1Dm+VTGG7u?pQR+5Z5&&?dUB&rcm4GCU2A?!B!0yA%nihVolJ&LuCK6_kgf&YVe$@b3QFU)o&CeEl-VyF4g}MOK0P;gPHVn*Z+a> zP`^<@y=u#_L0U^ZAyyRgJ&9l2`)TW+p?Bx`$8A;+@2Ei~pW2?U`dh}QNCd`bvDt=h^)XpvMi=9J zM|qj50=04|)%}rFtbY>uDt%t$RPiMsCAm zd#3mcItw~ezvskX&~0?49&Oz_%2%+(&*4v5Bvk#&@I3RQ|F(UQ#6MLM&d3e|f>`=C zNOSEBmG?a{C}I|)GtAh=O5(XnSxJxr@?W!@nZ(|YxzhGA)Z-4HiZcn~K}gIA-WFR! z@qF11CYF-3onZnz8y|q!_^+M4X;j|q+eS5q9o@e4UOe-u)-|QgzED+dNNfBS4>kM3 zRkdNQ@n&^AtEzUE*7y}U&X2L*YvZ*XiW{MqUpU{TSF=oNyqvS7h!w^{b#0N>IDzA4 z-?*yUaav=c9M`&H_qcffOPt92vT`QxMs@8dt?@&Mk-UHlejLmi-{S01fFGP~SlauF zLaIQKRN{5ppaYu7c7(DMA!!mSTBbISyMAibxEr*_|K^#g%?odEOs!maJ>U8d&V%W; zFu9!?B>Xe=7b-0EZ5Sfx%_?q_l%`0pzJVGmPdrI8@U{YV*l0{*S*&f1RCZ}|EjOg< z0eMd>I6y>t`gxXlz!O@7>}8cATLFMfb*)=#yg(ISi}6Xqy0(Q3jKZ%9c>Mf>l0!xu zoTNP~cr7VevE#nt>e^!3&#^R6AZPYm)EZvk0(iJ}FhCJW2bNQAU3R(3Q8IaPP7?*t zR+$u>r)%ObSp4H0zvvXr>*7|5-36=;iB46WAy$~&&WKOmF|~T~&gex`H_wKz)%jzWOfE=d#}0HO{f`Bo>T(vM6lBN(N|NS;U>Zp(n6Hf zKXKL;_f=NcR!096_tjL_)hgOt1XXyuer8Z zg^+qFyn)N5TrMSYK&1xYoSp)Pz>|dF34-V8sfQ#bljT07NnyXqj^tE+vL=WD zO-AiOwm^bIyn5sI4dp^|_Fn*AOpLt-Qk90|4iy$WF-UZsGV`Q9kBv&Z?vVEhhi^TJ znBTW-~Ae+T2&7YAin zS#4oj=h^ z4`}TNRs=>a)qT9CHQp)%_i|r-RbJ$xFdY>1^s;L}tH0qTs*2o)I(Z!7715Gf$7VDS zQfx&!^@w~Xb}y1#lE-6al{C=d_>3YIu@UxkhY3461eG0Ol51ws5}BelUk?$p(I4Y{ z=XVuQC`ooJRs1b&1#u?8O2UJU1;r8&!5y98tXs+@JlJn6*8Rlcwi6yqobW6O3G%}3 z3v%3IvjTIMKaeHjC4Lb379y%5RtXUvD*&ng75!!NTxLHwqSQo#%G&G2%g{z!4qVor z2P+ZaKL6p6@tF*=jO>%RZ){mcZE?uBrW99#a-m>|ZG6MVm@sh(VUk}E--fy(I|nHJ zhVy_#HfarWMWFQOt`0-ZdtBm<673;bxv{EPufDN7;tLwPgRO53of)5ZrE7NFeA2zq(r!V1m(x0|SlxR*id^e)Sr~>DH3FP?2 zM-_1Rz`*)0ANGG~P`_F@^Xt-2H18dH zynl71iaoWypIbg9m#eVlOEaa?jN)|RhhGD-2u$f${Ij;^QzK-MJZ4m~Io=C;yh4wC z$DOA&Y=$Qgy11#8s^sk#2|vbX70)7T7A`k%FdCz)zLEq`!FZ&E5INHBe#edfANk#7 z2;koqGHUvi0{tDgn#imT9{aaL7FD839%TyKLhCZjzYIwnS;ifobi&}o$uT|`W74VR(1lU6tFSiTFX zif$nt?etepbVsLz;t@Ba=2{x}iiX;zDlCobRsKZdVQQ*ObjCw1I_a;-OwV!SO44LdM5>>)%;q z+>R*e4VU#T`z-$7Fo9%gbLu#Abs1tx>GL<;#lz&alf9hTeA9R<6o*Jjk@(UxkOmB3 zu0uDjWoByEVv-hw8^tq>QN8ON$tKZaWOjbltdVL;{{Qx5sa#DI=9i1+e89}7XOm&| zJWbNUn+3VU^vKg@Kf4#BM4liJWv z!tC{un^!aIC8>is`_a>`mtOm#wO$%+WKE`&Dv`?w(pNHTFexXe%wxYATxRZm$j>z8 z6qsGVqQPbT?xeE%*K z=!bVKK~SZJaIW=j;PzTR zgg5>S*e4|M&c31`6Hw66!Y;p0&@9pu1xL%Sy-o7K_?X8>Dcw2wd8OIxKQsZq35LvqL_q=0|w^IzLJ1Oc^ z11cxJX7&C@rQV6hO6uh|vmal4LWm%n!#zu6gFtyAYf#?Umhs|8jNb$0TEw~Jp;oQo zT#>=D)ixTUOcbTQrcNJ(6i;qaA){=_t#BNbqcf;Y1rlf}CPQuXU8TO=hLR!ry7+d8 zbo?W3Qla?8RzIwg5$q1`M)g<$C^8<&Kcp~C8mouV|M3XY?c-bsRnI3~^>39sq9oFpkLu`U29f9xv?|!n*c?3ky56yg zI;6=Hc}XyKG#x4QH!pPKeR7Q>P_=LjOtL-lx73iZv5B>VQtZQx+oR1$ljL1AiKaD5 zzCkonU@a=k!d$gmm-(H%vl5W0CxXS%WKadv(7gJPaaRwd9HHI+MW|!H*nl>BS5f53 ziY>v|%Cp?VmTD+-XTjDT{dDH3jTAZQ+}xGo*t>KNyw4aFfy-KiRz$W zt}*VROV4WekD+ZH{xNO=nD8H?dR^dpRBxL&k!4lyYU@oQ69*O9nW@+bk=(Mu$Ql7~PF*o)cEuoXZpFSlsA9p~iaD2FcB+c8=b7W< z>CJveI?$vx4isE%j61vZjhQ;$&|k+nIdxo~MZ6)|b%eyZb^IQiiDeUSRVcCQ(M-0< zK65D?9gbhdLUy`K8xz=*{4E%V5d98uX51j;~FFthx{f-mt zHf7O1yGAHVA~Ll4H53Z%M=o7S(7;f*;R?~pkoK{aE_c2(2pJ4nTyC1pldW)rY#2nv zS`JuaUKkZlP;bTOxrABsg%dI_O1-J5%Vo1E3%EhWb$Zu3f`?yQJd08YZ*GZ9mFCH~ zBXf0P=-XdFw}O@6F=mqy%o5Ra)o!(lzra}wrqDWEKJz3V3|!UA`XWY@pVpk2fplx{ynt-W+r!ii+b-tX05by`DRxucrit!{sbrnm~gQ> zRCaV(2@1x=MR_wj{1=OAm^U*Xy4VHy#Zt*!wrXE`wz2YJSnfIc@$D$#Z? zaSF{``lW#)i)fqcSm*qGC>M)xElfJ45azz+chSQ9r6iEA#fz;kfB6_}3V2u*wo+1k zjk{ynNM^CH@oMrHELNEB$*jZFGmOD3Qx6nlh8Sj#W}#ZEntD#5Iwb!^T9Fvt^Z8+U z3a8}wxEzP112YM+67wImJ?mlWUUS1w(QiMcJzAM(_(r|%2^6hT$ux3Q7d1-0d5C^{ zGo#QC=w}KaWwCNSoqsI9&U)M0v+hQpZ15+LHo9BTcq0hsu>RTOdqzYc2q#d|r1II- z{z>lWXJLm)u9@+blS(B7XvMeprI9~p;dhVv_FUNWesp{47gL-4lPafH`6m@cMqwvt zk~97*ni*R;saQF-|7Cu^cE@V!Kjz^|OiCdVt-Pki;zGuqswjo$PV=w zh{LKbP`)057SM2v<#u25EXmp4i9Wava%~_**8j)cyT?aWor~WyA%OsiJ5i!hsf-#c zv08(mCI)2&GO!0`07VoP6pJEOt4K0}#mK}-G&|F2J+1cgYi(&g?eTU_v8@{MmVhP! zs|KkGSS8?XkK-kRauw(OK5Or}B>`#A`QzpDAv3f0x;|^IXFd04rLYCljEjd9O%jRR zq-OsRC`qtoNBkZR1t6BlS#lE)bg;0{?TQq{yy-p>uVu-*JhLUPdA2B|bcWHOOLqTtg{}`wDw1Q)_JH>qtnrEE^cvEx+ z(apMpudAYerKn6&fWnxf^W3^INbj7aWG=cf3E|(To|XxomZeU2~~e5H`~i*};@*W|~Hu3g=(ZntAkzT^w@)=R|<*e1OG z=;_13#N8fskNS*{pOfMN1N5nABH3)hUB1p^NYkFs57{o!i{Q$Tbu)D@t69%#Zo}l9Yh*(2aIiIq?oD^u0SvW!u?(bR!yM21|)HyaBsK2Do(~#Q)|Sgf`NW6 ztJx4kYMfrXzp}J}$owLNs~COvO)XN2gU-U{f&Tg!X}%^1wYP z%zVaYl()d9{G){l$%Ncq^FoNGfgmSbtsb3GLHan(!K-zbAb!zzZ^8XtYY2ib;$G|c zsj~;zEAhw_KV~#wMX}>xZL)?9_L{=06-6q=c*ZNAF|N!vzDb?<5E5N)B=sgB);U z)Ku*!v=Sk$*GhcP#&V9R!VUy;R2wxC-~tI$dIS|QXbIy;%tt#y2qz}SZr4I3>~D{V z*0(8zkA3Fukt){yVYx4I)x~NMuSMAYyElVF?bCPd%=F$~jAu*?ELzE(y~@0EHxokX z#nqe7ZQUc{Afk%(K;K}(uh4CU98#YVGe0O~;E^BLhxA(eka`Fp*zhic^CHu4nhtGKXC_hGM@sB9zVqMP1?1eSFGChj z4ZRzP5z~^PdfR-k{t<7Ngt&x=D)qKZW=7Odk=MA54h*4Fxx3t2=y&*U0eE*zEOL^= zd*%oB@V4;qDQgo-{^(bb^;(Y9YU|)gEeKqNh9R+nY_?zU0{p@JWw5|g?X}Tad#$qH zUVDfo=)c$Q?zh)yuHqXv+GsXfrFpD)a2{%-aU$(~cE|ASeTGt)tKbG^;zdK%bSd+< z4@JW%JoG8SA!7^0KIg9-5bj;kQam1`PsoZ$eP!$k_K0kJR208ek2l5M=I9^tnto2= zdB|NI8BykeAIOE=C(h?5V#yF3SG8|xMNRaFP6B7V36juizOLGbDZ`63+9a_cGM64N z`!z?(C0>(b5{_1N-YmFy~-OR%x1P`}E1%eSPUMCnPmrUMj7B9mOXZ6d;j?0VAJ{++jB1_C?aqQ zTMecZ@o6|oga5+#ZW%z1002&={rLO$r0pI0^JCWh4pRT!_rI~en#a?W>(9rr*kaiv z$8x~k{w7ScL!gHpGDJ)&wz(iGII<}pcxdYp;y-x7u624C=P?~7GCcr&PLK6 z$Buzz$ER)hxK}o3nzLUdoP9v74IXdf4LO+ohJ+N+BZF@_QEX~=seJxGK>KHW}ra~@$e`L1XADO4q z1XnXeWd!ob@VZ31NK**Hz4`v{AWRbxwTz^^Js|A%&xB@V5D=yn2;JO}SgR<@5Reg- zL%~D6Vzt#u*HXUeyJ}`{a{5>K4Kfc;E;2i?#f5pV9?Y1u&{lPSsi~i@f)$bDkvD5# zinP!gUizv?cyX6RWPvD{&lu-$t?kfIdPMW472zCO1ANTl2K?ZsS%ZVPn_M(KIudi5 zjoMw(1_F7kdh)~|Qftg*Na!=`+(^wJ8(y0cnOnrZ*`K%M6lC7Sm6_IAQ>3;Tg3ltt z{LLLjJeE=FDLex5;x#TT8-oZ%Ff@KiiB?2noS~KZH&uSIbu=%eh0@(8DsP=$sy3WO*r66{ea+lN6soN-YUb51-&V> z;;tjaKpQCm+~Hq&Q2Ek@B?`-O8cybiEZ|7Sl6CQU*>{NPTM_uo-GH9K( z@Zj`JI$pB6nH1)m!;HeIyeSai^UYV@0q1=*!2R5(zEB{4335au-ub%72-)H3rqa^J ze)7gj*>owaq{3>ktQ-?;fdZ|9FuaQd2@aPL4%Ql;hM&PogdIZ&Y-4sCmfFotj{q() zx6fm}8TKLxOi}hW5EY5xVAyrBDif0)@aXREfyc<;(?&1k1oH4gNxNaMl??nc;qF`E zl;oe1eBV7;9*L1&t1wfDFt?a@&9}LxQ>69C4B8Czu!DzyOJL6?_>gIc+?yAo;8Qjc z(<$_(+zKjin^>HpcQlklyHwfQg1I6;*o4HfhgigU@T>Eg7nn^rj`~$Za6=fgNNaS$ zsrsXCmmZ<|2F1XC!NB~4aiBOYE`znDbz#Zo6t$3quBlmG$kK3*i0{BJF=;gJ5AjVh z<0<*tq|ohWmm<#| zTF!Cm65)6~<^9G7bheVmf)0?jituFT)grN;H*-ehnzJ$Zm0rrXO0I&thk^JA7GRaP zKB5Ki728Ey_YBqiPQu8|n~4mMj1FJyQj>!DRg(zj(zQ%chO^j55HDZ#grFv}pJ>Up ze3+5HX|hmLfQuzqj1Vuu7{SuqXZ3h-K0=AvGfDiW6{EbyT+@e4O0MGA7Iq}0&wNL) zcUq*55ySm9e~m~+poG!Nj~y0pc9=I`X#?j21spG3vb*hZkw^)B`sXxJfN@{5}1=9A(<4bYx{Y!o2C(W^X^npZWh6>=V}8m|(ZzGMCQ90>+Z-dK}hF2PBxC^$*}3K=}+ zHCfHiLVZw@*3_+yyMBwGDdBkFR1INIWY_ge1k>8H`#sOr+i& z>lwI9&Yf(9<^B6yE`8b^#-5kjHWC=MneT!GoU9i1sAw{*5Fmtl5j@b5#se6Rb;{vP z;(_l|BNGpFYIk2Mk3@?1j7W0SX}Dvqz2N8YE&v~oq;Ldun!gMZ#};3rjV&tzY|tTS zDVM<>?!l1Q(j9+w#U8Qnr&g&tP|E$bv3vn$03 z1-OQ&AsW&aPieDvnJ68`u|hr+)9PA)R^&X)M_=!+s-MqJ<>l1K?H5=_`&mw$*0`4@ ztjRofg*}-O^u^KUKSWihR}H?yi{xF7Hc?i2(X>)}mUDeyh;OnPO0QH$8x6$U(<9eh zkUu?AcR`WA{4*btmAgBnR@UhzmhEVDx_ixc=55C!?MsA;MPR>*iJ{vsAR0bL8hM3S z&8s6Vu&o|nCWm?(hx*Z64$M}>Im-U}(5D(F?%rf0k`LvQ8U|2o&USvMO`)iO*8 zXJ8_(N1}p|W5t43B9ANN%oQK5uS5oF?S+Wi3tHo+>UhpMH+4Llq@P5|3FpX@&ttC) za8!(#bvQ4o?{_#KQaBc>IP!xcPA0c#(@NTtrN~&w8FM9q=G(Fy*5SNC4Yb}7E0ZsM zkbz2HDj7nz-`=l3@e*VORev$dmCUN`#d{_`GTQ z-jJ_-Y&jE1m)W)v`$Ty47Vok$XLHk^nGZBjFh|U1_nF_F2Tgr9!%zW}Q1Z^8UF-X< z*i5J{)rN%^*=Z4VIkMr1;Gg#&b{ikfrHx6np|D>(Vtp`N`@+qt2VviEEb^)^q|y;o z3V>HYn37%CT%o81F+94Y2wk|!P>L)JBWE$5!P>|m-xd;G1Dk5X9-3F(s7R_sdUXZJ zYVoB2#C+==NHW}jyz;rNd+7?m zFoa4LH5<(cZ&p)FW-O=38_1;QCVL}%O-N1ZBznw1cKy5hSKw(~KG14OAbw2i zHYwP&QuX(jGgJMg&)>fV&zAe8fzY#ZfE}2!C?h6l!eD-)q%PU7g6akI8G4uS3xdx3 z&G6uF79R3Egr1e=9BMtuaS3$4rk~_&L%brc57M6hv-K3YcLZXpe}gHO*!HJUM*PYM zLYc>4ICJtviW;jswwY`C0xL(|9YvWLeiV{b#m#FjN!s*S_FlFjl3T)1h~{$-7q1LhWd(`**n0?aenc1Yx!O2>Dz)-d&N|$*F^%? z`M_1#&mkx5^s1=-4f|vh)n3y)`zy<67!0nGl4J$qZgn{vJ>cCgxmih?rbqLp|9Ci~ zfTWMk{>rSHw^5=8H2qYq4d6iHh^!KU*kF747a?>ty2~aMgp3XCvB8q8jBblV>)M(F zUp0FVSaC7p4WVrlLhC{vqubMN7NAVTz;EfXo={g$O|$o_=D>kw@7JDI_NPPfkDgG^ z1YU;PKRPnBzLz;r>Ogbg>t=7l3Yrl+Ll!KWS3$z-WNxpINra8r=*vt1CF}mx=hB*a z_Y%uG4zZ?nKPB_y&gabcSeVpIl!O3wa?2%3rhdmhd0F`z`ubx5yKH}~8K& zSf|fQ9u2jEN)wl|(-ZmkWss-0l={lwsXLb_+&EyZ<-z&yF&Z3!9zTsChL?-SogS(7 zB#@RW%)dvR@03@Q@&LkBl;|mua}p(wQZG5DG~(hIaf%kvSOzK(8&)g-{IX>3IBP#e zpa3yjY--~`^lD9Erc5w)U{6%~95Q*b8!mEb<+GKvTBO&wFcJTNr`Yu*g6AES1P|7|sx&Dh;f71~hB9KuXVNm?=1+@NY_WhVHkI>z0ri6kU zRV;kD7;`86X*B>Y6tplwPPGdDLS)wU<}YGzU`um?gybJZSCYAItuIpSZE?Gk#mtjE zn6qtBKc6CMrDLc5$N0u%J~rBCrC({8ST;U~1d{pfa*!`Bn++yui;9|3O`k z;Go~8hs~jWZ4v{?+h1Scn7$x4gm~GL=#kuWZk2m3Z+fA$hO~x43w|NF=VX*Ixpr}0 zU{eStE@fSR!+G_z%DiL8F$59QXEbxE65?3RY`9NKs?l8ErnI>dGqp#tDA*15awz?enJX}Zs-ok{UltN5I!WM~qe0~yg=*-n00*pjPR5vI70 zQpqW{oA13LplWzQ#&%`KmBs!+SmX><=HPvwHOCf`EL!`6IaV@9JBJ|#mU(v(t|hrD z3)AJSRf(;$Rz;;TRQnSdmB4~@wYo8k3CJa<2S{}J&82dFpQe(f44{Q5@E6uL% zL%BKqCoqqj^yQ2u~~dKAwK$J10_d z^HM=TcDV(zE7e|B=aX)o8?0^@Wq>OqUJ`SGUJ~C>$O;>B(UOnz3mCba+Qdu;K$M&#Vk*lPv8i)o0x8tj!FN|VLlS)| zIMT{R9FY?$n71*rBf)-(B9lAAXkX=QTvzvMJjSk6`D&ak`7JY@F*PFJ{&dyKBTmZ&d%CH#)P&6WTi% zGwk(VZBkcw4e1a3WoKCft6E=M)^3(kj$)M3o@k>S#V9h?I#Ln=r%jShyX9E08TXnw z4{cOQr@tqg+RZ&I%TiOe7`Fs}^hagFiHS8Ieg-on&mqL1zy;blns+yMiqEiOp8Lpv z7{H#I&r)Bf+eI~p`9WA9o`lz0iL9+lH;akS&#}w9pjqfkh0qHp<|vA7dDC!*m5Fup zq6`Wtg)f}Jvr!ji;DpzLL}9kt$h&A)3U^pI;q@1-C9i~d$V8;4qzhU|=3m4YvwouR z#kq{%x`YH@{POSi{$g*@-oW@`?Gp#Z7xVt(oAAYHQX*RTT|PXmNqn)v?)G287tiD# z5?@?{Qh*$rXJ5-I%67>{82M?0aWQ8Kgt6z~2xC@ePX|R97QTq&M`q?Ke37ybS*1qs zXjw=;JG~Md13rz+uu;!$Jb$&YSV`(p?<%=~C0vYb)mNUBQz(2(-bSu@o7qw55z>g^ zEt?iuXqFLSty38%#+L(w=vD#EdBT?@QMkTLSS#AC>-R6qJYqQ9_i#B1AiXeu2 zAVFP7v_w}Fh}`Cav(@0oG<)(pJVP1L*~7N&WDY_+MoT8Xm&dvXx-6_`-u$dg z&w6z_ucR)odn`0y&Xm_YGT(e|qvU+cv_Z%Hu$m^paU}l9A zlwT#~6H;Egvzx!h9;=S_lLz=E^-Qat*7O(;C`#SfulWiOZ|R4^dn$s(B;5tg!qcNt zY8pbLGMb;ZMK5d!?>iB1k^D7UQ!l!QPHzu&$8Fh-vYh(E7IK**(qPZBIk;I$|!)hOtML+AI8bLY2Bs@!v(w-s0z_6zuo* z38D3{--KO&{l-cd7~TC7UcqGx3*OT_dt0-2`_ppSseHiN6YXrm4dk0^$t_Z5vDTC4 zttZ`P4Do)#;_8ik?H?61Fc5h91)=q{Rn#0PZuTDeylPI^MYr|@x`)CBRXacSBz5ga zH(8Hp@DDspG5)b5L+g53K*qMMdG_{Z@4HVc{-Hv8Rg-D|>_~U$)n0*c^X%g0z>&?~ zqn=k~?xBn=_TOUuV^YfDY@gZ55Al@?F-_pF>?8Zyk7OR5>qllDow3JTOmiw_w}?0U z*^BmXFMZaI&1&ym_#MHH$@Wr|z4ZmcGxp#YJ5wHV@|!K-NEWm2N0_l3i*m48vfnJu zWXZBG!OPN=dh!yqcp!*>$mYCKRxEk54r-7qM=@sNdu`vpQfdicPL}#dNJ++xNE_4*bMAa*3!ZW|M~h}mex8{?|sw< z#MiAJ7{pJe3noF#dhXPofpRHqA&tF1lFJQKs0~JdyCAoLD4^;XT?Fu_!p*MnCAOt@ zuJxra{>zk~>T)6x#HCK+&>zV_GfrY99F`mA*h9}tG45DV8lK<`dQ`}|8PV}~a3miA z8geAr&&W7D+LMD9GVO9IjRx9DetCAQoXZY8QNIqp6`v>#oG+v^{w1`bl-Q{@rbTj5 zB~YI>Dl*zAR&BhHk2h=ZEp@!zHrtJaMA%Qr*pd%hGNvHgSWjsJ)S9L7k<0RnCc%z* zD(Z5#M6V8>rrj9tQ1tLeMfoC6Ocx|tB_!6DhZk%-pmE? ziLd-+?an#UlJTP6{)x-yd?kFKP`mq|!0Rc;w;>lFh%LF|DMzXLriCYSv!^$h1NJ$VD^-h;S1J)0=<(Fw(Bb9 z46&4WCNiCq!utjZ%duW-l9DP+L-@eASIiYqHLjz6_`pe8lh8pTB^o{Vq?k0_^hw>a z@PVOPaEsvE1wn(CxeWZoVApFm-t8QUSTv2oLW~OJ}@`vwrb6d zDI@=ANr4oy8C=g!(*YCuzFU#C9&Gn_fuonrM}n2u8{V)BP!YZ3%(~wu`VvF)SjG}FDSD@Cmki9 zqg$p9YneD)WenyHT5zi@(?>qTG<#>Nh&0#pMD0=)fxz6t(=^gY2IeXBHS7riwOfyr z%NcQw+z%67ay|6$y1-XXFwl1CPQ8(vW4$m`a(VPQ->#Y#AO9~rv8Ls+liV%WpWJd; zSxw6=rx4O+7hUb=|N98p;{3+L@rm|;@Ti^i?Ke&@lSrufaui|L>dHz3H}qC|{^s=j zH3vsYX6CyV(aK+PJWuAhAJ6$~j%QWQMD2;X(<*!m#y#eDzLNOBYrGpDS!28(KgMfp zk00qZK8zQNLt=gnF9vyy9zqXP2C6;{c6vhla~Q@;xLS63Li^kt@s}l;glm>RyG&B8Xrr*r; zo3B5)ndvv*atfgJ~P^ly+qIp zs0{@8H7)Kk=?~TW8gKp@kN6^e%M!iHy)_Ov>jmz~?B3Q!LvmL=B zJPmu`A012cyyQC=CKYR_8Gj+P>{LfkemiTLJwxMv6U~tXX5>b7p`2V}3Q-w!;w8MsTy>O?0^s)BY=Mj2Rp)f>RwoC*x&3a$d`n zq!L-Q$K!D!5^6wOy>|jf!AfAF>FshXJXq2oZ<81=;xa;rI>;eRh`NsAg8mInWBLNA zI*X$?NgYM7B#{8{2gi^#wvz(Hn&@m=$rt&Tl*)+}YIAfYPpqRN!BwI6&akCoPeGlj zu*>&J5ymFQywfTW&MC81%PQU2Cr>9ZkVMHk;G&>}N!l-|k|_DfP@dp?(GtLrY)@`* zMRQ<)U&CzUDzuod5Djb{76UgKjyQN2}Z|w=UW>#pSF61#C9o zS|UOHc3D5Zd%IkK!3UMbo&>8X?U9tQVqy6l00WGp0l4@s z{F$HlY*EY$AN#DpTLobuzdCYQPiO*gowrD9jH-p$?{0ba_k2UxCLT5xM<1>q&2h#F zrXo?|7O=~9r|m?^FhcEc+GPp1O7!@X(r+sg z#&%H|6gfwEs)hF!YCk4nodw;-path*t#PIG?PwaO;!cltv-+bCUZ~X-t}byp_{>|Q zKHq9zsJ+>CzLKRjeIi4N1{TZSTyO$oy^rp!rTdEUe8bW;y`-v_d@_27YQ@t!Mdtem zPY0CTiqoYfxouiW!RGsZFMpfzOjkNP0GQTbk1mM0fMWS?d}3&MXW&t zu>RO%J}y0TavC+>TXL(UFM{|ETnksFoSWxh5+--L$VSvDAD@?r0|v84EgZm6*BTdL z@|P$%HeIAQHiJic>#S>Us=M|kSpiVmf@@{@uf8FP(wcs**bM7f&E-hPE})V+m5}J} zqJ`Q`U9yQiN2-Ha=u@9>@$AiZ`(O%^N$#5;%J%yT?FWnCINNg_J41Uy&k28i?LygN zOn0j91CG z#PjM!k^AQ2<)Q~C;}?~E6{YOckH_0amIgcVK`9`DD%*3!^iPcje>7Lj&DaGmy!I4IUY$QLh=;B?&|ChDY01Sv6quT3^>&40jVAwq@!)5GUEg3}1f%IOBbpkIf0oT4YXMAt5CS~7_| zMkcvp_UU(s-RH#)n5YZ+Z{=F=y$@+WCA9(Rn(ZkYkScR*T|=ACQnW z2!FCHo?ptcc-F!U*MY^bV#V|@0Wq3L!-7C*kTt|fGDOZ$uLOQxo*G~H_95NF2-4+5 zO*vzexNV>D0M@*b89n--8KxLR0}S)|Q^Z+xDXf;aHx^-RqSoDE=A3L3u+Tj$3Qf%Z zinWm%QK?}Bfk%BepPQhb+T>c%BemGc*5(H#LUgZf;=1E_X5KUcX^OCN3VH>%622f8 zey)x95Z&Y#?-|%)mP<(4x-NqH9LOU3sFX#vMM`Z4*9~NoO*F+!n{11ic$~titG2&M zwspIT)|J(pEOT(Cm99I?i@vR#jqb7VfwhR7+wafk(6*W99F@+vI&W=%eQIWTfs|#@ zt7e&GgzQhXKN<$kEhW~~IY=pN8(P>Ot?>ZMpj_5A%3V?+5!7IMu>Fsg+<&4X0ajTW zlQ>y;OD-Cfd?ch<98>v{@J(X1K@_{zki4tO?`lXyK~TA!vv4Ht?}}G>w_Z zoZpZC&x#WjuJ5*Z_)UqDX+SWICrhAnlX!ccC@50)JS%B9&6#>j*(lI5XL(vC%X&0! z;I$Zci2T&zR?*~mTJ(yxZG%?lVbs6zBcQOy{0&$lbcYR;J?6YwvMKL4)q#Xtf>}ed zAhC6}>4UtWl06tpBd84y4lPSKmVGA;nHfNDN(S_FV+b&jAqwBd*-0*;C1B!S5w>>a zC$hP1ZckXfa6N|j#2^fEXHR10X*d+_XL~#fYzvN2usxfP)#bErK3y%a?Te55+Y8XL zU}9R1(N?6mq+E3rQD|^Mv0HPW3jf3tksm!Rq47fcK{a%eR-8 zz0dMmvc}{BUy(izV!D+nl#`$`xb28$=gk`9W%K<}>>F_vCK$qI*fny!WRx%mU&!W6 zzKi|Py4GNmFG@)qk$Dn8#*7kQCw^bXgi`tK!XM9(Wss!1Nw1vHn*Hc0z8@Rzz&ulr zjPLSC&;AX+0t?3fSdWgJV3{bb9%^am&-ElGH;?cHqPo*hVujcI9F_$4 z3ZlcPcyJ)I=fY;UFQE@P%5&6_!0&3UBJRYBs>#&{KUk}13ADxEwX=9 z+}M6VYdA-M#_a(yUIp}+@Q8K-RppLZR};y7sV3roDc4)oeCJo)80r9iLg&; zAEd8HoSo}kx1LbPPhef25mVyRN{}|tS9*qn%<_vg`S2B z7A&kAA)mDi>I&rZ#syl_)4XE|HepED%iP7Tt%F-HRKLj?Jh#QW86$7KbFlDINMU-J zJp$nsiISY;%sGx}VB)6K{w3{2fI62m0qa?}&cTccFwu}Py(r!)y$Q7>T`kYIx~jV` zS*OshBlKl_eaB?%Rjlq+*D{7+L%PGYwhAsf4+2nyw0wwrJyh)s9+@?Em7u`xLTfBg zC_)X5UQ$Dgoxt;f=y`jSC)Xbc;1=y*wbj~-hZJ(nFZwRNTCbD=(y}C)xADuH2;Mjy zziQK(!@vh*$12uc-n>TGz*B*KrTCb(G3z9t$LCsDs1bd&)5QlML-CZW zadI$V@9~89PFPy#*B)43JA|T3-i-%%{5&@8$JHK9a5*i!jB!DBy1dP~6L6l4Zx$8M zKX|nS?RtH0hc_WK%IrI!wj@q8L5+i^x%3=d?dMXHUFqa%XzZ#x%hJ?`CM*b^>ggDA zy-ZDOe2oElI;J>l`I)2L^`Z4MXMr+Kq?4s*BI#{Y3r;S+J?8tjk*>Si5xm52oJ0Ns z_8B=8MXf62fncrlm*d7|Re9EQ2#D7RQ6UVKi$~kA){}RQ5YdFG;E?6En(~QbtaJQe&tx=SUgUTPXk+s9sY5KAQIuBcLz6lG=nq!!Ne*{qeiJ z31^UfT#4vEV;?(r^hNoH(Oz0f^byt581ZkPizGK;-R{Z7$Utdn$$+H;OkW%ZDJ(u4 zWLdwE1g?|ZGptY5{rL`a=P~eSzievrYhJSP?!ubK^UU4ADWJ{xK(c4l)EFkQYy8pk z?|UGhh&2V3(<3#NEZ&QH`2h?rarNC|{*T>=PV{z6G6LH4_oePhR^5YCx^3V}#eTz- z$chK4HK}i{86O9t*D{`-LsUAVUnMm@jBO6p)uy8@(4=Oiy2?3pR}b{7q`D#r+M&Ao zLBCouD=HmoR+arKy)V(qrbP#w`%+H3TxoS>JNy|@Z0wQKxD-YvL(Y>qUL zO9R(S{gWv2x)f1%lj7TeE_X~@vz&lRg^ox(L(Xp~TdwSqdy9m0pIhegv=#{lLSyCQ zQ|>RVrKape?gCHqWalbpoM@PSENKWO&ZUY^5NJ=B95I%s5Ck#)we)L#^j%1o)W7uk z5^B$talFXP@abSrD>uEvI$rP4LJ7k$?;VjkUL>v{kEr(BHpn-(KZ-+Q_=TJrqsKa3 zqfQu_K3$SlFMYaZrrVHZ<8*xyh%R(mRa3_#yUxh|b!t=^7b!ngPO!w_D*q~Dcf^iL z4YfxCNq-AHpiO32yFyW7b{LJd9+fJ(<^r~l|ANx^>p&^BKT?okQ8Z1MK>Rjr@Brq& zDQU_D;7eH*wIa=;iccl=>s|OyKxR%kBeg{7^|A0D zarK&Bvov^q<0Xp$g0m)73dvG2J_#5Hd>cNQ79Dpw(bWWd=#hdUBu^V+VYj!zZj#`| z>^?FJ5BRhhUj&GyWqhF$`96gKiPSt7r@?c9YNxM!D^P_5g#6oN{>-k-ncE|#l1EFl zKOyq6&lpoZ7p9@^+@g3-a>MnVk7dT8OdVg5r0&L70pm+%5O97bktD1M3}ym@`=Dnn zdjg>LuL9+t3U#n_wM0T=Ph7yBxPZ}j_{zV|*b}c8r}hL{hNRZ2aM?as;pB`D5e@f>v)$8usorn-wuSgi8|{Q_H3Kw=8VFBtP!A^c^55 zTiQ(KJmFjkAj8~f{;V<9l}SG1VkX@1vQ?^=Sx!Dnaibtb0wQCpxj|J>d(E)EeJ{8io!hW=jzX zRkWf@T(I^lwQ>n(L0Ah|{Aj>s=5zIOB}&yos**FFs*h5Y9o@^0<`WODeihy3t1!8= z&?_}J5)a<08T!VW-R6DNR5mBab$A!z*~loqH&Y_us~>K2Hb2OndA#<-S|zSdzF-uL zcPe~-S=OUdF5yve)}z0Wq1b-Fsh#aM+etUUjL13pugZ z-10QrDj9&P9!;4KZptRmG5a{`1Ac|;UFy)*k4FBJ_4 zR_JPB3%_xN1|x>EtKL9W3(kb!`oM}vs z&lw{+o1Qdr5GX&>CgZ5Z_jOEefC$37Siqg_1%A?y-@vij=Jx# zEz^37pJlZ=uTQIjVr^;OVUE|@@M`{9Ef4C`vTCj$KYhsg(?Z7lxBpx7U)XQ{S*_0N z(`v^2GcGT_4y0cgepvd2HBYf2ZT*7t@bn85GpkQJq<+EM8?GFl)Gvrg-27VI|UH2`c)L52l3*xOFk$~E(m1)AeJ>OypEP1iynJ#l7 z8MWy=j}lCq&!5^iRu$o<5E&zAd(^=a5!;~NZYMd!4E=^K@<(@4zX5#Jh#`)Z&Vm%s zm}|==jlu}aFLOIt(M9xrI#;q8AmO+zsUkiHZ^$sJWb@>+Y#s^eUcX0Ayc+x`&tTkD zyfNrTp){5MlM=ycqiUq}qsy8IDe5sB$7pBFvi%U3oH(Q#P5BN?o|Kx^D01!XTq3szX_`gClp?D$sEOEJj4 zgjFML^>T@J$F~wK{IxWIZ>TQ5p}V&}T_L}tBTf)y%Wus_W1b( zz#FYs-&R^zP0TG9CFr^bOM%R;2eU!_gV77*4%SuI7hPv@vs7XH)Wu+q)$ia$1HojrOM=8qon(%E9(kt^6&#l($o(?+>@*zde4 z3Lx~XOxzI^QzsczqU5Y}&nPp#dTZcwXW^$Dy?SDIumD@3Qh)VCb4h-DQSCzYD>@Z= z6y0?>LCg69U7m{{&U#2fC;xpyv|s2#WPagH{`lPd@l=o$y$*Zksokp8T-74#-yChU zGy+BI$1X`5om<9t7n@~tihD$Uld`lze$w!9{vc7LtnrEQd{>HYm2mUBcLH!0nnf`h z%bJRu+57V*U;{e)H%NXRv12?Hsy7{5~(qx(^-cN;_?IudteN>FA!b#eJBY3|VEU>NmHeVTw3!*1Gy&16b#vRT+OKIe;c6#PXDjtNE(CAB(XZQ=5 z)bbxh-eYZiYv(rKJMIa_=c{^2yGwbtCa^8Kk#l05JJN`bMPwp~936bEMxJzndc~Jm z{${KFk;^Ll)yK-_@#uQBr?hsw^5$Wycvd-m-1v3p>w_*XTNE(1_#>B_fvSx`B)v!a zt1s%VJy}w*gx3Jx&fwM<2Gs0!tf!jZU_7c7NtTt`4HnM0^Y0kBqovgve#43m0f zWAmqYn*5n4KPUCdGyW7$lRp#X=OF$MJaT~G|3*bOhp9h0SN5_Em2J?0mRN$oLwOdRoNxUbJX7bgAs zW3oscA$Kf#Cuus|FrZx|N)zQAhHc3{^h4fCE&MBm`0ypYbGdxuCfg8~ov+aII6=?j z{LW7a?+PKhm+O>NpW!PIin0#k+yJXo#NUficxc75teD|%Bm8OOW6lHGi7-HIcM^B`27k~V&BK}_Na!tYt_7wT+Kc$GjHK%Zr zW9GwTV(>u$`rsd4AlV0|?xSljM5cQyqbKgl6-fKpah=nm`$eZav=ssLTkb~O4}OKtZbv}#y-uGQC>%)56qpGrBo<$!*k4s7 zjm(5Ly0Fxv{bG$Lw8i0W`)mlVzsPmQuMoo9`L(xs=ZxscD?IJ*g7V+y#;BkpZ=+li z5W}zPnr}}A{ApVePC`NzJ4t~ibxDH9J-Er!wr@y4d+xOv(GeHP`Sd$C$n^BYOIp*n z6}{hHvCCVbG)U_(MDkU=OgdO@qMt%3?F?uW-)2T~D5nWHXUSwTW;7$3dyz+==6sQ_ zTv05Gvx7FYrp8=BB(OM=V0o$hXh>SBB4)R}=>ihsBPudPNKO9w$eK=oHJ9HI16a1C zu{HduQ@b`wZ{fQUqkb}JJ|1hH*kIXOu46=J)C1V);|?SkllMTg#(cSfaq&$9@@5%3T?*@3ZduSAOz1=De2AT0TYiNhk;+!{x? zfo>!<)tw6%E2(NY8;~6D<+2kiNtxnOIkX6X(oHA|KQI=?!sqOTo2Z@Zj|}%$<;yP8 z*+tV*<3~-=jg_U(Snt>L*_G@8^0~hY1IbZ^h#)qz9J1roAv;bES?+NjhzU%4)&-oe z$Wq0Br&sN(JBve#k^1(`np7mmX#TPYj4WY9X&Fo#}{e(+6Th+-0Vrqa5ZVq0|QS3u5h z?Bp6(hV*{tHp}!Cf*=wcEdllL&B5;pQ=Gl#dT_Jf*p0g9L@oSR?&#PK_2k{y7?8hO zfbFWiZJ7(;clIdwzcMvC;shu`^;z(aTLU~AM~?2lk>IY<^@5)0sA0e;4X+XnF4 ze4um98vytt0KS0GDV&WkHUj)&1^i+K{9*v#7I1a|%Zm7a2^Ci@jiiB}swu8}9J`B) zWub&J!B&|xjYCOjPmSceoU$0OKY zhpyn8V!So>DFKEa-hZOc_y@q&!k0nA#D0ellO#@p#hj{cn6iIGL5fgQD8?W0%=cF{2rm~L?vFGGi^E1)22yQ@_-Jec zjkj4uuODfFV0o}7pK{2%^yn?~^{A??j`I$7RJX2qJElhqjzzV7tgmXAkl$0mPnd`P zv^@|h^;eb3ew+hBo5Q2Ejc?QBTMPazbEy-qFJx~o4AockH|TO6{h8^qulOiauHv0x)`KlYD@*XgEMxR=B15nSNXyI;SYftlyYY zgrKv6X;uJVkt#1`Lmj&(XSy0XU5IcvIo&@KjR~RSL3*>Y} zqny%kJvUI}Zi|I7hs>6cLTj;P!CgTo-7FU%p&#z~1SctJ5O&JU=8_Z9R(JxK2J)h;GtR>TAeeGUzvi;0Wp2S^elUYr)@A$0MMhFZrO zMe2Z1dd;rSz>5*@B3`-Vmd2%h#(HVh60YIbx=yhEPUbjM@R?y z&(sAw-a#RTuR7G7o57NxLh}eZn;ISW9bC`m+x{GT%~`4_c~Qx$+L4<-jBIf7o}X^L z8V97XuqEtdA5ZukiJ*IutgqI1E;~v@l7U6Y{ui^!fk9vyc0KrV^GnHh#K7lsy;|~v z<_msLbkK*34wm`IB>irxt;?yPN3I}x9;RT>GCt=&{l?eC(~%PX=;B16>dV^i`gXq# zhc6~Ws>KJS%Sd2xN3PRl4SSg{@p5ph)WI4EDhvTPGV=0v&vO(-WIO3|G4%0;-+=D> z(r!n5N>m%f^OmX8#w&~rnNZccS|iYR#Fom@5ynm?=}{9)rJQ6R>@e>*qL1)dYx=F4 zk#`v)^F!6F>0eWT$I32K;apd;uc-G8sQ}Ulw~t zO_6OL3FM1D3FSPOhot=$L}npkn>&ybj@J704+lHUGY6x?o@HsvBC~b#&q*CrZLu?FDEL=!5&bmFc_A2Jry;`z-nh%$Z>ofI;}F$+p=J7zp&P9cc2I@rKe; zc-yBa*PAM0!G)(=$PbjDu!=)zFyvmx!JI3?$BOm z@DUw4AARW`Nk5tx7W^&ZC$Mg!t8OR{zAn_Y8u+iyuQA}|>mD77P2nqlba@2^#I=!ouk~e)Evm}YPnYsKiDiW_H%ATaixN`$=`Y4uC;08y zu1s>Mue_^SaB7+!61Q-nha_@?WUP%`$kFzc)9517hWuDd1f`ZpG&%k!Rr3>@kkPl@=3ag$u7#%Udg;8B+$K=ruLc-ov314 zHWsPrJu5wOv0xs>wt9RMKN2Nxv`II~S+0DZ>!p(WTph?(7y7qq8n%OsWy{o{Q)?};eru$`DVGG1+6ItM0n$@`w zQAAgIQtn_wm9?jQc%Zz~?(?-#YPwCuY9Rw%5`L!1VED{QtyVN|lr<+CoVT2DSaUkb zZhwj0{$pxRfK%O+fbt>6p9W>^v;2}n1M^{RsSsm`VUWizsV^GymL6?t6`&fViE!r& z9@33D@JZe_Kl(FE$M@oM@*Jz;x2JP>qvs#3hWf{q>fz!Fe-&D-nqJLHXBZWq>Y3aD zZphL$7fK1g(R2?*p}*MhL{BkhkLI&NE?Yj`jKF&Bg)ga}X#*X0P5=XlSa7+Sn|kDH zXOqc?U{=2N@*)333=+Lhpla@4%{i>TU#291jg;KfybFmIhpCN+koZ?S8A=Xx-N)B|r+o#r$ND0D%o3aTnR+ft5#=*(6;v4fSD9 zHkwy)nV20D-D4`bs->Wkz|8YI_XsM2;LYjQ2un>y~~ z(ZrcWP@%vnQSunFqV&2i$1OEE{STkok%$>Wk6IO;wJLu6x?gzjBW*lkwEkzi4&p_mCKYPrB(6i63WM^5| z?SpEM1+v;d=6~5f$I7f8Ine$|Nqi6^Zf$|RR&iiN`afnmceuAaSv^s+M0fPt4wY|y4EAAtr95(MoQMbK}y||{v8z%h0?!URIOup5DTZD zzNiO!;05w%p8eC6CJNNAIcTkB~>j z_9H_*8pR_pH`sa+fxIQkco_jL(z|O?O=@?UR8V2@$zhTtCw#`t{&a+8Y3eJnvQ;cv zYj?Or0de8#IFE3NS;zFXY!lW*99?OS*xf^R`-2=5GUE2s(i zfyzjxOInwLwa|&)y;+s_ZW25R z-y~?(o$OY~A#sg04hSJhU=1bz-UOyKz5|b+k7$5i*On?ADg10_@R9g2o@er@hwL`K zPUxyjmE0|kQ6~eE2}EXh>&8(Ej~kP$HVoK+h_}m!A_6?yijq=N@h;24vQJB^44Nil z`-Had^mg%t@RYCBtx1%;^cS^Hl&BGo_uj`?#YZS3a}aPw^BQ13WqNyJ(K{a^2#dJv+!W_-uD-W>Ip&?@tPzQ4_7KGXmNg` zgXxb&#RFu3cnVqaLkXQE_m3A%Q$0>A2&uNym?C8mQZdm-R`FBRDaZYJ2VO_%hzKcZ zq9O{i_9wZ2WJ4W99&#J<5V_N_9t*c)5H1pr+eP9rw~TML#KVUKSKZI_y;2DVE@yqv z?`lg&$#viOdjUJLjv>S9P86fEst6 zEQts4!uv@))(ap~B=Ws~PD?y`k359LW4AiX$qvq@gT4}vh9Ls0`@3bY*%FT*zn7MH z{FK(SBpw&~QxcDbB(wYmiN_5GazP4~#N){#OA;W2M3NovBk_2Td8KFhKmP*?5{XBa zq@#OUO48wFc8ABFzxx&AfU6p7jlmKLMAMRvU%yK)eI*@tk$pumenvV8=m3(AyY05$ z)cQ#}B<%*|9PIh9teO4eznR&wyi7|vBp^6!1m|q~m$U zpPr5JD8K&CBpo}?=g>yaKV1#=k1JUW)N}v8l5`Y5Jb(BVls zChM7!j@IM;1xd%Oy=)>|(($_jV15{qj?PCi*Zn{6Cf99N`oMz&N;-a?u7IRteny4A zO9hd191i~=@{UO1K>TVSfBu8HZwQKu&Owbbo0~q4cYZBIT0Z><%G}B4^3^qS48}9R^z2KKP^8042$3?=e2{ z?0(yG;wNL;JPijDl-GU|WlElCfMmfFw7Wl&*{+U+93j4hbRyAdn1e`o^Jh?U6*e=x zNNxkmQ6?G2%EZBnmh*0WM=&{yyd{Se4qBYHDYsI9085w--9aZvW1w;ICi}h3nr8V9{Io>!NIsCXL`NN4n79^4* zc9HcY0XekdJSm5aL~9&xmqP=fHQg=cPP3lSB(J|^zXl+|8)KUN3zA)HlyKeB4CH+9 z!q^uaCHdu&S0CCx+`Kv`wpnN=$-6}?h=|0dE6E=&A`GPe5Ew5k%G7w143OATIh?{i zFKinXYKN!hSJfy`v-Il%r+l8JrS zUwy9DD2`n^+S-YoxxJ1ahhw5~V=u08(=kJvQS_V?1Q{4##@AHEwYx=B8Q#BQ=^4+l zc%*q-aqG#dkdesu9LVLjx7hw|gE4F^KBq}@q^ zV25nz@cV7vs?UNylAeD8spPg5nDoxjyl@evG23&&rP7luC){Ds;OT$ zYv?;n(_%a*wNgsuQsudX=8%5*8+_A)=Qo8-x^_6b_!IDW=z`6G+j zbRO-;kC*N)r6Cy>w&eWsNwZQ@JP=2BIC7OpAj_)4df{lE<8(JK%89>YY&zSqN$JKu zOPue>{|qDfyMdu$_IrFgj~n)fm{skPG3zXAgE6m-X_I5;bXb1zKC&V5n?s_)q~qQD zIkAF0L`wIB){#H^Bafuwwia@Zhb%StSr7peEKwBJ_rvl$?-P2rg?Dll_W{KB&T`upql3Cxy_g4xts48+&q0q zP4kucF<}|f6WPK<3hbR&MQ1(MnI5ywSW{yV{dS|;1MQ!XWBcV^Pv`>%^h(HUyi{Yn z=_QVw@sU!Sw#SbQy~JyKyvoYMXsOoL5$L%w@(jM0W#A!Vu%>m(E`!KH?zQ07v;5b$k7|lv=xaAm zA);tSP4h7C4QGp!Av?mMng~n7T8jT4kE(VeKdGF9$zs>8%(yxbEZ@Y5V zcI2Ev7-eaG_vZL-LhCA;t#^qwg~5{XBy@sQi-=8Iy=MYMf(1ByDB1|xz+ArEHQX_E zK|zSTgo$lC#DiHTRE+C8MKxkYYQ04v@vHeOYLUI>$MNt3>;Dczy&oAi>yF74T!zDQMHmxhm?NtdpYE)Azk`}=k2Pl?+kd`GC~ z#uXEd_L!M5R*>nks8!*x+gfibX{+J5p-X_mJgV?cKAqgXm_-svt7k}cUa)QAjQaVL z&p=0%&}8UR$Y~WqQ?~lb8O_egXN*ty((Qcr+uH%g7tSQe_icEQHb&mx!rN0!ZC%<6`m>B22A7Ae)Mf z0nB8-Jww{hn%g&!#E(_=@jr@igLpsWbvJjt*sC?_G1qgGiYErqCY0m}$mk?$4$;Qg zG^_J%{x2|QL&~{`b0p1WsMmxNIQ20B1>#~z@wiwiSn@{+;NTt*Da2?C?a34Zp@)#Y zje*7W?cyhI5GG4ZvJ3)#gc0sW{SvpCXM~XRnaOsjW&B=O<;}8c(r}G7n3xp-0BgE$)ZArla^#=@iu6t>rXfN`<|(ORLfYs($LnQuS^9s!kSM zn5wfl9db_M`_+6BWw`y=k|`iPR)-Ve{gxjWS3&>lb`LIYVrql3RQlr`&?z`Jhs z6|aJ+m`n*LKxHb&2QwlNDt%JC%%%BwC5&g&iK!v|KV<$%-m@oh+QD?OA56*SLRmgn zkVUd!A?ui4Rlzqf&a$;m`EMRGI8lF{0v_pt)UXFG);8padd~A_hkC{bE>P&@n21K# z;CVFVynt60J9OwoU&I3mO9VO0)f@7IJKA#_Mv=>)}1>Nx77f6}+q7oN!Qd8to!xRt9uZLz9E z)m)epzfB5414|v$>VMaLTL(b^9%?+Q!mvz$jO9MLFbE0|_1fFM|4Li}nx=a$6+HGY zD!4RVf!~Je{8Cu|J4Ua$%5?`gjbqbT^>X@m6jptmM^YPDb)fxTs{L|7zXR|oYd;X5rul_p zmDFe(n0zJF+{<2E1l{56**_?-iCT0=vK`y|QSOo*-bfYRp*>Z@pqJaHoFE!(7H=|w z#@Uf9kVp1eeV>2=yd^kV?Wc>%+;9nz+wz`PU-4AP#K;>1xF>7==gNE_ymDFdAC`nZ zu1@jIB?FVkV23b)h&h#&?&rV-~T}vhp{(ICcAB^U_xTM{sSU{K7@V%=e#@ zq4mj&#Qb8e75-Hug2fQZsY#F%Ndlk~=Nv(vbhw|Ovx)fIC1n!>EJp>Q)G7+KkUF@+ zvqv;!*@ZZ&Uac5XC@@9zVC+7tn^k@`>-Dmnl`GxhB^=W$ian+8RnH~Q?g;n6orsKP zHQaPjQiq3?3XmJFK!|mh74lBbnQXzONIb|bm+!16M`ZFPFG6ChMJ^Br0p!on-hoY) zT=A$L$G0<{qq{U5vOaz$we}aLi9C(Sl1h?VF7#-421A@tSbe=jL&UkYykQ(>a8XkJ z6#K%OU>i?UH0|=ljPCGeP9^{vsk^N(D+D@HBotNYWd*4Jzt2 zud$3Jxf{^m*6R~_m+(g6IjqVeD1%|=dm?ivItMr554F$}%=)Z`ap&uVn<(RSL%Yf< z+=e#b&f?x0#;Y3A>pBi8AwI1$tm`CN!1RAl+Jo>_`@@sm6jL6E- z>PrRPj<$I^ySy+uCr((nm zZNuo|(BbjWO^4455Fhl$p*vG(QhkH?bi=y z{kR-=5>M5;@(G=AvD(TlYAZjVxNp+V_&u`iSqIMYUS#q;Vi&;Q$FEhJ*NQ(m*K2RA z0`Bdc6U2}q*4L~?{D~ZvMu}*H?z#i3hbXWYT!v?KG(f!fm)UtIE0;4*jtI^XM>>n# z$|f~sA6K5^j@%0vSP>MGuOCW=F0lvTre(KErU8=HscSHnC`J${RK$lxR13HQpgD8nDpZcEP?cngRjB%S%zi}k$=?=dyA2Y!C4DKB^rbR*3 z@?#z^;Bn%vfkj`FqGB&P@bQE4xZ;?{U(;TK*!2BXF0bJ5rf(c^yzV_tE&9e$$9wf> z_0_4zd-W-=;-WQBdYE4~a?B5C@K>tV;m7;*uzFQ=yjNAK!I8&%73ZtO;(?94Nb!Vw z;4`IT@rv(LHH|yot6A!+(bg-q1+)z@ zq-l5Wh9<2p`r@!PHI8|8YHb^U?rhIBVR-+JCyLdh&?WUu0c>LPW8+C`hTlQ`K{_)RSwyHRUa$4S73;w~3it{GNx2 zsa$+6^`zbk5vy-R8)S>OTjiyt zo8mlIPrj?F9VP|N;Q4Lo0&mL2`8?U93MlANv`xHVBa+%k_M@t10m8&yZkMZKr^xNL z6vFJK#|m8r867&@;d_ggJB_Hm@l{HAw7*2rM4V-hBGzykJ4>2^FHa<~R#6LOU(9ua)FgSIvO~-(t%rwX+YILI6y92tvAKd*s)zCA>i9g`|K&*r+fOiC z2z|q0OWO9AgR66GD*MSawee&+g)qi0i9lMkyTduB$rr&VMo!Rr8`$-j9>G zrpXz;z$KR4gQ<=9b?#-+>%SOzGYiUMAJj`)^sS%kL>Y~Jp5rvujMi(8+(E&rMTkIY zOays$faX@r)7|0-1Hc1LSe-q|iP&e?&VhKWzv^ir#u+~2X5jRiC-Do=|1K}ZJ3x%C z_#FWNujMPTz2deQPjLhb*vafLZw_`4c^@&Ji-1zI`JZ6uhA-dzoEk8j_8{K#8FE6r z_Gh6MVW%S5H>#=#v(&GFmYIco!3HlljjqcoN%xn%FY`}$m(ZFVY!K$b0wfE5jr=q% z70XW++)=|oE)w3vDm02R$%1tQ3%R9`jTgtr)BCuhqx`9Il&Stj1M9I-j|e=JjAo#D z{wpH;Fj_?obPpldJ$88iR$Y4`2OakiPf0X%Xrg~l;s)4&d_upukB~4kx@IhwbHCAp zJ<&BqTweLLClvi!54}H_pkRaa(4I?Njva{;d3Zz*?LH%M5?9~wSkq&Bc)gp~TlLuP zLD(}8#?R^4lK8Jl9qABSN)u8He;gwC;CT0qYuOdE^Ubkey`9uH%+7T$+ami#+psVX zX=xdOCMt${>?rWM6X&RcUw`>F*ek|!%0`b{*4`>PhnWru+~sVTkt?X!f6;n7vGDx2 zI>UBncnEoTRa7*71B;wtJ>sq={&ZF%M$E_}7_;XT1t4Qw4f7op z`OZAg#@7#C@&0dq{vyq`dk7JIkVAk26ibCz&tM4zzO2y%MS2Kjv<#0-j+IETe1=At zpo}Jk3dER!ff3;9iK6{gU)3cWvRfAmTlg4(t``{jECb@{2 zgWa2&Jma>V^-^Jmdc4&W`#7IqpC=H6J$S)xdv(^Nj>ILt$W>s$_uR41GARF5@!|&? zzXH6WbM^=w5c@pC6H8>dH+_HlkZn&apFYHD#7zP?0yiG)@GNWWJHp=(ONFfo-A>}a zL=H9!*74dnBa(HZZtu{Ojry{!C5sVP$J#QqXFF-5>$JBf z24R^K>dc(fQHeV3;YMkguy8_}f&$EL;3C3era7^hbH7 zUOpg&PgKuP-Px+o;Dh?q2idl`p#SMIE7ha*P~$C$6Q*xS-z<|k7-Wkdq~FtpA5ujw zrN~?9o6DrgU|al6De_hN>3J0SGJP{nisaao{nd0))u>u>DI&49=}xFIPl`Bf@gGVp zlDt8U@-u2k44p3Sqv~FcNGUi39iJ4On|>j>3JT7V`%@X6Fk4a(7ORYcJP~ziVlWr@ zsHs=Eu!6iw?NsYW^gZPkDkLN1K2z9W5Py~&(Xl=GvE33!a8fjMaRw1CV$dHRN4wV{ z=)7EsaxMAQbwXle2er7U%-td+9%t`6$pY z3}UCi+Nd1rO`wcm?A$YF-@q=6xi|e|#@!#j_3&n_yop~XmQ1IB7K8uwQyX?8n1B83 z(MLx@{1u8h*<2zM=4R-YO&QlYP}I^1%(FR@ZJ}uy0S6Ml^7@LbL|7zUdMX0Dw+KTi zXVG{pdX)tRzcO@NT{3VH#ipRK6}gx(h`-~EiY$I6BFm<($@LYv+Oy803oDI^Jnk>5 zuh8P(5p;*34^)GlT(>Eqdg7-ESf(;Pp%TE14jYcwTn&1zN)9Svblyc6sLRoFipVAD zW$(mH5l&-CQ|7%z6RQU?W#=S55P@BBO;XN-s!@oDmqkPGojMcL_#L+8@}0|~@}{Jv zxANuKR8YAs@PrIyy6n~Jzsc#O8_`WdYNxoj^PJ1tDpR z?Ssby*N%1F)>!5&i8{lX&hQmkF5?ZsicVvYvwmR~hJ_>e9bD-&mSkh6Qok@4Ys9?z zilL+{QvUHNs7ud>8y@)Jb{zw{>Fem%+TqQ5*02_P3M$;z;Db}KT;Roti4R4}8M!o{ zDRdgm=T&84cy9(jd7EwDN2PFWktq;K7MXJ6+k&u&Hg9iqk*Y@^X3B9O#$SZ}_datj zn*%^6@jKI1KQpT(Q@Rtson>SKCmX~=6lj3J&1uPGfo;Y;S#i;r_uEnIryl!?>$MGb z%o_aHVa(va%^M-&SF#PSTONDyb;Kq&can=E`?ba0mD>F2nQLvf{n}O2@8O_JoT-ZZ{iq_HYpfzyQdAZAUkdDZ zYvZDo+WFa2dFp&IRy{c}}mi^kbt(aJ5k5nyQ6C?KR zxG0POoCXPvwPJd&6*CT}co->r;(hV&?FTYma zod3GKRl|}J+IOk5g%uS7hbwQ^Xq-6jZ#My|9#7DHV^@Md@;m!lRVjf@_g zHr0O`v31c6V3t8tT3vgj(P!U*-ZQYL+3rYeMqe;wMRv3Oti)f%6b0QcXCf3lU&Q?dW+Gjj80$xtA84@$uE9|Ld6CxX8*}+PiL8;H$d#Fl?rZIV z7*BXFdk7O*HqT||(?8ptEUy=p0(ymsg7VxQA4BE!%(p3-=82s(-O{s7sP`S`= zA49mYO%=5a`DAa5?a3tSInoaMYs;Die>v^#PGh72^8o3=ve@D`(Kagbb?2U7d(M(P z03zGXoB!IYCAZEmTyi=ZGP2sA9*xRpwa;jRV1Ge&IP+i+O!JZHr=-hc-!Hc-#^}MR zg#m14H(YKHwH1bXZVG7bmPVRN>dy{xlb zez5cDG0TT*8xGsMtMUj+B87%qJ2s{{A*lTq#WCaS4g3th~I%ETN(jXb8-s4@Z=4?CF~S3n;r)Q21rHY@dED?t=*T#@C3}0|Bo)6~ z7#i7VM8RO1h(Ar?5U^_V=Qd}al}M-$ z6M{VO_%WtwC(X>FoGso!xfE9Han6=>e>9Fsnw=*?|xc+FOK$=Lh-=BDSRi)3095uM;$OY3d@cCUsFzn7TOa z0dOf?;v{k|fIKkk`gGE#Ga9lo%jO5hqL|eWylB_|irBYO+KJ5KY{{JldcYr{YJ2>1 zKoLbJn(KMIb{hx1M4Q|Y)h*pM8D*+2nAI?Pm=0X(0+?g3 z4)r*-T9ZWx_4u^91-yFhbnfE2)uTmP?HgP?Ck$4o=PIqXP2Nqgsx0F=F_^jq*%++{ z_h>=nqc-Cur~OmyJ_+r?YH-&2SGtV%v_%K@Yv=Bhp?#@NnLj@w2c~s=@nGA2?V7D} zbbYML*B9|MXHJ)t?^5Nf29|H3d`umdPGeuD5T!3!z@&xjfN%T&ox^X)X}l9=LabNu zkC5nDGm$M`^|ph%wcx8#(B7imC+r}-)oOpPKK;aLyn9Ti4?TRGPIF?zhf>3Re3+y_3-q>&r(-sBpym#6(;T%gix9ioBrT-_nF9qKEgoKvq`GwU(i?5<}GbkDP?jx{6kf^ zluffyx!nISt~zyFphUNzsYJj9YtV{m7-BMCr`M3^-%6L@#rKtTe8i^r8C%T>)QNec z-Onc&zrr7he*y%T*fT2ovG4-oz-KR#CeES>iC^EB`u283W~y-cuX{qPk)@u+4{ise zec?&Tg59?Z+QK@JXfzOZ$%6IR7T|tM0GkmKk9@zm?!j#mnOp=TF*jKYpo4gRExlNY z=u4v~g^DUm8wau!ocFRr2Th8~5i8aMB>J=n9B+8u2-0R{RgX>F-D}Sow#}U89QHL? z;uve?#v{qfH=>pLnNj}>U+CK3TOrJbVEHi$N29MjrA^gL&T9kg#r5#CX%`2YNm7Md zTXPm=sy<2lq0hdtUzJ*|nB}gw`w$w{F5yzO0F5+yh->P|z+3bU!M}?aJX<`(?wWd) zJ+N64eQC85)XCdJR)vS5T^0|?(5GIN!L^f=)Q`o*Fn7IO2CVEcE$BkVevy)~V*^O| z9Pp1=c6Y-1Ss5~j2^T3CD<#B;@7I5@NT%NPgZ2}nPUAIrnlkv;=YByWl@ERKkhWnE z_k-)UL_GFD7qZ%dryzy9wDm&+C$J(y+UNovku_}A({5r-z2OVrT}G>t-?c2mpR+#W z{y~UMJBV_Vp(~~Z?u=M6y2Ty50qFZP_2k=DORuVy)Aom|{m4A&(qHSg7+V9MCH}Af z4pjEF#nSh}gF;eWqSgJF5gY9Xw|~EgWQAM@yR@f<1q!;7I!hK4Z$!L5Fid^wRykN| zdMFb0pQ3)t19Po!%H-t;V0lX!>3k_ER@38U%vRUogog;~5* ziUT!2d0pd0jgvi$Sg)IksM5Ua_bh@~)TUPu&lLl%b^-h2L?Q4eic=z*m+U+gnQ~qD z6b5bNqS$J__eZsW1N`fW?ItsEUE0zZ;DxLR+p(Um75NgXo>mqo%Hnv#(@Vipi4g+b z{q!TDHoF@7HM$W)*N|y6hW2E+B08#w?u@G47>3&e0eICDdC``o7E?`3dm_VVG#0d4 zL87hv3D)|uu&D*!<~4Tf;jE&>6I4UOEYO|d>rRD(a@MpVlt%xMm6?h%6P-$Z@gKM3d4ZLLe#1T^HT&QIzm@9 zm^n9QJ>au<%lML=jD(ocTT%mYYEL-=Z#ao+Weo$e6dSnoFy2fJgEWipIKwAca$F@B z&casd0k6GV*^b;zTvRk;tt>)&Y7=hn+k~C$K8ChnxjE){EZ{@`B3{L<*C~7X-Z{XM z$cHib0S0%hCh9mg+1Pep4MM0~QovDS56lr8DrKM>x*iWKDD??l?quErHx}5!c~9|o zsW+UZ4lqwR7YT&HT-uszmh)GHdJ|=P=Q)floB7yp#X8t@{b*bA6|3)nZy~-Z6V0#w zEYPeJGS^vPC=r5%DhX%%q>a8qlC;Y$_g}{wH9_GQ)X|BkuEZVrp>>RAzkfpk7=+fl zlVX>)%HHMHo|^tDPXnZ~E8R4auVGOk9>m|$KMz|~YqraCQokc8!Ah*kZ!Rx}xXhch zg@p;{^>7R^c-z{gGrdYv3~=5LX-StilajJY7fX$s`~Co`wFN+zOj zTi=49m8+=LyyQ1BSt*yAX4ltj!0gMgPWsl*aX(=jm_HfCz%Y}(Z1lFIqV--a(M~uj zUrgweD`leRBGDxU*mmt#-Upfx`t>=L36nvXweRc376MxsO_R2$9otv-ZQW=^0zVj- zhs$2@Wz}qo2xUnUHtkpL2M+7x?K0ZbBSm<+jh*s*r*0&jVmjm7j!FR+IrwnRGkwRgT6?2O~#Inh#3fV}pi5*Ed#tz|r`d?HZ`I4t_#1iA4DrJ-QccjhPRK3^V4$ur+{(dXF5Bk8x@ z=Xg`+Or&j_t&skmDi2~N3Jp^2IbL)jN{N{#a#zS5D$R2|GHdcL=sh!rkNHV@&E6=t z9>;4Q2R0+!F;fe5=A^Il$Jz?zWwXz**C$iiJr>=NEs}MggbJ*AMds|FTAd)OfzE?X zRBZE~%{q*fN>kv)RIBOFmTu_;DAXNM`r`~Q0De$x6%w@YA{udT)C2xomfq=K=AP6g zkW#bnM&0LRvHYjvSMGk!z53?6?wqysPWPmJ?h6CU?p*42v<6C49b|+>OSYwEHxprF zq{V!tbH|#v>|1<}R~VtuO>_kMm8;c#!YIs}o|f$b^uHq|QTQBee{zsk_ljM(s2$8| zCxv~+`<~Ft_RyLyb5~rrQM>^ZOsB`@3B8i}q@9qu2l)SeBNp175!;=?6p}RA(du!$ zn8@@QYM%TJsT52FPs#ib8t|V|#|U9X+HF>UJ4lpy5Zq z`F@c{U~Ipvb5K6hybkiYx=glbs>IoVdFUf%@*@;zow6=O_C3Sn=qBAzw;tMyoxt9F zkK=7t(dTGpGR6`Eq|obV*XsT$W8(jyT3(=ze#G_+RzPKsWDypC+iZ24<=_q&$r=kN z+GLaTNLU2ARcK4S%HdUh`jx6A$SYbVp1514kF>zAd$bv(xm~ke2AmPwGs-v=+Fc&o zeTrji>?4^Es$h7X)*fUz7&4|)oicicHPj1B0r(5VpN`^~e}nkncjmhu$EzO4Hy+1Z zKF3Qw$6Fr$8lMTA={1L>kQGORqqNg#r=PY=AnzpUez`PpirdjBXJ#)DjdVMIYL)_njUqQl!-5f&^=A!sPY|kMuB|Cod zrbV_5Rx1z3WJ&ddQJGDoWI1h~7x;{Sg|Y=}JG`2!OTC6mI-fmO#H)1M`hnQ!*}LEHV+xz zdMgB5IG{4KpSilgMy6%*P;%-iVRtWG)t|oZvuD@t6H%iN1%z<0KTrZRvLce26B1(w zT3GtxD4)dCk)1@5l&YTFpFX{V?3fc8k#UsW%0qY$p1 zkNeE3q0p!1N;+L?`rk<`G)PK*hPL4(jCRU{-|Sj3PTO#q9Wx!QbR1iG(p7b~wgDd# zyhK8sgJYd1Vz(3e@Dj(Xj+YXD!}9}7=V&)xO8lM@8L`e>N6dIN@tCyCEDF188Cv$O z$U;0DhC#{Y=o@Wkv(lv<{)xWGrMPi8kiBXfnrfq~&JK0wtsJClPeiNy(`~k4I2*ET z*41lQFKOc37-mZx&=tZtgRgPSa4^6sduZ<^WxG~X@CZXKc{C#i41}Ldx`F7#99DwOw?HQ|3FzYIljQSG=3Yf$Zf9Eu|4G{ksi?i z`D}j+8U#@cP zRkEYJlKvd#vCI5>a5qWOad1H`o_LAr@)@SLG~v&QKZfj4rVlFeXipo3cZspHnF9$$ z$}U^{Jciwu5-dd@?z1AhdyE!yGp;p)W9Uc9btc<8S;${T!Z8YmCixK$J*qfa3nB*a zvo)Vg5ip4SUr~@I$&ay~A3B&M4I}ADg*}S|%Dq-f3ZF5^XD~<Aq5%|~YmPy^=e-z4(B)_|o1q-b!L_YoZOn8=+Vzo1zBE^a-bm5GSk*tE2OJ}{>-FkCVaPa)n`adX{Y z=r(aelIZ7EB_l3{)g;z)q{f z>gXEXm|==-M+qiv-Gj9I4`EF24o9pS^qdxFe&*7t6DG7|am2^+Tdr+D9palKwtmkp@HyJTYsgjanv28#br4{; zaDW#>QRP6Jxg9M^opUuE@*0t!%1D_E^0Yi8m!yHJ{6f5GkkURUo0xw=nG`qni*=Xr zgc!f_QF?x~+8qLv1-2{YYvul|62K7GWFZjp4_Hef|9po@>8uVJ4Ts>IIs!eK-xC&jh9{?>ZS8AYw z`wE$&!W5{J!d&b<25(Qs_fkr2TyjrXvo0yVN?Ii)`2*8|GfyUoza%;0v-glVBGX@# zF992AyIRJWRm310X3ediIakY{RnEA|!?Vip-elO9jYt_RhvyUvgmU%pw$j6d%GvoXQVJ^+I%f-MCzChDm*!(CAB?<mjLxGeP{GtegNUNh%ha7`h7ctk)b zP?p{Yk?gOLwf61=UCA#bm%Q<&If`D%_AvE3JCd6PVgXbT;W4dAp}q}Ny*IsqwA$xc zxNqGh_}G(yX{LVkZgH#NYSJb~M{JnMa%tQ%#ki-;S$|J?Jf!OONTj?9^t1Jznloa>26q~G4DQ& z)f5%adz?bSDHF81x400md@&J=TJr@w&&v^*=68hG&{?o~#5|fn< zNgu`9MB>sU3r?A*HccNMe{YUF_#i%p~jT zp6Jp-*K_mlPEvJ-LPMBmHUB5a=pB3d;Qenzk@!}42MZMb=UAY6ict*~s4kB`PY@Dt zQv44b#%}AtfTlKoRG?t6_RlQFQP2%N(F8I2{|h}a>ZSi=B5vBfEgAnKQD1z<=MYYE zsKp~`jv+?JnkONm;>15wwmsz7)KVz9h3ajp`$L+fc1x{`Zjj zag}d6kDi*h%4yfY)iE6d9i&I1GMBt!p065!!ltkB2+(`%H+?fEqyOfU^ynMuPP%j? z?{8xvgB}W#kmjVmha2VLJv`J-NI&dd2{lR72n4#Vgo@_>Qa2b)2qSBPzu~k$=EIEx zm*e){4r$=p|6oq1sSm8>i0|l!pVM7Sb;nZ7Td+buCH9By=nih^HwVXjE}YVU&tr++ z@u>qTg%BR4l0JKh6@_R>xo1$ule?jHP zD!37e93>AC-DW>|h|CiB6(38K(l2|%f9vLfv*9;g{177^>8|TKuQ7;7inn-?jfheF z^J-NtMka&Y;o`OPLfw~WwfiWKn8Ck52?@12;f(drT9JkPk#&V0V~ryffiy7t!@}KIqR3MCGXXhUgM7Cn8b(gxWyY@O23xU zzdM+OedgJ8O4`rnn*bT7coV+EmTXGw2pzU-5BxXP>ft42Rv)Ng>2j?$i<+%|Y}f9W z0R+oNA(Z))t7g|ahM%`yY2pV`$M2X84}dSa+2-n0l0Ip*PfJ}#2_4GiL`e%B>Yz?i zCsdG25jx0w7@zJwmhUrR`CRK@%Urjls8fsQ^D)>vmYa{mea6KzsJCUA6|GhThj=|( z9VnztX!W%)%<#NTyz-WQq}@N>>cH8IuvupMEbg_slVt6~B3h6QE=(>qo~H}tZ_)JI z&5qkS3WXeW+uuv^xm_Mb7LJo*d(GZF7 z@esiyrCj<<1fG{Oa#wgZr{Qc)!-brNOE?Wz$Z5D%PQw-Fs(I->3OV%TB=mpFNf`D4 zFO4pIZ{B%%n+h2tus=Yiq(}s(Z<(JLqGV(J8E0$2OKF z>{?FLK#}rz8eCr=E#>imK(*TSYMKOl&T;kOAcS^DPcSx8*-j*(zAWTHU;B)hkL)@9 zWI??X5JL}7qHhonF}m7V874k zG__k{1MExlUE#_ynFy~D2NLDYU2G^9N$yI|BI6F*cr-LH{1$?R05e2HxHas<)j4L% zUU3_cd6|IadzkjzIcX>tHB+&gPO@k@jgNht`loE#My9#G62bxltn7nyiLag$0byWy z|9$YSdjRxx)E;mmwVzwbPWac0`AD45KZMhJ_3U|+OnCmN$w&zw-#3PH&mUoRsVIoQW zu`V4(+ROwd3l^8d9PVVSCh7_no{zhf@`06nIy2d>TxSGDi$J~ZXKJu$YTC>{vfs)w z0%uwKMleh2{L*vG2j9m-RVhnqe*;u_jZRsmt-5qY8X@$KW5D1Mo9!{* z+9i!-3L1{@W~qAZt-qDt26qJ4tg{VF!MW+;{%~Cj{2fae|Ht%pxs~7Coh-O7jCTlCS`*Og&?72ZO<}ROsir47&m15DpSQ=_}X4}q^Sc=flK4>>kstVg;HnBpU z@X5X~ZnNP27e#=M>5W_RkXPj(cpyekVPHN{Me`dL&8=UUQh!vGhZo^~4GXb?LbDOU z&4M1P7|~LpBn-xqqVTL@qavjYsTgN0EK`c({&u>}6*-Qy6^j+s8w`d!d3#xErG+UL zZF9empgjz1JBYcs9VDXFb_h<35jae{n&s69KZX8+1+ zSTt>eo}q`js@K~qbw|7ZW%Z`g4;`_=lM&jtywb5XuqE+VE57Uel+DaU(n&x?f9WfE zamDREqglAn*NOIu)|TuOVDJk7`d@L@%#M^@04{n8O?;2}`l>pR{~6xW<`sjfFLU$Si@h8+K+D8b6woF5 zwFJ=a@|Hxc6486-p$X3jydsWuMZ2;#myKK*oe{h@(>^t@G0{u|dq;^BDSM1i6%*;4 zX|9&MHrZQF5!h14g+v|(C`Flawe|9!179Xm=0oCtf&nxdu*E_pak5+?d&yh?IEX#b zJLY9_)ht)KT*YdV>Og%snleMcHmuQ~J1JVkDX*L#O zk*S!Jg^t{d?k}e`@kS^)s`?dfVVI9h4K#*g?}iRdt=@zHJRgHS?DE`in2A4$Ma5D0 zY?a`%<$d^!sS_6gcgZ%b_D#Vxm=aBjKBr8JHd2u-Cuj>QMeYGyYF!N{VmO2Q`OZ~k zSQJ^urXD&>dbVFs)`fAT_QY;2B+@wiUhJ=7+UqGLgvcW?pB*v(j=(?SO;$k+X~ia| zgdACy;I6o9g_FCh?0W1&Okmz8#8CoIX(+{7DXwi;h7W2ClcNu?ef;1=D^AjflzP|Y z_>i8sj70oS4t|^^c|XYI_(VN?KYkStecBV9RdeX(V!sE>sMj10QmJ;|V&3UW!OtUQ zrE{N09tlC$Kb2Jc0;xF^!(QlvT$khhxLxiA)+IN>HC+<4Pplz`r%T*jQav;`734@^2``HK**L>RI-AS~?^edJBW~~eh z1A~gf)R1ahwAx8bbh6<0-%Vjg>zEiYIF5-MF0|SDh6X>J_<3L|J;TvG{vc>O^)7K= zN(8&K6EoWF&iXa5gxO=k1=7=n*FZgv!9;MEwTjuJhxZ}_i(T4h&I`yXqugb_o&G4s z9b)+bQhFn-46W(3NRaKxf=+tchvNS*`FJSaiq{{`@TlH0Z9$JchNYt?)_sZZ%+|mJ zcj#`o5f&X^eCBp7Ty7P|M{U2lfq=p#%#52B#IG=L5}~vtz?5BbjS+K-#dYrpUd`UWj~ zWt|^sQr?I^ZgkeZ;U5gq!wY>*BsbGT94KQRlnQB4P<~=U=ryjAR71s>BQon)8^)Ar zTD$pkzaZnhkC^{W=QI99E_Z_qxEsfv&uBGEDbd?skZ&=ui|v8)+!0-jh6px>xrXKK zLO8LN_qsTXreRaKVlt3x+q`Zi5_j%Cp|C ztBa%TAB%&lb(??WB(ef@aaO7s8sM)g=j-<|sQ&&4Z+Ka;ukbK<%3 zCXzS)WC;3p<|IzRVR%Ad zn5^O$S;bSWRXmv$TLo05#2YcQ`uhixfsY5SD=Q@JDbO(5d?k$mE3-juN8mzfR^TO9 z;ANt;7QL6K3OyNtQ56kjQ9(zqqol{&bmYn$=ntEHs$Xm>i{s=y5D4$c?Q31&W&d&+ zYKpQdmQ_{;rB+<_s?qA0z)3L&<5EqW740@iRmAaPp`7rP*h(KcdnF@chsubkDzDa5Mnt}G)q8FB#7lZQF`x<% zlv@J}Nv_M`dhq2=SN&*8&9~X5Xhz~^dhmTJd^s5V_{3mam$d7uUo3Cu+cKm`rV0Ue z4Bh>*oTdBaSoq;qNTiQBBi!Mc`SFW@35hWW@`9wpM-&``3DToOiHYU>QHR<|N9~_g zR+sfLkXu~Lu4ux6N-p&M^-O-xelSv{9*NR?c3In;QmGWJpql4!Oqe-{^x`9fQ( zXH{ySZ>iMoYOmC;+qz#{-uBcN+VU+=Rcbf$^ljoTiPUafC4magCsM>qt&q&xTF{t; zZ^LyLNmb>+9okO_ES>9P2uYrkPDw%>=t_*`DQUx4G!-Yqqj`wL(4ilEN7sJRNUWJh z)F;&2o}ubXLY8@~a3RQURt?vmm+j#zdD&C?hDVzt|8G&<$OOi=io!`;%vsf-xHiOsC$+wN(3Np(T< z#SxE_9(Y+6I6%R^uk@3^bcy6|DJPYQ&VD`lCgQ)kU(zX`#76!l?UL0wM~g_>Rd4tv zs+HT&ecWCe$+`(&?m}s83N-#d8j17Fbvf5Hnbr~S7DdNgNqB)&5Iw!zUME0$3pLwl z6yTJ=_HOg_A9f_m|7MrwB?g-(^z~q^_P1R1?_YA^2r2L*DUf_IK83;ce@*v|m++$Y z)5*c>?o_evB&=ZV+afm65AFnTypiEhs%<)^Cr@=n)@~*RF=>cf zhUk$y+jY1rU7PuN=o@Wier#`+<1>-ymL3jZbhZmzTYWmt{8K}RvA(*3DdeTcI4n50 zR%g`{ncUI(VC{i(n3qb!?<~YDOnP{qLK%mo z=o8jZmjEiY|0_FEya|9C*$Cc<8}j`SK>sfN0LwXx&gZY!dAh=Fpee)YJe|-po+Kzj zf}sFj!jgp!(YxRCjeIh$g1=rtgj`GJNiRn@WnxFP+ETvh{Xjyp$Oq^4`{3OEAAF;2$Env*US_4}Zx{|7z( z)xCv9ej|m)^ea5ZDl7r1LeWEhug8wHZ4a|kpDJ7^h38wdQz(V!7h;o_162{pK0hN3 z;nr?3|K~RG81Bx|>MoLPtpNKjIb^iEwpMDlv~#L-$f?r7sd60wjF!jbE-GhC;}_aG z9VR@U$(NzS=WBIeehqC@x{L4+0!`)GPnyef-V=!UNmF^w7h2t$yq|QS?!ekpLPxT+ z&`aD3xbx*EE&(mIDgG>v8%B?^;#O%7{15j8t+HNwjh#fv67GUNhkn3PXwNQo7RKJs zvG2lI$ysO|485KaN@fN!fm3VB&>NJ%BS`Q{qP+V`t(A(&@TYOw7r=??+M}CGQw0zeU&~+%#-wi>r%eWe>T?WXKUG{ZrE2H*^(_ z9y2yURzGa(Re-!p3EgN~b zc7~Knk!46Pk?iIp#e^*vChDY&~AhmTs&*yteVm?^LaqiMx{*gjLI~z2R zx~o2ym5TB-@R{2nZ8T=Q!n#V}lfLP&rUDQ{ST8L$HZvO{@YsjjPJZH#7LbN|vID0c zEszZqRDzN!H$87}5(eS~CCv5v;9NdO*c-U$STU_CFM`^(;|Xe;D>oI`63-C(Ch)u^ z4-PzIwJ_I~c&y)U>5bo0^NB!ZpJkDiT2AR*FMh zA*aBMq?4!Ro=tXE(Gj$v1Kq~M14J-7Wx!x@~iJ4Jd(+`oeed>5Z*U>G6cWbW|x!za-a5`H0G ziQ{>Ohh=kS=%c~0kCbo_38K@n(?Rrtor#CBZHaw^*WN+hIGnhjf*G-o@Y*{ZUkQjZ znC$+!Dec%n1nIF_T*6)u<|X2LlGqT)E&#ji7r!0?r0Q@|=&A_}pb|R>DnVDBzp;?H zK>P=enSrnaM~LiC>_TMD$T4T$d?*Rox5C<9Dk<)ElHw*F#I8b}${{L&u0gaW44eqk z37|&cJrvT^hkb{#p(HrOoE!--JFH!2_e;8GXpxb0aSTMXmiri*CNJad`SqC~R0*jhpf7ZNTyO}awyV3)eZ^xmLk<*)vW zBIY>WztS(BOiKTk3KE5!Tv_%Z7Ta!##mIELWlaCg|C2MV&7Y1dGyq!D@lEL&B6Xth zrQ%FY@<{SQB3%@F!VcNe%-5a~R`Tt0$lr!Tl@&v3FdMg!wMB_e)G67Uq%)X8$pqen z*XAh2j$Cd}Y_S?98WQt06#EIUg!YQ$T_L6vR;nPC_ULkyd6!a?B&6b#G=6cDghb>N zf!sdb){-W=tio)H6E)5#Z<``EC&Fd`G>b*B%};FfF459US_Sc#a!MxawD8Fx!l%)J zQTT{v1#&C}kN@$sP=mJ!HL{c2vod`8>lo0^~r*Kj?wpW(Efl%l`drqsi zp`ExB0$UsC1_mJWfRv-=TjU?O0hfbOBQ+=VCFN?iXD03r&(NFgcI1kQyAUVpB2H|! zXC!Vw+=yuAQbaRw?uZaY4tKVQW*ADNlA|Gq%SxPde6h^#6e=&|L@@t(ZJ$`CS<+kR zIYi4>__s;AI^evo`Q)dvb$b0pUHMSV#3^Z3pb}hNY!3`S&?Itlc5G$o%5wulRk9}a zOz7xJBQVq%zPU_P38ulDNwvC;TVZ6aIdm`C5U3N!)m#Z#~9KKKn<=)e-a|+BVN|?M{Yg zF==y993w)s%pyh zSlM~uiU+A=b7$gU3rS~rp`PR1o%GsQ0wZg>#K7e#@f;DNfGJKE+;f^N&$Y#s#>#WS z(X!A3v>Z;R&MBRVWSd{6@fWC5DT;f{qPU#K`%LeY4koz_f4=adDJAX3qOuS(npt9X zH}H#+Sw)GTvdwcrjpjO+LUyg``glH{i2`%xsUKI=GC}|7MzjZOWty=WgBr>HbH6Xf zSYI6G;IK+RC#6Z>3WAjtNz)C71O_56fUBAJ^t{C-)pJU5vEO{vsYJ?Sk4PV~N79I; zz&r=-g`{kC%7kI6KVVa^fzw!5NV;jRZht|tU_R5SCKqc4JbF$WeLRxu*!}gStXkjx zQu&xXDpnSdgxB|ndsDF|V zMf16IICJy5vCXbCq{H_mQ_!S3453T@Sn2Iq(%YTjYgEs$O_^1M_`ZgaKqc%~_d*8mIvALTpQ{gPQb1NE7TV@{vJSOsv$7WWQbl z%xiB~aBR9dz1XQm@*cw&mMp$P0mr)3)?V*1aukHHt=Zb*vFYyh*tEt_PZNz4K}AxW_8E6PG^N1)sA5n-LX(PE&ku8P2p0@Uk9 z^#L_HG51IT>f_}3nzTiLku7vKJ4w`ki*y$Ba=MXP^Vv+T1*DO@8<;zG{Hf~4wcgsp zUxD#e9zHhxdfD`;56AcWu*CW>gCFaosC@JZJE-4B?56C(ejk0=ty+7PAM2yAeDo|I z(ZaE&Wcy^IuG}O@1Am@pK^Ceby|_i~oiv7l5#4W|rwX4;+GCF93PCja@mt}$zwJBo zz;n_CI-cXV;iuplFhtmuZ`p&1ql6eK z|6xRGQI(yeAIIs3(%e^X#F~Grk5yD>!!>76y)BIb=cOwK1=7waY7V|{ufIm(#~fpK zlO~IV9#Z&d9nC8CV-aJcnp9hV5T;}&X12b)0clqD{Mox4%Wc+oV<>$##i z5~ZST^V+P$41YO$xzH^?TG&1B#L;qAixa z9E>0g6zT5m0nX)Fqr)gIS2F&aq1AW#bx-L(S4>4qeEQ~f7qSgTs@4?S0i^DMj29#2 zoeK^mgX=7PEobxJ6-0{-!_|S8g)|WDBS*!mTdZS3tH+4*khwJ1BL0_<*1B#dj3_}) zM7+VIg2B7Z=ci#lSNczsr_Mr?*rJ2TtFd|Qba()TZoFcaAck^a9}zzHGfb06h@S)K z<_*&iq)+A^^8#*o5k8Zo%0|deIK@NP~tf+fU~M9UpN8fFSYBtQw6d6BT96J~^u@2-;`lI_Q_;E`hQ2&pU|&U<{;@&3SJWrvG!{| zX5!=&kD50Q05YZD!`@8H5>|!3KMqd^p)%az)%oN}3XEQ#gSD_CyMH1(_!mSVUjgxb!RB?_s1trJ+cU6EWs|tiJc~NvNC8Hz_CC;eu=MJ{ zn&7>|lGg-Q5Qc!TGIfs%F=e$hmX;*^{X|Y_#SV0q5e4{vDPZpSvsh{lbt@%}RMdb_ zu5_zbtHIlNi6BxcrWzm*Qa4C+2d^>1;WmcU&j5V)nPo@~)(?rl&&gmu&es^;RR9U= zvz5#GD?Fx$a5&Xs^5EFK_C^*zzE~s%j8n5L_(pIWzk)wnU7lRJ`4gDR#3;)s^EsR< zkK4gJrS<_Gye|GdzGcq-5l^iHwFsm7)w~pDN%POe3U|Cb=>U>g&NyF57t*E+EDHs1 z=|O+lq>f-&{#3D0Ak2Kbe_W#LDI{}^=54z=#JX^_Cz5-zyYx`?Al9FZ9UlAJxW4mc z^-~EZy-O0Q^vdv5YKTN!P}%@|c6@#kLq{chNJ)nFo873yRjef|dA1dwPh6s;%>EhF98kYB!bEq@R`@==k14(+obQ}4R8MNw^- zYkRW`{X8a?Ym}{*^d>kBx4rFLa8^d4#oC2TLm#KzACT(9uGVH}env$lA%(_%hrp?s zkoqLAAeHTq;63)J_5)Q6DSz^{xF|sx+KNkLXjt=~$m%Di_}G`1^Mo!xI7*&e20^5W zyA9Y{g?14$IL7aP+vqQA zc#vIz^~r(@uwG0J5%-dB@{V^H{cHJtTFMu-qfN(eF=4G4GBK`<80yr)sG#=Eqv9uLZ65lGlm^Ru%#~ypj&O%Y5a}VzaVc zjQbM?dEYZ|f^*R8$R$NbArZ zZr5w}rw;AKb`I??G5l7PHXAvHDlOgXje(KT6#p?KJ) z453732pe>lfSm|@<@~+XYP}>Tx!a7^#P0+x_WpybBk3p-qX+MRkH0au!EN7~gjOtY z0Mu4;oCHyl3%uMW#&WS&Jx8OX5<(Z`sawgsoyg2 z;@m#RKG8RxDYvAEDHx>QLc7}%q!266)a|Kq`*&`g>h=P;Rrb$UC_;%T7>$t>D#`rX zj#Zo)tyq?Ok(D7NGup3CMMOLZnzQ@A@!#U**ynQ8BOlxAZFLGr@u&1*cy>b+#;7I9RXwMm`D22LXE1?YIbL0RO z1NS^B(W0Xsq`3yVO4gp9&FiM~@i*uVFsW3-Q{53$>X6tOkVQ7OCs%?VN_0c2l#qxn zM;mb)<6jB(v|3gNyIS*p_8D%a47pc$lS5|hLmf#1ZwAQxCuS&|rEV)$rI_Pm{D*!` z?0e{F)r^KA!9({1t``;38m;aR6vym{#w_w#4x$pu%AZ0H2T1Ku8g(}H&ozA11@@a~+cfnjuvs1QlzvKGIAs{t*0QFyV_I8P&Y z6JH*?t)1G2QRuVCx^=`;g4(YK<8eBsg+!trJUl*7%-+qa&Yo>7ezTB_I6nIq1e+>t zEY}{v@^KqiTCK>`63<5NX@^P}QuVH}t33D-|F>-Beo*!D#LLFJp$|n5b_upAmxvl{ zDmN=pgMEY=Y%j}qBzXAq6&GUBi5jdWGxXu$*oUaW2;3=ZurDyBe?g3g;@2=9)R~yr zJ00I(F)z8H_#h+pA?mQtoW>XN3wh$Tzk}6h%OJk68B4O1T^Et*2E|9PWRlC`;YR(y zR=swsR=1KTGQPkK%HC7VAp&<;s~_sg)9U^o_TB_euByr(f9x@A4Kj!*@CYH@f$mOc zrPC7V&PD=R+H?YF0#()Bue-}sR~5A+-H8k(B4z-g2RFuLjEWl3!Jv$wqPEM(qN5Q< z%&7k{ZVU{L#sx)3?f>^|?^WHdN@r>P{XhTty-!!)ch9}|-2L2h&pr1%(gY_j#=##> zKlKfyd_&$=cwchr8~%>GuOEd<(idL(=K zoX(S|NnZcLarj;m2HEXPZvoej4_}hZAIa!69M(_aIqrDmwGz|=7IP`eoNOO!xxow3M!T!$niB;HJEaBU1+-H-yw-a}oI| zKTKg8x9IilDD-=+yWdcZa?aF89q1)@FBVUz_~bA!JWn1Hw-{_ z8h_^77YHVN)qyZ^in))!t`&u*5AWRm1;9}`d8YnNC%^paRB`{T?n!mxf4RCpJ45_? z)O|$V52|~cx>fW#Jm(~5g zx`yYwM@xPWs{4ex7XGsrOSt)GsQ+Abo7Fv2-OJRSr|v20TKXTU|9*9!Q1=dXbLz&` zU9Rprbq&vmQ_gm+*BYmOzn!A(`66-8R<}{z%hX-3Zd%

    h4tcL3N){cdxq7sC(>G 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%0AMf0KaOoFo!S_ER@ooQT{{32R+aK=! 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%0Ds5{-Hj1 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 BltT#?SF)+}DPWtSrX; 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 ?x#ROrvBLk1=@EU+6e93U=9Fyrx!6B-8yNlz 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

    <}2mNn3sD7-8&Q}h~U(-aDO^>!uJFsk)rFf1 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

    r4`2=ncR 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Ⓢ8~ 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